Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2d3e7c0

Browse files
authored
Merge pull request#1103 from lowcoder-org/versions-for-datasources
Versions for API based Datasources
2 parentsd63d3a0 +1a50316 commit2d3e7c0

File tree

85 files changed

+4026
-161
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+4026
-161
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import{specsToOptions,version2spec}from"./util";
2+
3+
describe('version2spec',()=>{
4+
test('should return the spec for the given version',()=>{
5+
constspecs={
6+
v1:'spec for version 1',
7+
v2:'spec for version 2',
8+
v3:'spec for version 3'
9+
};
10+
11+
expect(version2spec(specs,'v2')).toBe('spec for version 2');
12+
});
13+
14+
test('should return the first spec if version is undefined',()=>{
15+
constspecs={
16+
v1:'spec for version 1',
17+
v2:'spec for version 2',
18+
v3:'spec for version 3'
19+
};
20+
21+
expect(version2spec(specs,undefined)).toBe('spec for version 1');
22+
});
23+
24+
test('should return the first spec if version is an empty string',()=>{
25+
constspecs={
26+
v1:'spec for version 1',
27+
v2:'spec for version 2',
28+
v3:'spec for version 3'
29+
};
30+
31+
expect(version2spec(specs,"")).toBe('spec for version 1');
32+
});
33+
34+
test('should return undefined if specs is an empty object and version is undefined',()=>{
35+
constspecs={};
36+
37+
expect(version2spec(specs,undefined)).toBeUndefined();
38+
});
39+
40+
test('should return undefined if specs is an empty object and version is an empty string',()=>{
41+
constspecs={};
42+
43+
expect(version2spec(specs,"")).toBeUndefined();
44+
});
45+
46+
test('should return undefined if the specified version does not exist in specs',()=>{
47+
constspecs={
48+
v1:'spec for version 1',
49+
v2:'spec for version 2',
50+
v3:'spec for version 3'
51+
};
52+
53+
expect(version2spec(specs,'v4')).toBeUndefined();
54+
});
55+
});
56+
57+
describe('specsToOptions',()=>{
58+
test('should convert specs object to options array',()=>{
59+
constspecs={
60+
color:'red',
61+
size:'large',
62+
weight:'light'
63+
};
64+
65+
constexpectedOptions=[
66+
{value:'color',label:'color'},
67+
{value:'size',label:'size'},
68+
{value:'weight',label:'weight'}
69+
];
70+
71+
expect(specsToOptions(specs)).toEqual(expectedOptions);
72+
});
73+
74+
test('should return an empty array if specs object is empty',()=>{
75+
constspecs={};
76+
constexpectedOptions:any[]=[];
77+
78+
expect(specsToOptions(specs)).toEqual(expectedOptions);
79+
});
80+
81+
test('should handle specs object with non-string values',()=>{
82+
constspecs={
83+
color:'red',
84+
size:42,
85+
available:true
86+
};
87+
88+
constexpectedOptions=[
89+
{value:'color',label:'color'},
90+
{value:'size',label:'size'},
91+
{value:'available',label:'available'}
92+
];
93+
94+
expect(specsToOptions(specs)).toEqual(expectedOptions);
95+
});
96+
97+
test('should handle specs object with numeric keys',()=>{
98+
constspecs={
99+
1:'one',
100+
2:'two',
101+
3:'three'
102+
};
103+
104+
constexpectedOptions=[
105+
{value:'1',label:'1'},
106+
{value:'2',label:'2'},
107+
{value:'3',label:'3'}
108+
];
109+
110+
expect(specsToOptions(specs)).toEqual(expectedOptions);
111+
});
112+
});

‎server/node-service/src/common/util.ts‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
importyamlfrom"yaml";
22
importfsfrom"fs";
3+
import{MultiOpenApiSpecItem}from"../plugins/openApi/parse";
4+
importpathfrom"path";
5+
import{appendTags}from"../plugins/openApi/util";
6+
import_from"lodash";
37

48
exportfunctionkvToRecord(
59
kvs:{key:string;value:string}[],
@@ -85,3 +89,45 @@ export function safeJsonStringify(data: any) {
8589
returnnull;
8690
}
8791
}
92+
93+
exportfunctionspecsToOptions(specs:any){
94+
returnObject.keys(specs).map(k=>({value:k,label:k}));
95+
}
96+
97+
exportfunctionversion2spec(specs:any,version:any){
98+
if(version==undefined||version==""){
99+
constkeys=Object.keys(specs);
100+
if(keys.length==0)return;
101+
returnspecs[keys[0]];
102+
}
103+
returnspecs[version];
104+
}
105+
106+
functiongenTagFromFileName(name:string){
107+
constfileName=name.replace(/\.yaml|twilio_|\.json/g,"");
108+
constparts=fileName.split("_");
109+
returnparts.reduce((a,b)=>{
110+
if(/v\d+/.test(b)){
111+
return`${a}(${b})`;
112+
}
113+
returna+_.upperFirst(b);
114+
},"");
115+
}
116+
117+
exportfunctiondirToSpecList(specDir:string){
118+
constspecList:MultiOpenApiSpecItem[]=[];
119+
120+
conststart=performance.now();
121+
constspecFiles=fs.readdirSync(specDir);
122+
specFiles.forEach((specFile)=>{
123+
constspec=readYaml(path.join(specDir,specFile));
124+
consttag=genTagFromFileName(specFile);
125+
appendTags(spec,tag);
126+
specList.push({
127+
id:tag,
128+
spec,
129+
});
130+
});
131+
logger.info("spec list loaded %s, duration: %d ms",specDir,performance.now()-start);
132+
returnspecList;
133+
}

