@cloudcome/utils-uni 1.7.1 → 1.9.0

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.
@@ -33,6 +33,13 @@ export type BuildCloudExposeCreatorOptions = {
33
33
  * @default '需要登录后才能进行此操作'
34
34
  */
35
35
  requiredUserErrMsg?: string;
36
+ /**
37
+ * 响应附加数据函数
38
+ * 用于在云对象响应中添加额外的上下文信息
39
+ * @param objectThis 云对象上下文
40
+ * @returns 返回要附加到响应中的数据对象
41
+ */
42
+ respondAppend?: (objectThis: UniCloudObjectThis) => AnyObject;
36
43
  };
37
44
  export type CreateCloudObjectOptions = {
38
45
  /**
@@ -45,4 +52,36 @@ export type CreateCloudObjectExpose = {
45
52
  <S extends ZodObject, O>(schema: S, fn: (context: UniCloudObjectContext, input: z.infer<S>) => MaybePromise<O>, options?: CreateCloudObjectOptions): UniCloudObject<z.infer<S>, O>;
46
53
  <O>(fn: (context: UniCloudObjectContext) => MaybePromise<O>, options?: CreateCloudObjectOptions): UniCloudObject<void, O>;
47
54
  };
55
+ /**
56
+ * 构建云对象暴露创建器
57
+ *
58
+ * 该函数用于创建一个云对象暴露函数,可以处理用户身份验证、输入验证和错误处理等通用逻辑
59
+ *
60
+ * @param options 构建选项配置
61
+ * @param options.uniIdCloudObject 可选的UniIdCloudObject实例,用于处理用户身份验证和权限管理
62
+ * @param options.requiredUserErrCode 需要用户登录态时的错误码,默认为 'uni-id-check-token-failed'
63
+ * @param options.requiredUserErrMsg 需要用户登录态时的错误消息,默认为 '需要登录后才能进行此操作'
64
+ *
65
+ * @returns 返回一个云对象暴露创建函数,支持两种重载形式:
66
+ * 1. 无输入参数的形式:(fn, options) => UniCloudObject
67
+ * 2. 有输入验证的形式:(schema, fn, options) => UniCloudObject
68
+ *
69
+ * @example
70
+ * // 无输入参数的使用方式
71
+ * const expose = buildCloudObjectExposeCreator();
72
+ * export default expose(async (context) => {
73
+ * // 业务逻辑
74
+ * });
75
+ *
76
+ * @example
77
+ * // 有输入验证的使用方式
78
+ * const expose = buildCloudObjectExposeCreator();
79
+ * const schema = z.object({
80
+ * name: z.string().min(1)
81
+ * });
82
+ *
83
+ * export default expose(schema, async (context, input) => {
84
+ * // 业务逻辑,input类型已自动推断
85
+ * });
86
+ */
48
87
  export declare function buildCloudObjectExposeCreator(options?: BuildCloudExposeCreatorOptions): CreateCloudObjectExpose;
@@ -124,7 +124,6 @@ export type UniCloudObjectThis = {
124
124
  getHttpInfo: () => HttpInfo | undefined;
125
125
  };
126
126
  export type UniCloudObjectOutput<T> = {
127
- requestId?: string;
128
127
  errCode?: number | string;
129
128
  errMsg?: string;
130
129
  data: T;
@@ -1,3 +1,24 @@
1
1
  import { MaybePromise } from '@cloudcome/utils-core/types';
2
2
  import { UniCloudObjectOutput } from './object';
3
- export declare function respondCloudObject<O>(fn: () => MaybePromise<O>, requestId?: string): Promise<UniCloudObjectOutput<O>>;
3
+ /**
4
+ * 处理云函数响应结果,统一返回格式
5
+ * @param fn - 执行函数,可以返回任意类型的值或Promise
6
+ * @param append - 需要附加到响应结果中的额外字段
7
+ * @returns 统一格式的云函数响应结果
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // 成功情况
12
+ * const result = await respondCloudObject(async () => {
13
+ * return { name: 'test', value: 123 };
14
+ * });
15
+ * // 返回: { errCode: 0, errMsg: '', data: { name: 'test', value: 123 } }
16
+ *
17
+ * // 失败情况
18
+ * const result = await respondCloudObject(() => {
19
+ * throw new Error('操作失败');
20
+ * });
21
+ * // 返回: { errCode: -1, errMsg: '操作失败', data: null }
22
+ * ```
23
+ */
24
+ export declare function respondCloudObject<O>(fn: () => MaybePromise<O>, append?: AnyObject): Promise<UniCloudObjectOutput<O>>;
package/dist/cloud.cjs CHANGED
@@ -11,32 +11,33 @@ function createCloudObjectError(message, code) {
11
11
  errMsg: message
12
12
  });
13
13
  }
14
- async function respondCloudObject(fn, requestId) {
14
+ async function respondCloudObject(fn, append) {
15
15
  try {
16
16
  const data = await fn();
17
17
  return {
18
- requestId,
19
- data,
20
18
  errCode: 0,
21
- errMsg: ""
19
+ errMsg: "",
20
+ data,
21
+ ...append
22
22
  };
23
23
  } catch (err) {
24
24
  console.error("respondCloudObject error");
25
25
  console.error(err);
26
26
  const err2 = error.errorNormalize(err);
27
27
  return {
28
- requestId,
28
+ errCode: err2.errCode || -1,
29
+ errMsg: err2.errMsg || err2.message || "",
29
30
  // @ts-ignore
30
31
  data: null,
31
- errCode: err2.errCode || -1,
32
- errMsg: err2.errMsg || err2.message || ""
32
+ ...append
33
33
  };
34
34
  }
35
35
  }
36
36
  function buildCloudObjectExposeCreator(options) {
37
37
  const buildOptions = object.objectDefaults(options || {}, {
38
38
  requiredUserErrCode: "uni-id-check-token-failed",
39
- requiredUserErrMsg: "需要登录后才能进行此操作"
39
+ requiredUserErrMsg: "需要登录后才能进行此操作",
40
+ respondAppend: () => ({})
40
41
  });
41
42
  const createCloudObjectExpose = (arg0, arg1, arg2) => {
42
43
  const optionsSource = type.isFunction(arg0) ? arg1 : arg2;
@@ -65,7 +66,7 @@ function buildCloudObjectExposeCreator(options) {
65
66
  throw new Error("请求数据不正确");
66
67
  }
67
68
  return await arg1(context, parsed.data);
68
- }, this.getUniCloudRequestId());
69
+ }, buildOptions.respondAppend(this));
69
70
  };
70
71
  };
