@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.
Files changed (79) hide show
  1. package/Dockerfile +31 -0
  2. package/EXPRESS_MIGRATION.md +176 -0
  3. package/LICENSE +92 -0
  4. package/README.md +908 -0
  5. package/dist/config/subscription-config.d.ts +47 -0
  6. package/dist/config/subscription-config.d.ts.map +1 -0
  7. package/dist/config/subscription-config.js +133 -0
  8. package/dist/config/subscription-config.js.map +1 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +217 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/plugins/all-fields-filter-plugin.d.ts +4 -0
  14. package/dist/plugins/all-fields-filter-plugin.d.ts.map +1 -0
  15. package/dist/plugins/all-fields-filter-plugin.js +132 -0
  16. package/dist/plugins/all-fields-filter-plugin.js.map +1 -0
  17. package/dist/plugins/database-introspector.d.ts +23 -0
  18. package/dist/plugins/database-introspector.d.ts.map +1 -0
  19. package/dist/plugins/database-introspector.js +96 -0
  20. package/dist/plugins/database-introspector.js.map +1 -0
  21. package/dist/plugins/enhanced-playground.d.ts +9 -0
  22. package/dist/plugins/enhanced-playground.d.ts.map +1 -0
  23. package/dist/plugins/enhanced-playground.js +97 -0
  24. package/dist/plugins/enhanced-playground.js.map +1 -0
  25. package/dist/plugins/enhanced-server-manager.d.ts +28 -0
  26. package/dist/plugins/enhanced-server-manager.d.ts.map +1 -0
  27. package/dist/plugins/enhanced-server-manager.js +232 -0
  28. package/dist/plugins/enhanced-server-manager.js.map +1 -0
  29. package/dist/plugins/index.d.ts +9 -0
  30. package/dist/plugins/index.d.ts.map +1 -0
  31. package/dist/plugins/index.js +26 -0
  32. package/dist/plugins/index.js.map +1 -0
  33. package/dist/plugins/postgraphile-config.d.ts +94 -0
  34. package/dist/plugins/postgraphile-config.d.ts.map +1 -0
  35. package/dist/plugins/postgraphile-config.js +183 -0
  36. package/dist/plugins/postgraphile-config.js.map +1 -0
  37. package/dist/plugins/query-filter.d.ts +4 -0
  38. package/dist/plugins/query-filter.d.ts.map +1 -0
  39. package/dist/plugins/query-filter.js +42 -0
  40. package/dist/plugins/query-filter.js.map +1 -0
  41. package/dist/plugins/simple-naming.d.ts +4 -0
  42. package/dist/plugins/simple-naming.d.ts.map +1 -0
  43. package/dist/plugins/simple-naming.js +79 -0
  44. package/dist/plugins/simple-naming.js.map +1 -0
  45. package/dist/plugins/welcome-page.d.ts +11 -0
  46. package/dist/plugins/welcome-page.d.ts.map +1 -0
  47. package/dist/plugins/welcome-page.js +203 -0
  48. package/dist/plugins/welcome-page.js.map +1 -0
  49. package/dist/universal-subscriptions.d.ts +32 -0
  50. package/dist/universal-subscriptions.d.ts.map +1 -0
  51. package/dist/universal-subscriptions.js +318 -0
  52. package/dist/universal-subscriptions.js.map +1 -0
  53. package/dist/utils/logger/index.d.ts +80 -0
  54. package/dist/utils/logger/index.d.ts.map +1 -0
  55. package/dist/utils/logger/index.js +232 -0
  56. package/dist/utils/logger/index.js.map +1 -0
  57. package/docker-compose.yml +87 -0
  58. package/package.json +71 -0
  59. package/server.log +62 -0
  60. package/src/config/subscription-config.ts +186 -0
  61. package/src/index.ts +239 -0
  62. package/src/plugins/README.md +123 -0
  63. package/src/plugins/all-fields-filter-plugin.ts +158 -0
  64. package/src/plugins/database-introspector.ts +126 -0
  65. package/src/plugins/enhanced-playground.ts +105 -0
  66. package/src/plugins/enhanced-server-manager.ts +282 -0
  67. package/src/plugins/index.ts +9 -0
  68. package/src/plugins/postgraphile-config.ts +226 -0
  69. package/src/plugins/query-filter.ts +50 -0
  70. package/src/plugins/simple-naming.ts +105 -0
  71. package/src/plugins/welcome-page.ts +218 -0
  72. package/src/universal-subscriptions.ts +397 -0
  73. package/src/utils/logger/README.md +193 -0
  74. package/src/utils/logger/index.ts +315 -0
  75. package/sui-indexer-schema.graphql +1004 -0
  76. package/test-express.js +124 -0
  77. package/test_listen_subscription.js +121 -0
  78. package/test_notification.js +63 -0
  79. package/tsconfig.json +28 -0
