@operato/scene-graphql 8.0.0-beta.1 → 8.0.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.
@@ -1,185 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
-
5
- import {
6
- ApolloClient,
7
- DefaultOptions,
8
- from,
9
- HttpLink,
10
- HttpOptions,
11
- InMemoryCache,
12
- NormalizedCacheObject,
13
- ServerParseError
14
- } from '@apollo/client/core'
15
- import { ErrorLink, onError } from '@apollo/client/link/error'
16
- import { Component, ComponentNature, DataSource, RectPath, Shape } from '@hatiolab/things-scene'
17
-
18
- const defaultOptions: DefaultOptions = {
19
- watchQuery: {
20
- fetchPolicy: 'no-cache',
21
- errorPolicy: 'ignore'
22
- },
23
- query: {
24
- fetchPolicy: 'no-cache', //'network-only'
25
- errorPolicy: 'all'
26
- },
27
- mutate: {
28
- errorPolicy: 'all'
29
- }
30
- }
31
-
32
- const ERROR_HANDLER: ErrorLink.ErrorHandler = ({ operation, graphQLErrors, networkError }) => {
33
- if (graphQLErrors) {
34
- document.dispatchEvent(
35
- new CustomEvent('notify', {
36
- detail: {
37
- level: 'error',
38
- message: graphQLErrors[0].message,
39
- ex: graphQLErrors
40
- }
41
- })
42
- )
43
- }
44
-
45
- if (networkError) {
46
- /* networkError가 ServerParseError 이거나 ServerError 인 경우에만 statusCode를 갖는다. */
47
- switch ((networkError as ServerParseError).statusCode) {
48
- case undefined /* in case this error is not a server side error */:
49
- document.dispatchEvent(
50
- new CustomEvent('notify', {
51
- detail: {
52
- level: 'error',
53
- message: networkError.message,
54
- ex: networkError
55
- }
56
- })
57
- )
58
- break
59
-
60
- case 401:
61
- /* 401 에러가 리턴되면, 인증이 필요하다는 메시지를 dispatch 한다. 이 auth 모듈 등에서 이 메시지를 받아서 signin 프로세스를 진행할 수 있다. */
62
- document.dispatchEvent(new CustomEvent('auth-required'))
63
- break
64
-
65
- case 403:
66
- /* 403 에러가 리턴되면, 도메인 정보가 필요하다는 메시지를 dispatch 한다. 이 auth 모듈 등에서 이 메시지를 받아서 domain-register 프로세스 등을 진행할 수 있다. */
67
- document.dispatchEvent(new CustomEvent('domain-required'))
68
- break
69
-
70
- default:
71
- var { name, response, statusCode, bodyText, message } = networkError as ServerParseError
72
- if (name == 'ServerParseError') {
73
- message = `[ ${statusCode || ''} : ${response.statusText} ] ${bodyText}`
74
- } else {
75
- /* in case this error is instanceof ServerError */
76
- message = `[ ${statusCode || ''} : ${response.statusText} ] ${message}`
77
- }
78
-
79
- document.dispatchEvent(
80
- new CustomEvent('notify', {
81
- detail: {
82
- level: 'error',
83
- message,
84
- ex: networkError
85
- }
86
- })
87
- )
88
- }
89
- }
90
- }
91
-
92
- const NATURE: ComponentNature = {
93
- mutable: false,
94
- resizable: true,
95
- rotatable: true,
96
- properties: [
97
- {
98
- type: 'string',
99
- label: 'endpoint',
100
- name: 'endpoint'
101
- }
102
- ],
103
- help: 'scene/component/graphql'
104
- }
105
-
106
- export default class GraphqlClient extends DataSource(RectPath(Shape)) {
107
- private static _image: HTMLImageElement
108
- private _client?: ApolloClient<NormalizedCacheObject>
109
-
110
- static get image() {
111
- if (!GraphqlClient._image) {
112
- GraphqlClient._image = new Image()
113
- GraphqlClient._image.src = new URL('../icons/symbol-graphql-client.png', import.meta.url).href
114
- }
115
-
116
- return GraphqlClient._image
117
- }
118
-
119
- ready() {
120
- super.ready()
121
-
122
- this.init()
123
- }
124
-
125
- init() {
126
- var { endpoint } = this.state
127
-
128
- if (!endpoint) {
129
- console.warn('endpoint not defined')
130
- return
131
- }
132
-
133
- var cache = new InMemoryCache()
134
- const httpOptions: HttpOptions = {
135
- uri: endpoint,
136
- credentials: 'include'
137
- }
138
-
139
- const client = new ApolloClient({
140
- defaultOptions,
141
- cache,
142
- link: from([onError(ERROR_HANDLER), new HttpLink(httpOptions)])
143
- })
144
-
145
- this._client = client
146
- }
147
-
148
- get client(): ApolloClient<NormalizedCacheObject> | undefined {
149
- return this._client
150
- }
151
-
152
- dispose() {
153
- super.dispose()
154
-
155
- try {
156
- if (this._client) {
157
- this._client.stop()
158
- }
159
- } catch (e) {
160
- console.error(e)
161
- }
162
- delete this._client
163
- }
164
-
165
- render(context: CanvasRenderingContext2D) {
166
- /*
167
- * TODO role이 publisher 인지 subscriber 인지에 따라서 구분할 수 있는 표시를 추가할 것.
168
- */
169
-
170
- var { left, top, width, height } = this.bounds
171
-
172
- context.beginPath()
173
- this.drawImage(context, GraphqlClient.image, left, top, width, height)
174
- }
175
-
176
- onchangeData(data: any, before: any) {
177
- super.onchangeData(data, before)
178
- }
179
-
180
- get nature() {
181
- return NATURE
182
- }
183
- }
184
-
185
- Component.register('graphql-client', GraphqlClient)
@@ -1,234 +0,0 @@
1
- import 'ses'
2
- import gql from 'graphql-tag'
3
-
4
- import { ApolloClient, NormalizedCacheObject } from '@apollo/client/core'
5
- import { Component, ComponentNature, DataSource, Properties, RectPath, Shape } from '@hatiolab/things-scene'
6
- import { buildArgs, client as localClient } from '@operato/graphql'
7
-
8
- import GraphqlClient from './graphql-client'
9
-
10
- const NATURE: ComponentNature = {
11
- mutable: false,
12
- resizable: true,
13
- rotatable: true,
14
- properties: [
15
- {
16
- type: 'id-input',
17
- label: 'client',
18
- name: 'client',
19
- placeholder: 'leave blank to use origin server',
20
- property: {
21
- component: 'graphql-client' // component의 type (null or undefined이면 모든 컴포넌트)
22
- }
23
- },
24
- {
25
- type: 'number',
26
- label: 'period',
27
- name: 'period',
28
- placeholder: 'SECONDS'
29
- },
30
- {
31
- type: 'graphql',
32
- label: 'query',
33
- name: 'query'
34
- },
35
- {
36
- type: 'checkbox',
37
- label: 'auto-start',
38
- name: 'autoStart'
39
- }
40
- ],
41
- 'value-property': 'value',
42
- help: 'scene/component/graphql'
43
- }
44
-
45
- class GraphQLQuery extends DataSource(RectPath(Shape)) {
46
- private _repeatTimer?: number
47
- private _isStarted: boolean = false
48
-
49
- get nature() {
50
- return NATURE
51
- }
52
-
53
- onchange(after: Properties, before: Properties) {
54
- if ('value' in after) {
55
- if (after.value) this.requestData()
56
- }
57
- }
58
-
59
- get period() {
60
- return this.state.period * 1000
61
- }
62
-
63
- set period(period) {
64
- this.setState('period', period)
65
- this._initGraphqlQuery()
66
- }
67
-
68
- get repeatTimer() {
69
- return this._repeatTimer
70
- }
71
-
72
- set repeatTimer(repeatTimer) {
73
- this._stopRepeater()
74
- this._repeatTimer = repeatTimer
75
- }
76
-
77
- get autoStart() {
78
- return this.state.autoStart
79
- }
80
-
81
- set autoStart(autoStart) {
82
- this.setState('autoStart', autoStart)
83
- }
84
-
85
- get query() {
86
- var _query = this.state.query
87
- var objToVal = (exp: any) => {
88
- if (typeof exp === 'string') return exp
89
- else return JSON.stringify(exp)
90
- }
91
- var changedQuery: string | undefined = (Component.buildSubstitutor(_query, this, objToVal) || (() => _query))()
92
- try {
93
- changedQuery = changedQuery!.replace(/\(.*\)/gi, params => {
94
- const c = new Compartment({ console })
95
- let paramObject = c.evaluate(`({${params.slice(1, -1)}})`)
96
- return '(' + buildArgs(paramObject) + ')'
97
- })
98
- } catch (e) {
99
- console.log(e)
100
- }
101
-
102
- return changedQuery
103
- }
104
-
105
- get source() {
106
- return this.getState('source')
107
- }
108
-
109
- set source(source) {
110
- this.setState('source', source)
111
- }
112
-
113
- dispose() {
114
- super.dispose()
115
- this._stopRepeater()
116
- }
117
-
118
- ready() {
119
- super.ready()
120
- if (this.autoStart) {
121
- this._initGraphqlQuery()
122
- }
123
- }
124
-
125
- _initGraphqlQuery() {
126
- if (!this.app.isViewMode) return
127
-
128
- this._stopRepeater()
129
- this._startRepeater()
130
- }
131
-
132
- _stopRepeater() {
133
- if (this.repeatTimer !== undefined) {
134
- clearTimeout(this._repeatTimer!)
135
- delete this._repeatTimer
136
- }
137
-
138
- this._isStarted = false
139
- }
140
-
141
- _startRepeater() {
142
- this._isStarted = true
143
-
144
- // requestAnimationFrame 이 호출되지 않을 때는 requestData 호출도 하지 않도록 함.
145
- var _ = () => {
146
- if (!this._isStarted) {
147
- return
148
- }
149
- this.requestData()
150
- if (!Number.isNaN(this.period) && this.period > 0) {
151
- this._repeatTimer = setTimeout(() => {
152
- requestAnimationFrame(_)
153
- }, this.period)
154
- }
155
- }
156
- requestAnimationFrame(_)
157
- }
158
-
159
- async requestData() {
160
- if (!this.app.isViewMode) return
161
- var { client } = this.state
162
- var query = this.query
163
- var variables = this.value
164
-
165
- if (query) {
166
- const graphqlClient: ApolloClient<NormalizedCacheObject> =
167
- (client && (this.root.findById(client) as GraphqlClient)?.client) || localClient
168
-
169
- var response
170
-
171
- if (typeof variables === 'object') {
172
- response = await graphqlClient.query({
173
- query: gql`
174
- ${query}
175
- `,
176
- variables: variables
177
- })
178
- } else {
179
- response = await graphqlClient.query({
180
- query: gql`
181
- ${query}
182
- `,
183
- errorPolicy: 'all'
184
- })
185
- }
186
-
187
- console.log('response', response)
188
- this.data = response
189
- }
190
- }
191
- }
192
-
193
- export class Query extends GraphQLQuery {
194
- private static _image: HTMLImageElement
195
-
196
- static get image() {
197
- if (!Query._image) {
198
- Query._image = new Image()
199
- Query._image.src = new URL('../icons/symbol-graphql-query.png', import.meta.url).href
200
- }
201
-
202
- return Query._image
203
- }
204
-
205
- render(context: CanvasRenderingContext2D) {
206
- var { left, top, width, height } = this.bounds
207
-
208
- context.beginPath()
209
- this.drawImage(context, Query.image, left, top, width, height)
210
- }
211
- }
212
-
213
- export class Mutation extends GraphQLQuery {
214
- private static _image: HTMLImageElement
215
-
216
- static get image() {
217
- if (!Mutation._image) {
218
- Mutation._image = new Image()
219
- Mutation._image.src = new URL('../icons/symbol-graphql-mutation.png', import.meta.url).href
220
- }
221
-
222
- return Mutation._image
223
- }
224
-
225
- render(context: CanvasRenderingContext2D) {
226
- var { left, top, width, height } = this.bounds
227
-
228
- context.beginPath()
229
- this.drawImage(context, Mutation.image, left, top, width, height)
230
- }
231
- }
232
-
233
- Component.register('graphql-query', Query)
234
- Component.register('graphql-mutation', Mutation)
@@ -1,92 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
-
5
- import { gql } from 'graphql-tag'
6
-
7
- import { Component, ComponentNature, DataSource, RectPath, Shape } from '@hatiolab/things-scene'
8
- import { subscribe } from '@operato/graphql'
9
-
10
- const NATURE: ComponentNature = {
11
- mutable: false,
12
- resizable: true,
13
- rotatable: true,
14
- properties: [
15
- {
16
- /* origin의 subscription 만을 허용하므로, 엔드포인트 속성은 무시한다. */
17
- type: 'string',
18
- label: 'endpoint',
19
- name: 'endpoint'
20
- },
21
- {
22
- type: 'graphql',
23
- label: 'query',
24
- name: 'query'
25
- }
26
- ],
27
- help: 'scene/component/graphql-subscription'
28
- }
29
-
30
- export default class GraphqlSubscription extends DataSource(RectPath(Shape)) {
31
- private static _image: HTMLImageElement
32
- private unsubscribe?: () => void
33
-
34
- static get image() {
35
- if (!GraphqlSubscription._image) {
36
- GraphqlSubscription._image = new Image()
37
- GraphqlSubscription._image.src = new URL('../icons/symbol-graphql-subscription.png', import.meta.url).href
38
- }
39
-
40
- return GraphqlSubscription._image
41
- }
42
-
43
- dispose() {
44
- if (this.unsubscribe) {
45
- this.unsubscribe()
46
- }
47
-
48
- super.dispose()
49
- }
50
-
51
- render(context: CanvasRenderingContext2D) {
52
- var { left, top, width, height } = this.bounds
53
-
54
- context.beginPath()
55
- this.drawImage(context, GraphqlSubscription.image, left, top, width, height)
56
- }
57
-
58
- ready() {
59
- super.ready()
60
-
61
- if (this.app.isViewMode) {
62
- this.requestData()
63
- }
64
- }
65
-
66
- get nature() {
67
- return NATURE
68
- }
69
-
70
- async requestData() {
71
- var { query } = this.state
72
-
73
- const { unsubscribe } = await subscribe(
74
- {
75
- query: gql`
76
- ${query}
77
- `
78
- },
79
- {
80
- next: ({ data }: { data: any }) => {
81
- if (data) {
82
- this.data = data
83
- }
84
- }
85
- }
86
- )
87
-
88
- this.unsubscribe = unsubscribe
89
- }
90
- }
91
-
92
- Component.register('graphql-subscription', GraphqlSubscription)
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- import Client from './graphql-client'
2
- import { Mutation, Query } from './graphql-query-and-mutation'
3
- import Subscription from './graphql-subscription'
4
-
5
- export default [Client, Query, Mutation, Subscription]
@@ -1,19 +0,0 @@
1
- const icon = new URL('../../icons/icon-graphql-client.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'graphql-client',
5
- description: 'graphql-client',
6
- group: 'dataSource',
7
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
8
- icon,
9
- model: {
10
- type: 'graphql-client',
11
- left: 10,
12
- top: 10,
13
- width: 100,
14
- height: 100,
15
- fillStyle: 'cyan',
16
- strokeStyle: 'darkgray',
17
- endpoint: '/'
18
- }
19
- }
@@ -1,23 +0,0 @@
1
- const icon = new URL('../../icons/icon-graphql-mutation.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'graphql-mutation',
5
- description: 'graphql-mutation',
6
- group: 'dataSource',
7
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
8
- icon,
9
- model: {
10
- type: 'graphql-mutation',
11
- left: 10,
12
- top: 10,
13
- width: 100,
14
- height: 100,
15
- autoStart: false,
16
- period: 0,
17
- query: `mutation {
18
- resolverName ( patches:[] ) {
19
- id
20
- }
21
- }`
22
- }
23
- }
@@ -1,31 +0,0 @@
1
- const icon = new URL('../../icons/icon-graphql-query.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'graphql-query',
5
- description: 'graphql-query',
6
- group: 'dataSource',
7
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
8
- icon,
9
- model: {
10
- type: 'graphql-query',
11
- left: 10,
12
- top: 10,
13
- width: 100,
14
- height: 100,
15
- autoStart: true,
16
- period: 0,
17
- query: `query {
18
- boards {
19
- items {
20
- id
21
- name
22
- description
23
- thumbnail
24
- createdAt
25
- updatedAt
26
- }
27
- total
28
- }
29
- }`
30
- }
31
- }
@@ -1,26 +0,0 @@
1
- const icon = new URL('../../icons/icon-graphql-subscription.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'graphql-subscription',
5
- description: 'graphql-subscription',
6
- group: 'dataSource',
7
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
8
- icon,
9
- model: {
10
- type: 'graphql-subscription',
11
- left: 10,
12
- top: 10,
13
- width: 100,
14
- height: 100,
15
- lineWidth: 1,
16
- endpoint: 'ws://localhost:3000/subscriptions',
17
- requestType: 'mutation',
18
- query: `subscription {
19
- systemRebooted {
20
- name
21
- version
22
- description
23
- }
24
- }`
25
- }
26
- }
@@ -1,6 +0,0 @@
1
- import graphqlClient from './graphql-client'
2
- import graphqlMutation from './graphql-mutation'
3
- import graphqlQuery from './graphql-query'
4
- import graphqlSubscription from './graphql-subscription'
5
-
6
- export default [graphqlClient, graphqlQuery, graphqlMutation, graphqlSubscription]
package/tsconfig.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2018",
4
- "module": "esnext",
5
- "moduleResolution": "node",
6
- "noEmitOnError": true,
7
- "lib": ["es2019", "dom"],
8
- "strict": true,
9
- "esModuleInterop": false,
10
- "allowJs": true,
11
- "allowSyntheticDefaultImports": true,
12
- "experimentalDecorators": true,
13
- "importHelpers": true,
14
- "outDir": "dist",
15
- "sourceMap": true,
16
- "inlineSources": true,
17
- "rootDir": "src",
18
- "declaration": true,
19
- "incremental": true,
20
- "skipLibCheck": true,
21
- "types": []
22
- },
23
- "include": ["**/*.ts", "*.d.ts"]
24
- }