71
72
  return createCloudObjectExpose;
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.cjs","sources":["../src/cloud/error.ts","../src/cloud/respond.ts","../src/cloud/expose.ts"],"sourcesContent":["import { errorAssign } from '@cloudcome/utils-core/error';\n\nexport function createCloudObjectError(message: string, code?: number | string) {\n return errorAssign(new Error(message), {\n errCode: code,\n errMsg: message,\n });\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { UniCloudObjectOutput } from './object';\n\nexport async function respondCloudObject<O>(\n fn: () => MaybePromise<O>,\n requestId?: string,\n): Promise<UniCloudObjectOutput<O>> {\n try {\n const data = await fn();\n\n return {\n requestId,\n data,\n errCode: 0,\n errMsg: '',\n };\n } catch (err) {\n console.error('respondCloudObject error');\n console.error(err);\n\n const err2 = errorNormalize(err as Error & { errCode?: number | string; errMsg?: string });\n\n return {\n requestId,\n // @ts-ignore\n data: null,\n errCode: err2.errCode || -1,\n errMsg: err2.errMsg || err2.message || '',\n };\n }\n}\n","import { parseCloudObjectOutput } from '@/_helpers';\nimport { objectDefaults } from '@cloudcome/utils-core/object';\nimport { tryFlatten } from '@cloudcome/utils-core/try';\nimport { isFunction } from '@cloudcome/utils-core/type';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type z from 'zod';\nimport type { ZodObject } from 'zod';\nimport { createCloudObjectError } from './error';\nimport type { UniCloudObject, UniCloudObjectThis } from './object';\nimport { respondCloudObject } from './respond';\nimport type { UniIdCloudObject } from './uni-id';\n\nexport type UniCloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\nexport type UniCloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: UniCloudObjectThisAppendUser;\n};\n\nexport type UniCloudObjectContext = UniCloudObjectThis & UniCloudObjectThisAppend;\n\n/**\n * 构建云函数暴露创建器的选项配置\n * 用于配置云函数暴露创建器的行为,目前支持传入UniIdCloudObject实例\n */\nexport type BuildCloudExposeCreatorOptions = {\n /**\n * 可选的UniIdCloudObject实例\n * 用于处理用户身份验证和权限管理相关功能\n */\n uniIdCloudObject?: UniIdCloudObject;\n\n /**\n * 需要用户登录态的错误码\n * @default 'uni-id-check-token-failed'\n */\n requiredUserErrCode?: number | string;\n\n /**\n * 需要用户登录态的错误消息\n * @default '需要登录后才能进行此操作'\n */\n requiredUserErrMsg?: string;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n};\n\nexport type CreateCloudObjectExpose = {\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: UniCloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<z.infer<S>, O>;\n <O>(\n fn: (context: UniCloudObjectContext) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<void, O>;\n};\n\nexport function buildCloudObjectExposeCreator(options?: BuildCloudExposeCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n }) as Required<BuildCloudExposeCreatorOptions>;\n\n // @ts-ignore\n const createCloudObjectExpose: CreateCloudObjectExpose = (arg0, arg1, arg2) => {\n // 选项来源\n const optionsSource = (isFunction(arg0) ? arg1 : arg2) as CreateCloudObjectOptions | undefined;\n // 设置默认选项值\n const createOptions = objectDefaults(optionsSource || {}, {\n requiredUser: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云函数响应逻辑\n return await respondCloudObject(async () => {\n // 构建附加的上下文信息\n const user = await parseAppendUser(this, options?.uniIdCloudObject);\n const append: UniCloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as UniCloudObjectContext;\n\n if (createOptions.requiredUser && !user.id) {\n throw createCloudObjectError(buildOptions.requiredUserErrMsg, buildOptions.requiredUserErrCode);\n }\n\n // 无入参\n if (isFunction(arg0)) {\n return await arg0(context);\n }\n\n // 单入参\n // 验证输入数据\n const parsed = arg0.safeParse(input);\n\n if (!parsed.success) {\n console.log(parsed.error.issues);\n\n const issue0 = parsed.error?.issues?.[0];\n\n // 处理验证错误\n if (issue0?.code === 'custom') throw issue0.message;\n throw new Error('请求数据不正确');\n }\n\n return await arg1(context, parsed.data);\n }, this.getUniCloudRequestId());\n };\n };\n\n return createCloudObjectExpose;\n}\n\nasync function parseAppendUser(\n objectThis: UniCloudObjectThis,\n uniIdCloudObject?: UniIdCloudObject,\n): Promise<UniCloudObjectThisAppendUser> {\n const appendUser: UniCloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCloudObject) return appendUser;\n\n const uniId = uniIdCloudObject.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 忽略错误1\n const [err1, user] = await tryFlatten(uniId.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 忽略错误2\n const [err2, userData] = tryFlatten(() => parseCloudObjectOutput(user));\n if (!userData) return appendUser;\n\n appendUser.id = userData.uid || '';\n appendUser.role = userData.role || [];\n appendUser.permission = userData.permission || [];\n appendUser.isAdmin = appendUser.role.includes('admin') && appendUser.permission.length === 0;\n\n return appendUser;\n}\n"],"names":["errorAssign","errorNormalize","objectDefaults","isFunction","tryFlatten","parseCloudObjectOutput"],"mappings":";;;;;;;AAEgB,SAAA,uBAAuB,SAAiB,MAAwB;AAC9E,SAAOA,kBAAY,IAAI,MAAM,OAAO,GAAG;AAAA,IACrC,SAAS;AAAA,IACT,QAAQ;AAAA,EAAA,CACT;AACH;ACHsB,eAAA,mBACpB,IACA,WACkC;AAC9B,MAAA;AACI,UAAA,OAAO,MAAM,GAAG;AAEf,WAAA;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,WACO,KAAK;AACZ,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,GAAG;AAEX,UAAA,OAAOC,qBAAe,GAA6D;AAElF,WAAA;AAAA,MACL;AAAA;AAAA,MAEA,MAAM;AAAA,MACN,SAAS,KAAK,WAAW;AAAA,MACzB,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA,IACzC;AAAA,EAAA;AAEJ;ACuCO,SAAS,8BAA8B,SAA0C;AACtF,QAAM,eAAeC,OAAAA,eAAe,WAAW,IAAI;AAAA,IACjD,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,EAAA,CACrB;AAGD,QAAM,0BAAmD,CAAC,MAAM,MAAM,SAAS;AAE7E,UAAM,gBAAiBC,KAAA,WAAW,IAAI,IAAI,OAAO;AAEjD,UAAM,gBAAgBD,OAAAA,eAAe,iBAAiB,IAAI;AAAA,MACxD,cAAc;AAAA,IAAA,CACf;AAED,WAAO,eAAgB,OAAO;AAErB,aAAA,MAAM,mBAAmB,YAAY;AAE1C,cAAM,OAAO,MAAM,gBAAgB,MAAM,SAAS,gBAAgB;AAClE,cAAM,SAAmC;AAAA,UACvC,SAAS;AAAA,UACT;AAAA,QACF;AACA,cAAM,UAAU,OAAO,OAAO,MAAM,MAAM;AAE1C,YAAI,cAAc,gBAAgB,CAAC,KAAK,IAAI;AAC1C,gBAAM,uBAAuB,aAAa,oBAAoB,aAAa,mBAAmB;AAAA,QAAA;AAI5F,YAAAC,KAAAA,WAAW,IAAI,GAAG;AACb,iBAAA,MAAM,KAAK,OAAO;AAAA,QAAA;AAKrB,cAAA,SAAS,KAAK,UAAU,KAAK;AAE/B,YAAA,CAAC,OAAO,SAAS;AACX,kBAAA,IAAI,OAAO,MAAM,MAAM;AAE/B,gBAAM,SAAS,OAAO,OAAO,SAAS,CAAC;AAGvC,cAAI,QAAQ,SAAS,SAAU,OAAM,OAAO;AACtC,gBAAA,IAAI,MAAM,SAAS;AAAA,QAAA;AAG3B,eAAO,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,MAAA,GACrC,KAAK,sBAAsB;AAAA,IAChC;AAAA,EACF;AAEO,SAAA;AACT;AAEA,eAAe,gBACb,YACA,kBACuC;AACvC,QAAM,aAA2C;AAAA,IAC/C,IAAI;AAAA,IACJ,MAAM,CAAC;AAAA,IACP,YAAY,CAAC;AAAA,IACb,SAAS;AAAA,EACX;AAEI,MAAA,CAAC,iBAAyB,QAAA;AAExB,QAAA,QAAQ,iBAAiB,eAAe;AAAA,IAC5C,YAAY,WAAW,cAAc;AAAA,EAAA,CACtC;AAGD,QAAM,CAAC,MAAM,IAAI,IAAI,MAAMC,KAAA,WAAW,MAAM,WAAW,WAAW,cAAmB,KAAA,EAAE,CAAC;AACpF,MAAA,CAAC,KAAa,QAAA;AAGZ,QAAA,CAAC,MAAM,QAAQ,IAAIA,gBAAW,MAAMC,SAAAA,uBAAuB,IAAI,CAAC;AAClE,MAAA,CAAC,SAAiB,QAAA;AAEX,aAAA,KAAK,SAAS,OAAO;AACrB,aAAA,OAAO,SAAS,QAAQ,CAAC;AACzB,aAAA,aAAa,SAAS,cAAc,CAAC;AACrC,aAAA,UAAU,WAAW,KAAK,SAAS,OAAO,KAAK,WAAW,WAAW,WAAW;AAEpF,SAAA;AACT;;;;"}
1
+ {"version":3,"file":"cloud.cjs","sources":["../src/cloud/error.ts","../src/cloud/respond.ts","../src/cloud/expose.ts"],"sourcesContent":["import { errorAssign } from '@cloudcome/utils-core/error';\n\nexport function createCloudObjectError(message: string, code?: number | string) {\n return errorAssign(new Error(message), {\n errCode: code,\n errMsg: message,\n });\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { UniCloudObjectOutput } from './object';\n\n/**\n * 处理云函数响应结果,统一返回格式\n * @param fn - 执行函数,可以返回任意类型的值或Promise\n * @param append - 需要附加到响应结果中的额外字段\n * @returns 统一格式的云函数响应结果\n *\n * @example\n * ```typescript\n * // 成功情况\n * const result = await respondCloudObject(async () => {\n * return { name: 'test', value: 123 };\n * });\n * // 返回: { errCode: 0, errMsg: '', data: { name: 'test', value: 123 } }\n *\n * // 失败情况\n * const result = await respondCloudObject(() => {\n * throw new Error('操作失败');\n * });\n * // 返回: { errCode: -1, errMsg: '操作失败', data: null }\n * ```\n */\nexport async function respondCloudObject<O>(\n fn: () => MaybePromise<O>,\n append?: AnyObject,\n): Promise<UniCloudObjectOutput<O>> {\n try {\n const data = await fn();\n\n return {\n errCode: 0,\n errMsg: '',\n data,\n ...append,\n };\n } catch (err) {\n console.error('respondCloudObject error');\n console.error(err);\n\n const err2 = errorNormalize(err as Error & { errCode?: number | string; errMsg?: string });\n\n return {\n errCode: err2.errCode || -1,\n errMsg: err2.errMsg || err2.message || '',\n // @ts-ignore\n data: null,\n ...append,\n };\n }\n}\n","import { parseCloudObjectOutput } from '@/_helpers';\nimport { objectDefaults } from '@cloudcome/utils-core/object';\nimport { tryFlatten } from '@cloudcome/utils-core/try';\nimport { isFunction } from '@cloudcome/utils-core/type';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type z from 'zod';\nimport type { ZodObject } from 'zod';\nimport { createCloudObjectError } from './error';\nimport type { UniCloudObject, UniCloudObjectThis } from './object';\nimport { respondCloudObject } from './respond';\nimport type { UniIdCloudObject } from './uni-id';\n\nexport type UniCloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\nexport type UniCloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: UniCloudObjectThisAppendUser;\n};\n\nexport type UniCloudObjectContext = UniCloudObjectThis & UniCloudObjectThisAppend;\n\n/**\n * 构建云函数暴露创建器的选项配置\n * 用于配置云函数暴露创建器的行为,目前支持传入UniIdCloudObject实例\n */\nexport type BuildCloudExposeCreatorOptions = {\n /**\n * 可选的UniIdCloudObject实例\n * 用于处理用户身份验证和权限管理相关功能\n */\n uniIdCloudObject?: UniIdCloudObject;\n\n /**\n * 需要用户登录态的错误码\n * @default 'uni-id-check-token-failed'\n */\n requiredUserErrCode?: number | string;\n\n /**\n * 需要用户登录态的错误消息\n * @default '需要登录后才能进行此操作'\n */\n requiredUserErrMsg?: string;\n\n /**\n * 响应附加数据函数\n * 用于在云对象响应中添加额外的上下文信息\n * @param objectThis 云对象上下文\n * @returns 返回要附加到响应中的数据对象\n */\n respondAppend?: (objectThis: UniCloudObjectThis) => AnyObject;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n};\n\nexport type CreateCloudObjectExpose = {\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: UniCloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<z.infer<S>, O>;\n <O>(\n fn: (context: UniCloudObjectContext) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<void, O>;\n};\n\n/**\n * 构建云对象暴露创建器\n *\n * 该函数用于创建一个云对象暴露函数,可以处理用户身份验证、输入验证和错误处理等通用逻辑\n *\n * @param options 构建选项配置\n * @param options.uniIdCloudObject 可选的UniIdCloudObject实例,用于处理用户身份验证和权限管理\n * @param options.requiredUserErrCode 需要用户登录态时的错误码,默认为 'uni-id-check-token-failed'\n * @param options.requiredUserErrMsg 需要用户登录态时的错误消息,默认为 '需要登录后才能进行此操作'\n *\n * @returns 返回一个云对象暴露创建函数,支持两种重载形式:\n * 1. 无输入参数的形式:(fn, options) => UniCloudObject\n * 2. 有输入验证的形式:(schema, fn, options) => UniCloudObject\n *\n * @example\n * // 无输入参数的使用方式\n * const expose = buildCloudObjectExposeCreator();\n * export default expose(async (context) => {\n * // 业务逻辑\n * });\n *\n * @example\n * // 有输入验证的使用方式\n * const expose = buildCloudObjectExposeCreator();\n * const schema = z.object({\n * name: z.string().min(1)\n * });\n *\n * export default expose(schema, async (context, input) => {\n * // 业务逻辑,input类型已自动推断\n * });\n */\nexport function buildCloudObjectExposeCreator(options?: BuildCloudExposeCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n respondAppend: () => ({}),\n }) as Required<BuildCloudExposeCreatorOptions>;\n\n // @ts-ignore\n const createCloudObjectExpose: CreateCloudObjectExpose = (arg0, arg1, arg2) => {\n // 确定选项来源:如果arg0是函数,则选项在arg1;否则在arg2\n const optionsSource = (isFunction(arg0) ? arg1 : arg2) as CreateCloudObjectOptions | undefined;\n\n // 设置默认选项值\n const createOptions = objectDefaults(optionsSource || {}, {\n requiredUser: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云函数响应逻辑,包括错误捕获和统一响应格式\n return await respondCloudObject(async () => {\n // 构建附加的上下文信息,包括用户身份和权限信息\n const user = await parseAppendUser(this, options?.uniIdCloudObject);\n const append: UniCloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as UniCloudObjectContext;\n\n // 如果需要用户登录态但用户未登录,则抛出错误\n if (createOptions.requiredUser && !user.id) {\n throw createCloudObjectError(buildOptions.requiredUserErrMsg, buildOptions.requiredUserErrCode);\n }\n\n // 无入参函数调用\n if (isFunction(arg0)) {\n return await arg0(context);\n }\n\n // 有入参函数调用 - 验证输入数据\n const parsed = arg0.safeParse(input);\n\n // 输入验证失败处理\n if (!parsed.success) {\n console.log(parsed.error.issues);\n\n const issue0 = parsed.error?.issues?.[0];\n\n // 处理自定义验证错误\n if (issue0?.code === 'custom') throw issue0.message;\n throw new Error('请求数据不正确');\n }\n\n // 执行业务逻辑函数,传入上下文和验证后的数据\n return await arg1(context, parsed.data);\n }, buildOptions.respondAppend(this));\n };\n };\n\n return createCloudObjectExpose;\n}\n\nasync function parseAppendUser(\n objectThis: UniCloudObjectThis,\n uniIdCloudObject?: UniIdCloudObject,\n): Promise<UniCloudObjectThisAppendUser> {\n const appendUser: UniCloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCloudObject) return appendUser;\n\n const uniId = uniIdCloudObject.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 忽略错误1\n const [err1, user] = await tryFlatten(uniId.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 忽略错误2\n const [err2, userData] = tryFlatten(() => parseCloudObjectOutput(user));\n if (!userData) return appendUser;\n\n appendUser.id = userData.uid || '';\n appendUser.role = userData.role || [];\n appendUser.permission = userData.permission || [];\n appendUser.isAdmin = appendUser.role.includes('admin') && appendUser.permission.length === 0;\n\n return appendUser;\n}\n"],"names":["errorAssign","errorNormalize","objectDefaults","isFunction","tryFlatten","parseCloudObjectOutput"],"mappings":";;;;;;;AAEgB,SAAA,uBAAuB,SAAiB,MAAwB;AAC9E,SAAOA,kBAAY,IAAI,MAAM,OAAO,GAAG;AAAA,IACrC,SAAS;AAAA,IACT,QAAQ;AAAA,EAAA,CACT;AACH;ACkBsB,eAAA,mBACpB,IACA,QACkC;AAC9B,MAAA;AACI,UAAA,OAAO,MAAM,GAAG;AAEf,WAAA;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR;AAAA,MACA,GAAG;AAAA,IACL;AAAA,WACO,KAAK;AACZ,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,GAAG;AAEX,UAAA,OAAOC,qBAAe,GAA6D;AAElF,WAAA;AAAA,MACL,SAAS,KAAK,WAAW;AAAA,MACzB,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA;AAAA,MAEvC,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AAAA,EAAA;AAEJ;AC0DO,SAAS,8BAA8B,SAA0C;AACtF,QAAM,eAAeC,OAAAA,eAAe,WAAW,IAAI;AAAA,IACjD,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,eAAe,OAAO,CAAC;AAAA,EAAA,CACxB;AAGD,QAAM,0BAAmD,CAAC,MAAM,MAAM,SAAS;AAE7E,UAAM,gBAAiBC,KAAA,WAAW,IAAI,IAAI,OAAO;AAGjD,UAAM,gBAAgBD,OAAAA,eAAe,iBAAiB,IAAI;AAAA,MACxD,cAAc;AAAA,IAAA,CACf;AAED,WAAO,eAAgB,OAAO;AAErB,aAAA,MAAM,mBAAmB,YAAY;AAE1C,cAAM,OAAO,MAAM,gBAAgB,MAAM,SAAS,gBAAgB;AAClE,cAAM,SAAmC;AAAA,UACvC,SAAS;AAAA,UACT;AAAA,QACF;AACA,cAAM,UAAU,OAAO,OAAO,MAAM,MAAM;AAG1C,YAAI,cAAc,gBAAgB,CAAC,KAAK,IAAI;AAC1C,gBAAM,uBAAuB,aAAa,oBAAoB,aAAa,mBAAmB;AAAA,QAAA;AAI5F,YAAAC,KAAAA,WAAW,IAAI,GAAG;AACb,iBAAA,MAAM,KAAK,OAAO;AAAA,QAAA;AAIrB,cAAA,SAAS,KAAK,UAAU,KAAK;AAG/B,YAAA,CAAC,OAAO,SAAS;AACX,kBAAA,IAAI,OAAO,MAAM,MAAM;AAE/B,gBAAM,SAAS,OAAO,OAAO,SAAS,CAAC;AAGvC,cAAI,QAAQ,SAAS,SAAU,OAAM,OAAO;AACtC,gBAAA,IAAI,MAAM,SAAS;AAAA,QAAA;AAI3B,eAAO,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,MAAA,GACrC,aAAa,cAAc,IAAI,CAAC;AAAA,IACrC;AAAA,EACF;AAEO,SAAA;AACT;AAEA,eAAe,gBACb,YACA,kBACuC;AACvC,QAAM,aAA2C;AAAA,IAC/C,IAAI;AAAA,IACJ,MAAM,CAAC;AAAA,IACP,YAAY,CAAC;AAAA,IACb,SAAS;AAAA,EACX;AAEI,MAAA,CAAC,iBAAyB,QAAA;AAExB,QAAA,QAAQ,iBAAiB,eAAe;AAAA,IAC5C,YAAY,WAAW,cAAc;AAAA,EAAA,CACtC;AAGD,QAAM,CAAC,MAAM,IAAI,IAAI,MAAMC,KAAA,WAAW,MAAM,WAAW,WAAW,cAAmB,KAAA,EAAE,CAAC;AACpF,MAAA,CAAC,KAAa,QAAA;AAGZ,QAAA,CAAC,MAAM,QAAQ,IAAIA,gBAAW,MAAMC,SAAAA,uBAAuB,IAAI,CAAC;AAClE,MAAA,CAAC,SAAiB,QAAA;AAEX,aAAA,KAAK,SAAS,OAAO;AACrB,aAAA,OAAO,SAAS,QAAQ,CAAC;AACzB,aAAA,aAAa,SAAS,cAAc,CAAC;AACrC,aAAA,UAAU,WAAW,KAAK,SAAS,OAAO,KAAK,WAAW,WAAW,WAAW;AAEpF,SAAA;AACT;;;;"}
package/dist/cloud.mjs CHANGED
@@ -9,32 +9,33 @@ function createCloudObjectError(message, code) {
9
9
  errMsg: message
10
10
  });
11
11
  }
12
- async function respondCloudObject(fn, requestId) {
12
+ async function respondCloudObject(fn, append) {
13
13
  try {
14
14
  const data = await fn();
15
15
  return {
16
- requestId,
17
- data,
18
16
  errCode: 0,
19
- errMsg: ""
17
+ errMsg: "",
18
+ data,
19
+ ...append
20
20
  };
21
21
  } catch (err) {
22
22
  console.error("respondCloudObject error");
23
23
  console.error(err);
24
24
  const err2 = errorNormalize(err);
25
25
  return {
26
- requestId,
26
+ errCode: err2.errCode || -1,
27
+ errMsg: err2.errMsg || err2.message || "",
27
28
  // @ts-ignore
28
29
  data: null,
29
- errCode: err2.errCode || -1,
30
- errMsg: err2.errMsg || err2.message || ""
30
+ ...append
31
31
  };
32
32
  }
33
33
  }
34
34
  function buildCloudObjectExposeCreator(options) {
35
35
  const buildOptions = objectDefaults(options || {}, {
36
36
  requiredUserErrCode: "uni-id-check-token-failed",
37
- requiredUserErrMsg: "需要登录后才能进行此操作"
37
+ requiredUserErrMsg: "需要登录后才能进行此操作",
38
+ respondAppend: () => ({})
38
39
  });
39
40
  const createCloudObjectExpose = (arg0, arg1, arg2) => {
40
41
  const optionsSource = isFunction(arg0) ? arg1 : arg2;
@@ -63,7 +64,7 @@ function buildCloudObjectExposeCreator(options) {
63
64
  throw new Error("请求数据不正确");
64
65
  }
65
66
  return await arg1(context, parsed.data);
66
- }, this.getUniCloudRequestId());
67
+ }, buildOptions.respondAppend(this));
67
68
  };
