@0xobelisk/graphql-server 1.2.0-pre.24
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/Dockerfile +31 -0
- package/EXPRESS_MIGRATION.md +176 -0
- package/LICENSE +92 -0
- package/README.md +908 -0
- package/dist/config/subscription-config.d.ts +47 -0
- package/dist/config/subscription-config.d.ts.map +1 -0
- package/dist/config/subscription-config.js +133 -0
- package/dist/config/subscription-config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +217 -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 +97 -0
- package/dist/plugins/enhanced-playground.js.map +1 -0
- package/dist/plugins/enhanced-server-manager.d.ts +28 -0
- package/dist/plugins/enhanced-server-manager.d.ts.map +1 -0
- package/dist/plugins/enhanced-server-manager.js +232 -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 +183 -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/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 +232 -0
- package/dist/utils/logger/index.js.map +1 -0
- package/docker-compose.yml +87 -0
- package/package.json +71 -0
- package/server.log +62 -0
- package/src/config/subscription-config.ts +186 -0
- package/src/index.ts +239 -0
- package/src/plugins/README.md +123 -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 +105 -0
- package/src/plugins/enhanced-server-manager.ts +282 -0
- package/src/plugins/index.ts +9 -0
- package/src/plugins/postgraphile-config.ts +226 -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/universal-subscriptions.ts +397 -0
- package/src/utils/logger/README.md +193 -0
- package/src/utils/logger/index.ts +315 -0
- package/sui-indexer-schema.graphql +1004 -0
- package/test-express.js +124 -0
- package/test_listen_subscription.js +121 -0
- package/test_notification.js +63 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface SubscriptionCapabilities {
|
|
2
|
+
liveQueries: boolean;
|
|
3
|
+
pgSubscriptions: boolean;
|
|
4
|
+
nativeWebSocket: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface SubscriptionConfig {
|
|
7
|
+
enableSubscriptions: boolean;
|
|
8
|
+
capabilities: SubscriptionCapabilities;
|
|
9
|
+
walLevel: 'minimal' | 'replica' | 'logical';
|
|
10
|
+
pgVersion: string;
|
|
11
|
+
graphqlPort: number;
|
|
12
|
+
websocketPort?: number;
|
|
13
|
+
maxConnections: number;
|
|
14
|
+
heartbeatInterval: number;
|
|
15
|
+
enableNotificationLogging: boolean;
|
|
16
|
+
enablePerformanceMetrics: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class SubscriptionConfigManager {
|
|
19
|
+
private config;
|
|
20
|
+
constructor(envVars: Record<string, string>);
|
|
21
|
+
private parseEnvironmentVariables;
|
|
22
|
+
private detectWalLevel;
|
|
23
|
+
getConfig(): SubscriptionConfig;
|
|
24
|
+
isCapabilityEnabled(capability: keyof SubscriptionCapabilities): boolean;
|
|
25
|
+
getRecommendedSubscriptionMethod(): string;
|
|
26
|
+
generateClientConfig(): {
|
|
27
|
+
graphqlEndpoint: string;
|
|
28
|
+
subscriptionEndpoint: string | undefined;
|
|
29
|
+
nativeWebSocketEndpoint: string | undefined;
|
|
30
|
+
capabilities: SubscriptionCapabilities;
|
|
31
|
+
recommendedMethod: string;
|
|
32
|
+
};
|
|
33
|
+
generatePostGraphileConfig(): {
|
|
34
|
+
subscriptions: boolean;
|
|
35
|
+
live: boolean;
|
|
36
|
+
simpleSubscriptions: boolean;
|
|
37
|
+
pgSettings: {
|
|
38
|
+
statement_timeout: string;
|
|
39
|
+
default_transaction_isolation: string;
|
|
40
|
+
};
|
|
41
|
+
allowExplain: boolean;
|
|
42
|
+
disableQueryLog: boolean;
|
|
43
|
+
};
|
|
44
|
+
generateDocumentation(): string;
|
|
45
|
+
}
|
|
46
|
+
export declare const subscriptionConfig: SubscriptionConfigManager;
|
|
47
|
+
//# sourceMappingURL=subscription-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-config.d.ts","sourceRoot":"","sources":["../../src/config/subscription-config.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAEjC,mBAAmB,EAAE,OAAO,CAAC;IAG7B,YAAY,EAAE,wBAAwB,CAAC;IAGvC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAGlB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAG1B,yBAAyB,EAAE,OAAO,CAAC;IACnC,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAED,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAqB;gBAEvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAK3C,OAAO,CAAC,yBAAyB;IAkCjC,OAAO,CAAC,cAAc;IAStB,SAAS,IAAI,kBAAkB;IAK/B,mBAAmB,CAAC,UAAU,EAAE,MAAM,wBAAwB,GAAG,OAAO;IAKxE,gCAAgC,IAAI,MAAM;IAa1C,oBAAoB;;;;;;;IAkBpB,0BAA0B;;;;;;;;;;;IAmB1B,qBAAqB,IAAI,MAAM;CAqChC;AAGD,eAAO,MAAM,kBAAkB,2BAE9B,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Subscription configuration manager - supports dynamic configuration for three subscription modes
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.subscriptionConfig = exports.SubscriptionConfigManager = void 0;
|
|
5
|
+
class SubscriptionConfigManager {
|
|
6
|
+
config;
|
|
7
|
+
constructor(envVars) {
|
|
8
|
+
this.config = this.parseEnvironmentVariables(envVars);
|
|
9
|
+
}
|
|
10
|
+
// Parse configuration from environment variables
|
|
11
|
+
parseEnvironmentVariables(env) {
|
|
12
|
+
const enableSubscriptions = env.ENABLE_SUBSCRIPTIONS !== 'false'; // Default enabled unless explicitly set to false
|
|
13
|
+
// Auto-detect WAL level (in actual applications, query through database)
|
|
14
|
+
const walLevel = this.detectWalLevel(env.DATABASE_URL);
|
|
15
|
+
// Determine capabilities based on WAL level and environment variables - default enable all features
|
|
16
|
+
const capabilities = {
|
|
17
|
+
liveQueries: enableSubscriptions && env.ENABLE_LIVE_QUERIES !== 'false' && walLevel === 'logical',
|
|
18
|
+
pgSubscriptions: enableSubscriptions && env.ENABLE_PG_SUBSCRIPTIONS !== 'false',
|
|
19
|
+
nativeWebSocket: enableSubscriptions && env.ENABLE_NATIVE_WEBSOCKET !== 'false'
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
enableSubscriptions,
|
|
23
|
+
capabilities,
|
|
24
|
+
walLevel,
|
|
25
|
+
pgVersion: '13+', // In actual applications, get through query
|
|
26
|
+
graphqlPort: parseInt(env.PORT || '4000'),
|
|
27
|
+
websocketPort: env.REALTIME_PORT ? parseInt(env.REALTIME_PORT) : undefined,
|
|
28
|
+
maxConnections: parseInt(env.MAX_SUBSCRIPTION_CONNECTIONS || '1000'),
|
|
29
|
+
heartbeatInterval: parseInt(env.SUBSCRIPTION_HEARTBEAT_INTERVAL || '30000'),
|
|
30
|
+
enableNotificationLogging: env.DEBUG_NOTIFICATIONS === 'true',
|
|
31
|
+
enablePerformanceMetrics: env.ENABLE_SUBSCRIPTION_METRICS === 'true'
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Detect database WAL level
|
|
35
|
+
detectWalLevel(databaseUrl) {
|
|
36
|
+
// In actual applications should query database
|
|
37
|
+
// SELECT setting FROM pg_settings WHERE name = 'wal_level';
|
|
38
|
+
// Currently return default value
|
|
39
|
+
return 'replica';
|
|
40
|
+
}
|
|
41
|
+
// Get current configuration
|
|
42
|
+
getConfig() {
|
|
43
|
+
return { ...this.config };
|
|
44
|
+
}
|
|
45
|
+
// Check if specific capability is available
|
|
46
|
+
isCapabilityEnabled(capability) {
|
|
47
|
+
return this.config.capabilities[capability];
|
|
48
|
+
}
|
|
49
|
+
// Get recommended subscription method
|
|
50
|
+
getRecommendedSubscriptionMethod() {
|
|
51
|
+
if (this.config.capabilities.liveQueries) {
|
|
52
|
+
return 'live-queries';
|
|
53
|
+
}
|
|
54
|
+
else if (this.config.capabilities.pgSubscriptions) {
|
|
55
|
+
return 'pg-subscriptions';
|
|
56
|
+
}
|
|
57
|
+
else if (this.config.capabilities.nativeWebSocket) {
|
|
58
|
+
return 'native-websocket';
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
return 'none';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Generate client configuration
|
|
65
|
+
generateClientConfig() {
|
|
66
|
+
const baseUrl = `http://localhost:${this.config.graphqlPort}`;
|
|
67
|
+
return {
|
|
68
|
+
graphqlEndpoint: `${baseUrl}/graphql`,
|
|
69
|
+
subscriptionEndpoint: this.config.capabilities.pgSubscriptions || this.config.capabilities.liveQueries
|
|
70
|
+
? `ws://localhost:${this.config.graphqlPort}/graphql`
|
|
71
|
+
: undefined,
|
|
72
|
+
nativeWebSocketEndpoint: this.config.capabilities.nativeWebSocket
|
|
73
|
+
? `ws://localhost:${this.config.websocketPort || this.config.graphqlPort}`
|
|
74
|
+
: undefined,
|
|
75
|
+
capabilities: this.config.capabilities,
|
|
76
|
+
recommendedMethod: this.getRecommendedSubscriptionMethod()
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// Generate PostGraphile configuration - simplified version, only keep listen subscriptions
|
|
80
|
+
generatePostGraphileConfig() {
|
|
81
|
+
return {
|
|
82
|
+
subscriptions: this.config.enableSubscriptions,
|
|
83
|
+
live: false, // Disable live queries, only use listen subscriptions
|
|
84
|
+
simpleSubscriptions: this.config.capabilities.pgSubscriptions,
|
|
85
|
+
// Performance configuration - optimized for listen subscriptions
|
|
86
|
+
pgSettings: {
|
|
87
|
+
statement_timeout: '30s',
|
|
88
|
+
default_transaction_isolation: 'read committed'
|
|
89
|
+
},
|
|
90
|
+
// Monitoring configuration
|
|
91
|
+
allowExplain: this.config.enablePerformanceMetrics,
|
|
92
|
+
disableQueryLog: !this.config.enableNotificationLogging
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Generate environment variable documentation
|
|
96
|
+
generateDocumentation() {
|
|
97
|
+
return `
|
|
98
|
+
# 📡 Subscription System Configuration Guide
|
|
99
|
+
|
|
100
|
+
## Basic Configuration
|
|
101
|
+
ENABLE_SUBSCRIPTIONS=false # Disable subscription features (default enabled, set to false to disable)
|
|
102
|
+
|
|
103
|
+
## Capability Configuration (optional, auto-detect by default)
|
|
104
|
+
ENABLE_LIVE_QUERIES=true # Enable @live directive (requires wal_level=logical)
|
|
105
|
+
ENABLE_PG_SUBSCRIPTIONS=true # Enable PostgreSQL subscriptions
|
|
106
|
+
ENABLE_NATIVE_WEBSOCKET=true # Enable native WebSocket
|
|
107
|
+
|
|
108
|
+
## Port Configuration
|
|
109
|
+
PORT=4000 # GraphQL port
|
|
110
|
+
REALTIME_PORT=4001 # Native WebSocket port (optional)
|
|
111
|
+
|
|
112
|
+
## Performance Configuration
|
|
113
|
+
MAX_SUBSCRIPTION_CONNECTIONS=1000 # Maximum connections
|
|
114
|
+
SUBSCRIPTION_HEARTBEAT_INTERVAL=30000 # Heartbeat interval (ms)
|
|
115
|
+
|
|
116
|
+
## Debug Configuration
|
|
117
|
+
DEBUG_NOTIFICATIONS=false # Notification logging
|
|
118
|
+
ENABLE_SUBSCRIPTION_METRICS=false # Performance metrics
|
|
119
|
+
|
|
120
|
+
## Current Configuration Status:
|
|
121
|
+
- Subscription Features: ${this.config.enableSubscriptions ? '✅ Enabled' : '❌ Disabled'}
|
|
122
|
+
- Live Queries: ${this.config.capabilities.liveQueries ? '✅ Available' : '❌ Not Available'}
|
|
123
|
+
- PG Subscriptions: ${this.config.capabilities.pgSubscriptions ? '✅ Available' : '❌ Not Available'}
|
|
124
|
+
- Native WebSocket: ${this.config.capabilities.nativeWebSocket ? '✅ Available' : '❌ Not Available'}
|
|
125
|
+
- WAL Level: ${this.config.walLevel}
|
|
126
|
+
- Recommended Method: ${this.getRecommendedSubscriptionMethod()}
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.SubscriptionConfigManager = SubscriptionConfigManager;
|
|
131
|
+
// Export singleton instance
|
|
132
|
+
exports.subscriptionConfig = new SubscriptionConfigManager(process.env);
|
|
133
|
+
//# sourceMappingURL=subscription-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-config.js","sourceRoot":"","sources":["../../src/config/subscription-config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const postgraphile_1 = require("postgraphile");
|
|
37
|
+
const pg_1 = require("pg");
|
|
38
|
+
const dotenv = __importStar(require("dotenv"));
|
|
39
|
+
const logger_1 = require("./utils/logger");
|
|
40
|
+
const plugins_1 = require("./plugins");
|
|
41
|
+
const enhanced_server_manager_1 = require("./plugins/enhanced-server-manager");
|
|
42
|
+
const subscription_config_1 = require("./config/subscription-config");
|
|
43
|
+
const universal_subscriptions_1 = require("./universal-subscriptions");
|
|
44
|
+
// Load environment variables
|
|
45
|
+
dotenv.config();
|
|
46
|
+
// Environment variable configuration
|
|
47
|
+
const { DATABASE_URL = 'postgres://postgres:postgres@127.0.0.1:5432/postgres', PORT = 4000, NODE_ENV = 'development', GRAPHQL_ENDPOINT = '/graphql', PG_SCHEMA = 'public', ENABLE_CORS = 'true' } = process.env;
|
|
48
|
+
// Subscription feature is enabled by default unless explicitly set to false
|
|
49
|
+
const ENABLE_SUBSCRIPTIONS = process.env.ENABLE_SUBSCRIPTIONS !== 'false' ? 'true' : 'false';
|
|
50
|
+
// Create database connection pool
|
|
51
|
+
const pgPool = new pg_1.Pool({
|
|
52
|
+
connectionString: DATABASE_URL
|
|
53
|
+
});
|
|
54
|
+
// Start server
|
|
55
|
+
const startServer = async () => {
|
|
56
|
+
const startTime = Date.now();
|
|
57
|
+
try {
|
|
58
|
+
// 1. Test database connection and scan table structure
|
|
59
|
+
logger_1.systemLogger.info('Initializing database connection and scanning table structure...', {
|
|
60
|
+
schema: PG_SCHEMA,
|
|
61
|
+
databaseUrl: DATABASE_URL.replace(/:[^:]*@/, ':****@') // Hide password
|
|
62
|
+
});
|
|
63
|
+
const introspector = new plugins_1.DatabaseIntrospector(pgPool, PG_SCHEMA);
|
|
64
|
+
const isConnected = await introspector.testConnection();
|
|
65
|
+
if (!isConnected) {
|
|
66
|
+
throw new Error('Database connection failed');
|
|
67
|
+
}
|
|
68
|
+
logger_1.dbLogger.info('Database connection successful', { schema: PG_SCHEMA });
|
|
69
|
+
const allTables = await introspector.getAllTables();
|
|
70
|
+
const tableNames = allTables.map((t) => t.table_name);
|
|
71
|
+
logger_1.dbLogger.info('Table structure scan completed', {
|
|
72
|
+
tableCount: allTables.length,
|
|
73
|
+
storeTableCount: tableNames.filter((name) => name.startsWith('store_')).length,
|
|
74
|
+
tableNames: tableNames.slice(0, 10) // Only show first 10 table names
|
|
75
|
+
});
|
|
76
|
+
// 2. Display subscription configuration status
|
|
77
|
+
const config = subscription_config_1.subscriptionConfig.getConfig();
|
|
78
|
+
logger_1.subscriptionLogger.info('📡 Subscription system configuration status', {
|
|
79
|
+
enableSubscriptions: config.enableSubscriptions,
|
|
80
|
+
capabilities: {
|
|
81
|
+
pgSubscriptions: config.capabilities.pgSubscriptions
|
|
82
|
+
},
|
|
83
|
+
recommendedMethod: 'pg-subscriptions',
|
|
84
|
+
walLevel: config.walLevel
|
|
85
|
+
});
|
|
86
|
+
// 3. Pre-generate store table information for dynamic queries
|
|
87
|
+
logger_1.subscriptionLogger.info('Pre-generating store table information for tool queries...');
|
|
88
|
+
const storeTablesInfo = await (0, universal_subscriptions_1.generateStoreTablesInfo)(pgPool);
|
|
89
|
+
const storeTableNames = Object.keys(storeTablesInfo);
|
|
90
|
+
logger_1.subscriptionLogger.info(`Discovered store tables: ${storeTableNames.join(', ')}`);
|
|
91
|
+
// 4. Create PostGraphile configuration
|
|
92
|
+
const postgraphileConfigOptions = {
|
|
93
|
+
port: PORT,
|
|
94
|
+
nodeEnv: NODE_ENV,
|
|
95
|
+
graphqlEndpoint: GRAPHQL_ENDPOINT,
|
|
96
|
+
enableSubscriptions: ENABLE_SUBSCRIPTIONS,
|
|
97
|
+
enableCors: ENABLE_CORS,
|
|
98
|
+
databaseUrl: DATABASE_URL,
|
|
99
|
+
availableTables: tableNames
|
|
100
|
+
};
|
|
101
|
+
logger_1.serverLogger.info('Creating PostGraphile configuration', {
|
|
102
|
+
endpoint: GRAPHQL_ENDPOINT,
|
|
103
|
+
enableCors: ENABLE_CORS,
|
|
104
|
+
enableSubscriptions: ENABLE_SUBSCRIPTIONS
|
|
105
|
+
});
|
|
106
|
+
// Use simplified configuration
|
|
107
|
+
const postgraphileConfig = {
|
|
108
|
+
...(0, plugins_1.createPostGraphileConfig)(postgraphileConfigOptions),
|
|
109
|
+
...subscription_config_1.subscriptionConfig.generatePostGraphileConfig()
|
|
110
|
+
};
|
|
111
|
+
// Add tools query plugin
|
|
112
|
+
const toolsPlugin = (0, universal_subscriptions_1.createUniversalSubscriptionsPlugin)(storeTablesInfo);
|
|
113
|
+
postgraphileConfig.appendPlugins = [...(postgraphileConfig.appendPlugins || []), toolsPlugin];
|
|
114
|
+
// 5. Create PostGraphile middleware
|
|
115
|
+
console.log('🔧 Creating PostGraphile middleware...');
|
|
116
|
+
const postgraphileMiddleware = (0, postgraphile_1.postgraphile)(pgPool, PG_SCHEMA, {
|
|
117
|
+
...postgraphileConfig
|
|
118
|
+
});
|
|
119
|
+
console.log('✅ PostGraphile middleware creation completed:', typeof postgraphileMiddleware);
|
|
120
|
+
// 6. Configure welcome page
|
|
121
|
+
const welcomeConfig = {
|
|
122
|
+
port: PORT,
|
|
123
|
+
graphqlEndpoint: GRAPHQL_ENDPOINT,
|
|
124
|
+
nodeEnv: NODE_ENV,
|
|
125
|
+
schema: PG_SCHEMA,
|
|
126
|
+
enableCors: ENABLE_CORS,
|
|
127
|
+
enableSubscriptions: ENABLE_SUBSCRIPTIONS
|
|
128
|
+
};
|
|
129
|
+
// 7. Create Express server manager
|
|
130
|
+
const serverManager = new enhanced_server_manager_1.EnhancedServerManager();
|
|
131
|
+
// 8. Create Express server
|
|
132
|
+
await serverManager.createEnhancedServer({
|
|
133
|
+
postgraphileMiddleware,
|
|
134
|
+
pgPool,
|
|
135
|
+
tableNames,
|
|
136
|
+
databaseUrl: DATABASE_URL,
|
|
137
|
+
allTables,
|
|
138
|
+
welcomeConfig,
|
|
139
|
+
postgraphileConfigOptions
|
|
140
|
+
});
|
|
141
|
+
// 9. Start Express server
|
|
142
|
+
await serverManager.startServer();
|
|
143
|
+
(0, logger_1.logPerformance)('Express server startup', startTime, {
|
|
144
|
+
port: PORT,
|
|
145
|
+
tableCount: allTables.length,
|
|
146
|
+
storeTableCount: storeTableNames.length,
|
|
147
|
+
nodeEnv: NODE_ENV,
|
|
148
|
+
framework: 'Express',
|
|
149
|
+
capabilities: {
|
|
150
|
+
pgSubscriptions: config.capabilities.pgSubscriptions
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
// 10. Display usage instructions
|
|
154
|
+
if (NODE_ENV === 'development') {
|
|
155
|
+
console.log('\n' + '='.repeat(80));
|
|
156
|
+
console.log('📖 Quick Access (Express Architecture):');
|
|
157
|
+
console.log(`Visit http://localhost:${PORT}/ to view homepage`);
|
|
158
|
+
console.log(`Visit http://localhost:${PORT}/playground to use GraphQL Playground`);
|
|
159
|
+
console.log(`Visit http://localhost:${PORT}/health to check server status`);
|
|
160
|
+
console.log(`Visit http://localhost:${PORT}/subscription-config to get client configuration`);
|
|
161
|
+
console.log(`Visit http://localhost:${PORT}/subscription-docs to view configuration guide`);
|
|
162
|
+
console.log('='.repeat(80) + '\n');
|
|
163
|
+
}
|
|
164
|
+
// 11. Set up simple and direct shutdown handling
|
|
165
|
+
let isShuttingDown = false;
|
|
166
|
+
const quickShutdown = (signal) => {
|
|
167
|
+
if (isShuttingDown) {
|
|
168
|
+
logger_1.systemLogger.info('⚡ Force exiting process...');
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
isShuttingDown = true;
|
|
172
|
+
logger_1.systemLogger.info(`🛑 Received ${signal} signal, shutting down Express server...`);
|
|
173
|
+
// Set 1 second force exit timeout
|
|
174
|
+
setTimeout(() => {
|
|
175
|
+
logger_1.systemLogger.info('⚡ Quick exit');
|
|
176
|
+
process.exit(0);
|
|
177
|
+
}, 1000);
|
|
178
|
+
// Try to shutdown Express server quickly
|
|
179
|
+
serverManager.quickShutdown().finally(() => {
|
|
180
|
+
process.exit(0);
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
process.on('SIGINT', () => quickShutdown('SIGINT'));
|
|
184
|
+
process.on('SIGTERM', () => quickShutdown('SIGTERM'));
|
|
185
|
+
// Simplified exception handling
|
|
186
|
+
process.on('unhandledRejection', (reason) => {
|
|
187
|
+
console.error('❌ Unhandled Promise rejection:', reason);
|
|
188
|
+
});
|
|
189
|
+
process.on('uncaughtException', (error) => {
|
|
190
|
+
console.error('❌ Uncaught exception:', error.message);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
logger_1.systemLogger.error('Failed to start Express server', error, {
|
|
196
|
+
databaseUrl: DATABASE_URL.replace(/:[^:]*@/, ':****@'),
|
|
197
|
+
schema: PG_SCHEMA,
|
|
198
|
+
port: PORT
|
|
199
|
+
});
|
|
200
|
+
logger_1.systemLogger.info('💡 Possible causes:');
|
|
201
|
+
logger_1.systemLogger.info('1. Database connection failed - check DATABASE_URL');
|
|
202
|
+
logger_1.systemLogger.info('2. Expected table structure not found in database - ensure sui-rust-indexer is running');
|
|
203
|
+
logger_1.systemLogger.info('3. Permission issues - ensure database user has sufficient permissions');
|
|
204
|
+
logger_1.systemLogger.info('4. Missing dependencies - run pnpm install');
|
|
205
|
+
// Display subscription configuration help
|
|
206
|
+
console.log('\n' + subscription_config_1.subscriptionConfig.generateDocumentation());
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
// Start application
|
|
211
|
+
logger_1.systemLogger.info('🚀 Starting Sui Indexer GraphQL Server (Express Architecture)...', {
|
|
212
|
+
nodeVersion: process.version,
|
|
213
|
+
platform: process.platform,
|
|
214
|
+
pid: process.pid
|
|
215
|
+
});
|
|
216
|
+
startServer();
|
|
217
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"all-fields-filter-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/all-fields-filter-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,eAAO,MAAM,qBAAqB,EAAE,MAwJnC,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AllFieldsFilterPlugin = void 0;
|
|
4
|
+
// All fields filter plugin - ensure all fields support filtering
|
|
5
|
+
const AllFieldsFilterPlugin = (builder) => {
|
|
6
|
+
// Extend filter input type, add filter support for all fields
|
|
7
|
+
builder.hook('GraphQLInputObjectType:fields', (fields, build, context) => {
|
|
8
|
+
const { scope: { isPgConnectionFilter, pgIntrospection: table } } = context;
|
|
9
|
+
// Only handle connection filters
|
|
10
|
+
if (!isPgConnectionFilter || !table || table.kind !== 'class') {
|
|
11
|
+
return fields;
|
|
12
|
+
}
|
|
13
|
+
const enhancedFields = { ...fields };
|
|
14
|
+
// Add filters for each field of the table
|
|
15
|
+
table.attributes.forEach((attr) => {
|
|
16
|
+
const fieldName = build.inflection.column(attr);
|
|
17
|
+
// Skip fields that already exist
|
|
18
|
+
if (enhancedFields[fieldName]) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Determine filter type based on field type
|
|
22
|
+
let filterType;
|
|
23
|
+
const pgType = attr.type;
|
|
24
|
+
// Special handling for BigInt type
|
|
25
|
+
if (pgType.name === 'int8' || pgType.name === 'bigint') {
|
|
26
|
+
// For BigInt type, try to use StringFilter (because BigInt is represented as string in GraphQL)
|
|
27
|
+
filterType = build.getTypeByName('StringFilter');
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Map PostgreSQL types to GraphQL filter types
|
|
31
|
+
switch (pgType.category) {
|
|
32
|
+
case 'S': // String type
|
|
33
|
+
filterType = build.getTypeByName('StringFilter');
|
|
34
|
+
break;
|
|
35
|
+
case 'N': // Numeric type
|
|
36
|
+
if (pgType.name.includes('int')) {
|
|
37
|
+
filterType = build.getTypeByName('IntFilter');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
filterType = build.getTypeByName('FloatFilter');
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
case 'B': // Boolean type
|
|
44
|
+
filterType = build.getTypeByName('BooleanFilter');
|
|
45
|
+
break;
|
|
46
|
+
case 'D': // Date/time type
|
|
47
|
+
filterType = build.getTypeByName('DatetimeFilter');
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
// For other types, use string filter as default
|
|
51
|
+
filterType = build.getTypeByName('StringFilter');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// If specific filter type not found, use string filter
|
|
55
|
+
if (!filterType) {
|
|
56
|
+
filterType = build.getTypeByName('StringFilter');
|
|
57
|
+
}
|
|
58
|
+
// Add field filter
|
|
59
|
+
if (filterType) {
|
|
60
|
+
enhancedFields[fieldName] = {
|
|
61
|
+
type: filterType,
|
|
62
|
+
description: `Filter by the object's \`${attr.name}\` field.`
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return enhancedFields;
|
|
67
|
+
});
|
|
68
|
+
// Ensure sorting options are generated for all fields
|
|
69
|
+
builder.hook('GraphQLEnumType:values', (values, build, context) => {
|
|
70
|
+
const { scope: { isPgRowSortEnum, pgIntrospection: table } } = context;
|
|
71
|
+
if (!isPgRowSortEnum || !table || table.kind !== 'class') {
|
|
72
|
+
return values;
|
|
73
|
+
}
|
|
74
|
+
const enhancedValues = { ...values };
|
|
75
|
+
// Add ASC and DESC sorting options for each field
|
|
76
|
+
table.attributes.forEach((attr) => {
|
|
77
|
+
const columnName = build.inflection.column(attr);
|
|
78
|
+
const enumName = build.inflection.constantCase(columnName);
|
|
79
|
+
// Add ascending sort
|
|
80
|
+
const ascKey = `${enumName}_ASC`;
|
|
81
|
+
if (!enhancedValues[ascKey]) {
|
|
82
|
+
enhancedValues[ascKey] = {
|
|
83
|
+
value: {
|
|
84
|
+
alias: `${attr.name.toLowerCase()}_ASC`,
|
|
85
|
+
specs: [[attr.name, true]]
|
|
86
|
+
},
|
|
87
|
+
description: `Sorts by ${attr.name} in ascending order.`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// Add descending sort
|
|
91
|
+
const descKey = `${enumName}_DESC`;
|
|
92
|
+
if (!enhancedValues[descKey]) {
|
|
93
|
+
enhancedValues[descKey] = {
|
|
94
|
+
value: {
|
|
95
|
+
alias: `${attr.name.toLowerCase()}_DESC`,
|
|
96
|
+
specs: [[attr.name, false]]
|
|
97
|
+
},
|
|
98
|
+
description: `Sorts by ${attr.name} in descending order.`
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return enhancedValues;
|
|
103
|
+
});
|
|
104
|
+
// Extend condition filters to support all fields
|
|
105
|
+
builder.hook('GraphQLInputObjectType:fields', (fields, build, context) => {
|
|
106
|
+
const { scope: { isPgCondition, pgIntrospection: table } } = context;
|
|
107
|
+
if (!isPgCondition || !table || table.kind !== 'class') {
|
|
108
|
+
return fields;
|
|
109
|
+
}
|
|
110
|
+
const enhancedFields = { ...fields };
|
|
111
|
+
// Add condition filters for each field
|
|
112
|
+
table.attributes.forEach((attr) => {
|
|
113
|
+
const fieldName = build.inflection.column(attr);
|
|
114
|
+
// Skip fields that already exist
|
|
115
|
+
if (enhancedFields[fieldName]) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Get GraphQL type
|
|
119
|
+
const gqlType = build.pgGetGqlTypeByTypeIdAndModifier(attr.typeId, attr.typeModifier);
|
|
120
|
+
if (gqlType) {
|
|
121
|
+
enhancedFields[fieldName] = {
|
|
122
|
+
type: gqlType,
|
|
123
|
+
description: `Checks for equality with the object's \`${attr.name}\` field.`
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return enhancedFields;
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
exports.AllFieldsFilterPlugin = AllFieldsFilterPlugin;
|
|
131
|
+
exports.default = exports.AllFieldsFilterPlugin;
|
|
132
|
+
//# sourceMappingURL=all-fields-filter-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"all-fields-filter-plugin.js","sourceRoot":"","sources":["../../src/plugins/all-fields-filter-plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Pool } from 'pg';
|
|
2
|
+
export interface TableField {
|
|
3
|
+
field_name: string;
|
|
4
|
+
field_type: string;
|
|
5
|
+
field_index: number | null;
|
|
6
|
+
is_key: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface DynamicTable {
|
|
9
|
+
table_name: string;
|
|
10
|
+
fields: TableField[];
|
|
11
|
+
}
|
|
12
|
+
export declare class DatabaseIntrospector {
|
|
13
|
+
private pool;
|
|
14
|
+
private schema;
|
|
15
|
+
constructor(pool: Pool, schema?: string);
|
|
16
|
+
getStoreTables(): Promise<string[]>;
|
|
17
|
+
getSystemTables(): Promise<string[]>;
|
|
18
|
+
getDynamicTableFields(tableName: string): Promise<TableField[]>;
|
|
19
|
+
getSystemTableFields(tableName: string): Promise<TableField[]>;
|
|
20
|
+
getAllTables(): Promise<DynamicTable[]>;
|
|
21
|
+
testConnection(): Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=database-introspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-introspector.d.ts","sourceRoot":"","sources":["../../src/plugins/database-introspector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAG1B,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAGD,qBAAa,oBAAoB;IACnB,OAAO,CAAC,IAAI;IAAQ,OAAO,CAAC,MAAM;gBAA1B,IAAI,EAAE,IAAI,EAAU,MAAM,GAAE,MAAiB;IAG3D,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBnC,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBpC,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAkB/D,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAmB9D,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA2BvC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CASzC"}
|