sofa-api 0.11.1 → 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} +76 -134
- package/{index.mjs → dist/index.mjs} +79 -137
- 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,7 @@ class SubscriptionManager {
|
|
|
236
237
|
}
|
|
237
238
|
const { url } = this.clients.get(id);
|
|
238
239
|
logger.info(`[Subscription] Trigger ${id}`);
|
|
239
|
-
const response = yield
|
|
240
|
+
const response = yield fetch.fetch(url, {
|
|
240
241
|
method: 'POST',
|
|
241
242
|
body: JSON.stringify(result),
|
|
242
243
|
headers: {
|
|
@@ -277,7 +278,9 @@ class SubscriptionManager {
|
|
|
277
278
|
|
|
278
279
|
function createRouter(sofa) {
|
|
279
280
|
logger.debug('[Sofa] Creating router');
|
|
280
|
-
const router =
|
|
281
|
+
const router = ittyRouter.Router({
|
|
282
|
+
base: sofa.basePath,
|
|
283
|
+
});
|
|
281
284
|
const queryType = sofa.schema.getQueryType();
|
|
282
285
|
const mutationType = sofa.schema.getMutationType();
|
|
283
286
|
const subscriptionManager = new SubscriptionManager(sofa);
|
|
@@ -297,92 +300,75 @@ function createRouter(sofa) {
|
|
|
297
300
|
}
|
|
298
301
|
});
|
|
299
302
|
}
|
|
300
|
-
router.post('/webhook', (
|
|
301
|
-
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();
|
|
302
305
|
try {
|
|
303
306
|
const result = yield subscriptionManager.start({
|
|
304
307
|
subscription,
|
|
305
308
|
variables,
|
|
306
309
|
url,
|
|
307
310
|
}, contextValue);
|
|
308
|
-
return {
|
|
309
|
-
type: 'result',
|
|
311
|
+
return new fetch.Response(JSON.stringify(result), {
|
|
310
312
|
status: 200,
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
313
|
+
statusText: 'OK',
|
|
314
|
+
headers: {
|
|
315
|
+
'Content-Type': 'application/json',
|
|
316
|
+
},
|
|
317
|
+
});
|
|
314
318
|
}
|
|
315
319
|
catch (error) {
|
|
316
|
-
return {
|
|
317
|
-
type: 'error',
|
|
320
|
+
return new fetch.Response(JSON.stringify(error), {
|
|
318
321
|
status: 500,
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
};
|
|
322
|
+
statusText: 'Subscription failed',
|
|
323
|
+
});
|
|
322
324
|
}
|
|
323
325
|
}));
|
|
324
|
-
router.post('/webhook/:id', (
|
|
325
|
-
|
|
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();
|
|
326
330
|
const variables = body.variables;
|
|
327
331
|
try {
|
|
328
332
|
const result = yield subscriptionManager.update({
|
|
329
333
|
id,
|
|
330
334
|
variables,
|
|
331
335
|
}, contextValue);
|
|
332
|
-
return {
|
|
333
|
-
type: 'result',
|
|
336
|
+
return new fetch.Response(JSON.stringify(result), {
|
|
334
337
|
status: 200,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
+
statusText: 'OK',
|
|
339
|
+
headers: {
|
|
340
|
+
'Content-Type': 'application/json',
|
|
341
|
+
},
|
|
342
|
+
});
|
|
338
343
|
}
|
|
339
344
|
catch (error) {
|
|
340
|
-
return {
|
|
341
|
-
type: 'error',
|
|
345
|
+
return new fetch.Response(JSON.stringify(error), {
|
|
342
346
|
status: 500,
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
};
|
|
347
|
+
statusText: 'Subscription failed to update',
|
|
348
|
+
});
|
|
346
349
|
}
|
|
347
350
|
}));
|
|
348
|
-
router.delete('/webhook/:id', (
|
|
349
|
-
|
|
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;
|
|
350
354
|
try {
|
|
351
355
|
const result = yield subscriptionManager.stop(id);
|
|
352
|
-
return {
|
|
353
|
-
type: 'result',
|
|
356
|
+
return new fetch.Response(JSON.stringify(result), {
|
|
354
357
|
status: 200,
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
+
statusText: 'OK',
|
|
359
|
+
headers: {
|
|
360
|
+
'Content-Type': 'application/json',
|
|
361
|
+
},
|
|
362
|
+
});
|
|
358
363
|
}
|
|
359
364
|
catch (error) {
|
|
360
|
-
return {
|
|
361
|
-
type: 'error',
|
|
365
|
+
return new fetch.Response(JSON.stringify(error), {
|
|
362
366
|
status: 500,
|
|
363
|
-
|
|
364
|
-
error,
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
}));
|
|
368
|
-
return ({ method, url, body, contextValue }) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
369
|
-
if (!url.startsWith(sofa.basePath)) {
|
|
370
|
-
return null;
|
|
371
|
-
}
|
|
372
|
-
// trim base path and search
|
|
373
|
-
const [slicedUrl] = url.slice(sofa.basePath.length).split('?');
|
|
374
|
-
const trouterMethod = method.toUpperCase();
|
|
375
|
-
const obj = router.find(trouterMethod, slicedUrl);
|
|
376
|
-
for (const handler of obj.handlers) {
|
|
377
|
-
return yield handler({
|
|
378
|
-
url,
|
|
379
|
-
body,
|
|
380
|
-
params: obj.params,
|
|
381
|
-
contextValue,
|
|
367
|
+
statusText: 'Subscription failed to stop',
|
|
382
368
|
});
|
|
383
369
|
}
|
|
384
|
-
|
|
385
|
-
|
|
370
|
+
}));
|
|
371
|
+
return router;
|
|
386
372
|
}
|
|
387
373
|
function createQueryRoute({ sofa, router, fieldName, }) {
|
|
388
374
|
var _a, _b, _c, _d;
|
|
@@ -413,7 +399,7 @@ function createQueryRoute({ sofa, router, fieldName, }) {
|
|
|
413
399
|
path: (_c = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.path) !== null && _c !== void 0 ? _c : getPath(fieldName, isSingle && hasIdArgument),
|
|
414
400
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
415
401
|
};
|
|
416
|
-
router[route.method
|
|
402
|
+
router[route.method](route.path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
417
403
|
logger.debug(`[Router] ${fieldName} query available at ${route.method} ${route.path}`);
|
|
418
404
|
return {
|
|
419
405
|
document: operation,
|
|
@@ -446,7 +432,7 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
446
432
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
447
433
|
};
|
|
448
434
|
const { method, path } = route;
|
|
449
|
-
router[method
|
|
435
|
+
router[method](path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
450
436
|
logger.debug(`[Router] ${fieldName} mutation available at ${method} ${path}`);
|
|
451
437
|
return {
|
|
452
438
|
document: operation,
|
|
@@ -457,11 +443,24 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
457
443
|
function useHandler(config) {
|
|
458
444
|
const { sofa, operation, fieldName } = config;
|
|
459
445
|
const info = config.info;
|
|
460
|
-
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
|
+
}
|
|
461
455
|
const variableValues = info.variables.reduce((variables, variable) => {
|
|
462
456
|
const name = variable.variable.name.value;
|
|
463
457
|
const value = parseVariable({
|
|
464
|
-
value: pickParam({
|
|
458
|
+
value: pickParam({
|
|
459
|
+
url: request.url,
|
|
460
|
+
body,
|
|
461
|
+
params: request.params || {},
|
|
462
|
+
name,
|
|
463
|
+
}),
|
|
465
464
|
variable,
|
|
466
465
|
schema: sofa.schema,
|
|
467
466
|
});
|
|
@@ -479,27 +478,26 @@ function useHandler(config) {
|
|
|
479
478
|
});
|
|
480
479
|
if (result.errors) {
|
|
481
480
|
const defaultErrorHandler = (errors) => {
|
|
482
|
-
return {
|
|
483
|
-
type: 'error',
|
|
481
|
+
return new fetch.Response(errors[0], {
|
|
484
482
|
status: 500,
|
|
485
|
-
|
|
486
|
-
};
|
|
483
|
+
});
|
|
487
484
|
};
|
|
488
485
|
const errorHandler = sofa.errorHandler || defaultErrorHandler;
|
|
489
486
|
return errorHandler(result.errors);
|
|
490
487
|
}
|
|
491
|
-
return {
|
|
492
|
-
type: 'result',
|
|
488
|
+
return new fetch.Response(JSON.stringify((_a = result.data) === null || _a === void 0 ? void 0 : _a[fieldName]), {
|
|
493
489
|
status: config.route.responseStatus,
|
|
494
|
-
|
|
495
|
-
|
|
490
|
+
headers: {
|
|
491
|
+
'Content-Type': 'application/json',
|
|
492
|
+
},
|
|
493
|
+
});
|
|
496
494
|
});
|
|
497
495
|
}
|
|
498
496
|
function getPath(fieldName, hasId = false) {
|
|
499
497
|
return `/${convertName(fieldName)}${hasId ? '/:id' : ''}`;
|
|
500
498
|
}
|
|
501
499
|
function pickParam({ name, url, params, body, }) {
|
|
502
|
-
if (
|
|
500
|
+
if (name in params) {
|
|
503
501
|
return params[name];
|
|
504
502
|
}
|
|
505
503
|
const searchParams = new URLSearchParams(url.split('?')[1]);
|
|
@@ -566,24 +564,8 @@ function extractsModels(schema) {
|
|
|
566
564
|
}
|
|
567
565
|
// it's dumb but let's leave it for now
|
|
568
566
|
function isArrayOf(type, expected) {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
if (graphql.isNonNullType(type) && isOptionalList(type.ofType)) {
|
|
573
|
-
return true;
|
|
574
|
-
}
|
|
575
|
-
function isOptionalList(list) {
|
|
576
|
-
if (graphql.isListType(list)) {
|
|
577
|
-
if (list.ofType.name === expected.name) {
|
|
578
|
-
return true;
|
|
579
|
-
}
|
|
580
|
-
if (graphql.isNonNullType(list.ofType) &&
|
|
581
|
-
list.ofType.ofType.name === expected.name) {
|
|
582
|
-
return true;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return false;
|
|
567
|
+
const typeNameInSdl = type.toString();
|
|
568
|
+
return (typeNameInSdl.includes('[') && typeNameInSdl.includes(expected.toString()));
|
|
587
569
|
}
|
|
588
570
|
function hasID(type) {
|
|
589
571
|
return graphql.isObjectType(type) && !!type.getFields().id;
|
|
@@ -856,50 +838,10 @@ function isContextFn(context) {
|
|
|
856
838
|
return typeof context === 'function';
|
|
857
839
|
}
|
|
858
840
|
function useSofa(_a) {
|
|
859
|
-
var
|
|
860
|
-
const
|
|
861
|
-
return
|
|
862
|
-
|
|
863
|
-
try {
|
|
864
|
-
let contextValue = { req };
|
|
865
|
-
if (context) {
|
|
866
|
-
if (typeof context === 'function') {
|
|
867
|
-
contextValue = yield context({ req, res });
|
|
868
|
-
}
|
|
869
|
-
else {
|
|
870
|
-
contextValue = context;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
const response = yield invokeSofa({
|
|
874
|
-
method: req.method,
|
|
875
|
-
url: (_b = req.originalUrl) !== null && _b !== void 0 ? _b : req.url,
|
|
876
|
-
body: req.body,
|
|
877
|
-
contextValue,
|
|
878
|
-
});
|
|
879
|
-
if (response == null) {
|
|
880
|
-
next();
|
|
881
|
-
}
|
|
882
|
-
else {
|
|
883
|
-
const headers = {
|
|
884
|
-
'Content-Type': 'application/json',
|
|
885
|
-
};
|
|
886
|
-
if (response.statusMessage) {
|
|
887
|
-
res.writeHead(response.status, response.statusMessage, headers);
|
|
888
|
-
}
|
|
889
|
-
else {
|
|
890
|
-
res.writeHead(response.status, headers);
|
|
891
|
-
}
|
|
892
|
-
if (response.type === 'result') {
|
|
893
|
-
res.end(JSON.stringify(response.body));
|
|
894
|
-
}
|
|
895
|
-
if (response.type === 'error') {
|
|
896
|
-
res.end(JSON.stringify(response.error));
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
catch (error) {
|
|
901
|
-
next(error);
|
|
902
|
-
}
|
|
841
|
+
var config = tslib.__rest(_a, ["context"]);
|
|
842
|
+
const sofaRouter = createSofaRouter(config);
|
|
843
|
+
return server.createServerAdapter({
|
|
844
|
+
handleRequest: sofaRouter.handle,
|
|
903
845
|
});
|
|
904
846
|
}
|
|
905
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 { fetch } from '
|
|
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
|
|
|
@@ -271,7 +272,9 @@ class SubscriptionManager {
|
|
|
271
272
|
|
|
272
273
|
function createRouter(sofa) {
|
|
273
274
|
logger.debug('[Sofa] Creating router');
|
|
274
|
-
const router =
|
|
275
|
+
const router = Router({
|
|
276
|
+
base: sofa.basePath,
|
|
277
|
+
});
|
|
275
278
|
const queryType = sofa.schema.getQueryType();
|
|
276
279
|
const mutationType = sofa.schema.getMutationType();
|
|
277
280
|
const subscriptionManager = new SubscriptionManager(sofa);
|
|
@@ -291,92 +294,75 @@ function createRouter(sofa) {
|
|
|
291
294
|
}
|
|
292
295
|
});
|
|
293
296
|
}
|
|
294
|
-
router.post('/webhook', (
|
|
295
|
-
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();
|
|
296
299
|
try {
|
|
297
300
|
const result = yield subscriptionManager.start({
|
|
298
301
|
subscription,
|
|
299
302
|
variables,
|
|
300
303
|
url,
|
|
301
304
|
}, contextValue);
|
|
302
|
-
return {
|
|
303
|
-
type: 'result',
|
|
305
|
+
return new Response(JSON.stringify(result), {
|
|
304
306
|
status: 200,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
307
|
+
statusText: 'OK',
|
|
308
|
+
headers: {
|
|
309
|
+
'Content-Type': 'application/json',
|
|
310
|
+
},
|
|
311
|
+
});
|
|
308
312
|
}
|
|
309
313
|
catch (error) {
|
|
310
|
-
return {
|
|
311
|
-
type: 'error',
|
|
314
|
+
return new Response(JSON.stringify(error), {
|
|
312
315
|
status: 500,
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
};
|
|
316
|
+
statusText: 'Subscription failed',
|
|
317
|
+
});
|
|
316
318
|
}
|
|
317
319
|
}));
|
|
318
|
-
router.post('/webhook/:id', (
|
|
319
|
-
|
|
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();
|
|
320
324
|
const variables = body.variables;
|
|
321
325
|
try {
|
|
322
326
|
const result = yield subscriptionManager.update({
|
|
323
327
|
id,
|
|
324
328
|
variables,
|
|
325
329
|
}, contextValue);
|
|
326
|
-
return {
|
|
327
|
-
type: 'result',
|
|
330
|
+
return new Response(JSON.stringify(result), {
|
|
328
331
|
status: 200,
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
statusText: 'OK',
|
|
333
|
+
headers: {
|
|
334
|
+
'Content-Type': 'application/json',
|
|
335
|
+
},
|
|
336
|
+
});
|
|
332
337
|
}
|
|
333
338
|
catch (error) {
|
|
334
|
-
return {
|
|
335
|
-
type: 'error',
|
|
339
|
+
return new Response(JSON.stringify(error), {
|
|
336
340
|
status: 500,
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
};
|
|
341
|
+
statusText: 'Subscription failed to update',
|
|
342
|
+
});
|
|
340
343
|
}
|
|
341
344
|
}));
|
|
342
|
-
router.delete('/webhook/:id', (
|
|
343
|
-
|
|
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;
|
|
344
348
|
try {
|
|
345
349
|
const result = yield subscriptionManager.stop(id);
|
|
346
|
-
return {
|
|
347
|
-
type: 'result',
|
|
350
|
+
return new Response(JSON.stringify(result), {
|
|
348
351
|
status: 200,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
+
statusText: 'OK',
|
|
353
|
+
headers: {
|
|
354
|
+
'Content-Type': 'application/json',
|
|
355
|
+
},
|
|
356
|
+
});
|
|
352
357
|
}
|
|
353
358
|
catch (error) {
|
|
354
|
-
return {
|
|
355
|
-
type: 'error',
|
|
359
|
+
return new Response(JSON.stringify(error), {
|
|
356
360
|
status: 500,
|
|
357
|
-
|
|
358
|
-
error,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
}));
|
|
362
|
-
return ({ method, url, body, contextValue }) => __awaiter(this, void 0, void 0, function* () {
|
|
363
|
-
if (!url.startsWith(sofa.basePath)) {
|
|
364
|
-
return null;
|
|
365
|
-
}
|
|
366
|
-
// trim base path and search
|
|
367
|
-
const [slicedUrl] = url.slice(sofa.basePath.length).split('?');
|
|
368
|
-
const trouterMethod = method.toUpperCase();
|
|
369
|
-
const obj = router.find(trouterMethod, slicedUrl);
|
|
370
|
-
for (const handler of obj.handlers) {
|
|
371
|
-
return yield handler({
|
|
372
|
-
url,
|
|
373
|
-
body,
|
|
374
|
-
params: obj.params,
|
|
375
|
-
contextValue,
|
|
361
|
+
statusText: 'Subscription failed to stop',
|
|
376
362
|
});
|
|
377
363
|
}
|
|
378
|
-
|
|
379
|
-
|
|
364
|
+
}));
|
|
365
|
+
return router;
|
|
380
366
|
}
|
|
381
367
|
function createQueryRoute({ sofa, router, fieldName, }) {
|
|
382
368
|
var _a, _b, _c, _d;
|
|
@@ -407,7 +393,7 @@ function createQueryRoute({ sofa, router, fieldName, }) {
|
|
|
407
393
|
path: (_c = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.path) !== null && _c !== void 0 ? _c : getPath(fieldName, isSingle && hasIdArgument),
|
|
408
394
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
409
395
|
};
|
|
410
|
-
router[route.method
|
|
396
|
+
router[route.method](route.path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
411
397
|
logger.debug(`[Router] ${fieldName} query available at ${route.method} ${route.path}`);
|
|
412
398
|
return {
|
|
413
399
|
document: operation,
|
|
@@ -440,7 +426,7 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
440
426
|
responseStatus: (_d = routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.responseStatus) !== null && _d !== void 0 ? _d : 200,
|
|
441
427
|
};
|
|
442
428
|
const { method, path } = route;
|
|
443
|
-
router[method
|
|
429
|
+
router[method](path, useHandler({ info, route, fieldName, sofa, operation }));
|
|
444
430
|
logger.debug(`[Router] ${fieldName} mutation available at ${method} ${path}`);
|
|
445
431
|
return {
|
|
446
432
|
document: operation,
|
|
@@ -451,11 +437,24 @@ function createMutationRoute({ sofa, router, fieldName, }) {
|
|
|
451
437
|
function useHandler(config) {
|
|
452
438
|
const { sofa, operation, fieldName } = config;
|
|
453
439
|
const info = config.info;
|
|
454
|
-
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
|
+
}
|
|
455
449
|
const variableValues = info.variables.reduce((variables, variable) => {
|
|
456
450
|
const name = variable.variable.name.value;
|
|
457
451
|
const value = parseVariable({
|
|
458
|
-
value: pickParam({
|
|
452
|
+
value: pickParam({
|
|
453
|
+
url: request.url,
|
|
454
|
+
body,
|
|
455
|
+
params: request.params || {},
|
|
456
|
+
name,
|
|
457
|
+
}),
|
|
459
458
|
variable,
|
|
460
459
|
schema: sofa.schema,
|
|
461
460
|
});
|
|
@@ -473,27 +472,26 @@ function useHandler(config) {
|
|
|
473
472
|
});
|
|
474
473
|
if (result.errors) {
|
|
475
474
|
const defaultErrorHandler = (errors) => {
|
|
476
|
-
return {
|
|
477
|
-
type: 'error',
|
|
475
|
+
return new Response(errors[0], {
|
|
478
476
|
status: 500,
|
|
479
|
-
|
|
480
|
-
};
|
|
477
|
+
});
|
|
481
478
|
};
|
|
482
479
|
const errorHandler = sofa.errorHandler || defaultErrorHandler;
|
|
483
480
|
return errorHandler(result.errors);
|
|
484
481
|
}
|
|
485
|
-
return {
|
|
486
|
-
type: 'result',
|
|
482
|
+
return new Response(JSON.stringify((_a = result.data) === null || _a === void 0 ? void 0 : _a[fieldName]), {
|
|
487
483
|
status: config.route.responseStatus,
|
|
488
|
-
|
|
489
|
-
|
|
484
|
+
headers: {
|
|
485
|
+
'Content-Type': 'application/json',
|
|
486
|
+
},
|
|
487
|
+
});
|
|
490
488
|
});
|
|
491
489
|
}
|
|
492
490
|
function getPath(fieldName, hasId = false) {
|
|
493
491
|
return `/${convertName(fieldName)}${hasId ? '/:id' : ''}`;
|
|
494
492
|
}
|
|
495
493
|
function pickParam({ name, url, params, body, }) {
|
|
496
|
-
if (
|
|
494
|
+
if (name in params) {
|
|
497
495
|
return params[name];
|
|
498
496
|
}
|
|
499
497
|
const searchParams = new URLSearchParams(url.split('?')[1]);
|
|
@@ -560,24 +558,8 @@ function extractsModels(schema) {
|
|
|
560
558
|
}
|
|
561
559
|
// it's dumb but let's leave it for now
|
|
562
560
|
function isArrayOf(type, expected) {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
}
|
|
566
|
-
if (isNonNullType(type) && isOptionalList(type.ofType)) {
|
|
567
|
-
return true;
|
|
568
|
-
}
|
|
569
|
-
function isOptionalList(list) {
|
|
570
|
-
if (isListType(list)) {
|
|
571
|
-
if (list.ofType.name === expected.name) {
|
|
572
|
-
return true;
|
|
573
|
-
}
|
|
574
|
-
if (isNonNullType(list.ofType) &&
|
|
575
|
-
list.ofType.ofType.name === expected.name) {
|
|
576
|
-
return true;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
return false;
|
|
561
|
+
const typeNameInSdl = type.toString();
|
|
562
|
+
return (typeNameInSdl.includes('[') && typeNameInSdl.includes(expected.toString()));
|
|
581
563
|
}
|
|
582
564
|
function hasID(type) {
|
|
583
565
|
return isObjectType(type) && !!type.getFields().id;
|
|
@@ -850,50 +832,10 @@ function isContextFn(context) {
|
|
|
850
832
|
return typeof context === 'function';
|
|
851
833
|
}
|
|
852
834
|
function useSofa(_a) {
|
|
853
|
-
var
|
|
854
|
-
const
|
|
855
|
-
return (
|
|
856
|
-
|
|
857
|
-
try {
|
|
858
|
-
let contextValue = { req };
|
|
859
|
-
if (context) {
|
|
860
|
-
if (typeof context === 'function') {
|
|
861
|
-
contextValue = yield context({ req, res });
|
|
862
|
-
}
|
|
863
|
-
else {
|
|
864
|
-
contextValue = context;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
const response = yield invokeSofa({
|
|
868
|
-
method: req.method,
|
|
869
|
-
url: (_b = req.originalUrl) !== null && _b !== void 0 ? _b : req.url,
|
|
870
|
-
body: req.body,
|
|
871
|
-
contextValue,
|
|
872
|
-
});
|
|
873
|
-
if (response == null) {
|
|
874
|
-
next();
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
const headers = {
|
|
878
|
-
'Content-Type': 'application/json',
|
|
879
|
-
};
|
|
880
|
-
if (response.statusMessage) {
|
|
881
|
-
res.writeHead(response.status, response.statusMessage, headers);
|
|
882
|
-
}
|
|
883
|
-
else {
|
|
884
|
-
res.writeHead(response.status, headers);
|
|
885
|
-
}
|
|
886
|
-
if (response.type === 'result') {
|
|
887
|
-
res.end(JSON.stringify(response.body));
|
|
888
|
-
}
|
|
889
|
-
if (response.type === 'error') {
|
|
890
|
-
res.end(JSON.stringify(response.error));
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
catch (error) {
|
|
895
|
-
next(error);
|
|
896
|
-
}
|
|
835
|
+
var config = __rest(_a, ["context"]);
|
|
836
|
+
const sofaRouter = createSofaRouter(config);
|
|
837
|
+
return createServerAdapter({
|
|
838
|
+
handleRequest: sofaRouter.handle,
|
|
897
839
|
});
|
|
898
840
|
}
|
|
899
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.1",
|
|
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;
|