package/README.md ADDED
@@ -0,0 +1,908 @@
1
+ # 🚀 Universal GraphQL Server
2
+
3
+ 一个智能的 GraphQL 服务器适配器,能够自动连接到 `sui-rust-indexer` 创建的数据库,并动态生成完整的 GraphQL API。
4
+
5
+ ## ✨ 核心特性
6
+
7
+ ### 🎯 智能数据库适配
8
+ - **动态扫描**: 自动扫描 `sui-rust-indexer` 创建的所有表结构
9
+ - **PostGraphile 驱动**: 基于强大的 PostGraphile 自动生成 GraphQL API
10
+ - **零配置**: 无需手动定义 schema,基于现有数据库自动推断
11
+
12
+ ### 🔍 高级过滤功能
13
+ - **丰富的操作符**: 支持等于、大于、小于、包含、模糊匹配等20+种过滤操作符
14
+ - **逻辑组合**: 支持AND、OR、NOT逻辑操作符进行复杂条件组合
15
+ - **全字段过滤**: 自动为所有字段生成相应的过滤器
16
+ - **类型智能**: 根据字段类型自动提供合适的过滤操作符
17
+ - **关系过滤**: 支持基于关联表字段进行过滤
18
+
19
+ ### 📈 增强的排序和分页
20
+ - **全字段排序**: 支持对任意字段进行升序/降序排序
21
+ - **多字段排序**: 支持同时按多个字段排序
22
+ - **高效分页**: Relay风格的cursor分页和offset分页
23
+ - **性能优化**: 智能查询优化和索引建议
24
+
25
+ ### 📡 实时功能
26
+ - **WebSocket 支持**: 完整的 GraphQL 订阅功能
27
+ - **实时查询**: PostGraphile Live Queries 支持
28
+ - **数据监听**: 可选的数据库变更监听
29
+
30
+ ### 🛠️ 开发体验
31
+ - **GraphiQL**: 内置的 GraphQL 查询界面
32
+ - **自动文档**: 基于数据库结构自动生成的 API 文档
33
+ - **类型安全**: 完整的 TypeScript 支持
34
+ - **美观界面**: 现代化的欢迎页面和信息展示
35
+
36
+ ## 📦 安装
37
+
38
+ ```bash
39
+ # 进入项目目录
40
+ cd packages/universal-graphql-server
41
+
42
+ # 安装依赖
43
+ pnpm install
44
+
45
+ # 或使用 npm
46
+ npm install
47
+ ```
48
+
49
+ ## 🔧 配置
50
+
51
+ ### 环境变量
52
+
53
+ 创建 `.env` 文件:
54
+
55
+ ```env
56
+ # 数据库配置(连接到 sui-rust-indexer 的数据库)
57
+ DATABASE_URL=postgres://username:password@localhost:5432/sui_indexer_db
58
+
59
+ # 服务器配置
60
+ PORT=4000
61
+ NODE_ENV=development
62
+
63
+ # GraphQL 配置
64
+ GRAPHQL_ENDPOINT=/graphql
65
+ PG_SCHEMA=public
66
+
67
+ # 功能开关
68
+ ENABLE_CORS=true
69
+ ENABLE_SUBSCRIPTIONS=true
70
+ ```
71
+
72
+ ### 前置条件
73
+
74
+ 确保 `sui-rust-indexer` 已经运行并创建了数据库表:
75
+
76
+ 1. **系统表**: `__dubheStoreTransactions`, `__dubheStoreSchemas`, `__dubheStoreEvents`
77
+ 2. **元数据表**: `table_fields` (存储动态表结构信息)
78
+ 3. **动态表**: `store_*` 表(根据配置文件动态创建)
79
+
80
+ ## 🚀 运行
81
+
82
+ ### 开发模式
83
+
84
+ ```bash
85
+ # 启动开发服务器(支持热重载)
86
+ pnpm dev
87
+
88
+ # 或使用 npm
89
+ npm run dev
90
+ ```
91
+
92
+ ### 生产模式
93
+
94
+ ```bash
95
+ # 构建项目
96
+ pnpm build
97
+
98
+ # 启动生产服务器
99
+ pnpm start
100
+ ```
101
+
102
+ ## 📊 访问端点
103
+
104
+ 启动服务器后,你可以访问:
105
+
106
+ - **欢迎页面**: `http://localhost:4000` - 查看扫描到的表和系统信息
107
+ - **GraphQL API**: `http://localhost:4000/graphql` - API 端点
108
+ - **GraphiQL**: `http://localhost:4000/graphiql` - 交互式查询界面
109
+ - **WebSocket**: `ws://localhost:4000/graphql` - 订阅功能
110
+
111
+ ## 🎮 使用示例
112
+
113
+ ### 查询系统表
114
+
115
+ ```graphql
116
+ # 查询 Schemas 表
117
+ query GetSchemas {
118
+ allDubheStoreSchemas(first: 10) {
119
+ nodes {
120
+ id
121
+ name
122
+ key1
123
+ key2
124
+ value
125
+ lastUpdateCheckpoint
126
+ isRemoved
127
+ createdAt
128
+ }
129
+ }
130
+ }
131
+
132
+ # 查询 Transactions 表
133
+ query GetTransactions {
134
+ allDubheStoreTransactions(first: 10) {
135
+ nodes {
136
+ id
137
+ sender
138
+ checkpoint
139
+ digest
140
+ package
141
+ module
142
+ function
143
+ arguments
144
+ createdAt
145
+ }
146
+ }
147
+ }
148
+
149
+ # 查询 Events 表
150
+ query GetEvents {
151
+ allDubheStoreEvents(first: 10) {
152
+ nodes {
153
+ id
154
+ sender
155
+ name
156
+ value
157
+ checkpoint
158
+ digest
159
+ createdAt
160
+ }
161
+ }
162
+ }
163
+ ```
164
+
165
+ ### 查询动态表
166
+
167
+ 如果 `sui-rust-indexer` 创建了动态表(例如从 `config.json` 配置),你可以查询它们:
168
+
169
+ ```graphql
170
+ # 查询 store_accounts 表(如果存在)
171
+ query GetAccounts {
172
+ allStoreAccounts {
173
+ nodes {
174
+ assetId
175
+ account
176
+ balance
177
+ }
178
+ }
179
+ }
180
+
181
+ # 查询 store_position 表(如果存在)
182
+ query GetPositions {
183
+ allStorePositions {
184
+ nodes {
185
+ player
186
+ x
187
+ y
188
+ }
189
+ }
190
+ }
191
+ ```
192
+
193
+ ### 实时订阅
194
+
195
+ ```graphql
196
+ # 订阅 Schemas 变更
197
+ subscription OnSchemaChanges {
198
+ allDubheStoreSchemas(first: 1, orderBy: [CREATED_AT_DESC]) {
199
+ nodes {
200
+ id
201
+ name
202
+ value
203
+ createdAt
204
+ }
205
+ }
206
+ }
207
+
208
+ # 订阅 Events
209
+ subscription OnNewEvents {
210
+ allDubheStoreEvents(first: 1, orderBy: [CREATED_AT_DESC]) {
211
+ nodes {
212
+ id
213
+ name
214
+ value
215
+ checkpoint
216
+ }
217
+ }
218
+ }
219
+ ```
220
+
221
+ ### 高级查询
222
+
223
+ ```graphql
224
+ # 分页查询
225
+ query GetSchemasPaginated($after: Cursor) {
226
+ allDubheStoreSchemas(first: 10, after: $after) {
227
+ pageInfo {
228
+ hasNextPage
229
+ endCursor
230
+ }
231
+ nodes {
232
+ id
233
+ name
234
+ value
235
+ }
236
+ }
237
+ }
238
+
239
+ # 条件过滤
240
+ query GetSchemasByName($name: String!) {
241
+ allDubheStoreSchemas(condition: { name: $name }) {
242
+ nodes {
243
+ id
244
+ name
245
+ key1
246
+ key2
247
+ value
248
+ }
249
+ }
250
+ }
251
+
252
+ # 排序查询
253
+ query GetRecentTransactions {
254
+ allDubheStoreTransactions(
255
+ first: 20,
256
+ orderBy: [CREATED_AT_DESC]
257
+ ) {
258
+ nodes {
259
+ id
260
+ sender
261
+ function
262
+ checkpoint
263
+ createdAt
264
+ }
265
+ }
266
+ }
267
+ ```
268
+
269
+ ### 高级过滤查询
270
+
271
+ 现在支持强大的过滤功能,包括多种操作符和逻辑组合:
272
+
273
+ ```graphql
274
+ # 基础过滤 - 使用大于操作符
275
+ query GetHighValueAccounts {
276
+ storeAccounts(filter: {
277
+ balance: { gt: "1000" }
278
+ }) {
279
+ nodes {
280
+ assetId
281
+ account
282
+ balance
283
+ }
284
+ }
285
+ }
286
+
287
+ # 多条件过滤 - 隐式AND组合
288
+ query GetSpecificAccounts {
289
+ storeAccounts(filter: {
290
+ balance: { gte: "100", lte: "10000" },
291
+ assetId: { startsWith: "0x2" }
292
+ }) {
293
+ nodes {
294
+ assetId
295
+ account
296
+ balance
297
+ }
298
+ }
299
+ }
300
+
301
+ # 逻辑操作符 - OR组合
302
+ query GetAccountsWithConditions {
303
+ storeAccounts(filter: {
304
+ or: [
305
+ { balance: { gt: "50000" } },
306
+ { assetId: { in: ["0x123", "0x456", "0x789"] } }
307
+ ]
308
+ }) {
309
+ nodes {
310
+ assetId
311
+ account
312
+ balance
313
+ }
314
+ }
315
+ }
316
+
317
+ # 复杂逻辑组合 - AND, OR, NOT
318
+ query GetComplexFilteredAccounts {
319
+ storeAccounts(filter: {
320
+ and: [
321
+ {
322
+ or: [
323
+ { balance: { gt: "1000" } },
324
+ { assetId: { like: "%special%" } }
325
+ ]
326
+ },
327
+ {
328
+ not: {
329
+ account: { includesInsensitive: "test" }
330
+ }
331
+ }
332
+ ]
333
+ }) {
334
+ nodes {
335
+ assetId
336
+ account
337
+ balance
338
+ }
339
+ }
340
+ }
341
+
342
+ # 字符串模糊搜索
343
+ query SearchPlayers {
344
+ storeEncounters(filter: {
345
+ player: { includesInsensitive: "alice" },
346
+ monster: { isNull: false }
347
+ }) {
348
+ nodes {
349
+ player
350
+ monster
351
+ catchAttempts
352
+ }
353
+ }
354
+ }
355
+
356
+ # 数组和范围查询
357
+ query GetPositionsInRange {
358
+ storePositions(filter: {
359
+ player: { in: ["player1", "player2", "player3"] },
360
+ x: { gte: "10", lte: "100" },
361
+ y: { isNull: false }
362
+ }) {
363
+ nodes {
364
+ player
365
+ x
366
+ y
367
+ }
368
+ }
369
+ }
370
+ ```
371
+
372
+ ### 增强的排序功能
373
+
374
+ 支持所有字段的多种排序组合:
375
+
376
+ ```graphql
377
+ # 单字段排序
378
+ query GetAccountsByBalance {
379
+ storeAccounts(
380
+ orderBy: [BALANCE_DESC]
381
+ ) {
382
+ nodes {
383
+ assetId
384
+ account
385
+ balance
386
+ }
387
+ }
388
+ }
389
+
390
+ # 多字段排序
391
+ query GetAccountsMultiSort {
392
+ storeAccounts(
393
+ orderBy: [ASSET_ID_ASC, BALANCE_DESC]
394
+ ) {
395
+ nodes {
396
+ assetId
397
+ account
398
+ balance
399
+ }
400
+ }
401
+ }
402
+
403
+ # 过滤 + 排序 + 分页
404
+ query GetFilteredSortedPaginated($after: Cursor) {
405
+ storeAccounts(
406
+ filter: {
407
+ balance: { gt: "1000" }
408
+ },
409
+ orderBy: [BALANCE_DESC, ASSET_ID_ASC],
410
+ first: 10,
411
+ after: $after
412
+ ) {
413
+ edges {
414
+ node {
415
+ assetId
416
+ account
417
+ balance
418
+ }
419
+ cursor
420
+ }
421
+ pageInfo {
422
+ hasNextPage
423
+ hasPreviousPage
424
+ startCursor
425
+ endCursor
426
+ }
427
+ totalCount
428
+ }
429
+ }
430
+ ```
431
+
432
+ > 📖 **详细过滤功能文档**: 查看 [高级过滤和查询功能使用指南](./ADVANCED_FILTERING_GUIDE.md) 了解所有支持的操作符、使用示例和最佳实践。
433
+
434
+ ## 🏗️ 架构说明
435
+
436
+ ### 工作原理
437
+
438
+ ```
439
+ sui-rust-indexer 数据库
440
+
441
+ [数据库内省器]
442
+
443
+ [PostGraphile]
444
+
445
+ [GraphQL API]
446
+
447
+ [WebSocket]
448
+ ```
449
+
450
+ 1. **数据库扫描**: 启动时自动扫描数据库中的所有表
451
+ 2. **结构解析**: 从 `table_fields` 元数据表读取动态表结构
452
+ 3. **Schema 生成**: PostGraphile 基于表结构自动生成 GraphQL schema
453
+ 4. **API 服务**: 提供完整的 GraphQL CRUD 操作和订阅功能
454
+
455
+ ### 支持的表类型
456
+
457
+ 1. **系统表**:
458
+ - `__dubheStoreTransactions` - 交易记录
459
+ - `__dubheStoreSchemas` - Schema 数据
460
+ - `__dubheStoreEvents` - 事件记录
461
+ - `table_fields` - 表结构元数据
462
+
463
+ 2. **动态表**:
464
+ - `store_*` - 根据 `sui-rust-indexer` 配置动态创建的表
465
+
466
+ ## 🚀 部署
467
+
468
+ ### Docker 部署
469
+
470
+ ```bash
471
+ # 使用提供的 docker-compose
472
+ docker-compose up -d
473
+ ```
474
+
475
+ ### 手动部署
476
+
477
+ ```bash
478
+ # 构建项目
479
+ pnpm build
480
+
481
+ # 设置环境变量
482
+ export DATABASE_URL="postgres://..."
483
+ export PORT=4000
484
+
485
+ # 启动服务器
486
+ pnpm start
487
+ ```
488
+
489
+ ## 🔧 配置选项
490
+
491
+ ### PostGraphile 特性
492
+
493
+ - ✅ **自动 CRUD**: 所有表自动支持增删改查
494
+ - ✅ **关系查询**: 自动处理表之间的关系
495
+ - ✅ **分页**: Relay 风格的连接分页
496
+ - ✅ **订阅**: GraphQL 订阅和 Live Queries
497
+ - ✅ **过滤排序**: 强大的查询条件和排序
498
+ - ✅ **权限控制**: 基于 PostgreSQL 的行级安全
499
+
500
+ ### 自定义配置
501
+
502
+ 在 `src/index.ts` 中可以修改 PostGraphile 配置:
503
+
504
+ ```typescript
505
+ const createPostGraphileConfig = (availableTables: string[]) => {
506
+ return {
507
+ // 添加插件
508
+ appendPlugins: [
509
+ require('@graphile-contrib/pg-simplify-inflector'),
510
+ require('postgraphile-plugin-connection-filter')
511
+ ],
512
+
513
+ // 自定义命名
514
+ inflection: {
515
+ // 自定义表名映射
516
+ },
517
+
518
+ // 添加自定义字段
519
+ makeAddInflectorsPlugin: (inflectors) => {
520
+ // 自定义逻辑
521
+ }
522
+ };
523
+ };
524
+ ```
525
+
526
+ ## 🛡️ 安全配置
527
+
528
+ ### 数据库权限
529
+
530
+ ```sql
531
+ -- 创建只读用户
532
+ CREATE USER graphql_readonly WITH PASSWORD 'secure_password';
533
+
534
+ -- 授予查询权限
535
+ GRANT CONNECT ON DATABASE sui_indexer TO graphql_readonly;
536
+ GRANT USAGE ON SCHEMA public TO graphql_readonly;
537
+ GRANT SELECT ON ALL TABLES IN SCHEMA public TO graphql_readonly;
538
+
539
+ -- 如需写入权限
540
+ GRANT INSERT, UPDATE, DELETE ON specific_tables TO graphql_readonly;
541
+ ```
542
+
543
+ ### 生产环境配置
544
+
545
+ ```env
546
+ NODE_ENV=production
547
+ ENABLE_CORS=false
548
+ # 或设置特定来源
549
+ CORS_ORIGIN=https://yourdomain.com
550
+ ```
551
+
552
+ ## 📋 故障排除
553
+
554
+ ### 常见问题
555
+
556
+ 1. **数据库连接失败**
557
+ ```
558
+ 解决方案:检查 DATABASE_URL 和数据库服务状态
559
+ ```
560
+
561
+ 2. **表扫描为空**
562
+ ```
563
+ 解决方案:确保 sui-rust-indexer 已运行并创建了表
564
+ ```
565
+
566
+ 3. **schema 生成失败**
567
+ ```
568
+ 解决方案:检查 table_fields 表是否存在且有数据
569
+ ```
570
+
571
+ 4. **WebSocket 连接失败**
572
+ ```
573
+ 解决方案:检查防火墙设置和 ENABLE_SUBSCRIPTIONS 配置
574
+ ```
575
+
576
+ ### 调试模式
577
+
578
+ ```bash
579
+ # 启用详细日志
580
+ DEBUG=postgraphile:* pnpm dev
581
+
582
+ # 查看生成的 schema
583
+ ls -la *.graphql
584
+ ```
585
+
586
+ ## 🤝 集成指南
587
+
588
+ ### 与 sui-rust-indexer 集成
589
+
590
+ 1. **启动顺序**: 先启动 `sui-rust-indexer`,再启动 GraphQL 服务器
591
+ 2. **数据库共享**: 两个服务共享同一个 PostgreSQL 数据库
592
+ 3. **配置同步**: 确保数据库连接配置一致
593
+
594
+ ### 与前端集成
595
+
596
+ ```typescript
597
+ // Apollo Client 配置
598
+ import { ApolloClient, InMemoryCache, split, HttpLink } from '@apollo/client';
599
+ import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
600
+ import { createClient } from 'graphql-ws';
601
+
602
+ const httpLink = new HttpLink({
603
+ uri: 'http://localhost:4000/graphql',
604
+ });
605
+
606
+ const wsLink = new GraphQLWsLink(createClient({
607
+ url: 'ws://localhost:4000/graphql',
608
+ }));
609
+
610
+ const splitLink = split(
611
+ ({ query }) => {
612
+ const definition = getMainDefinition(query);
613
+ return (
614
+ definition.kind === 'OperationDefinition' &&
615
+ definition.operation === 'subscription'
616
+ );
617
+ },
618
+ wsLink,
619
+ httpLink,
620
+ );
621
+
622
+ const client = new ApolloClient({
623
+ link: splitLink,
624
+ cache: new InMemoryCache(),
625
+ });
626
+ ```
627
+
628
+ ## 📄 许可证
629
+
630
+ MIT License
631
+
632
+ ## WebSocket Subscription 支持
633
+
634
+ 本服务器现已支持通过 WebSocket 进行实时数据订阅,使用 PostgreSQL 的 LISTEN/NOTIFY 机制。
635
+
636
+ ### 环境变量配置
637
+
638
+ 创建 `.env` 文件并配置以下变量:
639
+
640
+ ```bash
641
+ # 数据库连接 URL
642
+ # 注意:对于 WebSocket 订阅,请使用直接连接而不是连接池
643
+ DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/postgres
644
+
645
+ # 服务器端口
646
+ PORT=4000
647
+
648
+ # 环境模式
649
+ NODE_ENV=development
650
+
651
+ # GraphQL 端点路径
652
+ GRAPHQL_ENDPOINT=/graphql
653
+
654
+ # PostgreSQL Schema
655
+ PG_SCHEMA=public
656
+
657
+ # 启用 CORS
658
+ ENABLE_CORS=true
659
+
660
+ # 启用 WebSocket 订阅
661
+ # 设置为 true 以启用实时订阅功能
662
+ ENABLE_SUBSCRIPTIONS=true
663
+ ```
664
+
665
+ ### 订阅类型
666
+
667
+ 1. **特定 Store 表订阅** - 自动为每个 `store_*` 表生成订阅
668
+ 2. **所有 Store 表订阅** - 订阅所有 store 表的变更
669
+ 3. **任意表订阅** - 订阅任意表的变更
670
+ 4. **系统事件订阅** - 订阅系统级事件
671
+
672
+ ### 测试订阅
673
+
674
+ ```bash
675
+ # 安装依赖
676
+ npm install
677
+
678
+ # 启动服务器
679
+ npm run dev
680
+
681
+ # 在另一个终端测试订阅
682
+ npm run test:subscription
683
+ ```
684
+
685
+ ### 使用示例
686
+
687
+ 在 GraphiQL 中运行:
688
+
689
+ ```graphql
690
+ subscription {
691
+ allStoresChanged {
692
+ event
693
+ table
694
+ timestamp
695
+ data
696
+ id
697
+ }
698
+ }
699
+ ```
700
+
701
+ 详细使用指南请参考 [SUBSCRIPTION_USAGE.md](./SUBSCRIPTION_USAGE.md)。
702
+
703
+ ### 注意事项
704
+
705
+ 1. WebSocket 订阅不兼容 Neon 连接池,请使用直接数据库连接
706
+ 2. 确保 PostgreSQL 支持 LISTEN/NOTIFY
707
+ 3. sui-rust-indexer 会自动创建必要的触发器
708
+ 4. 大量订阅可能影响性能,请合理使用
709
+
710
+ ## 📄 许可证
711
+
712
+ MIT License
713
+
714
+ ---
715
+
716
+ 💡 **提示**: 这个服务器设计为 `sui-rust-indexer` 的完美伴侣,提供强大的 GraphQL 接口来访问索引的数据。无需手动配置 schema,一切都是自动的!
717
+
718
+ # 🔧 主要特性
719
+
720
+ - 🚀 **自动扫描数据库表结构**:无需手动配置,自动适配 sui-rust-indexer 的动态表
721
+ - 📊 **完整的 GraphQL API**:为所有表自动生成 CRUD 操作
722
+ - 📡 **实时订阅支持**:WebSocket 订阅数据变更
723
+ - 🎮 **增强版 GraphQL Playground**:现代化的查询界面,支持 Schema Explorer 和代码导出
724
+ - 🔍 **智能过滤和分页**:支持复杂查询条件
725
+ - 🎯 **开发友好**:提供详细的欢迎页面和使用指南
726
+ - 📝 **结构化日志系统**:使用 Winston 提供专业的日志记录和监控
727
+
728
+ ## 📋 环境要求
729
+
730
+ - Node.js 18.0.0+
731
+ - PostgreSQL 数据库(由 sui-rust-indexer 管理)
732
+ - TypeScript 5.0+
733
+
734
+ ## 🚀 快速开始
735
+
736
+ ### 1. 安装依赖
737
+
738
+ ```bash
739
+ npm install
740
+ ```
741
+
742
+ ### 2. 配置环境变量
743
+
744
+ 复制并编辑环境变量文件:
745
+
746
+ ```bash
747
+ cp .env.example .env
748
+ ```
749
+
750
+ 主要配置项:
751
+
752
+ ```bash
753
+ # 数据库连接
754
+ DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/postgres
755
+
756
+ # 服务器配置
757
+ PORT=4000
758
+ GRAPHQL_ENDPOINT=/graphql
759
+ PG_SCHEMA=public
760
+
761
+ # 功能开关
762
+ ENABLE_CORS=true
763
+ ENABLE_SUBSCRIPTIONS=true
764
+ REALTIME_PORT=4001
765
+
766
+ # 日志配置
767
+ LOG_LEVEL=info # error, warn, info, debug, verbose
768
+ ```
769
+
770
+ ### 3. 启动服务器
771
+
772
+ ```bash
773
+ # 开发模式(支持热重载)
774
+ npm run dev
775
+
776
+ # 生产模式
777
+ npm run build
778
+ npm start
779
+ ```
780
+
781
+ ### 4. 访问服务
782
+
783
+ - 🏠 **主页**:http://localhost:4000 - 服务器信息和使用指南
784
+ - 🎮 **GraphQL Playground**:http://localhost:4000/playground - 现代化查询界面
785
+ - 📊 **GraphQL API**:http://localhost:4000/graphql - API 端点
786
+ - 📡 **WebSocket 订阅**:ws://localhost:4000/graphql - 实时订阅
787
+
788
+ ## 📊 日志系统
789
+
790
+ 本项目使用专业的 Winston 日志系统,提供结构化的日志记录:
791
+
792
+ ### 主要特性
793
+
794
+ - 🎨 **彩色输出**:不同级别使用不同颜色
795
+ - 📁 **文件记录**:自动保存到 `logs/` 目录
796
+ - 🏷️ **组件标识**:明确标识日志来源
797
+ - 📊 **结构化数据**:支持附加元数据
798
+ - ⚡ **性能监控**:内置性能指标记录
799
+ - 🔒 **敏感信息保护**:自动隐藏密码等敏感信息
800
+
801
+ ### 日志级别
802
+
803
+ ```bash
804
+ export LOG_LEVEL=debug # 显示所有级别的日志
805
+ export LOG_LEVEL=info # 默认级别,生产环境推荐
806
+ export LOG_LEVEL=warn # 只显示警告和错误
807
+ ```
808
+
809
+ ### 日志文件
810
+
811
+ - `logs/combined.log`:所有日志(JSON格式)
812
+ - `logs/error.log`:错误日志
813
+ - `logs/exceptions.log`:未捕获异常
814
+ - `logs/rejections.log`:Promise拒绝
815
+
816
+ 详细使用说明请参考:[LOGGING.md](./LOGGING.md)
817
+
818
+ ## 🎮 使用 GraphQL Playground
819
+
820
+ 访问 http://localhost:4000/playground 体验增强版 GraphQL Playground:
821
+
822
+ ### 主要功能
823
+
824
+ - 📊 **Schema Explorer**:可视化浏览 GraphQL Schema
825
+ - 🔍 **智能补全**:自动补全查询语句
826
+ - 📝 **查询历史**:保存和管理查询历史
827
+ - 📋 **代码导出**:支持多种语言的代码生成
828
+ - 🎨 **现代化界面**:美观的用户界面
829
+
830
+ ### 示例查询
831
+
832
+ ```graphql
833
+ # 查询所有动态表
834
+ {
835
+ __schema {
836
+ queryType {
837
+ fields {
838
+ name
839
+ description
840
+ }
841
+ }
842
+ }
843
+ }
844
+
845
+ # 如果有 store_accounts 表
846
+ {
847
+ allStoreAccounts(first: 10) {
848
+ edges {
849
+ node {
850
+ id
851
+ # 其他字段根据表结构动态生成
852
+ }
853
+ }
854
+ }
855
+ }
856
+ ```
857
+
858
+ ### 实时订阅
859
+
860
+ 如果启用了订阅功能,可以使用实时订阅:
861
+
862
+ ```graphql
863
+ subscription {
864
+ allStoresChanged {
865
+ event
866
+ table
867
+ data
868
+ timestamp
869
+ }
870
+ }
871
+ ```
872
+
873
+ ## 🔧 配置选项
874
+
875
+ ### 数据库配置
876
+
877
+ ```bash
878
+ DATABASE_URL=postgres://username:password@host:port/database
879
+ PG_SCHEMA=public # 要扫描的数据库模式
880
+ ```
881
+
882
+ ### 服务器配置
883
+
884
+ ```bash
885
+ PORT=4000 # HTTP 服务器端口
886
+ GRAPHQL_ENDPOINT=/graphql # GraphQL API 路径
887
+ ENABLE_CORS=true # 是否启用 CORS
888
+ ```
889
+
890
+ ### 订阅配置
891
+
892
+ ```bash
893
+ ENABLE_SUBSCRIPTIONS=true # 是否启用订阅功能
894
+ REALTIME_PORT=4001 # WebSocket 服务器端口
895
+ ```
896
+
897
+ ### 日志配置
898
+
899
+ ```bash
900
+ LOG_LEVEL=info # 日志级别
901
+ LOG_TO_FILE=true # 是否保存到文件
902
+ LOG_DIR=./logs # 日志文件目录
903
+
904
+ # PostGraphile SQL查询日志控制
905
+ DISABLE_QUERY_LOG=false # 设置为true禁用SQL查询日志
906
+ ENABLE_QUERY_LOG=false # 生产环境中设置为true启用查询日志
907
+ QUERY_TIMEOUT=30000 # GraphQL查询超时时间(毫秒)
908
+ ```