@things-factory/shell 4.0.0-alpha.6 → 4.0.0-beta.0

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 (85) hide show
  1. package/bin/things-factory-dev +5 -11
  2. package/client/elements/oops-progress.js +15 -7
  3. package/client/graphql-client.js +23 -17
  4. package/client/index.js +2 -2
  5. package/client/{notification-store.js → indexdb.js} +49 -40
  6. package/client/serviceworker/sw-src.js +3 -3
  7. package/client/themes/oops-theme.css +9 -9
  8. package/config/config.development.js +12 -1
  9. package/dist-server/graphql-local-client.js +1 -1
  10. package/dist-server/graphql-local-client.js.map +1 -1
  11. package/dist-server/index.js +1 -1
  12. package/dist-server/initializers/database.js +3 -2
  13. package/dist-server/initializers/database.js.map +1 -1
  14. package/dist-server/initializers/naming-strategy.js +1 -1
  15. package/dist-server/initializers/naming-strategy.js.map +1 -1
  16. package/dist-server/middlewares/domain-middleware.js +1 -1
  17. package/dist-server/middlewares/domain-middleware.js.map +1 -1
  18. package/dist-server/middlewares/index.js +2 -2
  19. package/dist-server/middlewares/index.js.map +1 -1
  20. package/dist-server/migrations/1000000000000-SeedDomain.js +2 -2
  21. package/dist-server/migrations/1000000000000-SeedDomain.js.map +1 -1
  22. package/dist-server/pubsub-log-transport.js +1 -1
  23. package/dist-server/pubsub-log-transport.js.map +1 -1
  24. package/dist-server/pubsub.js +15 -13
  25. package/dist-server/pubsub.js.map +1 -1
  26. package/dist-server/routers/index.js +1 -1
  27. package/dist-server/schema.js +10 -10
  28. package/dist-server/schema.js.map +1 -1
  29. package/dist-server/server-dev.js +71 -52
  30. package/dist-server/server-dev.js.map +1 -1
  31. package/dist-server/server.js +62 -47
  32. package/dist-server/server.js.map +1 -1
  33. package/dist-server/service/common-types/index.js +1 -1
  34. package/dist-server/service/common-types/list-param.js +15 -15
  35. package/dist-server/service/common-types/list-param.js.map +1 -1
  36. package/dist-server/service/common-types/log.js +5 -5
  37. package/dist-server/service/common-types/log.js.map +1 -1
  38. package/dist-server/service/common-types/object-ref.js +4 -4
  39. package/dist-server/service/common-types/object-ref.js.map +1 -1
  40. package/dist-server/service/common-types/scalar-any.js +27 -13
  41. package/dist-server/service/common-types/scalar-any.js.map +1 -1
  42. package/dist-server/service/directive-transaction/index.js +1 -1
  43. package/dist-server/service/directive-transaction/transaction.js +5 -4
  44. package/dist-server/service/directive-transaction/transaction.js.map +1 -1
  45. package/dist-server/service/domain/domain-resolver.js +43 -41
  46. package/dist-server/service/domain/domain-resolver.js.map +1 -1
  47. package/dist-server/service/domain/domain-types.js +17 -17
  48. package/dist-server/service/domain/domain-types.js.map +1 -1
  49. package/dist-server/service/domain/domain.js +31 -31
  50. package/dist-server/service/domain/domain.js.map +1 -1
  51. package/dist-server/service/index.js +9 -6
  52. package/dist-server/service/index.js.map +1 -1
  53. package/dist-server/service/subscription-data/data-resolver.js +5 -4
  54. package/dist-server/service/subscription-data/data-resolver.js.map +1 -1
  55. package/dist-server/service/subscription-data/data-types.js +4 -4
  56. package/dist-server/service/subscription-data/data-types.js.map +1 -1
  57. package/dist-server/utils/condition-builder.js +25 -26
  58. package/dist-server/utils/condition-builder.js.map +1 -1
  59. package/dist-server/utils/get-domain.js +3 -3
  60. package/dist-server/utils/get-domain.js.map +1 -1
  61. package/dist-server/utils/index.js +1 -1
  62. package/dist-server/utils/list-params-converter.js +21 -21
  63. package/dist-server/utils/list-params-converter.js.map +1 -1
  64. package/dist-server/utils/list-query-builder.js +4 -3
  65. package/dist-server/utils/list-query-builder.js.map +1 -1
  66. package/helps/about/components.md +3 -0
  67. package/helps/about/{common → framework}/redirection.md +0 -0
  68. package/helps/about/framework/typegraphql.md +74 -0
  69. package/helps/about/framework.md +10 -0
  70. package/helps/about/modules.md +3 -1
  71. package/helps/about/things-factory.en.md +3 -0
  72. package/helps/about/things-factory.ko.md +4 -0
  73. package/helps/components/oops-progress.md +73 -0
  74. package/package.json +25 -29
  75. package/server/pubsub.ts +16 -15
  76. package/server/schema.ts +5 -5
  77. package/server/server-dev.ts +55 -36
  78. package/server/server.ts +47 -31
  79. package/server/service/common-types/list-param.ts +1 -1
  80. package/server/service/common-types/scalar-any.ts +29 -13
  81. package/server/service/domain/domain-resolver.ts +8 -6
  82. package/server/service/index.ts +14 -5
  83. package/server/utils/condition-builder.ts +23 -25
  84. package/server/utils/list-query-builder.ts +1 -1
  85. package/db.test.sqlite +0 -0