‎server/node-service/src/plugins/asana/index.ts‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{readYaml}from"../../common/util";
1+
import{readYaml,specsToOptions,version2spec}from"../../common/util";
22
import_from"lodash";
33
importpathfrom"path";
44
import{OpenAPIV3,OpenAPI}from"openapi-types";
@@ -8,7 +8,9 @@ import { parseOpenApi, ParseOpenApiOptions } from "../openApi/parse";
88

99

1010
constspec=readYaml(path.join(__dirname,"./asana.spec.yaml"));
11-
11+
constspecs={
12+
"v1.0":spec,
13+
}
1214

1315
constdataSourceConfig={
1416
type:"dataSource",
@@ -23,7 +25,15 @@ const dataSourceConfig = {
2325
"key":"personalAccessToken.value",
2426
"label":"Token",
2527
"tooltip":"A [personal access token](https://developers.asana.com/docs/personal-access-token) allows access to the api for the user who created it. This should be kept a secret and be treated like a password.",
26-
}
28+
},
29+
{
30+
label:"Spec Version",
31+
key:"specVersion",
32+
type:"select",
33+
tooltip:"Version of the spec file.",
34+
placeholder:"v1.0",
35+
options:specsToOptions(specs)
36+
},
2737
]
2838
}asconst;
2939

@@ -41,8 +51,8 @@ const asanaPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
4151
icon:"asana.svg",
4252
category:"Project Management",
4353
dataSourceConfig,
44-
queryConfig:async()=>{
45-
const{ actions, categories}=awaitparseOpenApi(specasOpenAPI.Document,parseOptions);
54+
queryConfig:async(data)=>{
55+
const{ actions, categories}=awaitparseOpenApi(version2spec(specs,data.specVersion)asOpenAPI.Document,parseOptions);
4656
return{
4757
type:"query",
4858
label:"Action",
@@ -58,8 +68,9 @@ const asanaPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
5868
url:"",
5969
serverURL:"",
6070
dynamicParamsConfig:dataSourceConfig,
71+
specVersion:dataSourceConfig.specVersion,
6172
};
62-
returnrunOpenApi(actionData,runApiDsConfig,specasOpenAPIV3.Document);
73+
returnrunOpenApi(actionData,runApiDsConfig,version2spec(specs,dataSourceConfig.specVersion)asOpenAPIV3.Document);
6374
},
6475
};
6576

‎server/node-service/src/plugins/circleCi/index.ts‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { runOpenApi } from "../openApi";
55
import{parseOpenApi,ParseOpenApiOptions}from"../openApi/parse";
66

77
importspecfrom"./circleCi.spec.json";
8+
import{specsToOptions,version2spec}from"../../common/util";
9+
constspecs={
10+
"v1.0":spec,
11+
}
812

913
constdataSourceConfig={
1014
type:"dataSource",
@@ -16,6 +20,14 @@ const dataSourceConfig = {
1620
tooltip:
1721
"[Personal API Token](https://circleci.com/docs/managing-api-tokens/#creating-a-personal-api-token)",
1822
},
23+
{
24+
label:"Spec Version",
25+
key:"specVersion",
26+
type:"select",
27+
tooltip:"Version of the spec file.",
28+
placeholder:"v1.0",
29+
options:specsToOptions(specs)
30+
},
1931
],
2032
}asconst;
2133

@@ -33,9 +45,9 @@ const circleCiPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
3345
icon:"circleCI.svg",
3446
category:"DevOps",
3547
dataSourceConfig,
36-
queryConfig:async()=>{
48+
queryConfig:async(data)=>{
3749
const{ actions, categories}=awaitparseOpenApi(
38-
specasunknownasOpenAPI.Document,
50+
version2spec(specs,data.specVersion)asunknownasOpenAPI.Document,
3951
parseOptions
4052
);
4153
return{
@@ -53,8 +65,9 @@ const circleCiPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
5365
url:"",
5466
serverURL:"",
5567
dynamicParamsConfig:dataSourceConfig,
68+
specVersion:dataSourceConfig.specVersion,
5669
};
57-
returnrunOpenApi(actionData,runApiDsConfig,specasunknownasOpenAPIV3.Document);
70+
returnrunOpenApi(actionData,runApiDsConfig,version2spec(specs,dataSourceConfig.specVersion)asunknownasOpenAPIV3.Document);
5871
},
5972
};
6073

