@nocobase/resourcer 0.5.0-alpha.34 → 0.5.0-alpha.35

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/action.d.ts CHANGED
@@ -47,9 +47,9 @@ export interface ActionParams {
47
47
  perPage?: number;
48
48
  values?: any;
49
49
  resourceName?: string;
50
- resourceKey?: string;
50
+ resourceIndex?: string;
51
51
  associatedName?: string;
52
- associatedKey?: string;
52
+ associatedIndex?: string;
53
53
  associated?: any;
54
54
  actionName?: string;
55
55
  [key: string]: any;
@@ -1 +1 @@
1
- {"version":3,"sources":["action.ts"],"names":[],"mappings":"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","file":"action.d.ts","sourcesContent":["import _ from 'lodash';\nimport compose from 'koa-compose';\nimport Resource from './resource';\nimport { requireModule } from './utils';\nimport { HandlerType } from './resourcer';\nimport Middleware, { MiddlewareType } from './middleware';\nimport { ActionParameterTypes, ActionParameter, UnknownParameter, PageParameter } from './parameter';\n\nexport type ActionType = string | HandlerType | ActionOptions;\n\nexport type DefaultActionType = 'list' | 'create' | 'get' | 'update' | 'destroy' | 'set' | 'add' | 'remove';\n\nexport type ActionName = DefaultActionType | Omit<String, DefaultActionType>;\n\nexport interface ActionContext {\n action?: Action;\n [key: string]: any;\n}\n\nexport type FieldsOptions = string[] | {\n only?: string[];\n appends?: string[];\n} | {\n except?: string[];\n appends?: string[];\n};\n\nexport type FieldsOptionsFn = (ctx: ActionContext) => FieldsOptions | Promise<FieldsOptions>;\n\n/**\n * 过滤参数\n * \n * TODO:细节待定\n */\nexport interface FilterOptions {\n [key: string]: any;\n}\n\nexport type FilterOptionsFn = (ctx: ActionContext) => FilterOptions | Promise<FieldsOptions>;\n\nexport type ParamsCallback = (ctx: ActionContext) => ActionParams | Promise<ActionParams>;\n\nexport interface ActionOptions {\n /**\n * 默认数据\n */\n values?: any;\n /**\n * 字段\n * \n * 示例一:\n * ['col1', 'col2', 'relation.col1'];\n * \n * 示例二:\n * {\n * only: ['col1'],\n * }\n * \n * 示例三:\n * {\n * except: ['col1'],\n * }\n */\n fields?: FieldsOptions;\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n */\n sort?: string | string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 最大每页显示数量\n */\n maxPerPage?: number;\n /**\n * 中间件\n */\n middleware?: MiddlewareType;\n /**\n * 中间件\n * \n * 与 middleware 用法相同\n */\n middlewares?: MiddlewareType;\n /**\n * 当前 Action 待执行的方法\n * \n * 支持 Function 和 require 调用\n */\n handler?: HandlerType;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\n/**\n * action params 与 action options 略有不同\n * - options 的参数更灵活,主要用于开发配置\n * - params 是开发配置参数 + 客户端参数的结合体\n */\nexport interface ActionParams {\n /**\n * 输出哪些字段\n * \n * 与 ActionOptions 的不同,这里的 fields 是 object,提供 only,except,appends 三种情况\n */\n fields?: {\n only?: string[];\n except?: string[];\n appends?: string[];\n };\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n * \n * 与 ActionOptions 的不同,这里的 sort 只有一种 array 类型\n */\n sort?: string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 数据,默认为 options.defaultValues + request.body\n */\n values?: any;\n /**\n * 当前资源的主体,对应的表名或 Model 名称\n */\n resourceName?: string;\n /**\n * 资源标识符\n */\n resourceKey?: string;\n /**\n * 资源的从属关系\n */\n associatedName?: string;\n /**\n * 从属关系的标识符\n */\n associatedKey?: string;\n /**\n * 从属关系的当前实例\n */\n associated?: any;\n /**\n * 资源提供哪些行为或方法\n */\n actionName?: string;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\nexport class Action {\n\n protected handler: any;\n\n protected resource: Resource;\n\n protected name: ActionName;\n\n protected options: ActionOptions;\n\n protected parameters: Map<string, ActionParameter | UnknownParameter> = new Map();\n\n protected context: ActionContext = {};\n\n public readonly middlewares: Array<Middleware> = [];\n\n constructor(options: ActionOptions) {\n options = requireModule(options);\n if (typeof options === 'function') {\n options = { handler: options };\n }\n const {\n middleware,\n middlewares = [],\n handler,\n ...params\n } = options;\n this.middlewares = Middleware.toInstanceArray(middleware || middlewares);\n this.handler = handler;\n this.options = options;\n this.mergeParams(params, {});\n }\n\n get params(): ActionParams {\n const result = this.parameters.get('_').get();\n for (const paramType of this.parameters.values()) {\n Object.assign(result, paramType.get());\n }\n return result;\n }\n\n clone() {\n const options = _.cloneDeep(this.options);\n delete options.middleware;\n delete options.middlewares;\n const action = new Action(options);\n action.setName(this.name);\n action.setResource(this.resource);\n action.middlewares.push(...this.middlewares);\n return action;\n }\n\n setContext(context: any) {\n this.context = context;\n }\n\n async mergeParams(params, strategies = {}) {\n const typeKeys = new Set<string>();\n Object.keys(params).forEach(key => {\n for (const typeKey of ActionParameterTypes.getAllKeys()) {\n if (typeof params[key] !== 'undefined' && key in ActionParameterTypes.get(typeKey).picking) {\n typeKeys.add(typeKey);\n }\n }\n });\n let type;\n for (const key of typeKeys) {\n const strategy = strategies[key];\n type = this.parameters.get(key);\n if (!type) {\n const Type = ActionParameterTypes.get(key);\n if (!Type) {\n throw new Error(`parameter type ${key} is unregistered`);\n }\n // @ts-ignore\n type = new Type(params);\n this.parameters.set(key, type);\n }\n type.merge(params, strategy);\n }\n type = this.parameters.get('_');\n if (!type) {\n type = new UnknownParameter(params);\n this.parameters.set('_', type);\n }\n type.merge(params, strategies['_']);\n }\n\n setResource(resource: Resource) {\n this.resource = resource;\n return this;\n }\n\n getResource() {\n return this.resource;\n }\n\n getOptions(): ActionOptions {\n return this.options;\n }\n\n setName(name: ActionName) {\n this.name = name;\n return this;\n }\n\n getName() {\n return this.name;\n }\n\n getMiddlewareHandlers() {\n return this.middlewares\n .filter(middleware => middleware.canAccess(this.name))\n .map(middleware => middleware.getHandler());\n }\n\n getHandler() {\n const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name));\n if (typeof handler !== 'function') {\n throw new Error('Handler must be a function!');\n }\n return handler;\n }\n\n getHandlers() {\n return [...this.resource.resourcer.getMiddlewares(), ...this.getMiddlewareHandlers(), this.getHandler()].filter(Boolean);\n }\n\n async execute(context: any, next?: any) {\n return await compose(this.getHandlers())(context, next);\n }\n\n static toInstanceMap(actions: object, resource?: Resource) {\n return new Map(Object.entries(actions).map(([key, options]) => {\n let action: Action;\n if (options instanceof Action) {\n action = options;\n } else {\n action = new Action(options);\n }\n action.setName(key);\n action.setResource(resource);\n resource && action.middlewares.unshift(...resource.middlewares);\n return [key, action];\n }));\n }\n}\n\nexport default Action;\n"]}
1
+ {"version":3,"sources":["action.ts"],"names":[],"mappings":"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","file":"action.d.ts","sourcesContent":["import _ from 'lodash';\nimport compose from 'koa-compose';\nimport Resource from './resource';\nimport { requireModule } from './utils';\nimport { HandlerType } from './resourcer';\nimport Middleware, { MiddlewareType } from './middleware';\nimport { ActionParameterTypes, ActionParameter, UnknownParameter, PageParameter } from './parameter';\n\nexport type ActionType = string | HandlerType | ActionOptions;\n\nexport type DefaultActionType = 'list' | 'create' | 'get' | 'update' | 'destroy' | 'set' | 'add' | 'remove';\n\nexport type ActionName = DefaultActionType | Omit<String, DefaultActionType>;\n\nexport interface ActionContext {\n action?: Action;\n [key: string]: any;\n}\n\nexport type FieldsOptions = string[] | {\n only?: string[];\n appends?: string[];\n} | {\n except?: string[];\n appends?: string[];\n};\n\nexport type FieldsOptionsFn = (ctx: ActionContext) => FieldsOptions | Promise<FieldsOptions>;\n\n/**\n * 过滤参数\n * \n * TODO:细节待定\n */\nexport interface FilterOptions {\n [key: string]: any;\n}\n\nexport type FilterOptionsFn = (ctx: ActionContext) => FilterOptions | Promise<FieldsOptions>;\n\nexport type ParamsCallback = (ctx: ActionContext) => ActionParams | Promise<ActionParams>;\n\nexport interface ActionOptions {\n /**\n * 默认数据\n */\n values?: any;\n /**\n * 字段\n * \n * 示例一:\n * ['col1', 'col2', 'relation.col1'];\n * \n * 示例二:\n * {\n * only: ['col1'],\n * }\n * \n * 示例三:\n * {\n * except: ['col1'],\n * }\n */\n fields?: FieldsOptions;\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n */\n sort?: string | string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 最大每页显示数量\n */\n maxPerPage?: number;\n /**\n * 中间件\n */\n middleware?: MiddlewareType;\n /**\n * 中间件\n * \n * 与 middleware 用法相同\n */\n middlewares?: MiddlewareType;\n /**\n * 当前 Action 待执行的方法\n * \n * 支持 Function 和 require 调用\n */\n handler?: HandlerType;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\n/**\n * action params 与 action options 略有不同\n * - options 的参数更灵活,主要用于开发配置\n * - params 是开发配置参数 + 客户端参数的结合体\n */\nexport interface ActionParams {\n /**\n * 输出哪些字段\n * \n * 与 ActionOptions 的不同,这里的 fields 是 object,提供 only,except,appends 三种情况\n */\n fields?: {\n only?: string[];\n except?: string[];\n appends?: string[];\n };\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n * \n * 与 ActionOptions 的不同,这里的 sort 只有一种 array 类型\n */\n sort?: string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 数据,默认为 options.defaultValues + request.body\n */\n values?: any;\n /**\n * 当前资源的主体,对应的表名或 Model 名称\n */\n resourceName?: string;\n /**\n * 资源标识符\n */\n resourceIndex?: string;\n /**\n * 资源的从属关系\n */\n associatedName?: string;\n /**\n * 从属关系的标识符\n */\n associatedIndex?: string;\n /**\n * 从属关系的当前实例\n */\n associated?: any;\n /**\n * 资源提供哪些行为或方法\n */\n actionName?: string;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\nexport class Action {\n\n protected handler: any;\n\n protected resource: Resource;\n\n protected name: ActionName;\n\n protected options: ActionOptions;\n\n protected parameters: Map<string, ActionParameter | UnknownParameter> = new Map();\n\n protected context: ActionContext = {};\n\n public readonly middlewares: Array<Middleware> = [];\n\n constructor(options: ActionOptions) {\n options = requireModule(options);\n if (typeof options === 'function') {\n options = { handler: options };\n }\n const {\n middleware,\n middlewares = [],\n handler,\n ...params\n } = options;\n this.middlewares = Middleware.toInstanceArray(middleware || middlewares);\n this.handler = handler;\n this.options = options;\n this.mergeParams(params, {});\n }\n\n get params(): ActionParams {\n const result = this.parameters.get('_').get();\n for (const paramType of this.parameters.values()) {\n Object.assign(result, paramType.get());\n }\n return result;\n }\n\n clone() {\n const options = _.cloneDeep(this.options);\n delete options.middleware;\n delete options.middlewares;\n const action = new Action(options);\n action.setName(this.name);\n action.setResource(this.resource);\n action.middlewares.push(...this.middlewares);\n return action;\n }\n\n setContext(context: any) {\n this.context = context;\n }\n\n async mergeParams(params, strategies = {}) {\n const typeKeys = new Set<string>();\n Object.keys(params).forEach(key => {\n for (const typeKey of ActionParameterTypes.getAllKeys()) {\n if (typeof params[key] !== 'undefined' && key in ActionParameterTypes.get(typeKey).picking) {\n typeKeys.add(typeKey);\n }\n }\n });\n let type;\n for (const key of typeKeys) {\n const strategy = strategies[key];\n type = this.parameters.get(key);\n if (!type) {\n const Type = ActionParameterTypes.get(key);\n if (!Type) {\n throw new Error(`parameter type ${key} is unregistered`);\n }\n // @ts-ignore\n type = new Type(params);\n this.parameters.set(key, type);\n }\n type.merge(params, strategy);\n }\n type = this.parameters.get('_');\n if (!type) {\n type = new UnknownParameter(params);\n this.parameters.set('_', type);\n }\n type.merge(params, strategies['_']);\n }\n\n setResource(resource: Resource) {\n this.resource = resource;\n return this;\n }\n\n getResource() {\n return this.resource;\n }\n\n getOptions(): ActionOptions {\n return this.options;\n }\n\n setName(name: ActionName) {\n this.name = name;\n return this;\n }\n\n getName() {\n return this.name;\n }\n\n getMiddlewareHandlers() {\n return this.middlewares\n .filter(middleware => middleware.canAccess(this.name))\n .map(middleware => middleware.getHandler());\n }\n\n getHandler() {\n const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name));\n if (typeof handler !== 'function') {\n throw new Error('Handler must be a function!');\n }\n return handler;\n }\n\n getHandlers() {\n return [...this.resource.resourcer.getMiddlewares(), ...this.getMiddlewareHandlers(), this.getHandler()].filter(Boolean);\n }\n\n async execute(context: any, next?: any) {\n return await compose(this.getHandlers())(context, next);\n }\n\n static toInstanceMap(actions: object, resource?: Resource) {\n return new Map(Object.entries(actions).map(([key, options]) => {\n let action: Action;\n if (options instanceof Action) {\n action = options;\n } else {\n action = new Action(options);\n }\n action.setName(key);\n action.setResource(resource);\n resource && action.middlewares.unshift(...resource.middlewares);\n return [key, action];\n }));\n }\n}\n\nexport default Action;\n"]}
package/lib/action.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["action.ts"],"names":[],"mappings":"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","file":"action.js","sourcesContent":["import _ from 'lodash';\nimport compose from 'koa-compose';\nimport Resource from './resource';\nimport { requireModule } from './utils';\nimport { HandlerType } from './resourcer';\nimport Middleware, { MiddlewareType } from './middleware';\nimport { ActionParameterTypes, ActionParameter, UnknownParameter, PageParameter } from './parameter';\n\nexport type ActionType = string | HandlerType | ActionOptions;\n\nexport type DefaultActionType = 'list' | 'create' | 'get' | 'update' | 'destroy' | 'set' | 'add' | 'remove';\n\nexport type ActionName = DefaultActionType | Omit<String, DefaultActionType>;\n\nexport interface ActionContext {\n action?: Action;\n [key: string]: any;\n}\n\nexport type FieldsOptions = string[] | {\n only?: string[];\n appends?: string[];\n} | {\n except?: string[];\n appends?: string[];\n};\n\nexport type FieldsOptionsFn = (ctx: ActionContext) => FieldsOptions | Promise<FieldsOptions>;\n\n/**\n * 过滤参数\n * \n * TODO:细节待定\n */\nexport interface FilterOptions {\n [key: string]: any;\n}\n\nexport type FilterOptionsFn = (ctx: ActionContext) => FilterOptions | Promise<FieldsOptions>;\n\nexport type ParamsCallback = (ctx: ActionContext) => ActionParams | Promise<ActionParams>;\n\nexport interface ActionOptions {\n /**\n * 默认数据\n */\n values?: any;\n /**\n * 字段\n * \n * 示例一:\n * ['col1', 'col2', 'relation.col1'];\n * \n * 示例二:\n * {\n * only: ['col1'],\n * }\n * \n * 示例三:\n * {\n * except: ['col1'],\n * }\n */\n fields?: FieldsOptions;\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n */\n sort?: string | string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 最大每页显示数量\n */\n maxPerPage?: number;\n /**\n * 中间件\n */\n middleware?: MiddlewareType;\n /**\n * 中间件\n * \n * 与 middleware 用法相同\n */\n middlewares?: MiddlewareType;\n /**\n * 当前 Action 待执行的方法\n * \n * 支持 Function 和 require 调用\n */\n handler?: HandlerType;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\n/**\n * action params 与 action options 略有不同\n * - options 的参数更灵活,主要用于开发配置\n * - params 是开发配置参数 + 客户端参数的结合体\n */\nexport interface ActionParams {\n /**\n * 输出哪些字段\n * \n * 与 ActionOptions 的不同,这里的 fields 是 object,提供 only,except,appends 三种情况\n */\n fields?: {\n only?: string[];\n except?: string[];\n appends?: string[];\n };\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n * \n * 与 ActionOptions 的不同,这里的 sort 只有一种 array 类型\n */\n sort?: string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 数据,默认为 options.defaultValues + request.body\n */\n values?: any;\n /**\n * 当前资源的主体,对应的表名或 Model 名称\n */\n resourceName?: string;\n /**\n * 资源标识符\n */\n resourceKey?: string;\n /**\n * 资源的从属关系\n */\n associatedName?: string;\n /**\n * 从属关系的标识符\n */\n associatedKey?: string;\n /**\n * 从属关系的当前实例\n */\n associated?: any;\n /**\n * 资源提供哪些行为或方法\n */\n actionName?: string;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\nexport class Action {\n\n protected handler: any;\n\n protected resource: Resource;\n\n protected name: ActionName;\n\n protected options: ActionOptions;\n\n protected parameters: Map<string, ActionParameter | UnknownParameter> = new Map();\n\n protected context: ActionContext = {};\n\n public readonly middlewares: Array<Middleware> = [];\n\n constructor(options: ActionOptions) {\n options = requireModule(options);\n if (typeof options === 'function') {\n options = { handler: options };\n }\n const {\n middleware,\n middlewares = [],\n handler,\n ...params\n } = options;\n this.middlewares = Middleware.toInstanceArray(middleware || middlewares);\n this.handler = handler;\n this.options = options;\n this.mergeParams(params, {});\n }\n\n get params(): ActionParams {\n const result = this.parameters.get('_').get();\n for (const paramType of this.parameters.values()) {\n Object.assign(result, paramType.get());\n }\n return result;\n }\n\n clone() {\n const options = _.cloneDeep(this.options);\n delete options.middleware;\n delete options.middlewares;\n const action = new Action(options);\n action.setName(this.name);\n action.setResource(this.resource);\n action.middlewares.push(...this.middlewares);\n return action;\n }\n\n setContext(context: any) {\n this.context = context;\n }\n\n async mergeParams(params, strategies = {}) {\n const typeKeys = new Set<string>();\n Object.keys(params).forEach(key => {\n for (const typeKey of ActionParameterTypes.getAllKeys()) {\n if (typeof params[key] !== 'undefined' && key in ActionParameterTypes.get(typeKey).picking) {\n typeKeys.add(typeKey);\n }\n }\n });\n let type;\n for (const key of typeKeys) {\n const strategy = strategies[key];\n type = this.parameters.get(key);\n if (!type) {\n const Type = ActionParameterTypes.get(key);\n if (!Type) {\n throw new Error(`parameter type ${key} is unregistered`);\n }\n // @ts-ignore\n type = new Type(params);\n this.parameters.set(key, type);\n }\n type.merge(params, strategy);\n }\n type = this.parameters.get('_');\n if (!type) {\n type = new UnknownParameter(params);\n this.parameters.set('_', type);\n }\n type.merge(params, strategies['_']);\n }\n\n setResource(resource: Resource) {\n this.resource = resource;\n return this;\n }\n\n getResource() {\n return this.resource;\n }\n\n getOptions(): ActionOptions {\n return this.options;\n }\n\n setName(name: ActionName) {\n this.name = name;\n return this;\n }\n\n getName() {\n return this.name;\n }\n\n getMiddlewareHandlers() {\n return this.middlewares\n .filter(middleware => middleware.canAccess(this.name))\n .map(middleware => middleware.getHandler());\n }\n\n getHandler() {\n const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name));\n if (typeof handler !== 'function') {\n throw new Error('Handler must be a function!');\n }\n return handler;\n }\n\n getHandlers() {\n return [...this.resource.resourcer.getMiddlewares(), ...this.getMiddlewareHandlers(), this.getHandler()].filter(Boolean);\n }\n\n async execute(context: any, next?: any) {\n return await compose(this.getHandlers())(context, next);\n }\n\n static toInstanceMap(actions: object, resource?: Resource) {\n return new Map(Object.entries(actions).map(([key, options]) => {\n let action: Action;\n if (options instanceof Action) {\n action = options;\n } else {\n action = new Action(options);\n }\n action.setName(key);\n action.setResource(resource);\n resource && action.middlewares.unshift(...resource.middlewares);\n return [key, action];\n }));\n }\n}\n\nexport default Action;\n"]}
1
+ {"version":3,"sources":["action.ts"],"names":[],"mappings":"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","file":"action.js","sourcesContent":["import _ from 'lodash';\nimport compose from 'koa-compose';\nimport Resource from './resource';\nimport { requireModule } from './utils';\nimport { HandlerType } from './resourcer';\nimport Middleware, { MiddlewareType } from './middleware';\nimport { ActionParameterTypes, ActionParameter, UnknownParameter, PageParameter } from './parameter';\n\nexport type ActionType = string | HandlerType | ActionOptions;\n\nexport type DefaultActionType = 'list' | 'create' | 'get' | 'update' | 'destroy' | 'set' | 'add' | 'remove';\n\nexport type ActionName = DefaultActionType | Omit<String, DefaultActionType>;\n\nexport interface ActionContext {\n action?: Action;\n [key: string]: any;\n}\n\nexport type FieldsOptions = string[] | {\n only?: string[];\n appends?: string[];\n} | {\n except?: string[];\n appends?: string[];\n};\n\nexport type FieldsOptionsFn = (ctx: ActionContext) => FieldsOptions | Promise<FieldsOptions>;\n\n/**\n * 过滤参数\n * \n * TODO:细节待定\n */\nexport interface FilterOptions {\n [key: string]: any;\n}\n\nexport type FilterOptionsFn = (ctx: ActionContext) => FilterOptions | Promise<FieldsOptions>;\n\nexport type ParamsCallback = (ctx: ActionContext) => ActionParams | Promise<ActionParams>;\n\nexport interface ActionOptions {\n /**\n * 默认数据\n */\n values?: any;\n /**\n * 字段\n * \n * 示例一:\n * ['col1', 'col2', 'relation.col1'];\n * \n * 示例二:\n * {\n * only: ['col1'],\n * }\n * \n * 示例三:\n * {\n * except: ['col1'],\n * }\n */\n fields?: FieldsOptions;\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n */\n sort?: string | string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 最大每页显示数量\n */\n maxPerPage?: number;\n /**\n * 中间件\n */\n middleware?: MiddlewareType;\n /**\n * 中间件\n * \n * 与 middleware 用法相同\n */\n middlewares?: MiddlewareType;\n /**\n * 当前 Action 待执行的方法\n * \n * 支持 Function 和 require 调用\n */\n handler?: HandlerType;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\n/**\n * action params 与 action options 略有不同\n * - options 的参数更灵活,主要用于开发配置\n * - params 是开发配置参数 + 客户端参数的结合体\n */\nexport interface ActionParams {\n /**\n * 输出哪些字段\n * \n * 与 ActionOptions 的不同,这里的 fields 是 object,提供 only,except,appends 三种情况\n */\n fields?: {\n only?: string[];\n except?: string[];\n appends?: string[];\n };\n /**\n * 过滤\n */\n filter?: FilterOptions;\n /**\n * 排序\n * \n * 与 ActionOptions 的不同,这里的 sort 只有一种 array 类型\n */\n sort?: string[];\n /**\n * 当前页码\n */\n page?: number;\n /**\n * 每页显示数量\n */\n perPage?: number;\n /**\n * 数据,默认为 options.defaultValues + request.body\n */\n values?: any;\n /**\n * 当前资源的主体,对应的表名或 Model 名称\n */\n resourceName?: string;\n /**\n * 资源标识符\n */\n resourceIndex?: string;\n /**\n * 资源的从属关系\n */\n associatedName?: string;\n /**\n * 从属关系的标识符\n */\n associatedIndex?: string;\n /**\n * 从属关系的当前实例\n */\n associated?: any;\n /**\n * 资源提供哪些行为或方法\n */\n actionName?: string;\n /**\n * 其他扩展配置\n */\n [key: string]: any;\n}\n\nexport class Action {\n\n protected handler: any;\n\n protected resource: Resource;\n\n protected name: ActionName;\n\n protected options: ActionOptions;\n\n protected parameters: Map<string, ActionParameter | UnknownParameter> = new Map();\n\n protected context: ActionContext = {};\n\n public readonly middlewares: Array<Middleware> = [];\n\n constructor(options: ActionOptions) {\n options = requireModule(options);\n if (typeof options === 'function') {\n options = { handler: options };\n }\n const {\n middleware,\n middlewares = [],\n handler,\n ...params\n } = options;\n this.middlewares = Middleware.toInstanceArray(middleware || middlewares);\n this.handler = handler;\n this.options = options;\n this.mergeParams(params, {});\n }\n\n get params(): ActionParams {\n const result = this.parameters.get('_').get();\n for (const paramType of this.parameters.values()) {\n Object.assign(result, paramType.get());\n }\n return result;\n }\n\n clone() {\n const options = _.cloneDeep(this.options);\n delete options.middleware;\n delete options.middlewares;\n const action = new Action(options);\n action.setName(this.name);\n action.setResource(this.resource);\n action.middlewares.push(...this.middlewares);\n return action;\n }\n\n setContext(context: any) {\n this.context = context;\n }\n\n async mergeParams(params, strategies = {}) {\n const typeKeys = new Set<string>();\n Object.keys(params).forEach(key => {\n for (const typeKey of ActionParameterTypes.getAllKeys()) {\n if (typeof params[key] !== 'undefined' && key in ActionParameterTypes.get(typeKey).picking) {\n typeKeys.add(typeKey);\n }\n }\n });\n let type;\n for (const key of typeKeys) {\n const strategy = strategies[key];\n type = this.parameters.get(key);\n if (!type) {\n const Type = ActionParameterTypes.get(key);\n if (!Type) {\n throw new Error(`parameter type ${key} is unregistered`);\n }\n // @ts-ignore\n type = new Type(params);\n this.parameters.set(key, type);\n }\n type.merge(params, strategy);\n }\n type = this.parameters.get('_');\n if (!type) {\n type = new UnknownParameter(params);\n this.parameters.set('_', type);\n }\n type.merge(params, strategies['_']);\n }\n\n setResource(resource: Resource) {\n this.resource = resource;\n return this;\n }\n\n getResource() {\n return this.resource;\n }\n\n getOptions(): ActionOptions {\n return this.options;\n }\n\n setName(name: ActionName) {\n this.name = name;\n return this;\n }\n\n getName() {\n return this.name;\n }\n\n getMiddlewareHandlers() {\n return this.middlewares\n .filter(middleware => middleware.canAccess(this.name))\n .map(middleware => middleware.getHandler());\n }\n\n getHandler() {\n const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name));\n if (typeof handler !== 'function') {\n throw new Error('Handler must be a function!');\n }\n return handler;\n }\n\n getHandlers() {\n return [...this.resource.resourcer.getMiddlewares(), ...this.getMiddlewareHandlers(), this.getHandler()].filter(Boolean);\n }\n\n async execute(context: any, next?: any) {\n return await compose(this.getHandlers())(context, next);\n }\n\n static toInstanceMap(actions: object, resource?: Resource) {\n return new Map(Object.entries(actions).map(([key, options]) => {\n let action: Action;\n if (options instanceof Action) {\n action = options;\n } else {\n action = new Action(options);\n }\n action.setName(key);\n action.setResource(resource);\n resource && action.middlewares.unshift(...resource.middlewares);\n return [key, action];\n }));\n }\n}\n\nexport default Action;\n"]}
package/lib/utils.d.ts CHANGED
@@ -19,9 +19,9 @@ export interface ParseOptions {
19
19
  export interface ParsedParams {
20
20
  actionName?: string;
21
21
  resourceName?: string;
22
- resourceKey?: string;
22
+ resourceIndex?: string;
23
23
  associatedName?: string;
24
- associatedKey?: string;
24
+ associatedIndex?: string;
25
25
  }
26
26
  export declare function getNameByParams(params: ParsedParams): string;
27
27
  export declare function parseRequest(request: ParseRequest, options?: ParseOptions): ParsedParams | false;
@@ -1 +1 @@
1
- {"version":3,"sources":["utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CAMxB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAG5D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,YAAiB,GAAG,YAAY,GAAG,KAAK,CA4IpG;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,OAQxC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAc7C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,OAmCtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAuCrD","file":"utils.d.ts","sourcesContent":["import _ from 'lodash';\nimport { pathToRegexp } from 'path-to-regexp';\nimport qs from 'qs';\nimport { ResourceType } from './resource';\n\nexport interface ParseRequest {\n path: string;\n method: string;\n // 资源类型\n type?: ResourceType;\n}\n\nexport interface ParseOptions {\n prefix?: string;\n accessors?: {\n list?: string;\n create?: string;\n get?: string;\n update?: string;\n delete?: string;\n set?: string;\n add?: string;\n };\n}\n\nexport interface ParsedParams {\n actionName?: string;\n resourceName?: string;\n resourceKey?: string;\n associatedName?: string;\n associatedKey?: string;\n // table: string;\n // tableKey?: string | number;\n // relatedTable?: string;\n // relatedKey?: string | number;\n // action?: ActionName,\n}\n\nexport function getNameByParams(params: ParsedParams): string {\n const { resourceName, associatedName } = params;\n return associatedName ? `${associatedName}.${resourceName}` : resourceName;\n}\n\nexport function parseRequest(request: ParseRequest, options: ParseOptions = {}): ParsedParams | false {\n\n const accessors = {\n // 常规 actions\n list: 'list',\n create: 'create',\n get: 'get',\n update: 'update',\n delete: 'destroy',\n // associate 操作\n add: 'add',\n set: 'set',\n remove: 'remove',\n ...(options.accessors || {}),\n };\n const keys = [];\n const regexp = pathToRegexp('/resourcer/{:associatedName.}?:resourceName{\\\\::actionName}', keys);\n const matches = regexp.exec(request.path);\n if (matches) {\n const params = {};\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n return params;\n }\n const defaults = {\n single: {\n '/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete\n },\n '/:resourceName/:resourceKey': {\n get: accessors.get,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasOne: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.get,\n post: accessors.update,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasMany: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n belongsTo: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.get,\n delete: accessors.remove,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n post: accessors.set,\n },\n },\n belongsToMany: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.list,\n post: accessors.set,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n get: accessors.get,\n post: accessors.add,\n put: accessors.update, // Many to Many 的 update 是针对 through\n patch: accessors.update, // Many to Many 的 update 是针对 through\n delete: accessors.remove,\n },\n },\n };\n\n const params: ParsedParams = {};\n\n let prefix = (options.prefix || '').trim();\n\n if (prefix && !prefix.startsWith('/')) {\n prefix = `/${prefix}`;\n }\n\n const { type = 'single' } = request;\n\n for (const path in defaults[type]) {\n const keys = [];\n const regexp = pathToRegexp(`${prefix}${path}`, keys, {});\n const matches = regexp.exec(request.path);\n if (!matches) {\n continue;\n }\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n params.actionName = _.get(defaults, [type, path, request.method.toLowerCase()]);\n }\n\n if (Object.keys(params).length === 0) {\n return false;\n }\n\n if (params.resourceName) {\n const [resourceName, actionName] = params.resourceName.split(':');\n if (actionName) {\n params.resourceName = resourceName;\n params.actionName = actionName;\n }\n }\n\n return params;\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function parseQuery(input: string): any {\n // 自带 query 处理的不太给力,需要用 qs 转一下\n const query = qs.parse(input, {\n // 原始 query string 中如果一个键连等号“=”都没有可以被认为是 null 类型\n strictNullHandling: true,\n // 逗号分隔转换为数组\n comma: true\n });\n // filter 支持 json string\n if (typeof query.filter === 'string') {\n query.filter = JSON.parse(query.filter);\n }\n\n return query;\n}\n\nexport function parseFields(fields: any) {\n if (!fields) {\n return {}\n }\n if (typeof fields === 'string') {\n fields = fields.split(',').map(field => field.trim());\n }\n if (Array.isArray(fields)) {\n const onlyFields = [];\n const output: any = {};\n fields.forEach(item => {\n if (typeof item === 'string') {\n onlyFields.push(item);\n } else if (typeof item === 'object') {\n if (item.only) {\n onlyFields.push(...item.only.toString().split(','));\n }\n Object.assign(output, parseFields(item));\n }\n });\n if (onlyFields.length) {\n output.only = onlyFields;\n }\n return output;\n }\n if (fields.only && typeof fields.only === 'string') {\n fields.only = fields.only.split(',').map(field => field.trim());\n }\n if (fields.except && typeof fields.except === 'string') {\n fields.except = fields.except.split(',').map(field => field.trim());\n }\n if (fields.appends && typeof fields.appends === 'string') {\n fields.appends = fields.appends.split(',').map(field => field.trim());\n }\n return fields;\n}\n\nexport function mergeFields(defaults: any, inputs: any) {\n let fields: any = {};\n defaults = parseFields(defaults);\n inputs = parseFields(inputs);\n if (inputs.only) {\n // 前端提供 only,后端提供 only\n if (defaults.only) {\n fields.only = defaults.only.filter(field => inputs.only.includes(field))\n }\n // 前端提供 only,后端提供 except,输出 only 排除 except\n else if (defaults.except) {\n fields.only = inputs.only.filter(field => !defaults.except.includes(field))\n }\n // 前端提供 only,后端没有提供 only 或 except\n else {\n fields.only = inputs.only;\n }\n } else if (inputs.except) {\n // 前端提供 except,后端提供 only,只输出 only 里排除 except 的字段\n if (defaults.only) {\n fields.only = defaults.only.filter(field => !inputs.except.includes(field))\n }\n // 前端提供 except,后端提供 except 或不提供,合并 except\n else {\n fields.except = _.uniq([...inputs.except, ...(defaults.except || [])]);\n }\n }\n // 前端没提供 only 或 except\n else {\n fields = defaults;\n }\n // 如果前端提供了 appends\n if (!_.isEmpty(inputs.appends)) {\n fields.appends = _.uniq([...inputs.appends, ...(defaults.appends || [])]);\n }\n if (!fields.appends) {\n fields.appends = [];\n }\n return fields;\n}\n"]}
1
+ {"version":3,"sources":["utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAM1B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAG5D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,YAAiB,GAAG,YAAY,GAAG,KAAK,CA4IpG;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,OAQxC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAc7C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,OAmCtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAuCrD","file":"utils.d.ts","sourcesContent":["import _ from 'lodash';\nimport { pathToRegexp } from 'path-to-regexp';\nimport qs from 'qs';\nimport { ResourceType } from './resource';\n\nexport interface ParseRequest {\n path: string;\n method: string;\n // 资源类型\n type?: ResourceType;\n}\n\nexport interface ParseOptions {\n prefix?: string;\n accessors?: {\n list?: string;\n create?: string;\n get?: string;\n update?: string;\n delete?: string;\n set?: string;\n add?: string;\n };\n}\n\nexport interface ParsedParams {\n actionName?: string;\n resourceName?: string;\n resourceIndex?: string;\n associatedName?: string;\n associatedIndex?: string;\n // table: string;\n // tableKey?: string | number;\n // relatedTable?: string;\n // relatedKey?: string | number;\n // action?: ActionName,\n}\n\nexport function getNameByParams(params: ParsedParams): string {\n const { resourceName, associatedName } = params;\n return associatedName ? `${associatedName}.${resourceName}` : resourceName;\n}\n\nexport function parseRequest(request: ParseRequest, options: ParseOptions = {}): ParsedParams | false {\n\n const accessors = {\n // 常规 actions\n list: 'list',\n create: 'create',\n get: 'get',\n update: 'update',\n delete: 'destroy',\n // associate 操作\n add: 'add',\n set: 'set',\n remove: 'remove',\n ...(options.accessors || {}),\n };\n const keys = [];\n const regexp = pathToRegexp('/resourcer/{:associatedName.}?:resourceName{\\\\::actionName}', keys);\n const matches = regexp.exec(request.path);\n if (matches) {\n const params = {};\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n return params;\n }\n const defaults = {\n single: {\n '/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete\n },\n '/:resourceName/:resourceIndex': {\n get: accessors.get,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasOne: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.get,\n post: accessors.update,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasMany: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n belongsTo: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.get,\n delete: accessors.remove,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n post: accessors.set,\n },\n },\n belongsToMany: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.list,\n post: accessors.set,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n get: accessors.get,\n post: accessors.add,\n put: accessors.update, // Many to Many 的 update 是针对 through\n patch: accessors.update, // Many to Many 的 update 是针对 through\n delete: accessors.remove,\n },\n },\n };\n\n const params: ParsedParams = {};\n\n let prefix = (options.prefix || '').trim().replace(/\\/$/, '');\n\n if (prefix && !prefix.startsWith('/')) {\n prefix = `/${prefix}`;\n }\n\n const { type = 'single' } = request;\n\n for (const path in defaults[type]) {\n const keys = [];\n const regexp = pathToRegexp(`${prefix}${path}`, keys, {});\n const matches = regexp.exec(request.path);\n if (!matches) {\n continue;\n }\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n params.actionName = _.get(defaults, [type, path, request.method.toLowerCase()]);\n }\n\n if (Object.keys(params).length === 0) {\n return false;\n }\n\n if (params.resourceName) {\n const [resourceName, actionName] = params.resourceName.split(':');\n if (actionName) {\n params.resourceName = resourceName;\n params.actionName = actionName;\n }\n }\n\n return params;\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function parseQuery(input: string): any {\n // 自带 query 处理的不太给力,需要用 qs 转一下\n const query = qs.parse(input, {\n // 原始 query string 中如果一个键连等号“=”都没有可以被认为是 null 类型\n strictNullHandling: true,\n // 逗号分隔转换为数组\n comma: true\n });\n // filter 支持 json string\n if (typeof query.filter === 'string') {\n query.filter = JSON.parse(query.filter);\n }\n\n return query;\n}\n\nexport function parseFields(fields: any) {\n if (!fields) {\n return {}\n }\n if (typeof fields === 'string') {\n fields = fields.split(',').map(field => field.trim());\n }\n if (Array.isArray(fields)) {\n const onlyFields = [];\n const output: any = {};\n fields.forEach(item => {\n if (typeof item === 'string') {\n onlyFields.push(item);\n } else if (typeof item === 'object') {\n if (item.only) {\n onlyFields.push(...item.only.toString().split(','));\n }\n Object.assign(output, parseFields(item));\n }\n });\n if (onlyFields.length) {\n output.only = onlyFields;\n }\n return output;\n }\n if (fields.only && typeof fields.only === 'string') {\n fields.only = fields.only.split(',').map(field => field.trim());\n }\n if (fields.except && typeof fields.except === 'string') {\n fields.except = fields.except.split(',').map(field => field.trim());\n }\n if (fields.appends && typeof fields.appends === 'string') {\n fields.appends = fields.appends.split(',').map(field => field.trim());\n }\n return fields;\n}\n\nexport function mergeFields(defaults: any, inputs: any) {\n let fields: any = {};\n defaults = parseFields(defaults);\n inputs = parseFields(inputs);\n if (inputs.only) {\n // 前端提供 only,后端提供 only\n if (defaults.only) {\n fields.only = defaults.only.filter(field => inputs.only.includes(field))\n }\n // 前端提供 only,后端提供 except,输出 only 排除 except\n else if (defaults.except) {\n fields.only = inputs.only.filter(field => !defaults.except.includes(field))\n }\n // 前端提供 only,后端没有提供 only 或 except\n else {\n fields.only = inputs.only;\n }\n } else if (inputs.except) {\n // 前端提供 except,后端提供 only,只输出 only 里排除 except 的字段\n if (defaults.only) {\n fields.only = defaults.only.filter(field => !inputs.except.includes(field))\n }\n // 前端提供 except,后端提供 except 或不提供,合并 except\n else {\n fields.except = _.uniq([...inputs.except, ...(defaults.except || [])]);\n }\n }\n // 前端没提供 only 或 except\n else {\n fields = defaults;\n }\n // 如果前端提供了 appends\n if (!_.isEmpty(inputs.appends)) {\n fields.appends = _.uniq([...inputs.appends, ...(defaults.appends || [])]);\n }\n if (!fields.appends) {\n fields.appends = [];\n }\n return fields;\n}\n"]}
package/lib/utils.js CHANGED
@@ -83,18 +83,18 @@ function parseRequest(request, options = {}) {
83
83
  post: accessors.create,
84
84
  delete: accessors.delete
85
85
  },
86
- '/:resourceName/:resourceKey': {
86
+ '/:resourceName/:resourceIndex': {
87
87
  get: accessors.get,
88
88
  put: accessors.update,
89
89
  patch: accessors.update,
90
90
  delete: accessors.delete
91
91
  },
92
- '/:associatedName/:associatedKey/:resourceName': {
92
+ '/:associatedName/:associatedIndex/:resourceName': {
93
93
  get: accessors.list,
94
94
  post: accessors.create,
95
95
  delete: accessors.delete
96
96
  },
97
- '/:associatedName/:associatedKey/:resourceName/:resourceKey': {
97
+ '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {
98
98
  get: accessors.get,
99
99
  post: accessors.create,
100
100
  put: accessors.update,
@@ -103,7 +103,7 @@ function parseRequest(request, options = {}) {
103
103
  }
104
104
  },
105
105
  hasOne: {
106
- '/:associatedName/:associatedKey/:resourceName': {
106
+ '/:associatedName/:associatedIndex/:resourceName': {
107
107
  get: accessors.get,
108
108
  post: accessors.update,
109
109
  put: accessors.update,
@@ -112,12 +112,12 @@ function parseRequest(request, options = {}) {
112
112
  }
113
113
  },
114
114
  hasMany: {
115
- '/:associatedName/:associatedKey/:resourceName': {
115
+ '/:associatedName/:associatedIndex/:resourceName': {
116
116
  get: accessors.list,
117
117
  post: accessors.create,
118
118
  delete: accessors.delete
119
119
  },
120
- '/:associatedName/:associatedKey/:resourceName/:resourceKey': {
120
+ '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {
121
121
  get: accessors.get,
122
122
  post: accessors.create,
123
123
  put: accessors.update,
@@ -126,20 +126,20 @@ function parseRequest(request, options = {}) {
126
126
  }
127
127
  },
128
128
  belongsTo: {
129
- '/:associatedName/:associatedKey/:resourceName': {
129
+ '/:associatedName/:associatedIndex/:resourceName': {
130
130
  get: accessors.get,
131
131
  delete: accessors.remove
132
132
  },
133
- '/:associatedName/:associatedKey/:resourceName/:resourceKey': {
133
+ '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {
134
134
  post: accessors.set
135
135
  }
136
136
  },
137
137
  belongsToMany: {
138
- '/:associatedName/:associatedKey/:resourceName': {
138
+ '/:associatedName/:associatedIndex/:resourceName': {
139
139
  get: accessors.list,
140
140
  post: accessors.set
141
141
  },
142
- '/:associatedName/:associatedKey/:resourceName/:resourceKey': {
142
+ '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {
143
143
  get: accessors.get,
144
144
  post: accessors.add,
145
145
  put: accessors.update,
@@ -149,7 +149,7 @@ function parseRequest(request, options = {}) {
149
149
  }
150
150
  };
151
151
  const params = {};
152
- let prefix = (options.prefix || '').trim();
152
+ let prefix = (options.prefix || '').trim().replace(/\/$/, '');
153
153
 
154
154
  if (prefix && !prefix.startsWith('/')) {
155
155
  prefix = `/${prefix}`;
package/lib/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import _ from 'lodash';\nimport { pathToRegexp } from 'path-to-regexp';\nimport qs from 'qs';\nimport { ResourceType } from './resource';\n\nexport interface ParseRequest {\n path: string;\n method: string;\n // 资源类型\n type?: ResourceType;\n}\n\nexport interface ParseOptions {\n prefix?: string;\n accessors?: {\n list?: string;\n create?: string;\n get?: string;\n update?: string;\n delete?: string;\n set?: string;\n add?: string;\n };\n}\n\nexport interface ParsedParams {\n actionName?: string;\n resourceName?: string;\n resourceKey?: string;\n associatedName?: string;\n associatedKey?: string;\n // table: string;\n // tableKey?: string | number;\n // relatedTable?: string;\n // relatedKey?: string | number;\n // action?: ActionName,\n}\n\nexport function getNameByParams(params: ParsedParams): string {\n const { resourceName, associatedName } = params;\n return associatedName ? `${associatedName}.${resourceName}` : resourceName;\n}\n\nexport function parseRequest(request: ParseRequest, options: ParseOptions = {}): ParsedParams | false {\n\n const accessors = {\n // 常规 actions\n list: 'list',\n create: 'create',\n get: 'get',\n update: 'update',\n delete: 'destroy',\n // associate 操作\n add: 'add',\n set: 'set',\n remove: 'remove',\n ...(options.accessors || {}),\n };\n const keys = [];\n const regexp = pathToRegexp('/resourcer/{:associatedName.}?:resourceName{\\\\::actionName}', keys);\n const matches = regexp.exec(request.path);\n if (matches) {\n const params = {};\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n return params;\n }\n const defaults = {\n single: {\n '/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete\n },\n '/:resourceName/:resourceKey': {\n get: accessors.get,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasOne: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.get,\n post: accessors.update,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasMany: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n belongsTo: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.get,\n delete: accessors.remove,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n post: accessors.set,\n },\n },\n belongsToMany: {\n '/:associatedName/:associatedKey/:resourceName': {\n get: accessors.list,\n post: accessors.set,\n },\n '/:associatedName/:associatedKey/:resourceName/:resourceKey': {\n get: accessors.get,\n post: accessors.add,\n put: accessors.update, // Many to Many 的 update 是针对 through\n patch: accessors.update, // Many to Many 的 update 是针对 through\n delete: accessors.remove,\n },\n },\n };\n\n const params: ParsedParams = {};\n\n let prefix = (options.prefix || '').trim();\n\n if (prefix && !prefix.startsWith('/')) {\n prefix = `/${prefix}`;\n }\n\n const { type = 'single' } = request;\n\n for (const path in defaults[type]) {\n const keys = [];\n const regexp = pathToRegexp(`${prefix}${path}`, keys, {});\n const matches = regexp.exec(request.path);\n if (!matches) {\n continue;\n }\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n params.actionName = _.get(defaults, [type, path, request.method.toLowerCase()]);\n }\n\n if (Object.keys(params).length === 0) {\n return false;\n }\n\n if (params.resourceName) {\n const [resourceName, actionName] = params.resourceName.split(':');\n if (actionName) {\n params.resourceName = resourceName;\n params.actionName = actionName;\n }\n }\n\n return params;\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function parseQuery(input: string): any {\n // 自带 query 处理的不太给力,需要用 qs 转一下\n const query = qs.parse(input, {\n // 原始 query string 中如果一个键连等号“=”都没有可以被认为是 null 类型\n strictNullHandling: true,\n // 逗号分隔转换为数组\n comma: true\n });\n // filter 支持 json string\n if (typeof query.filter === 'string') {\n query.filter = JSON.parse(query.filter);\n }\n\n return query;\n}\n\nexport function parseFields(fields: any) {\n if (!fields) {\n return {}\n }\n if (typeof fields === 'string') {\n fields = fields.split(',').map(field => field.trim());\n }\n if (Array.isArray(fields)) {\n const onlyFields = [];\n const output: any = {};\n fields.forEach(item => {\n if (typeof item === 'string') {\n onlyFields.push(item);\n } else if (typeof item === 'object') {\n if (item.only) {\n onlyFields.push(...item.only.toString().split(','));\n }\n Object.assign(output, parseFields(item));\n }\n });\n if (onlyFields.length) {\n output.only = onlyFields;\n }\n return output;\n }\n if (fields.only && typeof fields.only === 'string') {\n fields.only = fields.only.split(',').map(field => field.trim());\n }\n if (fields.except && typeof fields.except === 'string') {\n fields.except = fields.except.split(',').map(field => field.trim());\n }\n if (fields.appends && typeof fields.appends === 'string') {\n fields.appends = fields.appends.split(',').map(field => field.trim());\n }\n return fields;\n}\n\nexport function mergeFields(defaults: any, inputs: any) {\n let fields: any = {};\n defaults = parseFields(defaults);\n inputs = parseFields(inputs);\n if (inputs.only) {\n // 前端提供 only,后端提供 only\n if (defaults.only) {\n fields.only = defaults.only.filter(field => inputs.only.includes(field))\n }\n // 前端提供 only,后端提供 except,输出 only 排除 except\n else if (defaults.except) {\n fields.only = inputs.only.filter(field => !defaults.except.includes(field))\n }\n // 前端提供 only,后端没有提供 only 或 except\n else {\n fields.only = inputs.only;\n }\n } else if (inputs.except) {\n // 前端提供 except,后端提供 only,只输出 only 里排除 except 的字段\n if (defaults.only) {\n fields.only = defaults.only.filter(field => !inputs.except.includes(field))\n }\n // 前端提供 except,后端提供 except 或不提供,合并 except\n else {\n fields.except = _.uniq([...inputs.except, ...(defaults.except || [])]);\n }\n }\n // 前端没提供 only 或 except\n else {\n fields = defaults;\n }\n // 如果前端提供了 appends\n if (!_.isEmpty(inputs.appends)) {\n fields.appends = _.uniq([...inputs.appends, ...(defaults.appends || [])]);\n }\n if (!fields.appends) {\n fields.appends = [];\n }\n return fields;\n}\n"]}
1
+ {"version":3,"sources":["utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import _ from 'lodash';\nimport { pathToRegexp } from 'path-to-regexp';\nimport qs from 'qs';\nimport { ResourceType } from './resource';\n\nexport interface ParseRequest {\n path: string;\n method: string;\n // 资源类型\n type?: ResourceType;\n}\n\nexport interface ParseOptions {\n prefix?: string;\n accessors?: {\n list?: string;\n create?: string;\n get?: string;\n update?: string;\n delete?: string;\n set?: string;\n add?: string;\n };\n}\n\nexport interface ParsedParams {\n actionName?: string;\n resourceName?: string;\n resourceIndex?: string;\n associatedName?: string;\n associatedIndex?: string;\n // table: string;\n // tableKey?: string | number;\n // relatedTable?: string;\n // relatedKey?: string | number;\n // action?: ActionName,\n}\n\nexport function getNameByParams(params: ParsedParams): string {\n const { resourceName, associatedName } = params;\n return associatedName ? `${associatedName}.${resourceName}` : resourceName;\n}\n\nexport function parseRequest(request: ParseRequest, options: ParseOptions = {}): ParsedParams | false {\n\n const accessors = {\n // 常规 actions\n list: 'list',\n create: 'create',\n get: 'get',\n update: 'update',\n delete: 'destroy',\n // associate 操作\n add: 'add',\n set: 'set',\n remove: 'remove',\n ...(options.accessors || {}),\n };\n const keys = [];\n const regexp = pathToRegexp('/resourcer/{:associatedName.}?:resourceName{\\\\::actionName}', keys);\n const matches = regexp.exec(request.path);\n if (matches) {\n const params = {};\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n return params;\n }\n const defaults = {\n single: {\n '/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete\n },\n '/:resourceName/:resourceIndex': {\n get: accessors.get,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasOne: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.get,\n post: accessors.update,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n hasMany: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.list,\n post: accessors.create,\n delete: accessors.delete,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n get: accessors.get,\n post: accessors.create,\n put: accessors.update,\n patch: accessors.update,\n delete: accessors.delete,\n },\n },\n belongsTo: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.get,\n delete: accessors.remove,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n post: accessors.set,\n },\n },\n belongsToMany: {\n '/:associatedName/:associatedIndex/:resourceName': {\n get: accessors.list,\n post: accessors.set,\n },\n '/:associatedName/:associatedIndex/:resourceName/:resourceIndex': {\n get: accessors.get,\n post: accessors.add,\n put: accessors.update, // Many to Many 的 update 是针对 through\n patch: accessors.update, // Many to Many 的 update 是针对 through\n delete: accessors.remove,\n },\n },\n };\n\n const params: ParsedParams = {};\n\n let prefix = (options.prefix || '').trim().replace(/\\/$/, '');\n\n if (prefix && !prefix.startsWith('/')) {\n prefix = `/${prefix}`;\n }\n\n const { type = 'single' } = request;\n\n for (const path in defaults[type]) {\n const keys = [];\n const regexp = pathToRegexp(`${prefix}${path}`, keys, {});\n const matches = regexp.exec(request.path);\n if (!matches) {\n continue;\n }\n keys.forEach((obj, index) => {\n if (matches[index + 1] === undefined) {\n return;\n }\n params[obj.name] = matches[index + 1];\n });\n params.actionName = _.get(defaults, [type, path, request.method.toLowerCase()]);\n }\n\n if (Object.keys(params).length === 0) {\n return false;\n }\n\n if (params.resourceName) {\n const [resourceName, actionName] = params.resourceName.split(':');\n if (actionName) {\n params.resourceName = resourceName;\n params.actionName = actionName;\n }\n }\n\n return params;\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function parseQuery(input: string): any {\n // 自带 query 处理的不太给力,需要用 qs 转一下\n const query = qs.parse(input, {\n // 原始 query string 中如果一个键连等号“=”都没有可以被认为是 null 类型\n strictNullHandling: true,\n // 逗号分隔转换为数组\n comma: true\n });\n // filter 支持 json string\n if (typeof query.filter === 'string') {\n query.filter = JSON.parse(query.filter);\n }\n\n return query;\n}\n\nexport function parseFields(fields: any) {\n if (!fields) {\n return {}\n }\n if (typeof fields === 'string') {\n fields = fields.split(',').map(field => field.trim());\n }\n if (Array.isArray(fields)) {\n const onlyFields = [];\n const output: any = {};\n fields.forEach(item => {\n if (typeof item === 'string') {\n onlyFields.push(item);\n } else if (typeof item === 'object') {\n if (item.only) {\n onlyFields.push(...item.only.toString().split(','));\n }\n Object.assign(output, parseFields(item));\n }\n });\n if (onlyFields.length) {\n output.only = onlyFields;\n }\n return output;\n }\n if (fields.only && typeof fields.only === 'string') {\n fields.only = fields.only.split(',').map(field => field.trim());\n }\n if (fields.except && typeof fields.except === 'string') {\n fields.except = fields.except.split(',').map(field => field.trim());\n }\n if (fields.appends && typeof fields.appends === 'string') {\n fields.appends = fields.appends.split(',').map(field => field.trim());\n }\n return fields;\n}\n\nexport function mergeFields(defaults: any, inputs: any) {\n let fields: any = {};\n defaults = parseFields(defaults);\n inputs = parseFields(inputs);\n if (inputs.only) {\n // 前端提供 only,后端提供 only\n if (defaults.only) {\n fields.only = defaults.only.filter(field => inputs.only.includes(field))\n }\n // 前端提供 only,后端提供 except,输出 only 排除 except\n else if (defaults.except) {\n fields.only = inputs.only.filter(field => !defaults.except.includes(field))\n }\n // 前端提供 only,后端没有提供 only 或 except\n else {\n fields.only = inputs.only;\n }\n } else if (inputs.except) {\n // 前端提供 except,后端提供 only,只输出 only 里排除 except 的字段\n if (defaults.only) {\n fields.only = defaults.only.filter(field => !inputs.except.includes(field))\n }\n // 前端提供 except,后端提供 except 或不提供,合并 except\n else {\n fields.except = _.uniq([...inputs.except, ...(defaults.except || [])]);\n }\n }\n // 前端没提供 only 或 except\n else {\n fields = defaults;\n }\n // 如果前端提供了 appends\n if (!_.isEmpty(inputs.appends)) {\n fields.appends = _.uniq([...inputs.appends, ...(defaults.appends || [])]);\n }\n if (!fields.appends) {\n fields.appends = [];\n }\n return fields;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/resourcer",
3
- "version": "0.5.0-alpha.34",
3
+ "version": "0.5.0-alpha.35",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -18,5 +18,5 @@
18
18
  "url": "git+https://github.com/nocobase/nocobase.git",
19
19
  "directory": "packages/resourcer"
20
20
  },
21
- "gitHead": "11cded6153bab633fb0b7415c33b4c3c369c2427"
21
+ "gitHead": "2b81a6af327ee784a6943aff6e028fde3298dec9"
22
22
  }