@@ -7,6 +7,10 @@ Things-Factory 프레임워크는 수많은 NPM 패키지들로 구성된 모노
7
7
  이 패키지들은 자바스크립트 앱을 개발하기위한 최적의 계층적 구조를 구성하도록 개발되었습니다.
8
8
  Typescript를 포함하여, 서버사이들의 Koa, 웹컴포넌트 UI를 위한 LitElement, 클라이언트 서버간의 Graphql 통신을 위한 Apollo 그리고 테스트를 위한 Jest 등이 적용되었습니다. 이들을 잘 연결하고 조립하여 최고의 어플리케이션을 만들어보세요.
9
9
 
10
+ - [Contents for modules](./modules.md)
11
+ - [Contents for components](./components.md)
12
+ - [Concepts for framework](./framework.md)
13
+
10
14
  ## features
11
15
 
12
16
  - It is based on module structure.
@@ -0,0 +1,73 @@
1
+ # OOPS Progress 컴포넌트
2
+
3
+ 긴 시간 진행되는 작업의 진행 상황을 표현해주기 위해 서버에 진행율을 Subscribe하는 클라이언트 컴포넌트이다.
4
+ 이 컴포넌트는 자체적으로 시각적 요소를 포함하지 않지만, 시각적 표현을 위해서 자식 노드(Light DOM)를 포함할 수는 있다.
5
+
6
+ ## properties
7
+
8
+ - tag: String 서브스크립션 태그이며, 서버의 'publishProgress'의 tag와 일치시키도록 한다.
9
+ - subscription: String (readonly) 이 속성이 값을 가지고 있으면, 서브스크립션 중임을 의미한다.
10
+
11
+ ## methods
12
+
13
+ - startSubscribe() 진행율 구독을 시작한다.
14
+ - stopSubscribe() 진행율 구독을 종료한다.(서버쪽 작업의 종료를 의미하지 않으며, 클라이언트에서 구독을 종료한다는 의미임.)
15
+
16
+ ## event
17
+
18
+ - progress(event) 서버로부터 진행율이 Subscribe 되었을 때 발생한다.
19
+ - event.detail : progress 값을 갖는다.
20
+ - finish(event) 진행율이 100% 도달하면 발생한다.
21
+
22
+ ## 예시
23
+
24
+ ### 클라이언트 사이드
25
+
26
+ ```
27
+ <oops-progress
28
+ .tag='progress-pending-job'
29
+ @progress=${e => {
30
+ this.progress = e.detail
31
+ }}
32
+ @finish=${() => {
33
+ console.log('complete')
34
+ }}
35
+ ?hidden=${progress < 0 || progress > 100}
36
+ >
37
+ <div>
38
+ <mwc-linear-progress .progress=${progress / 100}></mwc-linear-progress>
39
+ <span>Progress : ${progress} % (${message})</span>
40
+ </div>
41
+ </oops-progress>
42
+
43
+ ```
44
+
45
+ ### 서버사이드
46
+
47
+ ```
48
+ import { sleep } from '@things-factory/utils'
49
+
50
+ ...
51
+
52
+ @Mutation(returns => String, { description: 'To reference of pending job progress' })
53
+ async referencePendingJob(
54
+ @Root() _,
55
+ @Ctx() context: any
56
+ ) : Promise<string> {
57
+
58
+ const { domain } = context.state
59
+
60
+ for(var i = 0;i <= 100;i++) {
61
+ await sleep(100)
62
+
63
+ publishProgress({
64
+ domain,
65
+ tag: 'progress-pending-job',
66
+ progress: i,
67
+ message: `${i * 10} / 1000`
68
+ })
69
+ }
70
+
71
+ return 'success'
72
+ }
73
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/shell",
3
- "version": "4.0.0-alpha.6",
3
+ "version": "4.0.0-beta.0",
4
4
  "description": "Core module for framework",
5
5
  "bin": {
6
6
  "things-factory": "bin/things-factory",
@@ -31,9 +31,11 @@
31
31
  "test": "NODE_ENV=test jest"
32
32
  },
33
33
  "dependencies": {
34
+ "@apollo/client": "^3.4.16",
34
35
  "@graphql-tools/merge": "^7.0.0",
35
- "@graphql-tools/utils": "^8.0.2",
36
- "@hatiolab/things-scene": "^2.7.6",
36
+ "@graphql-tools/schema": "^8.2.0",
37
+ "@graphql-tools/utils": "^8.3.0",
38
+ "@hatiolab/things-scene": "^2.7.11",
37
39
  "@koa/cors": "^3.1.0",
38
40
  "@material/mwc-button": "^0.22.1",
39
41
  "@material/mwc-fab": "^0.22.1",
@@ -41,18 +43,15 @@
41
43
  "@material/mwc-icon-button": "^0.22.1",
42
44
  "@material/mwc-slider": "^0.22.1",
43
45
  "@material/mwc-textfield": "^0.22.1",
44
- "@things-factory/env": "^4.0.0-alpha.6",
45
- "@things-factory/styles": "^4.0.0-alpha.6",
46
- "@things-factory/utils": "^4.0.0-alpha.6",
47
- "@webcomponents/webcomponentsjs": "^2.2.7",
48
- "apollo-cache-inmemory": "^1.6.6",
49
- "apollo-cache-persist": "^0.1.1",
50
- "apollo-client": "^2.6.10",
51
- "apollo-link": "^1.2.14",
52
- "apollo-link-error": "^1.1.13",
53
- "apollo-link-http": "^1.5.17",
54
- "apollo-server-koa": "^2.25.2",
55
- "apollo-upload-client": "^12.1.0",
46
+ "@things-factory/ejs-remote": "^4.0.0-beta.0",
47
+ "@things-factory/env": "^4.0.0-beta.0",
48
+ "@things-factory/styles": "^4.0.0-beta.0",
49
+ "@things-factory/utils": "^4.0.0-beta.0",
50
+ "@webcomponents/webcomponentsjs": "^2.6.0",
51
+ "apollo-server-core": "^3.4.0",
52
+ "apollo-server-koa": "^3.4.0",
53
+ "apollo-server-types": "^3.4.0",
54
+ "apollo-upload-client": "^16.0.0",
56
55
  "args": "^5.0.0",
57
56
  "broadcastchannel-polyfill": "^1.0.1",
58
57
  "chalk": "^4.1.0",
@@ -63,31 +62,29 @@
63
62
  "firebase": "^8.0.1",
64
63
  "fs-extra": "^9.0.1",
65
64
  "glob": "^7.1.6",
66
- "graphql": "^15.5.1",
65
+ "graphql": "^15.6.1",
67
66
  "graphql-mqtt-subscriptions": "^1.2.0",
68
67
  "graphql-redis-subscriptions": "^2.4.0",
69
- "graphql-subscriptions": "^1.2.1",
70
- "graphql-tag": "^2.12.5",
68
+ "graphql-subscriptions": "^2.0.0",
69
+ "graphql-tag": "^2.12.6",
71
70
  "graphql-upload": "^12.0.0",
72
71
  "haunted": "^4.8.2",
73
- "headroom.js": "^0.12.0",
74
72
  "html-webpack-plugin": "^4.3.0",
75
73
  "husky": "7.0.1",
76
74
  "imports-loader": "^3.0.0",
77
- "inquirer": "^8.1.2",
78
- "ioredis": "^4.27.6",
75
+ "inquirer": "^8.2.0",
76
+ "ioredis": "^4.28.0",
79
77
  "json5": "^2.2.0",
80
- "koa": "^2.13.1",
78
+ "koa": "^2.13.4",
81
79
  "koa-bodyparser": "^4.2.0",
82
- "koa-ejs-remote": "^1.1.6",
83
80
  "koa-ip": "^2.1.0",
84
81
  "koa-router": "^7.4.0",
85
82
  "koa-send": "^5.0.0",
86
83
  "koa-static": "^5.0.0",
87
84
  "koa-unless": "^1.0.7",
88
- "koa-webpack": "^5.1.0",
85
+ "koa-webpack": "^6.0.0",
89
86
  "koa2-connect-history-api-fallback": "^0.1.2",
90
- "lit-element": "^2.5.1",
87
+ "lit-element": "^3.0.1",
91
88
  "loader-utils": "^2.0.0",
92
89
  "lodash": "^4.17.15",
93
90
  "mkdirp": "^1.0.3",
@@ -102,14 +99,13 @@
102
99
  "redux": "^4.0.0",
103
100
  "redux-thunk": "^2.3.0",
104
101
  "regenerator-runtime": "^0.13.2",
105
- "require-json5": "^1.1.0",
106
102
  "reselect": "^4.0.0",
107
103
  "scrollbooster": "^3.0.2",
108
- "subscriptions-transport-ws": "^0.9.19",
104
+ "subscriptions-transport-ws": "^0.11.0",
109
105
  "sweetalert2": "^10.9.0",
110
106
  "swipe-listener": "^1.3.0",
111
107
  "type-graphql": "^1.1.1",
112
- "typeorm": "^0.2.34",
108
+ "typeorm": "^0.2.38",
113
109
  "web-animations-js": "^2.3.2",
114
110
  "web-push": "^3.4.5",
115
111
  "webfontloader": "^1.6.28"
@@ -124,5 +120,5 @@
124
120
  "resolutions": {
125
121
  "core-js": "^3.16.0"
126
122
  },
127
- "gitHead": "79a276f40a3229fbf08f439d772f2c183871adfa"
123
+ "gitHead": "371b38f377c7e647bbe38bf79571d861b1bbe6f8"
128
124
  }
package/server/pubsub.ts CHANGED
@@ -1,22 +1,14 @@
1
- import { config } from '@things-factory/env'
2
- const { middleware, host, port, options } = config.get('pubsub', {})
3
-
4
- import { PubSub } from 'graphql-subscriptions'
1
+ import { MQTTPubSub } from 'graphql-mqtt-subscriptions'
5
2
  import { RedisPubSub } from 'graphql-redis-subscriptions'
3
+ import { PubSub } from 'graphql-subscriptions'
6
4
  import Redis from 'ioredis'
7
-
8
5
  import { connect } from 'mqtt'
9
- import { MQTTPubSub } from 'graphql-mqtt-subscriptions'
10
6
 
11
- const debug = require('debug')('things-factory:shell')
7
+ import { config } from '@things-factory/env'
12
8
 
13
- // override publish because payload of redis publish is required string only.
14
- class MyRedisPubSub extends RedisPubSub {
15
- publish(trigger: string, payload: any): Promise<void> {
16
- debug('payload', payload)
17
- return super.publish(trigger, JSON.stringify(payload))
18
- }
19
- }
9
+ const { middleware, host, port, nodes, options } = config.get('pubsub', {})
10
+
11
+ const debug = require('debug')('things-factory:shell')
20
12
 
21
13
  let pubsub: any
22
14
 
@@ -39,12 +31,21 @@ switch (middleware) {
39
31
  },
40
32
  ...options
41
33
  }
42
- pubsub = new MyRedisPubSub({
34
+ pubsub = new RedisPubSub({
43
35
  publisher: new Redis(redisOption),
44
36
  subscriber: new Redis(redisOption)
45
37
  })
38
+ break
39
+ case 'redisCluster':
40
+ const cluster = new Redis.Cluster(nodes, options)
41
+ pubsub = new RedisPubSub({
42
+ publisher: cluster,
43
+ subscriber: cluster
44
+ })
45
+ break
46
46
  default:
47
47
  pubsub = new PubSub()
48
+ break
48
49
  }
49
50
 
50
51
  export { pubsub }
package/server/schema.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { buildSchema } from 'type-graphql'
2
- import { mergeSchemas } from '@graphql-tools/merge'
3
- import { deepMerge } from '@things-factory/utils'
1
+ import { loader, orderedModuleNames } from '@things-factory/env'
2
+
4
3
  import { GraphQLSchema } from 'graphql'
5
4
  import { GraphQLUpload } from 'graphql-upload'
6
-
7
- import { orderedModuleNames, loader } from '@things-factory/env'
5
+ import { buildSchema } from 'type-graphql'
6
+ import { deepMerge } from '@things-factory/utils'
7
+ import { mergeSchemas } from '@graphql-tools/schema'
8
8
 
9
9
  export async function schema() {
10
10
  const schemas = orderedModuleNames
@@ -1,27 +1,26 @@
1
1
  process.env.NODE_ENV = 'development'
2
2
  process.setMaxListeners(0)
3
3
 
4
- import Koa from 'koa'
5
- import ip from 'koa-ip'
6
- import cors from '@koa/cors'
7
- import koaStatic from 'koa-static'
8
- import koaBodyParser from 'koa-bodyparser'
9
- import { historyApiFallback } from 'koa2-connect-history-api-fallback'
10
-
11
- import koaWebpack from 'koa-webpack'
4
+ import { ConnectionContext, SubscriptionServer } from 'subscriptions-transport-ws'
5
+ import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
6
+ import { domainPrivateRouter, domainPublicRouter, globalPrivateRouter, globalPublicRouter } from './routers'
7
+ import { execute, subscribe } from 'graphql'
12
8
 
13
9
  import { ApolloServer } from 'apollo-server-koa'
14
- import { graphqlUploadKoa } from 'graphql-upload'
15
-
10
+ import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core'
11
+ import { GraphqlLocalClient } from './graphql-local-client'
12
+ import Koa from 'koa'
16
13
  import co from 'co'
17
14
  import compose from 'koa-compose'
18
-
19
- import { config, logger, orderedModuleNames, loader } from '@things-factory/env'
20
-
15
+ import cors from '@koa/cors'
16
+ import { createServer } from 'http'
21
17
  import { databaseInitializer } from './initializers/database'
22
- import { globalPublicRouter, globalPrivateRouter, domainPublicRouter, domainPrivateRouter } from './routers'
23
- import { GraphqlLocalClient } from './graphql-local-client'
24
-
18
+ import { graphqlUploadKoa } from 'graphql-upload'
19
+ import { historyApiFallback } from 'koa2-connect-history-api-fallback'
20
+ import ip from 'koa-ip'
21
+ import koaBodyParser from 'koa-bodyparser'
22
+ import koaStatic from 'koa-static'
23
+ import koaWebpack from 'koa-webpack'
25
24
  import { schema } from './schema'
26
25
 
27
26
  const debug = require('debug')('things-factory:shell:server-dev')
@@ -32,7 +31,7 @@ args.option('port', 'The port on which the app will be running', config.get('por
32
31
  args.option(
33
32
  'inspect',
34
33
  `The address on which the inspection will be running. Used in development mode only.
