@nocobase/plugin-file-manager 0.7.0-alpha.4 → 0.7.0-alpha.56

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.
Files changed (68) hide show
  1. package/lib/actions/upload.js +236 -161
  2. package/lib/collections/attachments.js +53 -59
  3. package/lib/collections/storages.js +54 -60
  4. package/lib/constants.js +17 -9
  5. package/lib/index.js +29 -19
  6. package/lib/rules/index.js +14 -9
  7. package/lib/rules/mimetype.js +20 -9
  8. package/lib/server.js +91 -48
  9. package/lib/storages/ali-oss.js +36 -26
  10. package/lib/storages/index.js +22 -16
  11. package/lib/storages/local.d.ts +3 -0
  12. package/lib/storages/local.js +240 -119
  13. package/lib/storages/s3.js +77 -52
  14. package/lib/utils.js +43 -20
  15. package/package.json +6 -10
  16. package/esm/actions/upload.d.ts +0 -3
  17. package/esm/actions/upload.js +0 -143
  18. package/esm/actions/upload.js.map +0 -1
  19. package/esm/collections/attachments.d.ts +0 -3
  20. package/esm/collections/attachments.js +0 -59
  21. package/esm/collections/attachments.js.map +0 -1
  22. package/esm/collections/storages.d.ts +0 -3
  23. package/esm/collections/storages.js +0 -60
  24. package/esm/collections/storages.js.map +0 -1
  25. package/esm/constants.d.ts +0 -6
  26. package/esm/constants.js +0 -7
  27. package/esm/constants.js.map +0 -1
  28. package/esm/index.d.ts +0 -2
  29. package/esm/index.js +0 -3
  30. package/esm/index.js.map +0 -1
  31. package/esm/rules/index.d.ts +0 -1
  32. package/esm/rules/index.js +0 -3
  33. package/esm/rules/index.js.map +0 -1
  34. package/esm/rules/mimetype.d.ts +0 -1
  35. package/esm/rules/mimetype.js +0 -5
  36. package/esm/rules/mimetype.js.map +0 -1
  37. package/esm/server.d.ts +0 -7
  38. package/esm/server.js +0 -48
  39. package/esm/server.js.map +0 -1
  40. package/esm/storages/ali-oss.d.ts +0 -16
  41. package/esm/storages/ali-oss.js +0 -26
  42. package/esm/storages/ali-oss.js.map +0 -1
  43. package/esm/storages/index.d.ts +0 -8
  44. package/esm/storages/index.js +0 -12
  45. package/esm/storages/index.js.map +0 -1
  46. package/esm/storages/local.d.ts +0 -14
  47. package/esm/storages/local.js +0 -127
  48. package/esm/storages/local.js.map +0 -1
  49. package/esm/storages/s3.d.ts +0 -17
  50. package/esm/storages/s3.js +0 -53
  51. package/esm/storages/s3.js.map +0 -1
  52. package/esm/utils.d.ts +0 -2
  53. package/esm/utils.js +0 -16
  54. package/esm/utils.js.map +0 -1
  55. package/lib/actions/upload.js.map +0 -1
  56. package/lib/collections/attachments.js.map +0 -1
  57. package/lib/collections/storages.js.map +0 -1
  58. package/lib/constants.js.map +0 -1
  59. package/lib/index.js.map +0 -1
  60. package/lib/rules/index.js.map +0 -1
  61. package/lib/rules/mimetype.js.map +0 -1
  62. package/lib/server.js.map +0 -1
  63. package/lib/storages/ali-oss.js.map +0 -1
  64. package/lib/storages/index.js.map +0 -1
  65. package/lib/storages/local.js.map +0 -1
  66. package/lib/storages/s3.js.map +0 -1
  67. package/lib/utils.js.map +0 -1
  68. package/tsconfig.build.json +0 -9
