@nocobase/plugin-file-manager 0.7.0-alpha.9 → 0.7.1-alpha.6
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/lib/actions/upload.js +237 -161
- package/lib/collections/attachments.js +55 -59
- package/lib/collections/storages.js +54 -60
- package/lib/constants.js +17 -9
- package/lib/index.js +29 -19
- package/lib/rules/index.js +14 -9
- package/lib/rules/mimetype.js +20 -9
- package/lib/server.js +91 -48
- package/lib/storages/ali-oss.js +36 -26
- package/lib/storages/index.js +22 -16
- package/lib/storages/local.d.ts +3 -0
- package/lib/storages/local.js +240 -119
- package/lib/storages/s3.js +77 -52
- package/lib/utils.js +43 -20
- package/package.json +6 -10
- package/esm/actions/upload.d.ts +0 -3
- package/esm/actions/upload.js +0 -143
- package/esm/actions/upload.js.map +0 -1
- package/esm/collections/attachments.d.ts +0 -3
- package/esm/collections/attachments.js +0 -59
- package/esm/collections/attachments.js.map +0 -1
- package/esm/collections/storages.d.ts +0 -3
- package/esm/collections/storages.js +0 -60
- package/esm/collections/storages.js.map +0 -1
- package/esm/constants.d.ts +0 -6
- package/esm/constants.js +0 -7
- package/esm/constants.js.map +0 -1
- package/esm/index.d.ts +0 -2
- package/esm/index.js +0 -3
- package/esm/index.js.map +0 -1
- package/esm/rules/index.d.ts +0 -1
- package/esm/rules/index.js +0 -3
- package/esm/rules/index.js.map +0 -1
- package/esm/rules/mimetype.d.ts +0 -1
- package/esm/rules/mimetype.js +0 -5
- package/esm/rules/mimetype.js.map +0 -1
- package/esm/server.d.ts +0 -7
- package/esm/server.js +0 -48
- package/esm/server.js.map +0 -1
- package/esm/storages/ali-oss.d.ts +0 -16
- package/esm/storages/ali-oss.js +0 -26
- package/esm/storages/ali-oss.js.map +0 -1
- package/esm/storages/index.d.ts +0 -8
- package/esm/storages/index.js +0 -12
- package/esm/storages/index.js.map +0 -1
- package/esm/storages/local.d.ts +0 -14
- package/esm/storages/local.js +0 -127
- package/esm/storages/local.js.map +0 -1
- package/esm/storages/s3.d.ts +0 -17
- package/esm/storages/s3.js +0 -53
- package/esm/storages/s3.js.map +0 -1
- package/esm/utils.d.ts +0 -2
- package/esm/utils.js +0 -16
- package/esm/utils.js.map +0 -1
- package/lib/actions/upload.js.map +0 -1
- package/lib/collections/attachments.js.map +0 -1
- package/lib/collections/storages.js.map +0 -1
- package/lib/constants.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/rules/index.js.map +0 -1
- package/lib/rules/mimetype.js.map +0 -1
- package/lib/server.js.map +0 -1
- package/lib/storages/ali-oss.js.map +0 -1
- package/lib/storages/index.js.map +0 -1
- package/lib/storages/local.js.map +0 -1
- package/lib/storages/s3.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/tsconfig.build.json +0 -9
package/esm/actions/upload.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
-
var t = {};
|
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
-
t[p[i]] = s[p[i]];
|
|
18
|
-
}
|
|
19
|
-
return t;
|
|
20
|
-
};
|
|
21
|
-
import path from 'path';
|
|
22
|
-
import multer from '@koa/multer';
|
|
23
|
-
import { getStorageConfig } from '../storages';
|
|
24
|
-
import * as Rules from '../rules';
|
|
25
|
-
import { FILE_FIELD_NAME, LIMIT_FILES, LIMIT_MAX_FILE_SIZE } from '../constants';
|
|
26
|
-
import { BelongsToManyRepository, BelongsToRepository } from '@nocobase/database';
|
|
27
|
-
function getRules(ctx) {
|
|
28
|
-
const { resourceField } = ctx;
|
|
29
|
-
if (!resourceField) {
|
|
30
|
-
return ctx.storage.rules;
|
|
31
|
-
}
|
|
32
|
-
const { rules = {} } = resourceField.options.attachment || {};
|
|
33
|
-
return Object.assign({}, ctx.storage.rules, rules);
|
|
34
|
-
}
|
|
35
|
-
// TODO(optimize): 需要优化错误处理,计算失败后需要抛出对应错误,以便程序处理
|
|
36
|
-
function getFileFilter(ctx) {
|
|
37
|
-
return (req, file, cb) => {
|
|
38
|
-
// size 交给 limits 处理
|
|
39
|
-
const _a = getRules(ctx), { size } = _a, rules = __rest(_a, ["size"]);
|
|
40
|
-
const ruleKeys = Object.keys(rules);
|
|
41
|
-
const result = !ruleKeys.length ||
|
|
42
|
-
!ruleKeys.some((key) => typeof Rules[key] !== 'function' || !Rules[key](file, rules[key], ctx));
|
|
43
|
-
cb(null, result);
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
export function middleware(ctx, next) {
|
|
47
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
-
const { resourceName, actionName, associatedName } = ctx.action.params;
|
|
49
|
-
if (actionName !== 'upload') {
|
|
50
|
-
return next();
|
|
51
|
-
}
|
|
52
|
-
// NOTE:
|
|
53
|
-
// 1. 存储引擎选择依赖于字段定义
|
|
54
|
-
// 2. 字段定义中需包含引擎的外键值
|
|
55
|
-
// 3. 无字段时按 storages 表的默认项
|
|
56
|
-
// 4. 插件初始化后应提示用户添加至少一个存储引擎并设为默认
|
|
57
|
-
const Storage = ctx.db.getCollection('storages');
|
|
58
|
-
let storage;
|
|
59
|
-
if (resourceName === 'attachments') {
|
|
60
|
-
// 如果没有包含关联,则直接按默认文件上传至默认存储引擎
|
|
61
|
-
storage = yield Storage.repository.findOne({ filter: { default: true } });
|
|
62
|
-
}
|
|
63
|
-
else if (associatedName) {
|
|
64
|
-
const AssociatedCollection = ctx.db.getCollection(associatedName);
|
|
65
|
-
const resourceField = AssociatedCollection.getField(resourceName);
|
|
66
|
-
ctx.resourceField = resourceField;
|
|
67
|
-
const { attachment = {} } = resourceField.options;
|
|
68
|
-
storage = yield Storage.repository.findOne({
|
|
69
|
-
filter: attachment.storage ? { name: attachment.storage } : { default: true },
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
if (!storage) {
|
|
73
|
-
console.error('[file-manager] no default or linked storage provided');
|
|
74
|
-
return ctx.throw(500);
|
|
75
|
-
}
|
|
76
|
-
// 传递已取得的存储引擎,避免重查
|
|
77
|
-
ctx.storage = storage;
|
|
78
|
-
const storageConfig = getStorageConfig(storage.type);
|
|
79
|
-
if (!storageConfig) {
|
|
80
|
-
console.error(`[file-manager] storage type "${storage.type}" is not defined`);
|
|
81
|
-
return ctx.throw(500);
|
|
82
|
-
}
|
|
83
|
-
const multerOptions = {
|
|
84
|
-
fileFilter: getFileFilter(ctx),
|
|
85
|
-
limits: {
|
|
86
|
-
fileSize: Math.min(getRules(ctx).size || LIMIT_MAX_FILE_SIZE, LIMIT_MAX_FILE_SIZE),
|
|
87
|
-
// 每次只允许提交一个文件
|
|
88
|
-
files: LIMIT_FILES,
|
|
89
|
-
},
|
|
90
|
-
storage: storageConfig.make(storage),
|
|
91
|
-
};
|
|
92
|
-
const upload = multer(multerOptions).single(FILE_FIELD_NAME);
|
|
93
|
-
return upload(ctx, next);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
export function action(ctx, next) {
|
|
97
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
-
const { [FILE_FIELD_NAME]: file, storage } = ctx;
|
|
99
|
-
if (!file) {
|
|
100
|
-
return ctx.throw(400, 'file validation failed');
|
|
101
|
-
}
|
|
102
|
-
const storageConfig = getStorageConfig(storage.type);
|
|
103
|
-
const { [storageConfig.filenameKey || 'filename']: name } = file;
|
|
104
|
-
// make compatible filename across cloud service (with path)
|
|
105
|
-
const filename = path.basename(name);
|
|
106
|
-
const extname = path.extname(filename);
|
|
107
|
-
const urlPath = storage.path ? storage.path.replace(/^([^\/])/, '/$1') : '';
|
|
108
|
-
const data = Object.assign({ title: file.originalname.replace(extname, ''), filename,
|
|
109
|
-
extname,
|
|
110
|
-
// TODO(feature): 暂时两者相同,后面 storage.path 模版化以后,这里只是 file 实际的 path
|
|
111
|
-
path: storage.path, size: file.size,
|
|
112
|
-
// 直接缓存起来
|
|
113
|
-
url: `${storage.baseUrl}${urlPath}/${filename}`, mimetype: file.mimetype,
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
meta: ctx.request.body }, (storageConfig.getFileData ? storageConfig.getFileData(file) : {}));
|
|
116
|
-
const attachment = yield ctx.db.sequelize.transaction((transaction) => __awaiter(this, void 0, void 0, function* () {
|
|
117
|
-
// TODO(optimize): 应使用关联 accessors 获取
|
|
118
|
-
const result = yield storage.createAttachment(data, { transaction });
|
|
119
|
-
const { associatedName, associatedIndex, resourceName } = ctx.action.params;
|
|
120
|
-
const AssociatedCollection = ctx.db.getCollection(associatedName);
|
|
121
|
-
if (AssociatedCollection && associatedIndex && resourceName) {
|
|
122
|
-
const Repo = AssociatedCollection.repository.relation(resourceName).of(associatedIndex);
|
|
123
|
-
const Attachment = ctx.db.getCollection('attachments').model;
|
|
124
|
-
const opts = {
|
|
125
|
-
tk: result[Attachment.primaryKeyAttribute],
|
|
126
|
-
transaction,
|
|
127
|
-
};
|
|
128
|
-
if (Repo instanceof BelongsToManyRepository) {
|
|
129
|
-
yield Repo.add(opts);
|
|
130
|
-
}
|
|
131
|
-
else if (Repo instanceof BelongsToRepository) {
|
|
132
|
-
yield Repo.set(opts);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return result;
|
|
136
|
-
}));
|
|
137
|
-
// 将存储引擎的信息附在已创建的记录里,节省一次查询
|
|
138
|
-
// attachment.setDataValue('storage', storage);
|
|
139
|
-
ctx.body = attachment;
|
|
140
|
-
yield next();
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=upload.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/actions/upload.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport multer from '@koa/multer';\nimport { Context, Next } from '@nocobase/actions';\nimport { getStorageConfig } from '../storages';\nimport * as Rules from '../rules';\nimport { FILE_FIELD_NAME, LIMIT_FILES, LIMIT_MAX_FILE_SIZE } from '../constants';\nimport { BelongsToManyRepository, BelongsToRepository } from '@nocobase/database';\n\nfunction getRules(ctx: Context) {\n const { resourceField } = ctx;\n if (!resourceField) {\n return ctx.storage.rules;\n }\n const { rules = {} } = resourceField.options.attachment || {};\n return Object.assign({}, ctx.storage.rules, rules);\n}\n\n// TODO(optimize): 需要优化错误处理,计算失败后需要抛出对应错误,以便程序处理\nfunction getFileFilter(ctx: Context) {\n return (req, file, cb) => {\n // size 交给 limits 处理\n const { size, ...rules } = getRules(ctx);\n const ruleKeys = Object.keys(rules);\n const result =\n !ruleKeys.length ||\n !ruleKeys.some((key) => typeof Rules[key] !== 'function' || !Rules[key](file, rules[key], ctx));\n cb(null, result);\n };\n}\n\nexport async function middleware(ctx: Context, next: Next) {\n const { resourceName, actionName, associatedName } = ctx.action.params;\n if (actionName !== 'upload') {\n return next();\n }\n\n // NOTE:\n // 1. 存储引擎选择依赖于字段定义\n // 2. 字段定义中需包含引擎的外键值\n // 3. 无字段时按 storages 表的默认项\n // 4. 插件初始化后应提示用户添加至少一个存储引擎并设为默认\n\n const Storage = ctx.db.getCollection('storages');\n let storage;\n\n if (resourceName === 'attachments') {\n // 如果没有包含关联,则直接按默认文件上传至默认存储引擎\n storage = await Storage.repository.findOne({ filter: { default: true } });\n } else if (associatedName) {\n const AssociatedCollection = ctx.db.getCollection(associatedName);\n const resourceField = AssociatedCollection.getField(resourceName);\n ctx.resourceField = resourceField;\n const { attachment = {} } = resourceField.options;\n storage = await Storage.repository.findOne({\n filter: attachment.storage ? { name: attachment.storage } : { default: true },\n });\n }\n\n if (!storage) {\n console.error('[file-manager] no default or linked storage provided');\n return ctx.throw(500);\n }\n // 传递已取得的存储引擎,避免重查\n ctx.storage = storage;\n\n const storageConfig = getStorageConfig(storage.type);\n if (!storageConfig) {\n console.error(`[file-manager] storage type \"${storage.type}\" is not defined`);\n return ctx.throw(500);\n }\n const multerOptions = {\n fileFilter: getFileFilter(ctx),\n limits: {\n fileSize: Math.min(getRules(ctx).size || LIMIT_MAX_FILE_SIZE, LIMIT_MAX_FILE_SIZE),\n // 每次只允许提交一个文件\n files: LIMIT_FILES,\n },\n storage: storageConfig.make(storage),\n };\n const upload = multer(multerOptions).single(FILE_FIELD_NAME);\n return upload(ctx, next);\n}\n\nexport async function action(ctx: Context, next: Next) {\n const { [FILE_FIELD_NAME]: file, storage } = ctx;\n if (!file) {\n return ctx.throw(400, 'file validation failed');\n }\n\n const storageConfig = getStorageConfig(storage.type);\n const { [storageConfig.filenameKey || 'filename']: name } = file;\n // make compatible filename across cloud service (with path)\n const filename = path.basename(name);\n const extname = path.extname(filename);\n const urlPath = storage.path ? storage.path.replace(/^([^\\/])/, '/$1') : '';\n\n const data = {\n title: file.originalname.replace(extname, ''),\n filename,\n extname,\n // TODO(feature): 暂时两者相同,后面 storage.path 模版化以后,这里只是 file 实际的 path\n path: storage.path,\n size: file.size,\n // 直接缓存起来\n url: `${storage.baseUrl}${urlPath}/${filename}`,\n mimetype: file.mimetype,\n // @ts-ignore\n meta: ctx.request.body,\n ...(storageConfig.getFileData ? storageConfig.getFileData(file) : {}),\n };\n\n const attachment = await ctx.db.sequelize.transaction(async (transaction) => {\n // TODO(optimize): 应使用关联 accessors 获取\n const result = await storage.createAttachment(data, { transaction });\n\n const { associatedName, associatedIndex, resourceName } = ctx.action.params;\n const AssociatedCollection = ctx.db.getCollection(associatedName);\n\n if (AssociatedCollection && associatedIndex && resourceName) {\n const Repo = AssociatedCollection.repository.relation(resourceName).of(associatedIndex);\n const Attachment = ctx.db.getCollection('attachments').model;\n const opts = {\n tk: result[Attachment.primaryKeyAttribute],\n transaction,\n };\n\n if (Repo instanceof BelongsToManyRepository) {\n await Repo.add(opts);\n } else if (Repo instanceof BelongsToRepository) {\n await Repo.set(opts);\n }\n }\n\n return result;\n });\n\n // 将存储引擎的信息附在已创建的记录里,节省一次查询\n // attachment.setDataValue('storage', storage);\n ctx.body = attachment;\n\n await next();\n}\n"]}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
name: 'attachments',
|
|
3
|
-
title: '文件管理器',
|
|
4
|
-
fields: [
|
|
5
|
-
{
|
|
6
|
-
comment: '用户文件名(不含扩展名)',
|
|
7
|
-
type: 'string',
|
|
8
|
-
name: 'title',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
comment: '系统文件名(含扩展名)',
|
|
12
|
-
type: 'string',
|
|
13
|
-
name: 'filename',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
comment: '扩展名(含“.”)',
|
|
17
|
-
type: 'string',
|
|
18
|
-
name: 'extname',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
comment: '文件体积(字节)',
|
|
22
|
-
type: 'integer',
|
|
23
|
-
name: 'size',
|
|
24
|
-
},
|
|
25
|
-
// TODO: 使用暂不明确,以后再考虑
|
|
26
|
-
// {
|
|
27
|
-
// comment: '文件类型(mimetype 前半段,通常用于预览)',
|
|
28
|
-
// type: 'string',
|
|
29
|
-
// name: 'type',
|
|
30
|
-
// },
|
|
31
|
-
{
|
|
32
|
-
type: 'string',
|
|
33
|
-
name: 'mimetype',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
comment: '存储引擎',
|
|
37
|
-
type: 'belongsTo',
|
|
38
|
-
name: 'storage',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
comment: '相对路径(含“/”前缀)',
|
|
42
|
-
type: 'string',
|
|
43
|
-
name: 'path',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
comment: '其他文件信息(如图片的宽高)',
|
|
47
|
-
type: 'jsonb',
|
|
48
|
-
name: 'meta',
|
|
49
|
-
defaultValue: {},
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
comment: '网络访问地址',
|
|
53
|
-
type: 'string',
|
|
54
|
-
name: 'url',
|
|
55
|
-
// formula: '{{ storage.baseUrl }}{{ path }}/{{ filename }}'
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
//# sourceMappingURL=attachments.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/collections/attachments.ts"],"names":[],"mappings":"AAEA,eAAe;IACb,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE;QACN;YACE,OAAO,EAAE,cAAc;YACvB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,OAAO;SACd;QACD;YACE,OAAO,EAAE,aAAa;YACtB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,UAAU;SACjB;QACD;YACE,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,SAAS;SAChB;QACD;YACE,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,MAAM;SACb;QACD,qBAAqB;QACrB,IAAI;QACJ,0CAA0C;QAC1C,oBAAoB;QACpB,kBAAkB;QAClB,KAAK;QACL;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,UAAU;SACjB;QACD;YACE,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,SAAS;SAChB;QACD;YACE,OAAO,EAAE,cAAc;YACvB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;SACb;QACD;YACE,OAAO,EAAE,gBAAgB;YACzB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,EAAE;SACjB;QACD;YACE,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,KAAK;YACX,4DAA4D;SAC7D;KACF;CACmB,CAAC","sourcesContent":["import { CollectionOptions } from '@nocobase/database';\n\nexport default {\n name: 'attachments',\n title: '文件管理器',\n fields: [\n {\n comment: '用户文件名(不含扩展名)',\n type: 'string',\n name: 'title',\n },\n {\n comment: '系统文件名(含扩展名)',\n type: 'string',\n name: 'filename',\n },\n {\n comment: '扩展名(含“.”)',\n type: 'string',\n name: 'extname',\n },\n {\n comment: '文件体积(字节)',\n type: 'integer',\n name: 'size',\n },\n // TODO: 使用暂不明确,以后再考虑\n // {\n // comment: '文件类型(mimetype 前半段,通常用于预览)',\n // type: 'string',\n // name: 'type',\n // },\n {\n type: 'string',\n name: 'mimetype',\n },\n {\n comment: '存储引擎',\n type: 'belongsTo',\n name: 'storage',\n },\n {\n comment: '相对路径(含“/”前缀)',\n type: 'string',\n name: 'path',\n },\n {\n comment: '其他文件信息(如图片的宽高)',\n type: 'jsonb',\n name: 'meta',\n defaultValue: {},\n },\n {\n comment: '网络访问地址',\n type: 'string',\n name: 'url',\n // formula: '{{ storage.baseUrl }}{{ path }}/{{ filename }}'\n },\n ],\n} as CollectionOptions;\n"]}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
name: 'storages',
|
|
3
|
-
title: '存储引擎',
|
|
4
|
-
fields: [
|
|
5
|
-
{
|
|
6
|
-
title: '存储引擎名称',
|
|
7
|
-
comment: '存储引擎名称',
|
|
8
|
-
type: 'string',
|
|
9
|
-
name: 'title',
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
title: '英文标识',
|
|
13
|
-
// comment: '英文标识,用于代码层面配置',
|
|
14
|
-
type: 'string',
|
|
15
|
-
name: 'name',
|
|
16
|
-
unique: true,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
comment: '类型标识,如 local/ali-oss 等',
|
|
20
|
-
type: 'string',
|
|
21
|
-
name: 'type',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
comment: '配置项',
|
|
25
|
-
type: 'jsonb',
|
|
26
|
-
name: 'options',
|
|
27
|
-
defaultValue: {},
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
comment: '文件规则',
|
|
31
|
-
type: 'jsonb',
|
|
32
|
-
name: 'rules',
|
|
33
|
-
defaultValue: {},
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
comment: '存储相对路径模板',
|
|
37
|
-
type: 'string',
|
|
38
|
-
name: 'path',
|
|
39
|
-
defaultValue: '',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
comment: '访问地址前缀',
|
|
43
|
-
type: 'string',
|
|
44
|
-
name: 'baseUrl',
|
|
45
|
-
defaultValue: '',
|
|
46
|
-
},
|
|
47
|
-
// TODO(feature): 需要使用一个实现了可设置默认值的字段
|
|
48
|
-
{
|
|
49
|
-
comment: '默认引擎',
|
|
50
|
-
type: 'radio',
|
|
51
|
-
name: 'default',
|
|
52
|
-
defaultValue: false,
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
type: 'hasMany',
|
|
56
|
-
name: 'attachments',
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
//# sourceMappingURL=storages.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storages.js","sourceRoot":"","sources":["../../src/collections/storages.ts"],"names":[],"mappings":"AAEA,eAAe;IACb,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,MAAM;IACb,MAAM,EAAE;QACN;YACE,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,OAAO;SACd;QACD;YACE,KAAK,EAAE,MAAM;YACb,4BAA4B;YAC5B,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,IAAI;SACb;QACD;YACE,OAAO,EAAE,wBAAwB;YACjC,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;SACb;QACD;YACE,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,SAAS;YACf,YAAY,EAAE,EAAE;SACjB;QACD;YACE,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,YAAY,EAAE,EAAE;SACjB;QACD;YACE,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,EAAE;SACjB;QACD;YACE,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,SAAS;YACf,YAAY,EAAE,EAAE;SACjB;QACD,oCAAoC;QACpC;YACE,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,SAAS;YACf,YAAY,EAAE,KAAK;SACpB;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,aAAa;SACpB;KACF;CACmB,CAAC","sourcesContent":["import { CollectionOptions } from '@nocobase/database';\n\nexport default {\n name: 'storages',\n title: '存储引擎',\n fields: [\n {\n title: '存储引擎名称',\n comment: '存储引擎名称',\n type: 'string',\n name: 'title',\n },\n {\n title: '英文标识',\n // comment: '英文标识,用于代码层面配置',\n type: 'string',\n name: 'name',\n unique: true,\n },\n {\n comment: '类型标识,如 local/ali-oss 等',\n type: 'string',\n name: 'type',\n },\n {\n comment: '配置项',\n type: 'jsonb',\n name: 'options',\n defaultValue: {},\n },\n {\n comment: '文件规则',\n type: 'jsonb',\n name: 'rules',\n defaultValue: {},\n },\n {\n comment: '存储相对路径模板',\n type: 'string',\n name: 'path',\n defaultValue: '',\n },\n {\n comment: '访问地址前缀',\n type: 'string',\n name: 'baseUrl',\n defaultValue: '',\n },\n // TODO(feature): 需要使用一个实现了可设置默认值的字段\n {\n comment: '默认引擎',\n type: 'radio',\n name: 'default',\n defaultValue: false,\n },\n {\n type: 'hasMany',\n name: 'attachments',\n },\n ],\n} as CollectionOptions;\n"]}
|
package/esm/constants.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare const FILE_FIELD_NAME = "file";
|
|
2
|
-
export declare const LIMIT_FILES = 1;
|
|
3
|
-
export declare const LIMIT_MAX_FILE_SIZE: number;
|
|
4
|
-
export declare const STORAGE_TYPE_LOCAL = "local";
|
|
5
|
-
export declare const STORAGE_TYPE_ALI_OSS = "ali-oss";
|
|
6
|
-
export declare const STORAGE_TYPE_S3 = "s3";
|
package/esm/constants.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export const FILE_FIELD_NAME = 'file';
|
|
2
|
-
export const LIMIT_FILES = 1;
|
|
3
|
-
export const LIMIT_MAX_FILE_SIZE = 1024 * 1024 * 1024;
|
|
4
|
-
export const STORAGE_TYPE_LOCAL = 'local';
|
|
5
|
-
export const STORAGE_TYPE_ALI_OSS = 'ali-oss';
|
|
6
|
-
export const STORAGE_TYPE_S3 = 's3';
|
|
7
|
-
//# sourceMappingURL=constants.js.map
|
package/esm/constants.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAC9C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC","sourcesContent":["export const FILE_FIELD_NAME = 'file';\nexport const LIMIT_FILES = 1;\nexport const LIMIT_MAX_FILE_SIZE = 1024 * 1024 * 1024;\n\nexport const STORAGE_TYPE_LOCAL = 'local';\nexport const STORAGE_TYPE_ALI_OSS = 'ali-oss';\nexport const STORAGE_TYPE_S3 = 's3';\n"]}
|
package/esm/index.d.ts
DELETED
package/esm/index.js
DELETED
package/esm/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC","sourcesContent":["export * from './constants';\nexport { default } from './server';\n\n"]}
|
package/esm/rules/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as mimetype } from './mimetype';
|
package/esm/rules/index.js
DELETED
package/esm/rules/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEjD,oCAAoC","sourcesContent":["export { default as mimetype } from './mimetype';\n\n// TODO(feature): 提供注册新规则的方法,规则可动态添加\n"]}
|
package/esm/rules/mimetype.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function (file: any, options: string | string[], ctx: any): boolean;
|
package/esm/rules/mimetype.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mimetype.js","sourceRoot":"","sources":["../../src/rules/mimetype.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,UAA6B,GAAG,EAAE,GAAG;IAClE,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC","sourcesContent":["import match from 'mime-match';\n\nexport default function (file, options: string | string[] = '*', ctx): boolean {\n return options.toString().split(',').some(match(file.mimetype));\n}\n"]}
|
package/esm/server.d.ts
DELETED
package/esm/server.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { Plugin } from '@nocobase/server';
|
|
11
|
-
import { resolve } from 'path';
|
|
12
|
-
import { action as uploadAction, middleware as uploadMiddleware } from './actions/upload';
|
|
13
|
-
import { STORAGE_TYPE_LOCAL } from './constants';
|
|
14
|
-
import { getStorageConfig } from './storages';
|
|
15
|
-
export default class PluginFileManager extends Plugin {
|
|
16
|
-
storageType() {
|
|
17
|
-
return process.env.DEFAULT_STORAGE_TYPE;
|
|
18
|
-
}
|
|
19
|
-
install() {
|
|
20
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
const defaultStorageConfig = getStorageConfig(this.storageType());
|
|
22
|
-
if (defaultStorageConfig) {
|
|
23
|
-
const Storage = this.db.getCollection('storages');
|
|
24
|
-
yield Storage.repository.create({
|
|
25
|
-
values: Object.assign(Object.assign({}, defaultStorageConfig.defaults()), { type: this.storageType(), default: true }),
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
load() {
|
|
31
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
yield this.db.import({
|
|
33
|
-
directory: resolve(__dirname, 'collections'),
|
|
34
|
-
});
|
|
35
|
-
// 暂时中间件只能通过 use 加进来
|
|
36
|
-
this.app.resourcer.use(uploadMiddleware);
|
|
37
|
-
this.app.resourcer.registerActionHandler('upload', uploadAction);
|
|
38
|
-
if (process.env.NOCOBASE_ENV !== 'production') {
|
|
39
|
-
yield getStorageConfig(STORAGE_TYPE_LOCAL).middleware(this.app);
|
|
40
|
-
}
|
|
41
|
-
this.app.acl.allow('attachments', 'upload', 'loggedIn');
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
getName() {
|
|
45
|
-
return this.getPackageName(__dirname);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=server.js.map
|
package/esm/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,MAAM;IACnD,WAAW;QACT,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC1C,CAAC;IAEK,OAAO;;YACX,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAClE,IAAI,oBAAoB,EAAE;gBACxB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;gBAClD,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;oBAC9B,MAAM,kCACD,oBAAoB,CAAC,QAAQ,EAAE,KAClC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EACxB,OAAO,EAAE,IAAI,GACd;iBACF,CAAC,CAAC;aACJ;QACH,CAAC;KAAA;IAEK,IAAI;;YACR,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;gBACnB,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC;aAC7C,CAAC,CAAC;YAEH,oBAAoB;YACpB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACzC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAEjE,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,YAAY,EAAE;gBAC7C,MAAM,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aACjE;YAED,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC1D,CAAC;KAAA;IAED,OAAO;QACL,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;CACF","sourcesContent":["import { Plugin } from '@nocobase/server';\nimport { resolve } from 'path';\nimport { action as uploadAction, middleware as uploadMiddleware } from './actions/upload';\nimport { STORAGE_TYPE_LOCAL } from './constants';\nimport { getStorageConfig } from './storages';\n\nexport default class PluginFileManager extends Plugin {\n storageType() {\n return process.env.DEFAULT_STORAGE_TYPE;\n }\n\n async install() {\n const defaultStorageConfig = getStorageConfig(this.storageType());\n if (defaultStorageConfig) {\n const Storage = this.db.getCollection('storages');\n await Storage.repository.create({\n values: {\n ...defaultStorageConfig.defaults(),\n type: this.storageType(),\n default: true,\n },\n });\n }\n }\n\n async load() {\n await this.db.import({\n directory: resolve(__dirname, 'collections'),\n });\n\n // 暂时中间件只能通过 use 加进来\n this.app.resourcer.use(uploadMiddleware);\n this.app.resourcer.registerActionHandler('upload', uploadAction);\n\n if (process.env.NOCOBASE_ENV !== 'production') {\n await getStorageConfig(STORAGE_TYPE_LOCAL).middleware(this.app);\n }\n\n this.app.acl.allow('attachments', 'upload', 'loggedIn');\n }\n\n getName(): string {\n return this.getPackageName(__dirname);\n }\n}\n"]}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
declare const _default: {
|
|
2
|
-
make(storage: any): any;
|
|
3
|
-
defaults(): {
|
|
4
|
-
title: string;
|
|
5
|
-
type: string;
|
|
6
|
-
name: string;
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
options: {
|
|
9
|
-
region: string;
|
|
10
|
-
accessKeyId: string;
|
|
11
|
-
accessKeySecret: string;
|
|
12
|
-
bucket: string;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
export default _default;
|
package/esm/storages/ali-oss.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { STORAGE_TYPE_ALI_OSS } from '../constants';
|
|
2
|
-
import { cloudFilenameGetter } from '../utils';
|
|
3
|
-
export default {
|
|
4
|
-
make(storage) {
|
|
5
|
-
const createAliOssStorage = require('multer-aliyun-oss');
|
|
6
|
-
return new createAliOssStorage({
|
|
7
|
-
config: storage.options,
|
|
8
|
-
filename: cloudFilenameGetter(storage),
|
|
9
|
-
});
|
|
10
|
-
},
|
|
11
|
-
defaults() {
|
|
12
|
-
return {
|
|
13
|
-
title: '阿里云对象存储',
|
|
14
|
-
type: STORAGE_TYPE_ALI_OSS,
|
|
15
|
-
name: 'ali-oss-1',
|
|
16
|
-
baseUrl: process.env.ALI_OSS_STORAGE_BASE_URL,
|
|
17
|
-
options: {
|
|
18
|
-
region: process.env.ALI_OSS_REGION,
|
|
19
|
-
accessKeyId: process.env.ALI_OSS_ACCESS_KEY_ID,
|
|
20
|
-
accessKeySecret: process.env.ALI_OSS_ACCESS_KEY_SECRET,
|
|
21
|
-
bucket: process.env.ALI_OSS_BUCKET,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=ali-oss.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ali-oss.js","sourceRoot":"","sources":["../../src/storages/ali-oss.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,eAAe;IACb,IAAI,CAAC,OAAO;QACV,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;QACzD,OAAO,IAAI,mBAAmB,CAAC;YAC7B,MAAM,EAAE,OAAO,CAAC,OAAO;YACvB,QAAQ,EAAE,mBAAmB,CAAC,OAAO,CAAC;SACvC,CAAC,CAAC;IACL,CAAC;IACD,QAAQ;QACN,OAAO;YACL,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;YAC7C,OAAO,EAAE;gBACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;gBAClC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;gBAC9C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;gBACtD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;aACnC;SACF,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { STORAGE_TYPE_ALI_OSS } from '../constants';\nimport { cloudFilenameGetter } from '../utils';\n\nexport default {\n make(storage) {\n const createAliOssStorage = require('multer-aliyun-oss');\n return new createAliOssStorage({\n config: storage.options,\n filename: cloudFilenameGetter(storage),\n });\n },\n defaults() {\n return {\n title: '阿里云对象存储',\n type: STORAGE_TYPE_ALI_OSS,\n name: 'ali-oss-1',\n baseUrl: process.env.ALI_OSS_STORAGE_BASE_URL,\n options: {\n region: process.env.ALI_OSS_REGION,\n accessKeyId: process.env.ALI_OSS_ACCESS_KEY_ID,\n accessKeySecret: process.env.ALI_OSS_ACCESS_KEY_SECRET,\n bucket: process.env.ALI_OSS_BUCKET,\n },\n };\n },\n};\n"]}
|
package/esm/storages/index.d.ts
DELETED
package/esm/storages/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import local from './local';
|
|
2
|
-
import oss from './ali-oss';
|
|
3
|
-
import s3 from './s3';
|
|
4
|
-
import { STORAGE_TYPE_LOCAL, STORAGE_TYPE_ALI_OSS, STORAGE_TYPE_S3 } from '../constants';
|
|
5
|
-
const map = new Map();
|
|
6
|
-
map.set(STORAGE_TYPE_LOCAL, local);
|
|
7
|
-
map.set(STORAGE_TYPE_ALI_OSS, oss);
|
|
8
|
-
map.set(STORAGE_TYPE_S3, s3);
|
|
9
|
-
export function getStorageConfig(key) {
|
|
10
|
-
return map.get(key);
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storages/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,GAAG,MAAM,WAAW,CAAC;AAC5B,OAAO,EAAE,MAAM,MAAM,CAAC;AAEtB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAUzF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;AACxC,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AACnC,GAAG,CAAC,GAAG,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;AACnC,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;AAE7B,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC","sourcesContent":["import local from './local';\nimport oss from './ali-oss';\nimport s3 from './s3';\n\nimport { STORAGE_TYPE_LOCAL, STORAGE_TYPE_ALI_OSS, STORAGE_TYPE_S3 } from '../constants';\n\nexport interface IStorage {\n filenameKey?: string;\n middleware?: Function;\n getFileData?: Function;\n make: Function;\n defaults: Function;\n}\n\nconst map = new Map<string, IStorage>();\nmap.set(STORAGE_TYPE_LOCAL, local);\nmap.set(STORAGE_TYPE_ALI_OSS, oss);\nmap.set(STORAGE_TYPE_S3, s3);\n\nexport function getStorageConfig(key: string): IStorage {\n return map.get(key);\n}\n"]}
|
package/esm/storages/local.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import Application from '@nocobase/server';
|
|
2
|
-
import multer from 'multer';
|
|
3
|
-
declare function middleware(app: Application, options?: any): Promise<void>;
|
|
4
|
-
declare const _default: {
|
|
5
|
-
middleware: typeof middleware;
|
|
6
|
-
make(storage: any): multer.StorageEngine;
|
|
7
|
-
defaults(): {
|
|
8
|
-
title: string;
|
|
9
|
-
type: string;
|
|
10
|
-
name: string;
|
|
11
|
-
baseUrl: string;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
export default _default;
|