35
- This option is just to preventprevent termination for reasons of not recognizing the 'inspect' option.`,
34
+ This option is just to prevent termination for reasons of not recognizing the 'inspect' option.`,
36
35
  config.get('inspect', ':9229')
37
36
  )
38
37
 
@@ -91,13 +90,15 @@ const bootstrap = async () => {
91
90
 
92
91
  const builtSchema = await schema()
93
92
 
94
- const server = new ApolloServer({
95
- schema: builtSchema,
96
- uploads: false,
97
- subscriptions: {
98
- path: '/subscriptions',
99
- onConnect: async (connectionParams, webSocket, context) => {
100
- /* To maintain the same method as the http(s) request */
93
+ const httpServer = createServer(app.callback())
94
+
95
+ const subscriptionServer = SubscriptionServer.create(
96
+ {
97
+ schema: builtSchema,
98
+ // These are imported from `graphql`.
99
+ execute,
100
+ subscribe,
101
+ async onConnect(connectionParams: Object, webSocket: WebSocket, context: ConnectionContext) {
101
102
  var { request } = context
102
103
 
103
104
  var url = new URL((connectionParams['headers'] || connectionParams).referer)
@@ -121,6 +122,14 @@ const bootstrap = async () => {
121
122
  return koacontext
122
123
  }
123
124
  },
125
+ {
126
+ server: httpServer,
127
+ path: '/subscriptions'
128
+ }
129
+ )
130
+
131
+ const server = new ApolloServer({
132
+ schema: builtSchema,
124
133
  formatError: error => {
125
134
  logger.error(error)
126
135
  return error
@@ -129,20 +138,33 @@ const bootstrap = async () => {
129
138
  // logger.info('response %s', JSON.stringify(response, null, 2))
130
139
  return response
131
140
  },
132
- playground: {
133
- settings: {
134
- 'request.credentials': 'include'
135
- }
136
- },
137
141
  context: async ({ connection, ctx }) => {
138
142
  if (connection) {
139
143
  return connection.context
140
144
  } else {
141
145
  return ctx
142
146
  }
143
- }
147
+ },
148
+ plugins: [
149
+ ApolloServerPluginLandingPageGraphQLPlayground({
150
+ settings: {
151
+ 'request.credentials': 'same-origin'
152
+ }
153
+ }),
154
+ {
155
+ async serverWillStart() {
156
+ return {
157
+ async drainServer() {
158
+ subscriptionServer.close()
159
+ }
160
+ }
161
+ }
162
+ }
163
+ ]
144
164
  })
145
165
 
166
+ server.start()
167
+
146
168
  GraphqlLocalClient.init(builtSchema, app)
147
169
 
148
170
  orderedModuleNames.forEach(name => {
@@ -150,7 +172,7 @@ const bootstrap = async () => {
150
172
  initMiddlewares && initMiddlewares(app)
151
173
  })
152
174
 
153
- const render = require('koa-ejs-remote')
175
+ const render = require('@things-factory/ejs-remote')
154
176
  render(app, {
155
177
  root: '/views',
156
178
  host: `http://127.0.0.1:${PORT}`,
@@ -210,15 +232,12 @@ const bootstrap = async () => {
210
232
  })
211
233
  )
212
234
 
213
- /* httpServer */
214
- const httpServer = app.listen({ port: PORT }, () => {
235
+ httpServer.listen({ port: PORT }, () => {
215
236
  logger.info(`🚀 Server ready at http://0.0.0.0:${PORT}${server.graphqlPath}`)
216
- logger.info(`🚀 Subscriptions ready at ws://0.0.0.0:${PORT}${server.subscriptionsPath}`)
237
+ logger.info(`🚀 Subscriptions ready at ws://0.0.0.0:${PORT}${'/subscriptions'}`)
217
238
 
218
239
  process.emit('bootstrap-module-start' as any, { app, config, builtSchema, httpServer } as any)
219
240
  })
220
-
221
- server.installSubscriptionHandlers(httpServer)
222
241
  }
223
242
 
224
243
  bootstrap()
package/server/server.ts CHANGED
@@ -1,25 +1,24 @@
1
1
  process.env.NODE_ENV = 'production'
2
2
  process.setMaxListeners(0)
3
3
 
4
- import Koa from 'koa'
5
- import ip from 'koa-ip'
6
- import cors from '@koa/cors'
7
- import koaStatic from 'koa-static'
8
- import koaBodyParser from 'koa-bodyparser'
9
- import { historyApiFallback } from 'koa2-connect-history-api-fallback'
4
+ import { ConnectionContext, SubscriptionServer } from 'subscriptions-transport-ws'
5
+ import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
6
+ import { domainPrivateRouter, domainPublicRouter, globalPrivateRouter, globalPublicRouter } from './routers'
7
+ import { execute, subscribe } from 'graphql'
10
8
 
11
9
  import { ApolloServer } from 'apollo-server-koa'
12
- import { graphqlUploadKoa } from 'graphql-upload'
13
-
10
+ import { GraphqlLocalClient } from './graphql-local-client'
11
+ import Koa from 'koa'
14
12
  import co from 'co'
15
13
  import compose from 'koa-compose'
16
-
17
- import { config, logger, orderedModuleNames, loader } from '@things-factory/env'
18
-
14
+ import cors from '@koa/cors'
15
+ import { createServer } from 'http'
19
16
  import { databaseInitializer } from './initializers/database'
20
- import { globalPublicRouter, globalPrivateRouter, domainPublicRouter, domainPrivateRouter } from './routers'
21
- import { GraphqlLocalClient } from './graphql-local-client'
22
-
17
+ import { graphqlUploadKoa } from 'graphql-upload'
18
+ import { historyApiFallback } from 'koa2-connect-history-api-fallback'
19
+ import ip from 'koa-ip'
20
+ import koaBodyParser from 'koa-bodyparser'
21
+ import koaStatic from 'koa-static'
23
22
  import { schema } from './schema'
24
23
 
25
24
  const args = require('args')
@@ -77,12 +76,15 @@ const bootstrap = async () => {
77
76
 
78
77
  const builtSchema = await schema()
79
78
 
80
- const server = new ApolloServer({
81
- schema: builtSchema,
82
- uploads: false,
83
- subscriptions: {
84
- path: '/subscriptions',
85
- onConnect: async (connectionParams, webSocket, context) => {
79
+ const httpServer = createServer(app.callback())
80
+
81
+ const subscriptionServer = SubscriptionServer.create(
82
+ {
83
+ schema: builtSchema,
84
+ // These are imported from `graphql`.
85
+ execute,
86
+ subscribe,
87
+ async onConnect(connectionParams: Object, webSocket: WebSocket, context: ConnectionContext) {
86
88
  var { request } = context
87
89
 
88
90
  var url = new URL((connectionParams['headers'] || connectionParams).referer)
@@ -106,6 +108,14 @@ const bootstrap = async () => {
106
108
  return koacontext
107
109
  }
108
110
  },
111
+ {
112
+ server: httpServer,
113
+ path: '/subscriptions'
114
+ }
115
+ )
116
+
117
+ const server = new ApolloServer({
118
+ schema: builtSchema,
109
119
  formatError: error => {
110
120
  logger.error(error)
111
121
  return error
@@ -115,20 +125,28 @@ const bootstrap = async () => {
115
125
  return response
116
126
  },
117
127
  introspection: true,
118
- playground: {
119
- settings: {
120
- 'request.credentials': 'include'
121
- }
122
- },
123
128
  context: async ({ connection, ctx }) => {
124
129
  if (connection) {
125
130
  return connection.context
126
131
  } else {
127
132
  return ctx
128
133
  }
129
- }
134
+ },
135
+ plugins: [
136
+ {
137
+ async serverWillStart() {
138
+ return {
139
+ async drainServer() {
140
+ subscriptionServer.close()
141
+ }
142
+ }
143
+ }
144
+ }
145
+ ]
130
146
  })
131
147
 
148
+ await server.start()
149
+
132
150
  GraphqlLocalClient.init(builtSchema, app)
133
151
 
134
152
  orderedModuleNames.forEach(name => {
@@ -136,7 +154,7 @@ const bootstrap = async () => {
136
154
  initMiddlewares && initMiddlewares(app)
137
155
  })
138
156
 
139
- const render = require('koa-ejs-remote')
157
+ const render = require('@things-factory/ejs-remote')
140
158
  render(app, {
141
159
  root: '/views',
142
160
  host: `http://127.0.0.1:${PORT}`,
@@ -180,14 +198,12 @@ const bootstrap = async () => {
180
198
  })
181
199
  )
182
200
 
183
- const httpServer = app.listen({ port: PORT }, () => {
201
+ httpServer.listen({ port: PORT }, () => {
184
202
  logger.info(`🚀 Server ready at http://0.0.0.0:${PORT}${server.graphqlPath}`)
185
- logger.info(`🚀 Subscriptions ready at ws://0.0.0.0:${PORT}${server.subscriptionsPath}`)
203
+ logger.info(`🚀 Subscriptions ready at ws://0.0.0.0:${PORT}${'/subscriptions'}`)
186
204
 
187
205
  process.emit('bootstrap-module-start' as any, { app, config, builtSchema, httpServer } as any)
188
206
  })
189
-
190
- server.installSubscriptionHandlers(httpServer)
191
207
  }
192
208
 
193
209
  bootstrap()
@@ -28,7 +28,7 @@ export class Filter {
28
28
  operator: string
29
29
 
30
30
  @Field(type => ScalarAny)
31
- value: object
31
+ value: any
32
32
 
33
33
  @Field({ nullable: true })
34
34
  relation?: boolean
@@ -1,8 +1,35 @@
1
1
  import { GraphQLScalarType, Kind } from 'graphql'
2
2
 
3
+ function parseObject(ast) {
4
+ const value = Object.create(null)
5
+ ast.fields.forEach(field => {
6
+ value[field.name.value] = parseAst(field.value)
7
+ })
8
+ return value
9
+ }
10
+
11
+ function parseAst(ast) {
12
+ switch (ast.kind) {
13
+ case Kind.INT:
14
+ return parseInt(ast.value)
15
+ case Kind.FLOAT:
16
+ return parseFloat(ast.value)
17
+ case Kind.BOOLEAN:
18
+ return ast.value
19
+ case Kind.STRING:
20
+ return ast.value
21
+ case Kind.LIST:
22
+ return ast.values.map(parseAst)
23
+ case Kind.OBJECT:
24
+ return parseObject(ast)
25
+ default:
26
+ return null
27
+ }
28
+ }
29
+
3
30
  export const ScalarAny = new GraphQLScalarType({
4
31
  name: 'Any',
5
- description: 'Any Scalar type (String, Boolean, Int, Float)',
32
+ description: 'Any Scalar type (String, Boolean, Int, Float, Object, List)',
6
33
  serialize(value) {
7
34
  // Implement your own behavior here by setting the 'result' variable
8
35
  return value
@@ -12,17 +39,6 @@ export const ScalarAny = new GraphQLScalarType({
12
39
  return value
13
40
  },
14
41
  parseLiteral(ast) {
15
- switch (ast.kind) {
16
- case Kind.INT:
17
- return parseInt(ast.value)
18
- case Kind.FLOAT:
19
- return parseFloat(ast.value)
20
- case Kind.BOOLEAN:
21
- return ast.value
22
- case Kind.STRING:
23
- return ast.value
24
- case Kind.LIST:
25
- return ast.values.map((v: any) => v.value)
26
- }
42
+ return parseAst(ast)
27
43
  }
28
44
  })
@@ -1,19 +1,21 @@
1
- import { Resolver, Query, Mutation, Args, Arg, Ctx, Directive } from 'type-graphql'
1
+ import { Arg, Args, Ctx, Directive, Mutation, Query, Resolver } from 'type-graphql'
2
2
  import { getRepository, In, Repository } from 'typeorm'
3
- import { ListParam } from '../common-types/list-param'
3
+
4
4
  import { slugger } from '@things-factory/utils'
5
- import { Domain } from './domain'
6
- import { DomainPatch, DomainList } from './domain-types'
5
+
7
6
  import { buildQuery } from '../../utils/list-query-builder'
7
+ import { ListParam } from '../common-types/list-param'
8
+ import { Domain } from './domain'
9
+ import { DomainList, DomainPatch } from './domain-types'
8
10
 
9
11
  @Resolver(Domain)
10
12
  export class DomainResolver {
11
13
  @Directive('@privilege(category: "system", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
12
14
  @Query(returns => Domain, { description: 'To fetch domain' })
13
- async domain(@Arg('name') name: string): Promise<Domain> {
15
+ async domain(@Arg('id') id: string): Promise<Domain> {
14
16
  const repository = getRepository(Domain)
15
17
 
16
- return await repository.findOne({ name })
18
+ return await repository.findOne({ id })
17
19
  }
18
20
 
19
21
  @Directive('@privilege(category: "system", privilege: "query", superUserGranted: true)')