@cloudcome/utils-uni 1.18.1 → 1.19.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.
- package/dist/cloud.cjs.map +1 -1
- package/dist/cloud.mjs.map +1 -1
- package/dist/database/_db.class.d.ts +6 -43
- package/dist/database/proxy.d.ts +2 -1
- package/dist/database/types.d.ts +106 -0
- package/dist/database/unique.d.ts +1 -1
- package/dist/database/upsert.d.ts +1 -1
- package/dist/database.cjs +3 -1
- package/dist/database.cjs.map +1 -1
- package/dist/database.mjs +3 -1
- package/dist/database.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/cloud.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud.cjs","sources":["../src/cloud/module.ts","../src/cloud/respond.ts","../src/cloud/method.ts"],"sourcesContent":["import { objectOmit } from '@cloudcome/utils-core/object';\nimport { createCloudObjectError } from './error';\nimport type { CloudModuleOutput } from './types';\n\n/**\n * 解析云模块输出结果\n *\n * 该函数用于处理云模块的输出,如果输出中包含错误码,则抛出相应的错误;\n * 否则返回去除错误码和错误信息后的数据部分。\n *\n * @template O - 输出数据的类型\n * @param output - 云模块的输出结果,包含errCode、errMsg和数据部分\n * @param fallbackErrorMessage - 当输出中没有错误信息时使用的默认错误消息\n * @returns 返回去除errCode和errMsg字段后的数据对象\n * @throws {CloudObjectError} 当output中存在errCode时抛出包含错误码和错误信息的异常\n *\n * @example\n * // 成功情况\n * const result = parseCloudModuleOutput({ value: 'success', errCode: 0, errMsg: '' });\n * // 返回: { value: 'success' }\n *\n * @example\n * // 错误情况\n * try {\n * parseCloudModuleOutput({ errCode: 404, errMsg: 'Not Found' });\n * } catch (error) {\n * // 抛出错误: CloudObjectError('Not Found', 404)\n * }\n */\nexport function parseCloudModuleOutput<O>(\n output: CloudModuleOutput<O>,\n fallbackErrorMessage = '',\n): Omit<O, 'errCode' | 'errMsg'> {\n if (output.errCode) {\n throw createCloudObjectError(output.errMsg || fallbackErrorMessage, output.errCode);\n }\n return objectOmit(output, ['errCode', 'errMsg']);\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { CloudMethodOutput } from './types';\n\n/**\n * 执行云对象方法并标准化响应格式\n *\n * @template O - 函数返回值的类型\n * @param fn - 要执行的异步函数\n * @param append - 要附加到响应中的额外数据\n * @returns 标准化的云对象响应对象\n *\n * @example\n * ```typescript\n * const result = await respondCloudMethod(async () => {\n * return await getData();\n * }, { extra: 'data' });\n * ```\n */\nexport async function respondCloudMethod<O>(\n fn: () => MaybePromise<O>,\n append?: AnyObject,\n): Promise<CloudMethodOutput<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 { parseCloudMethodOutput } from '@/_helpers';\nimport { objectDefaults, objectOmit } 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 { parseCloudModuleOutput } from './module';\nimport { respondCloudMethod } from './respond';\nimport type { CloudMethod, CloudModuleOutput, CloudObjectThis } from './types';\nimport type { UniIdCommonModule } from './uni-id';\n\ntype _CloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\ntype _CloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: _CloudObjectThisAppendUser;\n};\n\nexport type CloudObjectContext = CloudObjectThis & _CloudObjectThisAppend;\n\nexport type BuildCloudMethodCreatorOptions = {\n /**\n * UniId 通用模块\n * 用于处理用户身份验证和权限管理\n * 如果提供,将在云对象执行前验证用户身份\n */\n uniIdCommonModule?: UniIdCommonModule;\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 * @default '运行环境不匹配'\n */\n onlyLocalEnvErrMsg?: string;\n\n /**\n * 响应附加数据函数\n * 用于在云对象响应中添加额外的上下文信息\n * @param objectThis 云对象上下文\n * @returns 返回要附加到响应中的数据对象\n */\n respondAppend?: (objectThis: CloudObjectThis) => AnyObject;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n\n /**\n * 是否仅在本地环境运行\n * @default false\n */\n onlyLocalEnv?: boolean;\n};\n\n/**\n * 云对象方法创建器类型定义\n *\n * 用于定义云对象方法的创建函数类型,支持两种重载形式:\n * 1. 带输入验证的版本:接收schema、处理函数和选项\n * 2. 无输入参数的版本:仅接收处理函数和选项\n */\nexport type CreateCloudMethod = {\n /**\n * 带输入验证的云对象方法创建器\n * @template S - Zod验证模式类型\n * @template O - 返回值类型\n * @param schema - Zod验证模式,用于验证输入数据\n * @param fn - 业务逻辑处理函数,接收上下文和验证后的输入数据\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: CloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): CloudMethod<z.infer<S>, O>;\n\n /**\n * 无输入参数的云对象方法创建器\n * @template O - 返回值类型\n * @param fn - 业务逻辑处理函数,仅接收上下文\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <O>(fn: (context: CloudObjectContext) => MaybePromise<O>, options?: CreateCloudObjectOptions): CloudMethod<void, O>;\n};\n\n/**\n * 构建云对象方法创建器\n *\n * 该函数用于创建云对象方法的工厂函数,支持输入验证、用户身份验证、环境检查等功能。\n * 返回的创建器函数可以根据不同的配置创建云对象方法。\n *\n * @param options 构建选项,用于配置云对象方法创建器的行为\n * @returns 返回一个云对象方法创建器函数\n *\n * @example\n * // 创建一个需要用户登录的云对象方法\n * const createMethod = buildCloudMethodCreator({ uniIdCommonModule });\n * const myMethod = createMethod(async (context) => {\n * return { message: 'Hello ' + context.user.id };\n * }, { requiredUser: true });\n */\nexport function buildCloudMethodCreator(options?: BuildCloudMethodCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n onlyLocalEnvErrMsg: '运行环境不匹配',\n respondAppend: () => ({}),\n }) as Required<BuildCloudMethodCreatorOptions>;\n\n // @ts-ignore\n const createCloudMethod: CreateCloudMethod = (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 onlyLocalEnv: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云对象方法响应逻辑,包括错误捕获和统一响应格式\n return await respondCloudMethod(async () => {\n const runtimeEnv = this.getCloudInfo().runtimeEnv;\n\n if (createOptions.onlyLocalEnv && runtimeEnv !== 'local') {\n throw createCloudObjectError(buildOptions.onlyLocalEnvErrMsg);\n }\n\n // 构建附加的上下文信息,包括用户身份和权限信息\n const user = await _parseAppendUser(this, options?.uniIdCommonModule);\n const append: _CloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as CloudObjectContext;\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 createCloudMethod;\n}\n\n/**\n * 解析并附加用户信息到云对象上下文\n *\n * 该函数用于验证用户身份并获取用户权限信息,将结果附加到云对象上下文中的user字段\n * 如果未提供uniIdCommonModule或验证失败,则返回默认的空用户信息\n *\n * @param objectThis 云对象上下文,包含客户端信息和token等\n * @param uniIdCommonModule 可选的UniId通用模块实例,用于验证用户token\n * @returns 返回包含用户ID、角色、权限等信息的对象\n *\n * @example\n * // 成功验证用户身份\n * const user = await _parseAppendUser(this, uniIdModule);\n * // 返回: { id: 'user123', role: ['user'], permission: ['read'], isAdmin: false }\n *\n * @example\n * // 验证失败或未提供模块\n * const user = await _parseAppendUser(this);\n * // 返回: { id: '', role: [], permission: [], isAdmin: false }\n */\nasync function _parseAppendUser(\n objectThis: CloudObjectThis,\n uniIdCommonModule?: UniIdCommonModule,\n): Promise<_CloudObjectThisAppendUser> {\n const appendUser: _CloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCommonModule) return appendUser;\n\n const uic = uniIdCommonModule.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 验证用户token,忽略验证过程中的错误\n const [err1, user] = await tryFlatten(uic.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 解析验证结果,忽略解析过程中的错误\n const [err2, userData] = tryFlatten(() => parseCloudModuleOutput(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":["createCloudObjectError","objectOmit","errorNormalize","objectDefaults","isFunction","tryFlatten"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cloud.cjs","sources":["../src/cloud/module.ts","../src/cloud/respond.ts","../src/cloud/method.ts"],"sourcesContent":["import { objectOmit } from '@cloudcome/utils-core/object';\nimport { createCloudObjectError } from './error';\nimport type { CloudModuleOutput } from './types';\n\n/**\n * 解析云模块输出结果\n *\n * 该函数用于处理云模块的输出,如果输出中包含错误码,则抛出相应的错误;\n * 否则返回去除错误码和错误信息后的数据部分。\n *\n * @template O - 输出数据的类型\n * @param output - 云模块的输出结果,包含errCode、errMsg和数据部分\n * @param fallbackErrorMessage - 当输出中没有错误信息时使用的默认错误消息\n * @returns 返回去除errCode和errMsg字段后的数据对象\n * @throws {CloudObjectError} 当output中存在errCode时抛出包含错误码和错误信息的异常\n *\n * @example\n * // 成功情况\n * const result = parseCloudModuleOutput({ value: 'success', errCode: 0, errMsg: '' });\n * // 返回: { value: 'success' }\n *\n * @example\n * // 错误情况\n * try {\n * parseCloudModuleOutput({ errCode: 404, errMsg: 'Not Found' });\n * } catch (error) {\n * // 抛出错误: CloudObjectError('Not Found', 404)\n * }\n */\nexport function parseCloudModuleOutput<O>(\n output: CloudModuleOutput<O>,\n fallbackErrorMessage = '',\n): Omit<O, 'errCode' | 'errMsg'> {\n if (output.errCode) {\n throw createCloudObjectError(output.errMsg || fallbackErrorMessage, output.errCode);\n }\n return objectOmit(output, ['errCode', 'errMsg']);\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { CloudMethodOutput } from './types';\n\n/**\n * 执行云对象方法并标准化响应格式\n *\n * @template O - 函数返回值的类型\n * @param fn - 要执行的异步函数\n * @param append - 要附加到响应中的额外数据\n * @returns 标准化的云对象响应对象\n *\n * @example\n * ```typescript\n * const result = await respondCloudMethod(async () => {\n * return await getData();\n * }, { extra: 'data' });\n * ```\n */\nexport async function respondCloudMethod<O>(\n fn: () => MaybePromise<O>,\n append?: AnyObject,\n): Promise<CloudMethodOutput<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 { objectDefaults, objectOmit } 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 { parseCloudModuleOutput } from './module';\nimport { respondCloudMethod } from './respond';\nimport type { CloudMethod, CloudModuleOutput, CloudObjectThis } from './types';\nimport type { UniIdCommonModule } from './uni-id';\n\ntype _CloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\ntype _CloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: _CloudObjectThisAppendUser;\n};\n\nexport type CloudObjectContext = CloudObjectThis & _CloudObjectThisAppend;\n\nexport type BuildCloudMethodCreatorOptions = {\n /**\n * UniId 通用模块\n * 用于处理用户身份验证和权限管理\n * 如果提供,将在云对象执行前验证用户身份\n */\n uniIdCommonModule?: UniIdCommonModule;\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 * @default '运行环境不匹配'\n */\n onlyLocalEnvErrMsg?: string;\n\n /**\n * 响应附加数据函数\n * 用于在云对象响应中添加额外的上下文信息\n * @param objectThis 云对象上下文\n * @returns 返回要附加到响应中的数据对象\n */\n respondAppend?: (objectThis: CloudObjectThis) => AnyObject;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n\n /**\n * 是否仅在本地环境运行\n * @default false\n */\n onlyLocalEnv?: boolean;\n};\n\n/**\n * 云对象方法创建器类型定义\n *\n * 用于定义云对象方法的创建函数类型,支持两种重载形式:\n * 1. 带输入验证的版本:接收schema、处理函数和选项\n * 2. 无输入参数的版本:仅接收处理函数和选项\n */\nexport type CreateCloudMethod = {\n /**\n * 带输入验证的云对象方法创建器\n * @template S - Zod验证模式类型\n * @template O - 返回值类型\n * @param schema - Zod验证模式,用于验证输入数据\n * @param fn - 业务逻辑处理函数,接收上下文和验证后的输入数据\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: CloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): CloudMethod<z.infer<S>, O>;\n\n /**\n * 无输入参数的云对象方法创建器\n * @template O - 返回值类型\n * @param fn - 业务逻辑处理函数,仅接收上下文\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <O>(fn: (context: CloudObjectContext) => MaybePromise<O>, options?: CreateCloudObjectOptions): CloudMethod<void, O>;\n};\n\n/**\n * 构建云对象方法创建器\n *\n * 该函数用于创建云对象方法的工厂函数,支持输入验证、用户身份验证、环境检查等功能。\n * 返回的创建器函数可以根据不同的配置创建云对象方法。\n *\n * @param options 构建选项,用于配置云对象方法创建器的行为\n * @returns 返回一个云对象方法创建器函数\n *\n * @example\n * // 创建一个需要用户登录的云对象方法\n * const createMethod = buildCloudMethodCreator({ uniIdCommonModule });\n * const myMethod = createMethod(async (context) => {\n * return { message: 'Hello ' + context.user.id };\n * }, { requiredUser: true });\n */\nexport function buildCloudMethodCreator(options?: BuildCloudMethodCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n onlyLocalEnvErrMsg: '运行环境不匹配',\n respondAppend: () => ({}),\n }) as Required<BuildCloudMethodCreatorOptions>;\n\n // @ts-ignore\n const createCloudMethod: CreateCloudMethod = (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 onlyLocalEnv: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云对象方法响应逻辑,包括错误捕获和统一响应格式\n return await respondCloudMethod(async () => {\n const runtimeEnv = this.getCloudInfo().runtimeEnv;\n\n if (createOptions.onlyLocalEnv && runtimeEnv !== 'local') {\n throw createCloudObjectError(buildOptions.onlyLocalEnvErrMsg);\n }\n\n // 构建附加的上下文信息,包括用户身份和权限信息\n const user = await _parseAppendUser(this, options?.uniIdCommonModule);\n const append: _CloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as CloudObjectContext;\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 createCloudMethod;\n}\n\n/**\n * 解析并附加用户信息到云对象上下文\n *\n * 该函数用于验证用户身份并获取用户权限信息,将结果附加到云对象上下文中的user字段\n * 如果未提供uniIdCommonModule或验证失败,则返回默认的空用户信息\n *\n * @param objectThis 云对象上下文,包含客户端信息和token等\n * @param uniIdCommonModule 可选的UniId通用模块实例,用于验证用户token\n * @returns 返回包含用户ID、角色、权限等信息的对象\n *\n * @example\n * // 成功验证用户身份\n * const user = await _parseAppendUser(this, uniIdModule);\n * // 返回: { id: 'user123', role: ['user'], permission: ['read'], isAdmin: false }\n *\n * @example\n * // 验证失败或未提供模块\n * const user = await _parseAppendUser(this);\n * // 返回: { id: '', role: [], permission: [], isAdmin: false }\n */\nasync function _parseAppendUser(\n objectThis: CloudObjectThis,\n uniIdCommonModule?: UniIdCommonModule,\n): Promise<_CloudObjectThisAppendUser> {\n const appendUser: _CloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCommonModule) return appendUser;\n\n const uic = uniIdCommonModule.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 验证用户token,忽略验证过程中的错误\n const [err1, user] = await tryFlatten(uic.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 解析验证结果,忽略解析过程中的错误\n const [err2, userData] = tryFlatten(() => parseCloudModuleOutput(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":["createCloudObjectError","objectOmit","errorNormalize","objectDefaults","isFunction","tryFlatten"],"mappings":"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"}
|
package/dist/cloud.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud.mjs","sources":["../src/cloud/module.ts","../src/cloud/respond.ts","../src/cloud/method.ts"],"sourcesContent":["import { objectOmit } from '@cloudcome/utils-core/object';\nimport { createCloudObjectError } from './error';\nimport type { CloudModuleOutput } from './types';\n\n/**\n * 解析云模块输出结果\n *\n * 该函数用于处理云模块的输出,如果输出中包含错误码,则抛出相应的错误;\n * 否则返回去除错误码和错误信息后的数据部分。\n *\n * @template O - 输出数据的类型\n * @param output - 云模块的输出结果,包含errCode、errMsg和数据部分\n * @param fallbackErrorMessage - 当输出中没有错误信息时使用的默认错误消息\n * @returns 返回去除errCode和errMsg字段后的数据对象\n * @throws {CloudObjectError} 当output中存在errCode时抛出包含错误码和错误信息的异常\n *\n * @example\n * // 成功情况\n * const result = parseCloudModuleOutput({ value: 'success', errCode: 0, errMsg: '' });\n * // 返回: { value: 'success' }\n *\n * @example\n * // 错误情况\n * try {\n * parseCloudModuleOutput({ errCode: 404, errMsg: 'Not Found' });\n * } catch (error) {\n * // 抛出错误: CloudObjectError('Not Found', 404)\n * }\n */\nexport function parseCloudModuleOutput<O>(\n output: CloudModuleOutput<O>,\n fallbackErrorMessage = '',\n): Omit<O, 'errCode' | 'errMsg'> {\n if (output.errCode) {\n throw createCloudObjectError(output.errMsg || fallbackErrorMessage, output.errCode);\n }\n return objectOmit(output, ['errCode', 'errMsg']);\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { CloudMethodOutput } from './types';\n\n/**\n * 执行云对象方法并标准化响应格式\n *\n * @template O - 函数返回值的类型\n * @param fn - 要执行的异步函数\n * @param append - 要附加到响应中的额外数据\n * @returns 标准化的云对象响应对象\n *\n * @example\n * ```typescript\n * const result = await respondCloudMethod(async () => {\n * return await getData();\n * }, { extra: 'data' });\n * ```\n */\nexport async function respondCloudMethod<O>(\n fn: () => MaybePromise<O>,\n append?: AnyObject,\n): Promise<CloudMethodOutput<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 { parseCloudMethodOutput } from '@/_helpers';\nimport { objectDefaults, objectOmit } 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 { parseCloudModuleOutput } from './module';\nimport { respondCloudMethod } from './respond';\nimport type { CloudMethod, CloudModuleOutput, CloudObjectThis } from './types';\nimport type { UniIdCommonModule } from './uni-id';\n\ntype _CloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\ntype _CloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: _CloudObjectThisAppendUser;\n};\n\nexport type CloudObjectContext = CloudObjectThis & _CloudObjectThisAppend;\n\nexport type BuildCloudMethodCreatorOptions = {\n /**\n * UniId 通用模块\n * 用于处理用户身份验证和权限管理\n * 如果提供,将在云对象执行前验证用户身份\n */\n uniIdCommonModule?: UniIdCommonModule;\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 * @default '运行环境不匹配'\n */\n onlyLocalEnvErrMsg?: string;\n\n /**\n * 响应附加数据函数\n * 用于在云对象响应中添加额外的上下文信息\n * @param objectThis 云对象上下文\n * @returns 返回要附加到响应中的数据对象\n */\n respondAppend?: (objectThis: CloudObjectThis) => AnyObject;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n\n /**\n * 是否仅在本地环境运行\n * @default false\n */\n onlyLocalEnv?: boolean;\n};\n\n/**\n * 云对象方法创建器类型定义\n *\n * 用于定义云对象方法的创建函数类型,支持两种重载形式:\n * 1. 带输入验证的版本:接收schema、处理函数和选项\n * 2. 无输入参数的版本:仅接收处理函数和选项\n */\nexport type CreateCloudMethod = {\n /**\n * 带输入验证的云对象方法创建器\n * @template S - Zod验证模式类型\n * @template O - 返回值类型\n * @param schema - Zod验证模式,用于验证输入数据\n * @param fn - 业务逻辑处理函数,接收上下文和验证后的输入数据\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: CloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): CloudMethod<z.infer<S>, O>;\n\n /**\n * 无输入参数的云对象方法创建器\n * @template O - 返回值类型\n * @param fn - 业务逻辑处理函数,仅接收上下文\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <O>(fn: (context: CloudObjectContext) => MaybePromise<O>, options?: CreateCloudObjectOptions): CloudMethod<void, O>;\n};\n\n/**\n * 构建云对象方法创建器\n *\n * 该函数用于创建云对象方法的工厂函数,支持输入验证、用户身份验证、环境检查等功能。\n * 返回的创建器函数可以根据不同的配置创建云对象方法。\n *\n * @param options 构建选项,用于配置云对象方法创建器的行为\n * @returns 返回一个云对象方法创建器函数\n *\n * @example\n * // 创建一个需要用户登录的云对象方法\n * const createMethod = buildCloudMethodCreator({ uniIdCommonModule });\n * const myMethod = createMethod(async (context) => {\n * return { message: 'Hello ' + context.user.id };\n * }, { requiredUser: true });\n */\nexport function buildCloudMethodCreator(options?: BuildCloudMethodCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n onlyLocalEnvErrMsg: '运行环境不匹配',\n respondAppend: () => ({}),\n }) as Required<BuildCloudMethodCreatorOptions>;\n\n // @ts-ignore\n const createCloudMethod: CreateCloudMethod = (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 onlyLocalEnv: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云对象方法响应逻辑,包括错误捕获和统一响应格式\n return await respondCloudMethod(async () => {\n const runtimeEnv = this.getCloudInfo().runtimeEnv;\n\n if (createOptions.onlyLocalEnv && runtimeEnv !== 'local') {\n throw createCloudObjectError(buildOptions.onlyLocalEnvErrMsg);\n }\n\n // 构建附加的上下文信息,包括用户身份和权限信息\n const user = await _parseAppendUser(this, options?.uniIdCommonModule);\n const append: _CloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as CloudObjectContext;\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 createCloudMethod;\n}\n\n/**\n * 解析并附加用户信息到云对象上下文\n *\n * 该函数用于验证用户身份并获取用户权限信息,将结果附加到云对象上下文中的user字段\n * 如果未提供uniIdCommonModule或验证失败,则返回默认的空用户信息\n *\n * @param objectThis 云对象上下文,包含客户端信息和token等\n * @param uniIdCommonModule 可选的UniId通用模块实例,用于验证用户token\n * @returns 返回包含用户ID、角色、权限等信息的对象\n *\n * @example\n * // 成功验证用户身份\n * const user = await _parseAppendUser(this, uniIdModule);\n * // 返回: { id: 'user123', role: ['user'], permission: ['read'], isAdmin: false }\n *\n * @example\n * // 验证失败或未提供模块\n * const user = await _parseAppendUser(this);\n * // 返回: { id: '', role: [], permission: [], isAdmin: false }\n */\nasync function _parseAppendUser(\n objectThis: CloudObjectThis,\n uniIdCommonModule?: UniIdCommonModule,\n): Promise<_CloudObjectThisAppendUser> {\n const appendUser: _CloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCommonModule) return appendUser;\n\n const uic = uniIdCommonModule.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 验证用户token,忽略验证过程中的错误\n const [err1, user] = await tryFlatten(uic.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 解析验证结果,忽略解析过程中的错误\n const [err2, userData] = tryFlatten(() => parseCloudModuleOutput(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":"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"}
|
|
1
|
+
{"version":3,"file":"cloud.mjs","sources":["../src/cloud/module.ts","../src/cloud/respond.ts","../src/cloud/method.ts"],"sourcesContent":["import { objectOmit } from '@cloudcome/utils-core/object';\nimport { createCloudObjectError } from './error';\nimport type { CloudModuleOutput } from './types';\n\n/**\n * 解析云模块输出结果\n *\n * 该函数用于处理云模块的输出,如果输出中包含错误码,则抛出相应的错误;\n * 否则返回去除错误码和错误信息后的数据部分。\n *\n * @template O - 输出数据的类型\n * @param output - 云模块的输出结果,包含errCode、errMsg和数据部分\n * @param fallbackErrorMessage - 当输出中没有错误信息时使用的默认错误消息\n * @returns 返回去除errCode和errMsg字段后的数据对象\n * @throws {CloudObjectError} 当output中存在errCode时抛出包含错误码和错误信息的异常\n *\n * @example\n * // 成功情况\n * const result = parseCloudModuleOutput({ value: 'success', errCode: 0, errMsg: '' });\n * // 返回: { value: 'success' }\n *\n * @example\n * // 错误情况\n * try {\n * parseCloudModuleOutput({ errCode: 404, errMsg: 'Not Found' });\n * } catch (error) {\n * // 抛出错误: CloudObjectError('Not Found', 404)\n * }\n */\nexport function parseCloudModuleOutput<O>(\n output: CloudModuleOutput<O>,\n fallbackErrorMessage = '',\n): Omit<O, 'errCode' | 'errMsg'> {\n if (output.errCode) {\n throw createCloudObjectError(output.errMsg || fallbackErrorMessage, output.errCode);\n }\n return objectOmit(output, ['errCode', 'errMsg']);\n}\n","import { errorNormalize } from '@cloudcome/utils-core/error';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\nimport type { CloudMethodOutput } from './types';\n\n/**\n * 执行云对象方法并标准化响应格式\n *\n * @template O - 函数返回值的类型\n * @param fn - 要执行的异步函数\n * @param append - 要附加到响应中的额外数据\n * @returns 标准化的云对象响应对象\n *\n * @example\n * ```typescript\n * const result = await respondCloudMethod(async () => {\n * return await getData();\n * }, { extra: 'data' });\n * ```\n */\nexport async function respondCloudMethod<O>(\n fn: () => MaybePromise<O>,\n append?: AnyObject,\n): Promise<CloudMethodOutput<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 { objectDefaults, objectOmit } 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 { parseCloudModuleOutput } from './module';\nimport { respondCloudMethod } from './respond';\nimport type { CloudMethod, CloudModuleOutput, CloudObjectThis } from './types';\nimport type { UniIdCommonModule } from './uni-id';\n\ntype _CloudObjectThisAppendUser = {\n id: string;\n role: string[];\n permission: string[];\n isAdmin: boolean;\n};\n\ntype _CloudObjectThisAppend = {\n options: Required<CreateCloudObjectOptions>;\n user: _CloudObjectThisAppendUser;\n};\n\nexport type CloudObjectContext = CloudObjectThis & _CloudObjectThisAppend;\n\nexport type BuildCloudMethodCreatorOptions = {\n /**\n * UniId 通用模块\n * 用于处理用户身份验证和权限管理\n * 如果提供,将在云对象执行前验证用户身份\n */\n uniIdCommonModule?: UniIdCommonModule;\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 * @default '运行环境不匹配'\n */\n onlyLocalEnvErrMsg?: string;\n\n /**\n * 响应附加数据函数\n * 用于在云对象响应中添加额外的上下文信息\n * @param objectThis 云对象上下文\n * @returns 返回要附加到响应中的数据对象\n */\n respondAppend?: (objectThis: CloudObjectThis) => AnyObject;\n};\n\nexport type CreateCloudObjectOptions = {\n /**\n * 是否需要用户登录态\n * @default false\n */\n requiredUser?: boolean;\n\n /**\n * 是否仅在本地环境运行\n * @default false\n */\n onlyLocalEnv?: boolean;\n};\n\n/**\n * 云对象方法创建器类型定义\n *\n * 用于定义云对象方法的创建函数类型,支持两种重载形式:\n * 1. 带输入验证的版本:接收schema、处理函数和选项\n * 2. 无输入参数的版本:仅接收处理函数和选项\n */\nexport type CreateCloudMethod = {\n /**\n * 带输入验证的云对象方法创建器\n * @template S - Zod验证模式类型\n * @template O - 返回值类型\n * @param schema - Zod验证模式,用于验证输入数据\n * @param fn - 业务逻辑处理函数,接收上下文和验证后的输入数据\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <S extends ZodObject, O>(\n schema: S,\n fn: (context: CloudObjectContext, input: z.infer<S>) => MaybePromise<O>,\n options?: CreateCloudObjectOptions,\n ): CloudMethod<z.infer<S>, O>;\n\n /**\n * 无输入参数的云对象方法创建器\n * @template O - 返回值类型\n * @param fn - 业务逻辑处理函数,仅接收上下文\n * @param options - 云对象创建选项\n * @returns 云对象方法函数\n */\n <O>(fn: (context: CloudObjectContext) => MaybePromise<O>, options?: CreateCloudObjectOptions): CloudMethod<void, O>;\n};\n\n/**\n * 构建云对象方法创建器\n *\n * 该函数用于创建云对象方法的工厂函数,支持输入验证、用户身份验证、环境检查等功能。\n * 返回的创建器函数可以根据不同的配置创建云对象方法。\n *\n * @param options 构建选项,用于配置云对象方法创建器的行为\n * @returns 返回一个云对象方法创建器函数\n *\n * @example\n * // 创建一个需要用户登录的云对象方法\n * const createMethod = buildCloudMethodCreator({ uniIdCommonModule });\n * const myMethod = createMethod(async (context) => {\n * return { message: 'Hello ' + context.user.id };\n * }, { requiredUser: true });\n */\nexport function buildCloudMethodCreator(options?: BuildCloudMethodCreatorOptions) {\n const buildOptions = objectDefaults(options || {}, {\n requiredUserErrCode: 'uni-id-check-token-failed',\n requiredUserErrMsg: '需要登录后才能进行此操作',\n onlyLocalEnvErrMsg: '运行环境不匹配',\n respondAppend: () => ({}),\n }) as Required<BuildCloudMethodCreatorOptions>;\n\n // @ts-ignore\n const createCloudMethod: CreateCloudMethod = (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 onlyLocalEnv: false,\n }) as Required<CreateCloudObjectOptions>;\n\n return async function (input) {\n // 处理云对象方法响应逻辑,包括错误捕获和统一响应格式\n return await respondCloudMethod(async () => {\n const runtimeEnv = this.getCloudInfo().runtimeEnv;\n\n if (createOptions.onlyLocalEnv && runtimeEnv !== 'local') {\n throw createCloudObjectError(buildOptions.onlyLocalEnvErrMsg);\n }\n\n // 构建附加的上下文信息,包括用户身份和权限信息\n const user = await _parseAppendUser(this, options?.uniIdCommonModule);\n const append: _CloudObjectThisAppend = {\n options: createOptions,\n user: user,\n };\n const context = Object.assign(this, append) as CloudObjectContext;\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 createCloudMethod;\n}\n\n/**\n * 解析并附加用户信息到云对象上下文\n *\n * 该函数用于验证用户身份并获取用户权限信息,将结果附加到云对象上下文中的user字段\n * 如果未提供uniIdCommonModule或验证失败,则返回默认的空用户信息\n *\n * @param objectThis 云对象上下文,包含客户端信息和token等\n * @param uniIdCommonModule 可选的UniId通用模块实例,用于验证用户token\n * @returns 返回包含用户ID、角色、权限等信息的对象\n *\n * @example\n * // 成功验证用户身份\n * const user = await _parseAppendUser(this, uniIdModule);\n * // 返回: { id: 'user123', role: ['user'], permission: ['read'], isAdmin: false }\n *\n * @example\n * // 验证失败或未提供模块\n * const user = await _parseAppendUser(this);\n * // 返回: { id: '', role: [], permission: [], isAdmin: false }\n */\nasync function _parseAppendUser(\n objectThis: CloudObjectThis,\n uniIdCommonModule?: UniIdCommonModule,\n): Promise<_CloudObjectThisAppendUser> {\n const appendUser: _CloudObjectThisAppendUser = {\n id: '',\n role: [],\n permission: [],\n isAdmin: false,\n };\n\n if (!uniIdCommonModule) return appendUser;\n\n const uic = uniIdCommonModule.createInstance({\n clientInfo: objectThis.getClientInfo(),\n });\n\n // 验证用户token,忽略验证过程中的错误\n const [err1, user] = await tryFlatten(uic.checkToken(objectThis.getUniIdToken() || ''));\n if (!user) return appendUser;\n\n // 解析验证结果,忽略解析过程中的错误\n const [err2, userData] = tryFlatten(() => parseCloudModuleOutput(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":"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"}
|
|
@@ -1,35 +1,6 @@
|
|
|
1
|
-
import { AnyObject,
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
[K in keyof T]?: T[K] | DbQueryCommand;
|
|
5
|
-
};
|
|
6
|
-
export type DbSelect<T> = {
|
|
7
|
-
[K in keyof T]?: K extends '_id' ? boolean : true;
|
|
8
|
-
};
|
|
9
|
-
export type DbFieldsDefault<T> = {
|
|
10
|
-
[K in keyof T]: true;
|
|
11
|
-
};
|
|
12
|
-
type _OnlyFieldId<D, V> = IsOnlyProperty<D, '_id'> extends true ? '_id' extends keyof D ? D['_id'] extends V ? true : false : false : false;
|
|
13
|
-
type _DbFields<D, S extends DbSelect<D>> = IsEmptyObject<S> extends true ? DbFieldsDefault<D> : _OnlyFieldId<S, false> extends true ? Omit<DbFieldsDefault<D>, '_id'> : _OnlyFieldId<S, true> extends true ? {
|
|
14
|
-
_id: true;
|
|
15
|
-
} : HasProperty<S, '_id'> extends true ? S : // 没有的话补上 {_id, ...}
|
|
16
|
-
S & {
|
|
17
|
-
_id: true;
|
|
18
|
-
};
|
|
19
|
-
type _DbQuery<D1, S1 extends DbSelect<D1>> = {
|
|
20
|
-
[K in keyof D1 as S1[K] extends true ? K : never]: D1[K];
|
|
21
|
-
};
|
|
22
|
-
export type DbQuery<D1, S1 extends DbSelect<D1>, D2> = _DbQuery<D1, _DbFields<D1, S1>> & D2;
|
|
23
|
-
export type DbForeign<D1, S1 extends DbSelect<D1>, D2, JT extends DbJoinType, AS extends string> = Record<AS, JT extends '1:1' ? DbQuery<D1, S1, D2> : DbQuery<D1, S1, D2>[]>;
|
|
24
|
-
export type DbCreate<T> = Omit<T, '_id'> & {
|
|
25
|
-
_id?: string;
|
|
26
|
-
};
|
|
27
|
-
export type DbUpdate<T> = T extends AnyObject ? {
|
|
28
|
-
[K in keyof T]?: DbUpdate<T[K]> | DbMutateCommand;
|
|
29
|
-
} : T;
|
|
30
|
-
export type DbOrder<T> = {
|
|
31
|
-
[K in keyof T]?: 'asc' | 'desc';
|
|
32
|
-
};
|
|
1
|
+
import { AnyObject, MergeIntersection } from '@cloudcome/utils-core/types';
|
|
2
|
+
import { DbQueryCommand } from './_command.class';
|
|
3
|
+
import { DbCreate, DbForeign, DbOrder, DbQuery, DbRelation, DbSelect, DbUpdate, DbWhere } from './types';
|
|
33
4
|
export type DbOptions = {
|
|
34
5
|
/**
|
|
35
6
|
* 数据表名称
|
|
@@ -44,18 +15,11 @@ export type DbOptions = {
|
|
|
44
15
|
*/
|
|
45
16
|
_mockDatabase?: any;
|
|
46
17
|
};
|
|
47
|
-
|
|
48
|
-
* 数据库关联类型
|
|
49
|
-
* - '1:1': 一对一关联,返回值 1 个
|
|
50
|
-
* - '1:n': 一对多关联,返回值 n 个
|
|
51
|
-
* - 'n:1': 多对一关联,返回值 n 个
|
|
52
|
-
*/
|
|
53
|
-
export type DbJoinType = '1:1' | '1:n' | 'n:1';
|
|
54
|
-
export type DbLookupOptions<JT extends DbJoinType, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {
|
|
18
|
+
export type DbLookupOptions<RL extends DbRelation, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {
|
|
55
19
|
/**
|
|
56
20
|
* 关联类型
|
|
57
21
|
*/
|
|
58
|
-
|
|
22
|
+
relation: RL;
|
|
59
23
|
/**
|
|
60
24
|
* 主表字段
|
|
61
25
|
*/
|
|
@@ -158,7 +122,7 @@ export declare class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject =
|
|
|
158
122
|
private _hasLookup;
|
|
159
123
|
get hasLookup(): boolean;
|
|
160
124
|
private _lookups;
|
|
161
|
-
lookup<FD1, FS1 extends DbSelect<FD1>, FD2 extends AnyObject, FW2 extends AnyObject,
|
|
125
|
+
lookup<FD1, FS1 extends DbSelect<FD1>, FD2 extends AnyObject, FW2 extends AnyObject, RL extends DbRelation, AS extends string, US extends boolean | undefined | void = undefined>(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<RL, D1, FD1, AS, US>): Db<D1, S1, US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, RL, AS>>, MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>>;
|
|
162
126
|
private _aggregated;
|
|
163
127
|
private _endAggregate;
|
|
164
128
|
private _endHost;
|
|
@@ -198,4 +162,3 @@ export declare class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject =
|
|
|
198
162
|
*/
|
|
199
163
|
remove(): Promise<number>;
|
|
200
164
|
}
|
|
201
|
-
export {};
|
package/dist/database/proxy.d.ts
CHANGED
package/dist/database/types.d.ts
CHANGED
|
@@ -1,9 +1,115 @@
|
|
|
1
|
+
import { HasProperty, IsEmptyObject, IsOnlyProperty } from '@cloudcome/utils-core/types';
|
|
2
|
+
import { DbMutateCommand, DbQueryCommand } from './_command.class';
|
|
3
|
+
/**
|
|
4
|
+
* 客户端数据库输出类型
|
|
5
|
+
* @template T - 原始数据类型
|
|
6
|
+
*/
|
|
1
7
|
export type ClientDatabaseOutput<T> = {
|
|
2
8
|
result: T & {
|
|
9
|
+
/** 状态码 */
|
|
3
10
|
code?: number | string;
|
|
11
|
+
/** 错误码 */
|
|
4
12
|
errCode?: number | string;
|
|
13
|
+
/** 错误信息 */
|
|
5
14
|
errMsg?: string;
|
|
15
|
+
/** 消息 */
|
|
6
16
|
message?: string;
|
|
7
17
|
};
|
|
8
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* 云端数据库输出类型
|
|
21
|
+
* @template T - 原始数据类型
|
|
22
|
+
*/
|
|
9
23
|
export type CloudDatabaseOutput<T> = T;
|
|
24
|
+
/** 数据库相关类型 */
|
|
25
|
+
/**
|
|
26
|
+
* 数据库查询条件类型
|
|
27
|
+
* @template T - 数据模型类型
|
|
28
|
+
*/
|
|
29
|
+
export type DbWhere<T> = {
|
|
30
|
+
[K in keyof T]?: T[K] | DbQueryCommand;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 数据库字段选择类型
|
|
34
|
+
* @template T - 数据模型类型
|
|
35
|
+
*/
|
|
36
|
+
export type DbSelect<T> = {
|
|
37
|
+
[K in keyof T]?: K extends '_id' ? boolean : true;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* 数据库默认字段类型
|
|
41
|
+
* @template T - 数据模型类型
|
|
42
|
+
*/
|
|
43
|
+
export type DbFieldsDefault<T> = {
|
|
44
|
+
[K in keyof T]: true;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* 判断是否只有 _id 字段的内部类型
|
|
48
|
+
* @template D - 字段选择类型
|
|
49
|
+
* @template V - 值类型
|
|
50
|
+
*/
|
|
51
|
+
type _OnlyFieldId<D, V> = IsOnlyProperty<D, '_id'> extends true ? '_id' extends keyof D ? D['_id'] extends V ? true : false : false : false;
|
|
52
|
+
/**
|
|
53
|
+
* 数据库字段处理类型
|
|
54
|
+
* @template D - 数据模型类型
|
|
55
|
+
* @template S - 字段选择类型
|
|
56
|
+
*/
|
|
57
|
+
export type DbFields<D, S extends DbSelect<D>> = IsEmptyObject<S> extends true ? DbFieldsDefault<D> : _OnlyFieldId<S, false> extends true ? Omit<DbFieldsDefault<D>, '_id'> : _OnlyFieldId<S, true> extends true ? {
|
|
58
|
+
_id: true;
|
|
59
|
+
} : HasProperty<S, '_id'> extends true ? S : // 没有的话补上 {_id, ...}
|
|
60
|
+
S & {
|
|
61
|
+
_id: true;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* 数据库查询结果类型
|
|
65
|
+
* @template D1 - 主数据模型类型
|
|
66
|
+
* @template S1 - 字段选择类型
|
|
67
|
+
*/
|
|
68
|
+
type _DbQuery<D1, S1 extends DbSelect<D1>> = {
|
|
69
|
+
[K in keyof D1 as S1[K] extends true ? K : never]: D1[K];
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* 数据库查询类型
|
|
73
|
+
* @template D1 - 主数据模型类型
|
|
74
|
+
* @template S1 - 字段选择类型
|
|
75
|
+
* @template D2 - 关联数据模型类型
|
|
76
|
+
*/
|
|
77
|
+
export type DbQuery<D1, S1 extends DbSelect<D1>, D2> = _DbQuery<D1, DbFields<D1, S1>> & D2;
|
|
78
|
+
/**
|
|
79
|
+
* 数据库关联类型
|
|
80
|
+
* - '1:1': 一对一关联,返回值 1 个
|
|
81
|
+
* - '1:n': 一对多关联,返回值 n 个
|
|
82
|
+
* - 'n:1': 多对一关联,返回值 n 个
|
|
83
|
+
*/
|
|
84
|
+
export type DbRelation = '1:1' | '1:n' | 'n:1';
|
|
85
|
+
/**
|
|
86
|
+
* 数据库外键关联类型
|
|
87
|
+
* @template D1 - 主数据模型类型
|
|
88
|
+
* @template S1 - 主数据字段选择类型
|
|
89
|
+
* @template D2 - 关联数据模型类型
|
|
90
|
+
* @template RL - 关联关系类型
|
|
91
|
+
* @template AS - 关联字段别名
|
|
92
|
+
*/
|
|
93
|
+
export type DbForeign<D1, S1 extends DbSelect<D1>, D2, RL extends DbRelation, AS extends string> = Record<AS, RL extends '1:1' ? DbQuery<D1, S1, D2> : DbQuery<D1, S1, D2>[]>;
|
|
94
|
+
/**
|
|
95
|
+
* 数据库创建数据类型
|
|
96
|
+
* @template T - 数据模型类型
|
|
97
|
+
*/
|
|
98
|
+
export type DbCreate<T> = Omit<T, '_id'> & {
|
|
99
|
+
_id?: string;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* 数据库更新数据类型
|
|
103
|
+
* @template T - 数据模型类型
|
|
104
|
+
*/
|
|
105
|
+
export type DbUpdate<T> = T extends AnyObject ? {
|
|
106
|
+
[K in keyof T]?: DbUpdate<T[K]> | DbMutateCommand;
|
|
107
|
+
} : T;
|
|
108
|
+
/**
|
|
109
|
+
* 数据库排序类型
|
|
110
|
+
* @template T - 数据模型类型
|
|
111
|
+
*/
|
|
112
|
+
export type DbOrder<T> = {
|
|
113
|
+
[K in keyof T]?: 'asc' | 'desc';
|
|
114
|
+
};
|
|
115
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DbCreate, DbSelect, DbUpdate, DbWhere } from './_db.class';
|
|
2
1
|
import { DbProxy } from './proxy';
|
|
2
|
+
import { DbCreate, DbSelect, DbUpdate, DbWhere } from './types';
|
|
3
3
|
export type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {
|
|
4
4
|
/** 查询条件 */
|
|
5
5
|
where: DbWhere<T>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Exact } from '@cloudcome/utils-core/types';
|
|
2
|
-
import { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './_db.class';
|
|
3
2
|
import { DbProxy } from './proxy';
|
|
3
|
+
import { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './types';
|
|
4
4
|
export type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {
|
|
5
5
|
/** 查询条件 */
|
|
6
6
|
where: DbWhere<T>;
|
package/dist/database.cjs
CHANGED
|
@@ -288,7 +288,7 @@ class Db {
|
|
|
288
288
|
this._aggregated = true;
|
|
289
289
|
let returnAggRef = aggRef;
|
|
290
290
|
const projects = {};
|
|
291
|
-
for (const {
|
|
291
|
+
for (const { relation: type2, as, foreignField, localField, table, unselect } of this._lookups) {
|
|
292
292
|
const letName = `let${gid++}`;
|
|
293
293
|
let pipeline = dbAgg.pipeline();
|
|
294
294
|
pipeline = pipeline.match({
|
|
@@ -344,6 +344,7 @@ class Db {
|
|
|
344
344
|
* @returns 查询结果
|
|
345
345
|
*/
|
|
346
346
|
async query() {
|
|
347
|
+
if (this._isTransaction) throw new Error("db.query() 方法不支持事务模式");
|
|
347
348
|
let res;
|
|
348
349
|
if (this._hasLookup) {
|
|
349
350
|
const aggRef = this.aggregate();
|
|
@@ -358,6 +359,7 @@ class Db {
|
|
|
358
359
|
return data;
|
|
359
360
|
}
|
|
360
361
|
async queryOne(allowMiss = false) {
|
|
362
|
+
if (this._isTransaction) throw new Error("db.queryOne() 方法不支持事务模式");
|
|
361
363
|
if (this._hasLimit) throw new Error("db.queryOne() 方法不支持 limit 条件");
|
|
362
364
|
if (!this._hasWhereId) this.limit(1);
|
|
363
365
|
const data = await this.query();
|
package/dist/database.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.cjs","sources":["../src/database/_command.class.ts","../src/database/command.ts","../src/database/_db.class.ts","../src/database/proxy.ts","../src/database/upsert.ts","../src/database/unique.ts","../src/database/transaction.ts"],"sourcesContent":["// 设置私有属性和静态方法是避免在 update 的时候提示类属性\n\nexport class DbBaseCommand {\n protected _isQuery = false;\n protected _isMutate = false;\n\n constructor(\n private _command: string,\n private _parameter: unknown,\n ) {}\n\n static getValue(cmd: DbBaseCommand, db: UniCloud.Database) {\n return (db.command as unknown as Record<string, (value: unknown) => unknown>)[cmd._command].call(\n db.command,\n cmd._parameter,\n );\n }\n\n static getExpression(cmd: DbBaseCommand, fieldName: string) {\n return {\n [`$${cmd._command}`]: [fieldName, cmd._parameter],\n };\n }\n\n static isQueryCommand(cmd: DbBaseCommand) {\n return cmd._isQuery;\n }\n\n static isMutateCommand(cmd: DbBaseCommand) {\n return cmd._isMutate;\n }\n}\n\nexport class DbQueryCommand extends DbBaseCommand {\n protected _isQuery = true;\n}\n\nexport class DbMutateCommand extends DbBaseCommand {\n protected _isMutate = true;\n}\n","import { DbMutateCommand, DbQueryCommand } from './_command.class';\n\n/**\n * 数据库查询命令对象,提供各种查询操作符\n */\nexport const dbQuery = {\n /**\n * 等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n eq: (value: unknown) => new DbQueryCommand('eq', value),\n\n /**\n * 不等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n neq: (value: unknown) => new DbQueryCommand('neq', value),\n\n /**\n * 大于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gt: (value: unknown) => new DbQueryCommand('gt', value),\n\n /**\n * 大于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gte: (value: unknown) => new DbQueryCommand('gte', value),\n\n /**\n * 小于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lt: (value: unknown) => new DbQueryCommand('lt', value),\n\n /**\n * 小于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lte: (value: unknown) => new DbQueryCommand('lte', value),\n\n /**\n * 包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n in: (value: unknown[]) => new DbQueryCommand('in', value),\n\n /**\n * 不包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n nin: (value: unknown[]) => new DbQueryCommand('nin', value),\n\n /**\n * 逻辑与操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n and: (conditions: unknown[]) => new DbQueryCommand('and', conditions),\n\n /**\n * 逻辑或操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n or: (conditions: unknown[]) => new DbQueryCommand('or', conditions),\n\n /**\n * 数组长度匹配操作符\n * @param size 数组长度\n * @returns DbQueryCommand 查询命令对象\n */\n size: (size: number) => new DbQueryCommand('size', size),\n};\n\n/**\n * 数据库变更命令对象,提供各种数据更新操作符\n */\nexport const dbMutate = {\n /**\n * 数值增加操作符\n * @param value 增加的数值\n * @returns DbMutateCommand 变更命令对象\n */\n inc: (value: number) => new DbMutateCommand('inc', value),\n\n /**\n * 数值乘法操作符\n * @param value 乘数\n * @returns DbMutateCommand 变更命令对象\n */\n mul: (value: number) => new DbMutateCommand('mul', value),\n\n /**\n * 设置字段值操作符\n * @param value 设置的值\n * @returns DbMutateCommand 变更命令对象\n */\n set: (value: unknown) => new DbMutateCommand('set', value),\n\n /**\n * 向数组末尾添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n push: (value: unknown) => new DbMutateCommand('push', value),\n\n /**\n * 向数组开头添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n unshift: (value: unknown) => new DbMutateCommand('unshift', value),\n\n /**\n * 从数组末尾移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n pop: () => new DbMutateCommand('pop', undefined),\n\n /**\n * 从数组开头移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n shift: () => new DbMutateCommand('shift', undefined),\n\n /**\n * 移除字段操作符\n * @returns DbMutateCommand 变更命令对象\n */\n remove: () => new DbMutateCommand('remove', undefined),\n};\n","import { createCloudObjectError } from '@/cloud';\nimport { parseDatabaseOutput } from '@/database';\nimport { objectEach, objectMap } from '@cloudcome/utils-core/object';\nimport { isArray, isNumber, isObject, isString } from '@cloudcome/utils-core/type';\nimport type {\n AnyObject,\n Exact,\n HasProperty,\n IsEmptyObject,\n IsOnlyProperty,\n MergeIntersection,\n} from '@cloudcome/utils-core/types';\nimport { DbBaseCommand, type DbMutateCommand, type DbQueryCommand } from './_command.class';\n\n/**\n * 数据库聚合操作符命令\n */\nconst dbAgg = uniCloud.database().command.aggregate as UniCloud.AggregateCommand & {\n pipeline: () => UniCloud.AggregateReference & {\n done: () => unknown;\n };\n};\n\nexport type DbWhere<T> = {\n [K in keyof T]?: T[K] | DbQueryCommand;\n};\nexport type DbSelect<T> = {\n [K in keyof T]?: K extends '_id' ? boolean : true;\n};\nexport type DbFieldsDefault<T> = {\n [K in keyof T]: true;\n};\ntype _OnlyFieldId<D, V> = IsOnlyProperty<D, '_id'> extends true\n ? '_id' extends keyof D\n ? D['_id'] extends V\n ? true\n : false\n : false\n : false;\ntype _DbFields<D, S extends DbSelect<D>> = IsEmptyObject<S> extends true // 判断是否为空对象\n ? // 默认全部字段\n DbFieldsDefault<D>\n : // 判断 _id 是否为唯一属性 且 为 false\n _OnlyFieldId<S, false> extends true\n ? // 从默认字段里排除 _id\n Omit<DbFieldsDefault<D>, '_id'>\n : // 判断 _id 是否为唯一属性 且 为 true\n _OnlyFieldId<S, true> extends true\n ? // 只保留 _id\n { _id: true }\n : // 判断是否有 _id\n HasProperty<S, '_id'> extends true\n ? // 有的话保留 {_id, ...}\n S\n : // 没有的话补上 {_id, ...}\n S & { _id: true };\ntype _DbQuery<D1, S1 extends DbSelect<D1>> = {\n [K in keyof D1 as S1[K] extends true ? K : never]: D1[K];\n};\n// @ts-ignore\nexport type DbQuery<D1, S1 extends DbSelect<D1>, D2> = _DbQuery<D1, _DbFields<D1, S1>> & D2;\nexport type DbForeign<D1, S1 extends DbSelect<D1>, D2, JT extends DbJoinType, AS extends string> = Record<\n AS,\n JT extends '1:1' ? DbQuery<D1, S1, D2> : DbQuery<D1, S1, D2>[]\n>;\nexport type DbCreate<T> = Omit<T, '_id'> & { _id?: string };\nexport type DbUpdate<T> = T extends AnyObject\n ? {\n [K in keyof T]?: DbUpdate<T[K]> | DbMutateCommand;\n }\n : T;\nexport type DbOrder<T> = {\n [K in keyof T]?: 'asc' | 'desc';\n};\n\ntype _WhereFrom = 'where' | 'whereId';\n\nconst db0 = uniCloud.database();\n\nexport type DbOptions = {\n /**\n * 数据表名称\n */\n table: string;\n\n /**\n * 事务对象,用于事务操作\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n transaction?: any;\n\n /**\n * 模拟数据库,用于单元测试\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any;\n};\n\n/**\n * 数据库关联类型\n * - '1:1': 一对一关联,返回值 1 个\n * - '1:n': 一对多关联,返回值 n 个\n * - 'n:1': 多对一关联,返回值 n 个\n */\nexport type DbJoinType = '1:1' | '1:n' | 'n:1';\n// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\nexport type DbLookupOptions<JT extends DbJoinType, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {\n /**\n * 关联类型\n */\n type: JT;\n\n /**\n * 主表字段\n */\n localField: keyof D1 & string;\n\n /**\n * 关联表字段\n */\n foreignField: keyof FD1 & string;\n\n /**\n * 关联数据在结果中的字段名\n */\n as: AS;\n\n /**\n * 是否取消筛选关联数据\n */\n unselect?: US;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport type DbLookup = DbLookupOptions<any, unknown, unknown, string, boolean> & {\n /**\n * 关联表\n */\n table: Db<unknown>;\n};\n\nlet gid = 0;\n\n/**\n * 数据库类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @template D2 - 副表数据\n * @template W2 - 副表查询\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject = {}, W2 extends AnyObject = {}> {\n private _host: UniCloud.CollectionReference;\n\n /**\n * 是否为事务环境\n * - 查询条件只能是 id\n * - 不能聚合操作\n */\n private _isTransaction = false;\n\n private _options: DbOptions;\n\n /**\n * 构造函数,初始化数据库集合引用\n * @param collection 数据表名称\n * @param _mockDatabase 模拟数据库,用于单元测试\n */\n constructor(options: DbOptions) {\n this._options = options;\n this._host =\n options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);\n this._isTransaction = !!options.transaction;\n }\n\n get table() {\n return this._options.table;\n }\n\n /**\n * 获取聚合操作实例\n * @returns 聚合操作实例\n */\n aggregate() {\n return this._host.aggregate();\n }\n\n private _hasWhere: _WhereFrom | undefined = undefined;\n private _hasWhereId: _WhereFrom | undefined = undefined;\n private _where = {};\n\n private _doWhere(where: DbWhere<D1>, from: _WhereFrom) {\n if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);\n\n const whereKeys = Object.keys(where);\n // 只有 _id 值为字符串或数字时,才能调用 doc 方法\n const isWhereId = whereKeys.length === 1 && '_id' in where && (isString(where._id) || isNumber(where._id));\n\n if (isWhereId && this._hasLimit) {\n throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);\n }\n\n this._hasWhere = from;\n this._where = where;\n if (isWhereId) this._hasWhereId = from;\n\n return this;\n }\n\n /**\n * 设置查询条件\n * @param where 查询条件对象\n * @returns 当前Db实例,支持链式调用\n */\n where(where: DbWhere<D1> & W2) {\n return this._doWhere(where, 'where');\n }\n\n /**\n * 根据ID设置查询条件\n * @param id 记录ID\n * @returns 当前Db实例,支持链式调用\n */\n whereId(id: string | number) {\n // @ts-ignore\n return this._doWhere({ _id: id }, 'whereId');\n }\n\n private _hasSelect = 0;\n private _select = {};\n\n /**\n * 指定要返回的字段\n * @param fields 要返回的字段对象,true表示返回,false表示不返回\n * @returns 当前Db实例,支持链式调用\n */\n select<const S extends DbSelect<D1>>(fields: S) {\n if (this._hasSelect) throw new Error('db.select() 方法只能调用一次');\n\n this._hasSelect++;\n this._select = fields;\n\n // @ts-ignore\n return this as Db<D1, S, D2, W2>;\n }\n\n private _hasOrder = 0;\n private _order = {};\n\n /**\n * 设置排序规则\n * @param order 排序规则对象,key为字段名,value为\"asc\"或\"desc\"\n * @returns 当前Db实例,支持链式调用\n */\n order(order: DbOrder<D1>) {\n this._hasOrder++;\n this._order = order;\n\n return this;\n }\n\n private _hasSkip = 0;\n private _skip = 0;\n\n /**\n * 跳过指定数量的记录\n * @param skip 要跳过的记录数\n * @returns 当前Db实例,支持链式调用\n */\n skip(skip: number) {\n if (this._hasSkip) throw new Error('db.skip() 方法只能调用一次');\n\n this._hasSkip++;\n this._skip = skip;\n\n return this;\n }\n\n private _hasLimit = 0;\n private _limit = 0;\n\n /**\n * 限制返回的记录数量\n * @param limit 最大返回记录数\n * @returns 当前Db实例,支持链式调用\n */\n limit(limit: number) {\n if (this._hasLimit) throw new Error('db.limit() 方法只能调用一次');\n\n if (this._hasWhereId) {\n throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);\n }\n\n this._hasLimit++;\n this._limit = limit;\n\n return this;\n }\n\n private _hasLookup = 0;\n get hasLookup() {\n return this._hasLookup > 0;\n }\n\n private _lookups: DbLookup[] = [];\n lookup<\n FD1,\n FS1 extends DbSelect<FD1>,\n FD2 extends AnyObject,\n FW2 extends AnyObject,\n JT extends DbJoinType,\n AS extends string,\n // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\n US extends boolean | undefined | void = undefined,\n >(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<JT, D1, FD1, AS, US>) {\n // 对方表也记为关联查询,避免做表更新操作\n table._hasLookup++;\n this._hasLookup++;\n this._lookups.push({\n ...lookup,\n table,\n } as unknown as DbLookup);\n\n // @ts-ignore\n return this as Db<\n D1,\n S1,\n US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, JT, AS>>,\n MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>\n >;\n }\n\n private _aggregated = false;\n private _endAggregate(aggRef: UniCloud.AggregateReference) {\n if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);\n\n this._aggregated = true;\n let returnAggRef = aggRef;\n const projects: Record<string, true> = {};\n\n for (const { type, as, foreignField, localField, table, unselect } of this._lookups) {\n const letName = `let${gid++}`;\n let pipeline = dbAgg.pipeline();\n\n // 关联条件\n // @ts-ignore\n pipeline = pipeline.match({\n $expr: {\n $and: [\n type === 'n:1'\n ? { $in: [`$${foreignField}`, `$$${letName}`] }\n : { $eq: [`$${foreignField}`, `$$${letName}`] },\n ],\n },\n });\n\n // 其他查询条件\n // @ts-ignore\n pipeline = table._endAggregate(pipeline);\n\n // @ts-ignore\n pipeline = pipeline.done();\n\n returnAggRef = returnAggRef.lookup({\n let: {\n [letName]: `$${localField}`,\n },\n as,\n from: table.table,\n pipeline,\n });\n\n // 1对1,展开数组\n if (type === '1:1') {\n // @ts-ignore\n returnAggRef = returnAggRef.unwind({\n path: `$${as}`,\n preserveNullAndEmptyArrays: true,\n });\n }\n\n if (as && !unselect) projects[as] = true;\n }\n\n // 主表查询\n if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));\n if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });\n if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => (v === 'asc' ? 1 : -1)));\n if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);\n if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);\n\n return returnAggRef;\n }\n\n private _endHost() {\n if (this._hasWhere) {\n // @ts-ignore\n this._host = this._host.where(_mapCommandRaw(this._where));\n }\n\n if (this._hasSelect) {\n // @ts-ignore\n this._host = this._host.field(this._select);\n }\n\n if (this._hasOrder) {\n objectEach(this._order, (val, key) => {\n // @ts-ignore\n this._host = this._host.orderBy(key, val);\n });\n }\n\n // @ts-ignore\n if (this._hasSkip) this._host = this._host.skip(this._skip);\n\n // @ts-ignore\n if (this._hasLimit) this._host = this._host.limit(this._limit);\n // @ts-ignore\n else if (this._hasWhereId) this._host = this._host.limit(1);\n }\n\n /**\n * 执行查询操作\n * @returns 查询结果\n */\n async query() {\n let res: { data: DbQuery<D1, S1, D2>[] };\n\n // 关联查询\n if (this._hasLookup) {\n const aggRef = this.aggregate();\n this._endAggregate(aggRef);\n res = await aggRef.end();\n }\n // 单表查询\n else {\n this._endHost();\n res = await this._host.get();\n }\n\n const rows = isArray(res.data) ? res.data : [res.data];\n const { data } = parseDatabaseOutput(res);\n return data;\n }\n\n /**\n * 只查询一条,自动添加 limit(1) 条件\n * @param allowMiss 是否允许没有匹配到记录,如果为 true,则可能返回 null\n * @returns 查询结果\n */\n async queryOne(): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: false): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: true): Promise<DbQuery<D1, S1, D2> | null>;\n async queryOne(allowMiss = false): Promise<DbQuery<D1, S1, D2> | null> {\n if (this._hasLimit) throw new Error('db.queryOne() 方法不支持 limit 条件');\n if (!this._hasWhereId) this.limit(1);\n\n const data = await this.query();\n const res = data.at(0);\n\n if (!allowMiss && !res) throw createCloudObjectError('查询数据为空', 'queryOneNotFound');\n return res || null;\n }\n\n /**\n * 获取匹配记录的数量\n * @returns 记录总数\n */\n async count() {\n if (this._hasLookup) throw new Error('db.count() 方法不支持 lookup 聚合');\n if (this._hasSelect) throw new Error('db.count() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.count() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.count() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.count() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.count();\n const { total } = parseDatabaseOutput<{ total: number }>(res);\n return total;\n }\n\n /**\n * 创建新记录\n * @param data 要创建的数据\n * @returns 创建结果\n */\n async create(data: DbCreate<D1>) {\n if (this._hasLookup) throw new Error('db.create() 方法不支持 lookup 聚合');\n if (this._hasWhere) throw new Error('db.create() 方法不支持 where 条件');\n if (this._hasSelect) throw new Error('db.create() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.create() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.create() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.create() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.add(data);\n const { id } = parseDatabaseOutput<{ id: string }>(res);\n return id;\n }\n\n /**\n * 更新记录\n * @param data 要更新的数据\n * @returns 更新结果\n */\n async update(data: DbUpdate<D1>) {\n if (this._hasLookup) throw new Error('db.update() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.update() 方法');\n if (this._hasSelect) throw new Error('db.update() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.update() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.update() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.update() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.update() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.update(_mapCommandRaw(data));\n const { updated } = parseDatabaseOutput<{ updated: number }>(res);\n return updated;\n }\n\n /**\n * 删除记录\n * @returns 删除结果\n */\n async remove() {\n if (this._hasLookup) throw new Error('db.remove() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.remove() 方法');\n if (this._hasSelect) throw new Error('db.remove() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.remove() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.remove() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.remove() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.remove() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.remove();\n const { deleted } = parseDatabaseOutput<{ deleted: number }>(res);\n return deleted;\n }\n}\n\nfunction _toWhereMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({...})' : 'whereId(id)';\n}\n\nfunction _toWhereIdMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({ _id })' : 'whereId(id)';\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nfunction _mapCommandRaw(where: any) {\n return objectMap(where, (val, key) => {\n return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;\n });\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db, type DbSelect } from './_db.class';\n\n/**\n * DbProxy 类型定义,用于创建数据库代理对象\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport type DbProxy<D1, S1 extends DbSelect<D1> = {}> = Db<D1, S1> & {\n _isProxy: true;\n};\n\n/**\n * 创建一个数据库代理对象,用于延迟实例化数据库操作类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @param name - 数据库表名\n * @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport function dbProxy<D1, S1 extends DbSelect<D1> = {}>(name: string) {\n return new Proxy(\n {},\n {\n get(target, prop) {\n if (prop === '_isProxy') return true;\n\n const table = new Db<D1, S1>({ table: name });\n const tableProp = prop as keyof Db<D1, S1>;\n const ref = table[tableProp];\n\n return isFunction(ref) ? ref.bind(table) : ref;\n },\n },\n ) as DbProxy<D1, S1>;\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { Exact } from '@cloudcome/utils-core/types';\nimport type { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './_db.class';\nimport type { DbProxy } from './proxy';\n\nexport type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 查询返回字段 */\n select?: Exact<S, DbSelect<T>>;\n\n /** 创建数据 */\n create: C;\n\n /**\n * 更新数据,可以是对象或根据查询结果生成更新对象的函数\n * @param row 查询到的文档数据,仅在传入函数时可用\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n update: U | ((exist: DbQuery<T, S, {}>) => U);\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /**\n * 更新前回调函数\n * @param exist 查询到的原始文档数据\n * @returns 如果返回 false,则取消更新操作\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;\n\n /**\n * 更新后回调函数\n * @param updateData 实际更新的数据\n * @param exist 查询到的原始文档数据\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUpsertOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n /** 是否为更新操作 */\n updated: boolean;\n};\n\nexport async function dbUpsert<D1, S1 extends DbSelect<D1>, C extends DbCreate<D1>, U extends DbUpdate<D1>>(\n dbProxy: DbProxy<D1>,\n options: DbUpsertOptions<D1, S1, C, U>,\n): Promise<DbUpsertOutput> {\n const {\n where,\n select = {},\n create,\n update,\n onBeforeCreate,\n onAfterCreate,\n onBeforeUpdate,\n onAfterUpdate,\n _mockDbInstance,\n } = options;\n\n // @ts-ignore\n if ('_id' in select) throw new Error('select 条件不能包含 _id 字段');\n\n const _db = (_mockDbInstance || dbProxy) as DbProxy<D1>;\n const exist = (await _db\n .where(where)\n .select(select || {})\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n .queryOne(true)) as DbQuery<D1, S1, {}> | null;\n\n if (exist) {\n const skipUpdate = (await onBeforeUpdate?.(exist)) === false;\n\n if (skipUpdate) {\n // @ts-ignore\n return { id: exist._id as string, updated: false, created: false };\n }\n\n const updateData = isFunction(update) ? update(exist) : update;\n // @ts-ignore\n const updated = await _db.whereId(exist._id).update(updateData);\n onAfterUpdate?.(updateData, exist);\n\n // @ts-ignore\n return { id: exist._id as string, updated: true, created: false };\n }\n\n await onBeforeCreate?.();\n const createdId = await _db.create(create);\n await onAfterCreate?.(createdId);\n\n return { id: createdId, updated: false, created: true };\n}\n","import type { DbCreate, DbSelect, DbUpdate, DbWhere } from './_db.class';\nimport type { DbProxy } from './proxy';\nimport { dbUpsert } from './upsert';\n\nexport type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 创建数据 */\n create: C;\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUniqueOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n};\n\nexport async function dbUnique<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(\n dbProxy: DbProxy<T>,\n options: DbUniqueOptions<T, S, C, U>,\n): Promise<DbUniqueOutput> {\n const { id, created } = await dbUpsert(dbProxy, {\n ...options,\n // @ts-ignore\n update: {},\n onBeforeUpdate: () => false,\n });\n return { id, created };\n}\n","import { tryFlatten } from '@cloudcome/utils-core/try';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db, type DbSelect } from './_db.class';\nimport type { DbProxy } from './proxy';\n\ntype _TransactionDb = {\n startTransaction: () => Promise<_Transaction>;\n};\n\ntype _Transaction = {\n commit: () => Promise<unknown>;\n rollback: () => Promise<unknown>;\n};\n\nexport type WithTransaction = <D1>(table: DbProxy<D1>) => Db<D1>;\n\n/**\n * 在数据库事务中执行操作\n *\n * @template K - 事务操作返回值类型\n * @param transacting - 事务执行函数,接收事务数据库实例作为参数\n * @param _mockDatabase - 用于测试的模拟数据库对象\n * @param _mockDbInstance - 用于测试的模拟数据库实例\n * @returns 事务操作的返回结果\n *\n * @example\n * ```typescript\n * const result = await dbTransaction(async (withTransaction) => {\n * const userId = await withTransaction(db.table('user')).create({ name: 'John' });\n * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });\n * return { user, order };\n * });\n * ```\n */\nexport async function dbTransaction<K>(\n transacting: (withTransaction: WithTransaction) => Promise<K>,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any,\n) {\n const transactionDb = (_mockDatabase || uniCloud.database()) as _TransactionDb;\n\n const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());\n if (err1) throw err1;\n\n const withTransaction: WithTransaction = <D1>(dbProxy: DbProxy<D1>) => {\n return _mockDbInstance || new Db<D1>({ table: dbProxy.table, transaction });\n };\n\n const [err2, result] = await tryFlatten(async () => {\n const result = await transacting(withTransaction);\n await transaction.commit();\n return result;\n });\n\n if (err2) {\n await tryFlatten(transaction.rollback());\n throw err2;\n }\n\n return result as unknown as K;\n}\n"],"names":["isString","isNumber","type","objectMap","objectEach","isArray","parseDatabaseOutput","createCloudObjectError","isObject","isFunction","dbProxy","tryFlatten","result"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"database.cjs","sources":["../src/database/_command.class.ts","../src/database/command.ts","../src/database/_db.class.ts","../src/database/proxy.ts","../src/database/upsert.ts","../src/database/unique.ts","../src/database/transaction.ts"],"sourcesContent":["// 设置私有属性和静态方法是避免在 update 的时候提示类属性\n\nexport class DbBaseCommand {\n protected _isQuery = false;\n protected _isMutate = false;\n\n constructor(\n private _command: string,\n private _parameter: unknown,\n ) {}\n\n static getValue(cmd: DbBaseCommand, db: UniCloud.Database) {\n return (db.command as unknown as Record<string, (value: unknown) => unknown>)[cmd._command].call(\n db.command,\n cmd._parameter,\n );\n }\n\n static getExpression(cmd: DbBaseCommand, fieldName: string) {\n return {\n [`$${cmd._command}`]: [fieldName, cmd._parameter],\n };\n }\n\n static isQueryCommand(cmd: DbBaseCommand) {\n return cmd._isQuery;\n }\n\n static isMutateCommand(cmd: DbBaseCommand) {\n return cmd._isMutate;\n }\n}\n\nexport class DbQueryCommand extends DbBaseCommand {\n protected _isQuery = true;\n}\n\nexport class DbMutateCommand extends DbBaseCommand {\n protected _isMutate = true;\n}\n","import { DbMutateCommand, DbQueryCommand } from './_command.class';\n\n/**\n * 数据库查询命令对象,提供各种查询操作符\n */\nexport const dbQuery = {\n /**\n * 等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n eq: (value: unknown) => new DbQueryCommand('eq', value),\n\n /**\n * 不等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n neq: (value: unknown) => new DbQueryCommand('neq', value),\n\n /**\n * 大于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gt: (value: unknown) => new DbQueryCommand('gt', value),\n\n /**\n * 大于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gte: (value: unknown) => new DbQueryCommand('gte', value),\n\n /**\n * 小于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lt: (value: unknown) => new DbQueryCommand('lt', value),\n\n /**\n * 小于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lte: (value: unknown) => new DbQueryCommand('lte', value),\n\n /**\n * 包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n in: (value: unknown[]) => new DbQueryCommand('in', value),\n\n /**\n * 不包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n nin: (value: unknown[]) => new DbQueryCommand('nin', value),\n\n /**\n * 逻辑与操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n and: (conditions: unknown[]) => new DbQueryCommand('and', conditions),\n\n /**\n * 逻辑或操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n or: (conditions: unknown[]) => new DbQueryCommand('or', conditions),\n\n /**\n * 数组长度匹配操作符\n * @param size 数组长度\n * @returns DbQueryCommand 查询命令对象\n */\n size: (size: number) => new DbQueryCommand('size', size),\n};\n\n/**\n * 数据库变更命令对象,提供各种数据更新操作符\n */\nexport const dbMutate = {\n /**\n * 数值增加操作符\n * @param value 增加的数值\n * @returns DbMutateCommand 变更命令对象\n */\n inc: (value: number) => new DbMutateCommand('inc', value),\n\n /**\n * 数值乘法操作符\n * @param value 乘数\n * @returns DbMutateCommand 变更命令对象\n */\n mul: (value: number) => new DbMutateCommand('mul', value),\n\n /**\n * 设置字段值操作符\n * @param value 设置的值\n * @returns DbMutateCommand 变更命令对象\n */\n set: (value: unknown) => new DbMutateCommand('set', value),\n\n /**\n * 向数组末尾添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n push: (value: unknown) => new DbMutateCommand('push', value),\n\n /**\n * 向数组开头添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n unshift: (value: unknown) => new DbMutateCommand('unshift', value),\n\n /**\n * 从数组末尾移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n pop: () => new DbMutateCommand('pop', undefined),\n\n /**\n * 从数组开头移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n shift: () => new DbMutateCommand('shift', undefined),\n\n /**\n * 移除字段操作符\n * @returns DbMutateCommand 变更命令对象\n */\n remove: () => new DbMutateCommand('remove', undefined),\n};\n","import { parseDatabaseOutput } from '@/_helpers';\nimport { createCloudObjectError } from '@/cloud';\nimport { objectEach, objectMap } from '@cloudcome/utils-core/object';\nimport { isArray, isNumber, isObject, isString } from '@cloudcome/utils-core/type';\nimport type { AnyObject, MergeIntersection } from '@cloudcome/utils-core/types';\nimport { DbBaseCommand, type DbQueryCommand } from './_command.class';\nimport type { DbCreate, DbForeign, DbOrder, DbQuery, DbRelation, DbSelect, DbUpdate, DbWhere } from './types';\n\n/**\n * 数据库聚合操作符命令\n */\nconst dbAgg = uniCloud.database().command.aggregate as UniCloud.AggregateCommand & {\n pipeline: () => UniCloud.AggregateReference & {\n done: () => unknown;\n };\n};\n\ntype _WhereFrom = 'where' | 'whereId';\n\nconst db0 = uniCloud.database();\n\nexport type DbOptions = {\n /**\n * 数据表名称\n */\n table: string;\n\n /**\n * 事务对象,用于事务操作\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n transaction?: any;\n\n /**\n * 模拟数据库,用于单元测试\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any;\n};\n\n// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\nexport type DbLookupOptions<RL extends DbRelation, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {\n /**\n * 关联类型\n */\n relation: RL;\n\n /**\n * 主表字段\n */\n localField: keyof D1 & string;\n\n /**\n * 关联表字段\n */\n foreignField: keyof FD1 & string;\n\n /**\n * 关联数据在结果中的字段名\n */\n as: AS;\n\n /**\n * 是否取消筛选关联数据\n */\n unselect?: US;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport type DbLookup = DbLookupOptions<any, unknown, unknown, string, boolean> & {\n /**\n * 关联表\n */\n table: Db<unknown>;\n};\n\nlet gid = 0;\n\n/**\n * 数据库类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @template D2 - 副表数据\n * @template W2 - 副表查询\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject = {}, W2 extends AnyObject = {}> {\n private _host: UniCloud.CollectionReference;\n\n /**\n * 是否为事务环境\n * - 查询条件只能是 id\n * - 不能聚合操作\n */\n private _isTransaction = false;\n\n private _options: DbOptions;\n\n /**\n * 构造函数,初始化数据库集合引用\n * @param collection 数据表名称\n * @param _mockDatabase 模拟数据库,用于单元测试\n */\n constructor(options: DbOptions) {\n this._options = options;\n this._host =\n options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);\n this._isTransaction = !!options.transaction;\n }\n\n get table() {\n return this._options.table;\n }\n\n /**\n * 获取聚合操作实例\n * @returns 聚合操作实例\n */\n aggregate() {\n return this._host.aggregate();\n }\n\n private _hasWhere: _WhereFrom | undefined = undefined;\n private _hasWhereId: _WhereFrom | undefined = undefined;\n private _where = {};\n\n private _doWhere(where: DbWhere<D1>, from: _WhereFrom) {\n if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);\n\n const whereKeys = Object.keys(where);\n // 只有 _id 值为字符串或数字时,才能调用 doc 方法\n const isWhereId = whereKeys.length === 1 && '_id' in where && (isString(where._id) || isNumber(where._id));\n\n if (isWhereId && this._hasLimit) {\n throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);\n }\n\n this._hasWhere = from;\n this._where = where;\n if (isWhereId) this._hasWhereId = from;\n\n return this;\n }\n\n /**\n * 设置查询条件\n * @param where 查询条件对象\n * @returns 当前Db实例,支持链式调用\n */\n where(where: DbWhere<D1> & W2) {\n return this._doWhere(where, 'where');\n }\n\n /**\n * 根据ID设置查询条件\n * @param id 记录ID\n * @returns 当前Db实例,支持链式调用\n */\n whereId(id: string | number) {\n // @ts-ignore\n return this._doWhere({ _id: id }, 'whereId');\n }\n\n private _hasSelect = 0;\n private _select = {};\n\n /**\n * 指定要返回的字段\n * @param fields 要返回的字段对象,true表示返回,false表示不返回\n * @returns 当前Db实例,支持链式调用\n */\n select<const S extends DbSelect<D1>>(fields: S) {\n if (this._hasSelect) throw new Error('db.select() 方法只能调用一次');\n\n this._hasSelect++;\n this._select = fields;\n\n // @ts-ignore\n return this as Db<D1, S, D2, W2>;\n }\n\n private _hasOrder = 0;\n private _order = {};\n\n /**\n * 设置排序规则\n * @param order 排序规则对象,key为字段名,value为\"asc\"或\"desc\"\n * @returns 当前Db实例,支持链式调用\n */\n order(order: DbOrder<D1>) {\n this._hasOrder++;\n this._order = order;\n\n return this;\n }\n\n private _hasSkip = 0;\n private _skip = 0;\n\n /**\n * 跳过指定数量的记录\n * @param skip 要跳过的记录数\n * @returns 当前Db实例,支持链式调用\n */\n skip(skip: number) {\n if (this._hasSkip) throw new Error('db.skip() 方法只能调用一次');\n\n this._hasSkip++;\n this._skip = skip;\n\n return this;\n }\n\n private _hasLimit = 0;\n private _limit = 0;\n\n /**\n * 限制返回的记录数量\n * @param limit 最大返回记录数\n * @returns 当前Db实例,支持链式调用\n */\n limit(limit: number) {\n if (this._hasLimit) throw new Error('db.limit() 方法只能调用一次');\n\n if (this._hasWhereId) {\n throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);\n }\n\n this._hasLimit++;\n this._limit = limit;\n\n return this;\n }\n\n private _hasLookup = 0;\n get hasLookup() {\n return this._hasLookup > 0;\n }\n\n private _lookups: DbLookup[] = [];\n lookup<\n FD1,\n FS1 extends DbSelect<FD1>,\n FD2 extends AnyObject,\n FW2 extends AnyObject,\n RL extends DbRelation,\n AS extends string,\n // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\n US extends boolean | undefined | void = undefined,\n >(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<RL, D1, FD1, AS, US>) {\n // 对方表也记为关联查询,避免做表更新操作\n table._hasLookup++;\n this._hasLookup++;\n this._lookups.push({\n ...lookup,\n table,\n } as unknown as DbLookup);\n\n // @ts-ignore\n return this as Db<\n D1,\n S1,\n US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, RL, AS>>,\n MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>\n >;\n }\n\n private _aggregated = false;\n private _endAggregate(aggRef: UniCloud.AggregateReference) {\n if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);\n\n this._aggregated = true;\n let returnAggRef = aggRef;\n const projects: Record<string, true> = {};\n\n for (const { relation: type, as, foreignField, localField, table, unselect } of this._lookups) {\n const letName = `let${gid++}`;\n let pipeline = dbAgg.pipeline();\n\n // 关联条件\n // @ts-ignore\n pipeline = pipeline.match({\n $expr: {\n $and: [\n type === 'n:1'\n ? { $in: [`$${foreignField}`, `$$${letName}`] }\n : { $eq: [`$${foreignField}`, `$$${letName}`] },\n ],\n },\n });\n\n // 其他查询条件\n // @ts-ignore\n pipeline = table._endAggregate(pipeline);\n\n // @ts-ignore\n pipeline = pipeline.done();\n\n returnAggRef = returnAggRef.lookup({\n let: {\n [letName]: `$${localField}`,\n },\n as,\n from: table.table,\n pipeline,\n });\n\n // 1对1,展开数组\n if (type === '1:1') {\n // @ts-ignore\n returnAggRef = returnAggRef.unwind({\n path: `$${as}`,\n preserveNullAndEmptyArrays: true,\n });\n }\n\n if (as && !unselect) projects[as] = true;\n }\n\n // 主表查询\n if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));\n if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });\n if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => (v === 'asc' ? 1 : -1)));\n if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);\n if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);\n\n return returnAggRef;\n }\n\n private _endHost() {\n if (this._hasWhere) {\n // @ts-ignore\n this._host = this._host.where(_mapCommandRaw(this._where));\n }\n\n if (this._hasSelect) {\n // @ts-ignore\n this._host = this._host.field(this._select);\n }\n\n if (this._hasOrder) {\n objectEach(this._order, (val, key) => {\n // @ts-ignore\n this._host = this._host.orderBy(key, val);\n });\n }\n\n // @ts-ignore\n if (this._hasSkip) this._host = this._host.skip(this._skip);\n\n // @ts-ignore\n if (this._hasLimit) this._host = this._host.limit(this._limit);\n // @ts-ignore\n else if (this._hasWhereId) this._host = this._host.limit(1);\n }\n\n /**\n * 执行查询操作\n * @returns 查询结果\n */\n async query() {\n if (this._isTransaction) throw new Error('db.query() 方法不支持事务模式');\n\n let res: { data: DbQuery<D1, S1, D2>[] };\n\n // 关联查询\n if (this._hasLookup) {\n const aggRef = this.aggregate();\n this._endAggregate(aggRef);\n res = await aggRef.end();\n }\n // 单表查询\n else {\n this._endHost();\n res = await this._host.get();\n }\n\n const rows = isArray(res.data) ? res.data : [res.data];\n const { data } = parseDatabaseOutput(res);\n return data;\n }\n\n /**\n * 只查询一条,自动添加 limit(1) 条件\n * @param allowMiss 是否允许没有匹配到记录,如果为 true,则可能返回 null\n * @returns 查询结果\n */\n async queryOne(): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: false): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: true): Promise<DbQuery<D1, S1, D2> | null>;\n async queryOne(allowMiss = false): Promise<DbQuery<D1, S1, D2> | null> {\n if (this._isTransaction) throw new Error('db.queryOne() 方法不支持事务模式');\n if (this._hasLimit) throw new Error('db.queryOne() 方法不支持 limit 条件');\n if (!this._hasWhereId) this.limit(1);\n\n const data = await this.query();\n const res = data.at(0);\n\n if (!allowMiss && !res) throw createCloudObjectError('查询数据为空', 'queryOneNotFound');\n return res || null;\n }\n\n /**\n * 获取匹配记录的数量\n * @returns 记录总数\n */\n async count() {\n if (this._hasLookup) throw new Error('db.count() 方法不支持 lookup 聚合');\n if (this._hasSelect) throw new Error('db.count() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.count() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.count() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.count() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.count();\n const { total } = parseDatabaseOutput<{ total: number }>(res);\n return total;\n }\n\n /**\n * 创建新记录\n * @param data 要创建的数据\n * @returns 创建结果\n */\n async create(data: DbCreate<D1>) {\n if (this._hasLookup) throw new Error('db.create() 方法不支持 lookup 聚合');\n if (this._hasWhere) throw new Error('db.create() 方法不支持 where 条件');\n if (this._hasSelect) throw new Error('db.create() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.create() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.create() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.create() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.add(data);\n const { id } = parseDatabaseOutput<{ id: string }>(res);\n return id;\n }\n\n /**\n * 更新记录\n * @param data 要更新的数据\n * @returns 更新结果\n */\n async update(data: DbUpdate<D1>) {\n if (this._hasLookup) throw new Error('db.update() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.update() 方法');\n if (this._hasSelect) throw new Error('db.update() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.update() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.update() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.update() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.update() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.update(_mapCommandRaw(data));\n const { updated } = parseDatabaseOutput<{ updated: number }>(res);\n return updated;\n }\n\n /**\n * 删除记录\n * @returns 删除结果\n */\n async remove() {\n if (this._hasLookup) throw new Error('db.remove() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.remove() 方法');\n if (this._hasSelect) throw new Error('db.remove() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.remove() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.remove() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.remove() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.remove() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.remove();\n const { deleted } = parseDatabaseOutput<{ deleted: number }>(res);\n return deleted;\n }\n}\n\nfunction _toWhereMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({...})' : 'whereId(id)';\n}\n\nfunction _toWhereIdMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({ _id })' : 'whereId(id)';\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nfunction _mapCommandRaw(where: any) {\n return objectMap(where, (val, key) => {\n return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;\n });\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db } from './_db.class';\nimport type { DbSelect } from './types';\n\n/**\n * DbProxy 类型定义,用于创建数据库代理对象\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport type DbProxy<D1, S1 extends DbSelect<D1> = {}> = Db<D1, S1> & {\n _isProxy: true;\n};\n\n/**\n * 创建一个数据库代理对象,用于延迟实例化数据库操作类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @param name - 数据库表名\n * @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport function dbProxy<D1, S1 extends DbSelect<D1> = {}>(name: string) {\n return new Proxy(\n {},\n {\n get(target, prop) {\n if (prop === '_isProxy') return true;\n\n const table = new Db<D1, S1>({ table: name });\n const tableProp = prop as keyof Db<D1, S1>;\n const ref = table[tableProp];\n\n return isFunction(ref) ? ref.bind(table) : ref;\n },\n },\n ) as DbProxy<D1, S1>;\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { Exact } from '@cloudcome/utils-core/types';\nimport type { DbProxy } from './proxy';\nimport type { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './types';\n\nexport type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 查询返回字段 */\n select?: Exact<S, DbSelect<T>>;\n\n /** 创建数据 */\n create: C;\n\n /**\n * 更新数据,可以是对象或根据查询结果生成更新对象的函数\n * @param row 查询到的文档数据,仅在传入函数时可用\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n update: U | ((exist: DbQuery<T, S, {}>) => U);\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /**\n * 更新前回调函数\n * @param exist 查询到的原始文档数据\n * @returns 如果返回 false,则取消更新操作\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;\n\n /**\n * 更新后回调函数\n * @param updateData 实际更新的数据\n * @param exist 查询到的原始文档数据\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUpsertOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n /** 是否为更新操作 */\n updated: boolean;\n};\n\nexport async function dbUpsert<D1, S1 extends DbSelect<D1>, C extends DbCreate<D1>, U extends DbUpdate<D1>>(\n dbProxy: DbProxy<D1>,\n options: DbUpsertOptions<D1, S1, C, U>,\n): Promise<DbUpsertOutput> {\n const {\n where,\n select = {},\n create,\n update,\n onBeforeCreate,\n onAfterCreate,\n onBeforeUpdate,\n onAfterUpdate,\n _mockDbInstance,\n } = options;\n\n // @ts-ignore\n if ('_id' in select) throw new Error('select 条件不能包含 _id 字段');\n\n const _db = (_mockDbInstance || dbProxy) as DbProxy<D1>;\n const exist = (await _db\n .where(where)\n .select(select || {})\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n .queryOne(true)) as DbQuery<D1, S1, {}> | null;\n\n if (exist) {\n const skipUpdate = (await onBeforeUpdate?.(exist)) === false;\n\n if (skipUpdate) {\n // @ts-ignore\n return { id: exist._id as string, updated: false, created: false };\n }\n\n const updateData = isFunction(update) ? update(exist) : update;\n // @ts-ignore\n const updated = await _db.whereId(exist._id).update(updateData);\n onAfterUpdate?.(updateData, exist);\n\n // @ts-ignore\n return { id: exist._id as string, updated: true, created: false };\n }\n\n await onBeforeCreate?.();\n const createdId = await _db.create(create);\n await onAfterCreate?.(createdId);\n\n return { id: createdId, updated: false, created: true };\n}\n","import type { DbProxy } from './proxy';\nimport type { DbCreate, DbSelect, DbUpdate, DbWhere } from './types';\nimport { dbUpsert } from './upsert';\n\nexport type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 创建数据 */\n create: C;\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUniqueOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n};\n\nexport async function dbUnique<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(\n dbProxy: DbProxy<T>,\n options: DbUniqueOptions<T, S, C, U>,\n): Promise<DbUniqueOutput> {\n const { id, created } = await dbUpsert(dbProxy, {\n ...options,\n // @ts-ignore\n update: {},\n onBeforeUpdate: () => false,\n });\n return { id, created };\n}\n","import { tryFlatten } from '@cloudcome/utils-core/try';\nimport { Db } from './_db.class';\nimport type { DbProxy } from './proxy';\n\ntype _TransactionDb = {\n startTransaction: () => Promise<_Transaction>;\n};\n\ntype _Transaction = {\n commit: () => Promise<unknown>;\n rollback: () => Promise<unknown>;\n};\n\nexport type WithTransaction = <D1>(table: DbProxy<D1>) => Db<D1>;\n\n/**\n * 在数据库事务中执行操作\n *\n * @template K - 事务操作返回值类型\n * @param transacting - 事务执行函数,接收事务数据库实例作为参数\n * @param _mockDatabase - 用于测试的模拟数据库对象\n * @param _mockDbInstance - 用于测试的模拟数据库实例\n * @returns 事务操作的返回结果\n *\n * @example\n * ```typescript\n * const result = await dbTransaction(async (withTransaction) => {\n * const userId = await withTransaction(db.table('user')).create({ name: 'John' });\n * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });\n * return { user, order };\n * });\n * ```\n */\nexport async function dbTransaction<K>(\n transacting: (withTransaction: WithTransaction) => Promise<K>,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any,\n) {\n const transactionDb = (_mockDatabase || uniCloud.database()) as _TransactionDb;\n\n const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());\n if (err1) throw err1;\n\n const withTransaction: WithTransaction = <D1>(dbProxy: DbProxy<D1>) => {\n return _mockDbInstance || new Db<D1>({ table: dbProxy.table, transaction });\n };\n\n const [err2, result] = await tryFlatten(async () => {\n const result = await transacting(withTransaction);\n await transaction.commit();\n return result;\n });\n\n if (err2) {\n await tryFlatten(transaction.rollback());\n throw err2;\n }\n\n return result as unknown as K;\n}\n"],"names":["isString","isNumber","type","objectMap","objectEach","isArray","parseDatabaseOutput","createCloudObjectError","isObject","isFunction","dbProxy","tryFlatten","result"],"mappings":"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"}
|
package/dist/database.mjs
CHANGED
|
@@ -286,7 +286,7 @@ class Db {
|
|
|
286
286
|
this._aggregated = true;
|
|
287
287
|
let returnAggRef = aggRef;
|
|
288
288
|
const projects = {};
|
|
289
|
-
for (const { type, as, foreignField, localField, table, unselect } of this._lookups) {
|
|
289
|
+
for (const { relation: type, as, foreignField, localField, table, unselect } of this._lookups) {
|
|
290
290
|
const letName = `let${gid++}`;
|
|
291
291
|
let pipeline = dbAgg.pipeline();
|
|
292
292
|
pipeline = pipeline.match({
|
|
@@ -342,6 +342,7 @@ class Db {
|
|
|
342
342
|
* @returns 查询结果
|
|
343
343
|
*/
|
|
344
344
|
async query() {
|
|
345
|
+
if (this._isTransaction) throw new Error("db.query() 方法不支持事务模式");
|
|
345
346
|
let res;
|
|
346
347
|
if (this._hasLookup) {
|
|
347
348
|
const aggRef = this.aggregate();
|
|
@@ -356,6 +357,7 @@ class Db {
|
|
|
356
357
|
return data;
|
|
357
358
|
}
|
|
358
359
|
async queryOne(allowMiss = false) {
|
|
360
|
+
if (this._isTransaction) throw new Error("db.queryOne() 方法不支持事务模式");
|
|
359
361
|
if (this._hasLimit) throw new Error("db.queryOne() 方法不支持 limit 条件");
|
|
360
362
|
if (!this._hasWhereId) this.limit(1);
|
|
361
363
|
const data = await this.query();
|
package/dist/database.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.mjs","sources":["../src/database/_command.class.ts","../src/database/command.ts","../src/database/_db.class.ts","../src/database/proxy.ts","../src/database/upsert.ts","../src/database/unique.ts","../src/database/transaction.ts"],"sourcesContent":["// 设置私有属性和静态方法是避免在 update 的时候提示类属性\n\nexport class DbBaseCommand {\n protected _isQuery = false;\n protected _isMutate = false;\n\n constructor(\n private _command: string,\n private _parameter: unknown,\n ) {}\n\n static getValue(cmd: DbBaseCommand, db: UniCloud.Database) {\n return (db.command as unknown as Record<string, (value: unknown) => unknown>)[cmd._command].call(\n db.command,\n cmd._parameter,\n );\n }\n\n static getExpression(cmd: DbBaseCommand, fieldName: string) {\n return {\n [`$${cmd._command}`]: [fieldName, cmd._parameter],\n };\n }\n\n static isQueryCommand(cmd: DbBaseCommand) {\n return cmd._isQuery;\n }\n\n static isMutateCommand(cmd: DbBaseCommand) {\n return cmd._isMutate;\n }\n}\n\nexport class DbQueryCommand extends DbBaseCommand {\n protected _isQuery = true;\n}\n\nexport class DbMutateCommand extends DbBaseCommand {\n protected _isMutate = true;\n}\n","import { DbMutateCommand, DbQueryCommand } from './_command.class';\n\n/**\n * 数据库查询命令对象,提供各种查询操作符\n */\nexport const dbQuery = {\n /**\n * 等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n eq: (value: unknown) => new DbQueryCommand('eq', value),\n\n /**\n * 不等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n neq: (value: unknown) => new DbQueryCommand('neq', value),\n\n /**\n * 大于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gt: (value: unknown) => new DbQueryCommand('gt', value),\n\n /**\n * 大于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gte: (value: unknown) => new DbQueryCommand('gte', value),\n\n /**\n * 小于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lt: (value: unknown) => new DbQueryCommand('lt', value),\n\n /**\n * 小于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lte: (value: unknown) => new DbQueryCommand('lte', value),\n\n /**\n * 包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n in: (value: unknown[]) => new DbQueryCommand('in', value),\n\n /**\n * 不包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n nin: (value: unknown[]) => new DbQueryCommand('nin', value),\n\n /**\n * 逻辑与操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n and: (conditions: unknown[]) => new DbQueryCommand('and', conditions),\n\n /**\n * 逻辑或操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n or: (conditions: unknown[]) => new DbQueryCommand('or', conditions),\n\n /**\n * 数组长度匹配操作符\n * @param size 数组长度\n * @returns DbQueryCommand 查询命令对象\n */\n size: (size: number) => new DbQueryCommand('size', size),\n};\n\n/**\n * 数据库变更命令对象,提供各种数据更新操作符\n */\nexport const dbMutate = {\n /**\n * 数值增加操作符\n * @param value 增加的数值\n * @returns DbMutateCommand 变更命令对象\n */\n inc: (value: number) => new DbMutateCommand('inc', value),\n\n /**\n * 数值乘法操作符\n * @param value 乘数\n * @returns DbMutateCommand 变更命令对象\n */\n mul: (value: number) => new DbMutateCommand('mul', value),\n\n /**\n * 设置字段值操作符\n * @param value 设置的值\n * @returns DbMutateCommand 变更命令对象\n */\n set: (value: unknown) => new DbMutateCommand('set', value),\n\n /**\n * 向数组末尾添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n push: (value: unknown) => new DbMutateCommand('push', value),\n\n /**\n * 向数组开头添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n unshift: (value: unknown) => new DbMutateCommand('unshift', value),\n\n /**\n * 从数组末尾移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n pop: () => new DbMutateCommand('pop', undefined),\n\n /**\n * 从数组开头移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n shift: () => new DbMutateCommand('shift', undefined),\n\n /**\n * 移除字段操作符\n * @returns DbMutateCommand 变更命令对象\n */\n remove: () => new DbMutateCommand('remove', undefined),\n};\n","import { createCloudObjectError } from '@/cloud';\nimport { parseDatabaseOutput } from '@/database';\nimport { objectEach, objectMap } from '@cloudcome/utils-core/object';\nimport { isArray, isNumber, isObject, isString } from '@cloudcome/utils-core/type';\nimport type {\n AnyObject,\n Exact,\n HasProperty,\n IsEmptyObject,\n IsOnlyProperty,\n MergeIntersection,\n} from '@cloudcome/utils-core/types';\nimport { DbBaseCommand, type DbMutateCommand, type DbQueryCommand } from './_command.class';\n\n/**\n * 数据库聚合操作符命令\n */\nconst dbAgg = uniCloud.database().command.aggregate as UniCloud.AggregateCommand & {\n pipeline: () => UniCloud.AggregateReference & {\n done: () => unknown;\n };\n};\n\nexport type DbWhere<T> = {\n [K in keyof T]?: T[K] | DbQueryCommand;\n};\nexport type DbSelect<T> = {\n [K in keyof T]?: K extends '_id' ? boolean : true;\n};\nexport type DbFieldsDefault<T> = {\n [K in keyof T]: true;\n};\ntype _OnlyFieldId<D, V> = IsOnlyProperty<D, '_id'> extends true\n ? '_id' extends keyof D\n ? D['_id'] extends V\n ? true\n : false\n : false\n : false;\ntype _DbFields<D, S extends DbSelect<D>> = IsEmptyObject<S> extends true // 判断是否为空对象\n ? // 默认全部字段\n DbFieldsDefault<D>\n : // 判断 _id 是否为唯一属性 且 为 false\n _OnlyFieldId<S, false> extends true\n ? // 从默认字段里排除 _id\n Omit<DbFieldsDefault<D>, '_id'>\n : // 判断 _id 是否为唯一属性 且 为 true\n _OnlyFieldId<S, true> extends true\n ? // 只保留 _id\n { _id: true }\n : // 判断是否有 _id\n HasProperty<S, '_id'> extends true\n ? // 有的话保留 {_id, ...}\n S\n : // 没有的话补上 {_id, ...}\n S & { _id: true };\ntype _DbQuery<D1, S1 extends DbSelect<D1>> = {\n [K in keyof D1 as S1[K] extends true ? K : never]: D1[K];\n};\n// @ts-ignore\nexport type DbQuery<D1, S1 extends DbSelect<D1>, D2> = _DbQuery<D1, _DbFields<D1, S1>> & D2;\nexport type DbForeign<D1, S1 extends DbSelect<D1>, D2, JT extends DbJoinType, AS extends string> = Record<\n AS,\n JT extends '1:1' ? DbQuery<D1, S1, D2> : DbQuery<D1, S1, D2>[]\n>;\nexport type DbCreate<T> = Omit<T, '_id'> & { _id?: string };\nexport type DbUpdate<T> = T extends AnyObject\n ? {\n [K in keyof T]?: DbUpdate<T[K]> | DbMutateCommand;\n }\n : T;\nexport type DbOrder<T> = {\n [K in keyof T]?: 'asc' | 'desc';\n};\n\ntype _WhereFrom = 'where' | 'whereId';\n\nconst db0 = uniCloud.database();\n\nexport type DbOptions = {\n /**\n * 数据表名称\n */\n table: string;\n\n /**\n * 事务对象,用于事务操作\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n transaction?: any;\n\n /**\n * 模拟数据库,用于单元测试\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any;\n};\n\n/**\n * 数据库关联类型\n * - '1:1': 一对一关联,返回值 1 个\n * - '1:n': 一对多关联,返回值 n 个\n * - 'n:1': 多对一关联,返回值 n 个\n */\nexport type DbJoinType = '1:1' | '1:n' | 'n:1';\n// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\nexport type DbLookupOptions<JT extends DbJoinType, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {\n /**\n * 关联类型\n */\n type: JT;\n\n /**\n * 主表字段\n */\n localField: keyof D1 & string;\n\n /**\n * 关联表字段\n */\n foreignField: keyof FD1 & string;\n\n /**\n * 关联数据在结果中的字段名\n */\n as: AS;\n\n /**\n * 是否取消筛选关联数据\n */\n unselect?: US;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport type DbLookup = DbLookupOptions<any, unknown, unknown, string, boolean> & {\n /**\n * 关联表\n */\n table: Db<unknown>;\n};\n\nlet gid = 0;\n\n/**\n * 数据库类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @template D2 - 副表数据\n * @template W2 - 副表查询\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject = {}, W2 extends AnyObject = {}> {\n private _host: UniCloud.CollectionReference;\n\n /**\n * 是否为事务环境\n * - 查询条件只能是 id\n * - 不能聚合操作\n */\n private _isTransaction = false;\n\n private _options: DbOptions;\n\n /**\n * 构造函数,初始化数据库集合引用\n * @param collection 数据表名称\n * @param _mockDatabase 模拟数据库,用于单元测试\n */\n constructor(options: DbOptions) {\n this._options = options;\n this._host =\n options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);\n this._isTransaction = !!options.transaction;\n }\n\n get table() {\n return this._options.table;\n }\n\n /**\n * 获取聚合操作实例\n * @returns 聚合操作实例\n */\n aggregate() {\n return this._host.aggregate();\n }\n\n private _hasWhere: _WhereFrom | undefined = undefined;\n private _hasWhereId: _WhereFrom | undefined = undefined;\n private _where = {};\n\n private _doWhere(where: DbWhere<D1>, from: _WhereFrom) {\n if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);\n\n const whereKeys = Object.keys(where);\n // 只有 _id 值为字符串或数字时,才能调用 doc 方法\n const isWhereId = whereKeys.length === 1 && '_id' in where && (isString(where._id) || isNumber(where._id));\n\n if (isWhereId && this._hasLimit) {\n throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);\n }\n\n this._hasWhere = from;\n this._where = where;\n if (isWhereId) this._hasWhereId = from;\n\n return this;\n }\n\n /**\n * 设置查询条件\n * @param where 查询条件对象\n * @returns 当前Db实例,支持链式调用\n */\n where(where: DbWhere<D1> & W2) {\n return this._doWhere(where, 'where');\n }\n\n /**\n * 根据ID设置查询条件\n * @param id 记录ID\n * @returns 当前Db实例,支持链式调用\n */\n whereId(id: string | number) {\n // @ts-ignore\n return this._doWhere({ _id: id }, 'whereId');\n }\n\n private _hasSelect = 0;\n private _select = {};\n\n /**\n * 指定要返回的字段\n * @param fields 要返回的字段对象,true表示返回,false表示不返回\n * @returns 当前Db实例,支持链式调用\n */\n select<const S extends DbSelect<D1>>(fields: S) {\n if (this._hasSelect) throw new Error('db.select() 方法只能调用一次');\n\n this._hasSelect++;\n this._select = fields;\n\n // @ts-ignore\n return this as Db<D1, S, D2, W2>;\n }\n\n private _hasOrder = 0;\n private _order = {};\n\n /**\n * 设置排序规则\n * @param order 排序规则对象,key为字段名,value为\"asc\"或\"desc\"\n * @returns 当前Db实例,支持链式调用\n */\n order(order: DbOrder<D1>) {\n this._hasOrder++;\n this._order = order;\n\n return this;\n }\n\n private _hasSkip = 0;\n private _skip = 0;\n\n /**\n * 跳过指定数量的记录\n * @param skip 要跳过的记录数\n * @returns 当前Db实例,支持链式调用\n */\n skip(skip: number) {\n if (this._hasSkip) throw new Error('db.skip() 方法只能调用一次');\n\n this._hasSkip++;\n this._skip = skip;\n\n return this;\n }\n\n private _hasLimit = 0;\n private _limit = 0;\n\n /**\n * 限制返回的记录数量\n * @param limit 最大返回记录数\n * @returns 当前Db实例,支持链式调用\n */\n limit(limit: number) {\n if (this._hasLimit) throw new Error('db.limit() 方法只能调用一次');\n\n if (this._hasWhereId) {\n throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);\n }\n\n this._hasLimit++;\n this._limit = limit;\n\n return this;\n }\n\n private _hasLookup = 0;\n get hasLookup() {\n return this._hasLookup > 0;\n }\n\n private _lookups: DbLookup[] = [];\n lookup<\n FD1,\n FS1 extends DbSelect<FD1>,\n FD2 extends AnyObject,\n FW2 extends AnyObject,\n JT extends DbJoinType,\n AS extends string,\n // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\n US extends boolean | undefined | void = undefined,\n >(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<JT, D1, FD1, AS, US>) {\n // 对方表也记为关联查询,避免做表更新操作\n table._hasLookup++;\n this._hasLookup++;\n this._lookups.push({\n ...lookup,\n table,\n } as unknown as DbLookup);\n\n // @ts-ignore\n return this as Db<\n D1,\n S1,\n US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, JT, AS>>,\n MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>\n >;\n }\n\n private _aggregated = false;\n private _endAggregate(aggRef: UniCloud.AggregateReference) {\n if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);\n\n this._aggregated = true;\n let returnAggRef = aggRef;\n const projects: Record<string, true> = {};\n\n for (const { type, as, foreignField, localField, table, unselect } of this._lookups) {\n const letName = `let${gid++}`;\n let pipeline = dbAgg.pipeline();\n\n // 关联条件\n // @ts-ignore\n pipeline = pipeline.match({\n $expr: {\n $and: [\n type === 'n:1'\n ? { $in: [`$${foreignField}`, `$$${letName}`] }\n : { $eq: [`$${foreignField}`, `$$${letName}`] },\n ],\n },\n });\n\n // 其他查询条件\n // @ts-ignore\n pipeline = table._endAggregate(pipeline);\n\n // @ts-ignore\n pipeline = pipeline.done();\n\n returnAggRef = returnAggRef.lookup({\n let: {\n [letName]: `$${localField}`,\n },\n as,\n from: table.table,\n pipeline,\n });\n\n // 1对1,展开数组\n if (type === '1:1') {\n // @ts-ignore\n returnAggRef = returnAggRef.unwind({\n path: `$${as}`,\n preserveNullAndEmptyArrays: true,\n });\n }\n\n if (as && !unselect) projects[as] = true;\n }\n\n // 主表查询\n if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));\n if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });\n if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => (v === 'asc' ? 1 : -1)));\n if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);\n if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);\n\n return returnAggRef;\n }\n\n private _endHost() {\n if (this._hasWhere) {\n // @ts-ignore\n this._host = this._host.where(_mapCommandRaw(this._where));\n }\n\n if (this._hasSelect) {\n // @ts-ignore\n this._host = this._host.field(this._select);\n }\n\n if (this._hasOrder) {\n objectEach(this._order, (val, key) => {\n // @ts-ignore\n this._host = this._host.orderBy(key, val);\n });\n }\n\n // @ts-ignore\n if (this._hasSkip) this._host = this._host.skip(this._skip);\n\n // @ts-ignore\n if (this._hasLimit) this._host = this._host.limit(this._limit);\n // @ts-ignore\n else if (this._hasWhereId) this._host = this._host.limit(1);\n }\n\n /**\n * 执行查询操作\n * @returns 查询结果\n */\n async query() {\n let res: { data: DbQuery<D1, S1, D2>[] };\n\n // 关联查询\n if (this._hasLookup) {\n const aggRef = this.aggregate();\n this._endAggregate(aggRef);\n res = await aggRef.end();\n }\n // 单表查询\n else {\n this._endHost();\n res = await this._host.get();\n }\n\n const rows = isArray(res.data) ? res.data : [res.data];\n const { data } = parseDatabaseOutput(res);\n return data;\n }\n\n /**\n * 只查询一条,自动添加 limit(1) 条件\n * @param allowMiss 是否允许没有匹配到记录,如果为 true,则可能返回 null\n * @returns 查询结果\n */\n async queryOne(): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: false): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: true): Promise<DbQuery<D1, S1, D2> | null>;\n async queryOne(allowMiss = false): Promise<DbQuery<D1, S1, D2> | null> {\n if (this._hasLimit) throw new Error('db.queryOne() 方法不支持 limit 条件');\n if (!this._hasWhereId) this.limit(1);\n\n const data = await this.query();\n const res = data.at(0);\n\n if (!allowMiss && !res) throw createCloudObjectError('查询数据为空', 'queryOneNotFound');\n return res || null;\n }\n\n /**\n * 获取匹配记录的数量\n * @returns 记录总数\n */\n async count() {\n if (this._hasLookup) throw new Error('db.count() 方法不支持 lookup 聚合');\n if (this._hasSelect) throw new Error('db.count() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.count() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.count() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.count() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.count();\n const { total } = parseDatabaseOutput<{ total: number }>(res);\n return total;\n }\n\n /**\n * 创建新记录\n * @param data 要创建的数据\n * @returns 创建结果\n */\n async create(data: DbCreate<D1>) {\n if (this._hasLookup) throw new Error('db.create() 方法不支持 lookup 聚合');\n if (this._hasWhere) throw new Error('db.create() 方法不支持 where 条件');\n if (this._hasSelect) throw new Error('db.create() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.create() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.create() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.create() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.add(data);\n const { id } = parseDatabaseOutput<{ id: string }>(res);\n return id;\n }\n\n /**\n * 更新记录\n * @param data 要更新的数据\n * @returns 更新结果\n */\n async update(data: DbUpdate<D1>) {\n if (this._hasLookup) throw new Error('db.update() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.update() 方法');\n if (this._hasSelect) throw new Error('db.update() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.update() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.update() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.update() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.update() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.update(_mapCommandRaw(data));\n const { updated } = parseDatabaseOutput<{ updated: number }>(res);\n return updated;\n }\n\n /**\n * 删除记录\n * @returns 删除结果\n */\n async remove() {\n if (this._hasLookup) throw new Error('db.remove() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.remove() 方法');\n if (this._hasSelect) throw new Error('db.remove() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.remove() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.remove() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.remove() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.remove() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.remove();\n const { deleted } = parseDatabaseOutput<{ deleted: number }>(res);\n return deleted;\n }\n}\n\nfunction _toWhereMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({...})' : 'whereId(id)';\n}\n\nfunction _toWhereIdMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({ _id })' : 'whereId(id)';\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nfunction _mapCommandRaw(where: any) {\n return objectMap(where, (val, key) => {\n return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;\n });\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db, type DbSelect } from './_db.class';\n\n/**\n * DbProxy 类型定义,用于创建数据库代理对象\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport type DbProxy<D1, S1 extends DbSelect<D1> = {}> = Db<D1, S1> & {\n _isProxy: true;\n};\n\n/**\n * 创建一个数据库代理对象,用于延迟实例化数据库操作类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @param name - 数据库表名\n * @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport function dbProxy<D1, S1 extends DbSelect<D1> = {}>(name: string) {\n return new Proxy(\n {},\n {\n get(target, prop) {\n if (prop === '_isProxy') return true;\n\n const table = new Db<D1, S1>({ table: name });\n const tableProp = prop as keyof Db<D1, S1>;\n const ref = table[tableProp];\n\n return isFunction(ref) ? ref.bind(table) : ref;\n },\n },\n ) as DbProxy<D1, S1>;\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { Exact } from '@cloudcome/utils-core/types';\nimport type { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './_db.class';\nimport type { DbProxy } from './proxy';\n\nexport type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 查询返回字段 */\n select?: Exact<S, DbSelect<T>>;\n\n /** 创建数据 */\n create: C;\n\n /**\n * 更新数据,可以是对象或根据查询结果生成更新对象的函数\n * @param row 查询到的文档数据,仅在传入函数时可用\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n update: U | ((exist: DbQuery<T, S, {}>) => U);\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /**\n * 更新前回调函数\n * @param exist 查询到的原始文档数据\n * @returns 如果返回 false,则取消更新操作\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;\n\n /**\n * 更新后回调函数\n * @param updateData 实际更新的数据\n * @param exist 查询到的原始文档数据\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUpsertOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n /** 是否为更新操作 */\n updated: boolean;\n};\n\nexport async function dbUpsert<D1, S1 extends DbSelect<D1>, C extends DbCreate<D1>, U extends DbUpdate<D1>>(\n dbProxy: DbProxy<D1>,\n options: DbUpsertOptions<D1, S1, C, U>,\n): Promise<DbUpsertOutput> {\n const {\n where,\n select = {},\n create,\n update,\n onBeforeCreate,\n onAfterCreate,\n onBeforeUpdate,\n onAfterUpdate,\n _mockDbInstance,\n } = options;\n\n // @ts-ignore\n if ('_id' in select) throw new Error('select 条件不能包含 _id 字段');\n\n const _db = (_mockDbInstance || dbProxy) as DbProxy<D1>;\n const exist = (await _db\n .where(where)\n .select(select || {})\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n .queryOne(true)) as DbQuery<D1, S1, {}> | null;\n\n if (exist) {\n const skipUpdate = (await onBeforeUpdate?.(exist)) === false;\n\n if (skipUpdate) {\n // @ts-ignore\n return { id: exist._id as string, updated: false, created: false };\n }\n\n const updateData = isFunction(update) ? update(exist) : update;\n // @ts-ignore\n const updated = await _db.whereId(exist._id).update(updateData);\n onAfterUpdate?.(updateData, exist);\n\n // @ts-ignore\n return { id: exist._id as string, updated: true, created: false };\n }\n\n await onBeforeCreate?.();\n const createdId = await _db.create(create);\n await onAfterCreate?.(createdId);\n\n return { id: createdId, updated: false, created: true };\n}\n","import type { DbCreate, DbSelect, DbUpdate, DbWhere } from './_db.class';\nimport type { DbProxy } from './proxy';\nimport { dbUpsert } from './upsert';\n\nexport type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 创建数据 */\n create: C;\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUniqueOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n};\n\nexport async function dbUnique<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(\n dbProxy: DbProxy<T>,\n options: DbUniqueOptions<T, S, C, U>,\n): Promise<DbUniqueOutput> {\n const { id, created } = await dbUpsert(dbProxy, {\n ...options,\n // @ts-ignore\n update: {},\n onBeforeUpdate: () => false,\n });\n return { id, created };\n}\n","import { tryFlatten } from '@cloudcome/utils-core/try';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db, type DbSelect } from './_db.class';\nimport type { DbProxy } from './proxy';\n\ntype _TransactionDb = {\n startTransaction: () => Promise<_Transaction>;\n};\n\ntype _Transaction = {\n commit: () => Promise<unknown>;\n rollback: () => Promise<unknown>;\n};\n\nexport type WithTransaction = <D1>(table: DbProxy<D1>) => Db<D1>;\n\n/**\n * 在数据库事务中执行操作\n *\n * @template K - 事务操作返回值类型\n * @param transacting - 事务执行函数,接收事务数据库实例作为参数\n * @param _mockDatabase - 用于测试的模拟数据库对象\n * @param _mockDbInstance - 用于测试的模拟数据库实例\n * @returns 事务操作的返回结果\n *\n * @example\n * ```typescript\n * const result = await dbTransaction(async (withTransaction) => {\n * const userId = await withTransaction(db.table('user')).create({ name: 'John' });\n * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });\n * return { user, order };\n * });\n * ```\n */\nexport async function dbTransaction<K>(\n transacting: (withTransaction: WithTransaction) => Promise<K>,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any,\n) {\n const transactionDb = (_mockDatabase || uniCloud.database()) as _TransactionDb;\n\n const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());\n if (err1) throw err1;\n\n const withTransaction: WithTransaction = <D1>(dbProxy: DbProxy<D1>) => {\n return _mockDbInstance || new Db<D1>({ table: dbProxy.table, transaction });\n };\n\n const [err2, result] = await tryFlatten(async () => {\n const result = await transacting(withTransaction);\n await transaction.commit();\n return result;\n });\n\n if (err2) {\n await tryFlatten(transaction.rollback());\n throw err2;\n }\n\n return result as unknown as K;\n}\n"],"names":["dbProxy","result"],"mappings":";;;;;AAEO,MAAM,cAAc;AAAA,EAIzB,YACU,UACA,YACR;AAFQ,SAAA,WAAA;AACA,SAAA,aAAA;AAAA,EAAA;AAAA,EALA,WAAW;AAAA,EACX,YAAY;AAAA,EAOtB,OAAO,SAAS,KAAoB,IAAuB;AACzD,WAAQ,GAAG,QAAmE,IAAI,QAAQ,EAAE;AAAA,MAC1F,GAAG;AAAA,MACH,IAAI;AAAA,IACN;AAAA,EAAA;AAAA,EAGF,OAAO,cAAc,KAAoB,WAAmB;AACnD,WAAA;AAAA,MACL,CAAC,IAAI,IAAI,QAAQ,EAAE,GAAG,CAAC,WAAW,IAAI,UAAU;AAAA,IAClD;AAAA,EAAA;AAAA,EAGF,OAAO,eAAe,KAAoB;AACxC,WAAO,IAAI;AAAA,EAAA;AAAA,EAGb,OAAO,gBAAgB,KAAoB;AACzC,WAAO,IAAI;AAAA,EAAA;AAEf;AAEO,MAAM,uBAAuB,cAAc;AAAA,EACtC,WAAW;AACvB;AAEO,MAAM,wBAAwB,cAAc;AAAA,EACvC,YAAY;AACxB;AClCO,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,IAAI,CAAC,UAAmB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,KAAK,CAAC,UAAmB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,IAAI,CAAC,UAAmB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,KAAK,CAAC,UAAmB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,IAAI,CAAC,UAAmB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,KAAK,CAAC,UAAmB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,IAAI,CAAC,UAAqB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,KAAK,CAAC,UAAqB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1D,KAAK,CAAC,eAA0B,IAAI,eAAe,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpE,IAAI,CAAC,eAA0B,IAAI,eAAe,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlE,MAAM,CAAC,SAAiB,IAAI,eAAe,QAAQ,IAAI;AACzD;AAKO,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtB,KAAK,CAAC,UAAkB,IAAI,gBAAgB,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,KAAK,CAAC,UAAkB,IAAI,gBAAgB,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,KAAK,CAAC,UAAmB,IAAI,gBAAgB,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzD,MAAM,CAAC,UAAmB,IAAI,gBAAgB,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3D,SAAS,CAAC,UAAmB,IAAI,gBAAgB,WAAW,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjE,KAAK,MAAM,IAAI,gBAAgB,OAAO,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/C,OAAO,MAAM,IAAI,gBAAgB,SAAS,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,QAAQ,MAAM,IAAI,gBAAgB,UAAU,MAAS;AACvD;AC3HA,MAAM,QAAQ,SAAS,SAAS,EAAE,QAAQ;AA4D1C,MAAM,MAAM,SAAS,SAAS;AAgE9B,IAAI,MAAM;AAUH,MAAM,GAA2F;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YAAY,SAAoB;AAC9B,SAAK,WAAW;AAChB,SAAK,QACH,QAAQ,iBAAiB,QAAQ,aAAa,WAAW,QAAQ,KAAK,KAAK,IAAI,WAAW,QAAQ,KAAK;AACpG,SAAA,iBAAiB,CAAC,CAAC,QAAQ;AAAA,EAAA;AAAA,EAGlC,IAAI,QAAQ;AACV,WAAO,KAAK,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOvB,YAAY;AACH,WAAA,KAAK,MAAM,UAAU;AAAA,EAAA;AAAA,EAGtB,YAAoC;AAAA,EACpC,cAAsC;AAAA,EACtC,SAAS,CAAC;AAAA,EAEV,SAAS,OAAoB,MAAkB;AACjD,QAAA,KAAK,UAAW,OAAM,IAAI,MAAM,aAAa,eAAe,KAAK,SAAS,CAAC,IAAI;AAE7E,UAAA,YAAY,OAAO,KAAK,KAAK;AAEnC,UAAM,YAAY,UAAU,WAAW,KAAK,SAAS,UAAU,SAAS,MAAM,GAAG,KAAK,SAAS,MAAM,GAAG;AAEpG,QAAA,aAAa,KAAK,WAAW;AAC/B,YAAM,IAAI,MAAM,MAAM,iBAAiB,IAAI,CAAC,0BAA0B;AAAA,IAAA;AAGxE,SAAK,YAAY;AACjB,SAAK,SAAS;AACV,QAAA,gBAAgB,cAAc;AAE3B,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAM,OAAyB;AACtB,WAAA,KAAK,SAAS,OAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrC,QAAQ,IAAqB;AAE3B,WAAO,KAAK,SAAS,EAAE,KAAK,GAAA,GAAM,SAAS;AAAA,EAAA;AAAA,EAGrC,aAAa;AAAA,EACb,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnB,OAAqC,QAAW;AAC9C,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,sBAAsB;AAEtD,SAAA;AACL,SAAK,UAAU;AAGR,WAAA;AAAA,EAAA;AAAA,EAGD,YAAY;AAAA,EACZ,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlB,MAAM,OAAoB;AACnB,SAAA;AACL,SAAK,SAAS;AAEP,WAAA;AAAA,EAAA;AAAA,EAGD,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,KAAK,MAAc;AACjB,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,oBAAoB;AAElD,SAAA;AACL,SAAK,QAAQ;AAEN,WAAA;AAAA,EAAA;AAAA,EAGD,YAAY;AAAA,EACZ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjB,MAAM,OAAe;AACnB,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,qBAAqB;AAEzD,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,oBAAoB,iBAAiB,KAAK,WAAW,CAAC,SAAS;AAAA,IAAA;AAG5E,SAAA;AACL,SAAK,SAAS;AAEP,WAAA;AAAA,EAAA;AAAA,EAGD,aAAa;AAAA,EACrB,IAAI,YAAY;AACd,WAAO,KAAK,aAAa;AAAA,EAAA;AAAA,EAGnB,WAAuB,CAAC;AAAA,EAChC,OASE,OAA+B,QAA8C;AAEvE,UAAA;AACD,SAAA;AACL,SAAK,SAAS,KAAK;AAAA,MACjB,GAAG;AAAA,MACH;AAAA,IAAA,CACsB;AAGjB,WAAA;AAAA,EAAA;AAAA,EAQD,cAAc;AAAA,EACd,cAAc,QAAqC;AACrD,QAAA,KAAK,YAAmB,OAAA,IAAI,MAAM,YAAY,KAAK,KAAK,SAAS;AAErE,SAAK,cAAc;AACnB,QAAI,eAAe;AACnB,UAAM,WAAiC,CAAC;AAE7B,eAAA,EAAE,MAAM,IAAI,cAAc,YAAY,OAAO,SAAA,KAAc,KAAK,UAAU;AAC7E,YAAA,UAAU,MAAM,KAAK;AACvB,UAAA,WAAW,MAAM,SAAS;AAI9B,iBAAW,SAAS,MAAM;AAAA,QACxB,OAAO;AAAA,UACL,MAAM;AAAA,YACJ,SAAS,QACL,EAAE,KAAK,CAAC,IAAI,YAAY,IAAI,KAAK,OAAO,EAAE,MAC1C,EAAE,KAAK,CAAC,IAAI,YAAY,IAAI,KAAK,OAAO,EAAE,EAAE;AAAA,UAAA;AAAA,QAClD;AAAA,MACF,CACD;AAIU,iBAAA,MAAM,cAAc,QAAQ;AAGvC,iBAAW,SAAS,KAAK;AAEzB,qBAAe,aAAa,OAAO;AAAA,QACjC,KAAK;AAAA,UACH,CAAC,OAAO,GAAG,IAAI,UAAU;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,MAAM,MAAM;AAAA,QACZ;AAAA,MAAA,CACD;AAGD,UAAI,SAAS,OAAO;AAElB,uBAAe,aAAa,OAAO;AAAA,UACjC,MAAM,IAAI,EAAE;AAAA,UACZ,4BAA4B;AAAA,QAAA,CAC7B;AAAA,MAAA;AAGH,UAAI,MAAM,CAAC,SAAU,UAAS,EAAE,IAAI;AAAA,IAAA;AAIlC,QAAA,KAAK,UAA0B,gBAAA,aAAa,MAAM,eAAe,KAAK,MAAM,CAAC;AAC7E,QAAA,KAAK,WAAY,gBAAe,aAAa,QAAQ,EAAE,GAAG,KAAK,SAAS,GAAG,UAAU;AACzF,QAAI,KAAK,UAA0B,gBAAA,aAAa,KAAK,UAAU,KAAK,QAAQ,CAAC,MAAO,MAAM,QAAQ,IAAI,EAAG,CAAC;AAC1G,QAAI,KAAK,SAAU,gBAAe,aAAa,KAAK,KAAK,KAAK;AAC9D,QAAI,KAAK,UAAW,gBAAe,aAAa,MAAM,KAAK,MAAM;AAE1D,WAAA;AAAA,EAAA;AAAA,EAGD,WAAW;AACjB,QAAI,KAAK,WAAW;AAElB,WAAK,QAAQ,KAAK,MAAM,MAAM,eAAe,KAAK,MAAM,CAAC;AAAA,IAAA;AAG3D,QAAI,KAAK,YAAY;AAEnB,WAAK,QAAQ,KAAK,MAAM,MAAM,KAAK,OAAO;AAAA,IAAA;AAG5C,QAAI,KAAK,WAAW;AAClB,iBAAW,KAAK,QAAQ,CAAC,KAAK,QAAQ;AAEpC,aAAK,QAAQ,KAAK,MAAM,QAAQ,KAAK,GAAG;AAAA,MAAA,CACzC;AAAA,IAAA;AAIC,QAAA,KAAK,SAAe,MAAA,QAAQ,KAAK,MAAM,KAAK,KAAK,KAAK;AAGtD,QAAA,KAAK,UAAgB,MAAA,QAAQ,KAAK,MAAM,MAAM,KAAK,MAAM;AAAA,aAEpD,KAAK,YAAa,MAAK,QAAQ,KAAK,MAAM,MAAM,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5D,MAAM,QAAQ;AACR,QAAA;AAGJ,QAAI,KAAK,YAAY;AACb,YAAA,SAAS,KAAK,UAAU;AAC9B,WAAK,cAAc,MAAM;AACnB,YAAA,MAAM,OAAO,IAAI;AAAA,IAAA,OAGpB;AACH,WAAK,SAAS;AACR,YAAA,MAAM,KAAK,MAAM,IAAI;AAAA,IAAA;AAGhB,YAAQ,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,IAAI;AACrD,UAAM,EAAE,KAAA,IAAS,oBAAoB,GAAG;AACjC,WAAA;AAAA,EAAA;AAAA,EAWT,MAAM,SAAS,YAAY,OAA4C;AACrE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,8BAA8B;AAClE,QAAI,CAAC,KAAK,YAAa,MAAK,MAAM,CAAC;AAE7B,UAAA,OAAO,MAAM,KAAK,MAAM;AACxB,UAAA,MAAM,KAAK,GAAG,CAAC;AAErB,QAAI,CAAC,aAAa,CAAC,IAAW,OAAA,uBAAuB,UAAU,kBAAkB;AACjF,WAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,MAAM,QAAQ;AACZ,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,4BAA4B;AACjE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,4BAA4B;AACjE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,2BAA2B;AAC/D,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,0BAA0B;AAC7D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,2BAA2B;AAE/D,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,MAAM;AACnC,UAAM,EAAE,MAAA,IAAU,oBAAuC,GAAG;AACrD,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAM,OAAO,MAAoB;AAC/B,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,2BAA2B;AAC9D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAEhE,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,IAAI,IAAI;AACrC,UAAM,EAAE,GAAA,IAAO,oBAAoC,GAAG;AAC/C,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAM,OAAO,MAAoB;AAC/B,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,CAAC,KAAK,UAAiB,OAAA,IAAI,MAAM,iCAAiC;AACtE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,2BAA2B;AAC9D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAE5D,QAAA,KAAK,kBAAkB,CAAC,KAAK,YAAmB,OAAA,IAAI,MAAM,qCAAqC;AAEnG,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,OAAO,eAAe,IAAI,CAAC;AACxD,UAAM,EAAE,QAAA,IAAY,oBAAyC,GAAG;AACzD,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,MAAM,SAAS;AACb,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,CAAC,KAAK,UAAiB,OAAA,IAAI,MAAM,iCAAiC;AACtE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,2BAA2B;AAC9D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAE5D,QAAA,KAAK,kBAAkB,CAAC,KAAK,YAAmB,OAAA,IAAI,MAAM,qCAAqC;AAEnG,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,OAAO;AACpC,UAAM,EAAE,QAAA,IAAY,oBAAyC,GAAG;AACzD,WAAA;AAAA,EAAA;AAEX;AAEA,SAAS,eAAe,WAAuB;AACtC,SAAA,cAAc,UAAU,iBAAiB;AAClD;AAEA,SAAS,iBAAiB,WAAuB;AACxC,SAAA,cAAc,UAAU,mBAAmB;AACpD;AAGA,SAAS,eAAe,OAAY;AAClC,SAAO,UAAU,OAAO,CAAC,KAAK,QAAQ;AAC7B,WAAA,SAAS,GAAG,KAAK,eAAe,gBAAgB,cAAc,SAAS,KAAK,GAAG,IAAI;AAAA,EAAA,CAC3F;AACH;ACrhBO,SAAS,QAA0C,MAAc;AACtE,SAAO,IAAI;AAAA,IACT,CAAC;AAAA,IACD;AAAA,MACE,IAAI,QAAQ,MAAM;AACZ,YAAA,SAAS,WAAmB,QAAA;AAEhC,cAAM,QAAQ,IAAI,GAAW,EAAE,OAAO,MAAM;AAC5C,cAAM,YAAY;AACZ,cAAA,MAAM,MAAM,SAAS;AAE3B,eAAO,WAAW,GAAG,IAAI,IAAI,KAAK,KAAK,IAAI;AAAA,MAAA;AAAA,IAC7C;AAAA,EAEJ;AACF;AC2BsB,eAAA,SACpBA,UACA,SACyB;AACnB,QAAA;AAAA,IACJ;AAAA,IACA,SAAS,CAAC;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAGJ,MAAI,SAAS,OAAc,OAAA,IAAI,MAAM,sBAAsB;AAE3D,QAAM,MAAO,mBAAmBA;AAChC,QAAM,QAAS,MAAM,IAClB,MAAM,KAAK,EACX,OAAO,UAAU,CAAA,CAAE,EAEnB,SAAS,IAAI;AAEhB,MAAI,OAAO;AACT,UAAM,aAAc,MAAM,iBAAiB,KAAK,MAAO;AAEvD,QAAI,YAAY;AAEd,aAAO,EAAE,IAAI,MAAM,KAAe,SAAS,OAAO,SAAS,MAAM;AAAA,IAAA;AAGnE,UAAM,aAAa,WAAW,MAAM,IAAI,OAAO,KAAK,IAAI;AAExC,UAAM,IAAI,QAAQ,MAAM,GAAG,EAAE,OAAO,UAAU;AAC9D,oBAAgB,YAAY,KAAK;AAGjC,WAAO,EAAE,IAAI,MAAM,KAAe,SAAS,MAAM,SAAS,MAAM;AAAA,EAAA;AAGlE,QAAM,iBAAiB;AACvB,QAAM,YAAY,MAAM,IAAI,OAAO,MAAM;AACzC,QAAM,gBAAgB,SAAS;AAE/B,SAAO,EAAE,IAAI,WAAW,SAAS,OAAO,SAAS,KAAK;AACxD;AC7EsB,eAAA,SACpBA,UACA,SACyB;AACzB,QAAM,EAAE,IAAI,QAAY,IAAA,MAAM,SAASA,UAAS;AAAA,IAC9C,GAAG;AAAA;AAAA,IAEH,QAAQ,CAAC;AAAA,IACT,gBAAgB,MAAM;AAAA,EAAA,CACvB;AACM,SAAA,EAAE,IAAI,QAAQ;AACvB;ACZsB,eAAA,cACpB,aAEA,eAEA,iBACA;AACM,QAAA,gBAAiB,iBAAiB,SAAS,SAAS;AAEpD,QAAA,CAAC,MAAM,WAAW,IAAI,MAAM,WAAW,cAAc,kBAAkB;AAC7E,MAAI,KAAY,OAAA;AAEV,QAAA,kBAAmC,CAAKA,aAAyB;AAC9D,WAAA,mBAAmB,IAAI,GAAO,EAAE,OAAOA,SAAQ,OAAO,aAAa;AAAA,EAC5E;AAEA,QAAM,CAAC,MAAM,MAAM,IAAI,MAAM,WAAW,YAAY;AAC5CC,UAAAA,UAAS,MAAM,YAAY,eAAe;AAChD,UAAM,YAAY,OAAO;AAClBA,WAAAA;AAAAA,EAAA,CACR;AAED,MAAI,MAAM;AACF,UAAA,WAAW,YAAY,UAAU;AACjC,UAAA;AAAA,EAAA;AAGD,SAAA;AACT;"}
|
|
1
|
+
{"version":3,"file":"database.mjs","sources":["../src/database/_command.class.ts","../src/database/command.ts","../src/database/_db.class.ts","../src/database/proxy.ts","../src/database/upsert.ts","../src/database/unique.ts","../src/database/transaction.ts"],"sourcesContent":["// 设置私有属性和静态方法是避免在 update 的时候提示类属性\n\nexport class DbBaseCommand {\n protected _isQuery = false;\n protected _isMutate = false;\n\n constructor(\n private _command: string,\n private _parameter: unknown,\n ) {}\n\n static getValue(cmd: DbBaseCommand, db: UniCloud.Database) {\n return (db.command as unknown as Record<string, (value: unknown) => unknown>)[cmd._command].call(\n db.command,\n cmd._parameter,\n );\n }\n\n static getExpression(cmd: DbBaseCommand, fieldName: string) {\n return {\n [`$${cmd._command}`]: [fieldName, cmd._parameter],\n };\n }\n\n static isQueryCommand(cmd: DbBaseCommand) {\n return cmd._isQuery;\n }\n\n static isMutateCommand(cmd: DbBaseCommand) {\n return cmd._isMutate;\n }\n}\n\nexport class DbQueryCommand extends DbBaseCommand {\n protected _isQuery = true;\n}\n\nexport class DbMutateCommand extends DbBaseCommand {\n protected _isMutate = true;\n}\n","import { DbMutateCommand, DbQueryCommand } from './_command.class';\n\n/**\n * 数据库查询命令对象,提供各种查询操作符\n */\nexport const dbQuery = {\n /**\n * 等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n eq: (value: unknown) => new DbQueryCommand('eq', value),\n\n /**\n * 不等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n neq: (value: unknown) => new DbQueryCommand('neq', value),\n\n /**\n * 大于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gt: (value: unknown) => new DbQueryCommand('gt', value),\n\n /**\n * 大于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gte: (value: unknown) => new DbQueryCommand('gte', value),\n\n /**\n * 小于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lt: (value: unknown) => new DbQueryCommand('lt', value),\n\n /**\n * 小于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lte: (value: unknown) => new DbQueryCommand('lte', value),\n\n /**\n * 包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n in: (value: unknown[]) => new DbQueryCommand('in', value),\n\n /**\n * 不包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n nin: (value: unknown[]) => new DbQueryCommand('nin', value),\n\n /**\n * 逻辑与操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n and: (conditions: unknown[]) => new DbQueryCommand('and', conditions),\n\n /**\n * 逻辑或操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n or: (conditions: unknown[]) => new DbQueryCommand('or', conditions),\n\n /**\n * 数组长度匹配操作符\n * @param size 数组长度\n * @returns DbQueryCommand 查询命令对象\n */\n size: (size: number) => new DbQueryCommand('size', size),\n};\n\n/**\n * 数据库变更命令对象,提供各种数据更新操作符\n */\nexport const dbMutate = {\n /**\n * 数值增加操作符\n * @param value 增加的数值\n * @returns DbMutateCommand 变更命令对象\n */\n inc: (value: number) => new DbMutateCommand('inc', value),\n\n /**\n * 数值乘法操作符\n * @param value 乘数\n * @returns DbMutateCommand 变更命令对象\n */\n mul: (value: number) => new DbMutateCommand('mul', value),\n\n /**\n * 设置字段值操作符\n * @param value 设置的值\n * @returns DbMutateCommand 变更命令对象\n */\n set: (value: unknown) => new DbMutateCommand('set', value),\n\n /**\n * 向数组末尾添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n push: (value: unknown) => new DbMutateCommand('push', value),\n\n /**\n * 向数组开头添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n unshift: (value: unknown) => new DbMutateCommand('unshift', value),\n\n /**\n * 从数组末尾移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n pop: () => new DbMutateCommand('pop', undefined),\n\n /**\n * 从数组开头移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n shift: () => new DbMutateCommand('shift', undefined),\n\n /**\n * 移除字段操作符\n * @returns DbMutateCommand 变更命令对象\n */\n remove: () => new DbMutateCommand('remove', undefined),\n};\n","import { parseDatabaseOutput } from '@/_helpers';\nimport { createCloudObjectError } from '@/cloud';\nimport { objectEach, objectMap } from '@cloudcome/utils-core/object';\nimport { isArray, isNumber, isObject, isString } from '@cloudcome/utils-core/type';\nimport type { AnyObject, MergeIntersection } from '@cloudcome/utils-core/types';\nimport { DbBaseCommand, type DbQueryCommand } from './_command.class';\nimport type { DbCreate, DbForeign, DbOrder, DbQuery, DbRelation, DbSelect, DbUpdate, DbWhere } from './types';\n\n/**\n * 数据库聚合操作符命令\n */\nconst dbAgg = uniCloud.database().command.aggregate as UniCloud.AggregateCommand & {\n pipeline: () => UniCloud.AggregateReference & {\n done: () => unknown;\n };\n};\n\ntype _WhereFrom = 'where' | 'whereId';\n\nconst db0 = uniCloud.database();\n\nexport type DbOptions = {\n /**\n * 数据表名称\n */\n table: string;\n\n /**\n * 事务对象,用于事务操作\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n transaction?: any;\n\n /**\n * 模拟数据库,用于单元测试\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any;\n};\n\n// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\nexport type DbLookupOptions<RL extends DbRelation, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {\n /**\n * 关联类型\n */\n relation: RL;\n\n /**\n * 主表字段\n */\n localField: keyof D1 & string;\n\n /**\n * 关联表字段\n */\n foreignField: keyof FD1 & string;\n\n /**\n * 关联数据在结果中的字段名\n */\n as: AS;\n\n /**\n * 是否取消筛选关联数据\n */\n unselect?: US;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport type DbLookup = DbLookupOptions<any, unknown, unknown, string, boolean> & {\n /**\n * 关联表\n */\n table: Db<unknown>;\n};\n\nlet gid = 0;\n\n/**\n * 数据库类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @template D2 - 副表数据\n * @template W2 - 副表查询\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject = {}, W2 extends AnyObject = {}> {\n private _host: UniCloud.CollectionReference;\n\n /**\n * 是否为事务环境\n * - 查询条件只能是 id\n * - 不能聚合操作\n */\n private _isTransaction = false;\n\n private _options: DbOptions;\n\n /**\n * 构造函数,初始化数据库集合引用\n * @param collection 数据表名称\n * @param _mockDatabase 模拟数据库,用于单元测试\n */\n constructor(options: DbOptions) {\n this._options = options;\n this._host =\n options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);\n this._isTransaction = !!options.transaction;\n }\n\n get table() {\n return this._options.table;\n }\n\n /**\n * 获取聚合操作实例\n * @returns 聚合操作实例\n */\n aggregate() {\n return this._host.aggregate();\n }\n\n private _hasWhere: _WhereFrom | undefined = undefined;\n private _hasWhereId: _WhereFrom | undefined = undefined;\n private _where = {};\n\n private _doWhere(where: DbWhere<D1>, from: _WhereFrom) {\n if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);\n\n const whereKeys = Object.keys(where);\n // 只有 _id 值为字符串或数字时,才能调用 doc 方法\n const isWhereId = whereKeys.length === 1 && '_id' in where && (isString(where._id) || isNumber(where._id));\n\n if (isWhereId && this._hasLimit) {\n throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);\n }\n\n this._hasWhere = from;\n this._where = where;\n if (isWhereId) this._hasWhereId = from;\n\n return this;\n }\n\n /**\n * 设置查询条件\n * @param where 查询条件对象\n * @returns 当前Db实例,支持链式调用\n */\n where(where: DbWhere<D1> & W2) {\n return this._doWhere(where, 'where');\n }\n\n /**\n * 根据ID设置查询条件\n * @param id 记录ID\n * @returns 当前Db实例,支持链式调用\n */\n whereId(id: string | number) {\n // @ts-ignore\n return this._doWhere({ _id: id }, 'whereId');\n }\n\n private _hasSelect = 0;\n private _select = {};\n\n /**\n * 指定要返回的字段\n * @param fields 要返回的字段对象,true表示返回,false表示不返回\n * @returns 当前Db实例,支持链式调用\n */\n select<const S extends DbSelect<D1>>(fields: S) {\n if (this._hasSelect) throw new Error('db.select() 方法只能调用一次');\n\n this._hasSelect++;\n this._select = fields;\n\n // @ts-ignore\n return this as Db<D1, S, D2, W2>;\n }\n\n private _hasOrder = 0;\n private _order = {};\n\n /**\n * 设置排序规则\n * @param order 排序规则对象,key为字段名,value为\"asc\"或\"desc\"\n * @returns 当前Db实例,支持链式调用\n */\n order(order: DbOrder<D1>) {\n this._hasOrder++;\n this._order = order;\n\n return this;\n }\n\n private _hasSkip = 0;\n private _skip = 0;\n\n /**\n * 跳过指定数量的记录\n * @param skip 要跳过的记录数\n * @returns 当前Db实例,支持链式调用\n */\n skip(skip: number) {\n if (this._hasSkip) throw new Error('db.skip() 方法只能调用一次');\n\n this._hasSkip++;\n this._skip = skip;\n\n return this;\n }\n\n private _hasLimit = 0;\n private _limit = 0;\n\n /**\n * 限制返回的记录数量\n * @param limit 最大返回记录数\n * @returns 当前Db实例,支持链式调用\n */\n limit(limit: number) {\n if (this._hasLimit) throw new Error('db.limit() 方法只能调用一次');\n\n if (this._hasWhereId) {\n throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);\n }\n\n this._hasLimit++;\n this._limit = limit;\n\n return this;\n }\n\n private _hasLookup = 0;\n get hasLookup() {\n return this._hasLookup > 0;\n }\n\n private _lookups: DbLookup[] = [];\n lookup<\n FD1,\n FS1 extends DbSelect<FD1>,\n FD2 extends AnyObject,\n FW2 extends AnyObject,\n RL extends DbRelation,\n AS extends string,\n // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\n US extends boolean | undefined | void = undefined,\n >(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<RL, D1, FD1, AS, US>) {\n // 对方表也记为关联查询,避免做表更新操作\n table._hasLookup++;\n this._hasLookup++;\n this._lookups.push({\n ...lookup,\n table,\n } as unknown as DbLookup);\n\n // @ts-ignore\n return this as Db<\n D1,\n S1,\n US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, RL, AS>>,\n MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>\n >;\n }\n\n private _aggregated = false;\n private _endAggregate(aggRef: UniCloud.AggregateReference) {\n if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);\n\n this._aggregated = true;\n let returnAggRef = aggRef;\n const projects: Record<string, true> = {};\n\n for (const { relation: type, as, foreignField, localField, table, unselect } of this._lookups) {\n const letName = `let${gid++}`;\n let pipeline = dbAgg.pipeline();\n\n // 关联条件\n // @ts-ignore\n pipeline = pipeline.match({\n $expr: {\n $and: [\n type === 'n:1'\n ? { $in: [`$${foreignField}`, `$$${letName}`] }\n : { $eq: [`$${foreignField}`, `$$${letName}`] },\n ],\n },\n });\n\n // 其他查询条件\n // @ts-ignore\n pipeline = table._endAggregate(pipeline);\n\n // @ts-ignore\n pipeline = pipeline.done();\n\n returnAggRef = returnAggRef.lookup({\n let: {\n [letName]: `$${localField}`,\n },\n as,\n from: table.table,\n pipeline,\n });\n\n // 1对1,展开数组\n if (type === '1:1') {\n // @ts-ignore\n returnAggRef = returnAggRef.unwind({\n path: `$${as}`,\n preserveNullAndEmptyArrays: true,\n });\n }\n\n if (as && !unselect) projects[as] = true;\n }\n\n // 主表查询\n if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));\n if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });\n if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => (v === 'asc' ? 1 : -1)));\n if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);\n if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);\n\n return returnAggRef;\n }\n\n private _endHost() {\n if (this._hasWhere) {\n // @ts-ignore\n this._host = this._host.where(_mapCommandRaw(this._where));\n }\n\n if (this._hasSelect) {\n // @ts-ignore\n this._host = this._host.field(this._select);\n }\n\n if (this._hasOrder) {\n objectEach(this._order, (val, key) => {\n // @ts-ignore\n this._host = this._host.orderBy(key, val);\n });\n }\n\n // @ts-ignore\n if (this._hasSkip) this._host = this._host.skip(this._skip);\n\n // @ts-ignore\n if (this._hasLimit) this._host = this._host.limit(this._limit);\n // @ts-ignore\n else if (this._hasWhereId) this._host = this._host.limit(1);\n }\n\n /**\n * 执行查询操作\n * @returns 查询结果\n */\n async query() {\n if (this._isTransaction) throw new Error('db.query() 方法不支持事务模式');\n\n let res: { data: DbQuery<D1, S1, D2>[] };\n\n // 关联查询\n if (this._hasLookup) {\n const aggRef = this.aggregate();\n this._endAggregate(aggRef);\n res = await aggRef.end();\n }\n // 单表查询\n else {\n this._endHost();\n res = await this._host.get();\n }\n\n const rows = isArray(res.data) ? res.data : [res.data];\n const { data } = parseDatabaseOutput(res);\n return data;\n }\n\n /**\n * 只查询一条,自动添加 limit(1) 条件\n * @param allowMiss 是否允许没有匹配到记录,如果为 true,则可能返回 null\n * @returns 查询结果\n */\n async queryOne(): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: false): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: true): Promise<DbQuery<D1, S1, D2> | null>;\n async queryOne(allowMiss = false): Promise<DbQuery<D1, S1, D2> | null> {\n if (this._isTransaction) throw new Error('db.queryOne() 方法不支持事务模式');\n if (this._hasLimit) throw new Error('db.queryOne() 方法不支持 limit 条件');\n if (!this._hasWhereId) this.limit(1);\n\n const data = await this.query();\n const res = data.at(0);\n\n if (!allowMiss && !res) throw createCloudObjectError('查询数据为空', 'queryOneNotFound');\n return res || null;\n }\n\n /**\n * 获取匹配记录的数量\n * @returns 记录总数\n */\n async count() {\n if (this._hasLookup) throw new Error('db.count() 方法不支持 lookup 聚合');\n if (this._hasSelect) throw new Error('db.count() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.count() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.count() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.count() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.count();\n const { total } = parseDatabaseOutput<{ total: number }>(res);\n return total;\n }\n\n /**\n * 创建新记录\n * @param data 要创建的数据\n * @returns 创建结果\n */\n async create(data: DbCreate<D1>) {\n if (this._hasLookup) throw new Error('db.create() 方法不支持 lookup 聚合');\n if (this._hasWhere) throw new Error('db.create() 方法不支持 where 条件');\n if (this._hasSelect) throw new Error('db.create() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.create() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.create() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.create() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.add(data);\n const { id } = parseDatabaseOutput<{ id: string }>(res);\n return id;\n }\n\n /**\n * 更新记录\n * @param data 要更新的数据\n * @returns 更新结果\n */\n async update(data: DbUpdate<D1>) {\n if (this._hasLookup) throw new Error('db.update() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.update() 方法');\n if (this._hasSelect) throw new Error('db.update() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.update() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.update() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.update() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.update() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.update(_mapCommandRaw(data));\n const { updated } = parseDatabaseOutput<{ updated: number }>(res);\n return updated;\n }\n\n /**\n * 删除记录\n * @returns 删除结果\n */\n async remove() {\n if (this._hasLookup) throw new Error('db.remove() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.remove() 方法');\n if (this._hasSelect) throw new Error('db.remove() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.remove() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.remove() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.remove() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.remove() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.remove();\n const { deleted } = parseDatabaseOutput<{ deleted: number }>(res);\n return deleted;\n }\n}\n\nfunction _toWhereMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({...})' : 'whereId(id)';\n}\n\nfunction _toWhereIdMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({ _id })' : 'whereId(id)';\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nfunction _mapCommandRaw(where: any) {\n return objectMap(where, (val, key) => {\n return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;\n });\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db } from './_db.class';\nimport type { DbSelect } from './types';\n\n/**\n * DbProxy 类型定义,用于创建数据库代理对象\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport type DbProxy<D1, S1 extends DbSelect<D1> = {}> = Db<D1, S1> & {\n _isProxy: true;\n};\n\n/**\n * 创建一个数据库代理对象,用于延迟实例化数据库操作类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @param name - 数据库表名\n * @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport function dbProxy<D1, S1 extends DbSelect<D1> = {}>(name: string) {\n return new Proxy(\n {},\n {\n get(target, prop) {\n if (prop === '_isProxy') return true;\n\n const table = new Db<D1, S1>({ table: name });\n const tableProp = prop as keyof Db<D1, S1>;\n const ref = table[tableProp];\n\n return isFunction(ref) ? ref.bind(table) : ref;\n },\n },\n ) as DbProxy<D1, S1>;\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { Exact } from '@cloudcome/utils-core/types';\nimport type { DbProxy } from './proxy';\nimport type { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './types';\n\nexport type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 查询返回字段 */\n select?: Exact<S, DbSelect<T>>;\n\n /** 创建数据 */\n create: C;\n\n /**\n * 更新数据,可以是对象或根据查询结果生成更新对象的函数\n * @param row 查询到的文档数据,仅在传入函数时可用\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n update: U | ((exist: DbQuery<T, S, {}>) => U);\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /**\n * 更新前回调函数\n * @param exist 查询到的原始文档数据\n * @returns 如果返回 false,则取消更新操作\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;\n\n /**\n * 更新后回调函数\n * @param updateData 实际更新的数据\n * @param exist 查询到的原始文档数据\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUpsertOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n /** 是否为更新操作 */\n updated: boolean;\n};\n\nexport async function dbUpsert<D1, S1 extends DbSelect<D1>, C extends DbCreate<D1>, U extends DbUpdate<D1>>(\n dbProxy: DbProxy<D1>,\n options: DbUpsertOptions<D1, S1, C, U>,\n): Promise<DbUpsertOutput> {\n const {\n where,\n select = {},\n create,\n update,\n onBeforeCreate,\n onAfterCreate,\n onBeforeUpdate,\n onAfterUpdate,\n _mockDbInstance,\n } = options;\n\n // @ts-ignore\n if ('_id' in select) throw new Error('select 条件不能包含 _id 字段');\n\n const _db = (_mockDbInstance || dbProxy) as DbProxy<D1>;\n const exist = (await _db\n .where(where)\n .select(select || {})\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n .queryOne(true)) as DbQuery<D1, S1, {}> | null;\n\n if (exist) {\n const skipUpdate = (await onBeforeUpdate?.(exist)) === false;\n\n if (skipUpdate) {\n // @ts-ignore\n return { id: exist._id as string, updated: false, created: false };\n }\n\n const updateData = isFunction(update) ? update(exist) : update;\n // @ts-ignore\n const updated = await _db.whereId(exist._id).update(updateData);\n onAfterUpdate?.(updateData, exist);\n\n // @ts-ignore\n return { id: exist._id as string, updated: true, created: false };\n }\n\n await onBeforeCreate?.();\n const createdId = await _db.create(create);\n await onAfterCreate?.(createdId);\n\n return { id: createdId, updated: false, created: true };\n}\n","import type { DbProxy } from './proxy';\nimport type { DbCreate, DbSelect, DbUpdate, DbWhere } from './types';\nimport { dbUpsert } from './upsert';\n\nexport type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 创建数据 */\n create: C;\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUniqueOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n};\n\nexport async function dbUnique<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(\n dbProxy: DbProxy<T>,\n options: DbUniqueOptions<T, S, C, U>,\n): Promise<DbUniqueOutput> {\n const { id, created } = await dbUpsert(dbProxy, {\n ...options,\n // @ts-ignore\n update: {},\n onBeforeUpdate: () => false,\n });\n return { id, created };\n}\n","import { tryFlatten } from '@cloudcome/utils-core/try';\nimport { Db } from './_db.class';\nimport type { DbProxy } from './proxy';\n\ntype _TransactionDb = {\n startTransaction: () => Promise<_Transaction>;\n};\n\ntype _Transaction = {\n commit: () => Promise<unknown>;\n rollback: () => Promise<unknown>;\n};\n\nexport type WithTransaction = <D1>(table: DbProxy<D1>) => Db<D1>;\n\n/**\n * 在数据库事务中执行操作\n *\n * @template K - 事务操作返回值类型\n * @param transacting - 事务执行函数,接收事务数据库实例作为参数\n * @param _mockDatabase - 用于测试的模拟数据库对象\n * @param _mockDbInstance - 用于测试的模拟数据库实例\n * @returns 事务操作的返回结果\n *\n * @example\n * ```typescript\n * const result = await dbTransaction(async (withTransaction) => {\n * const userId = await withTransaction(db.table('user')).create({ name: 'John' });\n * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });\n * return { user, order };\n * });\n * ```\n */\nexport async function dbTransaction<K>(\n transacting: (withTransaction: WithTransaction) => Promise<K>,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any,\n) {\n const transactionDb = (_mockDatabase || uniCloud.database()) as _TransactionDb;\n\n const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());\n if (err1) throw err1;\n\n const withTransaction: WithTransaction = <D1>(dbProxy: DbProxy<D1>) => {\n return _mockDbInstance || new Db<D1>({ table: dbProxy.table, transaction });\n };\n\n const [err2, result] = await tryFlatten(async () => {\n const result = await transacting(withTransaction);\n await transaction.commit();\n return result;\n });\n\n if (err2) {\n await tryFlatten(transaction.rollback());\n throw err2;\n }\n\n return result as unknown as K;\n}\n"],"names":["dbProxy","result"],"mappings":";;;;;AAEO,MAAM,cAAc;AAAA,EAIzB,YACU,UACA,YACR;AAFQ,SAAA,WAAA;AACA,SAAA,aAAA;AAAA,EAAA;AAAA,EALA,WAAW;AAAA,EACX,YAAY;AAAA,EAOtB,OAAO,SAAS,KAAoB,IAAuB;AACzD,WAAQ,GAAG,QAAmE,IAAI,QAAQ,EAAE;AAAA,MAC1F,GAAG;AAAA,MACH,IAAI;AAAA,IACN;AAAA,EAAA;AAAA,EAGF,OAAO,cAAc,KAAoB,WAAmB;AACnD,WAAA;AAAA,MACL,CAAC,IAAI,IAAI,QAAQ,EAAE,GAAG,CAAC,WAAW,IAAI,UAAU;AAAA,IAClD;AAAA,EAAA;AAAA,EAGF,OAAO,eAAe,KAAoB;AACxC,WAAO,IAAI;AAAA,EAAA;AAAA,EAGb,OAAO,gBAAgB,KAAoB;AACzC,WAAO,IAAI;AAAA,EAAA;AAEf;AAEO,MAAM,uBAAuB,cAAc;AAAA,EACtC,WAAW;AACvB;AAEO,MAAM,wBAAwB,cAAc;AAAA,EACvC,YAAY;AACxB;AClCO,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,IAAI,CAAC,UAAmB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,KAAK,CAAC,UAAmB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,IAAI,CAAC,UAAmB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,KAAK,CAAC,UAAmB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,IAAI,CAAC,UAAmB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,KAAK,CAAC,UAAmB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,IAAI,CAAC,UAAqB,IAAI,eAAe,MAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,KAAK,CAAC,UAAqB,IAAI,eAAe,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1D,KAAK,CAAC,eAA0B,IAAI,eAAe,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpE,IAAI,CAAC,eAA0B,IAAI,eAAe,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlE,MAAM,CAAC,SAAiB,IAAI,eAAe,QAAQ,IAAI;AACzD;AAKO,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtB,KAAK,CAAC,UAAkB,IAAI,gBAAgB,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,KAAK,CAAC,UAAkB,IAAI,gBAAgB,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,KAAK,CAAC,UAAmB,IAAI,gBAAgB,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzD,MAAM,CAAC,UAAmB,IAAI,gBAAgB,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3D,SAAS,CAAC,UAAmB,IAAI,gBAAgB,WAAW,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjE,KAAK,MAAM,IAAI,gBAAgB,OAAO,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/C,OAAO,MAAM,IAAI,gBAAgB,SAAS,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,QAAQ,MAAM,IAAI,gBAAgB,UAAU,MAAS;AACvD;ACjIA,MAAM,QAAQ,SAAS,SAAS,EAAE,QAAQ;AAQ1C,MAAM,MAAM,SAAS,SAAS;AAyD9B,IAAI,MAAM;AAUH,MAAM,GAA2F;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YAAY,SAAoB;AAC9B,SAAK,WAAW;AAChB,SAAK,QACH,QAAQ,iBAAiB,QAAQ,aAAa,WAAW,QAAQ,KAAK,KAAK,IAAI,WAAW,QAAQ,KAAK;AACpG,SAAA,iBAAiB,CAAC,CAAC,QAAQ;AAAA,EAAA;AAAA,EAGlC,IAAI,QAAQ;AACV,WAAO,KAAK,SAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOvB,YAAY;AACH,WAAA,KAAK,MAAM,UAAU;AAAA,EAAA;AAAA,EAGtB,YAAoC;AAAA,EACpC,cAAsC;AAAA,EACtC,SAAS,CAAC;AAAA,EAEV,SAAS,OAAoB,MAAkB;AACjD,QAAA,KAAK,UAAW,OAAM,IAAI,MAAM,aAAa,eAAe,KAAK,SAAS,CAAC,IAAI;AAE7E,UAAA,YAAY,OAAO,KAAK,KAAK;AAEnC,UAAM,YAAY,UAAU,WAAW,KAAK,SAAS,UAAU,SAAS,MAAM,GAAG,KAAK,SAAS,MAAM,GAAG;AAEpG,QAAA,aAAa,KAAK,WAAW;AAC/B,YAAM,IAAI,MAAM,MAAM,iBAAiB,IAAI,CAAC,0BAA0B;AAAA,IAAA;AAGxE,SAAK,YAAY;AACjB,SAAK,SAAS;AACV,QAAA,gBAAgB,cAAc;AAE3B,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAM,OAAyB;AACtB,WAAA,KAAK,SAAS,OAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrC,QAAQ,IAAqB;AAE3B,WAAO,KAAK,SAAS,EAAE,KAAK,GAAA,GAAM,SAAS;AAAA,EAAA;AAAA,EAGrC,aAAa;AAAA,EACb,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnB,OAAqC,QAAW;AAC9C,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,sBAAsB;AAEtD,SAAA;AACL,SAAK,UAAU;AAGR,WAAA;AAAA,EAAA;AAAA,EAGD,YAAY;AAAA,EACZ,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlB,MAAM,OAAoB;AACnB,SAAA;AACL,SAAK,SAAS;AAEP,WAAA;AAAA,EAAA;AAAA,EAGD,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,KAAK,MAAc;AACjB,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,oBAAoB;AAElD,SAAA;AACL,SAAK,QAAQ;AAEN,WAAA;AAAA,EAAA;AAAA,EAGD,YAAY;AAAA,EACZ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjB,MAAM,OAAe;AACnB,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,qBAAqB;AAEzD,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,oBAAoB,iBAAiB,KAAK,WAAW,CAAC,SAAS;AAAA,IAAA;AAG5E,SAAA;AACL,SAAK,SAAS;AAEP,WAAA;AAAA,EAAA;AAAA,EAGD,aAAa;AAAA,EACrB,IAAI,YAAY;AACd,WAAO,KAAK,aAAa;AAAA,EAAA;AAAA,EAGnB,WAAuB,CAAC;AAAA,EAChC,OASE,OAA+B,QAA8C;AAEvE,UAAA;AACD,SAAA;AACL,SAAK,SAAS,KAAK;AAAA,MACjB,GAAG;AAAA,MACH;AAAA,IAAA,CACsB;AAGjB,WAAA;AAAA,EAAA;AAAA,EAQD,cAAc;AAAA,EACd,cAAc,QAAqC;AACrD,QAAA,KAAK,YAAmB,OAAA,IAAI,MAAM,YAAY,KAAK,KAAK,SAAS;AAErE,SAAK,cAAc;AACnB,QAAI,eAAe;AACnB,UAAM,WAAiC,CAAC;AAE7B,eAAA,EAAE,UAAU,MAAM,IAAI,cAAc,YAAY,OAAO,cAAc,KAAK,UAAU;AACvF,YAAA,UAAU,MAAM,KAAK;AACvB,UAAA,WAAW,MAAM,SAAS;AAI9B,iBAAW,SAAS,MAAM;AAAA,QACxB,OAAO;AAAA,UACL,MAAM;AAAA,YACJ,SAAS,QACL,EAAE,KAAK,CAAC,IAAI,YAAY,IAAI,KAAK,OAAO,EAAE,MAC1C,EAAE,KAAK,CAAC,IAAI,YAAY,IAAI,KAAK,OAAO,EAAE,EAAE;AAAA,UAAA;AAAA,QAClD;AAAA,MACF,CACD;AAIU,iBAAA,MAAM,cAAc,QAAQ;AAGvC,iBAAW,SAAS,KAAK;AAEzB,qBAAe,aAAa,OAAO;AAAA,QACjC,KAAK;AAAA,UACH,CAAC,OAAO,GAAG,IAAI,UAAU;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,MAAM,MAAM;AAAA,QACZ;AAAA,MAAA,CACD;AAGD,UAAI,SAAS,OAAO;AAElB,uBAAe,aAAa,OAAO;AAAA,UACjC,MAAM,IAAI,EAAE;AAAA,UACZ,4BAA4B;AAAA,QAAA,CAC7B;AAAA,MAAA;AAGH,UAAI,MAAM,CAAC,SAAU,UAAS,EAAE,IAAI;AAAA,IAAA;AAIlC,QAAA,KAAK,UAA0B,gBAAA,aAAa,MAAM,eAAe,KAAK,MAAM,CAAC;AAC7E,QAAA,KAAK,WAAY,gBAAe,aAAa,QAAQ,EAAE,GAAG,KAAK,SAAS,GAAG,UAAU;AACzF,QAAI,KAAK,UAA0B,gBAAA,aAAa,KAAK,UAAU,KAAK,QAAQ,CAAC,MAAO,MAAM,QAAQ,IAAI,EAAG,CAAC;AAC1G,QAAI,KAAK,SAAU,gBAAe,aAAa,KAAK,KAAK,KAAK;AAC9D,QAAI,KAAK,UAAW,gBAAe,aAAa,MAAM,KAAK,MAAM;AAE1D,WAAA;AAAA,EAAA;AAAA,EAGD,WAAW;AACjB,QAAI,KAAK,WAAW;AAElB,WAAK,QAAQ,KAAK,MAAM,MAAM,eAAe,KAAK,MAAM,CAAC;AAAA,IAAA;AAG3D,QAAI,KAAK,YAAY;AAEnB,WAAK,QAAQ,KAAK,MAAM,MAAM,KAAK,OAAO;AAAA,IAAA;AAG5C,QAAI,KAAK,WAAW;AAClB,iBAAW,KAAK,QAAQ,CAAC,KAAK,QAAQ;AAEpC,aAAK,QAAQ,KAAK,MAAM,QAAQ,KAAK,GAAG;AAAA,MAAA,CACzC;AAAA,IAAA;AAIC,QAAA,KAAK,SAAe,MAAA,QAAQ,KAAK,MAAM,KAAK,KAAK,KAAK;AAGtD,QAAA,KAAK,UAAgB,MAAA,QAAQ,KAAK,MAAM,MAAM,KAAK,MAAM;AAAA,aAEpD,KAAK,YAAa,MAAK,QAAQ,KAAK,MAAM,MAAM,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5D,MAAM,QAAQ;AACZ,QAAI,KAAK,eAAsB,OAAA,IAAI,MAAM,sBAAsB;AAE3D,QAAA;AAGJ,QAAI,KAAK,YAAY;AACb,YAAA,SAAS,KAAK,UAAU;AAC9B,WAAK,cAAc,MAAM;AACnB,YAAA,MAAM,OAAO,IAAI;AAAA,IAAA,OAGpB;AACH,WAAK,SAAS;AACR,YAAA,MAAM,KAAK,MAAM,IAAI;AAAA,IAAA;AAGhB,YAAQ,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,IAAI;AACrD,UAAM,EAAE,KAAA,IAAS,oBAAoB,GAAG;AACjC,WAAA;AAAA,EAAA;AAAA,EAWT,MAAM,SAAS,YAAY,OAA4C;AACrE,QAAI,KAAK,eAAsB,OAAA,IAAI,MAAM,yBAAyB;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,8BAA8B;AAClE,QAAI,CAAC,KAAK,YAAa,MAAK,MAAM,CAAC;AAE7B,UAAA,OAAO,MAAM,KAAK,MAAM;AACxB,UAAA,MAAM,KAAK,GAAG,CAAC;AAErB,QAAI,CAAC,aAAa,CAAC,IAAW,OAAA,uBAAuB,UAAU,kBAAkB;AACjF,WAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,MAAM,QAAQ;AACZ,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,4BAA4B;AACjE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,4BAA4B;AACjE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,2BAA2B;AAC/D,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,0BAA0B;AAC7D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,2BAA2B;AAE/D,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,MAAM;AACnC,UAAM,EAAE,MAAA,IAAU,oBAAuC,GAAG;AACrD,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAM,OAAO,MAAoB;AAC/B,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,2BAA2B;AAC9D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAEhE,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,IAAI,IAAI;AACrC,UAAM,EAAE,GAAA,IAAO,oBAAoC,GAAG;AAC/C,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAM,OAAO,MAAoB;AAC/B,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,CAAC,KAAK,UAAiB,OAAA,IAAI,MAAM,iCAAiC;AACtE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,2BAA2B;AAC9D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAE5D,QAAA,KAAK,kBAAkB,CAAC,KAAK,YAAmB,OAAA,IAAI,MAAM,qCAAqC;AAEnG,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,OAAO,eAAe,IAAI,CAAC;AACxD,UAAM,EAAE,QAAA,IAAY,oBAAyC,GAAG;AACzD,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,MAAM,SAAS;AACb,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,CAAC,KAAK,UAAiB,OAAA,IAAI,MAAM,iCAAiC;AACtE,QAAI,KAAK,WAAkB,OAAA,IAAI,MAAM,6BAA6B;AAClE,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAChE,QAAI,KAAK,SAAgB,OAAA,IAAI,MAAM,2BAA2B;AAC9D,QAAI,KAAK,UAAiB,OAAA,IAAI,MAAM,4BAA4B;AAE5D,QAAA,KAAK,kBAAkB,CAAC,KAAK,YAAmB,OAAA,IAAI,MAAM,qCAAqC;AAEnG,SAAK,SAAS;AACd,UAAM,MAAM,MAAM,KAAK,MAAM,OAAO;AACpC,UAAM,EAAE,QAAA,IAAY,oBAAyC,GAAG;AACzD,WAAA;AAAA,EAAA;AAEX;AAEA,SAAS,eAAe,WAAuB;AACtC,SAAA,cAAc,UAAU,iBAAiB;AAClD;AAEA,SAAS,iBAAiB,WAAuB;AACxC,SAAA,cAAc,UAAU,mBAAmB;AACpD;AAGA,SAAS,eAAe,OAAY;AAClC,SAAO,UAAU,OAAO,CAAC,KAAK,QAAQ;AAC7B,WAAA,SAAS,GAAG,KAAK,eAAe,gBAAgB,cAAc,SAAS,KAAK,GAAG,IAAI;AAAA,EAAA,CAC3F;AACH;ACtdO,SAAS,QAA0C,MAAc;AACtE,SAAO,IAAI;AAAA,IACT,CAAC;AAAA,IACD;AAAA,MACE,IAAI,QAAQ,MAAM;AACZ,YAAA,SAAS,WAAmB,QAAA;AAEhC,cAAM,QAAQ,IAAI,GAAW,EAAE,OAAO,MAAM;AAC5C,cAAM,YAAY;AACZ,cAAA,MAAM,MAAM,SAAS;AAE3B,eAAO,WAAW,GAAG,IAAI,IAAI,KAAK,KAAK,IAAI;AAAA,MAAA;AAAA,IAC7C;AAAA,EAEJ;AACF;AC0BsB,eAAA,SACpBA,UACA,SACyB;AACnB,QAAA;AAAA,IACJ;AAAA,IACA,SAAS,CAAC;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAGJ,MAAI,SAAS,OAAc,OAAA,IAAI,MAAM,sBAAsB;AAE3D,QAAM,MAAO,mBAAmBA;AAChC,QAAM,QAAS,MAAM,IAClB,MAAM,KAAK,EACX,OAAO,UAAU,CAAA,CAAE,EAEnB,SAAS,IAAI;AAEhB,MAAI,OAAO;AACT,UAAM,aAAc,MAAM,iBAAiB,KAAK,MAAO;AAEvD,QAAI,YAAY;AAEd,aAAO,EAAE,IAAI,MAAM,KAAe,SAAS,OAAO,SAAS,MAAM;AAAA,IAAA;AAGnE,UAAM,aAAa,WAAW,MAAM,IAAI,OAAO,KAAK,IAAI;AAExC,UAAM,IAAI,QAAQ,MAAM,GAAG,EAAE,OAAO,UAAU;AAC9D,oBAAgB,YAAY,KAAK;AAGjC,WAAO,EAAE,IAAI,MAAM,KAAe,SAAS,MAAM,SAAS,MAAM;AAAA,EAAA;AAGlE,QAAM,iBAAiB;AACvB,QAAM,YAAY,MAAM,IAAI,OAAO,MAAM;AACzC,QAAM,gBAAgB,SAAS;AAE/B,SAAO,EAAE,IAAI,WAAW,SAAS,OAAO,SAAS,KAAK;AACxD;AC7EsB,eAAA,SACpBA,UACA,SACyB;AACzB,QAAM,EAAE,IAAI,QAAY,IAAA,MAAM,SAASA,UAAS;AAAA,IAC9C,GAAG;AAAA;AAAA,IAEH,QAAQ,CAAC;AAAA,IACT,gBAAgB,MAAM;AAAA,EAAA,CACvB;AACM,SAAA,EAAE,IAAI,QAAQ;AACvB;ACbsB,eAAA,cACpB,aAEA,eAEA,iBACA;AACM,QAAA,gBAAiB,iBAAiB,SAAS,SAAS;AAEpD,QAAA,CAAC,MAAM,WAAW,IAAI,MAAM,WAAW,cAAc,kBAAkB;AAC7E,MAAI,KAAY,OAAA;AAEV,QAAA,kBAAmC,CAAKA,aAAyB;AAC9D,WAAA,mBAAmB,IAAI,GAAO,EAAE,OAAOA,SAAQ,OAAO,aAAa;AAAA,EAC5E;AAEA,QAAM,CAAC,MAAM,MAAM,IAAI,MAAM,WAAW,YAAY;AAC5CC,UAAAA,UAAS,MAAM,YAAY,eAAe;AAChD,UAAM,YAAY,OAAO;AAClBA,WAAAA;AAAAA,EAAA,CACR;AAED,MAAI,MAAM;AACF,UAAA,WAAW,YAAY,UAAU;AACjC,UAAA;AAAA,EAAA;AAGD,SAAA;AACT;"}
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED