@0xobelisk/graphql-server 1.2.0-pre.100
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.
- package/.turbo/turbo-build.log +8 -0
- package/DUAL_POOL_CONFIG.md +188 -0
- package/Dockerfile +35 -0
- package/LICENSE +92 -0
- package/README.md +487 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +206 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/subscription-config.d.ts +80 -0
- package/dist/config/subscription-config.d.ts.map +1 -0
- package/dist/config/subscription-config.js +158 -0
- package/dist/config/subscription-config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/all-fields-filter-plugin.d.ts +4 -0
- package/dist/plugins/all-fields-filter-plugin.d.ts.map +1 -0
- package/dist/plugins/all-fields-filter-plugin.js +132 -0
- package/dist/plugins/all-fields-filter-plugin.js.map +1 -0
- package/dist/plugins/database-introspector.d.ts +23 -0
- package/dist/plugins/database-introspector.d.ts.map +1 -0
- package/dist/plugins/database-introspector.js +96 -0
- package/dist/plugins/database-introspector.js.map +1 -0
- package/dist/plugins/enhanced-playground.d.ts +9 -0
- package/dist/plugins/enhanced-playground.d.ts.map +1 -0
- package/dist/plugins/enhanced-playground.js +113 -0
- package/dist/plugins/enhanced-playground.js.map +1 -0
- package/dist/plugins/enhanced-server-manager.d.ts +29 -0
- package/dist/plugins/enhanced-server-manager.d.ts.map +1 -0
- package/dist/plugins/enhanced-server-manager.js +262 -0
- package/dist/plugins/enhanced-server-manager.js.map +1 -0
- package/dist/plugins/index.d.ts +9 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +26 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/postgraphile-config.d.ts +94 -0
- package/dist/plugins/postgraphile-config.d.ts.map +1 -0
- package/dist/plugins/postgraphile-config.js +138 -0
- package/dist/plugins/postgraphile-config.js.map +1 -0
- package/dist/plugins/query-filter.d.ts +4 -0
- package/dist/plugins/query-filter.d.ts.map +1 -0
- package/dist/plugins/query-filter.js +42 -0
- package/dist/plugins/query-filter.js.map +1 -0
- package/dist/plugins/simple-naming.d.ts +4 -0
- package/dist/plugins/simple-naming.d.ts.map +1 -0
- package/dist/plugins/simple-naming.js +79 -0
- package/dist/plugins/simple-naming.js.map +1 -0
- package/dist/plugins/welcome-page.d.ts +11 -0
- package/dist/plugins/welcome-page.d.ts.map +1 -0
- package/dist/plugins/welcome-page.js +203 -0
- package/dist/plugins/welcome-page.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +265 -0
- package/dist/server.js.map +1 -0
- package/dist/universal-subscriptions.d.ts +32 -0
- package/dist/universal-subscriptions.d.ts.map +1 -0
- package/dist/universal-subscriptions.js +318 -0
- package/dist/universal-subscriptions.js.map +1 -0
- package/dist/utils/logger/index.d.ts +80 -0
- package/dist/utils/logger/index.d.ts.map +1 -0
- package/dist/utils/logger/index.js +230 -0
- package/dist/utils/logger/index.js.map +1 -0
- package/docker-compose.yml +46 -0
- package/eslint.config.mjs +3 -0
- package/package.json +78 -0
- package/src/cli.ts +232 -0
- package/src/config/subscription-config.ts +243 -0
- package/src/index.ts +11 -0
- package/src/plugins/README.md +138 -0
- package/src/plugins/all-fields-filter-plugin.ts +158 -0
- package/src/plugins/database-introspector.ts +126 -0
- package/src/plugins/enhanced-playground.ts +121 -0
- package/src/plugins/enhanced-server-manager.ts +314 -0
- package/src/plugins/index.ts +9 -0
- package/src/plugins/postgraphile-config.ts +182 -0
- package/src/plugins/query-filter.ts +50 -0
- package/src/plugins/simple-naming.ts +105 -0
- package/src/plugins/welcome-page.ts +218 -0
- package/src/server.ts +324 -0
- package/src/universal-subscriptions.ts +397 -0
- package/src/utils/logger/README.md +209 -0
- package/src/utils/logger/index.ts +275 -0
- package/sui-indexer-schema.graphql +3691 -0
- package/tsconfig.json +28 -0
package/src/cli.ts
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs, { Argv } from 'yargs';
|
|
4
|
+
import { hideBin } from 'yargs/helpers';
|
|
5
|
+
import * as dotenv from 'dotenv';
|
|
6
|
+
import { startServer, ServerConfig } from './server';
|
|
7
|
+
import { systemLogger } from './utils/logger';
|
|
8
|
+
import packageJson from '../package.json';
|
|
9
|
+
|
|
10
|
+
// Load environment variables
|
|
11
|
+
dotenv.config();
|
|
12
|
+
|
|
13
|
+
// Helper function to get environment variable or default value
|
|
14
|
+
const getEnvOrDefault = (envKey: string, defaultValue: string): string => {
|
|
15
|
+
return process.env[envKey] || defaultValue;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const getBooleanEnvOrDefault = (envKey: string, defaultValue: boolean): boolean => {
|
|
19
|
+
const envValue = process.env[envKey];
|
|
20
|
+
if (envValue === undefined) return defaultValue;
|
|
21
|
+
return envValue.toLowerCase() === 'true';
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
interface StartArgs {
|
|
25
|
+
// Basic server configuration
|
|
26
|
+
port: string;
|
|
27
|
+
'database-url': string;
|
|
28
|
+
schema: string;
|
|
29
|
+
endpoint: string;
|
|
30
|
+
cors: boolean;
|
|
31
|
+
subscriptions: boolean;
|
|
32
|
+
env: string;
|
|
33
|
+
|
|
34
|
+
// Debug configuration
|
|
35
|
+
debug: boolean;
|
|
36
|
+
|
|
37
|
+
// Performance configuration
|
|
38
|
+
'query-timeout': number;
|
|
39
|
+
'max-connections': number;
|
|
40
|
+
'heartbeat-interval': number;
|
|
41
|
+
'enable-metrics': boolean;
|
|
42
|
+
|
|
43
|
+
// Subscription capabilities
|
|
44
|
+
'enable-live-queries': boolean;
|
|
45
|
+
'enable-pg-subscriptions': boolean;
|
|
46
|
+
'enable-native-websocket': boolean;
|
|
47
|
+
'realtime-port'?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface _HealthArgs {
|
|
51
|
+
url: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface _InitArgs {
|
|
55
|
+
output: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const cli = yargs(hideBin(process.argv))
|
|
59
|
+
.scriptName('dubhe-graphql-server')
|
|
60
|
+
.usage('$0 <command> [options]')
|
|
61
|
+
.version(packageJson.version)
|
|
62
|
+
.help('help')
|
|
63
|
+
.alias('h', 'help')
|
|
64
|
+
.alias('v', 'version')
|
|
65
|
+
.demandCommand(1, 'You need to specify a command')
|
|
66
|
+
.recommendCommands()
|
|
67
|
+
.strict();
|
|
68
|
+
|
|
69
|
+
// Start command
|
|
70
|
+
cli.command(
|
|
71
|
+
'start',
|
|
72
|
+
'Start GraphQL server',
|
|
73
|
+
(yargs: Argv) => {
|
|
74
|
+
return (
|
|
75
|
+
yargs
|
|
76
|
+
.option('port', {
|
|
77
|
+
alias: 'p',
|
|
78
|
+
type: 'string',
|
|
79
|
+
default: getEnvOrDefault('PORT', '4000'),
|
|
80
|
+
describe: 'Server port (env: PORT)'
|
|
81
|
+
})
|
|
82
|
+
.option('database-url', {
|
|
83
|
+
alias: 'd',
|
|
84
|
+
type: 'string',
|
|
85
|
+
default: getEnvOrDefault(
|
|
86
|
+
'DATABASE_URL',
|
|
87
|
+
'postgres://postgres:postgres@127.0.0.1:5432/postgres'
|
|
88
|
+
),
|
|
89
|
+
describe: 'Database connection URL (env: DATABASE_URL)'
|
|
90
|
+
})
|
|
91
|
+
.option('schema', {
|
|
92
|
+
alias: 's',
|
|
93
|
+
type: 'string',
|
|
94
|
+
default: getEnvOrDefault('PG_SCHEMA', 'public'),
|
|
95
|
+
describe: 'PostgreSQL schema name (env: PG_SCHEMA)'
|
|
96
|
+
})
|
|
97
|
+
.option('endpoint', {
|
|
98
|
+
alias: 'e',
|
|
99
|
+
type: 'string',
|
|
100
|
+
default: getEnvOrDefault('GRAPHQL_ENDPOINT', '/graphql'),
|
|
101
|
+
describe: 'GraphQL endpoint path (env: GRAPHQL_ENDPOINT)'
|
|
102
|
+
})
|
|
103
|
+
.option('cors', {
|
|
104
|
+
type: 'boolean',
|
|
105
|
+
default: getBooleanEnvOrDefault('ENABLE_CORS', true),
|
|
106
|
+
describe: 'Enable CORS (env: ENABLE_CORS)'
|
|
107
|
+
})
|
|
108
|
+
.option('subscriptions', {
|
|
109
|
+
type: 'boolean',
|
|
110
|
+
default: getBooleanEnvOrDefault('ENABLE_SUBSCRIPTIONS', true),
|
|
111
|
+
describe: 'Enable GraphQL subscriptions (env: ENABLE_SUBSCRIPTIONS)'
|
|
112
|
+
})
|
|
113
|
+
.option('env', {
|
|
114
|
+
type: 'string',
|
|
115
|
+
default: getEnvOrDefault('NODE_ENV', 'development'),
|
|
116
|
+
choices: ['development', 'production'],
|
|
117
|
+
describe: 'Environment mode (env: NODE_ENV)'
|
|
118
|
+
})
|
|
119
|
+
// Debug configuration
|
|
120
|
+
.option('debug', {
|
|
121
|
+
type: 'boolean',
|
|
122
|
+
default: getBooleanEnvOrDefault('DEBUG', false),
|
|
123
|
+
describe: 'Enable debug mode (verbose logging + query logs) (env: DEBUG)'
|
|
124
|
+
})
|
|
125
|
+
// Performance configuration
|
|
126
|
+
.option('query-timeout', {
|
|
127
|
+
type: 'number',
|
|
128
|
+
default: parseInt(getEnvOrDefault('QUERY_TIMEOUT', '30000')),
|
|
129
|
+
describe: 'GraphQL query timeout in milliseconds (env: QUERY_TIMEOUT)'
|
|
130
|
+
})
|
|
131
|
+
.option('max-connections', {
|
|
132
|
+
type: 'number',
|
|
133
|
+
default: parseInt(getEnvOrDefault('MAX_CONNECTIONS', '1000')),
|
|
134
|
+
describe: 'Maximum database connections (env: MAX_CONNECTIONS)'
|
|
135
|
+
})
|
|
136
|
+
.option('heartbeat-interval', {
|
|
137
|
+
type: 'number',
|
|
138
|
+
default: parseInt(getEnvOrDefault('HEARTBEAT_INTERVAL', '30000')),
|
|
139
|
+
describe: 'WebSocket heartbeat interval in milliseconds (env: HEARTBEAT_INTERVAL)'
|
|
140
|
+
})
|
|
141
|
+
.option('enable-metrics', {
|
|
142
|
+
type: 'boolean',
|
|
143
|
+
default: getBooleanEnvOrDefault('ENABLE_METRICS', false),
|
|
144
|
+
describe: 'Enable performance metrics (env: ENABLE_METRICS)'
|
|
145
|
+
})
|
|
146
|
+
// Subscription capabilities
|
|
147
|
+
.option('enable-live-queries', {
|
|
148
|
+
type: 'boolean',
|
|
149
|
+
default: getBooleanEnvOrDefault('ENABLE_LIVE_QUERIES', true),
|
|
150
|
+
describe: 'Enable GraphQL live queries (env: ENABLE_LIVE_QUERIES)'
|
|
151
|
+
})
|
|
152
|
+
.option('enable-pg-subscriptions', {
|
|
153
|
+
type: 'boolean',
|
|
154
|
+
default: getBooleanEnvOrDefault('ENABLE_PG_SUBSCRIPTIONS', true),
|
|
155
|
+
describe: 'Enable PostgreSQL subscriptions (env: ENABLE_PG_SUBSCRIPTIONS)'
|
|
156
|
+
})
|
|
157
|
+
.option('enable-native-websocket', {
|
|
158
|
+
type: 'boolean',
|
|
159
|
+
default: getBooleanEnvOrDefault('ENABLE_NATIVE_WEBSOCKET', true),
|
|
160
|
+
describe: 'Enable native WebSocket support (env: ENABLE_NATIVE_WEBSOCKET)'
|
|
161
|
+
})
|
|
162
|
+
.option('realtime-port', {
|
|
163
|
+
type: 'number',
|
|
164
|
+
default: process.env.REALTIME_PORT ? parseInt(process.env.REALTIME_PORT) : undefined,
|
|
165
|
+
describe: 'Realtime WebSocket port (env: REALTIME_PORT)'
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
.example(
|
|
169
|
+
'$0 start -p 4000 -d postgres://user:pass@localhost/db',
|
|
170
|
+
'Start server with custom port and database'
|
|
171
|
+
)
|
|
172
|
+
.example(
|
|
173
|
+
'$0 start --no-cors --no-subscriptions',
|
|
174
|
+
'Start server with CORS and subscriptions disabled'
|
|
175
|
+
)
|
|
176
|
+
.example('$0 start --debug', 'Start server in debug mode (verbose logging + notifications)')
|
|
177
|
+
.example(
|
|
178
|
+
'$0 start --debug --enable-metrics',
|
|
179
|
+
'Start server in debug mode with performance metrics'
|
|
180
|
+
)
|
|
181
|
+
);
|
|
182
|
+
},
|
|
183
|
+
async (argv: StartArgs) => {
|
|
184
|
+
try {
|
|
185
|
+
systemLogger.info('🚀 Starting Dubhe GraphQL server via CLI...', {
|
|
186
|
+
port: argv.port,
|
|
187
|
+
schema: argv.schema,
|
|
188
|
+
endpoint: argv.endpoint,
|
|
189
|
+
environment: argv.env
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Build server configuration object
|
|
193
|
+
const serverConfig: ServerConfig = {
|
|
194
|
+
// Basic server configuration
|
|
195
|
+
port: argv.port,
|
|
196
|
+
databaseUrl: argv['database-url'],
|
|
197
|
+
schema: argv.schema,
|
|
198
|
+
endpoint: argv.endpoint,
|
|
199
|
+
cors: argv.cors,
|
|
200
|
+
subscriptions: argv.subscriptions,
|
|
201
|
+
env: argv.env,
|
|
202
|
+
|
|
203
|
+
// Debug configuration (explicit control)
|
|
204
|
+
debug: argv.debug,
|
|
205
|
+
|
|
206
|
+
// Performance configuration
|
|
207
|
+
queryTimeout: argv['query-timeout'],
|
|
208
|
+
maxConnections: argv['max-connections'],
|
|
209
|
+
heartbeatInterval: argv['heartbeat-interval'],
|
|
210
|
+
|
|
211
|
+
// Subscription capabilities
|
|
212
|
+
enableLiveQueries: argv['enable-live-queries'],
|
|
213
|
+
enablePgSubscriptions: argv['enable-pg-subscriptions'],
|
|
214
|
+
enableNativeWebSocket: argv['enable-native-websocket'],
|
|
215
|
+
realtimePort: argv['realtime-port'],
|
|
216
|
+
|
|
217
|
+
// Debug configuration (notifications only in development or when debug is enabled)
|
|
218
|
+
debugNotifications: argv.debug || argv.env === 'development',
|
|
219
|
+
enableMetrics: argv['enable-metrics']
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// Pass configuration object directly to startServer
|
|
223
|
+
await startServer(serverConfig);
|
|
224
|
+
} catch (error: unknown) {
|
|
225
|
+
systemLogger.error('Failed to start server via CLI', error);
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
// Parse command line arguments
|
|
232
|
+
cli.parse();
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// Subscription configuration manager - supports dynamic configuration for three subscription modes
|
|
2
|
+
|
|
3
|
+
export interface SubscriptionCapabilities {
|
|
4
|
+
liveQueries: boolean;
|
|
5
|
+
pgSubscriptions: boolean;
|
|
6
|
+
nativeWebSocket: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SubscriptionConfig {
|
|
10
|
+
// Basic configuration
|
|
11
|
+
enableSubscriptions: boolean;
|
|
12
|
+
|
|
13
|
+
// Capability configuration
|
|
14
|
+
capabilities: SubscriptionCapabilities;
|
|
15
|
+
|
|
16
|
+
// Database configuration detection
|
|
17
|
+
walLevel: 'minimal' | 'replica' | 'logical';
|
|
18
|
+
|
|
19
|
+
// Port configuration
|
|
20
|
+
graphqlPort: number;
|
|
21
|
+
websocketPort?: number;
|
|
22
|
+
|
|
23
|
+
// Performance configuration
|
|
24
|
+
maxConnections: number;
|
|
25
|
+
heartbeatInterval: number;
|
|
26
|
+
|
|
27
|
+
// Debug configuration
|
|
28
|
+
enableNotificationLogging: boolean;
|
|
29
|
+
enablePerformanceMetrics: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Subscription configuration input parameter interface
|
|
33
|
+
export interface SubscriptionConfigInput {
|
|
34
|
+
enableSubscriptions: boolean;
|
|
35
|
+
databaseUrl: string;
|
|
36
|
+
port: string;
|
|
37
|
+
enableLiveQueries?: boolean;
|
|
38
|
+
enablePgSubscriptions?: boolean;
|
|
39
|
+
enableNativeWebSocket?: boolean;
|
|
40
|
+
realtimePort?: string;
|
|
41
|
+
maxConnections?: string;
|
|
42
|
+
heartbeatInterval?: string;
|
|
43
|
+
debugNotifications?: boolean;
|
|
44
|
+
enableMetrics?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class SubscriptionConfigManager {
|
|
48
|
+
private config: SubscriptionConfig;
|
|
49
|
+
|
|
50
|
+
constructor(configInput: SubscriptionConfigInput) {
|
|
51
|
+
this.config = this.parseConfigInput(configInput);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Parse configuration from input parameters
|
|
55
|
+
private parseConfigInput(input: SubscriptionConfigInput): SubscriptionConfig {
|
|
56
|
+
const enableSubscriptions = input.enableSubscriptions;
|
|
57
|
+
|
|
58
|
+
// Auto-detect WAL level (in actual applications, query through database)
|
|
59
|
+
const walLevel = this.detectWalLevel(input.databaseUrl);
|
|
60
|
+
|
|
61
|
+
// Determine capabilities based on input parameters - default enable all features when subscriptions are enabled
|
|
62
|
+
const capabilities: SubscriptionCapabilities = {
|
|
63
|
+
liveQueries:
|
|
64
|
+
enableSubscriptions && input.enableLiveQueries !== false && walLevel === 'logical',
|
|
65
|
+
|
|
66
|
+
pgSubscriptions: enableSubscriptions && input.enablePgSubscriptions !== false,
|
|
67
|
+
|
|
68
|
+
nativeWebSocket: enableSubscriptions && input.enableNativeWebSocket !== false
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
enableSubscriptions,
|
|
73
|
+
capabilities,
|
|
74
|
+
walLevel,
|
|
75
|
+
|
|
76
|
+
graphqlPort: parseInt(input.port),
|
|
77
|
+
websocketPort: input.realtimePort ? parseInt(input.realtimePort) : undefined,
|
|
78
|
+
|
|
79
|
+
maxConnections: parseInt(input.maxConnections || '1000'),
|
|
80
|
+
heartbeatInterval: parseInt(input.heartbeatInterval || '30000'),
|
|
81
|
+
|
|
82
|
+
enableNotificationLogging: input.debugNotifications === true,
|
|
83
|
+
enablePerformanceMetrics: input.enableMetrics === true
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Detect database WAL level
|
|
88
|
+
private detectWalLevel(_databaseUrl?: string): 'minimal' | 'replica' | 'logical' {
|
|
89
|
+
// In actual applications should query database
|
|
90
|
+
// SELECT setting FROM pg_settings WHERE name = 'wal_level';
|
|
91
|
+
|
|
92
|
+
// Currently return default value
|
|
93
|
+
return 'replica';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Get current configuration
|
|
97
|
+
getConfig(): SubscriptionConfig {
|
|
98
|
+
return { ...this.config };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Get recommended subscription method
|
|
102
|
+
getRecommendedSubscriptionMethod(): string {
|
|
103
|
+
if (this.config.capabilities.liveQueries) {
|
|
104
|
+
return 'live-queries';
|
|
105
|
+
} else if (this.config.capabilities.pgSubscriptions) {
|
|
106
|
+
return 'pg-subscriptions';
|
|
107
|
+
} else if (this.config.capabilities.nativeWebSocket) {
|
|
108
|
+
return 'native-websocket';
|
|
109
|
+
} else {
|
|
110
|
+
return 'none';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Generate client configuration
|
|
115
|
+
generateClientConfig() {
|
|
116
|
+
const baseUrl = `http://localhost:${this.config.graphqlPort}`;
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
graphqlEndpoint: `${baseUrl}/graphql`,
|
|
120
|
+
subscriptionEndpoint:
|
|
121
|
+
this.config.capabilities.pgSubscriptions || this.config.capabilities.liveQueries
|
|
122
|
+
? `ws://localhost:${this.config.graphqlPort}/graphql`
|
|
123
|
+
: undefined,
|
|
124
|
+
nativeWebSocketEndpoint: this.config.capabilities.nativeWebSocket
|
|
125
|
+
? `ws://localhost:${this.config.websocketPort || this.config.graphqlPort}`
|
|
126
|
+
: undefined,
|
|
127
|
+
capabilities: this.config.capabilities,
|
|
128
|
+
recommendedMethod: this.getRecommendedSubscriptionMethod()
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Generate PostGraphile configuration - simplified version, only keep listen subscriptions
|
|
133
|
+
generatePostGraphileConfig() {
|
|
134
|
+
return {
|
|
135
|
+
subscriptions: this.config.enableSubscriptions,
|
|
136
|
+
live: false, // Disable live queries, only use listen subscriptions
|
|
137
|
+
simpleSubscriptions: this.config.capabilities.pgSubscriptions,
|
|
138
|
+
|
|
139
|
+
// Performance configuration - optimized for listen subscriptions
|
|
140
|
+
pgSettings: {
|
|
141
|
+
statement_timeout: '30s',
|
|
142
|
+
default_transaction_isolation: 'read committed'
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
// Monitoring configuration
|
|
146
|
+
allowExplain: this.config.enablePerformanceMetrics,
|
|
147
|
+
disableQueryLog: !this.config.enableNotificationLogging
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Generate environment variable documentation
|
|
152
|
+
generateDocumentation(): string {
|
|
153
|
+
return `
|
|
154
|
+
# 📡 Subscription System Configuration Guide
|
|
155
|
+
|
|
156
|
+
## Basic Configuration
|
|
157
|
+
enableSubscriptions=${
|
|
158
|
+
this.config.enableSubscriptions
|
|
159
|
+
} # Enable/disable subscription features
|
|
160
|
+
|
|
161
|
+
## Capability Configuration (optional, auto-detect by default)
|
|
162
|
+
enableLiveQueries=${
|
|
163
|
+
this.config.capabilities.liveQueries
|
|
164
|
+
} # Enable @live directive (requires wal_level=logical)
|
|
165
|
+
enablePgSubscriptions=${
|
|
166
|
+
this.config.capabilities.pgSubscriptions
|
|
167
|
+
} # Enable PostgreSQL subscriptions
|
|
168
|
+
enableNativeWebSocket=${this.config.capabilities.nativeWebSocket} # Enable native WebSocket
|
|
169
|
+
|
|
170
|
+
## Port Configuration
|
|
171
|
+
port=${this.config.graphqlPort} # GraphQL port
|
|
172
|
+
realtimePort=${
|
|
173
|
+
this.config.websocketPort || 'undefined'
|
|
174
|
+
} # Native WebSocket port (optional)
|
|
175
|
+
|
|
176
|
+
## Performance Configuration
|
|
177
|
+
maxConnections=${this.config.maxConnections} # Maximum connections
|
|
178
|
+
heartbeatInterval=${this.config.heartbeatInterval} # Heartbeat interval (ms)
|
|
179
|
+
|
|
180
|
+
## Debug Configuration
|
|
181
|
+
debugNotifications=${this.config.enableNotificationLogging} # Notification logging
|
|
182
|
+
enableMetrics=${this.config.enablePerformanceMetrics} # Performance metrics
|
|
183
|
+
|
|
184
|
+
## Current Configuration Status:
|
|
185
|
+
- Subscription Features: ${this.config.enableSubscriptions ? '✅ Enabled' : '❌ Disabled'}
|
|
186
|
+
- Live Queries: ${this.config.capabilities.liveQueries ? '✅ Available' : '❌ Not Available'}
|
|
187
|
+
- PG Subscriptions: ${
|
|
188
|
+
this.config.capabilities.pgSubscriptions ? '✅ Available' : '❌ Not Available'
|
|
189
|
+
}
|
|
190
|
+
- Native WebSocket: ${
|
|
191
|
+
this.config.capabilities.nativeWebSocket ? '✅ Available' : '❌ Not Available'
|
|
192
|
+
}
|
|
193
|
+
- WAL Level: ${this.config.walLevel}
|
|
194
|
+
- Recommended Method: ${this.getRecommendedSubscriptionMethod()}
|
|
195
|
+
`;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Export singleton instance - lazy initialization
|
|
200
|
+
let _subscriptionConfigInstance: SubscriptionConfigManager | null = null;
|
|
201
|
+
|
|
202
|
+
export const subscriptionConfig = {
|
|
203
|
+
getConfig(): SubscriptionConfig {
|
|
204
|
+
if (!_subscriptionConfigInstance) {
|
|
205
|
+
throw new Error(
|
|
206
|
+
'Subscription config not initialized. Call refresh() first with configuration.'
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
return _subscriptionConfigInstance.getConfig();
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
generateClientConfig() {
|
|
213
|
+
if (!_subscriptionConfigInstance) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
'Subscription config not initialized. Call refresh() first with configuration.'
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
return _subscriptionConfigInstance.generateClientConfig();
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
generatePostGraphileConfig() {
|
|
222
|
+
if (!_subscriptionConfigInstance) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
'Subscription config not initialized. Call refresh() first with configuration.'
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
return _subscriptionConfigInstance.generatePostGraphileConfig();
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
generateDocumentation(): string {
|
|
231
|
+
if (!_subscriptionConfigInstance) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
'Subscription config not initialized. Call refresh() first with configuration.'
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
return _subscriptionConfigInstance.generateDocumentation();
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
// Initialize/refresh configuration with input parameters
|
|
240
|
+
refresh(configInput: SubscriptionConfigInput) {
|
|
241
|
+
_subscriptionConfigInstance = new SubscriptionConfigManager(configInput);
|
|
242
|
+
}
|
|
243
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// import { startServer } from './server';
|
|
2
|
+
// import { systemLogger } from './utils/logger';
|
|
3
|
+
|
|
4
|
+
// // // Start application
|
|
5
|
+
// // systemLogger.info('🚀 Starting Sui Indexer GraphQL Server (Express Architecture)...', {
|
|
6
|
+
// // nodeVersion: process.version,
|
|
7
|
+
// // platform: process.platform,
|
|
8
|
+
// // pid: process.pid
|
|
9
|
+
// // });
|
|
10
|
+
|
|
11
|
+
// // startServer();
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# GraphQL Server Plugin Architecture
|
|
2
|
+
|
|
3
|
+
This directory contains various functional module plugins for the Sui Indexer GraphQL server, using modular design for easy management and extension.
|
|
4
|
+
|
|
5
|
+
## 📁 Plugin Structure
|
|
6
|
+
|
|
7
|
+
### Core Plugins
|
|
8
|
+
|
|
9
|
+
#### `database-introspector.ts` - Database Introspector
|
|
10
|
+
|
|
11
|
+
- **Function**: Scan and analyze database table structure
|
|
12
|
+
- **Main Class**: `DatabaseIntrospector`
|
|
13
|
+
- **Responsibilities**:
|
|
14
|
+
- Get store\_\* dynamic tables
|
|
15
|
+
- Get system tables (dubhe related)
|
|
16
|
+
- Get field information from table_fields
|
|
17
|
+
- Test database connection
|
|
18
|
+
- Output table structure logs
|
|
19
|
+
|
|
20
|
+
#### `welcome-page.ts` - Welcome Page Generator
|
|
21
|
+
|
|
22
|
+
- **Function**: Generate server homepage
|
|
23
|
+
- **Main Function**: `createWelcomePage()`
|
|
24
|
+
- **Responsibilities**:
|
|
25
|
+
- Display server status and configuration information
|
|
26
|
+
- Show detected data tables
|
|
27
|
+
- Provide navigation links and usage guides
|
|
28
|
+
- Responsive design and beautiful interface
|
|
29
|
+
|
|
30
|
+
#### `postgraphile-config.ts` - PostGraphile Configuration Generator
|
|
31
|
+
|
|
32
|
+
- **Function**: Create PostGraphile configuration
|
|
33
|
+
- **Main Function**: `createPostGraphileConfig()`
|
|
34
|
+
- **Responsibilities**:
|
|
35
|
+
- Configure GraphQL endpoints and features
|
|
36
|
+
- Integrate enhanced Playground
|
|
37
|
+
- Set up subscriptions and real-time queries
|
|
38
|
+
- Optimize performance parameters
|
|
39
|
+
|
|
40
|
+
#### `subscription-manager.ts` - Subscription Manager
|
|
41
|
+
|
|
42
|
+
- **Function**: Manage GraphQL subscription features
|
|
43
|
+
- **Main Class**: `SubscriptionManager`
|
|
44
|
+
- **Responsibilities**:
|
|
45
|
+
- Load @graphile/pg-pubsub plugin
|
|
46
|
+
- Configure custom subscription plugins
|
|
47
|
+
- Error handling and fallback solutions
|
|
48
|
+
- Output subscription status information
|
|
49
|
+
|
|
50
|
+
#### `server-manager.ts` - Server Manager
|
|
51
|
+
|
|
52
|
+
- **Function**: Manage HTTP and WebSocket servers
|
|
53
|
+
- **Main Class**: `ServerManager`
|
|
54
|
+
- **Responsibilities**:
|
|
55
|
+
- Create and configure HTTP server
|
|
56
|
+
- Start real-time subscription server
|
|
57
|
+
- Database change monitoring
|
|
58
|
+
- Graceful shutdown handling
|
|
59
|
+
|
|
60
|
+
#### `enhanced-playground.ts` - Enhanced GraphQL Playground
|
|
61
|
+
|
|
62
|
+
- **Function**: Provide modern GraphQL IDE
|
|
63
|
+
- **Main Function**: `createEnhancedPlayground()`
|
|
64
|
+
- **Responsibilities**:
|
|
65
|
+
- Visual Schema Explorer
|
|
66
|
+
- Code export functionality
|
|
67
|
+
- Modern UI interface
|
|
68
|
+
- Keyboard shortcuts support
|
|
69
|
+
|
|
70
|
+
## 🔧 Usage
|
|
71
|
+
|
|
72
|
+
### Unified Import
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import {
|
|
76
|
+
DatabaseIntrospector,
|
|
77
|
+
createPostGraphileConfig,
|
|
78
|
+
SubscriptionManager,
|
|
79
|
+
ServerManager,
|
|
80
|
+
WelcomePageConfig
|
|
81
|
+
} from './plugins';
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Typical Usage Flow
|
|
85
|
+
|
|
86
|
+
1. **Database Scanning**: Use `DatabaseIntrospector` to get table structure
|
|
87
|
+
2. **Subscription Configuration**: Load plugins through `SubscriptionManager`
|
|
88
|
+
3. **Configuration Generation**: Create configuration using `createPostGraphileConfig`
|
|
89
|
+
4. **Server Startup**: Manage server lifecycle through `ServerManager`
|
|
90
|
+
|
|
91
|
+
## 🎯 Design Advantages
|
|
92
|
+
|
|
93
|
+
### Modular Design
|
|
94
|
+
|
|
95
|
+
- Each plugin has a single clear responsibility
|
|
96
|
+
- Easy to test and maintain individually
|
|
97
|
+
- Supports independent upgrades and replacements
|
|
98
|
+
|
|
99
|
+
### Type Safety
|
|
100
|
+
|
|
101
|
+
- Complete TypeScript support
|
|
102
|
+
- Clear interface definitions
|
|
103
|
+
- Compile-time error checking
|
|
104
|
+
|
|
105
|
+
### Extensibility
|
|
106
|
+
|
|
107
|
+
- Plugin architecture easy to extend
|
|
108
|
+
- Supports custom plugin development
|
|
109
|
+
- Flexible and adjustable configuration
|
|
110
|
+
|
|
111
|
+
### Error Handling
|
|
112
|
+
|
|
113
|
+
- Graceful error degradation
|
|
114
|
+
- Detailed log output
|
|
115
|
+
- Fault isolation protection
|
|
116
|
+
|
|
117
|
+
## 📈 Extension Guide
|
|
118
|
+
|
|
119
|
+
### Adding New Plugins
|
|
120
|
+
|
|
121
|
+
1. Create new file in `plugins/` directory
|
|
122
|
+
2. Export main interfaces and classes
|
|
123
|
+
3. Add export in `index.ts`
|
|
124
|
+
4. Update main entry file to use
|
|
125
|
+
|
|
126
|
+
### Custom Configuration
|
|
127
|
+
|
|
128
|
+
- Pass configuration through environment variables
|
|
129
|
+
- Use interfaces to define configuration structure
|
|
130
|
+
- Support runtime dynamic configuration
|
|
131
|
+
|
|
132
|
+
### Plugin Integration
|
|
133
|
+
|
|
134
|
+
- Follow unified error handling patterns
|
|
135
|
+
- Use consistent log formats
|
|
136
|
+
- Maintain interface compatibility
|
|
137
|
+
|
|
138
|
+
This architecture makes the GraphQL server more modular, maintainable, and provides a solid foundation for future feature extensions.
|