@orion-js/graphql 2.2.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.
- package/LICENSE +21 -0
- package/lib/buildSchema/getArgs/getField.js +61 -0
- package/lib/buildSchema/getArgs/index.js +34 -0
- package/lib/buildSchema/getMutation.js +30 -0
- package/lib/buildSchema/getQuery.js +30 -0
- package/lib/buildSchema/getResolvers/index.js +65 -0
- package/lib/buildSchema/getSubscription.js +27 -0
- package/lib/buildSchema/getSubscriptions/index.js +42 -0
- package/lib/buildSchema/getType/BigIntScalar.js +53 -0
- package/lib/buildSchema/getType/DateScalar.js +19 -0
- package/lib/buildSchema/getType/JSONScalar.js +58 -0
- package/lib/buildSchema/getType/getScalar.js +45 -0
- package/lib/buildSchema/getType/getTypeAsResolver.js +42 -0
- package/lib/buildSchema/getType/index.js +85 -0
- package/lib/buildSchema/index.js +29 -0
- package/lib/errorHandler.js +31 -0
- package/lib/getApolloOptions/formatError.js +22 -0
- package/lib/getApolloOptions/index.js +27 -0
- package/lib/index.js +70 -0
- package/lib/pubsub.js +19 -0
- package/lib/resolversSchemas/ResolverParams.js +53 -0
- package/lib/resolversSchemas/getBasicResultQuery.js +28 -0
- package/lib/resolversSchemas/getField.js +54 -0
- package/lib/resolversSchemas/getField.test.js +30 -0
- package/lib/resolversSchemas/index.js +15 -0
- package/lib/resolversSchemas/params.js +46 -0
- package/lib/resolversSchemas/serializeSchema.js +23 -0
- package/lib/resolversSchemas/serializeSchema.test.js +30 -0
- package/lib/startGraphQL.js +73 -0
- package/lib/startGraphiQL.js +211 -0
- package/lib/startWebsocket.js +61 -0
- package/lib/subscription/getChannelName.js +21 -0
- package/lib/subscription/index.js +52 -0
- package/package.json +41 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = _default;
|
|
7
|
+
|
|
8
|
+
var _app = require("@orion-js/app");
|
|
9
|
+
|
|
10
|
+
// Ensures string values are safe to be used within a <script> tag.
|
|
11
|
+
// TODO: I don't think that's the right escape function
|
|
12
|
+
function safeSerialize(data) {
|
|
13
|
+
return data ? JSON.stringify(data).replace(/\//g, '\\/') : null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const getHTML = function (apolloOptions, options, data) {
|
|
17
|
+
// Current latest version of GraphiQL.
|
|
18
|
+
const GRAPHIQL_VERSION = '0.11.11';
|
|
19
|
+
const {
|
|
20
|
+
endpointURL,
|
|
21
|
+
subscriptionsEndpoint
|
|
22
|
+
} = apolloOptions;
|
|
23
|
+
const queryString = data.query;
|
|
24
|
+
const variablesString = data.variables ? JSON.stringify(data.variables, null, 2) : null;
|
|
25
|
+
const operationName = data.operationName;
|
|
26
|
+
const useSubs = !!options.subscriptions;
|
|
27
|
+
return `
|
|
28
|
+
<!DOCTYPE html>
|
|
29
|
+
<html>
|
|
30
|
+
<head>
|
|
31
|
+
<meta charset="utf-8" />
|
|
32
|
+
<title>GraphiQL</title>
|
|
33
|
+
<meta name="robots" content="noindex" />
|
|
34
|
+
<style>
|
|
35
|
+
html, body {
|
|
36
|
+
height: 100%;
|
|
37
|
+
margin: 0;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
width: 100%;
|
|
40
|
+
}
|
|
41
|
+
</style>
|
|
42
|
+
<link href="//unpkg.com/graphiql@${GRAPHIQL_VERSION}/graphiql.css" rel="stylesheet" />
|
|
43
|
+
<script src="//unpkg.com/react@15.6.1/dist/react.min.js"></script>
|
|
44
|
+
<script src="//unpkg.com/jssha@2.3.1/src/sha512.js"></script>
|
|
45
|
+
<script src="//unpkg.com/react-dom@15.6.1/dist/react-dom.min.js"></script>
|
|
46
|
+
<script src="//unpkg.com/graphiql@${GRAPHIQL_VERSION}/graphiql.min.js"></script>
|
|
47
|
+
<script src="//cdn.jsdelivr.net/fetch/2.0.1/fetch.min.js"></script>
|
|
48
|
+
${useSubs ? `<script src="//unpkg.com/subscriptions-transport-ws@0.5.4/browser/client.js"></script>
|
|
49
|
+
<script src="//unpkg.com/graphiql-subscriptions-fetcher@0.0.2/browser/client.js"></script>` : ''}
|
|
50
|
+
</head>
|
|
51
|
+
<body>
|
|
52
|
+
<script>
|
|
53
|
+
// Collect the URL parameters
|
|
54
|
+
var parameters = {};
|
|
55
|
+
window.location.search.substr(1).split('&').forEach(function (entry) {
|
|
56
|
+
var eq = entry.indexOf('=');
|
|
57
|
+
if (eq >= 0) {
|
|
58
|
+
parameters[decodeURIComponent(entry.slice(0, eq))] =
|
|
59
|
+
decodeURIComponent(entry.slice(eq + 1));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// Produce a Location query string from a parameter object.
|
|
63
|
+
function locationQuery(params, location) {
|
|
64
|
+
return (location ? location: '') + '?' + Object.keys(params).map(function (key) {
|
|
65
|
+
return encodeURIComponent(key) + '=' +
|
|
66
|
+
encodeURIComponent(params[key]);
|
|
67
|
+
}).join('&');
|
|
68
|
+
}
|
|
69
|
+
// Derive a fetch URL from the current URL, sans the GraphQL parameters.
|
|
70
|
+
var graphqlParamNames = {
|
|
71
|
+
query: true,
|
|
72
|
+
variables: true,
|
|
73
|
+
operationName: true
|
|
74
|
+
};
|
|
75
|
+
var otherParams = {};
|
|
76
|
+
for (var k in parameters) {
|
|
77
|
+
if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
|
|
78
|
+
otherParams[k] = parameters[k];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// We don't use safe-serialize for location, because it's not client input.
|
|
82
|
+
var fetchURL = '${endpointURL}'
|
|
83
|
+
// Defines a GraphQL fetcher using the fetch API.
|
|
84
|
+
function graphQLHttpFetcher(graphQLParams) {
|
|
85
|
+
const body = JSON.stringify(graphQLParams)
|
|
86
|
+
const headers = {
|
|
87
|
+
'Accept': 'application/json',
|
|
88
|
+
'Content-Type': 'application/json',
|
|
89
|
+
}
|
|
90
|
+
const publicKey = localStorage.getItem('GraphiQL:publicKey')
|
|
91
|
+
const secretKey = localStorage.getItem('GraphiQL:secretKey')
|
|
92
|
+
if (publicKey && secretKey) {
|
|
93
|
+
const nonce = new Date().getTime()
|
|
94
|
+
const shaObj = new jsSHA('SHA-512', 'TEXT')
|
|
95
|
+
shaObj.setHMACKey(secretKey, 'TEXT')
|
|
96
|
+
shaObj.update(nonce + body)
|
|
97
|
+
const signature = shaObj.getHMAC('HEX')
|
|
98
|
+
headers['X-ORION-NONCE'] = nonce
|
|
99
|
+
headers['X-ORION-PUBLICKEY'] = publicKey
|
|
100
|
+
headers['X-ORION-SIGNATURE'] = signature
|
|
101
|
+
}
|
|
102
|
+
return fetch(fetchURL, {
|
|
103
|
+
method: 'post',
|
|
104
|
+
headers,
|
|
105
|
+
body,
|
|
106
|
+
credentials: 'same-origin',
|
|
107
|
+
}).then(function (response) {
|
|
108
|
+
return response.text();
|
|
109
|
+
}).then(function (responseBody) {
|
|
110
|
+
try {
|
|
111
|
+
const json = JSON.parse(responseBody);
|
|
112
|
+
if (json.data && json.data.loginWithPassword) {
|
|
113
|
+
const publicKey = json.data.loginWithPassword.publicKey
|
|
114
|
+
const secretKey = json.data.loginWithPassword.secretKey
|
|
115
|
+
if (publicKey && secretKey) {
|
|
116
|
+
localStorage.setItem('GraphiQL:publicKey', publicKey)
|
|
117
|
+
localStorage.setItem('GraphiQL:secretKey', secretKey)
|
|
118
|
+
alert('Session saved in localStorage')
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (json.error && json.error === 'AuthError') {
|
|
122
|
+
localStorage.setItem('GraphiQL:publicKey', '')
|
|
123
|
+
localStorage.setItem('GraphiQL:secretKey', '')
|
|
124
|
+
alert('Logged out after receiving AuthError')
|
|
125
|
+
}
|
|
126
|
+
return json
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return responseBody;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
${useSubs ? `
|
|
133
|
+
let params = {}
|
|
134
|
+
const publicKey = localStorage.getItem('GraphiQL:publicKey')
|
|
135
|
+
const secretKey = localStorage.getItem('GraphiQL:secretKey')
|
|
136
|
+
if (publicKey && secretKey) {
|
|
137
|
+
const nonce = new Date().getTime() + 500
|
|
138
|
+
const shaObj = new jsSHA('SHA-512', 'TEXT')
|
|
139
|
+
shaObj.setHMACKey(secretKey, 'TEXT')
|
|
140
|
+
shaObj.update(nonce + 'websockethandshake')
|
|
141
|
+
const signature = shaObj.getHMAC('HEX')
|
|
142
|
+
params = {
|
|
143
|
+
nonce,
|
|
144
|
+
publicKey,
|
|
145
|
+
signature
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'
|
|
150
|
+
let subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient(protocol + window.location.host + '${subscriptionsEndpoint}', {
|
|
151
|
+
reconnect: true,
|
|
152
|
+
connectionParams: params
|
|
153
|
+
});
|
|
154
|
+
let myCustomFetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLHttpFetcher);
|
|
155
|
+
var fetcher = myCustomFetcher
|
|
156
|
+
` : `
|
|
157
|
+
var fetcher = graphQLHttpFetcher
|
|
158
|
+
`}
|
|
159
|
+
|
|
160
|
+
// When the query and variables string is edited, update the URL bar so
|
|
161
|
+
// that it can be easily shared.
|
|
162
|
+
function onEditQuery(newQuery) {
|
|
163
|
+
parameters.query = newQuery;
|
|
164
|
+
updateURL();
|
|
165
|
+
}
|
|
166
|
+
function onEditVariables(newVariables) {
|
|
167
|
+
parameters.variables = newVariables;
|
|
168
|
+
updateURL();
|
|
169
|
+
}
|
|
170
|
+
function onEditOperationName(newOperationName) {
|
|
171
|
+
parameters.operationName = newOperationName;
|
|
172
|
+
updateURL();
|
|
173
|
+
}
|
|
174
|
+
function updateURL() {
|
|
175
|
+
var cleanParams = Object.keys(parameters).filter(function(v) {
|
|
176
|
+
return parameters[v];
|
|
177
|
+
}).reduce(function(old, v) {
|
|
178
|
+
old[v] = parameters[v];
|
|
179
|
+
return old;
|
|
180
|
+
}, {});
|
|
181
|
+
history.replaceState(null, null, locationQuery(cleanParams) + window.location.hash);
|
|
182
|
+
}
|
|
183
|
+
// Render <GraphiQL /> into the body.
|
|
184
|
+
ReactDOM.render(
|
|
185
|
+
React.createElement(GraphiQL, {
|
|
186
|
+
fetcher: fetcher,
|
|
187
|
+
onEditQuery: onEditQuery,
|
|
188
|
+
onEditVariables: onEditVariables,
|
|
189
|
+
onEditOperationName: onEditOperationName,
|
|
190
|
+
query: ${safeSerialize(queryString)},
|
|
191
|
+
response: null,
|
|
192
|
+
variables: ${safeSerialize(variablesString)},
|
|
193
|
+
operationName: ${safeSerialize(operationName)},
|
|
194
|
+
}),
|
|
195
|
+
document.body
|
|
196
|
+
);
|
|
197
|
+
</script>
|
|
198
|
+
</body>
|
|
199
|
+
</html>`;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
function _default(apolloOptions, options) {
|
|
203
|
+
if (options.useGraphiql) {
|
|
204
|
+
(0, _app.route)('/graphiql', async function ({
|
|
205
|
+
query,
|
|
206
|
+
request
|
|
207
|
+
}) {
|
|
208
|
+
return getHTML(apolloOptions, options, query, request);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = _default;
|
|
7
|
+
|
|
8
|
+
var _app = require("@orion-js/app");
|
|
9
|
+
|
|
10
|
+
var _graphql = require("graphql");
|
|
11
|
+
|
|
12
|
+
var _subscriptionsTransportWs = require("subscriptions-transport-ws");
|
|
13
|
+
|
|
14
|
+
var _graphqlSubscriptions = require("graphql-subscriptions");
|
|
15
|
+
|
|
16
|
+
var _pubsub = require("./pubsub");
|
|
17
|
+
|
|
18
|
+
function _default({
|
|
19
|
+
schema
|
|
20
|
+
}, options) {
|
|
21
|
+
(0, _pubsub.setPubsub)(options.pubsub || new _graphqlSubscriptions.PubSub());
|
|
22
|
+
const server = (0, _app.getServer)();
|
|
23
|
+
|
|
24
|
+
if (!server) {
|
|
25
|
+
throw new Error('Error starting GraphQL WebSocket. You must start http server before starting GraphQL WebSocket');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const path = '/subscriptions';
|
|
29
|
+
const subServer = new _subscriptionsTransportWs.SubscriptionServer({
|
|
30
|
+
execute: _graphql.execute,
|
|
31
|
+
subscribe: _graphql.subscribe,
|
|
32
|
+
schema,
|
|
33
|
+
|
|
34
|
+
async onConnect(connectionParams, webSocket) {
|
|
35
|
+
try {
|
|
36
|
+
const params = {
|
|
37
|
+
headers: {
|
|
38
|
+
'x-orion-nonce': connectionParams.nonce,
|
|
39
|
+
'x-orion-publickey': connectionParams.publicKey,
|
|
40
|
+
'x-orion-signature': connectionParams.signature,
|
|
41
|
+
'x-orion-jwt': connectionParams.jwt
|
|
42
|
+
},
|
|
43
|
+
getBody: () => 'websockethandshake',
|
|
44
|
+
nonceName: 'graphqlsubs'
|
|
45
|
+
};
|
|
46
|
+
const viewer = await (0, _app.getViewer)(params);
|
|
47
|
+
return viewer;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const viewer = await (0, _app.getViewer)();
|
|
50
|
+
return viewer;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
onDisconnect() {}
|
|
55
|
+
|
|
56
|
+
}, {
|
|
57
|
+
server,
|
|
58
|
+
path
|
|
59
|
+
});
|
|
60
|
+
return subServer;
|
|
61
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = _default;
|
|
9
|
+
|
|
10
|
+
var _crypto = _interopRequireDefault(require("crypto"));
|
|
11
|
+
|
|
12
|
+
var _deepSortObject = _interopRequireDefault(require("deep-sort-object"));
|
|
13
|
+
|
|
14
|
+
function _default(name, params, viewer) {
|
|
15
|
+
const json = JSON.stringify((0, _deepSortObject.default)(params));
|
|
16
|
+
|
|
17
|
+
const hash = _crypto.default.createHash('sha1').update(json).digest('base64');
|
|
18
|
+
|
|
19
|
+
const channelName = `${name}_${hash}`;
|
|
20
|
+
return channelName;
|
|
21
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = _default;
|
|
9
|
+
|
|
10
|
+
var _pubsub = require("../pubsub");
|
|
11
|
+
|
|
12
|
+
var _getChannelName = _interopRequireDefault(require("./getChannelName"));
|
|
13
|
+
|
|
14
|
+
var _app = require("@orion-js/app");
|
|
15
|
+
|
|
16
|
+
function _default(options) {
|
|
17
|
+
const {
|
|
18
|
+
params,
|
|
19
|
+
returns,
|
|
20
|
+
checkPermission,
|
|
21
|
+
...otherOptions
|
|
22
|
+
} = options; // the publish function
|
|
23
|
+
|
|
24
|
+
const subscription = function publish(params, data) {
|
|
25
|
+
const pubsub = (0, _pubsub.getPubsub)();
|
|
26
|
+
const channelName = (0, _getChannelName.default)(subscription.key, params);
|
|
27
|
+
pubsub.publish(channelName, {
|
|
28
|
+
[subscription.key]: data
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
subscription.subscribe = async function (callParams, viewer) {
|
|
33
|
+
const pubsub = (0, _pubsub.getPubsub)();
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await (0, _app.checkResolverPermissions)({
|
|
37
|
+
callParams,
|
|
38
|
+
viewer,
|
|
39
|
+
checkPermission,
|
|
40
|
+
otherOptions
|
|
41
|
+
});
|
|
42
|
+
const channelName = (0, _getChannelName.default)(subscription.key, callParams);
|
|
43
|
+
return pubsub.asyncIterator(channelName);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
return pubsub.asyncIterator('unauthorized');
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
subscription.params = params;
|
|
50
|
+
subscription.returns = returns;
|
|
51
|
+
return subscription;
|
|
52
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orion-js/graphql",
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"main": "lib/index.js",
|
|
5
|
+
"author": "nicolaslopezj",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "rm -rf ./lib && babel ./src --out-dir ./lib",
|
|
9
|
+
"prepare": "yarn run build",
|
|
10
|
+
"watch": "rm -rf ./lib && babel ./src --watch --out-dir ./lib",
|
|
11
|
+
"test": "jest"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@orion-js/schema": "^2.1.0",
|
|
15
|
+
"apollo-server-core": "^2.16.1",
|
|
16
|
+
"apollo-server-micro": "^2.16.1",
|
|
17
|
+
"deep-sort-object": "^1.0.2",
|
|
18
|
+
"graphql": "^14.4.2",
|
|
19
|
+
"graphql-iso-date": "^3.6.1",
|
|
20
|
+
"graphql-subscriptions": "^1.1.0",
|
|
21
|
+
"lodash": "^4.17.19",
|
|
22
|
+
"subscriptions-transport-ws": "^0.9.17"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@babel/cli": "^7.10.5",
|
|
26
|
+
"@babel/core": "^7.11.1",
|
|
27
|
+
"@babel/plugin-transform-runtime": "^7.11.0",
|
|
28
|
+
"@babel/preset-env": "^7.11.0",
|
|
29
|
+
"@babel/runtime": "^7.11.2",
|
|
30
|
+
"@orion-js/app": "^2.2.0",
|
|
31
|
+
"babel-jest": "^26.2.2",
|
|
32
|
+
"jest": "^26.2.2"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@orion-js/app": "*"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"gitHead": "d50a4ec7ffc9ee6a5443a4b7b85e80527f988294"
|
|
41
|
+
}
|