@nocobase/plugin-file-manager 0.5.0-alpha.30 → 0.5.0-alpha.34

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.
@@ -186,7 +186,7 @@ function middleware(ctx, next) {
186
186
  },
187
187
  storage: makeStorage(storage)
188
188
  };
189
- const upload = multer_1.default(multerOptions);
189
+ const upload = (0, multer_1.default)(multerOptions);
190
190
  return upload.single(constants_1.FILE_FIELD_NAME)(ctx, next);
191
191
  });
192
192
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["actions/upload.ts"],"names":[],"mappings":"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","file":"upload.js","sourcesContent":["import path from 'path';\nimport multer from '@koa/multer';\nimport { Context, Next } from '@nocobase/actions';\nimport storageMakers from '../storages';\nimport * as Rules from '../rules';\nimport { FILE_FIELD_NAME, LIMIT_FILES, LIMIT_MAX_FILE_SIZE } from '../constants';\n\nfunction getRules(ctx: Context) {\n const { resourceField } = ctx.action.params;\n if (!resourceField) {\n return ctx.storage.rules;\n }\n const { rules = {} } = resourceField.getOptions().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 = !ruleKeys.length || !ruleKeys\n .some(key => typeof Rules[key] !== 'function'\n || !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, resourceField } = 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 StorageModel = ctx.db.getModel('storages');\n let storage;\n\n if (resourceName === 'attachments') {\n // 如果没有包含关联,则直接按默认文件上传至默认存储引擎\n storage = await StorageModel.findOne({ where: { default: true } });\n } else {\n const fieldOptions = resourceField.getOptions();\n storage = await StorageModel.findOne({\n where: fieldOptions.defaultValue\n ? { [StorageModel.primaryKeyAttribute]: fieldOptions.defaultValue }\n : { 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 makeStorage = storageMakers.get(storage.type);\n if (!makeStorage) {\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: makeStorage(storage),\n };\n const upload = multer(multerOptions);\n return upload.single(FILE_FIELD_NAME)(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 const { associatedName, associatedKey, resourceField } = ctx.action.params;\n const extname = path.extname(file.filename);\n const data = {\n title: file.originalname.replace(extname, ''),\n filename: file.filename,\n extname,\n // TODO(feature): 暂时两者相同,后面 storage.path 模版化以后,这里只是 file 实际的 path\n path: storage.path,\n size: file.size,\n // 直接缓存起来\n url: `${storage.baseUrl}${storage.path}/${file.filename}`,\n mimetype: file.mimetype,\n // @ts-ignore\n meta: ctx.request.body\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 if (associatedKey && resourceField) {\n const Attachment = ctx.db.getModel('attachments');\n const SourceModel = ctx.db.getModel(associatedName);\n const source = await SourceModel.findByPk(associatedKey, { transaction });\n await source[resourceField.getAccessors().set](result[Attachment.primaryKeyAttribute], { transaction });\n }\n\n return result;\n });\n\n // 将存储引擎的信息附在已创建的记录里,节省一次查询\n // attachment.setDataValue('storage', storage);\n ctx.body = attachment;\n\n await next();\n};\n"]}
1
+ {"version":3,"sources":["actions/upload.ts"],"names":[],"mappings":"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","file":"upload.js","sourcesContent":["import path from 'path';\nimport multer from '@koa/multer';\nimport { Context, Next } from '@nocobase/actions';\nimport storageMakers from '../storages';\nimport * as Rules from '../rules';\nimport { FILE_FIELD_NAME, LIMIT_FILES, LIMIT_MAX_FILE_SIZE } from '../constants';\n\nfunction getRules(ctx: Context) {\n const { resourceField } = ctx.action.params;\n if (!resourceField) {\n return ctx.storage.rules;\n }\n const { rules = {} } = resourceField.getOptions().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 = !ruleKeys.length || !ruleKeys\n .some(key => typeof Rules[key] !== 'function'\n || !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, resourceField } = 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 StorageModel = ctx.db.getModel('storages');\n let storage;\n\n if (resourceName === 'attachments') {\n // 如果没有包含关联,则直接按默认文件上传至默认存储引擎\n storage = await StorageModel.findOne({ where: { default: true } });\n } else {\n const fieldOptions = resourceField.getOptions();\n storage = await StorageModel.findOne({\n where: fieldOptions.defaultValue\n ? { [StorageModel.primaryKeyAttribute]: fieldOptions.defaultValue }\n : { 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 makeStorage = storageMakers.get(storage.type);\n if (!makeStorage) {\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: makeStorage(storage),\n };\n const upload = multer(multerOptions);\n return upload.single(FILE_FIELD_NAME)(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 const { associatedName, associatedKey, resourceField } = ctx.action.params;\n const extname = path.extname(file.filename);\n const data = {\n title: file.originalname.replace(extname, ''),\n filename: file.filename,\n extname,\n // TODO(feature): 暂时两者相同,后面 storage.path 模版化以后,这里只是 file 实际的 path\n path: storage.path,\n size: file.size,\n // 直接缓存起来\n url: `${storage.baseUrl}${storage.path}/${file.filename}`,\n mimetype: file.mimetype,\n // @ts-ignore\n meta: ctx.request.body\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 if (associatedKey && resourceField) {\n const Attachment = ctx.db.getModel('attachments');\n const SourceModel = ctx.db.getModel(associatedName);\n const source = await SourceModel.findByPk(associatedKey, { transaction });\n await source[resourceField.getAccessors().set](result[Attachment.primaryKeyAttribute], { transaction });\n }\n\n return result;\n });\n\n // 将存储引擎的信息附在已创建的记录里,节省一次查询\n // attachment.setDataValue('storage', storage);\n ctx.body = attachment;\n\n await next();\n};\n"]}
@@ -25,7 +25,7 @@ Object.defineProperty(exports, "__esModule", {
25
25
  const mime_match_1 = __importDefault(require("mime-match"));
26
26
 
27
27
  function default_1(file, options = '*', ctx) {
28
- return options.toString().split(',').some(mime_match_1.default(file.mimetype));
28
+ return options.toString().split(',').some((0, mime_match_1.default)(file.mimetype));
29
29
  }
30
30
 
31
31
  exports.default = default_1;
@@ -1 +1 @@
1
- {"version":3,"sources":["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,oBAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC;AAFD,4BAEC","file":"mimetype.js","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"]}
1
+ {"version":3,"sources":["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","file":"mimetype.js","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 CHANGED
@@ -72,7 +72,7 @@ exports.default = {
72
72
  });
73
73
  resourcer.use(upload_1.middleware);
74
74
  resourcer.registerActionHandler('upload', upload_1.action);
75
- local_1.middleware(this.app);
75
+ (0, local_1.middleware)(this.app);
76
76
  const Storage = database.getModel('storages');
77
77
  this.app.on('db.init', () => __awaiter(this, void 0, void 0, function* () {
78
78
  yield Storage.create({
package/lib/server.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["server.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,gDAAwB;AAKxB,6CAG0B;AAC1B,4CAE0B;AAE1B,kBAAe;IACb,IAAI,EAAE,cAAc;IACd,IAAI;;YACR,MAAM,QAAQ,GAAa,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,SAAS,GAAc,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YAEhD,QAAQ,CAAC,MAAM,CAAC;gBACd,SAAS,EAAE,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC;aAClD,CAAC,CAAC;YAGH,SAAS,CAAC,GAAG,CAAC,mBAAgB,CAAC,CAAC;YAChC,SAAS,CAAC,qBAAqB,CAAC,QAAQ,EAAE,eAAY,CAAC,CAAC;YACxD,kBAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAE1B,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAE9C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAS,EAAE;gBAChC,MAAM,OAAO,CAAC,MAAM,CAAC;oBACnB,KAAK,EAAE,MAAM;oBACb,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;oBAC3C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,OAAO;iBAC9C,CAAC,CAAC;gBACH,MAAM,OAAO,CAAC,MAAM,CAAC;oBACnB,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;oBAC7C,OAAO,EAAE;wBACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;wBAClC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;wBAC9C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;wBACtD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;qBACnC;oBACD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,SAAS;iBAChD,CAAC,CAAC;YACL,CAAC,CAAA,CAAC,CAAC;QACL,CAAC;KAAA;CACe,CAAC","file":"server.js","sourcesContent":["import path from 'path';\nimport Database from '@nocobase/database';\nimport Resourcer from '@nocobase/resourcer';\nimport { PluginOptions, Plugin } from '@nocobase/server';\n\nimport {\n action as uploadAction,\n middleware as uploadMiddleware,\n} from './actions/upload';\nimport {\n middleware as localMiddleware,\n} from './storages/local';\n\nexport default {\n name: 'file-manager',\n async load() {\n const database: Database = this.app.db;\n const resourcer: Resourcer = this.app.resourcer;\n \n database.import({\n directory: path.resolve(__dirname, 'collections'),\n });\n \n // 暂时中间件只能通过 use 加进来\n resourcer.use(uploadMiddleware);\n resourcer.registerActionHandler('upload', uploadAction);\n localMiddleware(this.app);\n \n const Storage = database.getModel('storages');\n \n this.app.on('db.init', async () => {\n await Storage.create({\n title: '本地存储',\n name: `local`,\n type: 'local',\n baseUrl: process.env.LOCAL_STORAGE_BASE_URL,\n default: process.env.STORAGE_TYPE === 'local',\n });\n await Storage.create({\n name: `ali-oss`,\n type: 'ali-oss',\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 default: process.env.STORAGE_TYPE === 'ali-oss',\n });\n });\n },\n} as PluginOptions;\n"]}
1
+ {"version":3,"sources":["server.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,gDAAwB;AAKxB,6CAG0B;AAC1B,4CAE0B;AAE1B,kBAAe;IACb,IAAI,EAAE,cAAc;IACd,IAAI;;YACR,MAAM,QAAQ,GAAa,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,SAAS,GAAc,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YAEhD,QAAQ,CAAC,MAAM,CAAC;gBACd,SAAS,EAAE,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC;aAClD,CAAC,CAAC;YAGH,SAAS,CAAC,GAAG,CAAC,mBAAgB,CAAC,CAAC;YAChC,SAAS,CAAC,qBAAqB,CAAC,QAAQ,EAAE,eAAY,CAAC,CAAC;YACxD,IAAA,kBAAe,EAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAE1B,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAE9C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAS,EAAE;gBAChC,MAAM,OAAO,CAAC,MAAM,CAAC;oBACnB,KAAK,EAAE,MAAM;oBACb,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;oBAC3C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,OAAO;iBAC9C,CAAC,CAAC;gBACH,MAAM,OAAO,CAAC,MAAM,CAAC;oBACnB,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;oBAC7C,OAAO,EAAE;wBACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;wBAClC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;wBAC9C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;wBACtD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;qBACnC;oBACD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,SAAS;iBAChD,CAAC,CAAC;YACL,CAAC,CAAA,CAAC,CAAC;QACL,CAAC;KAAA;CACe,CAAC","file":"server.js","sourcesContent":["import path from 'path';\nimport Database from '@nocobase/database';\nimport Resourcer from '@nocobase/resourcer';\nimport { PluginOptions, Plugin } from '@nocobase/server';\n\nimport {\n action as uploadAction,\n middleware as uploadMiddleware,\n} from './actions/upload';\nimport {\n middleware as localMiddleware,\n} from './storages/local';\n\nexport default {\n name: 'file-manager',\n async load() {\n const database: Database = this.app.db;\n const resourcer: Resourcer = this.app.resourcer;\n \n database.import({\n directory: path.resolve(__dirname, 'collections'),\n });\n \n // 暂时中间件只能通过 use 加进来\n resourcer.use(uploadMiddleware);\n resourcer.registerActionHandler('upload', uploadAction);\n localMiddleware(this.app);\n \n const Storage = database.getModel('storages');\n \n this.app.on('db.init', async () => {\n await Storage.create({\n title: '本地存储',\n name: `local`,\n type: 'local',\n baseUrl: process.env.LOCAL_STORAGE_BASE_URL,\n default: process.env.STORAGE_TYPE === 'local',\n });\n await Storage.create({\n name: `ali-oss`,\n type: 'ali-oss',\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 default: process.env.STORAGE_TYPE === 'ali-oss',\n });\n });\n },\n} as PluginOptions;\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["storages/local.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAM5B,wBAAgB,eAAe,CAAC,OAAO,KAAA,GAAG,MAAM,CAM/C;AAGD,wBAAgB,UAAU,CAAC,GAAG,KAAA,OA8C7B;;AAED,wBAQG","file":"local.d.ts","sourcesContent":["import path from 'path';\nimport { URL } from 'url';\nimport mkdirp from 'mkdirp';\nimport multer from 'multer';\nimport serve from 'koa-static';\nimport mount from 'koa-mount';\nimport { STORAGE_TYPE_LOCAL } from '../constants';\nimport { getFilename } from '../utils';\n\nexport function getDocumentRoot(storage): string {\n const { documentRoot = 'uploads' } = storage.options || {};\n // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹\n return path.resolve(path.isAbsolute(documentRoot)\n ? documentRoot\n : path.join(process.cwd(), documentRoot), storage.path);\n}\n\n// TODO(optimize): 初始化的时机不应该放在中间件里\nexport function middleware(app) {\n const storages = new Map<string, any>();\n const StorageModel = app.db.getModel('storages');\n\n return app.use(async function (ctx, next) {\n const items = await StorageModel.findAll({\n where: {\n type: STORAGE_TYPE_LOCAL,\n }\n });\n\n const primaryKey = StorageModel.primaryKeyAttribute;\n\n for (const storage of items) {\n\n // TODO:未解决 storage 更新问题\n if (storages.has(storage[primaryKey])) {\n continue;\n }\n\n const baseUrl = storage.get('baseUrl');\n\n let url;\n try {\n url = new URL(baseUrl);\n } catch (e) {\n url = {\n protocol: 'http:',\n hostname: 'localhost',\n port: process.env.API_PORT,\n pathname: baseUrl\n };\n }\n\n // 以下情况才认为当前进程所应该提供静态服务\n // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)\n // TODO(bug): https、端口 80 默认值和其他本地 ip/hostname 的情况未考虑\n // TODO 实际应该用 NOCOBASE_ENV 来判断,或者抛给 env 处理\n if (process.env.LOCAL_STORAGE_USE_STATIC_SERVER) {\n const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;\n app.use(mount(basePath, serve(getDocumentRoot(storage))));\n }\n storages.set(storage.primaryKey, storage);\n }\n await next();\n });\n}\n\nexport default (storage) => multer.diskStorage({\n destination: function (req, file, cb) {\n const destPath = getDocumentRoot(storage);\n mkdirp(destPath).then(() => {\n cb(null, destPath);\n }).catch(cb);\n },\n filename: getFilename\n});\n"]}
1
+ {"version":3,"sources":["storages/local.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAM5B,wBAAgB,eAAe,CAAC,OAAO,KAAA,GAAG,MAAM,CAM/C;AAGD,wBAAgB,UAAU,CAAC,GAAG,KAAA,OAkD7B;;AAED,wBAQG","file":"local.d.ts","sourcesContent":["import path from 'path';\nimport { URL } from 'url';\nimport mkdirp from 'mkdirp';\nimport multer from 'multer';\nimport serve from 'koa-static';\nimport mount from 'koa-mount';\nimport { STORAGE_TYPE_LOCAL } from '../constants';\nimport { getFilename } from '../utils';\n\nexport function getDocumentRoot(storage): string {\n const { documentRoot = 'uploads' } = storage.options || {};\n // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹\n return path.resolve(path.isAbsolute(documentRoot)\n ? documentRoot\n : path.join(process.cwd(), documentRoot), storage.path);\n}\n\n// TODO(optimize): 初始化的时机不应该放在中间件里\nexport function middleware(app) {\n if (process.env.NOCOBASE_ENV === 'production') {\n return;\n }\n\n const storages = new Map<string, any>();\n const StorageModel = app.db.getModel('storages');\n\n return app.use(async function (ctx, next) {\n const items = await StorageModel.findAll({\n where: {\n type: STORAGE_TYPE_LOCAL,\n }\n });\n\n const primaryKey = StorageModel.primaryKeyAttribute;\n\n for (const storage of items) {\n\n // TODO:未解决 storage 更新问题\n if (storages.has(storage[primaryKey])) {\n continue;\n }\n\n const baseUrl = storage.get('baseUrl');\n\n let url;\n try {\n url = new URL(baseUrl);\n } catch (e) {\n url = {\n protocol: 'http:',\n hostname: 'localhost',\n port: process.env.API_PORT,\n pathname: baseUrl\n };\n }\n\n // 以下情况才认为当前进程所应该提供静态服务\n // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)\n // TODO(bug): https、端口 80 默认值和其他本地 ip/hostname 的情况未考虑\n // TODO 实际应该用 NOCOBASE_ENV 来判断,或者抛给 env 处理\n if (process.env.LOCAL_STORAGE_USE_STATIC_SERVER) {\n const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;\n app.use(mount(basePath, serve(getDocumentRoot(storage))));\n }\n storages.set(storage.primaryKey, storage);\n }\n await next();\n });\n}\n\nexport default (storage) => multer.diskStorage({\n destination: function (req, file, cb) {\n const destPath = getDocumentRoot(storage);\n mkdirp(destPath).then(() => {\n cb(null, destPath);\n }).catch(cb);\n },\n filename: getFilename\n});\n"]}
@@ -88,6 +88,10 @@ function getDocumentRoot(storage) {
88
88
  exports.getDocumentRoot = getDocumentRoot;
89
89
 
90
90
  function middleware(app) {
91
+ if (process.env.NOCOBASE_ENV === 'production') {
92
+ return;
93
+ }
94
+
91
95
  const storages = new Map();
92
96
  const StorageModel = app.db.getModel('storages');
93
97
  return app.use(function (ctx, next) {
@@ -126,7 +130,7 @@ function middleware(app) {
126
130
 
127
131
  if (process.env.LOCAL_STORAGE_USE_STATIC_SERVER) {
128
132
  const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;
129
- app.use(koa_mount_1.default(basePath, koa_static_1.default(getDocumentRoot(storage))));
133
+ app.use((0, koa_mount_1.default)(basePath, (0, koa_static_1.default)(getDocumentRoot(storage))));
130
134
  }
131
135
 
132
136
  storages.set(storage.primaryKey, storage);
@@ -147,7 +151,7 @@ exports.middleware = middleware;
147
151
  exports.default = storage => multer_1.default.diskStorage({
148
152
  destination: function destination(req, file, cb) {
149
153
  const destPath = getDocumentRoot(storage);
150
- mkdirp_1.default(destPath).then(() => {
154
+ (0, mkdirp_1.default)(destPath).then(() => {
151
155
  cb(null, destPath);
152
156
  }).catch(cb);
153
157
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["storages/local.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,gDAAwB;AACxB,6BAA0B;AAC1B,oDAA4B;AAC5B,oDAA4B;AAC5B,4DAA+B;AAC/B,0DAA8B;AAC9B,4CAAkD;AAClD,oCAAuC;AAEvC,SAAgB,eAAe,CAAC,OAAO;IACrC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IAE3D,OAAO,cAAI,CAAC,OAAO,CAAC,cAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAC/C,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAND,0CAMC;AAGD,SAAgB,UAAU,CAAC,GAAG;IAC5B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAe,CAAC;IACxC,MAAM,YAAY,GAAG,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEjD,OAAO,GAAG,CAAC,GAAG,CAAC,UAAgB,GAAG,EAAE,IAAI;;YACtC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;gBACvC,KAAK,EAAE;oBACL,IAAI,EAAE,8BAAkB;iBACzB;aACF,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,YAAY,CAAC,mBAAmB,CAAC;YAEpD,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;gBAG3B,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE;oBACrC,SAAS;iBACV;gBAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAEvC,IAAI,GAAG,CAAC;gBACR,IAAI;oBACF,GAAG,GAAG,IAAI,SAAG,CAAC,OAAO,CAAC,CAAC;iBACxB;gBAAC,OAAO,CAAC,EAAE;oBACV,GAAG,GAAG;wBACJ,QAAQ,EAAE,OAAO;wBACjB,QAAQ,EAAE,WAAW;wBACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ;wBAC1B,QAAQ,EAAE,OAAO;qBAClB,CAAC;iBACH;gBAMD,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE;oBAC/C,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;oBAClF,GAAG,CAAC,GAAG,CAAC,mBAAK,CAAC,QAAQ,EAAE,oBAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC3D;gBACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;aAC3C;YACD,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;KAAA,CAAC,CAAC;AACL,CAAC;AA9CD,gCA8CC;AAED,kBAAe,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAM,CAAC,WAAW,CAAC;IAC7C,WAAW,EAAE,UAAU,GAAG,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC1C,gBAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACzB,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IACD,QAAQ,EAAE,mBAAW;CACtB,CAAC,CAAC","file":"local.js","sourcesContent":["import path from 'path';\nimport { URL } from 'url';\nimport mkdirp from 'mkdirp';\nimport multer from 'multer';\nimport serve from 'koa-static';\nimport mount from 'koa-mount';\nimport { STORAGE_TYPE_LOCAL } from '../constants';\nimport { getFilename } from '../utils';\n\nexport function getDocumentRoot(storage): string {\n const { documentRoot = 'uploads' } = storage.options || {};\n // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹\n return path.resolve(path.isAbsolute(documentRoot)\n ? documentRoot\n : path.join(process.cwd(), documentRoot), storage.path);\n}\n\n// TODO(optimize): 初始化的时机不应该放在中间件里\nexport function middleware(app) {\n const storages = new Map<string, any>();\n const StorageModel = app.db.getModel('storages');\n\n return app.use(async function (ctx, next) {\n const items = await StorageModel.findAll({\n where: {\n type: STORAGE_TYPE_LOCAL,\n }\n });\n\n const primaryKey = StorageModel.primaryKeyAttribute;\n\n for (const storage of items) {\n\n // TODO:未解决 storage 更新问题\n if (storages.has(storage[primaryKey])) {\n continue;\n }\n\n const baseUrl = storage.get('baseUrl');\n\n let url;\n try {\n url = new URL(baseUrl);\n } catch (e) {\n url = {\n protocol: 'http:',\n hostname: 'localhost',\n port: process.env.API_PORT,\n pathname: baseUrl\n };\n }\n\n // 以下情况才认为当前进程所应该提供静态服务\n // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)\n // TODO(bug): https、端口 80 默认值和其他本地 ip/hostname 的情况未考虑\n // TODO 实际应该用 NOCOBASE_ENV 来判断,或者抛给 env 处理\n if (process.env.LOCAL_STORAGE_USE_STATIC_SERVER) {\n const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;\n app.use(mount(basePath, serve(getDocumentRoot(storage))));\n }\n storages.set(storage.primaryKey, storage);\n }\n await next();\n });\n}\n\nexport default (storage) => multer.diskStorage({\n destination: function (req, file, cb) {\n const destPath = getDocumentRoot(storage);\n mkdirp(destPath).then(() => {\n cb(null, destPath);\n }).catch(cb);\n },\n filename: getFilename\n});\n"]}
1
+ {"version":3,"sources":["storages/local.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,gDAAwB;AACxB,6BAA0B;AAC1B,oDAA4B;AAC5B,oDAA4B;AAC5B,4DAA+B;AAC/B,0DAA8B;AAC9B,4CAAkD;AAClD,oCAAuC;AAEvC,SAAgB,eAAe,CAAC,OAAO;IACrC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IAE3D,OAAO,cAAI,CAAC,OAAO,CAAC,cAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAC/C,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAND,0CAMC;AAGD,SAAgB,UAAU,CAAC,GAAG;IAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,YAAY,EAAE;QAC7C,OAAO;KACR;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAe,CAAC;IACxC,MAAM,YAAY,GAAG,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEjD,OAAO,GAAG,CAAC,GAAG,CAAC,UAAgB,GAAG,EAAE,IAAI;;YACtC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;gBACvC,KAAK,EAAE;oBACL,IAAI,EAAE,8BAAkB;iBACzB;aACF,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,YAAY,CAAC,mBAAmB,CAAC;YAEpD,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;gBAG3B,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE;oBACrC,SAAS;iBACV;gBAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAEvC,IAAI,GAAG,CAAC;gBACR,IAAI;oBACF,GAAG,GAAG,IAAI,SAAG,CAAC,OAAO,CAAC,CAAC;iBACxB;gBAAC,OAAO,CAAC,EAAE;oBACV,GAAG,GAAG;wBACJ,QAAQ,EAAE,OAAO;wBACjB,QAAQ,EAAE,WAAW;wBACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ;wBAC1B,QAAQ,EAAE,OAAO;qBAClB,CAAC;iBACH;gBAMD,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE;oBAC/C,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;oBAClF,GAAG,CAAC,GAAG,CAAC,IAAA,mBAAK,EAAC,QAAQ,EAAE,IAAA,oBAAK,EAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC3D;gBACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;aAC3C;YACD,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;KAAA,CAAC,CAAC;AACL,CAAC;AAlDD,gCAkDC;AAED,kBAAe,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAM,CAAC,WAAW,CAAC;IAC7C,WAAW,EAAE,UAAU,GAAG,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAA,gBAAM,EAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACzB,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IACD,QAAQ,EAAE,mBAAW;CACtB,CAAC,CAAC","file":"local.js","sourcesContent":["import path from 'path';\nimport { URL } from 'url';\nimport mkdirp from 'mkdirp';\nimport multer from 'multer';\nimport serve from 'koa-static';\nimport mount from 'koa-mount';\nimport { STORAGE_TYPE_LOCAL } from '../constants';\nimport { getFilename } from '../utils';\n\nexport function getDocumentRoot(storage): string {\n const { documentRoot = 'uploads' } = storage.options || {};\n // TODO(feature): 后面考虑以字符串模板的方式使用,可注入 req/action 相关变量,以便于区分文件夹\n return path.resolve(path.isAbsolute(documentRoot)\n ? documentRoot\n : path.join(process.cwd(), documentRoot), storage.path);\n}\n\n// TODO(optimize): 初始化的时机不应该放在中间件里\nexport function middleware(app) {\n if (process.env.NOCOBASE_ENV === 'production') {\n return;\n }\n\n const storages = new Map<string, any>();\n const StorageModel = app.db.getModel('storages');\n\n return app.use(async function (ctx, next) {\n const items = await StorageModel.findAll({\n where: {\n type: STORAGE_TYPE_LOCAL,\n }\n });\n\n const primaryKey = StorageModel.primaryKeyAttribute;\n\n for (const storage of items) {\n\n // TODO:未解决 storage 更新问题\n if (storages.has(storage[primaryKey])) {\n continue;\n }\n\n const baseUrl = storage.get('baseUrl');\n\n let url;\n try {\n url = new URL(baseUrl);\n } catch (e) {\n url = {\n protocol: 'http:',\n hostname: 'localhost',\n port: process.env.API_PORT,\n pathname: baseUrl\n };\n }\n\n // 以下情况才认为当前进程所应该提供静态服务\n // 否则都忽略,交给其他 server 来提供(如 nginx/cdn 等)\n // TODO(bug): https、端口 80 默认值和其他本地 ip/hostname 的情况未考虑\n // TODO 实际应该用 NOCOBASE_ENV 来判断,或者抛给 env 处理\n if (process.env.LOCAL_STORAGE_USE_STATIC_SERVER) {\n const basePath = url.pathname.startsWith('/') ? url.pathname : `/${url.pathname}`;\n app.use(mount(basePath, serve(getDocumentRoot(storage))));\n }\n storages.set(storage.primaryKey, storage);\n }\n await next();\n });\n}\n\nexport default (storage) => multer.diskStorage({\n destination: function (req, file, cb) {\n const destPath = getDocumentRoot(storage);\n mkdirp(destPath).then(() => {\n cb(null, destPath);\n }).catch(cb);\n },\n filename: getFilename\n});\n"]}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@nocobase/plugin-file-manager",
3
- "version": "0.5.0-alpha.30",
3
+ "version": "0.5.0-alpha.34",
4
4
  "main": "lib/index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
7
7
  "@koa/multer": "^3.0.0",
8
- "@nocobase/server": "^0.5.0-alpha.30",
8
+ "@nocobase/server": "^0.5.0-alpha.34",
9
9
  "ali-oss": "^6.12.0",
10
10
  "koa-mount": "^4.0.0",
11
11
  "koa-static": "^5.0.0",
@@ -13,8 +13,8 @@
13
13
  "multer": "^1.4.2"
14
14
  },
15
15
  "devDependencies": {
16
- "@nocobase/test": "^0.5.0-alpha.30",
16
+ "@nocobase/test": "^0.5.0-alpha.34",
17
17
  "@types/multer": "^1.4.5"
18
18
  },
19
- "gitHead": "829f969668edbf1ad6f325bf194ebfb6c6ed0fc6"
19
+ "gitHead": "11cded6153bab633fb0b7415c33b4c3c369c2427"
20
20
  }