postgraphile 4.12.11 → 5.0.0-0.3

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 (134) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/LICENSE.md +15 -20
  3. package/README.md +20 -171
  4. package/dist/cli-run.d.ts +3 -0
  5. package/dist/cli-run.d.ts.map +1 -0
  6. package/dist/cli-run.js +7 -0
  7. package/dist/cli-run.js.map +1 -0
  8. package/dist/cli.d.ts +21 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +180 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/index.d.ts +14 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +88 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/plugins/PgV4BehaviorPlugin.d.ts +11 -0
  17. package/dist/plugins/PgV4BehaviorPlugin.d.ts.map +1 -0
  18. package/dist/plugins/PgV4BehaviorPlugin.js +73 -0
  19. package/dist/plugins/PgV4BehaviorPlugin.js.map +1 -0
  20. package/dist/plugins/PgV4InflectionPlugin.d.ts +11 -0
  21. package/dist/plugins/PgV4InflectionPlugin.d.ts.map +1 -0
  22. package/dist/plugins/PgV4InflectionPlugin.js +91 -0
  23. package/dist/plugins/PgV4InflectionPlugin.js.map +1 -0
  24. package/dist/plugins/PgV4NoIgnoreIndexes.d.ts +2 -0
  25. package/dist/plugins/PgV4NoIgnoreIndexes.d.ts.map +1 -0
  26. package/dist/plugins/PgV4NoIgnoreIndexes.js +72 -0
  27. package/dist/plugins/PgV4NoIgnoreIndexes.js.map +1 -0
  28. package/dist/plugins/PgV4SmartTagsPlugin.d.ts +11 -0
  29. package/dist/plugins/PgV4SmartTagsPlugin.d.ts.map +1 -0
  30. package/dist/plugins/PgV4SmartTagsPlugin.js +190 -0
  31. package/dist/plugins/PgV4SmartTagsPlugin.js.map +1 -0
  32. package/dist/presets/amber.d.ts +5 -0
  33. package/dist/presets/amber.d.ts.map +1 -0
  34. package/dist/presets/amber.js +38 -0
  35. package/dist/presets/amber.js.map +1 -0
  36. package/dist/presets/v4.d.ts +34 -0
  37. package/dist/presets/v4.d.ts.map +1 -0
  38. package/dist/presets/v4.js +142 -0
  39. package/dist/presets/v4.js.map +1 -0
  40. package/dist/schema.d.ts +34 -0
  41. package/dist/schema.d.ts.map +1 -0
  42. package/dist/schema.js +82 -0
  43. package/dist/schema.js.map +1 -0
  44. package/package.json +77 -154
  45. package/build/assets/favicon.ico.d.ts +0 -3
  46. package/build/assets/favicon.ico.js +0 -6
  47. package/build/assets/graphiql.html.d.ts +0 -2
  48. package/build/assets/graphiql.html.js +0 -6
  49. package/build/index.d.ts +0 -8
  50. package/build/index.js +0 -34
  51. package/build/interfaces.d.ts +0 -162
  52. package/build/interfaces.js +0 -3
  53. package/build/plugins.d.ts +0 -3
  54. package/build/plugins.js +0 -53
  55. package/build/postgraphile/cli.d.ts +0 -3
  56. package/build/postgraphile/cli.js +0 -541
  57. package/build/postgraphile/extendedFormatError.d.ts +0 -9
  58. package/build/postgraphile/extendedFormatError.js +0 -51
  59. package/build/postgraphile/http/createPostGraphileHttpRequestHandler.d.ts +0 -11
  60. package/build/postgraphile/http/createPostGraphileHttpRequestHandler.js +0 -974
  61. package/build/postgraphile/http/frameworks.d.ts +0 -110
  62. package/build/postgraphile/http/frameworks.js +0 -258
  63. package/build/postgraphile/http/liveSubscribe.d.ts +0 -22
  64. package/build/postgraphile/http/liveSubscribe.js +0 -89
  65. package/build/postgraphile/http/mapAsyncIterator.d.ts +0 -15
  66. package/build/postgraphile/http/mapAsyncIterator.js +0 -71
  67. package/build/postgraphile/http/setupServerSentEvents.d.ts +0 -9
  68. package/build/postgraphile/http/setupServerSentEvents.js +0 -51
  69. package/build/postgraphile/http/subscriptions.d.ts +0 -7
  70. package/build/postgraphile/http/subscriptions.js +0 -410
  71. package/build/postgraphile/index.d.ts +0 -5
  72. package/build/postgraphile/index.js +0 -14
  73. package/build/postgraphile/pluginHook.d.ts +0 -104
  74. package/build/postgraphile/pluginHook.js +0 -100
  75. package/build/postgraphile/postgraphile.d.ts +0 -20
  76. package/build/postgraphile/postgraphile.js +0 -332
  77. package/build/postgraphile/postgraphilerc.d.ts +0 -2
  78. package/build/postgraphile/postgraphilerc.js +0 -16
  79. package/build/postgraphile/schema/exportPostGraphileSchema.d.ts +0 -6
  80. package/build/postgraphile/schema/exportPostGraphileSchema.js +0 -45
  81. package/build/postgraphile/shutdownActions.d.ts +0 -41
  82. package/build/postgraphile/shutdownActions.js +0 -87
  83. package/build/postgraphile/withPostGraphileContext.d.ts +0 -55
  84. package/build/postgraphile/withPostGraphileContext.js +0 -457
  85. package/build/postgres/inventory/pgClientFromContext.d.ts +0 -8
  86. package/build/postgres/inventory/pgClientFromContext.js +0 -21
  87. package/build-turbo/assets/favicon.ico.d.ts +0 -3
  88. package/build-turbo/assets/favicon.ico.js +0 -6
  89. package/build-turbo/assets/graphiql.html.d.ts +0 -2
  90. package/build-turbo/assets/graphiql.html.js +0 -6
  91. package/build-turbo/index.d.ts +0 -8
  92. package/build-turbo/index.js +0 -34
  93. package/build-turbo/interfaces.d.ts +0 -162
  94. package/build-turbo/interfaces.js +0 -3
  95. package/build-turbo/plugins.d.ts +0 -3
  96. package/build-turbo/plugins.js +0 -53
  97. package/build-turbo/postgraphile/cli.d.ts +0 -3
  98. package/build-turbo/postgraphile/cli.js +0 -572
  99. package/build-turbo/postgraphile/extendedFormatError.d.ts +0 -9
  100. package/build-turbo/postgraphile/extendedFormatError.js +0 -61
  101. package/build-turbo/postgraphile/http/createPostGraphileHttpRequestHandler.d.ts +0 -11
  102. package/build-turbo/postgraphile/http/createPostGraphileHttpRequestHandler.js +0 -982
  103. package/build-turbo/postgraphile/http/frameworks.d.ts +0 -110
  104. package/build-turbo/postgraphile/http/frameworks.js +0 -258
  105. package/build-turbo/postgraphile/http/liveSubscribe.d.ts +0 -22
  106. package/build-turbo/postgraphile/http/liveSubscribe.js +0 -89
  107. package/build-turbo/postgraphile/http/mapAsyncIterator.d.ts +0 -15
  108. package/build-turbo/postgraphile/http/mapAsyncIterator.js +0 -71
  109. package/build-turbo/postgraphile/http/setupServerSentEvents.d.ts +0 -9
  110. package/build-turbo/postgraphile/http/setupServerSentEvents.js +0 -51
  111. package/build-turbo/postgraphile/http/subscriptions.d.ts +0 -7
  112. package/build-turbo/postgraphile/http/subscriptions.js +0 -409
  113. package/build-turbo/postgraphile/index.d.ts +0 -5
  114. package/build-turbo/postgraphile/index.js +0 -14
  115. package/build-turbo/postgraphile/pluginHook.d.ts +0 -104
  116. package/build-turbo/postgraphile/pluginHook.js +0 -100
  117. package/build-turbo/postgraphile/postgraphile.d.ts +0 -20
  118. package/build-turbo/postgraphile/postgraphile.js +0 -337
  119. package/build-turbo/postgraphile/postgraphilerc.d.ts +0 -2
  120. package/build-turbo/postgraphile/postgraphilerc.js +0 -16
  121. package/build-turbo/postgraphile/schema/exportPostGraphileSchema.d.ts +0 -6
  122. package/build-turbo/postgraphile/schema/exportPostGraphileSchema.js +0 -45
  123. package/build-turbo/postgraphile/shutdownActions.d.ts +0 -41
  124. package/build-turbo/postgraphile/shutdownActions.js +0 -87
  125. package/build-turbo/postgraphile/withPostGraphileContext.d.ts +0 -55
  126. package/build-turbo/postgraphile/withPostGraphileContext.js +0 -466
  127. package/build-turbo/postgres/inventory/pgClientFromContext.d.ts +0 -8
  128. package/build-turbo/postgres/inventory/pgClientFromContext.js +0 -21
  129. package/cli.js +0 -6
  130. package/index.js +0 -5
  131. package/isTurbo.js +0 -11
  132. package/plugins.d.ts +0 -1
  133. package/plugins.js +0 -5
  134. package/sponsors.json +0 -150
