@tigerdata/mcp-boilerplate 1.3.2 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1,2 @@
1
- export declare function cliEntrypoint(stdioEntrypoint: string, httpEntrypoint: string, instrumentation?: string): Promise<void>;
1
+ import type { MigrationsConfig } from './types.js';
2
+ export declare function cliEntrypoint(stdioEntrypoint: string, httpEntrypoint: string, instrumentation?: string, dbConfig?: MigrationsConfig): Promise<void>;
@@ -1,11 +1,17 @@
1
1
  import { dirname, join } from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
+ import { log } from './logger.js';
3
4
  const __dirname = dirname(fileURLToPath(import.meta.url));
4
- export async function cliEntrypoint(stdioEntrypoint, httpEntrypoint, instrumentation = join(__dirname, './instrumentation.js')) {
5
+ export async function cliEntrypoint(stdioEntrypoint, httpEntrypoint, instrumentation = join(__dirname, './instrumentation.js'), dbConfig) {
5
6
  // Parse command line arguments first
6
7
  const args = process.argv.slice(2);
7
8
  const scriptName = args[0] || 'stdio';
8
9
  try {
10
+ if (dbConfig) {
11
+ const { createMigrator } = await import('./migrate.js');
12
+ log.info('starting server...');
13
+ await createMigrator(dbConfig).run();
14
+ }
9
15
  // Dynamically import only the requested module to prevent all modules from initializing
10
16
  switch (scriptName) {
11
17
  case 'stdio': {
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { cliEntrypoint } from './cliEntrypoint.js';
2
2
  export { httpServerFactory } from './httpServer.js';
3
3
  export { log } from './logger.js';
4
4
  export type { AdditionalSetupArgs } from './mcpServer.js';
5
+ export { createMigrator } from './migrate.js';
5
6
  export { registerExitHandlers } from './registerExitHandlers.js';
6
7
  export { StatusError } from './StatusError.js';
7
8
  export { stdioServerFactory } from './stdio.js';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { cliEntrypoint } from './cliEntrypoint.js';
2
2
  export { httpServerFactory } from './httpServer.js';
3
3
  export { log } from './logger.js';
4
+ export { createMigrator } from './migrate.js';
4
5
  export { registerExitHandlers } from './registerExitHandlers.js';
5
6
  export { StatusError } from './StatusError.js';
6
7
  export { stdioServerFactory } from './stdio.js';
@@ -0,0 +1,4 @@
1
+ import type { MigrationsConfig } from './types.js';
2
+ export declare const createMigrator: (config: MigrationsConfig) => {
3
+ run: () => Promise<void>;
4
+ };
@@ -0,0 +1,91 @@
1
+ import { createHash } from 'node:crypto';
2
+ import migrate from 'migrate';
3
+ import { Client } from 'pg';
4
+ import { log } from './logger.js';
5
+ const createStateStore = (name, schema = 'public') => {
6
+ let client;
7
+ // Use a hash of the project name to create a lock
8
+ const hash = createHash('sha256').update(name).digest('hex');
9
+ const advisoryLockId = parseInt(hash.substring(0, 15), 16);
10
+ return {
11
+ async load(callback) {
12
+ try {
13
+ client = new Client();
14
+ await client.connect();
15
+ // Acquire advisory lock to prevent concurrent migrations
16
+ await client.query(/* sql */ `SELECT pg_advisory_lock($1)`, [
17
+ advisoryLockId,
18
+ ]);
19
+ // Ensure migrations table exists
20
+ await client.query(/* sql */ `
21
+ CREATE SCHEMA IF NOT EXISTS ${schema};
22
+
23
+ CREATE TABLE IF NOT EXISTS ${schema}.migrations (
24
+ id SERIAL PRIMARY KEY,
25
+ set JSONB NOT NULL,
26
+ applied_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
27
+ );
28
+ `);
29
+ // Load the most recent migration set
30
+ const result = await client.query(
31
+ /* sql */ `SELECT set FROM ${schema}.migrations ORDER BY applied_at DESC LIMIT 1`);
32
+ const set = result.rows.length > 0 ? result.rows[0].set : {};
33
+ callback(null, set);
34
+ }
35
+ catch (error) {
36
+ callback(error);
37
+ }
38
+ },
39
+ async save(set, callback) {
40
+ try {
41
+ // Insert the entire set as JSONB
42
+ await client.query(
43
+ /* sql */ `INSERT INTO ${schema}.migrations (set) VALUES ($1)`, [JSON.stringify(set)]);
44
+ callback(null);
45
+ }
46
+ catch (error) {
47
+ callback(error);
48
+ }
49
+ },
50
+ async close() {
51
+ if (client) {
52
+ // Release advisory lock
53
+ await client.query(/* sql */ `SELECT pg_advisory_unlock($1)`, [
54
+ advisoryLockId,
55
+ ]);
56
+ await client.end();
57
+ }
58
+ },
59
+ };
60
+ };
61
+ export const createMigrator = (config) => {
62
+ const { schema, migrationsDirectory, serviceName } = config;
63
+ const stateStore = createStateStore(serviceName, schema);
64
+ return {
65
+ run: async () => new Promise((resolve, reject) => {
66
+ log.info('Running database migrations...');
67
+ migrate.load({
68
+ stateStore,
69
+ migrationsDirectory: migrationsDirectory ?? './migrations',
70
+ }, (err, set) => {
71
+ if (err) {
72
+ log.error('Database migration failed:', err);
73
+ stateStore.close().finally(() => reject(err));
74
+ return;
75
+ }
76
+ set.up((err) => {
77
+ stateStore.close().finally(() => {
78
+ if (err) {
79
+ log.error('Database migration failed:', err);
80
+ reject(err);
81
+ }
82
+ else {
83
+ log.info('Database migrations completed successfully');
84
+ resolve();
85
+ }
86
+ });
87
+ });
88
+ });
89
+ }),
90
+ };
91
+ };
package/dist/types.d.ts CHANGED
@@ -107,4 +107,9 @@ export type InferSchema<T extends Record<string, z.ZodType>> = Flatten<{
107
107
  } & {
108
108
  [K in OptionalKeys<T>]?: z.infer<T[K]>;
109
109
  }>;
110
+ export interface MigrationsConfig {
111
+ serviceName: string;
112
+ migrationsDirectory?: string;
113
+ schema?: string;
114
+ }
110
115
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tigerdata/mcp-boilerplate",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
4
4
  "description": "MCP boilerplate code for Node.js",
5
5
  "license": "Apache-2.0",
6
6
  "author": "TigerData",
@@ -58,10 +58,22 @@
58
58
  "yaml": "^2.8.2"
59
59
  },
60
60
  "peerDependencies": {
61
+ "migrate": "^2.1.0",
62
+ "pg": "^8.16.3",
61
63
  "zod": "^3.25 || ^4.0"
62
64
  },
65
+ "peerDependenciesMeta": {
66
+ "migrate": {
67
+ "optional": true
68
+ },
69
+ "pg": {
70
+ "optional": true
71
+ }
72
+ },
63
73
  "devDependencies": {
64
74
  "@biomejs/biome": "^2.4.8",
75
+ "migrate": "^2.1.0",
76
+ "pg": "^8.16.3",
65
77
  "zod": "^4.3.6",
66
78
  "@octokit/rest": "^22.0.1",
67
79
  "@types/bun": "^1.3.10",