Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions server/node-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"build": "rm -rf build/ && yarn test && tsc && yarn copy"
},
"devDependencies": {
"@types/ali-oss": "^6.16.11",
"@types/jest": "^29.2.4",
"commander": "^10.0.0",
"copyfiles": "^2.4.1",
Expand Down Expand Up @@ -44,6 +45,7 @@
"@types/morgan": "^1.9.3",
"@types/node": "^20.1.1",
"@types/node-fetch": "^2.6.2",
"ali-oss": "^6.20.0",
"axios": "^1.2.0",
"base64-arraybuffer": "^1.0.2",
"dynamodb-data-types": "^4.0.1",
Expand Down
52 changes: 52 additions & 0 deletions server/node-service/src/plugins/aliyunOss/dataSourceConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ConfigToType } from "lowcoder-sdk/dataSource";
import { AliyunOssI18nTranslator } from "./i18n";

const getDataSourceConfig = (i18n: AliyunOssI18nTranslator) => {
const dataSourceConfig = {
type: "dataSource",
params: [
{
key: "accessKeyId",
label: "Access key ID",
type: "textInput",
placeholder: "<Your Access key ID>",
rules: [{ required: true, message: i18n.trans("akRequiredMessage") }],
},
{
key: "accessKeySecret",
label: "Secret key",
type: "password",
placeholder: "<Your Access key Secrect>",
rules: [{ required: true, message: i18n.trans("skRequiredMessage") }],
},
{
key: "arn",
label: "ARN",
type: "password",
tooltip: i18n.trans("arnTooltip"),
placeholder: "<Your Aliyun ARN>",
rules: [{ required: true, message: i18n.trans("arnRequiredMessage") }],
},
{
key: "endpointUrl",
label: "STS Endpoint",
type: "textInput",
tooltip: i18n.trans("endpointUrlTooltip"),
default: "sts.cn-hangzhou.aliyuncs.com",
rules: [{ required: true }],
},
{
key: "region",
type: "textInput",
label: i18n.trans("region"),
defaultValue: "oss-cn-hangzhou",
rules: [{ required: true }],
},
],
} as const;
return dataSourceConfig;
};

export default getDataSourceConfig;

export type DataSourceDataType = ConfigToType<ReturnType<typeof getDataSourceConfig>>;
30 changes: 30 additions & 0 deletions server/node-service/src/plugins/aliyunOss/i18n/en.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const en = {
name: "OSS",
description: "Supports Aliyun Object Storage Service (Based on STS)",
skRequiredMessage: "Please input the SecretKey",
akRequiredMessage: "Please input the AccessKey",
arnRequiredMessage: "Please input the ARN",
endpointUrlTooltip: "Endpoint url of STS service",
arnTooltip: "The global resource descriptor for the role",
bucket: "Bucket",
returnSignedUrl: "Return signed url",
actions: "Actions",
prefix: "Prefix to filter",
delimiter: "Delimiter",
limit: "Limit",
fileName: "File name",
dataType: "Data type",
data: "Data",
dataTooltip:"The content of the data only supports BASE64 encoding, for example: window.btoa(xxx).",
region: "OSS Region",
messages: {
bucketRequired: "Bucket is required",
},
actionName: {
listBuckets: "List buckets",
listObjects: "List files",
uploadFile: "Upload file",
readFile: "Read file",
deleteFile: "Delete file",
},
};
9 changes: 9 additions & 0 deletions server/node-service/src/plugins/aliyunOss/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { en } from "./en";
import { zh } from "./zh";
import { I18n } from "../../../common/i18n";

export default function getI18nTranslator(languages: string[]) {
return new I18n<typeof en>({ zh, en }, languages);
}

export type AliyunOssI18nTranslator = ReturnType<typeof getI18nTranslator>;
32 changes: 32 additions & 0 deletions server/node-service/src/plugins/aliyunOss/i18n/zh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { en } from "./en";