@@ -1,127 +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 serve from 'koa-static';
11
- import mkdirp from 'mkdirp';
12
- import multer from 'multer';
13
- import path from 'path';
14
- import { URL } from 'url';
15
- import { STORAGE_TYPE_LOCAL } from '../constants';
16
- import { getFilename } from '../utils';
17
- // use koa-mount match logic
18
- function match(basePath, pathname) {
19
- if (!pathname.startsWith(basePath)) {
20
- return false;
21
- }
22
- const newPath = pathname.replace(basePath, '') || '/';
23
- if (basePath.slice(-1) === '/') {
24
- return true;
25
- }
26
- return newPath[0] === '/';
27
- }
28
- function update(app, storages) {
29
- return __awaiter(this, void 0, void 0, function* () {
30
- const Storage = app.db.getCollection('storages');
31
- const items = yield Storage.repository.find({
32
- filter: {
33
- type: STORAGE_TYPE_LOCAL,
34
- },
35
- });
36
- const primaryKey = Storage.model.primaryKeyAttribute;
37
- storages.clear();
38
- for (const storage of items) {
39
- storages.set(storage[primaryKey], storage);
40
- }
41
- });
42
- }
43
- function createLocalServerUpdateHook(app, storages) {
44
- return function (row) {
45
- return __awaiter(this, void 0, void 0, function* () {
46
- if (row.get('type') === STORAGE_TYPE_LOCAL) {
47
- yield update(app, storages);
48
- }
49
- });
50
- };
51
- }
52
- function getDocumentRoot(storage) {
53
- const { documentRoot = 'uploads' } = storage.options || {};
54
- // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹
55
- return path.resolve(path.isAbsolute(documentRoot) ? documentRoot : path.join(process.cwd(), documentRoot));
56
- }
57
- function middleware(app, options) {
58
- return __awaiter(this, void 0, void 0, function* () {
59
- const LOCALHOST = `http://localhost:${process.env.SERVER_PORT || '13002'}`;
60
- const Storage = app.db.getCollection('storages');
61
- const storages = new Map();
62
- const localServerUpdateHook = createLocalServerUpdateHook(app, storages);
63
- Storage.model.addHook('afterCreate', localServerUpdateHook);
64
- Storage.model.addHook('afterUpdate', localServerUpdateHook);
65
- Storage.model.addHook('afterDestroy', localServerUpdateHook);
66
- app.on('beforeStart', () => __awaiter(this, void 0, void 0, function* () {
67
- yield update(app, storages);
68
- }));
69
- app.use(function (ctx, next) {
70
- var _a;
71
- return __awaiter(this, void 0, void 0, function* () {
72
- for (const storage of storages.values()) {
73
- const baseUrl = storage.get('baseUrl');
74
- let url;
75
- try {
76
- url = new URL(baseUrl);
77
- }
78
- catch (e) {
79
- url = {
80
- pathname: baseUrl,
81
- };
82
- }
83
- // 以下情况才认为当前进程所应该提供静态服务
84
- // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)
85
- if (url.origin && ((_a = storage === null || storage === void 0 ? void 0 : storage.options) === null || _a === void 0 ? void 0 : _a.serve) === false) {
86
- continue;
87
- }
88
- const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;
89
- if (!match(basePath, ctx.path)) {
90
- continue;
91
- }
92
- return serve(getDocumentRoot(storage), {
93
- // for handle files after any api handlers
94
- defer: true,
95
- })(ctx, () => __awaiter(this, void 0, void 0, function* () {
96
- if (ctx.path.startsWith(basePath)) {
97
- ctx.path = ctx.path.replace(basePath, '');
98
- }
99
- yield next();
100
- }));
101
- }
102
- yield next();
103
- });
104
- });
105
- });
106
- }
107
- export default {
108
- middleware,
109
- make(storage) {
110
- return multer.diskStorage({
111
- destination: function (req, file, cb) {
112
- const destPath = path.join(getDocumentRoot(storage), storage.path);
113
- mkdirp(destPath, (err) => cb(err, destPath));
114
- },
115
- filename: getFilename,
116
- });
117
- },
118
- defaults() {
119
- return {
120
- title: '本地存储',
121
- type: STORAGE_TYPE_LOCAL,
122
- name: `local`,
123
- baseUrl: process.env.LOCAL_STORAGE_BASE_URL || `http://localhost:${process.env.SERVER_PORT || '13002'}/uploads`,
124
- };
125
- },
126
- };
127
- //# sourceMappingURL=local.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storages/local.ts"],"names":[],"mappings":"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","sourcesContent":["import Application from '@nocobase/server';\nimport serve from 'koa-static';\nimport mkdirp from 'mkdirp';\nimport multer from 'multer';\nimport path from 'path';\nimport { URL } from 'url';\nimport { STORAGE_TYPE_LOCAL } from '../constants';\nimport { getFilename } from '../utils';\n\n// use koa-mount match logic\nfunction match(basePath: string, pathname: string): boolean {\n if (!pathname.startsWith(basePath)) {\n return false;\n }\n\n const newPath = pathname.replace(basePath, '') || '/';\n if (basePath.slice(-1) === '/') {\n return true;\n }\n\n return newPath[0] === '/';\n}\n\nasync function update(app: Application, storages) {\n const Storage = app.db.getCollection('storages');\n\n const items = await Storage.repository.find({\n filter: {\n type: STORAGE_TYPE_LOCAL,\n },\n });\n\n const primaryKey = Storage.model.primaryKeyAttribute;\n\n storages.clear();\n for (const storage of items) {\n storages.set(storage[primaryKey], storage);\n }\n}\n\nfunction createLocalServerUpdateHook(app, storages) {\n return async function (row) {\n if (row.get('type') === STORAGE_TYPE_LOCAL) {\n await update(app, storages);\n }\n };\n}\n\nfunction getDocumentRoot(storage): string {\n const { documentRoot = 'uploads' } = storage.options || {};\n // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹\n return path.resolve(path.isAbsolute(documentRoot) ? documentRoot : path.join(process.cwd(), documentRoot));\n}\n\nasync function middleware(app: Application, options?) {\n const LOCALHOST = `http://localhost:${process.env.SERVER_PORT || '13002'}`;\n\n const Storage = app.db.getCollection('storages');\n const storages = new Map<string, any>();\n\n const localServerUpdateHook = createLocalServerUpdateHook(app, storages);\n Storage.model.addHook('afterCreate', localServerUpdateHook);\n Storage.model.addHook('afterUpdate', localServerUpdateHook);\n Storage.model.addHook('afterDestroy', localServerUpdateHook);\n\n app.on('beforeStart', async () => {\n await update(app, storages);\n });\n\n app.use(async function (ctx, next) {\n for (const storage of storages.values()) {\n const baseUrl = storage.get('baseUrl');\n\n let url;\n try {\n url = new URL(baseUrl);\n } catch (e) {\n url = {\n pathname: baseUrl,\n };\n }\n\n // 以下情况才认为当前进程所应该提供静态服务\n // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)\n if (url.origin && storage?.options?.serve === false) {\n continue;\n }\n\n const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;\n\n if (!match(basePath, ctx.path)) {\n continue;\n }\n\n return serve(getDocumentRoot(storage), {\n // for handle files after any api handlers\n defer: true,\n })(ctx, async () => {\n if (ctx.path.startsWith(basePath)) {\n ctx.path = ctx.path.replace(basePath, '');\n }\n await next();\n });\n }\n\n await next();\n });\n}\n\nexport default {\n middleware,\n make(storage) {\n return multer.diskStorage({\n destination: function (req, file, cb) {\n const destPath = path.join(getDocumentRoot(storage), storage.path);\n mkdirp(destPath, (err: Error | null) => cb(err, destPath));\n },\n filename: getFilename,\n });\n },\n defaults() {\n return {\n title: '本地存储',\n type: STORAGE_TYPE_LOCAL,\n name: `local`,\n baseUrl: process.env.LOCAL_STORAGE_BASE_URL || `http://localhost:${process.env.SERVER_PORT || '13002'}/uploads`,\n };\n },\n};\n"]}
@@ -1,17 +0,0 @@
1
- declare const _default: {
2
- filenameKey: string;
3
- make(storage: any): any;
4
- defaults(): {
5
- title: string;
6
- name: string;
7
- type: string;
8
- baseUrl: string;
9
- options: {
10
- region: string;
11
- accessKeyId: string;
12
- secretAccessKey: string;
13
- bucket: string;
14
- };
15
- };
16
- };
17
- export default _default;
@@ -1,53 +0,0 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { STORAGE_TYPE_S3 } from '../constants';
13
- import { cloudFilenameGetter } from '../utils';
14
- export default {
15
- filenameKey: 'key',
16
- make(storage) {
17
- const S3Client = require('aws-sdk/clients/s3');
18
- const multerS3 = require('multer-s3');
19
- const _a = storage.options, { accessKeyId, secretAccessKey, bucket, acl = 'public-read' } = _a, options = __rest(_a, ["accessKeyId", "secretAccessKey", "bucket", "acl"]);
20
- const s3 = new S3Client(Object.assign(Object.assign({}, options), { credentials: {
21
- accessKeyId,
22
- secretAccessKey,
23
- } }));
24
- return multerS3({
25
- s3,
26
- bucket,
27
- acl,
28
- contentType(req, file, cb) {
29
- if (file.mimetype) {
30
- cb(null, file.mimetype);
31
- return;
32
- }
33
- multerS3.AUTO_CONTENT_TYPE(req, file, cb);
34
- },
35
- key: cloudFilenameGetter(storage),
36
- });
37
- },
38
- defaults() {
39
- return {
40
- title: 'AWS S3',
41
- name: 'aws-s3',
42
- type: STORAGE_TYPE_S3,
43
- baseUrl: process.env.AWS_S3_STORAGE_BASE_URL,
44
- options: {
45
- region: process.env.AWS_S3_REGION,
46
- accessKeyId: process.env.AWS_ACCESS_KEY_ID,
47
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
48
- bucket: process.env.AWS_S3_BUCKET,
49
- },
50
- };
51
- },
52
- };
53
- //# sourceMappingURL=s3.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/storages/s3.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,eAAe;IACb,WAAW,EAAE,KAAK;IAClB,IAAI,CAAC,OAAO;QACV,MAAM,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,KAA4E,OAAO,CAAC,OAAO,EAA3F,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,GAAG,aAAa,OAAgC,EAA3B,OAAO,cAAvE,mDAAyE,CAAkB,CAAC;QAClG,MAAM,EAAE,GAAG,IAAI,QAAQ,iCAClB,OAAO,KACV,WAAW,EAAE;gBACX,WAAW;gBACX,eAAe;aAChB,IACD,CAAC;QAEH,OAAO,QAAQ,CAAC;YACd,EAAE;YACF,MAAM;YACN,GAAG;YACH,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;gBACvB,IAAI,IAAI,CAAC,QAAQ,EAAE;oBACjB,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACxB,OAAO;iBACR;gBAED,QAAQ,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,GAAG,EAAE,mBAAmB,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IACD,QAAQ;QACN,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;YAC5C,OAAO,EAAE;gBACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;gBACjC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBAC1C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;gBAClD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;aAClC;SACF,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { STORAGE_TYPE_S3 } from '../constants';\nimport { cloudFilenameGetter } from '../utils';\n\nexport default {\n filenameKey: 'key',\n make(storage) {\n const S3Client = require('aws-sdk/clients/s3');\n const multerS3 = require('multer-s3');\n const { accessKeyId, secretAccessKey, bucket, acl = 'public-read', ...options } = storage.options;\n const s3 = new S3Client({\n ...options,\n credentials: {\n accessKeyId,\n secretAccessKey,\n },\n });\n\n return multerS3({\n s3,\n bucket,\n acl,\n contentType(req, file, cb) {\n if (file.mimetype) {\n cb(null, file.mimetype);\n return;\n }\n\n multerS3.AUTO_CONTENT_TYPE(req, file, cb);\n },\n key: cloudFilenameGetter(storage),\n });\n },\n defaults() {\n return {\n title: 'AWS S3',\n name: 'aws-s3',\n type: STORAGE_TYPE_S3,\n baseUrl: process.env.AWS_S3_STORAGE_BASE_URL,\n options: {\n region: process.env.AWS_S3_REGION,\n accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n bucket: process.env.AWS_S3_BUCKET,\n },\n };\n },\n};\n"]}
package/esm/utils.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export declare function getFilename(req: any, file: any, cb: any): void;
2
- export declare const cloudFilenameGetter: (storage: any) => (req: any, file: any, cb: any) => void;
package/esm/utils.js DELETED
@@ -1,16 +0,0 @@
1
- import crypto from 'crypto';
2
- import path from 'path';
3
- export function getFilename(req, file, cb) {
4
- crypto.pseudoRandomBytes(16, function (err, raw) {
5
- cb(err, err ? undefined : `${raw.toString('hex')}${path.extname(file.originalname)}`);
6
- });
7
- }
8
- export const cloudFilenameGetter = (storage) => (req, file, cb) => {
9
- getFilename(req, file, (err, filename) => {
10
- if (err) {
11
- return cb(err);
12
- }
13
- cb(null, `${storage.path ? `${storage.path}/` : ''}${filename}`);
14
- });
15
- };
16
- //# sourceMappingURL=utils.js.map
package/esm/utils.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IACvC,MAAM,CAAC,iBAAiB,CAAC,EAAE,EAAE,UAAU,GAAG,EAAE,GAAG;QAC7C,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;IAChE,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;QACvC,IAAI,GAAG,EAAE;YACP,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;SAChB;QACD,EAAE,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["import crypto from 'crypto';\nimport path from 'path';\n\nexport function getFilename(req, file, cb) {\n crypto.pseudoRandomBytes(16, function (err, raw) {\n cb(err, err ? undefined : `${raw.toString('hex')}${path.extname(file.originalname)}`);\n });\n}\n\nexport const cloudFilenameGetter = (storage) => (req, file, cb) => {\n getFilename(req, file, (err, filename) => {\n if (err) {\n return cb(err);\n }\n cb(null, `${storage.path ? `${storage.path}/` : ''}${filename}`);\n });\n};\n"]}
@@ -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 +0,0 @@
1
- {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/collections/attachments.ts"],"names":[],"mappings":";;AAEA,kBAAe;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 +0,0 @@
1
- {"version":3,"file":"storages.js","sourceRoot":"","sources":["../../src/collections/storages.ts"],"names":[],"mappings":";;AAEA,kBAAe;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"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,eAAe,GAAG,MAAM,CAAC;AACzB,QAAA,WAAW,GAAG,CAAC,CAAC;AAChB,QAAA,mBAAmB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzC,QAAA,kBAAkB,GAAG,OAAO,CAAC;AAC7B,QAAA,oBAAoB,GAAG,SAAS,CAAC;AACjC,QAAA,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/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,mCAAmC;AAA1B,kHAAA,OAAO,OAAA","sourcesContent":["export * from './constants';\nexport { default } from './server';\n\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":";;;;;;AAAA,uCAAiD;AAAxC,qHAAA,OAAO,OAAY;AAE5B,oCAAoC","sourcesContent":["export { default as mimetype } from './mimetype';\n\n// TODO(feature): 提供注册新规则的方法,规则可动态添加\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mimetype.js","sourceRoot":"","sources":["../../src/rules/mimetype.ts"],"names":[],"mappings":";;;;;AAAA,4DAA+B;AAE/B,mBAAyB,IAAI,EAAE,UAA6B,GAAG,EAAE,GAAG;IAClE,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,oBAAK,EAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC;AAFD,4BAEC","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/lib/server.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,6CAA0C;AAC1C,+BAA+B;AAC/B,6CAA0F;AAC1F,2CAAiD;AACjD,yCAA8C;AAE9C,MAAqB,iBAAkB,SAAQ,eAAM;IACnD,WAAW;QACT,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC1C,CAAC;IAEK,OAAO;;YACX,MAAM,oBAAoB,GAAG,IAAA,2BAAgB,EAAC,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,IAAA,cAAO,EAAC,SAAS,EAAE,aAAa,CAAC;aAC7C,CAAC,CAAC;YAEH,oBAAoB;YACpB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAgB,CAAC,CAAC;YACzC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,QAAQ,EAAE,eAAY,CAAC,CAAC;YAEjE,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,YAAY,EAAE;gBAC7C,MAAM,IAAA,2BAAgB,EAAC,8BAAkB,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;AAtCD,oCAsCC","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 +0,0 @@
1
- {"version":3,"file":"ali-oss.js","sourceRoot":"","sources":["../../src/storages/ali-oss.ts"],"names":[],"mappings":";;AAAA,4CAAoD;AACpD,oCAA+C;AAE/C,kBAAe;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,IAAA,2BAAmB,EAAC,OAAO,CAAC;SACvC,CAAC,CAAC;IACL,CAAC;IACD,QAAQ;QACN,OAAO;YACL,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,gCAAoB;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"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storages/index.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,wDAA4B;AAC5B,8CAAsB;AAEtB,4CAAyF;AAUzF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;AACxC,GAAG,CAAC,GAAG,CAAC,8BAAkB,EAAE,eAAK,CAAC,CAAC;AACnC,GAAG,CAAC,GAAG,CAAC,gCAAoB,EAAE,iBAAG,CAAC,CAAC;AACnC,GAAG,CAAC,GAAG,CAAC,2BAAe,EAAE,YAAE,CAAC,CAAC;AAE7B,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAFD,4CAEC","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"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storages/local.ts"],"names":[],"mappings":"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","sourcesContent":["import Application from '@nocobase/server';\nimport serve from 'koa-static';\nimport mkdirp from 'mkdirp';\nimport multer from 'multer';\nimport path from 'path';\nimport { URL } from 'url';\nimport { STORAGE_TYPE_LOCAL } from '../constants';\nimport { getFilename } from '../utils';\n\n// use koa-mount match logic\nfunction match(basePath: string, pathname: string): boolean {\n if (!pathname.startsWith(basePath)) {\n return false;\n }\n\n const newPath = pathname.replace(basePath, '') || '/';\n if (basePath.slice(-1) === '/') {\n return true;\n }\n\n return newPath[0] === '/';\n}\n\nasync function update(app: Application, storages) {\n const Storage = app.db.getCollection('storages');\n\n const items = await Storage.repository.find({\n filter: {\n type: STORAGE_TYPE_LOCAL,\n },\n });\n\n const primaryKey = Storage.model.primaryKeyAttribute;\n\n storages.clear();\n for (const storage of items) {\n storages.set(storage[primaryKey], storage);\n }\n}\n\nfunction createLocalServerUpdateHook(app, storages) {\n return async function (row) {\n if (row.get('type') === STORAGE_TYPE_LOCAL) {\n await update(app, storages);\n }\n };\n}\n\nfunction getDocumentRoot(storage): string {\n const { documentRoot = 'uploads' } = storage.options || {};\n // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹\n return path.resolve(path.isAbsolute(documentRoot) ? documentRoot : path.join(process.cwd(), documentRoot));\n}\n\nasync function middleware(app: Application, options?) {\n const LOCALHOST = `http://localhost:${process.env.SERVER_PORT || '13002'}`;\n\n const Storage = app.db.getCollection('storages');\n const storages = new Map<string, any>();\n\n const localServerUpdateHook = createLocalServerUpdateHook(app, storages);\n Storage.model.addHook('afterCreate', localServerUpdateHook);\n Storage.model.addHook('afterUpdate', localServerUpdateHook);\n Storage.model.addHook('afterDestroy', localServerUpdateHook);\n\n app.on('beforeStart', async () => {\n await update(app, storages);\n });\n\n app.use(async function (ctx, next) {\n for (const storage of storages.values()) {\n const baseUrl = storage.get('baseUrl');\n\n let url;\n try {\n url = new URL(baseUrl);\n } catch (e) {\n url = {\n pathname: baseUrl,\n };\n }\n\n // 以下情况才认为当前进程所应该提供静态服务\n // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)\n if (url.origin && storage?.options?.serve === false) {\n continue;\n }\n\n const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;\n\n if (!match(basePath, ctx.path)) {\n continue;\n }\n\n return serve(getDocumentRoot(storage), {\n // for handle files after any api handlers\n defer: true,\n })(ctx, async () => {\n if (ctx.path.startsWith(basePath)) {\n ctx.path = ctx.path.replace(basePath, '');\n }\n await next();\n });\n }\n\n await next();\n });\n}\n\nexport default {\n middleware,\n make(storage) {\n return multer.diskStorage({\n destination: function (req, file, cb) {\n const destPath = path.join(getDocumentRoot(storage), storage.path);\n mkdirp(destPath, (err: Error | null) => cb(err, destPath));\n },\n filename: getFilename,\n });\n },\n defaults() {\n return {\n title: '本地存储',\n type: STORAGE_TYPE_LOCAL,\n name: `local`,\n baseUrl: process.env.LOCAL_STORAGE_BASE_URL || `http://localhost:${process.env.SERVER_PORT || '13002'}/uploads`,\n };\n },\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/storages/s3.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,4CAA+C;AAC/C,oCAA+C;AAE/C,kBAAe;IACb,WAAW,EAAE,KAAK;IAClB,IAAI,CAAC,OAAO;QACV,MAAM,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,KAA4E,OAAO,CAAC,OAAO,EAA3F,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,GAAG,aAAa,OAAgC,EAA3B,OAAO,cAAvE,mDAAyE,CAAkB,CAAC;QAClG,MAAM,EAAE,GAAG,IAAI,QAAQ,iCAClB,OAAO,KACV,WAAW,EAAE;gBACX,WAAW;gBACX,eAAe;aAChB,IACD,CAAC;QAEH,OAAO,QAAQ,CAAC;YACd,EAAE;YACF,MAAM;YACN,GAAG;YACH,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;gBACvB,IAAI,IAAI,CAAC,QAAQ,EAAE;oBACjB,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACxB,OAAO;iBACR;gBAED,QAAQ,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,GAAG,EAAE,IAAA,2BAAmB,EAAC,OAAO,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IACD,QAAQ;QACN,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,2BAAe;YACrB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;YAC5C,OAAO,EAAE;gBACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;gBACjC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBAC1C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;gBAClD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;aAClC;SACF,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { STORAGE_TYPE_S3 } from '../constants';\nimport { cloudFilenameGetter } from '../utils';\n\nexport default {\n filenameKey: 'key',\n make(storage) {\n const S3Client = require('aws-sdk/clients/s3');\n const multerS3 = require('multer-s3');\n const { accessKeyId, secretAccessKey, bucket, acl = 'public-read', ...options } = storage.options;\n const s3 = new S3Client({\n ...options,\n credentials: {\n accessKeyId,\n secretAccessKey,\n },\n });\n\n return multerS3({\n s3,\n bucket,\n acl,\n contentType(req, file, cb) {\n if (file.mimetype) {\n cb(null, file.mimetype);\n return;\n }\n\n multerS3.AUTO_CONTENT_TYPE(req, file, cb);\n },\n key: cloudFilenameGetter(storage),\n });\n },\n defaults() {\n return {\n title: 'AWS S3',\n name: 'aws-s3',\n type: STORAGE_TYPE_S3,\n baseUrl: process.env.AWS_S3_STORAGE_BASE_URL,\n options: {\n region: process.env.AWS_S3_REGION,\n accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n bucket: process.env.AWS_S3_BUCKET,\n },\n };\n },\n};\n"]}
package/lib/utils.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,gDAAwB;AAExB,SAAgB,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IACvC,gBAAM,CAAC,iBAAiB,CAAC,EAAE,EAAE,UAAU,GAAG,EAAE,GAAG;QAC7C,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;AACL,CAAC;AAJD,kCAIC;AAEM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;IAChE,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;QACvC,IAAI,GAAG,EAAE;YACP,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;SAChB;QACD,EAAE,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAPW,QAAA,mBAAmB,uBAO9B","sourcesContent":["import crypto from 'crypto';\nimport path from 'path';\n\nexport function getFilename(req, file, cb) {\n crypto.pseudoRandomBytes(16, function (err, raw) {\n cb(err, err ? undefined : `${raw.toString('hex')}${path.extname(file.originalname)}`);\n });\n}\n\nexport const cloudFilenameGetter = (storage) => (req, file, cb) => {\n getFilename(req, file, (err, filename) => {\n if (err) {\n return cb(err);\n }\n cb(null, `${storage.path ? `${storage.path}/` : ''}${filename}`);\n });\n};\n"]}
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.build.json",
3
- "compilerOptions": {
4
- "outDir": "./lib",
5
- "declaration": true
6
- },
7
- "include": ["./src/**/*.ts", "./src/**/*.tsx"],
8
- "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
9
- }