68
69
  };
69
70
  return createCloudObjectExpose;
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.mjs","sources":["../src/cloud/error.ts","../src/cloud/respond.ts","../src/cloud/expose.ts"],"sourcesContent":["import { errorAssign } from '@cloudcome/utils-core/error';\n\nexport function createCloudObjectError(message: string, code?: number | string) {\n return errorAssign(new Error(message), {\n errCode: code,\n errMsg: message,\n });\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { UniCloudObjectOutput } from './object';\n\nexport async function respondCloudObject<O>(\n fn: () => MaybePromise<O>,\n requestId?: string,\n): Promise<UniCloudObjectOutput<O>> {\n try {\n const data = await fn();\n\n return {\n requestId,\n data,\n errCode: 0,\n errMsg: '',\n };\n } catch (err) {\n console.error('respondCloudObject error');\n console.error(err);\n\n const err2 = errorNormalize(err as Error & { errCode?: number | string; errMsg?: string });\n\n return {\n requestId,\n // @ts-ignore\n data: null,\n errCode: err2.errCode || -1,\n errMsg: err2.errMsg || err2.message || '',\n };\n }\n}\n","import { parseCloudObjectOutput } from '@/_helpers';\nimport { objectDefaults } from '@cloudcome/utils-core/object';\nimport { tryFlatten } from '@cloudcome/utils-core/try';\nimport { isFunction } from '@cloudcome/utils-core/type';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type z from 'zod';\nimport type { ZodObject } from 'zod';\nimport { createCloudObjectError } from './error';\nimport type { UniCloudObject, UniCloudObjectThis } from './object';\nimport { respondCloudObject } from './respond';\nimport type { UniIdCloudObject } from './uni-id';\n\nexport type UniCloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\nexport type UniCloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: UniCloudObjectThisAppendUser;\n};\n\nexport type UniCloudObjectContext = UniCloudObjectThis & UniCloudObjectThisAppend;\n\n/**\n * 构建云函数暴露创建器的选项配置\n * 用于配置云函数暴露创建器的行为,目前支持传入UniIdCloudObject实例\n */\nexport type BuildCloudExposeCreatorOptions = {\n /**\n * 可选的UniIdCloudObject实例\n * 用于处理用户身份验证和权限管理相关功能\n */\n uniIdCloudObject?: UniIdCloudObject;\n\n /**\n * 需要用户登录态的错误码\n * @default 'uni-id-check-token-failed'\n */\n requiredUserErrCode?: number | string;\n\n /**\n * 需要用户登录态的错误消息\n * @default '需要登录后才能进行此操作'\n */\n requiredUserErrMsg?: string;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n};\n\nexport type CreateCloudObjectExpose = {\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: UniCloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<z.infer<S>, O>;\n <O>(\n fn: (context: UniCloudObjectContext) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<void, O>;\n};\n\nexport function buildCloudObjectExposeCreator(options?: BuildCloudExposeCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n }) as Required<BuildCloudExposeCreatorOptions>;\n\n // @ts-ignore\n const createCloudObjectExpose: CreateCloudObjectExpose = (arg0, arg1, arg2) => {\n // 选项来源\n const optionsSource = (isFunction(arg0) ? arg1 : arg2) as CreateCloudObjectOptions | undefined;\n // 设置默认选项值\n const createOptions = objectDefaults(optionsSource || {}, {\n requiredUser: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云函数响应逻辑\n return await respondCloudObject(async () => {\n // 构建附加的上下文信息\n const user = await parseAppendUser(this, options?.uniIdCloudObject);\n const append: UniCloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as UniCloudObjectContext;\n\n if (createOptions.requiredUser && !user.id) {\n throw createCloudObjectError(buildOptions.requiredUserErrMsg, buildOptions.requiredUserErrCode);\n }\n\n // 无入参\n if (isFunction(arg0)) {\n return await arg0(context);\n }\n\n // 单入参\n // 验证输入数据\n const parsed = arg0.safeParse(input);\n\n if (!parsed.success) {\n console.log(parsed.error.issues);\n\n const issue0 = parsed.error?.issues?.[0];\n\n // 处理验证错误\n if (issue0?.code === 'custom') throw issue0.message;\n throw new Error('请求数据不正确');\n }\n\n return await arg1(context, parsed.data);\n }, this.getUniCloudRequestId());\n };\n };\n\n return createCloudObjectExpose;\n}\n\nasync function parseAppendUser(\n objectThis: UniCloudObjectThis,\n uniIdCloudObject?: UniIdCloudObject,\n): Promise<UniCloudObjectThisAppendUser> {\n const appendUser: UniCloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCloudObject) return appendUser;\n\n const uniId = uniIdCloudObject.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 忽略错误1\n const [err1, user] = await tryFlatten(uniId.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 忽略错误2\n const [err2, userData] = tryFlatten(() => parseCloudObjectOutput(user));\n if (!userData) return appendUser;\n\n appendUser.id = userData.uid || '';\n appendUser.role = userData.role || [];\n appendUser.permission = userData.permission || [];\n appendUser.isAdmin = appendUser.role.includes('admin') && appendUser.permission.length === 0;\n\n return appendUser;\n}\n"],"names":[],"mappings":";;;;;AAEgB,SAAA,uBAAuB,SAAiB,MAAwB;AAC9E,SAAO,YAAY,IAAI,MAAM,OAAO,GAAG;AAAA,IACrC,SAAS;AAAA,IACT,QAAQ;AAAA,EAAA,CACT;AACH;ACHsB,eAAA,mBACpB,IACA,WACkC;AAC9B,MAAA;AACI,UAAA,OAAO,MAAM,GAAG;AAEf,WAAA;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,WACO,KAAK;AACZ,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,GAAG;AAEX,UAAA,OAAO,eAAe,GAA6D;AAElF,WAAA;AAAA,MACL;AAAA;AAAA,MAEA,MAAM;AAAA,MACN,SAAS,KAAK,WAAW;AAAA,MACzB,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA,IACzC;AAAA,EAAA;AAEJ;ACuCO,SAAS,8BAA8B,SAA0C;AACtF,QAAM,eAAe,eAAe,WAAW,IAAI;AAAA,IACjD,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,EAAA,CACrB;AAGD,QAAM,0BAAmD,CAAC,MAAM,MAAM,SAAS;AAE7E,UAAM,gBAAiB,WAAW,IAAI,IAAI,OAAO;AAEjD,UAAM,gBAAgB,eAAe,iBAAiB,IAAI;AAAA,MACxD,cAAc;AAAA,IAAA,CACf;AAED,WAAO,eAAgB,OAAO;AAErB,aAAA,MAAM,mBAAmB,YAAY;AAE1C,cAAM,OAAO,MAAM,gBAAgB,MAAM,SAAS,gBAAgB;AAClE,cAAM,SAAmC;AAAA,UACvC,SAAS;AAAA,UACT;AAAA,QACF;AACA,cAAM,UAAU,OAAO,OAAO,MAAM,MAAM;AAE1C,YAAI,cAAc,gBAAgB,CAAC,KAAK,IAAI;AAC1C,gBAAM,uBAAuB,aAAa,oBAAoB,aAAa,mBAAmB;AAAA,QAAA;AAI5F,YAAA,WAAW,IAAI,GAAG;AACb,iBAAA,MAAM,KAAK,OAAO;AAAA,QAAA;AAKrB,cAAA,SAAS,KAAK,UAAU,KAAK;AAE/B,YAAA,CAAC,OAAO,SAAS;AACX,kBAAA,IAAI,OAAO,MAAM,MAAM;AAE/B,gBAAM,SAAS,OAAO,OAAO,SAAS,CAAC;AAGvC,cAAI,QAAQ,SAAS,SAAU,OAAM,OAAO;AACtC,gBAAA,IAAI,MAAM,SAAS;AAAA,QAAA;AAG3B,eAAO,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,MAAA,GACrC,KAAK,sBAAsB;AAAA,IAChC;AAAA,EACF;AAEO,SAAA;AACT;AAEA,eAAe,gBACb,YACA,kBACuC;AACvC,QAAM,aAA2C;AAAA,IAC/C,IAAI;AAAA,IACJ,MAAM,CAAC;AAAA,IACP,YAAY,CAAC;AAAA,IACb,SAAS;AAAA,EACX;AAEI,MAAA,CAAC,iBAAyB,QAAA;AAExB,QAAA,QAAQ,iBAAiB,eAAe;AAAA,IAC5C,YAAY,WAAW,cAAc;AAAA,EAAA,CACtC;AAGD,QAAM,CAAC,MAAM,IAAI,IAAI,MAAM,WAAW,MAAM,WAAW,WAAW,cAAmB,KAAA,EAAE,CAAC;AACpF,MAAA,CAAC,KAAa,QAAA;AAGZ,QAAA,CAAC,MAAM,QAAQ,IAAI,WAAW,MAAM,uBAAuB,IAAI,CAAC;AAClE,MAAA,CAAC,SAAiB,QAAA;AAEX,aAAA,KAAK,SAAS,OAAO;AACrB,aAAA,OAAO,SAAS,QAAQ,CAAC;AACzB,aAAA,aAAa,SAAS,cAAc,CAAC;AACrC,aAAA,UAAU,WAAW,KAAK,SAAS,OAAO,KAAK,WAAW,WAAW,WAAW;AAEpF,SAAA;AACT;"}
1
+ {"version":3,"file":"cloud.mjs","sources":["../src/cloud/error.ts","../src/cloud/respond.ts","../src/cloud/expose.ts"],"sourcesContent":["import { errorAssign } from '@cloudcome/utils-core/error';\n\nexport function createCloudObjectError(message: string, code?: number | string) {\n return errorAssign(new Error(message), {\n errCode: code,\n errMsg: message,\n });\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { UniCloudObjectOutput } from './object';\n\n/**\n * 处理云函数响应结果,统一返回格式\n * @param fn - 执行函数,可以返回任意类型的值或Promise\n * @param append - 需要附加到响应结果中的额外字段\n * @returns 统一格式的云函数响应结果\n *\n * @example\n * ```typescript\n * // 成功情况\n * const result = await respondCloudObject(async () => {\n * return { name: 'test', value: 123 };\n * });\n * // 返回: { errCode: 0, errMsg: '', data: { name: 'test', value: 123 } }\n *\n * // 失败情况\n * const result = await respondCloudObject(() => {\n * throw new Error('操作失败');\n * });\n * // 返回: { errCode: -1, errMsg: '操作失败', data: null }\n * ```\n */\nexport async function respondCloudObject<O>(\n fn: () => MaybePromise<O>,\n append?: AnyObject,\n): Promise<UniCloudObjectOutput<O>> {\n try {\n const data = await fn();\n\n return {\n errCode: 0,\n errMsg: '',\n data,\n ...append,\n };\n } catch (err) {\n console.error('respondCloudObject error');\n console.error(err);\n\n const err2 = errorNormalize(err as Error & { errCode?: number | string; errMsg?: string });\n\n return {\n errCode: err2.errCode || -1,\n errMsg: err2.errMsg || err2.message || '',\n // @ts-ignore\n data: null,\n ...append,\n };\n }\n}\n","import { parseCloudObjectOutput } from '@/_helpers';\nimport { objectDefaults } from '@cloudcome/utils-core/object';\nimport { tryFlatten } from '@cloudcome/utils-core/try';\nimport { isFunction } from '@cloudcome/utils-core/type';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type z from 'zod';\nimport type { ZodObject } from 'zod';\nimport { createCloudObjectError } from './error';\nimport type { UniCloudObject, UniCloudObjectThis } from './object';\nimport { respondCloudObject } from './respond';\nimport type { UniIdCloudObject } from './uni-id';\n\nexport type UniCloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\nexport type UniCloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: UniCloudObjectThisAppendUser;\n};\n\nexport type UniCloudObjectContext = UniCloudObjectThis & UniCloudObjectThisAppend;\n\n/**\n * 构建云函数暴露创建器的选项配置\n * 用于配置云函数暴露创建器的行为,目前支持传入UniIdCloudObject实例\n */\nexport type BuildCloudExposeCreatorOptions = {\n /**\n * 可选的UniIdCloudObject实例\n * 用于处理用户身份验证和权限管理相关功能\n */\n uniIdCloudObject?: UniIdCloudObject;\n\n /**\n * 需要用户登录态的错误码\n * @default 'uni-id-check-token-failed'\n */\n requiredUserErrCode?: number | string;\n\n /**\n * 需要用户登录态的错误消息\n * @default '需要登录后才能进行此操作'\n */\n requiredUserErrMsg?: string;\n\n /**\n * 响应附加数据函数\n * 用于在云对象响应中添加额外的上下文信息\n * @param objectThis 云对象上下文\n * @returns 返回要附加到响应中的数据对象\n */\n respondAppend?: (objectThis: UniCloudObjectThis) => AnyObject;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n};\n\nexport type CreateCloudObjectExpose = {\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: UniCloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<z.infer<S>, O>;\n <O>(\n fn: (context: UniCloudObjectContext) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): UniCloudObject<void, O>;\n};\n\n/**\n * 构建云对象暴露创建器\n *\n * 该函数用于创建一个云对象暴露函数,可以处理用户身份验证、输入验证和错误处理等通用逻辑\n *\n * @param options 构建选项配置\n * @param options.uniIdCloudObject 可选的UniIdCloudObject实例,用于处理用户身份验证和权限管理\n * @param options.requiredUserErrCode 需要用户登录态时的错误码,默认为 'uni-id-check-token-failed'\n * @param options.requiredUserErrMsg 需要用户登录态时的错误消息,默认为 '需要登录后才能进行此操作'\n *\n * @returns 返回一个云对象暴露创建函数,支持两种重载形式:\n * 1. 无输入参数的形式:(fn, options) => UniCloudObject\n * 2. 有输入验证的形式:(schema, fn, options) => UniCloudObject\n *\n * @example\n * // 无输入参数的使用方式\n * const expose = buildCloudObjectExposeCreator();\n * export default expose(async (context) => {\n * // 业务逻辑\n * });\n *\n * @example\n * // 有输入验证的使用方式\n * const expose = buildCloudObjectExposeCreator();\n * const schema = z.object({\n * name: z.string().min(1)\n * });\n *\n * export default expose(schema, async (context, input) => {\n * // 业务逻辑,input类型已自动推断\n * });\n */\nexport function buildCloudObjectExposeCreator(options?: BuildCloudExposeCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n respondAppend: () => ({}),\n }) as Required<BuildCloudExposeCreatorOptions>;\n\n // @ts-ignore\n const createCloudObjectExpose: CreateCloudObjectExpose = (arg0, arg1, arg2) => {\n // 确定选项来源:如果arg0是函数,则选项在arg1;否则在arg2\n const optionsSource = (isFunction(arg0) ? arg1 : arg2) as CreateCloudObjectOptions | undefined;\n\n // 设置默认选项值\n const createOptions = objectDefaults(optionsSource || {}, {\n requiredUser: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云函数响应逻辑,包括错误捕获和统一响应格式\n return await respondCloudObject(async () => {\n // 构建附加的上下文信息,包括用户身份和权限信息\n const user = await parseAppendUser(this, options?.uniIdCloudObject);\n const append: UniCloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as UniCloudObjectContext;\n\n // 如果需要用户登录态但用户未登录,则抛出错误\n if (createOptions.requiredUser && !user.id) {\n throw createCloudObjectError(buildOptions.requiredUserErrMsg, buildOptions.requiredUserErrCode);\n }\n\n // 无入参函数调用\n if (isFunction(arg0)) {\n return await arg0(context);\n }\n\n // 有入参函数调用 - 验证输入数据\n const parsed = arg0.safeParse(input);\n\n // 输入验证失败处理\n if (!parsed.success) {\n console.log(parsed.error.issues);\n\n const issue0 = parsed.error?.issues?.[0];\n\n // 处理自定义验证错误\n if (issue0?.code === 'custom') throw issue0.message;\n throw new Error('请求数据不正确');\n }\n\n // 执行业务逻辑函数,传入上下文和验证后的数据\n return await arg1(context, parsed.data);\n }, buildOptions.respondAppend(this));\n };\n };\n\n return createCloudObjectExpose;\n}\n\nasync function parseAppendUser(\n objectThis: UniCloudObjectThis,\n uniIdCloudObject?: UniIdCloudObject,\n): Promise<UniCloudObjectThisAppendUser> {\n const appendUser: UniCloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCloudObject) return appendUser;\n\n const uniId = uniIdCloudObject.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 忽略错误1\n const [err1, user] = await tryFlatten(uniId.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 忽略错误2\n const [err2, userData] = tryFlatten(() => parseCloudObjectOutput(user));\n if (!userData) return appendUser;\n\n appendUser.id = userData.uid || '';\n appendUser.role = userData.role || [];\n appendUser.permission = userData.permission || [];\n appendUser.isAdmin = appendUser.role.includes('admin') && appendUser.permission.length === 0;\n\n return appendUser;\n}\n"],"names":[],"mappings":";;;;;AAEgB,SAAA,uBAAuB,SAAiB,MAAwB;AAC9E,SAAO,YAAY,IAAI,MAAM,OAAO,GAAG;AAAA,IACrC,SAAS;AAAA,IACT,QAAQ;AAAA,EAAA,CACT;AACH;ACkBsB,eAAA,mBACpB,IACA,QACkC;AAC9B,MAAA;AACI,UAAA,OAAO,MAAM,GAAG;AAEf,WAAA;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR;AAAA,MACA,GAAG;AAAA,IACL;AAAA,WACO,KAAK;AACZ,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,GAAG;AAEX,UAAA,OAAO,eAAe,GAA6D;AAElF,WAAA;AAAA,MACL,SAAS,KAAK,WAAW;AAAA,MACzB,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA;AAAA,MAEvC,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AAAA,EAAA;AAEJ;AC0DO,SAAS,8BAA8B,SAA0C;AACtF,QAAM,eAAe,eAAe,WAAW,IAAI;AAAA,IACjD,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,eAAe,OAAO,CAAC;AAAA,EAAA,CACxB;AAGD,QAAM,0BAAmD,CAAC,MAAM,MAAM,SAAS;AAE7E,UAAM,gBAAiB,WAAW,IAAI,IAAI,OAAO;AAGjD,UAAM,gBAAgB,eAAe,iBAAiB,IAAI;AAAA,MACxD,cAAc;AAAA,IAAA,CACf;AAED,WAAO,eAAgB,OAAO;AAErB,aAAA,MAAM,mBAAmB,YAAY;AAE1C,cAAM,OAAO,MAAM,gBAAgB,MAAM,SAAS,gBAAgB;AAClE,cAAM,SAAmC;AAAA,UACvC,SAAS;AAAA,UACT;AAAA,QACF;AACA,cAAM,UAAU,OAAO,OAAO,MAAM,MAAM;AAG1C,YAAI,cAAc,gBAAgB,CAAC,KAAK,IAAI;AAC1C,gBAAM,uBAAuB,aAAa,oBAAoB,aAAa,mBAAmB;AAAA,QAAA;AAI5F,YAAA,WAAW,IAAI,GAAG;AACb,iBAAA,MAAM,KAAK,OAAO;AAAA,QAAA;AAIrB,cAAA,SAAS,KAAK,UAAU,KAAK;AAG/B,YAAA,CAAC,OAAO,SAAS;AACX,kBAAA,IAAI,OAAO,MAAM,MAAM;AAE/B,gBAAM,SAAS,OAAO,OAAO,SAAS,CAAC;AAGvC,cAAI,QAAQ,SAAS,SAAU,OAAM,OAAO;AACtC,gBAAA,IAAI,MAAM,SAAS;AAAA,QAAA;AAI3B,eAAO,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,MAAA,GACrC,aAAa,cAAc,IAAI,CAAC;AAAA,IACrC;AAAA,EACF;AAEO,SAAA;AACT;AAEA,eAAe,gBACb,YACA,kBACuC;AACvC,QAAM,aAA2C;AAAA,IAC/C,IAAI;AAAA,IACJ,MAAM,CAAC;AAAA,IACP,YAAY,CAAC;AAAA,IACb,SAAS;AAAA,EACX;AAEI,MAAA,CAAC,iBAAyB,QAAA;AAExB,QAAA,QAAQ,iBAAiB,eAAe;AAAA,IAC5C,YAAY,WAAW,cAAc;AAAA,EAAA,CACtC;AAGD,QAAM,CAAC,MAAM,IAAI,IAAI,MAAM,WAAW,MAAM,WAAW,WAAW,cAAmB,KAAA,EAAE,CAAC;AACpF,MAAA,CAAC,KAAa,QAAA;AAGZ,QAAA,CAAC,MAAM,QAAQ,IAAI,WAAW,MAAM,uBAAuB,IAAI,CAAC;AAClE,MAAA,CAAC,SAAiB,QAAA;AAEX,aAAA,KAAK,SAAS,OAAO;AACrB,aAAA,OAAO,SAAS,QAAQ,CAAC;AACzB,aAAA,aAAa,SAAS,cAAc,CAAC;AACrC,aAAA,UAAU,WAAW,KAAK,SAAS,OAAO,KAAK,WAAW,WAAW,WAAW;AAEpF,SAAA;AACT;"}
@@ -1,5 +1,5 @@
1
- import { AnyObject, HasProperty, IsEmptyObject, IsOnlyProperty } from '@cloudcome/utils-core/types';
2
- import { UniClientDatabaseOutput, UniCloudDatabaseOutput } from './types';
1
+ import { AnyObject, HasProperty, IsEmptyObject, IsOnlyProperty, MergeIntersection } from '@cloudcome/utils-core/types';
2
+ import { UniClientDatabaseOutput, UniCloudDatabaseOutput, UniDatabaseCommand } from './types';
3
3
  export type DbWhere<T> = {
4
4
  [K in keyof T]?: unknown;
5
5
  };
@@ -16,18 +16,23 @@ S & {
16
16
  type _DbQuery<T, S extends Record<keyof T, boolean>> = {
17
17
  [K in keyof T as S[K] extends true ? K : never]: T[K];
18
18
  };
19
- export type DbQuery<T, S extends DbSelect<T>> = _DbQuery<T, _DbFields<T, S>>;
19
+ export type DbQuery<T, S extends DbSelect<T>, R> = _DbQuery<T, _DbFields<T, S>> & R;
20
+ export type DbForeign<T, S extends DbSelect<T>, R, J extends DbJoinType, A> = Record<A & string, J extends '1:1' ? DbQuery<T, S, R> : DbQuery<T, S, R>[]>;
20
21
  export type DbCreate<T> = Partial<T>;
21
22
  export type DbUpdate<T> = Partial<T>;
22
23
  export type DbOrder<T> = Record<keyof T, 'asc' | 'desc'>;
23
24
  /**
24
25
  * 数据库操作符命令
25
26
  */
26
- export declare const dbCmd: UniCloud.QueryCommand;
27
+ export declare const dbCmd: UniDatabaseCommand;
27
28
  /**
28
29
  * 数据库聚合操作符命令
29
30
  */
30
- export declare const dbAgg: UniCloud.AggregateCommand;
31
+ export declare const dbAgg: UniCloud.AggregateCommand & {
32
+ pipeline: () => UniCloud.AggregateReference & {
33
+ done: () => unknown;
34
+ };
35
+ };
31
36
  export type DbOptions = {
32
37
  /**
33
38
  * 数据表名称
@@ -42,7 +47,58 @@ export type DbOptions = {
42
47
  */
43
48
  _mockDatabase?: any;
44
49
  };
45
- export declare class Db<T, S extends DbSelect<T> = Record<string, never>> {
50
+ /**
51
+ * 数据库关联类型
52
+ * - '1:1': 一对一关联,返回值 1 个
53
+ * - '1:n': 一对多关联,返回值 n 个
54
+ * - 'n:1': 多对一关联,返回值 n 个
55
+ */
56
+ export type DbJoinType = '1:1' | '1:n' | 'n:1';
57
+ export type DbLookupOptions<J extends DbJoinType, L, F, A> = {
58
+ /**
59
+ * 关联类型
60
+ */
61
+ type: J;
62
+ /**
63
+ * 主表字段
64
+ */
65
+ localField: keyof L & string;
66
+ /**
67
+ * 关联表字段
68
+ */
69
+ foreignField: keyof F & string;
70
+ /**
71
+ * 关联数据在结果中的字段名
72
+ */
73
+ as: A;
74
+ };
75
+ export type DbLookup = {
76
+ /**
77
+ * 关联表
78
+ */
79
+ table: Db<unknown>;
80
+ /**
81
+ * 关联类型
82
+ */
83
+ type: DbJoinType;
84
+ /**
85
+ * 主表字段
86
+ */
87
+ localField: string;
88
+ /**
89
+ * 关联表字段
90
+ */
91
+ foreignField: string;
92
+ /**
93
+ * 关联表名称
94
+ */
95
+ from: string;
96
+ /**
97
+ * 关联数据在结果中的字段名
98
+ */
99
+ as: string;
100
+ };
101
+ export declare class Db<T, S extends DbSelect<T> = {}, R extends AnyObject = {}> {
46
102
  #private;
47
103
  /**
48
104
  * 构造函数,初始化数据库集合引用
@@ -50,8 +106,9 @@ export declare class Db<T, S extends DbSelect<T> = Record<string, never>> {
50
106
  * @param _mockDatabase 模拟数据库,用于单元测试
51
107
  */
52
108
  constructor(options: DbOptions);
109
+ get table(): string;
53
110
  /**
54
- * 创建聚合操作实例
111
+ * 获取聚合操作实例
55
112
  * @returns 聚合操作实例
56
113
  */
57
114
  aggregate(): UniCloud.AggregateReference;
@@ -72,7 +129,7 @@ export declare class Db<T, S extends DbSelect<T> = Record<string, never>> {
72
129
  * @param fields 要返回的字段对象,true表示返回,false表示不返回
73
130
  * @returns 当前Db实例,支持链式调用
74
131
  */
75
- select<U extends DbSelect<T>>(fields: U): Db<T, U>;
132
+ select<U extends DbSelect<T>>(fields: U): Db<T, S & U, R>;
76
133
  /**
77
134
  * 设置排序规则
78
135
  * @param order 排序规则对象,key为字段名,value为"asc"或"desc"
@@ -91,30 +148,32 @@ export declare class Db<T, S extends DbSelect<T> = Record<string, never>> {
91
148
  * @returns 当前Db实例,支持链式调用
92
149
  */
93
150
  limit(limit: number): this;
94
- /**
95
- * 创建新记录
96
- * @param data 要创建的数据
97
- * @returns 创建结果
98
- */
99
- create(data: DbCreate<T>): Promise<string>;
151
+ get hasLookup(): boolean;
152
+ lookup<FT, FS extends DbSelect<FT>, FR extends AnyObject, J extends DbJoinType, A extends string>(table: Db<FT, FS, FR>, lookup: DbLookupOptions<J, T, FT, A>): Db<T, S, MergeIntersection<R & DbForeign<FT, FS, FR, J, A>>>;
100
153
  /**
101
154
  * 执行查询操作
102
155
  * @returns 查询结果
103
156
  */
104
- query(): Promise<_DbQuery<T, _DbFields<T, S>>[]>;
157
+ query(): Promise<DbQuery<T, S, R>[]>;
105
158
  /**
106
159
  * 只查询一条,自动添加 limit(1) 条件
107
160
  * @param ignoreMiss 是否忽略没有匹配到记录
108
161
  * @returns 查询结果
109
162
  */
110
- queryOne(): Promise<DbQuery<T, S>>;
111
- queryOne(ignoreMiss: false): Promise<DbQuery<T, S>>;
112
- queryOne(ignoreMiss: true): Promise<DbQuery<T, S> | undefined>;
163
+ queryOne(): Promise<DbQuery<T, S, R>>;
164
+ queryOne(ignoreMiss: false): Promise<DbQuery<T, S, R>>;
165
+ queryOne(ignoreMiss: true): Promise<DbQuery<T, S, R> | undefined>;
113
166
  /**
114
167
  * 获取匹配记录的数量
115
168
  * @returns 记录总数
116
169
  */
117
170
  count(): Promise<number>;
171
+ /**
172
+ * 创建新记录
173
+ * @param data 要创建的数据
174
+ * @returns 创建结果
175
+ */
176
+ create(data: DbCreate<T>): Promise<string>;
118
177
  /**
119
178
  * 更新记录
120
179
  * @param data 要更新的数据
@@ -127,6 +186,9 @@ export declare class Db<T, S extends DbSelect<T> = Record<string, never>> {
127
186
  */
128
187
  remove(): Promise<number>;
129
188
  }
189
+ export type DbProxy<T, S extends DbSelect<T> = {}, R extends AnyObject = {}> = Db<T, S, R> & {
190
+ _isProxy: true;
191
+ };
130
192
  /**
131
193
  * 数据库操作对象
132
194
  */
@@ -136,7 +198,7 @@ export declare const db: {
136
198
  * @param name 数据表名称
137
199
  * @returns Db类实例,用于执行数据库操作
138
200
  */
139
- table<T>(name: string): Db<T>;
201
+ table<T, S extends DbSelect<T> = {}, R extends AnyObject = {}>(name: string): DbProxy<T>;
140
202
  };
141
203
  /**
142
204
  * 解析数据库执行结果
@@ -1,18 +1,8 @@
1
- import { Db, DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './db';
2
- /**
3
- * 数据库 upsert 操作的配置选项
4
- *
5
- * @template W - 查询条件类型
6
- * @template S - 查询返回字段类型
7
- * @template C - 创建数据类型
8
- * @template U - 更新数据类型
9
- * @template R - 查询结果类型
10
- */
11
- export type DbUpsertOptions<T, W extends DbWhere<T>, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {
12
- /** 集合名称 */
13
- collection: string;
1
+ import { AnyObject } from '@cloudcome/utils-core/types';
2
+ import { Db, DbCreate, DbProxy, DbQuery, DbSelect, DbUpdate, DbWhere } from './db';
3
+ export type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {
14
4
  /** 查询条件 */
15
- where: W;
5
+ where: DbWhere<T>;
16
6
  /** 查询返回字段 */
17
7
  select?: S;
18
8
  /** 创建数据 */
@@ -21,7 +11,7 @@ export type DbUpsertOptions<T, W extends DbWhere<T>, S extends DbSelect<T>, C ex
21
11
  * 更新数据,可以是对象或根据查询结果生成更新对象的函数
22
12
  * @param row 查询到的文档数据,仅在传入函数时可用
23
13
  */
24
- update: U | ((row: DbQuery<T, S>) => U);
14
+ update: U | ((exist: DbQuery<T, S, {}>) => U);
25
15
  /** 创建前回调函数 */
26
16
  onBeforeCreate?: () => unknown;
27
17
  /**
@@ -31,38 +21,49 @@ export type DbUpsertOptions<T, W extends DbWhere<T>, S extends DbSelect<T>, C ex
31
21
  onAfterCreate?: (id: string) => unknown;
32
22
  /**
33
23
  * 更新前回调函数
34
- * @param row 查询到的文档
24
+ * @param exist 查询到的原始文档数据
25
+ * @returns 如果返回 false,则取消更新操作
26
+ */
27
+ onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;
28
+ /**
29
+ * 更新后回调函数
30
+ * @param updateData 实际更新的数据
31
+ * @param exist 查询到的原始文档数据
35
32
  */
36
- onBeforeUpdate?: (row: DbQuery<T, S>) => unknown;
37
- /** 更新后回调函数 */
38
- onAfterUpdate?: () => unknown;
33
+ onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;
39
34
  /** 用于测试的模拟数据库实例 */
40
- _mockDb?: (collection: string) => any;
41
- };
42
- export declare function dbUpsert<T, W extends DbWhere<T>, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(options: DbUpsertOptions<T, W, S, C, U>): Promise<string | number>;
43
- type _TransactionDb = {
44
- startTransaction: () => Promise<_Transaction>;
35
+ _mockDbInstance?: any;
45
36
  };
46
- type _Transaction = {
47
- commit: () => Promise<unknown>;
48
- rollback: () => Promise<unknown>;
37
+ /**
38
+ * 数据库 upsert 操作的返回结果类型
39
+ */
40
+ export type DbUpsertOutput = {
41
+ /** 操作的文档ID */
42
+ id: string;
43
+ /** 是否为创建操作 */
44
+ created: boolean;
45
+ /** 是否为更新操作 */
46
+ updated: boolean;
49
47
  };
48
+ export declare function dbUpsert<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(dbProxy: DbProxy<T>, options: DbUpsertOptions<T, S, C, U>): Promise<DbUpsertOutput>;
49
+ type _WithTransaction = <T, S extends DbSelect<T>, R extends AnyObject>(table: DbProxy<T, S, R>) => Db<T, S, R>;
50
50
  /**
51
51
  * 在数据库事务中执行操作
52
52
  *
53
53
  * @template T - 事务操作返回值类型
54
- * @param transact - 事务执行函数,接收事务数据库实例作为参数
55
- * @param _mockDatabase - 用于测试的模拟数据库实例
54
+ * @param transacting - 事务执行函数,接收事务数据库实例作为参数
55
+ * @param _mockDatabase - 用于测试的模拟数据库对象
56
+ * @param _mockDbInstance - 用于测试的模拟数据库实例
56
57
  * @returns 事务操作的返回结果
57
58
  *
58
59
  * @example
59
60
  * ```typescript
60
- * const result = await dbTransaction(async (ta) => {
61
- * const user = await ta.collection('users').create({ name: 'John' });
62
- * const order = await ta.collection('orders').create({ userId: user.id, amount: 100 });
61
+ * const result = await dbTransaction(async (withTransaction) => {
62
+ * const userId = await withTransaction(db.table('user')).create({ name: 'John' });
63
+ * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });
63
64
  * return { user, order };
64
65
  * });
65
66
  * ```
66
67
  */
67
- export declare function dbTransaction<T, S extends DbSelect<T> = {}>(transact: (ta: Db<T, S>) => Promise<unknown>, _mockDatabase?: _TransactionDb): Promise<unknown>;
68
+ export declare function dbTransaction<K>(transacting: (withTransaction: _WithTransaction) => Promise<K>, _mockDatabase?: any, _mockDbInstance?: any): Promise<K>;
68
69
  export {};
@@ -0,0 +1 @@
1
+ export {};