export const zh: typeof en = {
name: "阿里云对象存储",
description: "支持OSS对象存储服务(基于 STS 身份认证)",
skRequiredMessage: "请输入 SecretKey",
akRequiredMessage: "请输入 AccessKey",
arnRequiredMessage: "请输入阿里云ARN",
endpointUrlTooltip: "STS 服务接入点",
arnTooltip: "角色的全局资源描述符",
bucket: "存储桶",
region: "OSS 区域",
returnSignedUrl: "返回文件签名地址",
actions: "方法",
prefix: "前缀",
delimiter: "分隔符",
limit: "最大文件数",
fileName: "文件名",
dataType: "数据类型",
data: "数据",
dataTooltip:"数据内容仅支持 BASE64 编码,例:window.btoa(xxx)",
messages: {
bucketRequired: "需要提供存储桶名称",
},
actionName: {
listBuckets: "查询桶列表",
listObjects: "获取文件列表",
uploadFile: "上传文件",
readFile: "读取文件",
deleteFile: "删除文件",
},
};
39 changes: 39 additions & 0 deletions server/node-service/src/plugins/aliyunOss/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { DataSourcePluginFactory, PluginContext } from "lowcoder-sdk/dataSource";
import getI18nTranslator from "./i18n";
import getDataSourceConfig, { DataSourceDataType } from "./dataSourceConfig";
import run, { validateDataSourceConfig } from "./run";
import getQueryConfig, { ActionDataType } from "./queryConfig";
import { ServiceError } from "../../common/error";

const ossPlugin: DataSourcePluginFactory = (context: PluginContext) => {
const i18n = getI18nTranslator(context.languages);
return {
id: "oss",
name: i18n.trans("name"),
icon: "https://img.alicdn.com/tfs/TB1_ZXuNcfpK1RjSZFOXXa6nFXa-32-32.ico",
description: i18n.trans("description"),
category: "api",
dataSourceConfig: getDataSourceConfig(i18n),
queryConfig: getQueryConfig(i18n),

validateDataSourceConfig: async (dataSourceConfig: DataSourceDataType) => {
return validateDataSourceConfig(dataSourceConfig);
},

run: async (
action: ActionDataType,
dataSourceConfig: DataSourceDataType,
ctx: PluginContext
) => {
const i18n = getI18nTranslator(ctx.languages);
try {
return await run(action, dataSourceConfig, i18n);
} catch (e:any) {
throw new ServiceError(e.message, 400);
}
},
};
};

export default ossPlugin;

80 changes: 80 additions & 0 deletions server/node-service/src/plugins/aliyunOss/queryConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { ActionParamConfig, Config, ConfigToType, QueryConfig } from "lowcoder-sdk/dataSource";
import { AliyunOssI18nTranslator } from "./i18n";

function getQueryConfig(i18n: AliyunOssI18nTranslator) {
const bucketActionParam = {
key: "bucket",
type: "textInput",
label: i18n.trans("bucket"),
} as const;

const queryConfig = {
type: "query",
label: i18n.trans("actions"),
actions: [
// {
// actionName: "listBuckets",
// label: i18n.trans("actionName.listBuckets"),
// params: [],
// },
{
actionName: "listObjects",
label: i18n.trans("actionName.listObjects"),
params: [
bucketActionParam,
{
key: "prefix",
type: "textInput",
label: i18n.trans("prefix"),
},
{
key: "delimiter",
type: "textInput",
label: i18n.trans("delimiter"),
},
{
key: "limit",
type: "numberInput",
defaultValue: 10,
label: i18n.trans("limit"),
}
],
},
{
actionName: "uploadData",
label: i18n.trans("actionName.uploadFile"),
params: [
bucketActionParam,
{
key: "fileName",
type: "textInput",
label: i18n.trans("fileName"),
},
{
key: "data",
type: "textInput",
label: i18n.trans("data"),
tooltip: i18n.trans("dataTooltip"),
},
],
},
// {
// actionName: "deleteFile",
// label: i18n.trans("actionName.deleteFile"),
// params: [
// bucketActionParam,
// {
// key: "fileName",
// type: "textInput",
// label: i18n.trans("fileName"),
// },
// ],
// },
],
} as const;
return queryConfig;
}

export type ActionDataType = ConfigToType<ReturnType<typeof getQueryConfig>>;

export default getQueryConfig;
Loading