@steedos/service-api 2.6.1-beta.7 → 2.6.2-beta.2
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/index.js +59 -21
- package/package.json +6 -6
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const { LRUMap } = require('lru_map');
|
|
|
18
18
|
const validator = require('validator');
|
|
19
19
|
const enablePlayground = validator.toBoolean(process.env.STEEDOS_GRAPHQL_ENABLE_CONSOLE || 'true', true);
|
|
20
20
|
const openBrowser = require('react-dev-utils/openBrowser');
|
|
21
|
+
const requestIp = require('request-ip');
|
|
21
22
|
const mixinOptions = {
|
|
22
23
|
|
|
23
24
|
// Global GraphQL typeDefs
|
|
@@ -86,7 +87,7 @@ const mixinOptions = {
|
|
|
86
87
|
introspection: enablePlayground
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
|
-
|
|
90
|
+
const ObjectDataLoaderMapKeys = {};
|
|
90
91
|
/**
|
|
91
92
|
* @typedef {import('moleculer').Context} Context Moleculer's Context
|
|
92
93
|
* @typedef {import('http').IncomingMessage} IncomingRequest Incoming HTTP Request
|
|
@@ -94,7 +95,6 @@ const mixinOptions = {
|
|
|
94
95
|
*/
|
|
95
96
|
module.exports = {
|
|
96
97
|
name: "api",
|
|
97
|
-
projectStarted: false,
|
|
98
98
|
mixins: [ApiGateway,
|
|
99
99
|
// GraphQL Apollo Server
|
|
100
100
|
ApolloService(mixinOptions),
|
|
@@ -171,10 +171,13 @@ module.exports = {
|
|
|
171
171
|
* @param {ServerResponse} res
|
|
172
172
|
* @param {Object} data
|
|
173
173
|
*
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
174
176
|
onBeforeCall(ctx, route, req, res) {
|
|
175
177
|
// Set request headers to context meta
|
|
176
178
|
ctx.meta.userAgent = req.headers["user-agent"];
|
|
177
|
-
|
|
179
|
+
ctx.meta.clientIp = requestIp.getClientIp(req);
|
|
180
|
+
},
|
|
178
181
|
|
|
179
182
|
/**
|
|
180
183
|
* After call hook. You can modify the data.
|
|
@@ -325,9 +328,14 @@ module.exports = {
|
|
|
325
328
|
* @param {Object.<string, any>} args - Arguments passed to GraphQL child resolver
|
|
326
329
|
* @returns {string} Key to the dataloader instance
|
|
327
330
|
*/
|
|
328
|
-
getObjectDataLoaderMapKey(objectName) {
|
|
331
|
+
getObjectDataLoaderMapKey(objectName, referenceToField = '_id', spaceId) {
|
|
329
332
|
if (objectName) {
|
|
330
|
-
|
|
333
|
+
const key = `${spaceId}_object:${objectName}.${referenceToField}`;
|
|
334
|
+
if(!ObjectDataLoaderMapKeys[objectName]){
|
|
335
|
+
ObjectDataLoaderMapKeys[objectName] = [] ;
|
|
336
|
+
}
|
|
337
|
+
ObjectDataLoaderMapKeys[objectName].push(key);
|
|
338
|
+
return key;
|
|
331
339
|
}
|
|
332
340
|
// 如果没有objectName,则抛出错误信息
|
|
333
341
|
throw new Error("objectName is required");
|
|
@@ -337,8 +345,12 @@ module.exports = {
|
|
|
337
345
|
async objectDataLoaderHandler(actionName, staticParams, rootParams, graphqlCtx) {
|
|
338
346
|
const rootKeys = Object.keys(rootParams);
|
|
339
347
|
const {root, args, context, resolveInfo} = graphqlCtx;
|
|
348
|
+
const userSession = context.ctx.meta.user;
|
|
349
|
+
const spaceId = userSession.spaceId;
|
|
340
350
|
const dataLoaderMapKey = this.getObjectDataLoaderMapKey(
|
|
341
351
|
staticParams.__objectName || staticParams.objectName
|
|
352
|
+
, staticParams.referenceToField || '_id'
|
|
353
|
+
, spaceId
|
|
342
354
|
);
|
|
343
355
|
const objectDataLoaders = this.objectDataLoaders;
|
|
344
356
|
// if a dataLoader batching parameter is specified, then all root params can be data loaded;
|
|
@@ -361,7 +373,8 @@ module.exports = {
|
|
|
361
373
|
batchedParamKey,
|
|
362
374
|
staticParams,
|
|
363
375
|
args,
|
|
364
|
-
{ hashCacheKey: dataLoaderUseAllRootKeys } // must hash the cache key if not loading scalar
|
|
376
|
+
{ hashCacheKey: dataLoaderUseAllRootKeys }, // must hash the cache key if not loading scalar
|
|
377
|
+
spaceId
|
|
365
378
|
);
|
|
366
379
|
objectDataLoaders.set(dataLoaderMapKey, dataLoader);
|
|
367
380
|
}
|
|
@@ -456,10 +469,13 @@ module.exports = {
|
|
|
456
469
|
if(useObjectDataLoader){
|
|
457
470
|
return await this.objectDataLoaderHandler(actionName, staticParams, rootParams, {root, args, context, resolveInfo});
|
|
458
471
|
}else if (useDataLoader) {
|
|
472
|
+
const userSession = context.ctx.meta.user;
|
|
473
|
+
const spaceId = userSession.spaceId;
|
|
459
474
|
const dataLoaderMapKey = this.getDataLoaderMapKey(
|
|
460
475
|
actionName,
|
|
461
476
|
staticParams,
|
|
462
|
-
args
|
|
477
|
+
args,
|
|
478
|
+
spaceId
|
|
463
479
|
);
|
|
464
480
|
// if a dataLoader batching parameter is specified, then all root params can be data loaded;
|
|
465
481
|
// otherwise use only the primary rootParam
|
|
@@ -481,7 +497,8 @@ module.exports = {
|
|
|
481
497
|
batchedParamKey,
|
|
482
498
|
staticParams,
|
|
483
499
|
args,
|
|
484
|
-
{ hashCacheKey: dataLoaderUseAllRootKeys } // must hash the cache key if not loading scalar
|
|
500
|
+
{ hashCacheKey: dataLoaderUseAllRootKeys }, // must hash the cache key if not loading scalar
|
|
501
|
+
spaceId
|
|
485
502
|
);
|
|
486
503
|
context.dataLoaders.set(dataLoaderMapKey, dataLoader);
|
|
487
504
|
}
|
|
@@ -894,6 +911,25 @@ module.exports = {
|
|
|
894
911
|
}
|
|
895
912
|
},
|
|
896
913
|
|
|
914
|
+
/**
|
|
915
|
+
* Get the unique key assigned to the DataLoader map
|
|
916
|
+
* @param {string} actionName - Fully qualified action name to bind to dataloader
|
|
917
|
+
* @param {Object.<string, any>} staticParams - Static parameters to use in dataloader
|
|
918
|
+
* @param {Object.<string, any>} args - Arguments passed to GraphQL child resolver
|
|
919
|
+
* @returns {string} Key to the dataloader instance
|
|
920
|
+
*/
|
|
921
|
+
getDataLoaderMapKey(actionName, staticParams, args, spaceId) {
|
|
922
|
+
if (Object.keys(staticParams).length > 0 || Object.keys(args).length > 0) {
|
|
923
|
+
// create a unique hash of the static params and the arguments to ensure a unique DataLoader instance
|
|
924
|
+
const actionParams = _.defaultsDeep({}, args, staticParams);
|
|
925
|
+
const paramsHash = hash(actionParams);
|
|
926
|
+
return `${spaceId}_${actionName}:${paramsHash}`;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// if no static params or arguments are present then the action name can serve as the key
|
|
930
|
+
return actionName;
|
|
931
|
+
},
|
|
932
|
+
|
|
897
933
|
/**
|
|
898
934
|
* Build a DataLoader instance
|
|
899
935
|
*
|
|
@@ -912,11 +948,13 @@ module.exports = {
|
|
|
912
948
|
batchedParamKey,
|
|
913
949
|
staticParams,
|
|
914
950
|
args,
|
|
915
|
-
{ hashCacheKey = false } = {}
|
|
951
|
+
{ hashCacheKey = false } = {},
|
|
952
|
+
spaceId
|
|
916
953
|
) {
|
|
917
954
|
const batchLoadFn = keys => {
|
|
918
955
|
const rootParams = { [batchedParamKey]: keys };
|
|
919
|
-
|
|
956
|
+
// !!! 这里的ctx是buildDataLoader时传进来的参数,在后续触发执行batchLoadFn时ctx.meta中的信息依然是旧的,故此函数体中代码不要使用ctx.meta中的信息
|
|
957
|
+
return ctx.call(actionName, _.defaultsDeep({}, args, rootParams, staticParams), { meta: { ...ctx.meta, spaceId } });
|
|
920
958
|
};
|
|
921
959
|
|
|
922
960
|
const dataLoaderOptions = this.dataLoaderOptions.get(actionName) || {};
|
|
@@ -938,19 +976,19 @@ module.exports = {
|
|
|
938
976
|
'@objectRecordEvent.*.*': function(ctx){
|
|
939
977
|
const { objectApiName, isUpdate, isDelete, id, doc } = ctx.params;
|
|
940
978
|
if(objectApiName && (isUpdate || isDelete)){
|
|
941
|
-
const
|
|
942
|
-
objectApiName
|
|
943
|
-
);
|
|
979
|
+
const keys = ObjectDataLoaderMapKeys[objectApiName] || [];
|
|
944
980
|
let dataLoaderKeys = [id];
|
|
945
981
|
if(objectApiName === 'space_users'){
|
|
946
982
|
dataLoaderKeys.push(doc.user)
|
|
947
983
|
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
984
|
+
_.each(keys, (key)=>{
|
|
985
|
+
const loader = this.objectDataLoaders.get(key);
|
|
986
|
+
if(loader){
|
|
987
|
+
for(const dataLoaderKey of dataLoaderKeys){
|
|
988
|
+
loader.clear(dataLoaderKey);
|
|
989
|
+
}
|
|
952
990
|
}
|
|
953
|
-
}
|
|
991
|
+
})
|
|
954
992
|
}
|
|
955
993
|
},
|
|
956
994
|
'service-ui.started': function(){
|
|
@@ -995,9 +1033,9 @@ module.exports = {
|
|
|
995
1033
|
// });
|
|
996
1034
|
// }
|
|
997
1035
|
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1036
|
+
this.broker.waitForServices('~packages-@steedos/service-ui').then(() => {
|
|
1037
|
+
this.app.use("/", this.express());
|
|
1038
|
+
})
|
|
1001
1039
|
|
|
1002
1040
|
global.SteedosApi = {
|
|
1003
1041
|
express: this.express
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos/service-api",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.2-beta.2",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@steedos/auth": "2.6.
|
|
8
|
-
"@steedos/router": "2.6.
|
|
9
|
-
"@steedos/service-object-graphql": "2.6.
|
|
10
|
-
"@steedos/service-ui": "2.6.
|
|
7
|
+
"@steedos/auth": "2.6.2-beta.2",
|
|
8
|
+
"@steedos/router": "2.6.2-beta.2",
|
|
9
|
+
"@steedos/service-object-graphql": "2.6.2-beta.2",
|
|
10
|
+
"@steedos/service-ui": "2.6.2-beta.2",
|
|
11
11
|
"graphql": "^15.8.0",
|
|
12
12
|
"graphql-iso-date": "^3.6.1",
|
|
13
13
|
"graphql-type-json": "^0.3.2",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"publishConfig": {
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "ddef9fbc34afc7b57c59a31e9ed4f56818dc4c31",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/graphql-iso-date": "^3.4.0",
|
|
28
28
|
"@types/react-dev-utils": "^9.0.11"
|