@@ -1,982 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmpty = void 0;
4
- /* eslint-disable @typescript-eslint/no-explicit-any,require-atomic-updates */
5
- const graphql_1 = require("graphql");
6
- const extendedFormatError_1 = require("../extendedFormatError");
7
- const pluginHook_1 = require("../pluginHook");
8
- const setupServerSentEvents_1 = require("./setupServerSentEvents");
9
- const withPostGraphileContext_1 = require("../withPostGraphileContext");
10
- const lru_1 = require("@graphile/lru");
11
- const chalk_1 = require("chalk");
12
- const Debugger = require("debug"); // tslint:disable-line variable-name
13
- const httpError = require("http-errors");
14
- const parseUrl = require("parseurl");
15
- const finalHandler = require("finalhandler");
16
- const bodyParser = require("body-parser");
17
- const crypto = require("crypto");
18
- const isKoaApp = (a, b) => a.req && a.res && typeof b === 'function';
19
- const CACHE_MULTIPLIER = 100000;
20
- const ALLOW_EXPLAIN_PLACEHOLDER = '__SHOULD_ALLOW_EXPLAIN__';
21
- const noop = () => {
22
- /* noop */
23
- };
24
- const { createHash } = crypto;
25
- /**
26
- * The favicon file in `Buffer` format. We can send a `Buffer` directly to the
27
- * client.
28
- *
29
- * @type {Buffer}
30
- */
31
- const favicon_ico_1 = require("../../assets/favicon.ico");
32
- /**
33
- * The GraphiQL HTML file as a string. We need it to be a string, because we
34
- * will use a regular expression to replace some variables.
35
- */
36
- const graphiql_html_1 = require("../../assets/graphiql.html");
37
- const subscriptions_1 = require("./subscriptions");
38
- const frameworks_1 = require("./frameworks");
39
- /**
40
- * When writing JSON to the browser, we need to be careful that it doesn't get
41
- * interpretted as HTML.
42
- */
43
- const JS_ESCAPE_LOOKUP = {
44
- '<': '\\u003c',
45
- '>': '\\u003e',
46
- '/': '\\u002f',
47
- '\u2028': '\\u2028',
48
- '\u2029': '\\u2029',
49
- };
50
- function safeJSONStringify(obj) {
51
- return JSON.stringify(obj).replace(/[<>/\u2028\u2029]/g, chr => JS_ESCAPE_LOOKUP[chr]);
52
- }
53
- /**
54
- * When people webpack us up, e.g. for lambda, if they don't want GraphiQL then
55
- * they can seriously reduce bundle size by omitting the assets.
56
- */
57
- const shouldOmitAssets = process.env.POSTGRAPHILE_OMIT_ASSETS === '1';
58
- // Used by `createPostGraphileHttpRequestHandler`
59
- let lastString;
60
- let lastHash;
61
- const calculateQueryHash = (queryString) => {
62
- if (queryString !== lastString) {
63
- lastString = queryString;
64
- lastHash = createHash('sha1').update(queryString).digest('base64');
65
- }
66
- return lastHash;
67
- };
68
- // Fast way of checking if an object is empty,
69
- // faster than `Object.keys(value).length === 0`.
70
- // NOTE: we don't need a `hasOwnProperty` call here because isEmpty is called
71
- // with an `Object.create(null)` object, so it has no no-own properties.
72
- /* tslint:disable forin */
73
- function isEmpty(value) {
74
- for (const _key in value) {
75
- return false;
76
- }
77
- return true;
78
- }
79
- exports.isEmpty = isEmpty;
80
- /* tslint:enable forin */
81
- const isPostGraphileDevelopmentMode = process.env.POSTGRAPHILE_ENV === 'development';
82
- const debugGraphql = Debugger('postgraphile:graphql');
83
- const debugRequest = Debugger('postgraphile:request');
84
- /**
85
- * We need to be able to share the withPostGraphileContext logic between HTTP
86
- * and websockets
87
- */
88
- function withPostGraphileContextFromReqResGenerator(options) {
89
- const { pgSettings: pgSettingsGenerator, allowExplain: allowExplainGenerator, jwtSecret, jwtPublicKey, additionalGraphQLContextFromRequest, } = options;
90
- return async (req, res, moreOptions, fn) => {
91
- const jwtVerificationSecret = jwtPublicKey || jwtSecret;
92
- const jwtToken = jwtVerificationSecret ? getJwtToken(req) : null;
93
- const additionalContext = typeof additionalGraphQLContextFromRequest === 'function'
94
- ? await additionalGraphQLContextFromRequest(req, res)
95
- : null;
96
- const pgSettings = typeof pgSettingsGenerator === 'function'
97
- ? await pgSettingsGenerator(req)
98
- : pgSettingsGenerator;
99
- const allowExplain = typeof allowExplainGenerator === 'function'
100
- ? await allowExplainGenerator(req)
101
- : allowExplainGenerator;
102
- return withPostGraphileContext_1.default({
103
- ...options,
104
- jwtToken,
105
- pgSettings,
106
- explain: allowExplain && req.headers['x-postgraphile-explain'] === 'on',
107
- ...moreOptions,
108
- }, context => {
109
- const graphqlContext = additionalContext
110
- ? { ...additionalContext, ...context }
111
- : context;
112
- return fn(graphqlContext);
113
- });
114
- };
115
- }
116
- /**
117
- * Creates a GraphQL request handler that can support many different `http` frameworks, including:
118
- *
119
- * - Native Node.js `http`.
120
- * - `connect`.
121
- * - `express`.
122
- * - `koa` (2.0).
123
- */
124
- function createPostGraphileHttpRequestHandler(options) {
125
- const MEGABYTE = 1024 * 1024;
126
- const subscriptions = !!options.subscriptions;
127
- const { getGqlSchema, pgPool, pgSettings, pgDefaultRole, shutdownActions, queryCacheMaxSize = 50 * MEGABYTE, extendedErrors, showErrorStack, watchPg, disableQueryLog, enableQueryBatching, websockets = options.subscriptions || options.live ? ['v0', 'v1'] : [], } = options;
128
- const live = !!options.live;
129
- const enhanceGraphiql = options.enhanceGraphiql === false ? false : !!options.enhanceGraphiql || subscriptions || live;
130
- const enableCors = !!options.enableCors || isPostGraphileDevelopmentMode;
131
- const graphiql = options.graphiql === true;
132
- if (options['absoluteRoutes']) {
133
- throw new Error('Sorry - the `absoluteRoutes` setting has been replaced with `externalUrlBase` which solves the issue in a cleaner way. Please update your settings. Thank you for testing a PostGraphile pre-release 🙏');
134
- }
135
- // Using let because we might override it on the first request.
136
- let externalUrlBase = options.externalUrlBase;
137
- if (externalUrlBase && externalUrlBase.endsWith('/')) {
138
- throw new Error('externalUrlBase must not end with a slash (`/`)');
139
- }
140
- // Validate websockets argument
141
- if (
142
- // must be array
143
- !Array.isArray(websockets) ||
144
- // empty array = 'none'
145
- (websockets.length &&
146
- // array can only hold the versions
147
- websockets.some(ver => !['v0', 'v1'].includes(ver)))) {
148
- throw new Error(`Invalid value for \`websockets\` option: '${websockets}'`);
149
- }
150
- const pluginHook = pluginHook_1.pluginHookFromOptions(options);
151
- const origGraphiqlHtml = pluginHook('postgraphile:graphiql:html', graphiql_html_1.default, { options });
152
- if (pgDefaultRole && typeof pgSettings === 'function') {
153
- throw new Error('pgDefaultRole cannot be combined with pgSettings(req) - please remove pgDefaultRole and instead always return a `role` key from pgSettings(req).');
154
- }
155
- if (pgDefaultRole &&
156
- pgSettings &&
157
- typeof pgSettings === 'object' &&
158
- Object.keys(pgSettings)
159
- .map(s => s.toLowerCase())
160
- .includes('role')) {
161
- throw new Error('pgDefaultRole cannot be combined with pgSettings.role - please use one or the other.');
162
- }
163
- if (graphiql && shouldOmitAssets) {
164
- throw new Error('Cannot enable GraphiQL when POSTGRAPHILE_OMIT_ASSETS is set');
165
- }
166
- // Gets the route names for our GraphQL endpoint, and our GraphiQL endpoint.
167
- const graphqlRoute = options.graphqlRoute || '/graphql';
168
- const graphiqlRoute = options.graphiqlRoute || '/graphiql';
169
- // Set the request credential behavior in graphiql.
170
- const graphiqlCredentials = options.graphiqlCredentials || 'same-origin';
171
- const eventStreamRoute = options.eventStreamRoute || `${graphqlRoute.replace(/\/+$/, '')}/stream`;
172
- const externalGraphqlRoute = options.externalGraphqlRoute;
173
- const externalEventStreamRoute = options.externalEventStreamRoute ||
174
- (externalGraphqlRoute && !options.eventStreamRoute
175
- ? `${externalGraphqlRoute.replace(/\/+$/, '')}/stream`
176
- : undefined);
177
- // Throw an error of the GraphQL and GraphiQL routes are the same.
178
- if (graphqlRoute === graphiqlRoute)
179
- throw new Error(`Cannot use the same route, '${graphqlRoute}', for both GraphQL and GraphiQL. Please use different routes.`);
180
- // Formats an error using the default GraphQL `formatError` function, and
181
- // custom formatting using some other options.
182
- const formatError = (error) => {
183
- // Get the appropriate formatted error object, including any extended error
184
- // fields if the user wants them.
185
- const formattedError = extendedErrors && extendedErrors.length
186
- ? extendedFormatError_1.extendedFormatError(error, extendedErrors)
187
- : graphql_1.formatError(error);
188
- // If the user wants to see the error’s stack, let’s add it to the
189
- // formatted error.
190
- if (showErrorStack)
191
- formattedError['stack'] =
192
- error.stack != null && showErrorStack === 'json' ? error.stack.split('\n') : error.stack;
193
- return formattedError;
194
- };
195
- const DEFAULT_HANDLE_ERRORS = (errors) => errors.map(formatError);
196
- const handleErrors = options.handleErrors || DEFAULT_HANDLE_ERRORS;
197
- // Define a list of middlewares that will get run before our request handler.
198
- // Note though that none of these middlewares will intercept a request (i.e.
199
- // not call `next`). Middlewares that handle a request like favicon
200
- // middleware will result in a promise that never resolves, and we don’t
201
- // want that.
202
- const bodyParserMiddlewares = [
203
- // Parse JSON bodies.
204
- bodyParser.json({ limit: options.bodySizeLimit }),
205
- // Parse URL encoded bodies (forms).
206
- bodyParser.urlencoded({ extended: false, limit: options.bodySizeLimit }),
207
- // Parse `application/graphql` content type bodies as text.
208
- bodyParser.text({ type: 'application/graphql', limit: options.bodySizeLimit }),
209
- ];
210
- // We'll turn this into one function now so it can be better JIT optimised
211
- const bodyParserMiddlewaresComposed = bodyParserMiddlewares.reduce((parent, fn) => {
212
- return (req, res, next) => {
213
- parent(req, res, error => {
214
- if (error) {
215
- return next(error);
216
- }
217
- fn(req, res, next);
218
- });
219
- };
220
- }, (_req, _res, next) => next());
221
- // And we really want that function to be await-able
222
- const parseBody = (req, res) => new Promise((resolve, reject) => {
223
- bodyParserMiddlewaresComposed(req,
224
- // Note: middleware here doesn't actually use the response, but we pass
225
- // the underlying value so types match up.
226
- res.getNodeServerResponse(), (error) => {
227
- if (error) {
228
- reject(error);
229
- }
230
- else {
231
- resolve();
232
- }
233
- });
234
- });
235
- // We only need to calculate the graphiql HTML once; but we need to receive the first request to do so.
236
- let graphiqlHtml;
237
- const withPostGraphileContextFromReqRes = withPostGraphileContextFromReqResGenerator(options);
238
- const staticValidationRules = pluginHook('postgraphile:validationRules:static', graphql_1.specifiedRules, {
239
- options,
240
- });
241
- const cacheSize = Math.ceil(queryCacheMaxSize / CACHE_MULTIPLIER);
242
- // Do not create an LRU for cache size < 2 because @graphile/lru will baulk.
243
- const cacheEnabled = cacheSize >= 2;
244
- const queryCache = cacheEnabled ? new lru_1.default({ maxLength: cacheSize }) : null;
245
- let lastGqlSchema;
246
- const parseQuery = (gqlSchema, queryString) => {
247
- if (gqlSchema !== lastGqlSchema) {
248
- if (queryCache) {
249
- queryCache.reset();
250
- }
251
- lastGqlSchema = gqlSchema;
252
- }
253
- // Only cache queries that are less than 100kB, we don't want DOS attacks
254
- // attempting to exhaust our memory.
255
- const canCache = cacheEnabled && queryString.length < 100000;
256
- const hash = canCache ? calculateQueryHash(queryString) : null;
257
- const result = canCache ? queryCache.get(hash) : null;
258
- if (result) {
259
- return result;
260
- }
261
- else {
262
- const source = new graphql_1.Source(queryString, 'GraphQL Http Request');
263
- let queryDocumentAst;
264
- // Catch an errors while parsing so that we can set the `statusCode` to
265
- // 400. Otherwise we don’t need to parse this way.
266
- try {
267
- queryDocumentAst = graphql_1.parse(source);
268
- }
269
- catch (error) {
270
- error.statusCode = 400;
271
- throw error;
272
- }
273
- if (debugRequest.enabled)
274
- debugRequest('GraphQL query is parsed.');
275
- // Validate our GraphQL query using given rules.
276
- const validationErrors = graphql_1.validate(gqlSchema, queryDocumentAst, staticValidationRules);
277
- const cacheResult = {
278
- queryDocumentAst,
279
- validationErrors,
280
- length: queryString.length,
281
- };
282
- if (canCache) {
283
- queryCache.set(hash, cacheResult);
284
- }
285
- return cacheResult;
286
- }
287
- };
288
- let firstRequestHandler = req => {
289
- // Never be called again
290
- firstRequestHandler = null;
291
- let graphqlRouteForWs = graphqlRoute;
292
- const { pathname = '' } = parseUrl(req) || {};
293
- const { pathname: originalPathname = '' } = parseUrl.original(req) || {};
294
- if (originalPathname !== pathname && originalPathname.endsWith(pathname)) {
295
- const base = originalPathname.slice(0, originalPathname.length - pathname.length);
296
- // Our websocket GraphQL route must be at a different place
297
- graphqlRouteForWs = base + graphqlRouteForWs;
298
- if (externalUrlBase == null) {
299
- // User hasn't specified externalUrlBase; let's try and guess it
300
- // We were mounted on a subpath (e.g. `app.use('/path/to', postgraphile(...))`).
301
- // Figure out our externalUrlBase for ourselves.
302
- externalUrlBase = base;
303
- }
304
- }
305
- // Make sure we have a string, at least
306
- externalUrlBase = externalUrlBase || '';
307
- // Takes the original GraphiQL HTML file and replaces the default config object.
308
- graphiqlHtml = origGraphiqlHtml
309
- ? origGraphiqlHtml.replace(/<\/head>/, ` <script>window.POSTGRAPHILE_CONFIG=${safeJSONStringify({
310
- graphqlUrl: externalGraphqlRoute || `${externalUrlBase}${graphqlRoute}`,
311
- streamUrl: watchPg
312
- ? externalEventStreamRoute || `${externalUrlBase}${eventStreamRoute}`
313
- : null,
314
- enhanceGraphiql,
315
- // if 'v1' websockets are included, use the v1 client always
316
- websockets: !websockets.length ? 'none' : websockets.includes('v1') ? 'v1' : 'v0',
317
- allowExplain: typeof options.allowExplain === 'function'
318
- ? ALLOW_EXPLAIN_PLACEHOLDER
319
- : !!options.allowExplain,
320
- credentials: graphiqlCredentials,
321
- })};</script>\n </head>`)
322
- : null;
323
- if (websockets.length) {
324
- const server = req && req.connection && req.connection['server'];
325
- if (!server) {
326
- // tslint:disable-next-line no-console
327
- console.warn("Failed to find server to add websocket listener to, you'll need to call `enhanceHttpServerWithWebSockets` manually");
328
- }
329
- else {
330
- // Relying on this means that a normal request must come in before an
331
- // upgrade attempt. It's better to call it manually.
332
- subscriptions_1.enhanceHttpServerWithWebSockets(server, middleware, {
333
- graphqlRoute: graphqlRouteForWs,
334
- });
335
- }
336
- }
337
- };
338
- /*
339
- * If we're not in watch mode, then avoid the cost of `await`ing the schema
340
- * on every tick by having it available once it was generated.
341
- */
342
- let theOneAndOnlyGraphQLSchema = null;
343
- if (!watchPg) {
344
- getGqlSchema()
345
- .then(schema => {
346
- theOneAndOnlyGraphQLSchema = schema;
347
- })
348
- .catch(noop);
349
- }
350
- function neverReject(middlewareName, middleware) {
351
- return async (res) => {
352
- try {
353
- await middleware(res);
354
- }
355
- catch (e) {
356
- console.error(`An unexpected error occurred whilst processing '${middlewareName}'; this indicates a bug. The connection will be terminated.`);
357
- console.error(e);
358
- try {
359
- // At least terminate the connection
360
- res.statusCode = 500;
361
- res.end();
362
- }
363
- catch (e) {
364
- /*NOOP*/
365
- }
366
- }
367
- };
368
- }
369
- /**
370
- * The actual request handler. It’s an async function so it will return a
371
- * promise when complete. If the function doesn’t handle anything, it calls
372
- * `next` to let the next middleware try and handle it. If the function
373
- * throws an error, it's up to the wrapping middleware (imaginatively named
374
- * `middleware`, below) to handle the error. Frameworks like Koa have
375
- * middlewares reject a promise on error, whereas Express requires you pass
376
- * the error to the `next(err)` function.
377
- */
378
- const requestHandler = async (responseHandler, next) => {
379
- const res = responseHandler;
380
- const incomingReq = res.getNodeServerRequest();
381
- const nodeRes = res.getNodeServerResponse();
382
- // You can use this hook either to modify the incoming request or to tell
383
- // PostGraphile not to handle the request further (return null). NOTE: if
384
- // you return `null` from this hook then you are also responsible for
385
- // calling `next()` (should that be required).
386
- const req = pluginHook('postgraphile:http:handler', incomingReq, {
387
- options,
388
- res: nodeRes,
389
- next,
390
- });
391
- if (req == null) {
392
- return;
393
- }
394
- const { pathname = '' } = parseUrl(req) || {};
395
- // Certain things depend on externalUrlBase, which we guess if the user
396
- // doesn't supply it, so we calculate them on the first request. After
397
- // first request, this function becomes a NOOP
398
- if (firstRequestHandler)
399
- firstRequestHandler(req);
400
- // ======================================================================
401
- // GraphQL Watch Stream
402
- // ======================================================================
403
- if (watchPg) {
404
- // Setup an event stream so we can broadcast events to graphiql, etc.
405
- if (pathname === eventStreamRoute || pathname === '/_postgraphile/stream') {
406
- return eventStreamRouteHandler(res);
407
- }
408
- }
409
- const isGraphqlRoute = pathname === graphqlRoute;
410
- // ========================================================================
411
- // Serve GraphiQL and Related Assets
412
- // ========================================================================
413
- if (!shouldOmitAssets && graphiql && !isGraphqlRoute) {
414
- // ======================================================================
415
- // Favicon
416
- // ======================================================================
417
- // If this is the favicon path and it has not yet been handled, let us
418
- // serve our GraphQL favicon.
419
- if (pathname === '/favicon.ico') {
420
- return faviconRouteHandler(res);
421
- }
422
- // ======================================================================
423
- // GraphiQL HTML
424
- // ======================================================================
425
- // If this is the GraphiQL route, show GraphiQL and stop execution.
426
- if (pathname === graphiqlRoute) {
427
- // If we are developing PostGraphile, instead just redirect.
428
- if (isPostGraphileDevelopmentMode) {
429
- res.statusCode = 302;
430
- res.setHeader('Location', 'http://localhost:5783');
431
- res.end();
432
- return;
433
- }
434
- return graphiqlRouteHandler(res);
435
- }
436
- }
437
- if (isGraphqlRoute) {
438
- return graphqlRouteHandler(res);
439
- }
440
- else {
441
- // This request wasn't for us.
442
- return next();
443
- }
444
- };
445
- const eventStreamRouteHandler = neverReject('eventStreamRouteHandler', async function eventStreamRouteHandler(res) {
446
- try {
447
- // You can use this hook either to modify the incoming request or to tell
448
- // PostGraphile not to handle the request further (return null). NOTE: if
449
- // you return `null` from this hook then you are also responsible for
450
- // terminating the request however your framework handles that (e.g.
451
- // `res.send(...)` or `next()`).
452
- const req = pluginHook('postgraphile:http:eventStreamRouteHandler', res.getNodeServerRequest(), { options, response: res });
453
- if (req == null) {
454
- return;
455
- }
456
- // Add our CORS headers to be good web citizens (there are perf
457
- // implications though so be careful!)
458
- //
459
- // Always enable CORS when developing PostGraphile because GraphiQL will be
460
- // on port 5783.
461
- if (enableCors)
462
- addCORSHeaders(res);
463
- if (req.headers.accept !== 'text/event-stream') {
464
- res.statusCode = 405;
465
- res.end();
466
- return;
467
- }
468
- setupServerSentEvents_1.default(res, options);
469
- }
470
- catch (e) {
471
- console.error('Unexpected error occurred in eventStreamRouteHandler');
472
- console.error(e);
473
- res.statusCode = 500;
474
- res.end();
475
- }
476
- });
477
- const faviconRouteHandler = neverReject('faviconRouteHandler', async function faviconRouteHandler(res) {
478
- // You can use this hook either to modify the incoming request or to tell
479
- // PostGraphile not to handle the request further (return null). NOTE: if
480
- // you return `null` from this hook then you are also responsible for
481
- // terminating the request however your framework handles that (e.g.
482
- // `res.send(...)` or `next()`).
483
- const req = pluginHook('postgraphile:http:faviconRouteHandler', res.getNodeServerRequest(), {
484
- options,
485
- response: res,
486
- });
487
- if (req == null) {
488
- return;
489
- }
490
- // If this is the wrong method, we should let the client know.
491
- if (!(req.method === 'GET' || req.method === 'HEAD')) {
492
- res.statusCode = req.method === 'OPTIONS' ? 200 : 405;
493
- res.setHeader('Allow', 'GET, HEAD, OPTIONS');
494
- res.end();
495
- return;
496
- }
497
- // Otherwise we are good and should pipe the favicon to the browser.
498
- res.statusCode = 200;
499
- res.setHeader('Cache-Control', 'public, max-age=86400');
500
- res.setHeader('Content-Type', 'image/x-icon');
501
- // End early if the method is `HEAD`.
502
- if (req.method === 'HEAD') {
503
- res.end();
504
- return;
505
- }
506
- res.end(favicon_ico_1.default);
507
- });
508
- const graphiqlRouteHandler = neverReject('graphiqlRouteHandler', async function graphiqlRouteHandler(res) {
509
- // You can use this hook either to modify the incoming request or to tell
510
- // PostGraphile not to handle the request further (return null). NOTE: if
511
- // you return `null` from this hook then you are also responsible for
512
- // terminating the request however your framework handles that (e.g.
513
- // `res.send(...)` or `next()`).
514
- const req = pluginHook('postgraphile:http:graphiqlRouteHandler', res.getNodeServerRequest(), {
515
- options,
516
- response: res,
517
- });
518
- if (req == null) {
519
- return;
520
- }
521
- if (firstRequestHandler)
522
- firstRequestHandler(req);
523
- // If using the incorrect method, let the user know.
524
- if (!(req.method === 'GET' || req.method === 'HEAD')) {
525
- res.statusCode = req.method === 'OPTIONS' ? 200 : 405;
526
- res.setHeader('Allow', 'GET, HEAD, OPTIONS');
527
- res.end();
528
- return;
529
- }
530
- res.statusCode = 200;
531
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
532
- res.setHeader('X-Frame-Options', 'SAMEORIGIN');
533
- res.setHeader('Content-Security-Policy', "frame-ancestors 'self'");
534
- // End early if the method is `HEAD`.
535
- if (req.method === 'HEAD') {
536
- res.end();
537
- return;
538
- }
539
- // Actually renders GraphiQL.
540
- if (graphiqlHtml && typeof options.allowExplain === 'function') {
541
- res.end(graphiqlHtml.replace(`"${ALLOW_EXPLAIN_PLACEHOLDER}"`, // Because JSON escaped
542
- JSON.stringify(!!(await options.allowExplain(req)))));
543
- }
544
- else {
545
- res.end(graphiqlHtml);
546
- }
547
- });
548
- const graphqlRouteHandler = neverReject('graphqlRouteHandler', async function graphqlRouteHandler(res) {
549
- // You can use this hook either to modify the incoming request or to tell
550
- // PostGraphile not to handle the request further (return null). NOTE: if
551
- // you return `null` from this hook then you are also responsible for
552
- // terminating the request however your framework handles that (e.g.
553
- // `res.send(...)` or `next()`).
554
- const req = pluginHook('postgraphile:http:graphqlRouteHandler', res.getNodeServerRequest(), {
555
- options,
556
- response: res,
557
- });
558
- if (req == null) {
559
- return;
560
- }
561
- if (firstRequestHandler)
562
- firstRequestHandler(req);
563
- // Add our CORS headers to be good web citizens (there are perf
564
- // implications though so be careful!)
565
- //
566
- // Always enable CORS when developing PostGraphile because GraphiQL will be
567
- // on port 5783.
568
- if (enableCors)
569
- addCORSHeaders(res);
570
- // ========================================================================
571
- // Execute GraphQL Queries
572
- // ========================================================================
573
- // If we didn’t call `next` above, all requests will return 200 by default!
574
- res.statusCode = 200;
575
- if (watchPg) {
576
- // Inform GraphiQL and other clients that they can subscribe to events
577
- // (such as the schema being updated) at the following URL
578
- res.setHeader('X-GraphQL-Event-Stream', externalEventStreamRoute || `${externalUrlBase}${eventStreamRoute}`);
579
- }
580
- // Don’t execute our GraphQL stuffs for `OPTIONS` requests.
581
- if (req.method === 'OPTIONS') {
582
- res.statusCode = 200;
583
- res.end();
584
- return;
585
- }
586
- // The `result` will be used at the very end in our `finally` block.
587
- // Statements inside the `try` will assign to `result` when they get
588
- // a result. We also keep track of `params`.
589
- let paramsList;
590
- let results = [];
591
- const queryTimeStart = !disableQueryLog && process.hrtime();
592
- let pgRole;
593
- if (debugRequest.enabled)
594
- debugRequest('GraphQL query request has begun.');
595
- let returnArray = false;
596
- // This big `try`/`catch`/`finally` block represents the execution of our
597
- // GraphQL query. All errors thrown in this block will be returned to the
598
- // client as GraphQL errors.
599
- try {
600
- // First thing we need to do is get the GraphQL schema for this request.
601
- // It should never really change unless we are in watch mode.
602
- const gqlSchema = theOneAndOnlyGraphQLSchema || (await getGqlSchema());
603
- // Note that we run our middleware after we make sure we are on the
604
- // correct route. This is so that if our middleware modifies the `req` or
605
- // `res` objects, only we downstream will see the modifications.
606
- //
607
- // We also run our middleware inside the `try` so that we get the GraphQL
608
- // error reporting style for syntax errors.
609
- await parseBody(req, res);
610
- // If this is not one of the correct methods, throw an error.
611
- if (req.method !== 'POST') {
612
- res.setHeader('Allow', 'POST, OPTIONS');
613
- throw httpError(405, 'Only `POST` requests are allowed.');
614
- }
615
- // Get the parameters we will use to run a GraphQL request. `params` may
616
- // include:
617
- //
618
- // - `query`: The required GraphQL query string.
619
- // - `variables`: An optional JSON object containing GraphQL variables.
620
- // - `operationName`: The optional name of the GraphQL operation we will
621
- // be executing.
622
- const body = req.body;
623
- paramsList = typeof body === 'string' ? { query: body } : body;
624
- // Validate our paramsList object a bit.
625
- if (paramsList == null)
626
- throw httpError(400, 'Must provide an object parameters, not nullish value.');
627
- if (typeof paramsList !== 'object')
628
- throw httpError(400, `Expected parameter object, not value of type '${typeof paramsList}'.`);
629
- if (Array.isArray(paramsList)) {
630
- if (!enableQueryBatching) {
631
- throw httpError(501, 'Batching queries as an array is currently unsupported. Please provide a single query object.');
632
- }
633
- else {
634
- returnArray = true;
635
- }
636
- }
637
- else {
638
- paramsList = [paramsList];
639
- }
640
- paramsList = pluginHook('postgraphile:httpParamsList', paramsList, {
641
- options,
642
- req,
643
- res,
644
- returnArray,
645
- httpError,
646
- });
647
- results = await Promise.all(paramsList.map(async (params) => {
648
- let queryDocumentAst = null;
649
- let result;
650
- const meta = Object.create(null);
651
- try {
652
- if (!params)
653
- throw httpError(400, 'Invalid query structure.');
654
- const { query, operationName } = params;
655
- let { variables } = params;
656
- if (!query)
657
- throw httpError(400, 'Must provide a query string.');
658
- // If variables is a string, we assume it is a JSON string and that it
659
- // needs to be parsed.
660
- if (typeof variables === 'string') {
661
- // If variables is just an empty string, we should set it to null and
662
- // ignore it.
663
- if (variables === '') {
664
- variables = null;
665
- }
666
- else {
667
- // Otherwise, let us try to parse it as JSON.
668
- try {
669
- variables = JSON.parse(variables);
670
- }
671
- catch (error) {
672
- error.statusCode = 400;
673
- throw error;
674
- }
675
- }
676
- }
677
- // Throw an error if `variables` is not an object.
678
- if (variables != null && typeof variables !== 'object')
679
- throw httpError(400, `Variables must be an object, not '${typeof variables}'.`);
680
- // Throw an error if `operationName` is not a string.
681
- if (operationName != null && typeof operationName !== 'string')
682
- throw httpError(400, `Operation name must be a string, not '${typeof operationName}'.`);
683
- let validationErrors;
684
- ({ queryDocumentAst, validationErrors } = parseQuery(gqlSchema, query));
685
- if (validationErrors.length === 0) {
686
- // You are strongly encouraged to use
687
- // `postgraphile:validationRules:static` if possible - you should
688
- // only use this one if you need access to variables.
689
- const moreValidationRules = pluginHook('postgraphile:validationRules', [], {
690
- options,
691
- req,
692
- res,
693
- variables,
694
- operationName,
695
- meta,
696
- });
697
- if (moreValidationRules.length) {
698
- validationErrors = graphql_1.validate(gqlSchema, queryDocumentAst, moreValidationRules);
699
- }
700
- }
701
- // If we have some validation errors, don’t execute the query. Instead
702
- // send the errors to the client with a `400` code.
703
- if (validationErrors.length > 0) {
704
- result = { errors: validationErrors, statusCode: 400 };
705
- }
706
- else if (!queryDocumentAst) {
707
- throw new Error('Could not process query');
708
- }
709
- else {
710
- if (debugRequest.enabled)
711
- debugRequest('GraphQL query is validated.');
712
- // Lazily log the query. If this debugger isn’t enabled, don’t run it.
713
- if (debugGraphql.enabled)
714
- debugGraphql('%s', graphql_1.print(queryDocumentAst).replace(/\s+/g, ' ').trim());
715
- result = await withPostGraphileContextFromReqRes(req,
716
- // For backwards compatibilty we must pass the actual node request object.
717
- res.getNodeServerResponse(), {
718
- singleStatement: false,
719
- queryDocumentAst,
720
- variables,
721
- operationName,
722
- }, (graphqlContext) => {
723
- pgRole = graphqlContext.pgRole;
724
- const graphqlResult = graphql_1.execute(gqlSchema, queryDocumentAst, null, graphqlContext, variables, operationName);
725
- if (typeof graphqlContext.getExplainResults === 'function') {
726
- return Promise.resolve(graphqlResult).then(async (obj) => ({
727
- ...obj,
728
- // Add our explain data
729
- explain: await graphqlContext.getExplainResults(),
730
- }));
731
- }
732
- else {
733
- return graphqlResult;
734
- }
735
- });
736
- }
737
- }
738
- catch (error) {
739
- result = {
740
- errors: [error],
741
- statusCode: error.status || error.statusCode || 500,
742
- };
743
- // If the status code is 500, let’s log our error.
744
- if (result.statusCode === 500)
745
- // tslint:disable-next-line no-console
746
- console.error(error.stack);
747
- }
748
- finally {
749
- // Format our errors so the client doesn’t get the full thing.
750
- if (result && result.errors) {
751
- result.errors = handleErrors(result.errors, req, res);
752
- }
753
- if (!isEmpty(meta)) {
754
- result.meta = meta;
755
- }
756
- result = pluginHook('postgraphile:http:result', result, {
757
- options,
758
- returnArray,
759
- queryDocumentAst,
760
- req,
761
- pgRole,
762
- });
763
- // Log the query. If this debugger isn’t enabled, don’t run it.
764
- if (!disableQueryLog && queryDocumentAst) {
765
- // To appease TypeScript
766
- const definitelyQueryDocumentAst = queryDocumentAst;
767
- // We must reference this before it's deleted!
768
- const resultStatusCode = result.statusCode;
769
- const timeDiff = queryTimeStart && process.hrtime(queryTimeStart);
770
- setImmediate(() => {
771
- const prettyQuery = graphql_1.print(definitelyQueryDocumentAst)
772
- .replace(/\s+/g, ' ')
773
- .trim();
774
- const errorCount = (result.errors || []).length;
775
- const ms = timeDiff[0] * 1e3 + timeDiff[1] * 1e-6;
776
- let message;
777
- if (resultStatusCode === 401) {
778
- // Users requested that JWT errors were raised differently:
779
- //
780
- // https://github.com/graphile/postgraphile/issues/560
781
- message = chalk_1.default.red(`401 authentication error`);
782
- }
783
- else if (resultStatusCode === 403) {
784
- message = chalk_1.default.red(`403 forbidden error`);
785
- }
786
- else {
787
- message = chalk_1.default[errorCount === 0 ? 'green' : 'red'](`${errorCount} error(s)`);
788
- }
789
- // tslint:disable-next-line no-console
790
- console.log(`${message} ${pgRole != null ? `as ${chalk_1.default.magenta(pgRole)} ` : ''}in ${chalk_1.default.grey(`${ms.toFixed(2)}ms`)} :: ${prettyQuery}`);
791
- });
792
- }
793
- if (debugRequest.enabled)
794
- debugRequest('GraphQL query has been executed.');
795
- }
796
- return result;
797
- }));
798
- }
799
- catch (error) {
800
- // Set our status code and send the client our results!
801
- if (res.statusCode === 200)
802
- res.statusCode = error.status || error.statusCode || 500;
803
- // Overwrite entire response
804
- returnArray = false;
805
- results = [{ errors: handleErrors([error], req, res) }];
806
- // If the status code is 500, let’s log our error.
807
- if (res.statusCode === 500) {
808
- // tslint:disable-next-line no-console
809
- console.error(error.stack);
810
- }
811
- }
812
- finally {
813
- // Finally, we send the client the results.
814
- if (!returnArray) {
815
- if (res.statusCode === 200 && results[0].statusCode) {
816
- res.statusCode = results[0].statusCode;
817
- }
818
- results[0].statusCode = undefined;
819
- }
820
- res.setHeader('Content-Type', 'application/json; charset=utf-8');
821
- const { statusCode, result } = pluginHook('postgraphile:http:end', {
822
- statusCode: res.statusCode,
823
- result: returnArray ? results : results[0],
824
- }, {
825
- options,
826
- returnArray,
827
- req,
828
- // For backwards compatibility, the underlying response object.
829
- res: res.getNodeServerResponse(),
830
- });
831
- if (statusCode) {
832
- res.statusCode = statusCode;
833
- }
834
- res.end(JSON.stringify(result));
835
- if (debugRequest.enabled) {
836
- debugRequest('GraphQL ' + (returnArray ? 'queries' : 'query') + ' request finished.');
837
- }
838
- }
839
- });
840
- /**
841
- * A polymorphic request handler that should detect what `http` framework is
842
- * being used and specifically handle that framework.
843
- *
844
- * Supported frameworks include:
845
- *
846
- * - Native Node.js `http`.
847
- * - `connect`.
848
- * - `express`.
849
- * - `koa` (2.0).
850
- */
851
- const middleware = (a, b, c) => {
852
- // If are arguments look like the arguments to koa middleware, this is
853
- // `koa` middleware.
854
- if (isKoaApp(a, b)) {
855
- // Set the correct `koa` variable names…
856
- const ctx = a;
857
- const next = b;
858
- const responseHandler = new frameworks_1.PostGraphileResponseKoa(ctx, next);
859
- // Execute our request handler. If an error is thrown, we don’t call
860
- // `next` with an error. Instead we return the promise and let `koa`
861
- // handle the error.
862
- return requestHandler(responseHandler, next);
863
- }
864
- else {
865
- // Set the correct `connect` style variable names. If there was no `next`
866
- // defined (likely the case if the client is using `http`) we use the
867
- // final handler.
868
- const req = a;
869
- const res = b;
870
- const next = c || finalHandler(req, res);
871
- const responseHandler = new frameworks_1.PostGraphileResponseNode(req, res, next);
872
- // Execute our request handler. If the request errored out, call `next` with the error.
873
- requestHandler(responseHandler, next).catch(next);
874
- // No return value.
875
- }
876
- };
877
- middleware.getGraphQLSchema = getGqlSchema;
878
- middleware.formatError = formatError;
879
- middleware.pgPool = pgPool;
880
- middleware.withPostGraphileContextFromReqRes = withPostGraphileContextFromReqRes;
881
- middleware.handleErrors = handleErrors;
882
- middleware.options = options;
883
- middleware.graphqlRoute = graphqlRoute;
884
- middleware.graphqlRouteHandler = graphqlRouteHandler;
885
- middleware.graphiqlRoute = graphiqlRoute;
886
- middleware.graphiqlRouteHandler = graphiql ? graphiqlRouteHandler : null;
887
- middleware.faviconRouteHandler = graphiql ? faviconRouteHandler : null;
888
- middleware.eventStreamRoute = eventStreamRoute;
889
- middleware.eventStreamRouteHandler = watchPg ? eventStreamRouteHandler : null;
890
- middleware.shutdownActions = shutdownActions;
891
- // Experimental
892
- middleware.release = () => shutdownActions.invokeAll();
893
- const hookedMiddleware = pluginHook('postgraphile:middleware', middleware, {
894
- options,
895
- // Experimental
896
- shutdownActions,
897
- });
898
- // Sanity check:
899
- if (!hookedMiddleware.getGraphQLSchema) {
900
- throw new Error("Hook for 'postgraphile:middleware' has not copied over the helpers; e.g. missing `Object.assign(newMiddleware, oldMiddleware)`");
901
- }
902
- return hookedMiddleware;
903
- }
904
- exports.default = createPostGraphileHttpRequestHandler;
905
- /**
906
- * Adds CORS to a request. See [this][1] flowchart for an explanation of how
907
- * CORS works. Note that these headers are set for all requests, CORS
908
- * algorithms normally run a preflight request using the `OPTIONS` method to
909
- * get these headers.
910
- *
911
- * Note though, that enabling CORS will incur extra costs when it comes to the
912
- * preflight requests. It is much better if you choose to use a proxy and
913
- * bypass CORS altogether.
914
- *
915
- * [1]: http://www.html5rocks.com/static/images/cors_server_flowchart.png
916
- */
917
- function addCORSHeaders(res) {
918
- res.setHeader('Access-Control-Allow-Origin', '*');
919
- res.setHeader('Access-Control-Allow-Methods', 'HEAD, GET, POST');
920
- res.setHeader('Access-Control-Allow-Headers', [
921
- 'Origin',
922
- 'X-Requested-With',
923
- // Used by `express-graphql` to determine whether to expose the GraphiQL
924
- // interface (`text/html`) or not.
925
- 'Accept',
926
- // Used by PostGraphile for auth purposes.
927
- 'Authorization',
928
- // Used by GraphQL Playground and other Apollo-enabled servers
929
- 'X-Apollo-Tracing',
930
- // The `Content-*` headers are used when making requests with a body,
931
- // like in a POST request.
932
- 'Content-Type',
933
- 'Content-Length',
934
- // For our 'Explain' feature
935
- 'X-PostGraphile-Explain',
936
- ].join(', '));
937
- res.setHeader('Access-Control-Expose-Headers', ['X-GraphQL-Event-Stream'].join(', '));
938
- }
939
- function createBadAuthorizationHeaderError() {
940
- return httpError(400, 'Authorization header is not of the correct bearer scheme format.');
941
- }
942
- /**
943
- * Parses the `Bearer` auth scheme token out of the `Authorization` header as
944
- * defined by [RFC7235][1].
945
- *
946
- * ```
947
- * Authorization = credentials
948
- * credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
949
- * token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" )*"="
950
- * ```
951
- *
952
- * [1]: https://tools.ietf.org/html/rfc7235
953
- *
954
- * @private
955
- */
956
- const authorizationBearerRex = /^\s*bearer\s+([a-z0-9\-._~+/]+=*)\s*$/i;
957
- /**
958
- * Gets the JWT token from the Http request’s headers. Specifically the
959
- * `Authorization` header in the `Bearer` format. Will throw an error if the
960
- * header is in the incorrect format, but will not throw an error if the header
961
- * does not exist.
962
- *
963
- * @private
964
- * @param {IncomingMessage} request
965
- * @returns {string | null}
966
- */
967
- function getJwtToken(request) {
968
- const { authorization } = request.headers;
969
- if (Array.isArray(authorization))
970
- throw createBadAuthorizationHeaderError();
971
- // If there was no authorization header, just return null.
972
- if (authorization == null)
973
- return null;
974
- const match = authorizationBearerRex.exec(authorization);
975
- // If we did not match the authorization header with our expected format,
976
- // throw a 400 error.
977
- if (!match)
978
- throw createBadAuthorizationHeaderError();
979
- // Return the token from our match.
980
- return match[1];
981
- }
982
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlUG9zdEdyYXBoaWxlSHR0cFJlcXVlc3RIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Bvc3RncmFwaGlsZS9odHRwL2NyZWF0ZVBvc3RHcmFwaGlsZUh0dHBSZXF1ZXN0SGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw4RUFBOEU7QUFDOUUscUNBV2lCO0FBQ2pCLGdFQUE2RDtBQUU3RCw4Q0FBc0Q7QUFFdEQsbUVBQTREO0FBQzVELHdFQUFpRTtBQUNqRSx1Q0FBZ0M7QUFFaEMsaUNBQTBCO0FBQzFCLGtDQUFtQyxDQUFDLG9DQUFvQztBQUN4RSx5Q0FBMEM7QUFDMUMscUNBQXNDO0FBQ3RDLDZDQUE4QztBQUM5QywwQ0FBMkM7QUFDM0MsaUNBQWtDO0FBRWxDLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBTSxFQUFFLENBQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFVBQVUsQ0FBQztBQUUvRSxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQztBQUVoQyxNQUFNLHlCQUF5QixHQUFHLDBCQUEwQixDQUFDO0FBQzdELE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRTtJQUNoQixVQUFVO0FBQ1osQ0FBQyxDQUFDO0FBRUYsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLE1BQU0sQ0FBQztBQUU5Qjs7Ozs7R0FLRztBQUNILDBEQUErQztBQUUvQzs7O0dBR0c7QUFDSCw4REFBMEQ7QUFDMUQsbURBQWtFO0FBQ2xFLDZDQU1zQjtBQUV0Qjs7O0dBR0c7QUFDSCxNQUFNLGdCQUFnQixHQUFHO0lBQ3ZCLEdBQUcsRUFBRSxTQUFTO0lBQ2QsR0FBRyxFQUFFLFNBQVM7SUFDZCxHQUFHLEVBQUUsU0FBUztJQUNkLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFFBQVEsRUFBRSxTQUFTO0NBQ3BCLENBQUM7QUFDRixT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