sofa-api 0.11.0 → 0.11.2-alpha.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/CHANGELOG.md +50 -0
- package/README.md +11 -42
- package/bob.config.js +1 -0
- package/bump.js +18 -0
- package/dist/LICENSE +21 -0
- package/{ast.d.ts → dist/ast.d.ts} +0 -0
- package/{common.d.ts → dist/common.d.ts} +0 -0
- package/dist/index.d.ts +16 -0
- package/{index.js → dist/index.js} +83 -134
- package/{index.mjs → dist/index.mjs} +87 -138
- package/{logger.d.ts → dist/logger.d.ts} +0 -0
- package/{open-api → dist/open-api}/index.d.ts +2 -2
- package/{open-api → dist/open-api}/interfaces.d.ts +0 -0
- package/{open-api → dist/open-api}/operations.d.ts +0 -0
- package/dist/open-api/types.d.ts +3 -0
- package/{open-api → dist/open-api}/utils.d.ts +0 -0
- package/dist/package.json +56 -0
- package/{parse.d.ts → dist/parse.d.ts} +0 -0
- package/dist/router.d.ts +4 -0
- package/{sofa.d.ts → dist/sofa.d.ts} +1 -1
- package/{subscriptions.d.ts → dist/subscriptions.d.ts} +2 -10
- package/{types.d.ts → dist/types.d.ts} +0 -0
- package/package.json +89 -34
- package/tsconfig.example.json +7 -0
- package/express.d.ts +0 -25
- package/index.d.ts +0 -38
- package/open-api/types.d.ts +0 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Change log
|
|
2
|
+
|
|
3
|
+
### vNEXT
|
|
4
|
+
|
|
5
|
+
### v0.7.0
|
|
6
|
+
|
|
7
|
+
- feat(swagger): custom components and security for OpenAPI [PR #296](https://github.com/Urigo/SOFA/pull/296)
|
|
8
|
+
|
|
9
|
+
### v0.6.1
|
|
10
|
+
|
|
11
|
+
- fix(swagger): broken type of ID scalar in generated swagger document [PR #280](https://github.com/Urigo/SOFA/pull/280)
|
|
12
|
+
- fix: do not resolve nil variables [PR #193](https://github.com/Urigo/SOFA/pull/193)
|
|
13
|
+
- fix: use Kind from graphql instead of strings [PR #192](https://github.com/Urigo/SOFA/pull/192)
|
|
14
|
+
- fix: replace request package with Axios [PR #194](https://github.com/Urigo/SOFA/pull/194)
|
|
15
|
+
|
|
16
|
+
### v0.6.0
|
|
17
|
+
|
|
18
|
+
- fix(swagger): fix descriptions [PR #178](https://github.com/Urigo/SOFA/pull/178)
|
|
19
|
+
- feat: support GraphQL Interfaces [PR #167](https://github.com/Urigo/SOFA/pull/167)
|
|
20
|
+
|
|
21
|
+
### v0.5.1
|
|
22
|
+
|
|
23
|
+
- fix: do not skip falsy values (only null and undefined) [PR #134](https://github.com/Urigo/SOFA/pull/134)
|
|
24
|
+
|
|
25
|
+
### v0.5.0
|
|
26
|
+
|
|
27
|
+
- feat(swagger): add description [PR #107](https://github.com/Urigo/SOFA/pull/107)
|
|
28
|
+
- feat(swagger): add `ID` scalar definition [PR #107](https://github.com/Urigo/SOFA/pull/107)
|
|
29
|
+
- fix(swagger): use `requestBody` or `parameters` not both [PR #107](https://github.com/Urigo/SOFA/pull/107)
|
|
30
|
+
- fix(swagger): generate valid YAML structure for nested objects [PR #107](https://github.com/Urigo/SOFA/pull/107)
|
|
31
|
+
- fix(swagger): avoid empty `required` array [PR #107](https://github.com/Urigo/SOFA/pull/107)
|
|
32
|
+
|
|
33
|
+
### v0.4.0
|
|
34
|
+
|
|
35
|
+
- feat: add error handler [PR #44](https://github.com/Urigo/SOFA/pull/44) [PR #45](https://github.com/Urigo/SOFA/pull/45)
|
|
36
|
+
- feat: allow to customize endpoint's HTTP Method [PR #46](https://github.com/Urigo/SOFA/pull/46)
|
|
37
|
+
- feat: add InputTypeObjects to OpenAPI generation [PR #34](https://github.com/Urigo/SOFA/pull/34) - [@hajnalben](https://github.com/hajnalben)
|
|
38
|
+
|
|
39
|
+
### v0.3.0
|
|
40
|
+
|
|
41
|
+
- fix: parse InputTypeObject with JSON.parse [PR #30](https://github.com/Urigo/SOFA/pull/30)
|
|
42
|
+
- feat: custom `depthLimit` (circular references) [PR #29](https://github.com/Urigo/SOFA/pull/29)
|
|
43
|
+
|
|
44
|
+
### v0.2.3
|
|
45
|
+
|
|
46
|
+
- fix: prevent circular references [PR #23](https://github.com/Urigo/SOFA/pull/23)
|
|
47
|
+
|
|
48
|
+
### v0.2.2
|
|
49
|
+
|
|
50
|
+
We didn't track changes before this version.
|
package/README.md
CHANGED
|
@@ -20,47 +20,14 @@ Here's complete example with no dependency on frameworks, but also integratable
|
|
|
20
20
|
```js
|
|
21
21
|
import http from 'http';
|
|
22
22
|
import getStream from 'get-stream';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
const invokeSofa = createSofaRouter({
|
|
26
|
-
basePath: '/api',
|
|
27
|
-
schema,
|
|
28
|
-
});
|
|
23
|
+
import { useSofa } from 'sofa-api';
|
|
29
24
|
|
|
30
|
-
const server = http.createServer(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
contextValue: {
|
|
37
|
-
req,
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
if (response) {
|
|
41
|
-
const headers = {
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
};
|
|
44
|
-
if (response.statusMessage) {
|
|
45
|
-
res.writeHead(response.status, response.statusMessage, headers);
|
|
46
|
-
} else {
|
|
47
|
-
res.writeHead(response.status, headers);
|
|
48
|
-
}
|
|
49
|
-
if (response.type === 'result') {
|
|
50
|
-
res.end(JSON.stringify(response.body));
|
|
51
|
-
}
|
|
52
|
-
if (response.type === 'error') {
|
|
53
|
-
res.end(JSON.stringify(response.error));
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
res.writeHead(404);
|
|
57
|
-
res.end();
|
|
58
|
-
}
|
|
59
|
-
} catch (error) {
|
|
60
|
-
res.writeHead(500);
|
|
61
|
-
res.end(JSON.stringify(error));
|
|
62
|
-
}
|
|
63
|
-
});
|
|
25
|
+
const server = http.createServer(
|
|
26
|
+
useSofa({
|
|
27
|
+
basePath: '/api',
|
|
28
|
+
schema,
|
|
29
|
+
})
|
|
30
|
+
);
|
|
64
31
|
```
|
|
65
32
|
|
|
66
33
|
Another example with builtin express-like frameworks support
|
|
@@ -302,6 +269,7 @@ Thanks to GraphQL's Type System Sofa is able to generate OpenAPI (Swagger) defin
|
|
|
302
269
|
|
|
303
270
|
```ts
|
|
304
271
|
import { useSofa, OpenAPI } from 'sofa-api';
|
|
272
|
+
import { writeFileSync } from 'fs';
|
|
305
273
|
|
|
306
274
|
const openApi = OpenAPI({
|
|
307
275
|
schema,
|
|
@@ -325,13 +293,14 @@ app.use(
|
|
|
325
293
|
);
|
|
326
294
|
|
|
327
295
|
// writes every recorder route
|
|
328
|
-
|
|
296
|
+
writeFileSync('./swagger.json', JSON.stringify(openApi.get(), null, 2));
|
|
329
297
|
```
|
|
330
298
|
|
|
331
299
|
OpenAPI (Swagger) with Bearer Authentication
|
|
332
300
|
|
|
333
301
|
```ts
|
|
334
302
|
import { useSofa, OpenAPI } from 'sofa-api';
|
|
303
|
+
import { writeFileSync } from 'fs';
|
|
335
304
|
|
|
336
305
|
const openApi = OpenAPI({
|
|
337
306
|
schema,
|
|
@@ -369,7 +338,7 @@ app.use(
|
|
|
369
338
|
);
|
|
370
339
|
|
|
371
340
|
// writes every recorder route
|
|
372
|
-
|
|
341
|
+
writeFileSync('./swagger.json', JSON.stringify(openApi.get(), null, 2));
|
|
373
342
|
```
|
|
374
343
|
|
|
375
344
|
## License
|
package/bob.config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = {};
|
package/bump.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const semver = require('semver');
|
|
2
|
+
const packageJson = require('./package.json');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const cp = require('child_process');
|
|
5
|
+
|
|
6
|
+
const gitHash = cp
|
|
7
|
+
.spawnSync('git', ['rev-parse', '--short', 'HEAD'])
|
|
8
|
+
.stdout.toString()
|
|
9
|
+
.trim();
|
|
10
|
+
const alphaVersion = semver.inc(
|
|
11
|
+
packageJson.version,
|
|
12
|
+
'prerelease',
|
|
13
|
+
true,
|
|
14
|
+
gitHash
|
|
15
|
+
);
|
|
16
|
+
packageJson.version = alphaVersion;
|
|
17
|
+
|
|
18
|
+
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2));
|
package/dist/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Uri Goldshtein
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
File without changes
|
|
File without changes
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import * as http from 'http';
|
|
3
|
+
import type { ContextValue } from './types';
|
|
4
|
+
import type { SofaConfig } from './sofa';
|
|
5
|
+
import { ServerAdapter } from '@whatwg-node/server';
|
|
6
|
+
export { OpenAPI } from './open-api';
|
|
7
|
+
export declare type ContextFn = (init: {
|
|
8
|
+
req: any;
|
|
9
|
+
res: any;
|
|
10
|
+
}) => ContextValue;
|
|
11
|
+
export declare function isContextFn(context: any): context is ContextFn;
|
|
12
|
+
interface SofaMiddlewareConfig extends SofaConfig {
|
|
13
|
+
context?: ContextValue | ContextFn;
|
|
14
|
+
}
|
|
15
|
+
export declare function useSofa({ context, ...config }: SofaMiddlewareConfig): ServerAdapter<http.IncomingMessage, http.ServerResponse>;
|
|
16
|
+
export declare function createSofaRouter(config: SofaConfig): import("itty-router").Router<import("itty-router").Request, {}>;
|
|
@@ -6,12 +6,13 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
|
|
|
6
6
|
|
|
7
7
|
const tslib = require('tslib');
|
|
8
8
|
const graphql = require('graphql');
|
|
9
|
-
const
|
|
9
|
+
const ittyRouter = require('itty-router');
|
|
10
10
|
const utils = require('@graphql-tools/utils');
|
|
11
11
|
const paramCase = require('param-case');
|
|
12
12
|
const uuid = require('uuid');
|
|
13
|
-
const
|
|
14
|
-
const colors = require('ansi-colors');
|
|
13
|
+
const fetch = require('@whatwg-node/fetch');
|
|
14
|
+
const colors = _interopDefault(require('ansi-colors'));
|
|
15
|
+
const server = require('@whatwg-node/server');
|
|
15
16
|
const jsYaml = require('js-yaml');
|
|
16
17
|
const fs = require('fs');
|
|
17
18
|
const titleCase = require('title-case');
|
|
@@ -236,7 +237,14 @@ class SubscriptionManager {
|
|
|
236
237
|
}
|
|
237
238
|
const { url } = this.clients.get(id);
|
|
238
239
|
logger.info(`[Subscription] Trigger ${id}`);
|
|
239
|
-
yield
|
|
240
|
+
const response = yield fetch.fetch(url, {
|
|
241
|
+
method: 'POST',
|
|
242
|
+
body: JSON.stringify(result),
|
|
243
|
+
headers: {
|
|
244
|
+
'Content-Type': 'application/json',
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
yield response.text();
|
|
240
248
|
});
|
|
241
249
|
}
|
|
242
250
|
buildOperations() {
|
|
@@ -270,7 +278,9 @@ class SubscriptionManager {
|
|
|
270
278
|
|
|
271
279
|
function createRouter(sofa) {
|
|
272
280
|
logger.debug('[Sofa] Creating router');
|
|
273
|
-
const router =
|
|
281
|
+
const router = ittyRouter.Router({
|
|
282
|
+
base: sofa.basePath,
|
|
283
|
+
});
|
|
274
284
|
const queryType = sofa.schema.getQueryType();
|
|
275
285
|
const mutationType = sofa.schema.getMutationType();
|
|
276
286
|
const subscriptionManager = new SubscriptionManager(sofa);
|
|
@@ -290,92 +300,75 @@ function createRouter(sofa) {
|
|
|
290
300
|
}
|
|
291
301
|
});
|
|
292
302
|
}
|
|
293
|
-
router.post('/webhook', (
|
|
294
|
-
const { subscription, variables, url } =
|
|
303
|
+
router.post('/webhook', (request, contextValue) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
304
|
+
const { subscription, variables, url } = yield request.json();
|
|
295
305
|
try {
|
|
296
306
|
const result = yield subscriptionManager.start({
|
|
297
307
|
subscription,
|
|
298
308
|
variables,
|
|
299
309
|
url,
|
|
300
310
|
}, contextValue);
|
|
301
|
-
return {
|
|
302
|
-
type: 'result',
|
|
311
|
+
return new fetch.Response(JSON.stringify(result), {
|
|
303
312
|
status: 200,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
313
|
+
statusText: 'OK',
|
|
314
|
+
headers: {
|
|
315
|
+
'Content-Type': 'application/json',
|
|
316
|
+
},
|
|
317
|
+
});
|
|
307
318
|
}
|
|
308
319
|
catch (error) {
|
|
309
|
-
return {
|
|
310
|
-
type: 'error',
|
|
320
|
+
return new fetch.Response(JSON.stringify(error), {
|
|
311
321
|
status: 500,
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
};
|
|
322
|
+
statusText: 'Subscription failed',
|
|
323
|
+
});
|
|
315
324
|
}
|
|
316
325
|
}));
|
|
317
|
-
router.post('/webhook/:id', (
|
|
318
|
-
|
|
326
|
+
router.post('/webhook/:id', (request, contextValue) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
327
|
+
var _a;
|
|
328
|
+
const id = (_a = request.params) === null || _a === void 0 ? void 0 : _a.id;
|
|
329
|
+
const body = yield request.json();
|
|
319
330
|
const variables = body.variables;
|
|
320
331
|
try {
|
|
321
332
|
const result = yield subscriptionManager.update({
|
|
322
333
|
id,
|
|
323
334
|
variables,
|
|
324
335
|
}, contextValue);
|
|
325
|
-
return {
|
|
326
|
-
type: 'result',
|
|
336
|
+
return new fetch.Response(JSON.stringify(result), {
|
|
327
337
|
status: 200,
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
338
|
+
statusText: 'OK',
|
|
339
|
+
headers: {
|
|
340
|
+
'Content-Type': 'application/json',
|
|
341
|
+
},
|
|
342
|
+
});
|
|
331
343
|
}
|
|
332
344
|
catch (error) {
|
|
333
|
-
return {
|
|
334
|
-
type: 'error',
|
|
345
|
+
return new fetch.Response(JSON.stringify(error), {
|
|
335
346
|
status: 500,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
};
|
|
347
|
+
statusText: 'Subscription failed to update',
|
|
348
|
+
});
|
|
339
349
|
}
|
|
340
350
|
}));
|
|
341
|
-
router.delete('/webhook/:id', (
|
|
342
|
-
|
|
351
|
+
router.delete('/webhook/:id', (request) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
352
|
+
var _b;
|
|
353
|
+
const id = (_b = request.params) === null || _b === void 0 ? void 0 : _b.id;
|
|
343
354
|
try {
|
|
344
355
|
const result = yield subscriptionManager.stop(id);
|
|
345
|
-
return {
|
|
346
|
-
type: 'result',
|
|
356
|
+
return new fetch.Response(JSON.stringify(result), {
|
|
347
357
|
status: 200,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
358
|
+
statusText: 'OK',
|
|
359
|
+
headers: {
|
|
360
|
+
'Content-Type': 'application/json',
|
|
361
|
+
},
|
|
362
|
+
});
|
|
351
363
|
}
|
|
352
364
|
catch (error) {
|
|
353
|
-
return {
|
|
354
|
-
type: 'error',
|
|
365
|
+
return new fetch.Response(JSON.stringify(error), {
|
|
355
366
|
status: 500,
|
|
356
|
-
|
|
357
|
-
error,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
}));
|
|
361
|
-
return ({ method, url, body, contextValue }) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
362
|
-
if (!url.startsWith(sofa.basePath)) {
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
|
-
// trim base path and search
|
|
366
|
-
const [slicedUrl] = url.slice(sofa.basePath.length).split('?');
|
|
367
|
-
const trouterMethod = method.toUpperCase();
|
|
368
|
-
const obj = router.find(trouterMethod, slicedUrl);
|
|
369
|
-
for (const handler of obj.handlers) {
|
|
370
|
-
return yield handler({
|
|
371
|
-
url,
|
|
372
|
-
body,
|
|
373
|
-
params: obj.params,
|
|
374
|
-
contextValue,
|
|
367
|
+
statusText: 'Subscription failed to stop',
|
|
375
368
|
});
|
|
376
369
|
}
|
|
377
|
-
|
|
378
|
-
|
|
370
|
+
}));
|
|
371
|
+
return router;
|
|
379
372
|
}
|
|
380
373
|
function createQueryRoute({ sofa, router, fieldName, }) {
|
|
381
374
|
var _a, _b, _c, _d;
|
|
@@ -406,7 +399,7 @@ function createQueryRoute({ sofa, router, fieldName, }) {
|
|
|
406
399
|
path: (_c = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.path) !== null && _c !== void 0 ? _c : getPath(fieldName, isSingle && hasIdArgument),
|
|
407
400
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
408
401
|
};
|
|
409
|
-
router[route.method
|
|
402
|
+
router[route.method](route.path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
410
403
|
logger.debug(`[Router] ${fieldName} query available at ${route.method} ${route.path}`);
|
|
411
404
|
return {
|
|
412
405
|
document: operation,
|
|
@@ -439,7 +432,7 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
439
432
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
440
433
|
};
|
|
441
434
|
const { method, path } = route;
|
|
442
|
-
router[method
|
|
435
|
+
router[method](path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
443
436
|
logger.debug(`[Router] ${fieldName} mutation available at ${method} ${path}`);
|
|
444
437
|
return {
|
|
445
438
|
document: operation,
|
|
@@ -450,11 +443,24 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
450
443
|
function useHandler(config) {
|
|
451
444
|
const { sofa, operation, fieldName } = config;
|
|
452
445
|
const info = config.info;
|
|
453
|
-
return (
|
|
446
|
+
return (request, contextValue) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
447
|
+
var _a;
|
|
448
|
+
let body = {};
|
|
449
|
+
if (request.body != null) {
|
|
450
|
+
const strBody = yield request.text();
|
|
451
|
+
if (strBody) {
|
|
452
|
+
body = JSON.parse(strBody);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
454
455
|
const variableValues = info.variables.reduce((variables, variable) => {
|
|
455
456
|
const name = variable.variable.name.value;
|
|
456
457
|
const value = parseVariable({
|
|
457
|
-
value: pickParam({
|
|
458
|
+
value: pickParam({
|
|
459
|
+
url: request.url,
|
|
460
|
+
body,
|
|
461
|
+
params: request.params || {},
|
|
462
|
+
name,
|
|
463
|
+
}),
|
|
458
464
|
variable,
|
|
459
465
|
schema: sofa.schema,
|
|
460
466
|
});
|
|
@@ -472,27 +478,26 @@ function useHandler(config) {
|
|
|
472
478
|
});
|
|
473
479
|
if (result.errors) {
|
|
474
480
|
const defaultErrorHandler = (errors) => {
|
|
475
|
-
return {
|
|
476
|
-
type: 'error',
|
|
481
|
+
return new fetch.Response(errors[0], {
|
|
477
482
|
status: 500,
|
|
478
|
-
|
|
479
|
-
};
|
|
483
|
+
});
|
|
480
484
|
};
|
|
481
485
|
const errorHandler = sofa.errorHandler || defaultErrorHandler;
|
|
482
486
|
return errorHandler(result.errors);
|
|
483
487
|
}
|
|
484
|
-
return {
|
|
485
|
-
type: 'result',
|
|
488
|
+
return new fetch.Response(JSON.stringify((_a = result.data) === null || _a === void 0 ? void 0 : _a[fieldName]), {
|
|
486
489
|
status: config.route.responseStatus,
|
|
487
|
-
|
|
488
|
-
|
|
490
|
+
headers: {
|
|
491
|
+
'Content-Type': 'application/json',
|
|
492
|
+
},
|
|
493
|
+
});
|
|
489
494
|
});
|
|
490
495
|
}
|
|
491
496
|
function getPath(fieldName, hasId = false) {
|
|
492
497
|
return `/${convertName(fieldName)}${hasId ? '/:id' : ''}`;
|
|
493
498
|
}
|
|
494
499
|
function pickParam({ name, url, params, body, }) {
|
|
495
|
-
if (
|
|
500
|
+
if (name in params) {
|
|
496
501
|
return params[name];
|
|
497
502
|
}
|
|
498
503
|
const searchParams = new URLSearchParams(url.split('?')[1]);
|
|
@@ -559,24 +564,8 @@ function extractsModels(schema) {
|
|
|
559
564
|
}
|
|
560
565
|
// it's dumb but let's leave it for now
|
|
561
566
|
function isArrayOf(type, expected) {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
}
|
|
565
|
-
if (graphql.isNonNullType(type) && isOptionalList(type.ofType)) {
|
|
566
|
-
return true;
|
|
567
|
-
}
|
|
568
|
-
function isOptionalList(list) {
|
|
569
|
-
if (graphql.isListType(list)) {
|
|
570
|
-
if (list.ofType.name === expected.name) {
|
|
571
|
-
return true;
|
|
572
|
-
}
|
|
573
|
-
if (graphql.isNonNullType(list.ofType) &&
|
|
574
|
-
list.ofType.ofType.name === expected.name) {
|
|
575
|
-
return true;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
return false;
|
|
567
|
+
const typeNameInSdl = type.toString();
|
|
568
|
+
return (typeNameInSdl.includes('[') && typeNameInSdl.includes(expected.toString()));
|
|
580
569
|
}
|
|
581
570
|
function hasID(type) {
|
|
582
571
|
return graphql.isObjectType(type) && !!type.getFields().id;
|
|
@@ -849,50 +838,10 @@ function isContextFn(context) {
|
|
|
849
838
|
return typeof context === 'function';
|
|
850
839
|
}
|
|
851
840
|
function useSofa(_a) {
|
|
852
|
-
var
|
|
853
|
-
const
|
|
854
|
-
return
|
|
855
|
-
|
|
856
|
-
try {
|
|
857
|
-
let contextValue = { req };
|
|
858
|
-
if (context) {
|
|
859
|
-
if (typeof context === 'function') {
|
|
860
|
-
contextValue = yield context({ req, res });
|
|
861
|
-
}
|
|
862
|
-
else {
|
|
863
|
-
contextValue = context;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
const response = yield invokeSofa({
|
|
867
|
-
method: req.method,
|
|
868
|
-
url: (_b = req.originalUrl) !== null && _b !== void 0 ? _b : req.url,
|
|
869
|
-
body: req.body,
|
|
870
|
-
contextValue,
|
|
871
|
-
});
|
|
872
|
-
if (response == null) {
|
|
873
|
-
next();
|
|
874
|
-
}
|
|
875
|
-
else {
|
|
876
|
-
const headers = {
|
|
877
|
-
'Content-Type': 'application/json',
|
|
878
|
-
};
|
|
879
|
-
if (response.statusMessage) {
|
|
880
|
-
res.writeHead(response.status, response.statusMessage, headers);
|
|
881
|
-
}
|
|
882
|
-
else {
|
|
883
|
-
res.writeHead(response.status, headers);
|
|
884
|
-
}
|
|
885
|
-
if (response.type === 'result') {
|
|
886
|
-
res.end(JSON.stringify(response.body));
|
|
887
|
-
}
|
|
888
|
-
if (response.type === 'error') {
|
|
889
|
-
res.end(JSON.stringify(response.error));
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
catch (error) {
|
|
894
|
-
next(error);
|
|
895
|
-
}
|
|
841
|
+
var config = tslib.__rest(_a, ["context"]);
|
|
842
|
+
const sofaRouter = createSofaRouter(config);
|
|
843
|
+
return server.createServerAdapter({
|
|
844
|
+
handleRequest: sofaRouter.handle,
|
|
896
845
|
});
|
|
897
846
|
}
|
|
898
847
|
function createSofaRouter(config) {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { __awaiter, __asyncValues, __rest } from 'tslib';
|
|
2
2
|
import { getOperationAST, Kind, isScalarType, isEqualType, GraphQLBoolean, isInputObjectType, subscribe, isObjectType, isNonNullType, print, graphql, getNamedType, isListType, isEnumType, parse, printType, isIntrospectionType } from 'graphql';
|
|
3
|
-
import
|
|
3
|
+
import { Router } from 'itty-router';
|
|
4
4
|
import { buildOperationNodeForField } from '@graphql-tools/utils';
|
|
5
5
|
import { paramCase } from 'param-case';
|
|
6
6
|
import { v4 } from 'uuid';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
7
|
+
import { fetch, Response } from '@whatwg-node/fetch';
|
|
8
|
+
import colors from 'ansi-colors';
|
|
9
|
+
import { createServerAdapter } from '@whatwg-node/server';
|
|
9
10
|
import { dump } from 'js-yaml';
|
|
10
11
|
import { writeFileSync } from 'fs';
|
|
11
12
|
import { titleCase } from 'title-case';
|
|
@@ -84,16 +85,16 @@ const log = (level, color, args) => {
|
|
|
84
85
|
};
|
|
85
86
|
const logger = {
|
|
86
87
|
error: (...args) => {
|
|
87
|
-
log('error', red, args);
|
|
88
|
+
log('error', colors.red, args);
|
|
88
89
|
},
|
|
89
90
|
warn: (...args) => {
|
|
90
|
-
log('warn', yellow, args);
|
|
91
|
+
log('warn', colors.yellow, args);
|
|
91
92
|
},
|
|
92
93
|
info: (...args) => {
|
|
93
|
-
log('info', green, args);
|
|
94
|
+
log('info', colors.green, args);
|
|
94
95
|
},
|
|
95
96
|
debug: (...args) => {
|
|
96
|
-
log('debug', blue, args);
|
|
97
|
+
log('debug', colors.blue, args);
|
|
97
98
|
},
|
|
98
99
|
};
|
|
99
100
|
|
|
@@ -230,7 +231,14 @@ class SubscriptionManager {
|
|
|
230
231
|
}
|
|
231
232
|
const { url } = this.clients.get(id);
|
|
232
233
|
logger.info(`[Subscription] Trigger ${id}`);
|
|
233
|
-
yield
|
|
234
|
+
const response = yield fetch(url, {
|
|
235
|
+
method: 'POST',
|
|
236
|
+
body: JSON.stringify(result),
|
|
237
|
+
headers: {
|
|
238
|
+
'Content-Type': 'application/json',
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
yield response.text();
|
|
234
242
|
});
|
|
235
243
|
}
|
|
236
244
|
buildOperations() {
|
|
@@ -264,7 +272,9 @@ class SubscriptionManager {
|
|
|
264
272
|
|
|
265
273
|
function createRouter(sofa) {
|
|
266
274
|
logger.debug('[Sofa] Creating router');
|
|
267
|
-
const router =
|
|
275
|
+
const router = Router({
|
|
276
|
+
base: sofa.basePath,
|
|
277
|
+
});
|
|
268
278
|
const queryType = sofa.schema.getQueryType();
|
|
269
279
|
const mutationType = sofa.schema.getMutationType();
|
|
270
280
|
const subscriptionManager = new SubscriptionManager(sofa);
|
|
@@ -284,92 +294,75 @@ function createRouter(sofa) {
|
|
|
284
294
|
}
|
|
285
295
|
});
|
|
286
296
|
}
|
|
287
|
-
router.post('/webhook', (
|
|
288
|
-
const { subscription, variables, url } =
|
|
297
|
+
router.post('/webhook', (request, contextValue) => __awaiter(this, void 0, void 0, function* () {
|
|
298
|
+
const { subscription, variables, url } = yield request.json();
|
|
289
299
|
try {
|
|
290
300
|
const result = yield subscriptionManager.start({
|
|
291
301
|
subscription,
|
|
292
302
|
variables,
|
|
293
303
|
url,
|
|
294
304
|
}, contextValue);
|
|
295
|
-
return {
|
|
296
|
-
type: 'result',
|
|
305
|
+
return new Response(JSON.stringify(result), {
|
|
297
306
|
status: 200,
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
307
|
+
statusText: 'OK',
|
|
308
|
+
headers: {
|
|
309
|
+
'Content-Type': 'application/json',
|
|
310
|
+
},
|
|
311
|
+
});
|
|
301
312
|
}
|
|
302
313
|
catch (error) {
|
|
303
|
-
return {
|
|
304
|
-
type: 'error',
|
|
314
|
+
return new Response(JSON.stringify(error), {
|
|
305
315
|
status: 500,
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
};
|
|
316
|
+
statusText: 'Subscription failed',
|
|
317
|
+
});
|
|
309
318
|
}
|
|
310
319
|
}));
|
|
311
|
-
router.post('/webhook/:id', (
|
|
312
|
-
|
|
320
|
+
router.post('/webhook/:id', (request, contextValue) => __awaiter(this, void 0, void 0, function* () {
|
|
321
|
+
var _a;
|
|
322
|
+
const id = (_a = request.params) === null || _a === void 0 ? void 0 : _a.id;
|
|
323
|
+
const body = yield request.json();
|
|
313
324
|
const variables = body.variables;
|
|
314
325
|
try {
|
|
315
326
|
const result = yield subscriptionManager.update({
|
|
316
327
|
id,
|
|
317
328
|
variables,
|
|
318
329
|
}, contextValue);
|
|
319
|
-
return {
|
|
320
|
-
type: 'result',
|
|
330
|
+
return new Response(JSON.stringify(result), {
|
|
321
331
|
status: 200,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
332
|
+
statusText: 'OK',
|
|
333
|
+
headers: {
|
|
334
|
+
'Content-Type': 'application/json',
|
|
335
|
+
},
|
|
336
|
+
});
|
|
325
337
|
}
|
|
326
338
|
catch (error) {
|
|
327
|
-
return {
|
|
328
|
-
type: 'error',
|
|
339
|
+
return new Response(JSON.stringify(error), {
|
|
329
340
|
status: 500,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
};
|
|
341
|
+
statusText: 'Subscription failed to update',
|
|
342
|
+
});
|
|
333
343
|
}
|
|
334
344
|
}));
|
|
335
|
-
router.delete('/webhook/:id', (
|
|
336
|
-
|
|
345
|
+
router.delete('/webhook/:id', (request) => __awaiter(this, void 0, void 0, function* () {
|
|
346
|
+
var _b;
|
|
347
|
+
const id = (_b = request.params) === null || _b === void 0 ? void 0 : _b.id;
|
|
337
348
|
try {
|
|
338
349
|
const result = yield subscriptionManager.stop(id);
|
|
339
|
-
return {
|
|
340
|
-
type: 'result',
|
|
350
|
+
return new Response(JSON.stringify(result), {
|
|
341
351
|
status: 200,
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
352
|
+
statusText: 'OK',
|
|
353
|
+
headers: {
|
|
354
|
+
'Content-Type': 'application/json',
|
|
355
|
+
},
|
|
356
|
+
});
|
|
345
357
|
}
|
|
346
358
|
catch (error) {
|
|
347
|
-
return {
|
|
348
|
-
type: 'error',
|
|
359
|
+
return new Response(JSON.stringify(error), {
|
|
349
360
|
status: 500,
|
|
350
|
-
|
|
351
|
-
error,
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
}));
|
|
355
|
-
return ({ method, url, body, contextValue }) => __awaiter(this, void 0, void 0, function* () {
|
|
356
|
-
if (!url.startsWith(sofa.basePath)) {
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
// trim base path and search
|
|
360
|
-
const [slicedUrl] = url.slice(sofa.basePath.length).split('?');
|
|
361
|
-
const trouterMethod = method.toUpperCase();
|
|
362
|
-
const obj = router.find(trouterMethod, slicedUrl);
|
|
363
|
-
for (const handler of obj.handlers) {
|
|
364
|
-
return yield handler({
|
|
365
|
-
url,
|
|
366
|
-
body,
|
|
367
|
-
params: obj.params,
|
|
368
|
-
contextValue,
|
|
361
|
+
statusText: 'Subscription failed to stop',
|
|
369
362
|
});
|
|
370
363
|
}
|
|
371
|
-
|
|
372
|
-
|
|
364
|
+
}));
|
|
365
|
+
return router;
|
|
373
366
|
}
|
|
374
367
|
function createQueryRoute({ sofa, router, fieldName, }) {
|
|
375
368
|
var _a, _b, _c, _d;
|
|
@@ -400,7 +393,7 @@ function createQueryRoute({ sofa, router, fieldName, }) {
|
|
|
400
393
|
path: (_c = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.path) !== null && _c !== void 0 ? _c : getPath(fieldName, isSingle && hasIdArgument),
|
|
401
394
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
402
395
|
};
|
|
403
|
-
router[route.method
|
|
396
|
+
router[route.method](route.path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
404
397
|
logger.debug(`[Router] ${fieldName} query available at ${route.method} ${route.path}`);
|
|
405
398
|
return {
|
|
406
399
|
document: operation,
|
|
@@ -433,7 +426,7 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
433
426
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
434
427
|
};
|
|
435
428
|
const { method, path } = route;
|
|
436
|
-
router[method
|
|
429
|
+
router[method](path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
437
430
|
logger.debug(`[Router] ${fieldName} mutation available at ${method} ${path}`);
|
|
438
431
|
return {
|
|
439
432
|
document: operation,
|
|
@@ -444,11 +437,24 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
444
437
|
function useHandler(config) {
|
|
445
438
|
const { sofa, operation, fieldName } = config;
|
|
446
439
|
const info = config.info;
|
|
447
|
-
return (
|
|
440
|
+
return (request, contextValue) => __awaiter(this, void 0, void 0, function* () {
|
|
441
|
+
var _a;
|
|
442
|
+
let body = {};
|
|
443
|
+
if (request.body != null) {
|
|
444
|
+
const strBody = yield request.text();
|
|
445
|
+
if (strBody) {
|
|
446
|
+
body = JSON.parse(strBody);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
448
449
|
const variableValues = info.variables.reduce((variables, variable) => {
|
|
449
450
|
const name = variable.variable.name.value;
|
|
450
451
|
const value = parseVariable({
|
|
451
|
-
value: pickParam({
|
|
452
|
+
value: pickParam({
|
|
453
|
+
url: request.url,
|
|
454
|
+
body,
|
|
455
|
+
params: request.params || {},
|
|
456
|
+
name,
|
|
457
|
+
}),
|
|
452
458
|
variable,
|
|
453
459
|
schema: sofa.schema,
|
|
454
460
|
});
|
|
@@ -466,27 +472,26 @@ function useHandler(config) {
|
|
|
466
472
|
});
|
|
467
473
|
if (result.errors) {
|
|
468
474
|
const defaultErrorHandler = (errors) => {
|
|
469
|
-
return {
|
|
470
|
-
type: 'error',
|
|
475
|
+
return new Response(errors[0], {
|
|
471
476
|
status: 500,
|
|
472
|
-
|
|
473
|
-
};
|
|
477
|
+
});
|
|
474
478
|
};
|
|
475
479
|
const errorHandler = sofa.errorHandler || defaultErrorHandler;
|
|
476
480
|
return errorHandler(result.errors);
|
|
477
481
|
}
|
|
478
|
-
return {
|
|
479
|
-
type: 'result',
|
|
482
|
+
return new Response(JSON.stringify((_a = result.data) === null || _a === void 0 ? void 0 : _a[fieldName]), {
|
|
480
483
|
status: config.route.responseStatus,
|
|
481
|
-
|
|
482
|
-
|
|
484
|
+
headers: {
|
|
485
|
+
'Content-Type': 'application/json',
|
|
486
|
+
},
|
|
487
|
+
});
|
|
483
488
|
});
|
|
484
489
|
}
|
|
485
490
|
function getPath(fieldName, hasId = false) {
|
|
486
491
|
return `/${convertName(fieldName)}${hasId ? '/:id' : ''}`;
|
|
487
492
|
}
|
|
488
493
|
function pickParam({ name, url, params, body, }) {
|
|
489
|
-
if (
|
|
494
|
+
if (name in params) {
|
|
490
495
|
return params[name];
|
|
491
496
|
}
|
|
492
497
|
const searchParams = new URLSearchParams(url.split('?')[1]);
|
|
@@ -553,24 +558,8 @@ function extractsModels(schema) {
|
|
|
553
558
|
}
|
|
554
559
|
// it's dumb but let's leave it for now
|
|
555
560
|
function isArrayOf(type, expected) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
if (isNonNullType(type) && isOptionalList(type.ofType)) {
|
|
560
|
-
return true;
|
|
561
|
-
}
|
|
562
|
-
function isOptionalList(list) {
|
|
563
|
-
if (isListType(list)) {
|
|
564
|
-
if (list.ofType.name === expected.name) {
|
|
565
|
-
return true;
|
|
566
|
-
}
|
|
567
|
-
if (isNonNullType(list.ofType) &&
|
|
568
|
-
list.ofType.ofType.name === expected.name) {
|
|
569
|
-
return true;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
return false;
|
|
561
|
+
const typeNameInSdl = type.toString();
|
|
562
|
+
return (typeNameInSdl.includes('[') && typeNameInSdl.includes(expected.toString()));
|
|
574
563
|
}
|
|
575
564
|
function hasID(type) {
|
|
576
565
|
return isObjectType(type) && !!type.getFields().id;
|
|
@@ -843,50 +832,10 @@ function isContextFn(context) {
|
|
|
843
832
|
return typeof context === 'function';
|
|
844
833
|
}
|
|
845
834
|
function useSofa(_a) {
|
|
846
|
-
var
|
|
847
|
-
const
|
|
848
|
-
return (
|
|
849
|
-
|
|
850
|
-
try {
|
|
851
|
-
let contextValue = { req };
|
|
852
|
-
if (context) {
|
|
853
|
-
if (typeof context === 'function') {
|
|
854
|
-
contextValue = yield context({ req, res });
|
|
855
|
-
}
|
|
856
|
-
else {
|
|
857
|
-
contextValue = context;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
const response = yield invokeSofa({
|
|
861
|
-
method: req.method,
|
|
862
|
-
url: (_b = req.originalUrl) !== null && _b !== void 0 ? _b : req.url,
|
|
863
|
-
body: req.body,
|
|
864
|
-
contextValue,
|
|
865
|
-
});
|
|
866
|
-
if (response == null) {
|
|
867
|
-
next();
|
|
868
|
-
}
|
|
869
|
-
else {
|
|
870
|
-
const headers = {
|
|
871
|
-
'Content-Type': 'application/json',
|
|
872
|
-
};
|
|
873
|
-
if (response.statusMessage) {
|
|
874
|
-
res.writeHead(response.status, response.statusMessage, headers);
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
res.writeHead(response.status, headers);
|
|
878
|
-
}
|
|
879
|
-
if (response.type === 'result') {
|
|
880
|
-
res.end(JSON.stringify(response.body));
|
|
881
|
-
}
|
|
882
|
-
if (response.type === 'error') {
|
|
883
|
-
res.end(JSON.stringify(response.error));
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
catch (error) {
|
|
888
|
-
next(error);
|
|
889
|
-
}
|
|
835
|
+
var config = __rest(_a, ["context"]);
|
|
836
|
+
const sofaRouter = createSofaRouter(config);
|
|
837
|
+
return createServerAdapter({
|
|
838
|
+
handleRequest: sofaRouter.handle,
|
|
890
839
|
});
|
|
891
840
|
}
|
|
892
841
|
function createSofaRouter(config) {
|
|
File without changes
|
|
@@ -9,8 +9,8 @@ export declare function OpenAPI({ schema, info, servers, components, security, t
|
|
|
9
9
|
tags?: Record<string, any>[];
|
|
10
10
|
}): {
|
|
11
11
|
addRoute(info: RouteInfo, config?: {
|
|
12
|
-
basePath?: string
|
|
13
|
-
}
|
|
12
|
+
basePath?: string;
|
|
13
|
+
}): void;
|
|
14
14
|
get(): any;
|
|
15
15
|
save(filepath: string): void;
|
|
16
16
|
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sofa-api",
|
|
3
|
+
"version": "0.11.1",
|
|
4
|
+
"description": "Create REST APIs with GraphQL",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"peerDependencies": {
|
|
7
|
+
"graphql": "^0.13.2 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@graphql-tools/utils": "8.8.0",
|
|
11
|
+
"@types/js-yaml": "4.0.5",
|
|
12
|
+
"@whatwg-node/fetch": "^0.0.2",
|
|
13
|
+
"@whatwg-node/server": "^0.0.2",
|
|
14
|
+
"ansi-colors": "4.1.3",
|
|
15
|
+
"itty-router": "^2.6.1",
|
|
16
|
+
"js-yaml": "4.1.0",
|
|
17
|
+
"param-case": "3.0.4",
|
|
18
|
+
"title-case": "3.0.3",
|
|
19
|
+
"trouter": "3.2.0",
|
|
20
|
+
"tslib": "2.4.0",
|
|
21
|
+
"uuid": "8.3.2"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "Urigo/sofa"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"api",
|
|
29
|
+
"rest",
|
|
30
|
+
"graphql",
|
|
31
|
+
"sofa"
|
|
32
|
+
],
|
|
33
|
+
"author": {
|
|
34
|
+
"name": "Uri Goldshtein",
|
|
35
|
+
"email": "uri.goldshtein@gmail.com",
|
|
36
|
+
"url": "https://github.com/Urigo"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"main": "index.js",
|
|
40
|
+
"module": "index.mjs",
|
|
41
|
+
"typings": "index.d.ts",
|
|
42
|
+
"typescript": {
|
|
43
|
+
"definition": "index.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"exports": {
|
|
46
|
+
".": {
|
|
47
|
+
"require": "./index.js",
|
|
48
|
+
"import": "./index.mjs"
|
|
49
|
+
},
|
|
50
|
+
"./*": {
|
|
51
|
+
"require": "./*.js",
|
|
52
|
+
"import": "./*.mjs"
|
|
53
|
+
},
|
|
54
|
+
"./package.json": "./package.json"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
File without changes
|
package/dist/router.d.ts
ADDED
|
@@ -20,19 +20,11 @@ export declare class SubscriptionManager {
|
|
|
20
20
|
private operations;
|
|
21
21
|
private clients;
|
|
22
22
|
constructor(sofa: Sofa);
|
|
23
|
-
start(event: StartSubscriptionEvent, contextValue: ContextValue): Promise<ExecutionResult<{
|
|
24
|
-
[key: string]: any;
|
|
25
|
-
}, {
|
|
26
|
-
[key: string]: any;
|
|
27
|
-
}> | {
|
|
23
|
+
start(event: StartSubscriptionEvent, contextValue: ContextValue): Promise<ExecutionResult<import("graphql/jsutils/ObjMap").ObjMap<unknown>, import("graphql/jsutils/ObjMap").ObjMap<unknown>> | {
|
|
28
24
|
id: string;
|
|
29
25
|
}>;
|
|
30
26
|
stop(id: ID): Promise<StopSubscriptionResponse>;
|
|
31
|
-
update(event: UpdateSubscriptionEvent, contextValue: ContextValue): Promise<ExecutionResult<{
|
|
32
|
-
[key: string]: any;
|
|
33
|
-
}, {
|
|
34
|
-
[key: string]: any;
|
|
35
|
-
}> | {
|
|
27
|
+
update(event: UpdateSubscriptionEvent, contextValue: ContextValue): Promise<ExecutionResult<import("graphql/jsutils/ObjMap").ObjMap<unknown>, import("graphql/jsutils/ObjMap").ObjMap<unknown>> | {
|
|
36
28
|
id: string;
|
|
37
29
|
}>;
|
|
38
30
|
private execute;
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,53 +1,108 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sofa-api",
|
|
3
|
-
"version": "0.11.0",
|
|
4
3
|
"description": "Create REST APIs with GraphQL",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
4
|
+
"version": "0.11.2-alpha.0",
|
|
5
|
+
"buildOptions": {
|
|
6
|
+
"input": "./src/index.ts"
|
|
8
7
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"module": "dist/index.mjs",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"require": "./dist/index.js",
|
|
14
|
+
"import": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"./*": {
|
|
17
|
+
"require": "./dist/*.js",
|
|
18
|
+
"import": "./dist/*.mjs"
|
|
19
|
+
}
|
|
20
20
|
},
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"
|
|
21
|
+
"typings": "dist/index.d.ts",
|
|
22
|
+
"typescript": {
|
|
23
|
+
"definition": "dist/index.d.ts"
|
|
24
24
|
},
|
|
25
|
+
"license": "MIT",
|
|
25
26
|
"keywords": [
|
|
26
27
|
"api",
|
|
27
28
|
"rest",
|
|
28
29
|
"graphql",
|
|
29
30
|
"sofa"
|
|
30
31
|
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "Urigo/sofa"
|
|
35
|
+
},
|
|
31
36
|
"author": {
|
|
32
37
|
"name": "Uri Goldshtein",
|
|
33
38
|
"email": "uri.goldshtein@gmail.com",
|
|
34
39
|
"url": "https://github.com/Urigo"
|
|
35
40
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
"module": "index.mjs",
|
|
39
|
-
"typings": "index.d.ts",
|
|
40
|
-
"typescript": {
|
|
41
|
-
"definition": "index.d.ts"
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"graphql": "^0.13.2 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
42
43
|
},
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@graphql-tools/utils": "8.12.0",
|
|
46
|
+
"ansi-colors": "4.1.3",
|
|
47
|
+
"@whatwg-node/fetch": "^0.4.3",
|
|
48
|
+
"@whatwg-node/server": "^0.4.1",
|
|
49
|
+
"itty-router": "^2.6.1",
|
|
50
|
+
"param-case": "3.0.4",
|
|
51
|
+
"title-case": "3.0.3",
|
|
52
|
+
"tslib": "2.4.0",
|
|
53
|
+
"uuid": "8.3.2"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"start": "ts-node --project tsconfig.example.json example/index.ts",
|
|
57
|
+
"clean": "rm -rf dist",
|
|
58
|
+
"prebuild": "yarn clean",
|
|
59
|
+
"build": "bob build --single",
|
|
60
|
+
"test": "jest --no-watchman",
|
|
61
|
+
"prepare-release": "yarn build && yarn test",
|
|
62
|
+
"release": "yarn prepare-release && bob prepack && npm publish dist",
|
|
63
|
+
"ci:release:canary": "node bump.js && bob prepack && npm publish dist --tag alpha --access public",
|
|
64
|
+
"postinstall": "husky install"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@graphql-tools/schema": "9.0.4",
|
|
68
|
+
"@graphql-yoga/node": "2.13.13",
|
|
69
|
+
"@types/jest": "28.1.8",
|
|
70
|
+
"@types/node": "14.18.29",
|
|
71
|
+
"@types/swagger-ui-dist": "3.30.1",
|
|
72
|
+
"@types/uuid": "8.3.4",
|
|
73
|
+
"@types/yamljs": "0.2.31",
|
|
74
|
+
"bob-the-bundler": "1.7.3",
|
|
75
|
+
"bundlesize": "0.18.1",
|
|
76
|
+
"chalk": "^4",
|
|
77
|
+
"express": "4.18.1",
|
|
78
|
+
"express-graphql": "0.12.0",
|
|
79
|
+
"graphql": "16.6.0",
|
|
80
|
+
"graphql-subscriptions": "2.0.0",
|
|
81
|
+
"husky": "8.0.1",
|
|
82
|
+
"jest": "28.1.3",
|
|
83
|
+
"lint-staged": "13.0.3",
|
|
84
|
+
"prettier": "2.7.1",
|
|
85
|
+
"supertest": "6.2.4",
|
|
86
|
+
"swagger-ui-dist": "4.14.0",
|
|
87
|
+
"ts-jest": "28.0.8",
|
|
88
|
+
"ts-node": "10.9.1",
|
|
89
|
+
"typescript": "4.7.4"
|
|
90
|
+
},
|
|
91
|
+
"husky": {
|
|
92
|
+
"hooks": {
|
|
93
|
+
"pre-commit": "lint-staged"
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"lint-staged": {
|
|
97
|
+
"*.{ts,js,md,json}": [
|
|
98
|
+
"prettier --write"
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"bundlesize": [
|
|
102
|
+
{
|
|
103
|
+
"path": "./dist/index.mjs",
|
|
104
|
+
"maxSize": "36 kB",
|
|
105
|
+
"compression": "none"
|
|
51
106
|
}
|
|
52
|
-
|
|
53
|
-
}
|
|
107
|
+
]
|
|
108
|
+
}
|
package/express.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { Sofa } from './sofa';
|
|
2
|
-
import type { ContextValue } from './types';
|
|
3
|
-
export declare type ErrorHandler = (errors: ReadonlyArray<any>) => RouterError;
|
|
4
|
-
declare type RouterRequest = {
|
|
5
|
-
method: string;
|
|
6
|
-
url: string;
|
|
7
|
-
body: any;
|
|
8
|
-
contextValue: ContextValue;
|
|
9
|
-
};
|
|
10
|
-
declare type RouterResult = {
|
|
11
|
-
type: 'result';
|
|
12
|
-
status: number;
|
|
13
|
-
statusMessage?: string;
|
|
14
|
-
body: any;
|
|
15
|
-
};
|
|
16
|
-
declare type RouterError = {
|
|
17
|
-
type: 'error';
|
|
18
|
-
status: number;
|
|
19
|
-
statusMessage?: string;
|
|
20
|
-
error: any;
|
|
21
|
-
};
|
|
22
|
-
declare type RouterResponse = RouterResult | RouterError;
|
|
23
|
-
declare type Router = (request: RouterRequest) => Promise<null | RouterResponse>;
|
|
24
|
-
export declare function createRouter(sofa: Sofa): Router;
|
|
25
|
-
export {};
|
package/index.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import * as http from 'http';
|
|
3
|
-
import type { ContextValue } from './types';
|
|
4
|
-
import type { SofaConfig } from './sofa';
|
|
5
|
-
export { OpenAPI } from './open-api';
|
|
6
|
-
declare type Request = http.IncomingMessage & {
|
|
7
|
-
method: string;
|
|
8
|
-
url: string;
|
|
9
|
-
originalUrl?: string;
|
|
10
|
-
body?: any;
|
|
11
|
-
};
|
|
12
|
-
declare type NextFunction = (err?: any) => void;
|
|
13
|
-
declare type Middleware = (req: Request, res: http.ServerResponse, next: NextFunction) => unknown;
|
|
14
|
-
export declare type ContextFn = (init: {
|
|
15
|
-
req: any;
|
|
16
|
-
res: any;
|
|
17
|
-
}) => ContextValue;
|
|
18
|
-
export declare function isContextFn(context: any): context is ContextFn;
|
|
19
|
-
interface SofaMiddlewareConfig extends SofaConfig {
|
|
20
|
-
context?: ContextValue | ContextFn;
|
|
21
|
-
}
|
|
22
|
-
export declare function useSofa({ context, ...config }: SofaMiddlewareConfig): Middleware;
|
|
23
|
-
export declare function createSofaRouter(config: SofaConfig): (request: {
|
|
24
|
-
method: string;
|
|
25
|
-
url: string;
|
|
26
|
-
body: any;
|
|
27
|
-
contextValue: ContextValue;
|
|
28
|
-
}) => Promise<({
|
|
29
|
-
type: "result";
|
|
30
|
-
status: number;
|
|
31
|
-
statusMessage?: string | undefined;
|
|
32
|
-
body: any;
|
|
33
|
-
} | {
|
|
34
|
-
type: "error";
|
|
35
|
-
status: number;
|
|
36
|
-
statusMessage?: string | undefined;
|
|
37
|
-
error: any;
|
|
38
|
-
}) | null>;
|
package/open-api/types.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { GraphQLObjectType, GraphQLInputObjectType, GraphQLOutputType, GraphQLNamedType } from 'graphql';
|
|
2
|
-
export declare function buildSchemaObjectFromType(type: GraphQLObjectType | GraphQLInputObjectType): any;
|
|
3
|
-
export declare function resolveFieldType(type: GraphQLOutputType | GraphQLNamedType): any;
|