‎server/node-service/src/plugins/cloudinary/index.ts‎

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{readYaml}from"../../common/util";
1+
import{readYaml,specsToOptions,version2spec}from"../../common/util";
22
import_from"lodash";
33
importpathfrom"path";
44
import{OpenAPI}from"openapi-types";
@@ -14,6 +14,9 @@ const specList = [
1414
{spec:adminApiSpec,id:"admin"},
1515
{spec:uploadApiSpec,id:"upload"},
1616
];
17+
constspecs={
18+
"v1.0":specList,
19+
}
1720

1821
constdataSourceConfig={
1922
type:"dataSource",
@@ -32,6 +35,14 @@ const dataSourceConfig = {
3235
tooltip:"Basic auth password",
3336
placeholder:"<Basic Auth Password>",
3437
},
38+
{
39+
label:"Spec Version",
40+
key:"specVersion",
41+
type:"select",
42+
tooltip:"Version of the spec file.",
43+
placeholder:"v1.0",
44+
options:specsToOptions(specs)
45+
},
3546
],
3647
}asconst;
3748

@@ -46,18 +57,18 @@ const parseOptions: ParseOpenApiOptions = {
4657

4758
typeDataSourceConfigType=ConfigToType<typeofdataSourceConfig>;
4859

49-
letqueryConfig:QueryConfig;
60+
letqueryConfig:any={};
5061

5162
constcloudinaryPlugin:DataSourcePlugin<any,DataSourceConfigType>={
5263
id:"cloudinary",
5364
name:"Cloudinary",
5465
icon:"cloudinary.svg",
5566
category:"Assets",
5667
dataSourceConfig,
57-
queryConfig:async()=>{
58-
if(!queryConfig){
59-
const{ actions, categories}=awaitparseMultiOpenApi(specList,parseOptions);
60-
queryConfig={
68+
queryConfig:async(data)=>{
69+
if(!queryConfig[data.specVersionaskeyoftypeofqueryConfig]){
70+
const{ actions, categories}=awaitparseMultiOpenApi(version2spec(specs,data.specVersion),parseOptions);
71+
queryConfig[data.specVersionaskeyoftypeofqueryConfig]={
6172
type:"query",
6273
label:"Action",
6374
categories:{
@@ -67,15 +78,16 @@ const cloudinaryPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
6778
actions,
6879
};
6980
}
70-
returnqueryConfig;
81+
returnqueryConfig[data.specVersionaskeyoftypeofqueryConfig];
7182
},
7283
run:function(actionData,dataSourceConfig):Promise<any>{
7384
construnApiDsConfig={
7485
url:"",
7586
serverURL:"",
7687
dynamicParamsConfig:dataSourceConfig,
88+
specVersion:dataSourceConfig.specVersion,
7789
};
78-
returnrunOpenApi(actionData,runApiDsConfig,specList);
90+
returnrunOpenApi(actionData,runApiDsConfig,version2spec(specs,dataSourceConfig.specVersion));
7991
},
8092
};
8193

‎server/node-service/src/plugins/couchdb/index.ts‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { ConfigToType, DataSourcePlugin } from "lowcoder-sdk/dataSource";
44
import{runOpenApi}from"../openApi";
55
import{defaultParseOpenApiOptions,parseOpenApi,ParseOpenApiOptions}from"../openApi/parse";
66
importspecfrom"./CouchDB-3.1.1-resolved.json";
7-
7+
import{specsToOptions,version2spec}from"../../common/util";
8+
constspecs={
9+
"v1.0":spec,
10+
}
811
constdataSourceConfig={
912
type:"dataSource",
1013
params:[
@@ -38,6 +41,14 @@ const dataSourceConfig = {
3841
tooltip:"",
3942
placeholder:"",
4043
},
44+
{
45+
label:"Spec Version",
46+
key:"specVersion",
47+
type:"select",
48+
tooltip:"Version of the spec file.",
49+
placeholder:"v1.0",
50+
options:specsToOptions(specs)
51+
},
4152
],
4253
}asconst;
4354

@@ -59,8 +70,8 @@ const couchdbPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
5970
icon:"couchdb.svg",
6071
category:"database",
6172
dataSourceConfig,
62-
queryConfig:async()=>{
63-
const{ actions, categories}=awaitparseOpenApi(specasOpenAPI.Document,parseOptions);
73+
queryConfig:async(data)=>{
74+
const{ actions, categories}=awaitparseOpenApi(version2spec(specs,data.specVersion)asOpenAPI.Document,parseOptions);
6475
return{
6576
type:"query",
6677
label:"Operation",
@@ -77,8 +88,9 @@ const couchdbPlugin: DataSourcePlugin<any, DataSourceConfigType> = {
7788
url:"",
7889
serverURL:serverURL,
7990
dynamicParamsConfig:otherDataSourceConfig,
91+
specVersion:dataSourceConfig.specVersion
8092
};
81-
returnrunOpenApi(actionData,runApiDsConfig,specasOpenAPIV2.Document);
93+
returnrunOpenApi(actionData,runApiDsConfig,version2spec(specs,dataSourceConfig.specVersion)asOpenAPIV2.Document);
8294
},
8395
};
8496

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp