proto.io 0.0.227 → 0.0.229
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/README.md +1017 -0
- package/dist/adapters/file/aliyun-oss.d.mts +26 -0
- package/dist/adapters/file/aliyun-oss.d.mts.map +1 -0
- package/dist/adapters/file/aliyun-oss.d.ts +3 -3
- package/dist/adapters/file/database.d.mts +23 -0
- package/dist/adapters/file/database.d.mts.map +1 -0
- package/dist/adapters/file/database.d.ts +2 -2
- package/dist/adapters/file/database.js +1 -1
- package/dist/adapters/file/database.mjs +1 -1
- package/dist/adapters/file/filesystem.d.mts +25 -0
- package/dist/adapters/file/filesystem.d.mts.map +1 -0
- package/dist/adapters/file/filesystem.d.ts +3 -3
- package/dist/adapters/file/google-cloud-storage.d.mts +29 -0
- package/dist/adapters/file/google-cloud-storage.d.mts.map +1 -0
- package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
- package/dist/adapters/storage/postgres.d.mts +299 -0
- package/dist/adapters/storage/postgres.d.mts.map +1 -0
- package/dist/adapters/storage/postgres.d.ts +5 -1
- package/dist/adapters/storage/postgres.d.ts.map +1 -1
- package/dist/adapters/storage/postgres.js +182 -74
- package/dist/adapters/storage/postgres.js.map +1 -1
- package/dist/adapters/storage/postgres.mjs +182 -74
- package/dist/adapters/storage/postgres.mjs.map +1 -1
- package/dist/client.d.mts +16 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/client.mjs +2 -2
- package/dist/index.d.mts +151 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +68 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -26
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{base-DSo02iAX.d.ts → base-Bhrj5Pq1.d.ts} +2 -2
- package/dist/internals/{base-DSo02iAX.d.ts.map → base-Bhrj5Pq1.d.ts.map} +1 -1
- package/dist/internals/base-CiZHXD0o.d.mts +27 -0
- package/dist/internals/base-CiZHXD0o.d.mts.map +1 -0
- package/dist/internals/chunk-Cp2QN7ug.d.mts +17 -0
- package/dist/internals/chunk-Cp2QN7ug.d.mts.map +1 -0
- package/dist/internals/{chunk-BhwfdCdq.d.ts → chunk-o7lWIP-f.d.ts} +3 -3
- package/dist/internals/{chunk-BhwfdCdq.d.ts.map → chunk-o7lWIP-f.d.ts.map} +1 -1
- package/dist/internals/{index-vOFh8pVc.js → index-B0TO6h9r.js} +8 -1
- package/dist/internals/index-B0TO6h9r.js.map +1 -0
- package/dist/internals/{index-Cj45GkKv.d.ts → index-B710pfTH.d.ts} +2 -2
- package/dist/internals/{index-Cj45GkKv.d.ts.map → index-B710pfTH.d.ts.map} +1 -1
- package/dist/internals/{index-BWZIV3_T.mjs → index-DG2-4tQ1.mjs} +8 -1
- package/dist/internals/index-DG2-4tQ1.mjs.map +1 -0
- package/dist/internals/index-DwjvuRyl.d.mts +92 -0
- package/dist/internals/index-DwjvuRyl.d.mts.map +1 -0
- package/dist/internals/index-OwgXw07h.d.mts +2107 -0
- package/dist/internals/index-OwgXw07h.d.mts.map +1 -0
- package/dist/internals/{index-1ZK5N4yb.d.ts → index-OwgXw07h.d.ts} +49 -7
- package/dist/internals/index-OwgXw07h.d.ts.map +1 -0
- package/dist/internals/{validator-Bc1jRJfA.js → validator-CFlx3oyq.js} +33 -1
- package/dist/internals/validator-CFlx3oyq.js.map +1 -0
- package/dist/internals/{validator-Boj1PUjM.mjs → validator-DubDY921.mjs} +32 -2
- package/dist/internals/validator-DubDY921.mjs.map +1 -0
- package/package.json +7 -19
- package/dist/internals/index-1ZK5N4yb.d.ts.map +0 -1
- package/dist/internals/index-BWZIV3_T.mjs.map +0 -1
- package/dist/internals/index-vOFh8pVc.js.map +0 -1
- package/dist/internals/validator-Bc1jRJfA.js.map +0 -1
- package/dist/internals/validator-Boj1PUjM.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-OwgXw07h.d.mts","sources":["../../src/internals/query/types/index.ts","../../src/internals/object/user.ts","../../src/internals/object/role.ts","../../src/internals/buffer.ts","../../src/internals/object/file.ts","../../src/internals/object/job.ts","../../src/internals/object/session.ts","../../src/internals/object/types.ts","../../src/internals/query/types/keys.ts","../../src/internals/query/types/expressions.ts","../../src/internals/query/types/selectors.ts","../../src/internals/query/types/accumulators.ts","../../src/internals/query/base.ts","../../src/internals/liveQuery/index.ts","../../src/internals/query/index.ts","../../src/internals/codec.ts","../../src/internals/proto/types.ts","../../src/server/proto/session.ts","../../src/internals/proto/index.ts","../../src/internals/options.ts","../../src/internals/object/index.ts","../../src/internals/types.ts","../../src/internals/schema.ts","../../src/server/file/index.ts","../../src/server/query/dispatcher/parser/expressions.ts","../../src/server/query/dispatcher/parser/index.ts","../../src/server/query/dispatcher/parser/accumulators.ts","../../src/server/storage/index.ts","../../src/server/crypto/password.ts","../../src/server/pubsub/index.ts","../../src/server/proto/types.ts","../../src/server/proto/index.ts"],"sourcesContent":["//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { Exact } from '../../types';\n\ntype _Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\ntype _Lower = 'a' | 'b' | 'c' | 'd' | 'e' |\n 'f' | 'g' | 'h' | 'i' | 'j' |\n 'k' | 'l' | 'm' | 'n' | 'o' |\n 'p' | 'q' | 'r' | 's' | 't' |\n 'u' | 'v' | 'w' | 'x' | 'y' | 'z';\ntype _Upper = Uppercase<_Lower>;\ntype _Alphabet = _Lower | _Upper;\n\ntype _String<T extends string, C extends string | number> = T extends `${infer H}${C}`\n ? H extends '' | _String<H, C> ? T : never\n : never;\n\nexport type Digits<T extends string> = T extends `${number}` ? T : never;\nexport type FieldName<T extends string> = string extends T ? string : T extends `${'_' | _Alphabet}${'' | _String<infer _U, '_' | '-' | _Alphabet | _Digit>}` ? T : never;\n\ntype PathArrayGetter<T extends string> = T extends `[${Digits<infer _T>}]` ? T\n : T extends `[${Digits<infer L>}]${infer R}`\n ? `[${L}]${PathArrayGetter<R>}`\n : never;\n\ntype PathComponent<T extends string> = T extends Digits<T> | FieldName<T> ? T\n : T extends `${Digits<infer L> | FieldName<infer L>}[${infer _R}`\n ? `${L}${PathArrayGetter<`[${_R}`>}`\n : never;\n\ntype PathComponents<T extends string> = T extends PathComponent<T> ? T\n : T extends `${PathComponent<infer L>}.${infer R}`\n ? `${L}.${PathComponents<R>}`\n : never;\n\nexport type PathName<T extends string> = string extends T ? string : T extends '$' | PathComponent<T> ? T\n : T extends `${infer L}.${infer R}`\n ? `${PathComponent<L>}.${PathComponents<R>}`\n : never;\n\nexport type PathNames<T extends _.RecursiveArray<string>> = T extends [] ? [] :\n T extends [infer H extends string, ...infer R extends _.RecursiveArray<string>] ?\nH extends undefined ? PathNames<R> : [PathName<H>, ...PathNames<R>] : T;\n\nexport type IncludePath<T extends string> = T extends '*' | FieldName<T> ? T\n : T extends `${infer L}.${infer R}`\n ? `${FieldName<L>}.${IncludePath<R>}`\n : never;\n\nexport type IncludePaths<T extends _.RecursiveArray<string>> = T extends [] ? [] :\n T extends [infer H extends string, ...infer R extends _.RecursiveArray<string>] ?\n H extends undefined ? IncludePaths<R> : [IncludePath<H>, ...IncludePaths<R>] : T;\n\nexport type PathNameMap<T extends object> = Exact<T, { [K in keyof T as K extends string ? PathName<K> : never]: T[K] }>;\n","//\n// user.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TObject } from './index';\nimport { TValue } from '../types';\n\nexport class TUser extends TObject {\n\n constructor(\n attributes?: Record<string, TValue> | ((self: TObject) => Record<string, TValue>),\n ) {\n super('User', attributes);\n }\n}","//\n// role.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TObject } from './index';\nimport { TValue } from '../types';\nimport { TUser } from './user';\n\n/**\n * Class representing a Role.\n * @extends TObject\n */\nexport class TRole extends TObject {\n\n constructor(\n attributes?: Record<string, TValue> | ((self: TObject) => Record<string, TValue>),\n ) {\n super('Role', attributes);\n }\n\n /**\n * Get the name of the role.\n * @return {string | undefined} The name of the role.\n */\n get name(): string | undefined {\n return this.get('name');\n }\n\n /**\n * Get the users associated with the role.\n * @return {TUser[]} The users associated with the role.\n */\n get users(): TUser[] {\n return this.get('users') ?? [];\n }\n\n /**\n * Set the users associated with the role.\n * @param {TUser[]} value - The users to associate with the role.\n */\n set users(value: TUser[]) {\n this.set('users', value);\n }\n\n /**\n * Get the roles associated with the role.\n * @return {TRole[]} The roles associated with the role.\n */\n get roles(): TRole[] {\n return this.get('roles') ?? [];\n }\n\n /**\n * Set the roles associated with the role.\n * @param {TRole[]} value - The roles to associate with the role.\n */\n set roles(value: TRole[]) {\n this.set('roles', value);\n }\n}","//\n// buffer.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport type { Readable } from 'node:stream';\nimport { BinaryData } from '@o2ter/utils-js';\n\n/**\n * Represents a stream of data that can be read.\n * It can be either a ReadableStream or a Readable.\n */\nexport type FileStream = ReadableStream | Readable;\n\n/**\n * Represents the data of a file.\n * It can be a string, Blob, BinaryData, FileStream, or an object containing a base64 string.\n */\nexport type FileData = string | Blob | BinaryData | FileStream | { base64: string; };\n","//\n// file.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TObject } from './index';\nimport { ExtraOptions } from '../options';\nimport { FileStream } from '../buffer';\nimport { TValue } from '../types';\n\n/**\n * Interface representing a file.\n */\nexport interface TFile {\n /**\n * URL of the file.\n */\n url: string | undefined;\n\n /**\n * Retrieves the file data.\n * @param options - Optional extra options.\n * @returns A FileStream containing the file data.\n */\n fileData(options?: ExtraOptions<boolean>): FileStream;\n\n /**\n * Saves the file.\n * @param options - Optional extra options including cascadeSave and uploadToken.\n * @returns A promise that resolves to the current instance.\n */\n save(options?: ExtraOptions<boolean> & {\n cascadeSave?: boolean;\n uploadToken?: string;\n }): PromiseLike<this>;\n}\n\n/**\n * Class representing a file.\n */\nexport class TFile extends TObject {\n\n constructor(\n attributes?: Record<string, TValue> | ((self: TObject) => Record<string, TValue>),\n ) {\n super('File', attributes);\n }\n\n /**\n * Gets the filename of the file.\n * @returns The filename.\n */\n get filename(): string | undefined {\n return this.get('filename');\n }\n\n /**\n * Gets the size of the file.\n * @returns The size of the file.\n */\n get size(): number | undefined {\n return this.get('size');\n }\n\n /**\n * Gets the type of the file.\n * @returns The type of the file.\n */\n get type(): string | undefined {\n return this.get('type');\n }\n\n /**\n * Gets the token of the file.\n * @returns The token of the file.\n */\n get token(): string | undefined {\n return this.get('token');\n }\n\n}\n","//\n// job.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TObject } from './index';\nimport { TValue } from '../types';\nimport { TUser } from './user';\n\n/**\n * Class representing a Job.\n * @extends TObject\n */\nexport class TJob extends TObject {\n\n constructor(\n attributes?: Record<string, TValue> | ((self: TObject) => Record<string, TValue>),\n ) {\n super('_Job', attributes);\n }\n\n /**\n * Get the name of the job.\n * @return {string} The name of the job.\n */\n get name(): string {\n return this.get('name');\n }\n\n /**\n * Get the data of the job.\n * @return {TValue | undefined} The data of the job.\n */\n get data(): TValue | undefined {\n return this.get('data');\n }\n\n /**\n * Get the user associated with the job.\n * @return {TUser | undefined} The user associated with the job.\n */\n get user(): TUser | undefined {\n return this.get('user');\n }\n\n /**\n * Get the error of the job.\n * @return {TValue | undefined} The error of the job.\n */\n get error(): TValue | undefined {\n return this.get('error');\n }\n\n /**\n * Get the start time of the job.\n * @return {Date | undefined} The start time of the job.\n */\n get startedAt(): Date | undefined {\n return this.get('startedAt');\n }\n\n /**\n * Get the completion time of the job.\n * @return {Date | undefined} The completion time of the job.\n */\n get completedAt(): Date | undefined {\n return this.get('completedAt');\n }\n}","//\n// session.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TObject } from './index';\nimport { TValue } from '../types';\n\nexport class TSession extends TObject {\n\n constructor(\n attributes?: Record<string, TValue> | ((self: TObject) => Record<string, TValue>),\n ) {\n super('_Session', attributes);\n }\n\n /**\n * Get the session ID.\n * @return {string} The session ID.\n */\n get sessionId(): string {\n return this.get('token');\n }\n\n /**\n * Get the user associated with the session.\n * @return {TObject | undefined} The user associated with the session.\n */\n get user(): TObject | undefined {\n return this.get('user');\n }\n\n get loginedAt(): Date | undefined {\n return this.get('loginedAt');\n }\n}","//\n// types.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { TObject } from './index';\nimport { TUser } from './user';\nimport { TRole } from './role';\nimport { TFile } from './file';\nimport { TValueWithUndefined } from '../types';\nimport { ExactOneProp } from '../types';\nimport { TJob } from './job';\nimport { TSession } from './session';\n\nexport const TObjectTypes = {\n 'User': TUser,\n 'Role': TRole,\n 'File': TFile,\n '_Job': TJob,\n '_Session': TSession,\n};\n\ntype _TObjectType<K> = K extends keyof typeof TObjectTypes ? InstanceType<(typeof TObjectTypes)[K]> : TObject;\n\ntype PickBy<T, C> = {\n [P in keyof T as T[P] extends C ? P : never]: T[P];\n}\n\ntype PropertyDescriptor<T> = {\n enumerable?: boolean;\n get: () => T;\n set?: (value: T) => void;\n};\ntype ReadOnlyProperty<T> = Pick<PropertyDescriptor<T>, 'get'>;\ntype ReadWriteProperty<T> = Required<Pick<PropertyDescriptor<T>, 'get' | 'set'>>;\n\ntype PropertyMapToMethods<T> = PickBy<T, Function>\n & { [P in keyof PickBy<T, ReadWriteProperty<any>>]: T[P] extends PropertyDescriptor<infer V> ? V : never; }\n & { readonly [P in keyof PickBy<T, ReadOnlyProperty<any>>]: T[P] extends PropertyDescriptor<infer V> ? V : never; }\ntype Property<T> = T extends Function ? T | PropertyDescriptor<T> : PropertyDescriptor<T>;\ntype PropertyMap<T, O, A> = {\n [K in keyof T]: T[K] extends Property<any> ? T[K] : never;\n} & ThisType<O & PropertyMapToMethods<T> & PropertyMapToMethods<A>>;\n\nexport type TExtensions<E> = {\n [K in keyof E]: PropertyMap<E[K], _TObjectType<K>, '*' extends keyof E ? Omit<E['*'], keyof E[K]> : {}>;\n};\n\ntype _TMethods<K, E> = K extends keyof E\n ? '*' extends keyof E ? PropertyMapToMethods<Omit<E['*'], keyof E[K]> & E[K]> : PropertyMapToMethods<E[K]>\n : {};\n\ntype IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;\ntype TMethods<K, E> = IfAny<E, {}, _TMethods<K, E>>;\n\nexport type TObjectType<K, E> = _TObjectType<K> & TMethods<K, E>;\n\nexport const TUpdateOpKeys = [\n '$set',\n '$inc',\n '$dec',\n '$mul',\n '$div',\n '$max',\n '$min',\n '$addToSet',\n '$push',\n '$removeAll',\n '$popFirst',\n '$popLast',\n] as const;\n\nexport type TUpdateOp = ExactOneProp<Record<(typeof TUpdateOpKeys)[number], TValueWithUndefined>>;\n","//\n// keys.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nexport const TComparisonKeys = [\n '$eq',\n '$gt',\n '$gte',\n '$lt',\n '$lte',\n '$ne',\n] as const;\n\nexport const TValueListKeys = [\n '$in',\n '$nin',\n] as const;\n\nexport const TValueSetKeys = [\n '$subset',\n '$superset',\n '$intersect',\n] as const;\n\nexport const TConditionalKeys = [\n '$and',\n '$nor',\n '$or',\n] as const;\n","//\n// expressions.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { TValue } from '../../types';\nimport { TComparisonKeys, TConditionalKeys } from './keys';\n\nexport const TZeroParamExprKeys = [\n '$now',\n '$rand',\n] as const;\n\nexport const TUnaryExprKeys = [\n '$abs',\n '$neg',\n '$sqrt',\n '$cbrt',\n '$ceil',\n '$floor',\n '$round',\n '$exp',\n '$ln',\n '$log2',\n '$log10',\n '$sin',\n '$cos',\n '$tan',\n '$asin',\n '$acos',\n '$atan',\n '$asinh',\n '$acosh',\n '$atanh',\n '$sinh',\n '$cosh',\n '$tanh',\n '$degrees',\n '$radians',\n '$sign',\n '$size',\n '$lower',\n '$upper',\n] as const;\n\nexport const TBinaryExprKeys = [\n '$divide',\n '$subtract',\n '$log',\n '$pow',\n '$atan2',\n '$trim',\n '$ltrim',\n '$rtrim',\n '$first',\n '$last',\n '$ldrop',\n '$rdrop',\n] as const;\n\nexport const TTernaryExprKeys = [\n '$lpad',\n '$rpad',\n] as const;\n\nexport const TListExprKeys = [\n '$add',\n '$multiply',\n '$ifNull',\n '$concat',\n] as const;\n\nexport const TDistanceExprKeys = [\n '$distance',\n '$innerProduct',\n '$negInnerProduct',\n '$cosineDistance',\n '$rectilinearDistance',\n] as const;\n\nexport type TBooleanExpression = {\n $not?: TBooleanExpression;\n} & {\n [x in (typeof TComparisonKeys)[number]]?: [TExpression, TExpression];\n } & {\n [x in (typeof TConditionalKeys)[number]]?: TBooleanExpression[];\n };\n\nexport type TDistanceExpression = {\n [x in (typeof TDistanceExprKeys)[number]]?: [\n TExpression[] | { $key: string; } | { $value: number[]; },\n TExpression[] | { $key: string; } | { $value: number[]; },\n ];\n};\n\nexport type TExpression = {\n $array?: TExpression[];\n $key?: string;\n $value?: TValue;\n} & {\n $cond?: {\n branch: _.Many<{\n case: TExpression;\n then: TExpression;\n }[]>;\n default: TExpression;\n };\n} & {\n [x in (typeof TZeroParamExprKeys)[number]]?: true | {};\n} & {\n [x in (typeof TUnaryExprKeys)[number]]?: TExpression;\n} & {\n [x in (typeof TBinaryExprKeys)[number]]?: [TExpression, TExpression];\n} & {\n [x in (typeof TTernaryExprKeys)[number]]?: [TExpression, TExpression, TExpression];\n} & {\n [x in (typeof TListExprKeys)[number]]?: TExpression[];\n} & TBooleanExpression & TDistanceExpression;\n","//\n// selectors.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { TValue } from '../../types';\nimport { TBooleanExpression } from './expressions';\nimport { TConditionalKeys, TValueListKeys, TValueSetKeys, TComparisonKeys } from './keys';\n\nexport const allFieldQueryKeys = [\n '$not', '$pattern', '$starts', '$ends', '$size', '$empty', '$every', '$some',\n ...TConditionalKeys,\n ...TValueListKeys,\n ...TValueSetKeys\n];\n\ntype TThisQuerySelector = { $?: TFieldQuerySelector; };\n\nexport type TFieldQuerySelector = {\n $not?: TFieldQuerySelector;\n $starts?: string;\n $ends?: string;\n $pattern?: RegExp | string;\n $size?: number;\n $empty?: boolean;\n $every?: TQuerySelector | TThisQuerySelector;\n $some?: TQuerySelector | TThisQuerySelector;\n} & {\n [x in (typeof TComparisonKeys)[number]]?: TValue;\n } & {\n [x in (typeof TValueListKeys)[number]]?: TValue[];\n } & {\n [x in (typeof TValueSetKeys)[number]]?: TValue[];\n };\n\nexport type TCoditionalQuerySelector = {\n [x in (typeof TConditionalKeys)[number]]?: TQuerySelector[];\n};\n\nexport type TQuerySelector = TCoditionalQuerySelector & {\n $expr?: TBooleanExpression\n} | {\n [x: string]: TFieldQuerySelector;\n};\n","//\n// accumulators.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { TExpression } from './expressions';\n\nexport const TUnaryAccumulatorKeys = [\n '$max',\n '$min',\n '$most',\n '$sum',\n '$avg',\n '$stdDevPop',\n '$stdDevSamp',\n '$varPop',\n '$varSamp'\n] as const;\n\nexport const TZeroParamAccumulatorKeys = [\n '$count'\n] as const;\n\nexport type TQueryAccumulator = {\n $percentile?: {\n input: TExpression;\n p: number;\n mode?: 'discrete' | 'continuous';\n };\n $group?: {\n key: TExpression;\n value: Omit<TQueryAccumulator, '$group'>;\n };\n} & {\n [x in (typeof TZeroParamAccumulatorKeys)[number]]?: true | {};\n} & {\n [x in (typeof TUnaryAccumulatorKeys)[number]]?: TExpression;\n};\n\nexport type TAccumulatorResult<A extends TQueryAccumulator> =\n A extends { $group: any }\n ? { key: any; value: any; }[]\n : A extends { $count: any } ? number : any;\n","//\n// base.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { PathName, PathNameMap, PathNames } from './types';\nimport { TQuerySelector } from './types/selectors';\nimport { TValueWithUndefined } from '../types';\nimport { PVK } from '../private';\nimport { TExpression } from './types/expressions';\nimport { TQueryAccumulator } from './types/accumulators';\n\n/**\n * Options for a query filter.\n */\ninterface TQueryFilterBaseOptions {\n /**\n * The filter(s) to apply to the query.\n */\n filter?: TQuerySelector | TQuerySelector[];\n};\n\n/**\n * Sort option for a query.\n */\nexport type TSortOption = {\n /**\n * The expression to sort by.\n */\n expr: TExpression;\n /**\n * The order of sorting, 1 for ascending and -1 for descending.\n */\n order: 1 | -1;\n};\n\n/**\n * Base options for a query.\n */\nexport interface TQueryBaseOptions extends TQueryFilterBaseOptions {\n /**\n * The sorting options for the query.\n */\n sort?: Record<string, 1 | -1> | TSortOption[];\n /**\n * The number of results to skip.\n */\n skip?: number;\n /**\n * The limit on the number of results.\n */\n limit?: number;\n /**\n * Nested query options for matching specific fields.\n */\n matches?: Record<string, TQueryBaseOptions>;\n /**\n * Groups the query results by the specified key and applies the provided accumulators.\n */\n groupMatches?: Record<string, Record<string, TQueryAccumulator>>;\n};\n\nconst mergeOpts = (lhs: TQueryBaseOptions, rhs: TQueryBaseOptions): TQueryBaseOptions => {\n return {\n ...lhs,\n ...rhs,\n filter: [\n ..._.castArray<TQuerySelector>(lhs.filter),\n ..._.castArray<TQuerySelector>(rhs.filter)\n ],\n matches: {\n ...lhs.matches,\n ..._.mapValues(rhs.matches, (opts, key) => lhs.matches?.[key] ? mergeOpts(lhs.matches[key], opts) : opts),\n },\n groupMatches: {\n ...lhs.groupMatches ?? {},\n ...rhs.groupMatches ?? {},\n },\n };\n}\n\n/**\n * Base class for query filters.\n */\nclass TQueryFilterBase {\n\n /** @internal */\n [PVK]: { options: TQueryFilterBaseOptions; } = { options: {} };\n\n /**\n * Applies a filter to the query.\n * @param filter - The filter to apply.\n * @returns The current instance for chaining.\n */\n filter(filter: TQuerySelector) {\n if (_.isNil(this[PVK].options.filter)) {\n this[PVK].options.filter = filter;\n } else if (_.isArray(this[PVK].options.filter)) {\n this[PVK].options.filter = [...this[PVK].options.filter, filter];\n } else {\n this[PVK].options.filter = [this[PVK].options.filter, filter];\n }\n return this;\n }\n\n /**\n * Applies an equality filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n equalTo<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n return this.filter({ [key]: { $eq: value ?? null } });\n }\n\n /**\n * Applies a not equal filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n notEqualTo<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n return this.filter({ [key]: { $ne: value ?? null } });\n }\n\n /**\n * Applies a less than filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n lessThan<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n return this.filter({ [key]: { $lt: value ?? null } });\n }\n\n /**\n * Applies a greater than filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n greaterThan<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n return this.filter({ [key]: { $gt: value ?? null } });\n }\n\n /**\n * Applies a less than or equal to filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n lessThanOrEqualTo<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n return this.filter({ [key]: { $lte: value ?? null } });\n }\n\n /**\n * Applies a greater than or equal to filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n greaterThanOrEqualTo<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n return this.filter({ [key]: { $gte: value ?? null } });\n }\n\n /**\n * Applies a pattern filter to the query.\n * @param key - The key to filter.\n * @param value - The pattern to filter.\n * @returns The current instance for chaining.\n */\n pattern<T extends string>(key: PathName<T>, value: RegExp | string) {\n return this.filter({ [key]: { $pattern: value ?? null } });\n }\n\n /**\n * Applies a starts with filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n startsWith<T extends string>(key: PathName<T>, value: string) {\n return this.filter({ [key]: { $starts: value ?? null } });\n }\n\n /**\n * Applies an ends with filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n endsWith<T extends string>(key: PathName<T>, value: string) {\n return this.filter({ [key]: { $ends: value ?? null } });\n }\n\n /**\n * Applies a size filter to the query.\n * @param key - The key to filter.\n * @param value - The value to filter.\n * @returns The current instance for chaining.\n */\n size<T extends string>(key: PathName<T>, value: number) {\n return this.filter({ [key]: { $size: value } });\n }\n\n /**\n * Applies an empty filter to the query.\n * @param key - The key to filter.\n * @returns The current instance for chaining.\n */\n empty<T extends string>(key: PathName<T>) {\n return this.filter({ [key]: { $empty: true } });\n }\n\n /**\n * Applies a not empty filter to the query.\n * @param key - The key to filter.\n * @returns The current instance for chaining.\n */\n notEmpty<T extends string>(key: PathName<T>) {\n return this.filter({ [key]: { $empty: false } });\n }\n\n /**\n * Filters the query to include only documents where the specified key contains any of the specified values.\n * @param key - The key to check for values.\n * @param value - The array of values to check for.\n * @returns The current instance for chaining.\n */\n containedIn<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $in: value } });\n }\n\n /**\n * Filters the query to exclude documents where the specified key contains any of the specified values.\n * @param key - The key to check for values.\n * @param value - The array of values to exclude.\n * @returns The current instance for chaining.\n */\n notContainedIn<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $nin: value } });\n }\n\n /**\n * Filters the query to include only documents where the specified key contains all of the specified values.\n * @param key - The key to check for containing values.\n * @param value - The array of values to check against.\n * @returns The current instance for chaining.\n */\n containedBy<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $superset: value } });\n }\n\n /**\n * Filters the query to exclude documents where the specified key contains all of the specified values.\n * @param key - The key to check for superset.\n * @param value - The array of values to check against.\n * @returns The current instance for chaining.\n */\n notContainedBy<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $not: { $superset: value } } });\n }\n\n /**\n * Filters the query to include only documents where the specified key is a subset of the specified values.\n * @param key - The key to check for subset.\n * @param value - The array of values to check against.\n * @returns The current instance for chaining.\n */\n isSubset<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $subset: value } });\n }\n\n /**\n * Filters the query to include only documents where the specified key is a superset of the specified values.\n * @param key - The key to check for superset.\n * @param value - The array of values to check against.\n * @returns The current instance for chaining.\n */\n isSuperset<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $superset: value } });\n }\n\n /**\n * Filters the query to include only documents where the specified key is disjoint from the specified values.\n * @param key - The key to check for disjoint.\n * @param value - The array of values to check against.\n * @returns The current instance for chaining.\n */\n isDisjoint<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $not: { $intersect: value } } });\n }\n\n /**\n * Filters the query to include only documents where the specified key intersects with the specified values.\n * @param key - The key to check for intersection.\n * @param value - The array of values to check against.\n * @returns The current instance for chaining.\n */\n isIntersect<T extends string>(key: PathName<T>, value: TValueWithUndefined[]) {\n return this.filter({ [key]: { $intersect: value } });\n }\n\n /**\n * Filters the query to include only documents where every element of the specified key matches the provided callback query.\n * @param key - The key to check for every element.\n * @param callback - The callback query to apply to each element.\n * @returns The current instance for chaining.\n */\n every<T extends string>(key: PathName<T>, callback: (query: TQueryFilterBase) => void) {\n const query = new TQueryFilterBase();\n callback(query);\n return this.filter({ [key]: { $every: { $and: _.castArray<TQuerySelector>(query[PVK].options.filter) } } });\n }\n\n /**\n * Filters the query to include only documents where some elements of the specified key match the provided callback query.\n * @param key - The key to check for some elements.\n * @param callback - The callback query to apply to each element.\n * @returns The current instance for chaining.\n */\n some<T extends string>(key: PathName<T>, callback: (query: TQueryFilterBase) => void) {\n const query = new TQueryFilterBase();\n callback(query);\n return this.filter({ [key]: { $some: { $and: _.castArray<TQuerySelector>(query[PVK].options.filter) } } });\n }\n\n /**\n * Filters the query to include only documents that match all of the provided callback queries.\n * @param callbacks - The callback queries to apply.\n * @returns The current instance for chaining.\n */\n and(...callbacks: _.Many<(query: TQueryFilterBase) => void>[]) {\n return this.filter({\n $and: _.flatMap(_.flatten(callbacks), callback => {\n const query = new TQueryFilterBase();\n callback(query);\n return _.castArray<TQuerySelector>(query[PVK].options.filter);\n }),\n });\n }\n\n /**\n * Filters the query to include only documents that match any of the provided callback queries.\n * @param callbacks - The callback queries to apply.\n * @returns The current instance for chaining.\n */\n or(...callbacks: _.Many<(query: TQueryFilterBase) => void>[]) {\n return this.filter({\n $or: _.map(_.flatten(callbacks), callback => {\n const query = new TQueryFilterBase();\n callback(query);\n return {\n $and: _.castArray<TQuerySelector>(query[PVK].options.filter),\n };\n }),\n });\n }\n\n /**\n * Filters the query to include only documents that do not match any of the provided callback queries.\n * @param callbacks - The callback queries to apply.\n * @returns The current instance for chaining.\n */\n nor(...callbacks: _.Many<(query: TQueryFilterBase) => void>[]) {\n return this.filter({\n $nor: _.map(_.flatten(callbacks), callback => {\n const query = new TQueryFilterBase();\n callback(query);\n return {\n $and: _.castArray<TQuerySelector>(query[PVK].options.filter),\n };\n }),\n });\n }\n}\n\nexport class TQueryBase extends TQueryFilterBase {\n\n /** @internal */\n [PVK]: { options: TQueryBaseOptions; } = { options: {} };\n\n /**\n * Sorts the query results.\n * @param sort - The sorting criteria.\n * @returns The current instance for chaining.\n */\n sort<T extends Record<string, 1 | -1>>(sort: PathNameMap<T> | TSortOption[]) {\n this[PVK].options.sort = sort;\n return this;\n }\n\n /**\n * Skips the specified number of results.\n * @param skip - The number of results to skip.\n * @returns The current instance for chaining.\n */\n skip(skip: number) {\n if (!_.isSafeInteger(skip) || skip < 0) throw Error('Invalid skip number');\n this[PVK].options.skip = skip;\n return this;\n }\n\n /**\n * Limits the number of results.\n * @param limit - The maximum number of results to return.\n * @returns The current instance for chaining.\n */\n limit(limit: number) {\n if (!_.isSafeInteger(limit) || limit < 0) throw Error('Invalid limit number');\n this[PVK].options.limit = limit;\n return this;\n }\n\n /**\n * Performs a nested query on a specific key.\n * @param key - The key to match.\n * @param callback - The callback function to execute.\n * @returns The current instance for chaining.\n */\n match<T extends string>(key: PathName<T>, callback: (query: TQueryBase) => void) {\n const query = new TQueryBase();\n callback(query);\n if (_.isNil(this[PVK].options.matches)) {\n this[PVK].options.matches = { [key]: query[PVK].options };\n } else if (_.isNil(this[PVK].options.matches[key])) {\n this[PVK].options.matches = { ...this[PVK].options.matches };\n this[PVK].options.matches[key] = query[PVK].options;\n } else {\n this[PVK].options.matches = { ...this[PVK].options.matches };\n this[PVK].options.matches[key] = mergeOpts(this[PVK].options.matches[key], query[PVK].options);\n }\n return this;\n }\n\n /**\n * Groups the query results by the specified key and applies the provided accumulators.\n * @param key - The key to group by.\n * @param accumulators - The accumulators to apply.\n * @returns The current instance for chaining.\n */\n groupMatches<T extends string>(key: PathName<T>, accumulators: Record<string, TQueryAccumulator>) {\n if (_.isNil(this[PVK].options.groupMatches)) {\n this[PVK].options.groupMatches = { [key]: accumulators };\n } else {\n this[PVK].options.groupMatches = { ...this[PVK].options.groupMatches };\n this[PVK].options.groupMatches[key] = accumulators;\n }\n return this;\n }\n}\n","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TQuerySelector } from '../query/types/selectors';\nimport { ProtoType } from '../proto';\nimport { TObjectType } from '../object/types';\nimport { PVK } from '../private';\n\nexport class LiveQuerySubscription<T extends string, E> {\n\n private _className: T;\n private _proto: ProtoType<E>;\n private _filter: TQuerySelector[];\n\n constructor(className: T, proto: ProtoType<E>, filter: TQuerySelector | TQuerySelector[]) {\n this._className = className;\n this._proto = proto;\n this._filter = _.isArray(filter) ? filter : [filter];\n }\n\n get className(): T {\n return this._className;\n }\n\n on(\n event: 'create' | 'update' | 'delete',\n callback: (object: TObjectType<T, E>) => void,\n ) {\n return this._proto[PVK].liveQuery(\n this._proto,\n event,\n this.className,\n this._filter,\n (object) => callback(object as TObjectType<T, E>),\n );\n }\n}","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { IncludePaths } from './types';\nimport { TValueWithUndefined } from '../types';\nimport { PVK } from '../private';\nimport { TObjectType } from '../object/types';\nimport { TQueryBase, TQueryBaseOptions } from './base';\nimport { TUpdateOp } from '../object/types';\nimport { ExtraOptions } from '../options';\nimport { asyncStream, Awaitable, EventIterator } from '@o2ter/utils-js';\nimport { LiveQuerySubscription } from '../liveQuery';\nimport { TExpression } from './types/expressions';\nimport { TAccumulatorResult, TQueryAccumulator } from './types/accumulators';\n\n/**\n * Options for a query.\n */\nexport interface TQueryOptions extends TQueryBaseOptions {\n /**\n * Fields to include in the query.\n */\n includes?: string[];\n};\n\n/**\n * Options for a random query.\n */\nexport interface TQueryRandomOptions {\n /**\n * Field to use for weighting the random selection.\n */\n weight?: TExpression;\n};\n\n/**\n * Abstract base class for queries.\n */\nexport abstract class TQuery<T extends string, Ext, M extends boolean> extends TQueryBase {\n\n /** @internal */\n [PVK]: { options: TQueryOptions; } = { options: {} };\n\n /**\n * Clones the query with optional new options.\n * @param options - The new options for the query.\n * @returns A new query instance.\n */\n abstract clone(options?: TQueryOptions): TQuery<T, Ext, M>;\n\n /**\n * Explains the query execution plan.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the explanation.\n */\n abstract explain(options?: ExtraOptions<M>): PromiseLike<any>;\n\n /**\n * Counts the number of results for the query.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the count.\n */\n abstract count(options?: ExtraOptions<M>): PromiseLike<number>;\n\n /**\n * Finds the results for the query.\n * @param options - Extra options for the query.\n * @returns A stream of the results.\n */\n abstract find(options?: ExtraOptions<M>): ReturnType<typeof asyncStream<TObjectType<T, Ext>>>;\n\n /**\n * Selects a random result for the query.\n * @param opts - Options for the random selection.\n * @param options - Extra options for the query.\n * @returns A stream of the random result.\n */\n abstract random(\n opts?: TQueryRandomOptions,\n options?: ExtraOptions<M>\n ): ReturnType<typeof asyncStream<TObjectType<T, Ext>>>;\n\n /**\n * Finds grouped results for the query.\n * @param accumulators - The accumulators to use for grouping.\n * @param options - Extra options for the query.\n * @returns A stream of the grouped results.\n */\n abstract groupFind<T extends Record<string, TQueryAccumulator>>(\n accumulators: T,\n options?: ExtraOptions<M>\n ): Promise<{ [K in keyof T]: TAccumulatorResult<T[K]>; }>;\n\n /**\n * Finds non-reference results for the query.\n * @param options - Extra options for the query.\n * @returns A stream of the non-reference results.\n */\n abstract nonrefs(options?: ExtraOptions<M>): ReturnType<typeof asyncStream<TObjectType<T, Ext>>>;\n\n /**\n * Inserts a new record.\n * @param attrs - The attributes of the new record.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the inserted record.\n */\n async insert(\n attrs: Record<string, TValueWithUndefined>,\n options?: ExtraOptions<M>\n ) {\n const result = _.first(await this.clone().insertMany([attrs], options));\n if (!result) throw Error('Unable to insert document');\n return result;\n }\n\n /**\n * Inserts multiple new records.\n * @param values - The attributes of the new records.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the inserted records.\n */\n abstract insertMany(\n values: Record<string, TValueWithUndefined>[],\n options?: ExtraOptions<M>\n ): PromiseLike<TObjectType<T, Ext>[]>;\n\n /**\n * Updates a single record.\n * @param update - The update operations.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the updated record or undefined.\n */\n async updateOne(\n update: Record<string, TUpdateOp>,\n options?: ExtraOptions<M>\n ) {\n return _.first(await this.clone().limit(1).updateMany(update, options));\n }\n\n /**\n * Updates multiple records.\n * @param update - The update operations.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the updated records.\n */\n abstract updateMany(\n update: Record<string, TUpdateOp>,\n options?: ExtraOptions<M>\n ): PromiseLike<TObjectType<T, Ext>[]>;\n\n /**\n * Upserts a single record.\n * @param update - The update operations.\n * @param setOnInsert - The attributes to set on insert.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the upserted record.\n */\n async upsertOne(\n update: Record<string, TUpdateOp>,\n setOnInsert: Record<string, TValueWithUndefined>,\n options?: ExtraOptions<M>\n ) {\n const result = _.first(await this.clone().limit(1).upsertMany(update, setOnInsert, options));\n if (!result) throw Error('Unable to upsert document');\n return result;\n }\n\n\n /**\n * Upserts multiple records.\n * @param update - The update operations.\n * @param setOnInsert - The attributes to set on insert.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the upserted records.\n */\n abstract upsertMany(\n update: Record<string, TUpdateOp>,\n setOnInsert: Record<string, TValueWithUndefined>,\n options?: ExtraOptions<M>\n ): PromiseLike<TObjectType<T, Ext>[]>;\n\n /**\n * Deletes a single record.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the deleted record or undefined.\n */\n async deleteOne(options?: ExtraOptions<M>) {\n return _.first(await this.clone().limit(1).deleteMany(options));\n }\n\n /**\n * Deletes multiple records.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the deleted records.\n */\n abstract deleteMany(options?: ExtraOptions<M>): PromiseLike<TObjectType<T, Ext>[]>;\n\n /**\n * Subscribes to live query updates.\n * @returns A live query subscription.\n */\n abstract subscribe(): LiveQuerySubscription<T, Ext>;\n\n /**\n * Adds fields to include in the query.\n * @param includes - The fields to include.\n * @returns The query instance.\n */\n includes<T extends _.RecursiveArray<string>>(...includes: IncludePaths<T>) {\n const keys = this[PVK].options.includes ? [...this[PVK].options.includes, ..._.flattenDeep(includes)] : _.flattenDeep(includes);\n this[PVK].options.includes = _.uniq(keys);\n return this;\n }\n\n /**\n * Gets a record by its ID.\n * @param id - The ID of the record.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the record or undefined.\n */\n async get(id: string, options?: ExtraOptions<M>) {\n return _.first(await this.clone().equalTo('_id', id).limit(1).find(options));\n }\n\n /**\n * Gets the first record.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the first record or undefined.\n */\n async first(options?: ExtraOptions<M>) {\n return _.first(await this.clone().limit(1).find(options));\n }\n\n /**\n * Gets a random record.\n * @param opts - Options for the random selection.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to the random record or undefined.\n */\n async randomOne(opts?: TQueryRandomOptions, options?: ExtraOptions<M>) {\n return _.first(await this.clone().limit(1).random(opts, options));\n }\n\n /**\n * Checks if any records exist.\n * @param options - Extra options for the query.\n * @returns A promise that resolves to a boolean indicating if any records exist.\n */\n async exists(options?: ExtraOptions<M>) {\n const query = this.clone();\n this[PVK].options.includes = [];\n return !_.isNil(await query.limit(1).find(options));\n }\n\n /**\n * Iterates over each batch of records.\n * @param callback - The callback to execute for each batch.\n * @param options - Extra options for the query.\n */\n async eachBatch(\n callback: (batch: TObjectType<T, Ext>[]) => Awaitable<void>,\n options?: ExtraOptions<M> & { batchSize?: number; },\n ) {\n const sorting = this[PVK].options.sort as Record<string, 1 | -1> ?? {};\n const batchSize = options?.batchSize ?? 100;\n if (!_.isPlainObject(sorting)) throw Error('Unsupported sort method');\n const is_asc = _.every(sorting, v => v === 1);\n const is_desc = _.every(sorting, v => v === -1);\n if (!is_asc && !is_desc) throw Error('Unsupported sort method');\n if (_.isNil(sorting._id)) sorting._id = is_asc ? 1 : -1;\n const query = this.clone().sort(sorting).limit(batchSize);\n const keys = _.keys(sorting);\n let batch: TObjectType<T, Ext>[] = [];\n while (true) {\n options?.abortSignal?.throwIfAborted();\n const q = _.isEmpty(batch) ? query : query.clone()\n .filter(keys.length > 1 ? {\n $expr: {\n [is_asc ? '$gt' : '$lt']: [\n { $array: _.map(keys, k => ({ $key: k })) },\n { $array: _.map(keys, k => ({ $value: _.last(batch)!.get(k) })) },\n ],\n },\n } : {\n [keys[0]]: { [is_asc ? '$gt' : '$lt']: _.last(batch)!.get(keys[0]) },\n });\n batch = await q.find(options);\n if (_.isEmpty(batch)) return;\n await callback(batch);\n }\n }\n\n /**\n * Iterates over each record.\n * @param callback - The callback to execute for each record.\n * @param options - Extra options for the query.\n */\n async each(\n callback: (object: TObjectType<T, Ext>) => Awaitable<void>,\n options?: ExtraOptions<M> & { batchSize?: number; },\n ) {\n await this.eachBatch(async (batch) => {\n for (const object of batch) {\n await callback(object);\n }\n }, options);\n }\n\n /**\n * Finds all records matching the query.\n * @param options - Extra options for the query.\n * @returns An iterator for the records.\n */\n findAll(options?: ExtraOptions<M> & { batchSize?: number; }) {\n return EventIterator<TObjectType<T, Ext>>(async (push, stop) => {\n await this.each(item => push(item), options);\n stop();\n });\n }\n};\n","//\n// codec.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { Decimal } from 'decimal.js';\nimport { TObject } from './object';\nimport { TObjectTypes } from './object/types';\nimport { isObjKey } from './utils';\nimport { _TContainer, TValue } from './types';\nimport { prototypes } from '@o2ter/utils-js';\n\nexport { Decimal };\nexport type TNumber = number | Decimal | BigInt;\ntype TPrimitive = RegExp | Date | string | TNumber | boolean | null | undefined;\nexport type TSerializable = _TContainer<TPrimitive | TObject>;\n\nexport type SerializeOptions = {\n space?: string | number;\n objAttrs?: string[];\n};\n\nexport type DeserializeOptions = {\n objAttrs?: string[];\n};\n\nconst encodeEJSON = (\n x: TSerializable,\n stack: any[],\n options: SerializeOptions,\n): any => {\n if (_.isNil(x) || _.isNumber(x) || _.isBoolean(x) || _.isString(x)) return x ?? null;\n if (_.isDate(x)) return { $date: x.valueOf() };\n if (_.isRegExp(x)) return { $regex: x.source, $options: x.flags };\n if (x instanceof BigInt) return { $integer: x.toString() };\n if (x instanceof Decimal) return { $decimal: x.toString() };\n\n const found = _.indexOf(stack, x);\n if (found !== -1) return { $ref: found };\n\n if (_.isArray(x)) return x.map(v => encodeEJSON(v, [...stack, x], options));\n if (x instanceof TObject) {\n const attributes = options.objAttrs ? _.pick(x.attributes, ...options.objAttrs) : x.attributes;\n return {\n $object: {\n className: x.className,\n attributes: _.mapValues(attributes, v => encodeEJSON(v, [...stack, x], options)),\n }\n };\n }\n\n const props = _.uniq(_.flatMap([x, ...prototypes(x)], x => Object.getOwnPropertyNames(x)));\n return _.transform(\n _.pick(x, props),\n (r, v, k) => {\n if (_.isFunction(v)) return;\n r[k.startsWith('$') ? `$${k}` : k] = encodeEJSON(v, [...stack, x], options);\n },\n {} as { [x: string]: TSerializable },\n );\n}\n\nconst decodeEJSON = (\n x: any,\n stack: any[],\n options: DeserializeOptions,\n): TSerializable => {\n if (_.isNil(x) || _.isNumber(x) || _.isBoolean(x) || _.isString(x)) return x ?? null;\n if (_.isArray(x)) {\n return _.transform(x, (r, v) => {\n r.push(decodeEJSON(v, [...stack, r], options));\n }, [] as TSerializable[]);\n }\n if (!_.isNil(x.$date)) return new Date(x.$date);\n if (!_.isNil(x.$regex)) return new RegExp(x.$regex, x.$options || '');\n if (!_.isNil(x.$integer)) return BigInt(x.$integer);\n if (!_.isNil(x.$decimal)) return new Decimal(x.$decimal);\n if (!_.isNil(x.$ref)) return stack[x.$ref];\n if (!_.isNil(x.$object)) {\n const { className, attributes } = x.$object;\n const _attributes = (self: TObject) => _.mapValues(\n options.objAttrs ? _.pick(attributes, ...options.objAttrs) : attributes,\n v => decodeEJSON(v, [...stack, self], options),\n ) as Record<string, TValue>;\n return isObjKey(className, TObjectTypes) ? new TObjectTypes[className](_attributes) : new TObject(className, _attributes);\n }\n return _.transform(x, (r, v, k) => {\n if (_.isString(k)) r[k.startsWith('$') ? k.substring(1) : k] = decodeEJSON(v, [...stack, r], options);\n }, {} as { [x: string]: TSerializable });\n}\n\nexport const serialize = (\n x: TSerializable,\n options?: SerializeOptions,\n) => JSON.stringify(encodeEJSON(x, [], options ?? {}), undefined, options?.space);\n\nexport const deserialize = (\n buffer: string,\n options?: DeserializeOptions,\n) => decodeEJSON(JSON.parse(buffer), [], options ?? {});\n","//\n// types.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { Awaitable } from '@o2ter/utils-js';\nimport { ProtoService } from '../../server/proto';\nimport { TSerializable } from '../codec';\nimport { TValueWithoutObject } from '../types';\nimport { TUser } from '../object/user';\nimport { TObjectType } from '../object/types';\n\n/**\n * A callback function type.\n * @param request - The request object.\n * @returns An awaitable response.\n */\ntype Callback<T, R, E> = (request: ProtoService<E> & T) => Awaitable<R>;\n\n/**\n * A callback function type.\n * @param request - The request object.\n * @returns An awaitable response.\n */\nexport type ProtoFunction<E, P extends TSerializable, R extends TSerializable | void> = Callback<{ params: P; }, R, E>;\n\n/**\n * A trigger callback function type.\n * @param request - The request object.\n * @returns An awaitable response.\n */\nexport type ProtoTriggerFunction<T, E> = Callback<{ object: TObjectType<T, E>; }, void, E>;\n\n/**\n * A job callback function type.\n * @param request - The request object.\n * @returns An awaitable response.\n */\nexport type ProtoJobFunction<E, P extends TValueWithoutObject> = Callback<{\n params: P;\n user?: TUser;\n job: TObjectType<'_Job', E>;\n}, void, E>;\n\n/**\n * Validator options for proto functions.\n */\ntype Validator = {\n /**\n * Indicates if a user is required.\n */\n requireUser?: boolean;\n\n /**\n * Indicates if a master user is required.\n */\n requireMaster?: boolean;\n\n /**\n * Indicates if any user roles are required.\n */\n requireAnyUserRoles?: string[];\n\n /**\n * Indicates if all user roles are required.\n */\n requireAllUserRoles?: string[];\n};\n\n/**\n * Options for configuring a proto function.\n */\nexport type ProtoFunctionOptions<E> = {\n /**\n * The callback function for the proto function.\n */\n callback: ProtoFunction<E, any, any>;\n\n /**\n * Optional validator for the proto function.\n */\n validator?: Validator;\n};\n\n/**\n * Options for configuring a proto job function.\n */\nexport type ProtoJobFunctionOptions<E> = {\n /**\n * The callback function for the proto job function.\n */\n callback: ProtoJobFunction<E, any>;\n\n /**\n * Optional scopes for the proto job function.\n */\n scopes?: string[];\n\n /**\n * Optional validator for the proto function.\n */\n validator?: Validator;\n};\n","//\n// session.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport jwt from 'jsonwebtoken';\nimport { CookieOptions, Request, Response } from '@o2ter/server-js';\nimport { ProtoService } from './index';\nimport { AUTH_COOKIE_KEY, AUTH_ALT_COOKIE_KEY, MASTER_PASS_HEADER_NAME, MASTER_USER_HEADER_NAME } from '../../internals/const';\nimport { randomUUID } from '@o2ter/crypto-js';\nimport { PVK } from '../../internals/private';\nimport { TUser } from '../../internals/object/user';\nimport { TRole } from '../../internals/object/role';\nimport { TSession } from '../../internals/object/session';\n\nexport type _Session = Awaited<ReturnType<typeof session>>;\n\nconst _sessionWithToken = async <E>(proto: ProtoService<E>, token: string) => {\n if (_.isEmpty(token)) return;\n const payload = proto[PVK].jwtVerify(token, 'login') ?? {} as any;\n if (!_.isString(payload.sessionId) || _.isEmpty(payload.sessionId)) return;\n const session = await proto.Query('_Session')\n .equalTo('token', payload.sessionId)\n .includes('user')\n .first({ master: true });\n if (!session) return;\n return { payload, session };\n}\n\nconst userCacheMap = new WeakMap<any, { [K in string]?: Promise<TRole[]>; }>();\nconst fetchUserRole = async <E>(proto: ProtoService<E>, user?: TUser) => {\n if (!userCacheMap.has(proto[PVK])) userCacheMap.set(proto[PVK], {});\n const cache = userCacheMap.get(proto[PVK])!;\n if (_.isNil(user?.id)) return {};\n if (_.isNil(cache[user.id])) cache[user.id] = (async () => {\n const _roles = user instanceof TUser ? _.filter(await proto.userRoles(user), x => !_.isEmpty(x.name)) : [];\n cache[user.id!] = undefined;\n return _roles;\n })();\n const _roles = await cache[user.id];\n return {\n user: user?.clone(),\n _roles: _.map(_roles, x => x.clone()),\n };\n}\n\nconst sessionMap = new WeakMap<Request, { payload: any, session: TSession } | undefined>();\nconst _session = async <E>(proto: ProtoService<E>, request: Request) => {\n\n const cached = sessionMap.get(request);\n if (cached) return {\n sessionId: cached.session.sessionId,\n createdAt: cached.session.createdAt!,\n updatedAt: cached.session.updatedAt!,\n loginedAt: cached.session.loginedAt,\n user: cached.session.user,\n cookieOptions: cached.payload.cookieOptions,\n };\n\n const cookieKey = _.last(_.castArray(request.headers[AUTH_ALT_COOKIE_KEY] || [])) || AUTH_COOKIE_KEY;\n\n let sessionId = '';\n if (request.headers.authorization) {\n const parts = request.headers.authorization.split(' ');\n if (parts.length === 2 && parts[0] === 'Bearer') sessionId = parts[1];\n } else if (request.cookies[cookieKey]) {\n sessionId = request.cookies[cookieKey];\n }\n\n const { payload, session } = await _sessionWithToken(proto, sessionId) ?? {};\n if (!session) return;\n\n sessionMap.set(request, { payload, session });\n return {\n sessionId: session.sessionId,\n createdAt: session.createdAt!,\n updatedAt: session.updatedAt!,\n loginedAt: session.loginedAt,\n user: session.user,\n cookieOptions: payload.cookieOptions,\n };\n}\n\ntype UserRole<E> = Partial<Awaited<ReturnType<typeof fetchUserRole<E>>>>;\nconst userRoleMap = new WeakMap<Request, UserRole<any>>();\n\nexport const session = async <E>(proto: ProtoService<E>, request: Request) => {\n\n const session = await _session(proto, request);\n const cached = userRoleMap.get(request) as UserRole<E>;\n if (cached) return {\n ...session ?? {},\n ...cached,\n };\n\n const info = await fetchUserRole(proto, session?.user);\n userRoleMap.set(request, info);\n\n return {\n ...session ?? {},\n ...info,\n };\n}\n\nexport const sessionWithToken = async <E>(proto: ProtoService<E>, token: string) => {\n\n const { payload, session } = await _sessionWithToken(proto, token) ?? {};\n if (!session) return;\n\n const info = await fetchUserRole(proto, session?.user);\n return {\n sessionId: session.sessionId,\n createdAt: session.createdAt!,\n updatedAt: session.updatedAt!,\n loginedAt: session.loginedAt,\n cookieOptions: payload.cookieOptions,\n ...info,\n } as _Session;\n}\n\nexport const sessionIsMaster = <E>(proto: ProtoService<E>, request: Request) => {\n const user = request.header(MASTER_USER_HEADER_NAME);\n const pass = request.header(MASTER_PASS_HEADER_NAME);\n if (_.isEmpty(user) || _.isEmpty(pass)) return false;\n return _.some(proto[PVK].options.masterUsers, x => x.user === user && x.pass === pass) ? 'valid' : 'invalid';\n}\n\nexport const signUser = async <E>(\n proto: ProtoService<E>,\n res: Response,\n user?: TUser,\n options?: {\n cookieOptions?: CookieOptions;\n jwtSignOptions?: jwt.SignOptions;\n }\n) => {\n if (_.isNil(proto[PVK].options.jwtToken)) return;\n const session = await _session(proto, res.req);\n const cookieOptions = options?.cookieOptions ?? session?.cookieOptions ?? proto[PVK].options.cookieOptions;\n const sessionId = session?.sessionId ?? randomUUID();\n const expiredAt = cookieOptions?.expires ?? (cookieOptions?.maxAge ? new Date(Date.now() + cookieOptions.maxAge) : undefined);\n const loginedAt = user ? session?.loginedAt ?? new Date() : undefined;\n await proto.Query('_Session')\n .equalTo('token', sessionId)\n .upsertOne(\n {\n loginedAt: { $set: loginedAt },\n user: { $set: user },\n _expired_at: { $set: expiredAt },\n },\n {\n token: sessionId,\n loginedAt: loginedAt,\n user,\n _expired_at: expiredAt,\n },\n { master: true }\n );\n const token = proto[PVK].jwtSign({\n sessionId,\n cookieOptions,\n }, options?.jwtSignOptions ?? 'login');\n const cookieKey = _.last(_.castArray(res.req.headers[AUTH_ALT_COOKIE_KEY] || [])) || AUTH_COOKIE_KEY;\n res.cookie(cookieKey, token, cookieOptions);\n userRoleMap.set(res.req, user ? await fetchUserRole(proto, user) : {});\n}\n","//\n// proto.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport axios from 'axios';\nimport { PVK } from '../private';\nimport type jwt from 'jsonwebtoken';\nimport type { CookieOptions, Request } from '@o2ter/server-js';\nimport type { SignOptions } from 'jsonwebtoken';\nimport { ExtraOptions } from '../options';\nimport { TQuery } from '../query';\nimport { TExtensions, TObjectType, TObjectTypes } from '../object/types';\nimport { TFile } from '../object/file';\nimport { FileData, FileStream } from '../buffer';\nimport { isObjKey } from '../utils';\nimport { applyObjectMethods } from '../object/methods';\nimport { TValue, TValueWithoutObject } from '../types';\nimport { TObject } from '../object';\nimport { TSerializable } from '../codec';\nimport { TUser } from '../object/user';\nimport { ProtoFunction, ProtoFunctionOptions, ProtoJobFunction, ProtoJobFunctionOptions, ProtoTriggerFunction } from './types';\nimport { Socket } from 'socket.io-client';\nimport { asyncStream } from '@o2ter/utils-js';\nimport { PathName } from '../query/types';\nimport { TRole } from '../object/role';\nimport { TJob } from '../object/job';\nimport { isFile, isJob, isObject, isQuery, isRole, isUser } from '../utils';\nimport { TQuerySelector } from '../query/types/selectors';\nimport { _Session } from '../../server/proto/session';\n\nexport const _logLevels = ['error', 'warn', 'info', 'debug', 'trace'] as const;\ntype _Logger = {\n [x in typeof _logLevels[number]]: (...args: any[]) => void;\n};\nexport type Logger = _Logger & {\n loggerLevel: keyof _Logger | 'all' | 'none';\n};\n\n/**\n * The mode of the transaction.\n */\nexport type TransactionMode = 'default' | 'committed' | 'repeatable' | 'serializable';\n\n/**\n * Options for configuring a transaction.\n */\nexport type TransactionOptions = {\n /**\n * The mode of the transaction.\n */\n mode?: TransactionMode;\n\n /**\n * The number of retries or a boolean indicating whether to retry.\n */\n retry?: number | boolean;\n};\n\n/**\n * Represents event data with additional metadata.\n */\nexport type EventData = Record<string, TValueWithoutObject> & {\n /**\n * The unique identifier for the event.\n */\n _id: string;\n\n /**\n * The creation date of the event.\n */\n _created_at: Date;\n\n /**\n * The read permissions for the event.\n */\n _rperm: string[];\n};\n\nexport interface ProtoInternalType<Ext, P extends ProtoType<any>> {\n\n options: {\n endpoint: string;\n classExtends?: TExtensions<Ext>;\n };\n\n saveFile(proto: P, object: TFile, options?: ExtraOptions<boolean>): Promise<TFile>;\n deleteFile(proto: P, object: TFile, options?: ExtraOptions<boolean>): Promise<TFile>;\n fileData(proto: P, object: TFile, options?: ExtraOptions<boolean>): FileStream;\n\n liveQuery(\n proto: P,\n event: string,\n className: string,\n filter: TQuerySelector[],\n callback: (object: TObject) => void,\n ): {\n remove: VoidFunction;\n socket?: Socket;\n };\n}\n\nexport abstract class ProtoType<Ext> {\n\n isQuery = isQuery;\n isObject = isObject;\n isUser = isUser;\n isRole = isRole;\n isFile = isFile;\n isJob = isJob;\n\n /** @internal */\n abstract [PVK]: ProtoInternalType<Ext, this>;\n\n /**\n * Gets the endpoint URL.\n * @returns The endpoint URL as a string.\n */\n get endpoint() {\n return this[PVK].options.endpoint;\n }\n\n /**\n * Retrieves the configuration.\n * @param options - Optional settings for retrieving the configuration.\n * @returns A promise that resolves to the configuration.\n */\n abstract config(options?: { master?: boolean; }): Promise<Record<string, TValueWithoutObject>>;\n\n /**\n * Retrieves the ACL of configuration.\n * @param options - Settings for retrieving the ACL of configuration.\n * @returns A promise that resolves to the ACL of configuration.\n */\n abstract configAcl(options: { master: true; }): PromiseLike<Record<string, string[]>>;\n\n /**\n * Sets the configuration.\n * @param values - The configuration values to set.\n * @param options - Settings for setting the configuration.\n * @returns A promise that resolves when the configuration is set.\n */\n abstract setConfig(values: Record<string, TValueWithoutObject>, options: { master: true; acl?: string[]; }): Promise<void>;\n\n /**\n * Runs a function.\n * @param name - The name of the function to run.\n * @param data - The data to pass to the function.\n * @param options - Additional options for running the function.\n * @returns A promise that resolves to the result of the function.\n */\n abstract run<R extends TSerializable | void = any>(\n name: string,\n data?: TSerializable,\n options?: ExtraOptions<boolean>\n ): Promise<R>;\n\n /**\n * Schedules a job.\n * @param name - The name of the job to schedule.\n * @param params - The parameters to pass to the job.\n * @param options - Additional options for scheduling the job.\n * @returns A promise that resolves when the job is scheduled.\n */\n abstract scheduleJob(name: string, params?: TValueWithoutObject, options?: ExtraOptions<boolean>): Promise<TJob>;\n\n /**\n * Creates a query.\n * @param className - The name of the class to query.\n * @returns A query instance.\n */\n abstract Query<T extends string>(className: T): TQuery<T, Ext, boolean>;\n\n /**\n * Creates a relation query.\n * @param object - The object to create the relation for.\n * @param key - The key of the relation.\n * @returns A relation query instance.\n */\n abstract Relation<T extends string>(object: TObject, key: PathName<T>): TQuery<string, Ext, boolean>;\n\n /**\n * Get all references to an object.\n * @param object - The object to get references for.\n * @param options - Additional options for getting references.\n * @returns A stream of references.\n */\n abstract refs(object: TObject, options?: ExtraOptions<boolean>): ReturnType<typeof asyncStream<TObjectType<string, Ext>>>;\n\n /**\n * Checks if the server is online.\n * @returns A promise that resolves to a boolean indicating if the server is online.\n */\n async online() {\n try {\n const res = await axios({\n method: 'get',\n baseURL: this[PVK].options.endpoint,\n url: 'health',\n });\n return res.status === 200;\n } catch {\n return false;\n }\n }\n\n /**\n * Rebinds an object to the proto instance.\n * @param object - The object to rebind.\n * @returns The rebinded object.\n */\n rebind<T extends TSerializable | undefined>(object: T): T {\n return applyObjectMethods(object, this);\n }\n\n /**\n * Creates a new object.\n * @param className - The name of the class to create.\n * @param id - The ID of the object to create.\n * @returns The created object.\n */\n Object<T extends string>(className: T, id?: string): TObjectType<T, Ext> {\n const attrs: Record<string, TValue> = id ? { _id: id } : {};\n const obj = isObjKey(className, TObjectTypes) ? new TObjectTypes[className](attrs) : new TObject(className, attrs);\n return this.rebind(obj as TObjectType<T, Ext>);\n }\n\n /**\n * Creates a new file object.\n * @param filename - The name of the file.\n * @param data - The file data.\n * @param type - The type of the file.\n * @returns The created file object.\n */\n File(filename: string, data: FileData, type?: string) {\n const file = this.Object('File');\n file.set('filename', filename);\n file.set('type', type);\n file[PVK].extra.data = data;\n return file;\n }\n\n /**\n * Notifies an event.\n * @param data - The data to notify.\n * @param options - Additional options for notifying the event.\n */\n abstract notify(\n data: Record<string, TValueWithoutObject> & { _rperm?: string[]; },\n options?: ExtraOptions<boolean>\n ): Promise<void>\n\n /**\n * Listens for events.\n * @param callback - The callback to call when an event occurs.\n * @returns An object with a remove function to stop listening.\n */\n abstract listen(\n callback: (data: EventData) => void,\n selector?: TQuerySelector\n ): {\n remove: VoidFunction;\n socket?: Socket;\n }\n};\n\nexport interface ProtoType<Ext> {\n\n get logger(): Logger;\n\n /**\n * Connects a request with optional attributes.\n * @param req - The request to connect.\n * @param attrs - Optional attributes or a function returning attributes.\n * @returns The instance with the request and attributes.\n */\n connect<R extends Request, T extends object>(\n req: R,\n attrs?: T | ((x: this & { req: R; }) => T)\n ): this & { req: R; } & T;\n\n /**\n * Connects using a session token with optional attributes.\n * @param token - The session token.\n * @param attrs - Optional attributes or a function returning attributes.\n * @returns A promise resolving to the instance with the session and attributes.\n */\n connectWithSessionToken<T extends object>(\n token: string,\n attrs?: T | ((x: this & { session?: _Session; }) => T)\n ): Promise<this & { session?: _Session; } & T>\n\n /**\n * Refreshes the authentication/session status for the socket connection.\n * \n * This method should be called when the session token or authentication state changes,\n * ensuring that any active socket connections are updated to reflect the new session.\n * Useful for maintaining real-time features (such as LiveQuery) after login, logout,\n * or session renewal.\n */\n refreshSocketSession(): void\n\n /**\n * Sets the session token.\n * @param token - The session token.\n */\n setSessionToken(token?: string): void\n\n /**\n * Retrieves the roles of a user.\n * @param user - The user whose roles are to be retrieved.\n * @returns A promise resolving to an array of roles.\n */\n userRoles(user: TUser): Promise<TRole[]>;\n\n /**\n * Becomes a specified user.\n * @param req - The request.\n * @param user - The user to become.\n * @param options - Optional cookie and JWT sign options.\n * @returns A promise resolving to void.\n */\n becomeUser(\n req: Request,\n user: TUser,\n options?: {\n cookieOptions?: CookieOptions | undefined;\n jwtSignOptions?: SignOptions | undefined;\n }\n ): Promise<void>;\n\n /**\n * Logs out a user.\n * @param req - The request.\n * @param options - Optional cookie and JWT sign options.\n * @returns A promise resolving to void.\n */\n logoutUser(\n req: Request,\n options?: {\n cookieOptions?: CookieOptions | undefined;\n jwtSignOptions?: SignOptions | undefined;\n }\n ): Promise<void>;\n\n /**\n * Verifies a user's password.\n * @param user - The user whose password is to be verified.\n * @param password - The password to verify.\n * @param options - Extra options.\n * @returns A promise resolving to a boolean indicating if the password is correct.\n */\n verifyPassword(user: TUser, password: string, options: ExtraOptions<true>): Promise<boolean>;\n\n /**\n * Sets a user's password.\n * @param user - The user whose password is to be set.\n * @param password - The new password.\n * @param options - Extra options.\n * @returns A promise resolving to void.\n */\n setPassword(user: TUser, password: string, options: ExtraOptions<true>): Promise<void>;\n\n /**\n * Unsets a user's password.\n * @param user - The user whose password is to be unset.\n * @param options - Extra options.\n * @returns A promise resolving to void.\n */\n unsetPassword(user: TUser, options: ExtraOptions<true>): Promise<void>;\n\n /**\n * Defines a new function.\n * @param name - The name of the function.\n * @param callback - The function callback.\n * @param options - Optional function options excluding the callback.\n */\n define<P extends TSerializable = any, R extends TSerializable | void = any>(\n name: string,\n callback: ProtoFunction<Ext, P, R>,\n options?: Omit<ProtoFunctionOptions<Ext>, 'callback'>,\n ): void;\n\n /**\n * Registers a callback to be executed after an object is created.\n * @param className - The name of the class.\n * @param callback - The callback function.\n */\n afterCreate<T extends string>(\n className: string,\n callback: ProtoTriggerFunction<T, Ext>,\n ): void;\n\n /**\n * Registers a callback to be executed after an object is updated.\n * @param className - The name of the class.\n * @param callback - The callback function.\n */\n afterUpdate<T extends string>(\n className: string,\n callback: ProtoTriggerFunction<T, Ext>,\n ): void;\n\n /**\n * Registers a callback to be executed after an object is deleted.\n * @param className - The name of the class.\n * @param callback - The callback function.\n */\n afterDelete<T extends string>(\n className: string,\n callback: ProtoTriggerFunction<T, Ext>,\n ): void;\n\n /**\n * Defines a new job function.\n * @param name - The name of the job function.\n * @param callback - The job function callback.\n * @param options - Optional job function options excluding the callback.\n */\n defineJob<P extends TValueWithoutObject = any>(\n name: string,\n callback: ProtoJobFunction<Ext, P>,\n options?: Omit<ProtoJobFunctionOptions<Ext>, 'callback'>,\n ): void;\n\n /**\n * Locks a table for updates.\n * @param className - The name of the class or an array of class names.\n * @param update - Whether to lock for update.\n */\n lockTable(className: string | string[], update: boolean): void;\n\n /**\n * Executes a callback within a transaction.\n * @param callback - The callback to execute.\n * @param options - Optional transaction options.\n */\n withTransaction<T>(\n callback: (connection: ProtoType<Ext>) => PromiseLike<T>,\n options?: TransactionOptions,\n ): void;\n\n /**\n * Generates an upload token.\n * @param options - Optional settings for the upload token.\n * @returns The generated upload token.\n */\n generateUploadToken(\n options?: { maxUploadSize?: number; }\n ): string;\n\n /**\n * Signs a JWT.\n * @param payload - The payload to sign.\n * @param options - Options for signing the JWT.\n * @returns The signed JWT.\n */\n jwtSign(payload: any, options: jwt.SignOptions): string;\n\n /**\n * Verifies a JWT.\n * @param token - The token to verify.\n * @param options - Options for verifying the JWT.\n * @returns The decoded JWT payload or undefined if verification fails.\n */\n jwtVerify(token: string, options?: jwt.VerifyOptions): jwt.JwtPayload | undefined;\n};\n","//\n// options.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { ProtoType } from './proto';\n\n/**\n * Represents additional options that can be passed to certain methods.\n */\nexport type ExtraOptions<M extends boolean> = {\n /**\n * Indicates whether the master option is enabled.\n */\n master?: M;\n\n /**\n * The session associated with the operation.\n */\n session?: ProtoType<any>;\n\n /**\n * An AbortSignal object that can be used to abort the operation.\n */\n abortSignal?: AbortSignal;\n\n /**\n * Disable the triggers.\n * \n * Only effective when `master` is `true`.\n */\n silent?: boolean;\n};\n","//\n// object.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { PVK } from '../private';\nimport { ExtraOptions } from '../options';\nimport { Decimal } from 'decimal.js';\nimport { TPrimitiveValue, TValue, TValueWithoutObject, TValueWithUndefined } from '../types';\nimport { TSchema, defaultObjectKeys, defaultObjectReadonlyKeys } from '../schema';\nimport { IncludePaths, PathName } from '../query/types';\nimport { TUpdateOp, TUpdateOpKeys } from './types';\nimport { TQuery } from '../query';\n\nexport const isPrimitiveValue = (x: any): x is TPrimitiveValue => {\n if (_.isNil(x) || _.isNumber(x) || _.isBoolean(x) || _.isString(x) || _.isDate(x)) return true;\n if (x instanceof Decimal) return true;\n return false;\n}\n\nexport const isValue = (x: any): x is TValue => {\n if (isPrimitiveValue(x) || x instanceof TObject) return true;\n if (_.isArray(x)) return _.every(x, v => isValue(v));\n if (_.isPlainObject(x)) return _.every(x, v => isValue(v));\n return false;\n}\n\nexport const cloneValue = <T extends TValue>(x: T): T => {\n if (isPrimitiveValue(x) || x instanceof TObject) return x;\n if (_.isArray(x)) return x.map(v => cloneValue(v)) as T;\n return _.mapValues(x, v => cloneValue(v)) as T;\n}\n\nexport const _decodeValue = (value: TValueWithoutObject): TValueWithoutObject => {\n if (isPrimitiveValue(value)) return value;\n if (_.isArray(value)) return _.map(value, x => _decodeValue(x));\n if (_.isString(value.$date)) return new Date(value.$date);\n if (_.isString(value.$decimal)) return new Decimal(value.$decimal);\n return _.transform(value, (r, v, k) => {\n r[k.startsWith('$') ? k.substring(1) : k] = _decodeValue(v);\n }, {} as any);\n};\n\nexport const _encodeValue = (value: TValueWithUndefined): TValueWithoutObject => {\n if (_.isNil(value)) return value ?? null;\n if (value instanceof TObject) throw Error('Invalid data type');\n if (_.isDate(value)) return { $date: value.toISOString() };\n if (value instanceof Decimal) return { $decimal: value.toString() };\n if (isPrimitiveValue(value)) return value;\n if (_.isArray(value)) return _.map(value, x => _encodeValue(x));\n return _.transform(value, (r, v, k) => {\n r[k.startsWith('$') ? `$${k}` : k] = _encodeValue(v);\n }, {} as any);\n};\n\nexport const decodeUpdateOp = (update: TUpdateOp) => {\n const pairs = _.toPairs(update);\n if (pairs.length !== 1) throw Error('Invalid update operation');\n return pairs[0] as [typeof TUpdateOpKeys[number], TValue];\n}\n\n/**\n * Interface representing a object.\n */\nexport interface TObject {\n /**\n * Clones the object.\n * @returns A clone of the object.\n */\n clone(): this;\n\n /**\n * Gets a relation query for the specified key.\n * @param key - The key of the relation.\n * @returns A query object for the relation.\n */\n relation<T extends string>(key: PathName<T>): TQuery<string, any, boolean>;\n\n /**\n * Fetches the object with the specified keys included.\n * @param keys - The keys to include.\n * @param options - Additional options for the fetch operation.\n * @returns A promise that resolves to the fetched object.\n */\n fetchWithInclude<T extends _.RecursiveArray<string>>(keys: IncludePaths<T>, options?: ExtraOptions<boolean>): PromiseLike<this>;\n\n /**\n * Saves the object.\n * @param options - Additional options for the save operation.\n * @returns A promise that resolves to the saved object.\n */\n save(options?: ExtraOptions<boolean> & { cascadeSave?: boolean }): PromiseLike<this>;\n\n /**\n * Destroys the object.\n * @param options - Additional options for the destroy operation.\n * @returns A promise that resolves to the destroyed object.\n */\n destroy(options?: ExtraOptions<boolean>): PromiseLike<this>;\n}\n\n/**\n * Class representing a object.\n */\nexport class TObject {\n\n static defaultReadonlyKeys = defaultObjectReadonlyKeys;\n static defaultKeys = defaultObjectKeys;\n\n /** @internal */\n [PVK]: {\n className: string;\n attributes: Record<string, TValue>;\n mutated: Record<string, TUpdateOp>;\n extra: Record<string, any>;\n };\n\n constructor(\n className: string,\n attributes?: Record<string, TValue> | ((self: TObject) => Record<string, TValue>),\n ) {\n const _attributes = _.isFunction(attributes) ? attributes(this) : attributes ?? {};\n this[PVK] = {\n className,\n attributes: cloneValue(_attributes),\n mutated: {},\n extra: {},\n }\n }\n\n /**\n * Gets the class name of the object.\n */\n get className(): string {\n return this[PVK].className;\n }\n\n /**\n * Gets the attributes of the object.\n */\n get attributes(): Record<string, TValue> {\n return cloneValue(this[PVK].attributes);\n }\n\n /**\n * Gets the object ID.\n */\n get id(): string | undefined {\n return this[PVK].attributes._id as string;\n }\n\n /**\n * Gets the creation date of the object.\n */\n get createdAt(): Date | undefined {\n return this[PVK].attributes._created_at as Date;\n }\n\n /**\n * Gets the last updated date of the object.\n */\n get updatedAt(): Date | undefined {\n return this[PVK].attributes._updated_at as Date;\n }\n\n /**\n * Gets the version number of the object.\n */\n get __v(): number {\n return this[PVK].attributes.__v as number;\n }\n\n /**\n * Gets the sequence number of the object.\n */\n get __i(): number {\n return this[PVK].attributes.__i as number;\n }\n\n /**\n * Gets the expiration date of the object.\n */\n get expiredAt(): Date | undefined {\n return this.get('_expired_at');\n }\n\n /**\n * Sets the expiration date of the object.\n * @param value - The expiration date.\n */\n set expiredAt(value: Date | undefined) {\n this.set('_expired_at', value);\n }\n\n /**\n * Gets the access control list (ACL) of the object.\n * @returns The ACL of the object.\n */\n acl(): TSchema.ACLs {\n return {\n read: this.get('_rperm') ?? ['*'],\n update: this.get('_wperm') ?? ['*'],\n };\n }\n\n /**\n * Sets the access control list (ACL) of the object.\n * @param value - The ACL to set.\n */\n setAcl(value: Partial<TSchema.ACLs>) {\n this.set('_rperm', value.read ?? ['*']);\n this.set('_wperm', value.update ?? ['*']);\n }\n\n /**\n * Sets the read access control list (ACL) of the object.\n * @param value - The read ACL to set.\n */\n setReadAcl(value: TSchema.ACL) {\n this.set('_rperm', value);\n }\n\n /**\n * Sets the write access control list (ACL) of the object.\n * @param value - The write ACL to set.\n */\n setWriteAcl(value: TSchema.ACL) {\n this.set('_wperm', value);\n }\n\n /**\n * Gets the keys of the object's attributes and mutated attributes.\n * @returns An array of keys.\n */\n keys(): string[] {\n return _.uniq([..._.keys(this[PVK].attributes), ..._.compact(_.map(_.keys(this[PVK].mutated), x => _.first(_.toPath(x))))]);\n }\n\n /**\n * Gets an iterator for the entries of the object's attributes.\n * @returns An iterator for the entries.\n */\n *entries() {\n for (const key of this.keys()) {\n yield [key, this.get(key)] as [string, any];\n }\n }\n\n /** @internal */\n *_set_entries() {\n for (const [key, op] of _.entries(this[PVK].mutated)) {\n for (const [_op, value] of _.entries(op)) {\n if (_op === '$set') yield [key, value] as [string, any];\n }\n }\n }\n\n /**\n * Converts the object to a plain object.\n * @param replacer - An optional function to replace values during the conversion.\n * @returns The plain object representation of the object.\n */\n toObject(replacer?: (value: TObject) => any): any {\n const toObject = (value: TValue): any => {\n if (isPrimitiveValue(value)) return value;\n if (value instanceof TObject) return replacer?.(value) ?? value.toObject(replacer);\n if (_.isArray(value)) return _.map(value, toObject);\n return _.mapValues(value, toObject);\n };\n return _.fromPairs(_.map(this.keys(), k => [k, toObject(this.get(k))]));\n }\n\n private _value(key: string): TValue {\n let value: TValue = this[PVK].attributes;\n for (const k of _.toPath(key)) {\n if (isPrimitiveValue(value)) return null;\n if (value instanceof TObject) {\n value = value.get(k);\n } else {\n value = _.get(value, k);\n }\n }\n return cloneValue(value);\n }\n\n /**\n * Get the value of the attribute.\n * @param key - The key of the attribute.\n * @returns The value of the attribute.\n */\n get<T extends string>(key: PathName<T>): any {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (_.isNil(this[PVK].mutated[key])) return this._value(key);\n const [op, value] = decodeUpdateOp(this[PVK].mutated[key]);\n return op === '$set' ? value : this._value(key);\n }\n\n /**\n * Set the value of the attribute.\n * @param key - The key of the attribute.\n * @param value - The value to set.\n */\n set<T extends string>(key: PathName<T>, value: TValueWithUndefined) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $set: value ?? null };\n }\n\n /**\n * Is the object dirty.\n */\n get isDirty(): boolean {\n return !_.isEmpty(this[PVK].mutated);\n }\n\n /**\n * Increment the value of the attribute.\n * @param key - The key to increment.\n * @param value - The value to increment by.\n */\n increment<T extends string>(key: PathName<T>, value: number | Decimal) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $inc: value };\n }\n\n /**\n * Decrement the value of the attribute.\n * @param key - The key to decrement.\n * @param value - The value to decrement by.\n */\n decrement<T extends string>(key: PathName<T>, value: number | Decimal) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $dec: value };\n }\n\n /**\n * Multiplies the value of the specified attribute.\n * @param key - The key of the attribute to multiply.\n * @param value - The multiplier value.\n */\n multiply<T extends string>(key: PathName<T>, value: number | Decimal) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $mul: value };\n }\n\n /**\n * Divides the value of the specified attribute.\n * @param key - The key of the attribute to divide.\n * @param value - The divisor value.\n */\n divide<T extends string>(key: PathName<T>, value: number | Decimal) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $div: value };\n }\n\n /**\n * Sets the value of the specified attribute to the maximum of the current value and the provided value.\n * @param key - The key of the attribute to compare.\n * @param value - The value to compare against.\n */\n max<T extends string>(key: PathName<T>, value: TValue) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $max: value };\n }\n\n /**\n * Sets the value of the specified attribute to the minimum of the current value and the provided value.\n * @param key - The key of the attribute to compare.\n * @param value - The value to compare against.\n */\n min<T extends string>(key: PathName<T>, value: TValue) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $min: value };\n }\n\n /**\n * Adds the specified values to the set of the specified attribute.\n * @param key - The key of the attribute.\n * @param values - The values to add to the set.\n */\n addToSet<T extends string>(key: PathName<T>, values: TValue[]) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $addToSet: values };\n }\n\n /**\n * Adds the values to the array of the attribute.\n * @param key - The key of the attribute.\n * @param values - The values to add.\n */\n push<T extends string>(key: PathName<T>, values: TValue[]) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $push: values };\n }\n\n /**\n * Removes the values from the array of the attribute.\n * @param key - The key of the attribute.\n * @param values - The values to remove.\n */\n removeAll<T extends string>(key: PathName<T>, values: TValue[]) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $removeAll: values };\n }\n\n /**\n * Removes the first elements from the array of the attribute.\n * @param key - The key of the attribute.\n * @param count - The number of elements to remove. Defaults to 1.\n */\n popFirst<T extends string>(key: PathName<T>, count = 1) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $popFirst: count };\n }\n\n /**\n * Removes the last elements from the array of the attribute.\n * @param key - The key of the attribute.\n * @param count - The number of elements to remove. Defaults to 1.\n */\n popLast<T extends string>(key: PathName<T>, count = 1) {\n if (_.isEmpty(key)) throw Error('Invalid key');\n if (TObject.defaultReadonlyKeys.includes(_.first(_.toPath(key))!)) return;\n this[PVK].mutated[key] = { $popLast: count };\n }\n\n /**\n * Fetches the object data.\n * @param options - Additional options for the fetch operation.\n * @returns A promise that resolves to the fetched object.\n */\n async fetch(options?: ExtraOptions<boolean>) {\n return this.fetchWithInclude(_.keys(this[PVK].attributes), options);\n }\n\n /**\n * Fetches the object data if needed.\n * @param keys - The keys of the attributes to fetch.\n * @param options - Additional options for the fetch operation.\n * @returns A promise that resolves to the fetched object.\n */\n async fetchIfNeeded<T extends _.RecursiveArray<string>>(keys: IncludePaths<T>, options?: ExtraOptions<boolean>) {\n const current = _.keys(this[PVK].attributes);\n if (_.every(keys, k => _.includes(current, k))) return this;\n return this.fetchWithInclude([current, keys], options);\n }\n\n}\n","//\n// types.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport Decimal from 'decimal.js';\nimport { TObject } from './object';\n\nexport type _TContainer<Primitive> = { [x: string]: _TContainer<Primitive>; } | _TContainer<Primitive>[] | Primitive;\n\nexport type TPrimitiveValue = boolean | number | Decimal | string | Date | null;\nexport type TValueWithUndefined = _TContainer<TPrimitiveValue | TObject | undefined>;\nexport type TValueWithoutObject = _TContainer<TPrimitiveValue>;\nexport type TValue = _TContainer<TPrimitiveValue | TObject>;\n\nexport type Exact<T, Shape> =\n T extends Shape ?\n Exclude<keyof T, keyof Shape> extends never ?\n T : never : never;\n\nexport type ExactOneProp<T> = {\n [K in keyof T]-?: Pick<T, K> & { [P in Exclude<keyof T, K>]?: never }\n}[keyof T];\n","//\n// schema.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TValueWithoutObject } from './types';\nimport { TQueryBaseOptions } from './query/base';\n\nexport namespace TSchema {\n /**\n * Access Control List (ACL).\n * \n * An array of strings representing users or roles that have access to a resource.\n */\n export type ACL = string[];\n\n /**\n * Access Control Lists for read and update operations.\n * \n * Defines separate ACLs for reading and updating an object.\n */\n export type ACLs = {\n /**\n * ACL for read operation.\n * Users or roles allowed to read the object.\n */\n read: TSchema.ACL;\n\n /**\n * ACL for update operation.\n * Users or roles allowed to update the object.\n */\n update: TSchema.ACL;\n };\n\n /**\n * Supported primitive data types.\n */\n export type Primitive =\n | 'boolean'\n | 'number'\n | 'decimal'\n | 'string'\n | 'string[]'\n | 'date'\n | 'object'\n | 'array';\n\n /**\n * Primitive type with optional default value.\n * \n * Can be a string literal (e.g., 'string') or an object specifying the type and a default value.\n */\n export type PrimitiveType =\n | Primitive\n | {\n /**\n * The primitive type.\n */\n type: Primitive;\n\n /**\n * Optional default value for the field.\n */\n default?: TValueWithoutObject;\n };\n\n /**\n * Vector type with a specified dimension and optional default value.\n * \n * Used for fields storing fixed-length numeric arrays (vectors).\n */\n export type VectorType = {\n /**\n * The type of the field. Always 'vector'.\n */\n type: 'vector';\n\n /**\n * The dimension (length) of the vector.\n */\n dimension: number;\n\n /**\n * Optional default value for the vector.\n */\n default?: number[];\n };\n\n /**\n * Shape type for nested objects.\n * \n * Allows defining complex, nested object structures with their own field types.\n */\n export type ShapeType = {\n /**\n * The type of the field. Always 'shape'.\n */\n type: 'shape';\n\n /**\n * The shape definition, mapping field names to their data types.\n */\n shape: Record<string, DataType>;\n };\n\n /**\n * Pointer type for referencing another class.\n * \n * Represents a one-to-one relationship to another object.\n */\n export type PointerType = {\n /**\n * The type of the field. Always 'pointer'.\n */\n type: 'pointer';\n\n /**\n * The name of the target class being referenced.\n */\n target: string;\n };\n\n /**\n * Relation type for referencing multiple objects in another class.\n * \n * Represents a one-to-many or many-to-many relationship.\n * - `target`: The related class name.\n * - `foreignField`: (Optional) The field in the target class that refers back to this class.\n * - `match`: (Optional) Default match query options (filter, sort, etc.) applied when querying this relation.\n * Only used if `foreignField` is set.\n */\n export type RelationType = {\n /**\n * The type of the field. Always 'relation'.\n */\n type: 'relation';\n\n /**\n * The name of the target class for this relation.\n */\n target: string;\n\n /**\n * (Optional) The field in the target class that refers back to this class.\n * If provided, the relation is managed via this foreign key.\n */\n foreignField?: string;\n\n /**\n * (Optional) Default match query options for this relation.\n * \n * These options define default query behaviors—such as filtering, sorting, limiting results, and other query parameters—\n * that will be automatically applied when querying this relation via the specified `foreignField`.\n * \n * Note: `match` is only applicable if `foreignField` is set. If `foreignField` is not provided, `match` will be ignored.\n */\n match?: TQueryBaseOptions;\n };\n\n /**\n * Data type for schema fields.\n * \n * Can be a primitive, vector, shape, pointer, or relation type.\n */\n export type DataType =\n | PrimitiveType\n | VectorType\n | ShapeType\n | PointerType\n | RelationType;\n\n /**\n * Class Level Permissions (CLPs).\n * \n * Defines access control for various operations at the class level.\n */\n export type CLPs = {\n /**\n * ACL for get (read single object) operation.\n */\n get?: TSchema.ACL;\n\n /**\n * ACL for find (query multiple objects) operation.\n */\n find?: TSchema.ACL;\n\n /**\n * ACL for count operation.\n */\n count?: TSchema.ACL;\n\n /**\n * ACL for create operation.\n */\n create?: TSchema.ACL;\n\n /**\n * ACL for update operation.\n */\n update?: TSchema.ACL;\n\n /**\n * ACL for delete operation.\n */\n delete?: TSchema.ACL;\n };\n\n /**\n * Field Level Permissions (FLPs).\n * \n * Defines access control for individual fields.\n */\n export type FLPs = {\n /**\n * ACL for reading the field.\n */\n read?: TSchema.ACL;\n\n /**\n * ACL for creating the field.\n */\n create?: TSchema.ACL;\n\n /**\n * ACL for updating the field.\n */\n update?: TSchema.ACL;\n };\n\n /**\n * Index definitions for the schema.\n * \n * Supports both basic and vector indexes.\n */\n export type Indexes = {\n /**\n * Type of the index. Default is 'basic'.\n */\n type?: 'basic';\n\n /**\n * Keys for the index, mapping field names to sort order (1 for ascending, -1 for descending).\n */\n keys: Record<string, 1 | -1>;\n\n /**\n * Whether the index is unique.\n */\n unique?: boolean;\n } | {\n /**\n * Type of the index. Must be 'vector' for vector indexes.\n */\n type: 'vector';\n\n /**\n * Keys for the vector index. Can be a single field or an array of fields.\n */\n keys: string | string[];\n\n /**\n * Method for the vector index. Supported: 'hnsw', 'ivfflat'.\n */\n method?: 'hnsw' | 'ivfflat';\n };\n}\n\nexport const _isTypeof = (x: TSchema.DataType, types: string | string[]) => {\n if (_.isString(x)) return _.includes(_.castArray(types), x);\n return _.includes(_.castArray(types), x.type);\n};\nexport const isPrimitive = (x: TSchema.DataType): x is TSchema.PrimitiveType => _.isString(x) || (x.type !== 'pointer' && x.type !== 'relation' && x.type !== 'shape');\nexport const isVector = (x: TSchema.DataType): x is TSchema.VectorType => !_.isString(x) && x.type === 'vector';\nexport const dimensionOf = (x: TSchema.DataType) => isVector(x) ? x.dimension : 0;\nexport const isShape = (x: TSchema.DataType): x is TSchema.ShapeType => !_.isString(x) && x.type === 'shape';\nexport const isPointer = (x: TSchema.DataType): x is TSchema.PointerType => !_.isString(x) && x.type === 'pointer';\nexport const isRelation = (x: TSchema.DataType): x is TSchema.RelationType => !_.isString(x) && x.type === 'relation';\nexport const _typeof = (x: TSchema.DataType) => _.isString(x) ? x : x.type !== 'pointer' && x.type !== 'relation' ? x.type : x.target;\n\nexport const shapePaths = (x: TSchema.ShapeType): {\n path: string,\n type: Exclude<TSchema.DataType, TSchema.ShapeType>,\n}[] => _.flatMap(x.shape, (v, k) => (\n isShape(v) ? _.map(shapePaths(v), x => ({ path: `${k}.${x.path}`, type: x.type })) : { path: k, type: v }\n));\n\nexport interface TSchema {\n /**\n * Fields of the schema, where each field is a data type.\n */\n fields: Record<string, TSchema.DataType>;\n\n /**\n * Class level permissions for the schema.\n */\n classLevelPermissions?: TSchema.CLPs;\n\n /**\n * Additional object permissions for the schema.\n */\n additionalObjectPermissions?: TSchema.ACLs;\n\n /**\n * Field level permissions for the schema, where each field can have its own permissions.\n */\n fieldLevelPermissions?: Record<string, TSchema.FLPs>;\n\n /**\n * Secure fields in the schema.\n */\n secureFields?: string[];\n\n /**\n * Indexes for the schema.\n */\n indexes?: TSchema.Indexes[];\n\n /**\n * Indicates if live query is enabled for the schema.\n */\n liveQuery?: boolean;\n}\n\nexport const defaultObjectKeyTypes: Record<string, TSchema.DataType> = {\n _id: 'string',\n __v: 'number',\n __i: 'number',\n _created_at: 'date',\n _updated_at: 'date',\n _expired_at: 'date',\n _rperm: 'string[]',\n _wperm: 'string[]',\n};\n\nexport const defaultObjectReadonlyKeys = ['_id', '__v', '__i', '_created_at', '_updated_at'];\nexport const defaultObjectKeys = [...defaultObjectReadonlyKeys, '_expired_at', '_rperm', '_wperm'];\n","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { ProtoService } from '../proto/index';\nimport { TSchema } from '../../internals/schema';\nimport { BinaryData } from '@o2ter/utils-js';\n\n/**\n * Represents file information.\n */\nexport type TFileInfo = {\n /**\n * The MIME type of the file.\n */\n mimeType?: string;\n\n /**\n * The filename.\n */\n filename?: string;\n};\n\n/**\n * Interface for file storage operations.\n */\nexport interface TFileStorage {\n\n /**\n * The schema definition for the file storage.\n */\n schema: Record<string, TSchema>;\n\n /**\n * Creates a new file in the storage.\n * @param proto - The ProtoService instance.\n * @param stream - The binary data stream or async iterable of binary data.\n * @param info - The file information.\n * @param maxUploadSize - The maximum upload size.\n * @returns A promise that resolves to an object containing the file ID and size.\n */\n create<E>(\n proto: ProtoService<E>,\n stream: BinaryData | AsyncIterable<BinaryData>,\n info: TFileInfo,\n maxUploadSize: number,\n ): PromiseLike<{ _id: string; size: number; }>;\n\n /**\n * Destroys a file in the storage.\n * @param proto - The ProtoService instance.\n * @param id - The ID of the file to destroy.\n * @returns A promise that resolves when the file is destroyed.\n */\n destroy<E>(proto: ProtoService<E>, id: string): PromiseLike<void>;\n\n /**\n * Retrieves file data from the storage.\n * @param proto - The ProtoService instance.\n * @param id - The ID of the file.\n * @param start - The optional start byte position.\n * @param end - The optional end byte position.\n * @returns An async iterable of binary data.\n */\n fileData<E>(proto: ProtoService<E>, id: string, start?: number, end?: number): AsyncIterable<BinaryData>;\n\n}","//\n// expressions.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TBinaryExprKeys, TDistanceExprKeys, TExpression, TListExprKeys, TZeroParamExprKeys, TUnaryExprKeys, TTernaryExprKeys } from '../../../../internals/query/types/expressions';\nimport { TComparisonKeys, TConditionalKeys } from '../../../../internals/query/types/keys';\nimport { isValue } from '../../../../internals/object';\nimport { TValue } from '../../../../internals/types';\nimport { cosine, distance, equal, getValue, greaterThan, greaterThanOrEqual, innerProduct, lessThan, lessThanOrEqual, rectilinearDistance } from './utils';\nimport { isPrimitive, isVector, TSchema } from '../../../../internals/schema';\nimport { resolveColumn } from '../validator';\nimport Decimal from 'decimal.js';\nimport { MathUtils } from './math';\n\nconst combineNumericTypes = (...list: _.RecursiveArray<TSchema.DataType>): TSchema.DataType[] => {\n return _.some(_.flattenDeep(list), x => x === 'decimal') ? ['decimal'] : ['number'];\n};\n\nexport class QueryExpression {\n\n static decode(expr: _.Many<TExpression>, dollerSign: boolean): QueryExpression {\n const exprs: QueryExpression[] = [];\n for (const selector of _.castArray(expr)) {\n for (const [key, query] of _.toPairs(selector)) {\n if (_.includes(TConditionalKeys, key) && _.isArray(query)) {\n exprs.push(new QueryCoditionalExpression(\n key as any,\n _.map(query, x => QueryExpression.decode(x as any, dollerSign)))\n );\n } else if (_.includes(TZeroParamExprKeys, key)) {\n exprs.push(new QueryZeroParamExpression(key as any));\n } else if (_.includes(TUnaryExprKeys, key)) {\n exprs.push(new QueryUnaryExpression(\n key as any,\n QueryExpression.decode(query as any, dollerSign))\n );\n } else if (_.includes(TBinaryExprKeys, key) && _.isArray(query) && query.length === 2) {\n const [left, right] = query;\n exprs.push(new QueryBinaryExpression(\n key as any,\n QueryExpression.decode(left as any, dollerSign),\n QueryExpression.decode(right as any, dollerSign))\n );\n } else if (_.includes(TTernaryExprKeys, key) && _.isArray(query) && query.length === 3) {\n const [first, second, last] = query;\n exprs.push(new QueryTernaryExpression(\n key as any,\n QueryExpression.decode(first as any, dollerSign),\n QueryExpression.decode(second as any, dollerSign),\n QueryExpression.decode(last as any, dollerSign))\n );\n } else if (_.includes(TListExprKeys, key) && _.isArray(query)) {\n if (query.length === 0) throw Error('Invalid expression');\n exprs.push(new QueryListExpression(\n key as any,\n _.map(query, x => QueryExpression.decode(x as any, dollerSign)))\n );\n } else if (_.includes(TComparisonKeys, key) && _.isArray(query) && query.length === 2) {\n const [left, right] = query;\n exprs.push(new QueryComparisonExpression(\n key as any,\n QueryExpression.decode(left as any, dollerSign),\n QueryExpression.decode(right as any, dollerSign))\n );\n } else if (_.includes(TDistanceExprKeys, key) && _.isArray(query) && query.length === 2) {\n const [left, right] = query;\n const _left = _.isArray(left) ? _.map(left, x => QueryExpression.decode(x as any, dollerSign)) : QueryExpression.decode(left as any, dollerSign);\n const _right = _.isArray(right) ? _.map(right, x => QueryExpression.decode(x as any, dollerSign)) : QueryExpression.decode(right as any, dollerSign);\n exprs.push(new QueryDistanceExpression(\n key as any,\n _.castArray(_left), _.castArray(_right))\n );\n } else if (key === '$cond' && _.isPlainObject(query)) {\n const { branch: _branch, default: defaultCase } = query as any;\n const branch = _.castArray(_branch ?? []);\n if (branch.length === 0) throw Error('Invalid expression');\n exprs.push(new QueryCondExpression(\n _.map(branch as any, ({ case: c, then: t }) => ({\n case: QueryExpression.decode(c as any, dollerSign),\n then: QueryExpression.decode(t as any, dollerSign),\n })),\n QueryExpression.decode(defaultCase as any, dollerSign)\n ));\n } else if (key === '$not') {\n exprs.push(new QueryNotExpression(QueryExpression.decode(query as any, dollerSign)));\n } else if (key === '$array' && _.isArray(query)) {\n exprs.push(new QueryArrayExpression(_.map(query, x => QueryExpression.decode(x as any, dollerSign))));\n } else if (key === '$key' && _.isString(query)) {\n if (dollerSign && query === '$') {\n exprs.push(new QueryKeyExpression(query));\n } else if (!query.startsWith('$')) {\n exprs.push(new QueryKeyExpression(query));\n } else {\n throw Error('Invalid expression');\n }\n } else if (key === '$value' && isValue(query)) {\n exprs.push(new QueryValueExpression(query));\n } else {\n throw Error('Invalid expression');\n }\n }\n }\n if (_.isEmpty(exprs)) return new QueryExpression;\n return (exprs.length === 1 ? exprs[0] : new QueryCoditionalExpression('$and', exprs)).simplify();\n }\n\n simplify(): QueryExpression {\n return this;\n }\n\n keyPaths(): string[] {\n return [];\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return this;\n }\n\n eval(value: any): any {\n return true;\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return [];\n }\n}\n\nexport class QueryCoditionalExpression extends QueryExpression {\n\n type: typeof TConditionalKeys[number];\n exprs: QueryExpression[];\n\n constructor(type: typeof TConditionalKeys[number], exprs: QueryExpression[]) {\n super();\n this.type = type;\n this.exprs = exprs;\n }\n\n simplify() {\n if (_.isEmpty(this.exprs)) return new QueryExpression;\n if (this.exprs.length === 1 && this.type !== '$nor') return this.exprs[0];\n switch (this.type) {\n case '$and':\n return new QueryCoditionalExpression(this.type, _.flatMap(\n this.exprs, x => x instanceof QueryCoditionalExpression && x.type === '$and' ? _.map(x.exprs, y => y.simplify()) : [x.simplify()]\n )) as QueryExpression;\n case '$nor':\n case '$or':\n return new QueryCoditionalExpression(this.type, _.flatMap(\n this.exprs, x => x instanceof QueryCoditionalExpression && x.type === '$or' ? _.map(x.exprs, y => y.simplify()) : [x.simplify()]\n )) as QueryExpression;\n }\n }\n\n keyPaths(): string[] {\n return _.uniq(_.flatMap(this.exprs, x => x.keyPaths()));\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryCoditionalExpression(this.type, _.map(this.exprs, x => x.mapKey(callback)));\n }\n\n eval(value: any) {\n switch (this.type) {\n case '$and': return _.every(this.exprs, expr => expr.eval(value));\n case '$nor': return !_.some(this.exprs, expr => expr.eval(value));\n case '$or': return _.some(this.exprs, expr => expr.eval(value));\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return ['boolean'];\n }\n}\n\nexport class QueryComparisonExpression extends QueryExpression {\n\n type: typeof TComparisonKeys[number];\n left: QueryExpression;\n right: QueryExpression;\n\n constructor(type: typeof TComparisonKeys[number], left: QueryExpression, right: QueryExpression) {\n super();\n this.type = type;\n this.left = left;\n this.right = right;\n }\n\n simplify() {\n return new QueryComparisonExpression(this.type, this.left.simplify(), this.right.simplify());\n }\n\n keyPaths(): string[] {\n return _.uniq([\n ...this.left.keyPaths(),\n ...this.right.keyPaths(),\n ]);\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryComparisonExpression(this.type, this.left.mapKey(callback), this.right.mapKey(callback));\n }\n\n eval(value: any) {\n switch (this.type) {\n case '$eq': return equal(this.left.eval(value), this.right.eval(value));\n case '$gt': return greaterThan(this.left.eval(value), this.right.eval(value));\n case '$gte': return greaterThanOrEqual(this.left.eval(value), this.right.eval(value));\n case '$lt': return lessThan(this.left.eval(value), this.right.eval(value));\n case '$lte': return lessThanOrEqual(this.left.eval(value), this.right.eval(value));\n case '$ne': return !equal(this.left.eval(value), this.right.eval(value));\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return ['boolean'];\n }\n}\n\nexport class QueryNotExpression extends QueryExpression {\n\n expr: QueryExpression;\n\n constructor(expr: QueryExpression) {\n super();\n this.expr = expr;\n }\n\n simplify() {\n return new QueryNotExpression(this.expr.simplify());\n }\n\n keyPaths(): string[] {\n return this.expr.keyPaths();\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryNotExpression(this.expr.mapKey(callback));\n }\n\n eval(value: any) {\n return !this.expr.eval(value);\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return ['boolean'];\n }\n}\n\nexport class QueryArrayExpression extends QueryExpression {\n\n exprs: QueryExpression[];\n\n constructor(exprs: QueryExpression[]) {\n super();\n this.exprs = exprs;\n }\n\n simplify() {\n return new QueryArrayExpression(_.map(this.exprs, x => x.simplify())) as QueryExpression;\n }\n\n keyPaths(): string[] {\n return _.uniq(_.flatMap(this.exprs, x => x.keyPaths()));\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryArrayExpression(_.map(this.exprs, x => x.mapKey(callback)));\n }\n\n eval(value: any) {\n return _.map(this.exprs, x => x.eval(value));\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return ['array'];\n }\n}\n\nexport class QueryZeroParamExpression extends QueryExpression {\n\n type: typeof TZeroParamExprKeys[number];\n\n constructor(type: typeof TZeroParamExprKeys[number]) {\n super();\n this.type = type;\n }\n\n eval(value: any): any {\n switch (this.type) {\n case '$now': return new Date();\n case '$rand': return Math.random();\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n switch (this.type) {\n case '$now': return ['date'];\n case '$rand': return ['number', 'decimal'];\n }\n }\n}\n\nexport class QueryUnaryExpression extends QueryExpression {\n\n type: typeof TUnaryExprKeys[number];\n expr: QueryExpression;\n\n constructor(type: typeof TUnaryExprKeys[number], expr: QueryExpression) {\n super();\n this.type = type;\n this.expr = expr;\n }\n\n simplify() {\n return new QueryUnaryExpression(this.type, this.expr.simplify());\n }\n\n keyPaths(): string[] {\n return this.expr.keyPaths();\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryUnaryExpression(this.type, this.expr.mapKey(callback));\n }\n\n eval(value: any) {\n switch (this.type) {\n case '$abs': return MathUtils.abs(this.expr.eval(value));\n case '$neg': return MathUtils.neg(this.expr.eval(value));\n case '$sqrt': return MathUtils.sqrt(this.expr.eval(value));\n case '$cbrt': return MathUtils.cbrt(this.expr.eval(value));\n case '$ceil': return MathUtils.ceil(this.expr.eval(value));\n case '$floor': return MathUtils.floor(this.expr.eval(value));\n case '$round': return MathUtils.round(this.expr.eval(value));\n case '$exp': return MathUtils.exp(this.expr.eval(value));\n case '$ln': return MathUtils.ln(this.expr.eval(value));\n case '$log2': return MathUtils.log2(this.expr.eval(value));\n case '$log10': return MathUtils.log10(this.expr.eval(value));\n case '$sin': return MathUtils.sin(this.expr.eval(value));\n case '$cos': return MathUtils.cos(this.expr.eval(value));\n case '$tan': return MathUtils.tan(this.expr.eval(value));\n case '$asin': return MathUtils.asin(this.expr.eval(value));\n case '$acos': return MathUtils.acos(this.expr.eval(value));\n case '$atan': return MathUtils.atan(this.expr.eval(value));\n case '$asinh': return MathUtils.asinh(this.expr.eval(value));\n case '$acosh': return MathUtils.acosh(this.expr.eval(value));\n case '$atanh': return MathUtils.atanh(this.expr.eval(value));\n case '$sinh': return MathUtils.sinh(this.expr.eval(value));\n case '$cosh': return MathUtils.cosh(this.expr.eval(value));\n case '$tanh': return MathUtils.tanh(this.expr.eval(value));\n case '$degrees': return MathUtils.degrees(this.expr.eval(value));\n case '$radians': return MathUtils.radians(this.expr.eval(value));\n case '$sign': return MathUtils.sign(this.expr.eval(value));\n case '$size':\n {\n const v = this.expr.eval(value);\n if (!_.isArray(v) && !_.isString(v)) throw Error('Invalid value');\n return v.length;\n }\n case '$lower': return _.toLower(this.expr.eval(value));\n case '$upper': return _.toUpper(this.expr.eval(value));\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n switch (this.type) {\n case '$abs': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$neg': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$sqrt': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$cbrt': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$ceil': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$floor': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$round': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$exp': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$ln': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$log2': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$log10': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$sin': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$cos': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$tan': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$asin': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$acos': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$atan': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$asinh': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$acosh': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$atanh': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$sinh': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$cosh': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$tanh': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$degrees': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$radians': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$sign': return combineNumericTypes(this.expr.evalType(schema, className));\n case '$size': return ['number'];\n case '$lower': return ['string'];\n case '$upper': return ['string'];\n }\n }\n}\n\nexport class QueryBinaryExpression extends QueryExpression {\n\n type: typeof TBinaryExprKeys[number];\n left: QueryExpression;\n right: QueryExpression;\n\n constructor(type: typeof TBinaryExprKeys[number], left: QueryExpression, right: QueryExpression) {\n super();\n this.type = type;\n this.left = left;\n this.right = right;\n }\n\n simplify() {\n return new QueryBinaryExpression(this.type, this.left.simplify(), this.right.simplify());\n }\n\n keyPaths(): string[] {\n return _.uniq([\n ...this.left.keyPaths(),\n ...this.right.keyPaths(),\n ]);\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryBinaryExpression(this.type, this.left.mapKey(callback), this.right.mapKey(callback));\n }\n\n eval(value: any) {\n const left = this.left.eval(value);\n const right = this.right?.eval(value);\n switch (this.type) {\n case '$divide': return MathUtils.divide(left, right);\n case '$subtract': return MathUtils.subtract(left, right);\n case '$log': return MathUtils.log(left, right);\n case '$pow': return MathUtils.pow(left, right);\n case '$atan2': return MathUtils.atan2(left, right);\n case '$trim':\n if (!_.isString(left) || !_.isString(right)) throw Error('Invalid value');\n return _.trim(left, right);\n case '$ltrim':\n if (!_.isString(left) || !_.isString(right)) throw Error('Invalid value');\n return _.trimStart(left, right);\n case '$rtrim':\n if (!_.isString(left) || !_.isString(right)) throw Error('Invalid value');\n return _.trimEnd(left, right);\n case '$first':\n if (!_.isArray(left) && !_.isString(left)) throw Error('Invalid value');\n if (!_.isSafeInteger(right) || right <= 0) throw Error('Invalid value');\n return _.isString(left) ? left.slice(0, right) : _.take(left, right);\n case '$last':\n if (!_.isArray(left) && !_.isString(left)) throw Error('Invalid value');\n if (!_.isSafeInteger(right) || right <= 0) throw Error('Invalid value');\n return _.isString(left) ? left.slice(-right) : _.takeRight(left, right);\n case '$ldrop':\n if (!_.isArray(left) && !_.isString(left)) throw Error('Invalid value');\n if (!_.isSafeInteger(right) || right <= 0) throw Error('Invalid value');\n return _.isString(left) ? left.slice(right) : _.drop(left, right);\n case '$rdrop':\n if (!_.isArray(left) && !_.isString(left)) throw Error('Invalid value');\n if (!_.isSafeInteger(right) || right <= 0) throw Error('Invalid value');\n return _.isString(left) ? left.slice(0, -right) : _.dropRight(left, right);\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n switch (this.type) {\n case '$divide':\n case '$subtract':\n case '$log':\n case '$pow':\n case '$atan2':\n return combineNumericTypes(this.left.evalType(schema, className), this.right.evalType(schema, className));\n case '$trim':\n case '$ltrim':\n case '$rtrim':\n return ['string'];\n case '$first':\n case '$last':\n case '$ldrop':\n case '$rdrop':\n return _.intersection(this.left.evalType(schema, className), ['string', 'string[]', 'array']);\n }\n }\n}\n\nexport class QueryTernaryExpression extends QueryExpression {\n\n type: typeof TTernaryExprKeys[number];\n first: QueryExpression;\n second: QueryExpression;\n last: QueryExpression;\n\n constructor(type: typeof TTernaryExprKeys[number], first: QueryExpression, second: QueryExpression, last: QueryExpression) {\n super();\n this.type = type;\n this.first = first;\n this.second = second;\n this.last = last;\n }\n\n simplify() {\n return new QueryTernaryExpression(this.type, this.first.simplify(), this.second.simplify(), this.last.simplify());\n }\n\n keyPaths(): string[] {\n return _.uniq([\n ...this.first.keyPaths(),\n ...this.second.keyPaths(),\n ...this.last.keyPaths(),\n ]);\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryTernaryExpression(this.type, this.first.mapKey(callback), this.second.mapKey(callback), this.last.mapKey(callback));\n }\n\n eval(value: any) {\n const first = this.first.eval(value);\n const second = this.second.eval(value);\n const last = this.last.eval(value);\n switch (this.type) {\n case '$lpad':\n if (!_.isString(first) || !_.isSafeInteger(second) || !_.isString(last)) throw Error('Invalid value');\n return _.padStart(first, second, last);\n case '$rpad':\n if (!_.isString(first) || !_.isSafeInteger(second) || !_.isString(last)) throw Error('Invalid value');\n return _.padEnd(first, second, last);\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n switch (this.type) {\n case '$lpad':\n case '$rpad':\n return ['string'];\n }\n }\n}\n\nexport class QueryListExpression extends QueryExpression {\n\n type: typeof TListExprKeys[number];\n exprs: QueryExpression[];\n\n constructor(type: typeof TListExprKeys[number], exprs: QueryExpression[]) {\n super();\n this.type = type;\n this.exprs = exprs;\n }\n\n simplify() {\n return new QueryListExpression(this.type, _.map(this.exprs, x => x.simplify())) as QueryExpression;\n }\n\n keyPaths(): string[] {\n return _.uniq(_.flatMap(this.exprs, x => x.keyPaths()));\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryListExpression(this.type, _.map(this.exprs, x => x.mapKey(callback)));\n }\n\n eval(value: any) {\n switch (this.type) {\n case '$add': return _.isEmpty(this.exprs) ? undefined : _.reduce(this.exprs, (a, b) => MathUtils.sum(a, b.eval(value)), 0 as number | Decimal);\n case '$multiply': return _.isEmpty(this.exprs) ? undefined : _.reduce(this.exprs, (a, b) => MathUtils.multiply(a, b.eval(value)), 1 as number | Decimal);\n case '$ifNull': return _.find(_.map(this.exprs, x => x.eval(value)), x => !_.isNil(x));\n case '$concat': return _.join(_.map(this.exprs, x => x.eval(value)), '');\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n switch (this.type) {\n case '$add': return combineNumericTypes(..._.map(this.exprs, x => x.evalType(schema, className)));\n case '$multiply': return combineNumericTypes(..._.map(this.exprs, x => x.evalType(schema, className)));\n case '$ifNull': return _.intersection(..._.map(this.exprs, x => x.evalType(schema, className)));\n case '$concat': return ['string'];\n }\n }\n}\n\nexport class QueryCondExpression extends QueryExpression {\n\n branch: {\n case: QueryExpression;\n then: QueryExpression;\n }[];\n default: QueryExpression;\n\n constructor(\n branch: {\n case: QueryExpression;\n then: QueryExpression;\n }[],\n defaultCase: QueryExpression\n ) {\n super();\n this.branch = branch;\n this.default = defaultCase;\n }\n\n simplify() {\n return new QueryCondExpression(\n _.map(this.branch, ({ case: c, then: t }) => ({ case: c.simplify(), then: t.simplify() })),\n this.default.simplify()\n );\n }\n\n keyPaths(): string[] {\n return _.uniq([\n ..._.flatMap(this.branch, ({ case: c, then: t }) => [...c.keyPaths(), ...t.keyPaths()]),\n ...this.default.keyPaths(),\n ]);\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryCondExpression(\n _.map(this.branch, ({ case: c, then: t }) => ({ case: c.mapKey(callback), then: t.mapKey(callback) })),\n this.default.mapKey(callback)\n );\n }\n\n eval(value: any) {\n for (const { case: c, then: t } of this.branch) {\n if (c.eval(value)) return t.eval(value);\n }\n return this.default.eval(value);\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return _.intersection(\n ..._.map(this.branch, ({ then: t }) => t.evalType(schema, className)),\n this.default.evalType(schema, className)\n );\n }\n}\n\nexport class QueryDistanceExpression extends QueryExpression {\n\n type: typeof TDistanceExprKeys[number];\n left: QueryExpression[];\n right: QueryExpression[];\n\n constructor(type: typeof TDistanceExprKeys[number], left: QueryExpression[], right: QueryExpression[]) {\n super();\n this.type = type;\n this.left = left;\n this.right = right;\n }\n\n simplify() {\n return new QueryDistanceExpression(this.type, _.map(this.left, x => x.simplify()), _.map(this.right, x => x.simplify()));\n }\n\n keyPaths(): string[] {\n return _.uniq([\n ..._.flatMap(this.left, x => x.keyPaths()),\n ..._.flatMap(this.right, x => x.keyPaths()),\n ]);\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryDistanceExpression(this.type, _.map(this.left, x => x.mapKey(callback)), _.map(this.right, x => x.mapKey(callback)));\n }\n\n eval(value: any) {\n const left = this.left.length === 1 ? this.left[0].eval(value) : _.map(this.left, x => x.eval(value));\n const right = this.right.length === 1 ? this.right[0].eval(value) : _.map(this.right, x => x.eval(value));\n if (!_.isArray(left) || !_.every(left, x => _.isFinite(x))) throw Error('Invalid vectors');\n if (!_.isArray(right) || !_.every(right, x => _.isFinite(x))) throw Error('Invalid vectors');\n switch (this.type) {\n case '$distance': return distance(left, right);\n case '$innerProduct': return innerProduct(left, right);\n case '$negInnerProduct': return -innerProduct(left, right);\n case '$cosineDistance': return cosine(left, right);\n case '$rectilinearDistance': return rectilinearDistance(left, right);\n }\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n return ['number'];\n }\n}\n\nexport class QueryKeyExpression extends QueryExpression {\n\n key: string;\n\n constructor(key: string) {\n super();\n this.key = key;\n }\n\n keyPaths(): string[] {\n return this.key === '$' ? [] : [this.key];\n }\n\n mapKey(callback: (key: string) => string): QueryExpression {\n return new QueryKeyExpression(callback(this.key));\n }\n\n eval(value: any) {\n return getValue(value, this.key);\n }\n\n evalType(schema: Record<string, TSchema>, className: string) {\n const { paths: [, ...subpath], dataType } = resolveColumn(schema, className, this.key);\n if (!_.isEmpty(subpath)) return [];\n if (_.isString(dataType)) return [dataType];\n if (isPrimitive(dataType)) return [dataType.type];\n if (isVector(dataType)) return [_.omit(dataType, 'default')];\n return [dataType];\n }\n}\n\nexport class QueryValueExpression extends QueryExpression {\n\n value: TValue;\n\n constructor(value: TValue) {\n super();\n this.value = value;\n }\n\n eval(value: any) {\n return value;\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType[] {\n if (_.isDate(this.value)) return ['date'];\n if (_.isBoolean(this.value)) return ['boolean'];\n if (_.isArray(this.value)) return ['array'];\n if (_.isString(this.value)) return ['string'];\n if (_.isNumber(this.value)) return ['number'];\n if (this.value instanceof Decimal) return ['decimal'];\n return [];\n }\n}\n","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { QueryExpression } from './expressions';\nimport { TFieldQuerySelector, TQuerySelector, allFieldQueryKeys } from '../../../../internals/query/types/selectors';\nimport { TComparisonKeys, TConditionalKeys, TValueListKeys, TValueSetKeys } from '../../../../internals/query/types/keys';\nimport { isValue } from '../../../../internals/object';\nimport { TValue } from '../../../../internals/types';\nimport { equal, getValue, greaterThan, greaterThanOrEqual, isIntersect, isSubset, isSuperset, lessThan, lessThanOrEqual } from './utils';\n\nexport class QuerySelector {\n\n static decode(selectors: _.Many<TQuerySelector>, dollerSign: boolean = false): QuerySelector {\n const exprs: QuerySelector[] = [];\n for (const selector of _.castArray(selectors)) {\n for (const [key, query] of _.toPairs(selector)) {\n if (_.includes(TConditionalKeys, key) && _.isArray(query)) {\n exprs.push(new QueryCoditionalSelector(key as any, _.map(query, x => QuerySelector.decode(x, dollerSign))));\n } else if (key === '$expr') {\n exprs.push(new QueryExpressionSelector(QueryExpression.decode(query as any, dollerSign)));\n } else if (dollerSign && key === '$' && !_.isArray(query)) {\n exprs.push(new QueryFieldSelector(key, FieldSelectorExpression.decode(query)));\n } else if (!key.startsWith('$') && !_.isArray(query)) {\n exprs.push(new QueryFieldSelector(key, FieldSelectorExpression.decode(query)));\n } else {\n throw Error('Invalid expression');\n }\n }\n }\n if (_.isEmpty(exprs)) return new QuerySelector;\n return (exprs.length === 1 ? exprs[0] : new QueryCoditionalSelector('$and', exprs)).simplify();\n }\n\n simplify(): QuerySelector {\n return this;\n }\n\n keyPaths(): string[] {\n return [];\n }\n\n eval(value: any): boolean {\n return true;\n }\n}\n\nexport class QueryCoditionalSelector extends QuerySelector {\n\n type: typeof TConditionalKeys[number];\n exprs: QuerySelector[];\n\n constructor(type: typeof TConditionalKeys[number], exprs: QuerySelector[]) {\n super();\n this.type = type;\n this.exprs = exprs;\n }\n\n simplify() {\n if (_.isEmpty(this.exprs)) return new QuerySelector;\n if (this.exprs.length === 1 && this.type !== '$nor') return this.exprs[0];\n switch (this.type) {\n case '$and':\n return new QueryCoditionalSelector(this.type, _.flatMap(\n this.exprs, x => x instanceof QueryCoditionalSelector && x.type === '$and' ? _.map(x.exprs, y => y.simplify()) : [x.simplify()]\n )) as QuerySelector;\n case '$nor':\n case '$or':\n return new QueryCoditionalSelector(this.type, _.flatMap(\n this.exprs, x => x instanceof QueryCoditionalSelector && x.type === '$or' ? _.map(x.exprs, y => y.simplify()) : [x.simplify()]\n )) as QuerySelector;\n }\n }\n\n keyPaths(): string[] {\n return _.uniq(_.flatMap(this.exprs, x => x.keyPaths()));\n }\n\n eval(value: any) {\n switch (this.type) {\n case '$and': return _.every(this.exprs, expr => expr.eval(value));\n case '$nor': return !_.some(this.exprs, expr => expr.eval(value));\n case '$or': return _.some(this.exprs, expr => expr.eval(value));\n }\n }\n}\n\nexport class FieldSelectorExpression {\n\n type: keyof TFieldQuerySelector;\n value: QuerySelector | FieldSelectorExpression | RegExp | TValue;\n\n constructor(type: keyof TFieldQuerySelector, value: QuerySelector | FieldSelectorExpression | RegExp | TValue) {\n this.type = type;\n this.value = value;\n }\n\n static decode(selector: TFieldQuerySelector): FieldSelectorExpression {\n for (const [type, expr] of _.toPairs(selector)) {\n if (_.includes(TComparisonKeys, type)) {\n if (!isValue(expr)) throw Error('Invalid expression');\n return new FieldSelectorExpression(type as any, expr);\n } else if (_.includes(TValueListKeys, type) || _.includes(TValueSetKeys, type)) {\n if (!isValue(expr) || !_.isArray(expr)) throw Error('Invalid expression');\n return new FieldSelectorExpression(type as any, expr);\n } else {\n switch (type) {\n case '$not':\n {\n const _expr = expr ? { ...expr as any } : {};\n const keys = _.keys(_expr);\n if (keys.length !== 1 && !allFieldQueryKeys.includes(keys[0])) throw Error('Invalid expression');\n return new FieldSelectorExpression(type, FieldSelectorExpression.decode(_expr));\n }\n case '$pattern':\n if (!_.isString(expr) && !_.isRegExp(expr)) throw Error('Invalid expression');\n return new FieldSelectorExpression(type, expr);\n case '$starts':\n case '$ends':\n if (!_.isString(expr)) throw Error('Invalid expression');\n return new FieldSelectorExpression(type, expr);\n case '$size':\n if (!_.isNumber(expr)) throw Error('Invalid expression');\n return new FieldSelectorExpression(type, expr);\n case '$empty':\n if (!_.isBoolean(expr)) throw Error('Invalid expression');\n return new FieldSelectorExpression(type, expr);\n case '$every':\n case '$some':\n return new FieldSelectorExpression(type, QuerySelector.decode(expr ? { ...expr as any } : {}, true));\n default: throw Error('Invalid expression');\n }\n }\n }\n throw Error('Invalid expression');\n }\n\n simplify(): FieldSelectorExpression {\n if (this.value instanceof QuerySelector) {\n return new FieldSelectorExpression(this.type, this.value.simplify());\n }\n if (this.value instanceof FieldSelectorExpression) {\n return new FieldSelectorExpression(this.type, this.value.simplify());\n }\n return this;\n }\n\n keyPaths(field?: string): string[] {\n let result: string[] = [];\n if (this.value instanceof QuerySelector) {\n result = this.value.keyPaths();\n } else if (this.value instanceof FieldSelectorExpression) {\n switch (this.type) {\n case '$every':\n case '$some':\n result = this.value.keyPaths();\n default:\n result = this.value.keyPaths();\n }\n }\n return field ? result.map(x => `${field}.${x}`) : result;\n }\n\n eval(value: any): any {\n if (_.includes(TComparisonKeys, this.type)) {\n switch (this.type) {\n case '$eq': return equal(value, this.value);\n case '$gt': return greaterThan(value, this.value);\n case '$gte': return greaterThanOrEqual(value, this.value);\n case '$lt': return lessThan(value, this.value);\n case '$lte': return lessThanOrEqual(value, this.value);\n case '$ne': return !equal(value, this.value);\n }\n } else if (_.includes(TValueListKeys, this.type) || _.includes(TValueSetKeys, this.type)) {\n switch (this.type) {\n case '$in': return _.isArray(value) && _.some(value, x => equal(x, this.value));\n case '$nin': return _.isArray(value) && !_.some(value, x => equal(x, this.value));\n case '$subset': return _.isArray(value) && _.isArray(this.value) && isSubset(value, this.value);\n case '$superset': return _.isArray(value) && _.isArray(this.value) && isSuperset(value, this.value);\n case '$intersect': return _.isArray(value) && _.isArray(this.value) && isIntersect(value, this.value);\n }\n } else {\n switch (this.type) {\n case '$not':\n return this.value instanceof FieldSelectorExpression && !this.value.eval(value);\n case '$pattern':\n if (_.isString(this.value)) {\n return _.isString(value) && value.includes(this.value);\n }\n if (_.isRegExp(this.value)) {\n return _.isString(value) && !!value.match(this.value);\n }\n return false;\n case '$starts':\n return _.isString(this.value) && _.isString(value) && value.startsWith(this.value);\n case '$ends':\n return _.isString(this.value) && _.isString(value) && value.endsWith(this.value);\n case '$size':\n return _.isNumber(this.value) && (_.isString(value) || _.isArray(value)) && value.length === this.value;\n case '$empty':\n return _.isBoolean(this.value) && (_.isString(value) || _.isArray(value)) && _.isEmpty(value);\n case '$every':\n {\n const expr = this.value;\n return expr instanceof QuerySelector && _.isArray(value) && _.every(value, x => expr.eval(x));\n }\n case '$some':\n {\n const expr = this.value;\n return expr instanceof QuerySelector && _.isArray(value) && _.some(value, x => expr.eval(x));\n }\n default: break;\n }\n }\n throw Error('Invalid expression');\n }\n}\n\nexport class QueryFieldSelector extends QuerySelector {\n\n field: string;\n expr: FieldSelectorExpression;\n\n constructor(field: string, expr: FieldSelectorExpression) {\n super();\n this.field = field;\n this.expr = expr;\n }\n\n simplify() {\n return new QueryFieldSelector(this.field, this.expr.simplify());\n }\n\n keyPaths(): string[] {\n return this.field === '$' ? this.expr.keyPaths() : [this.field, ...this.expr.keyPaths(this.field)];\n }\n\n eval(value: any) {\n return this.expr.eval(this.field === '$' ? value : getValue(value, this.field));\n }\n}\n\nexport class QueryExpressionSelector extends QuerySelector {\n\n expr: QueryExpression;\n\n constructor(expr: QueryExpression) {\n super();\n this.expr = expr;\n }\n\n simplify() {\n return new QueryExpressionSelector(this.expr.simplify());\n }\n\n keyPaths(): string[] {\n return this.expr.keyPaths();\n }\n\n eval(value: any) {\n return !!this.expr.eval(value);\n }\n}\n","//\n// accumulators.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { TUnaryAccumulatorKeys, TZeroParamAccumulatorKeys, TQueryAccumulator } from '../../../../internals/query/types/accumulators';\nimport { QueryExpression } from './expressions';\nimport { _isTypeof, TSchema } from '../../../../internals/schema';\n\nexport class QueryAccumulator {\n\n static decode(query: TQueryAccumulator): QueryAccumulator {\n for (const [key, expr] of _.toPairs(query)) {\n if (_.includes(TUnaryAccumulatorKeys, key)) {\n return new QueryUnaryAccumulator(key as typeof TUnaryAccumulatorKeys[number], QueryExpression.decode(expr as any ?? [], false));\n } else if (_.includes(TZeroParamAccumulatorKeys, key)) {\n return new QueryZeroParamAccumulator(key as typeof TZeroParamAccumulatorKeys[number]);\n } else if (key === '$percentile') {\n const { input, p, mode = 'discrete' } = expr as any ?? {};\n if (!_.isFinite(p) || p < 0 || p > 1) throw Error('Invalid expression');\n if (!_.includes(['discrete', 'continuous'], mode)) throw Error('Invalid expression');\n return new QueryPercentileAccumulator(QueryExpression.decode(input ?? [], false), p, mode);\n } else if (key === '$group') {\n const { key: groupKey, value } = expr as any ?? {};\n if (!groupKey || !value) throw Error('Invalid expression');\n return new QueryGroupAccumulator(\n QueryExpression.decode(groupKey ?? [], false),\n QueryAccumulator.decode(value)\n );\n } else {\n throw Error('Invalid expression');\n }\n }\n throw Error('Invalid expression');\n }\n\n simplify(): QueryAccumulator {\n return this;\n }\n\n keyPaths(): string[] {\n return [];\n }\n\n mapKey(callback: (key: string) => string): QueryAccumulator {\n return this;\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType | undefined {\n return;\n }\n}\n\nexport class QueryZeroParamAccumulator extends QueryAccumulator {\n\n type: typeof TZeroParamAccumulatorKeys[number];\n\n constructor(type: typeof TZeroParamAccumulatorKeys[number]) {\n super();\n this.type = type;\n }\n\n simplify() {\n return this;\n }\n\n keyPaths() {\n return [];\n }\n\n mapKey(callback: (key: string) => string) {\n return this;\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType | undefined {\n switch (this.type) {\n case '$count': return 'number';\n default: break;\n }\n }\n}\n\nexport class QueryUnaryAccumulator extends QueryAccumulator {\n\n type: typeof TUnaryAccumulatorKeys[number];\n expr: QueryExpression;\n\n constructor(type: typeof TUnaryAccumulatorKeys[number], expr: QueryExpression) {\n super();\n this.type = type;\n this.expr = expr;\n }\n\n simplify() {\n return new QueryUnaryAccumulator(this.type, this.expr.simplify());\n }\n\n keyPaths() {\n return this.expr.keyPaths();\n }\n\n mapKey(callback: (key: string) => string) {\n return new QueryUnaryAccumulator(this.type, this.expr.mapKey(callback));\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType | undefined {\n const [dataType] = this.expr.evalType(schema, className);\n if (_.isNil(dataType)) return;\n switch (this.type) {\n case '$max': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;\n case '$min': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;\n case '$most': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;\n case '$avg': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n case '$sum': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n case '$stdDevPop': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n case '$stdDevSamp': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n case '$varPop': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n case '$varSamp': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n default: break;\n }\n }\n}\n\nexport class QueryPercentileAccumulator extends QueryAccumulator {\n\n input: QueryExpression;\n p: number;\n mode: 'discrete' | 'continuous';\n\n constructor(input: QueryExpression, p: number, mode: 'discrete' | 'continuous') {\n super();\n this.input = input;\n this.p = p;\n this.mode = mode;\n }\n\n simplify(): QueryAccumulator {\n return new QueryPercentileAccumulator(this.input.simplify(), this.p, this.mode);\n }\n\n keyPaths(): string[] {\n return this.input.keyPaths();\n }\n\n mapKey(callback: (key: string) => string): QueryAccumulator {\n return new QueryPercentileAccumulator(this.input.mapKey(callback), this.p, this.mode);\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType | undefined {\n const [dataType] = this.input.evalType(schema, className);\n if (this.mode === 'continuous') {\n return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;\n }\n return dataType;\n }\n}\n\nexport class QueryGroupAccumulator extends QueryAccumulator {\n\n key: QueryExpression;\n value: QueryAccumulator;\n\n constructor(key: QueryExpression, value: QueryAccumulator) {\n super();\n this.key = key;\n this.value = value;\n }\n\n simplify(): QueryAccumulator {\n return new QueryGroupAccumulator(this.key.simplify(), this.value.simplify());\n }\n\n keyPaths(): string[] {\n return _.uniq([\n ...this.key.keyPaths(),\n ...this.value.keyPaths(),\n ]);\n }\n\n mapKey(callback: (key: string) => string): QueryAccumulator {\n return new QueryGroupAccumulator(this.key.mapKey(callback), this.value.mapKey(callback));\n }\n\n evalType(schema: Record<string, TSchema>, className: string): TSchema.DataType | undefined {\n return 'array';\n }\n}\n","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { QuerySelector } from '../query/dispatcher/parser';\nimport { TSchema } from '../../internals/schema';\nimport { TQueryBaseOptions } from '../../internals/query/base';\nimport { TransactionOptions } from '../../internals/proto';\nimport { TQueryOptions } from '../../internals/query';\nimport { TValueWithoutObject, TValueWithUndefined } from '../../internals/types';\nimport { TObject } from '../../internals/object';\nimport { TUpdateOp } from '../../internals/object/types';\nimport { QueryExpression } from '../query/dispatcher/parser/expressions';\nimport { QueryAccumulator } from '../query/dispatcher/parser/accumulators';\n\nexport type FindOptions = { className: string; } & TQueryOptions;\n\nexport type RelationOptions = {\n relatedBy?: {\n className: string;\n id: string;\n key: string;\n };\n};\n\ntype Decoded<T, R> = Omit<T, keyof R> & R;\n\nexport type DecodedSortOption = {\n expr: QueryExpression;\n order: 1 | -1;\n};\n\nexport type DecodedBaseQuery = Decoded<TQueryBaseOptions, {\n filter?: QuerySelector;\n matches: Record<string, DecodedBaseQuery>;\n groupMatches?: Record<string, Record<string, QueryAccumulator>>;\n sort?: Record<string, 1 | -1> | DecodedSortOption[];\n}>;\n\nexport type DecodedQuery<T> = Decoded<T, {\n filter: QuerySelector;\n matches: Record<string, DecodedBaseQuery>;\n groupMatches: Record<string, Record<string, QueryAccumulator>>;\n includes: string[];\n objectIdSize: number;\n sort?: Record<string, 1 | -1> | DecodedSortOption[];\n extraFilter?: (className: string) => QuerySelector;\n}>;\n\nexport type InsertOptions = {\n className: string;\n includes: string[];\n matches: Record<string, DecodedBaseQuery>;\n groupMatches: Record<string, Record<string, QueryAccumulator>>;\n objectIdSize: number;\n};\n\nexport type QueryRandomOptions = {\n weight?: QueryExpression;\n};\n\nexport interface TStorage {\n\n selectLock(): boolean;\n\n prepare(schema: Record<string, TSchema>): PromiseLike<void>;\n shutdown(): PromiseLike<void>;\n\n classes(): string[];\n\n config(acl?: string[]): PromiseLike<Record<string, TValueWithoutObject>>;\n configAcl(): PromiseLike<Record<string, string[]>>;\n setConfig(values: Record<string, TValueWithoutObject>, acl?: string[]): PromiseLike<void>;\n\n explain(query: DecodedQuery<FindOptions & RelationOptions>): PromiseLike<any>;\n\n count(query: DecodedQuery<FindOptions & RelationOptions>): PromiseLike<number>;\n find(query: DecodedQuery<FindOptions & RelationOptions>): AsyncIterable<TObject>;\n random(query: DecodedQuery<FindOptions & RelationOptions>, opts?: QueryRandomOptions): AsyncIterable<TObject>;\n groupFind(\n query: DecodedQuery<FindOptions & RelationOptions>,\n accumulators: Record<string, QueryAccumulator>\n ): PromiseLike<Record<string, any>>;\n\n refs(object: TObject, classNames: string[], roles?: string[]): AsyncIterable<TObject>;\n nonrefs(query: DecodedQuery<FindOptions>): AsyncIterable<TObject>;\n\n insert(options: InsertOptions, values: Record<string, TValueWithUndefined>[]): PromiseLike<TObject[]>;\n update(query: DecodedQuery<FindOptions>, update: Record<string, TUpdateOp>): PromiseLike<TObject[]>;\n upsert(query: DecodedQuery<FindOptions>, update: Record<string, TUpdateOp>, setOnInsert: Record<string, TValueWithUndefined>): PromiseLike<TObject[]>;\n delete(query: DecodedQuery<FindOptions>): PromiseLike<TObject[]>;\n\n lockTable(className: string | string[], update: boolean): Promise<void>;\n\n withConnection<T>(callback: (connection: TStorage) => PromiseLike<T>): PromiseLike<T>;\n\n isDuplicateIdError(error: any): boolean;\n\n atomic<T>(\n callback: (connection: TStorage) => PromiseLike<T>,\n options?: { lockTable?: string; retry?: boolean; },\n ): PromiseLike<T>;\n\n withTransaction<T>(\n callback: (connection: TStorage) => PromiseLike<T>,\n options?: TransactionOptions,\n ): PromiseLike<T>;\n}\n","//\n// password.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport { scrypt, BinaryLike, ScryptOptions } from 'node:crypto';\nimport { promisify } from 'util';\nimport { randomBytes } from '@o2ter/crypto-js';\n\nconst _scrypt = promisify<BinaryLike, BinaryLike, number, ScryptOptions, Buffer>(scrypt);\n\ntype _PasswordHashOptions = {\n 'scrypt': {\n log2n: number;\n blockSize: number;\n parallel: number;\n keySize: number;\n saltSize: number;\n };\n};\n\nexport type PasswordHashOptions = {\n [K in keyof _PasswordHashOptions]: { alg: K } & _PasswordHashOptions[K];\n}[keyof _PasswordHashOptions];\n\nconst _passwordHash = async <T extends keyof _PasswordHashOptions>(\n alg: T,\n password: string,\n salt: Buffer | Uint8Array,\n options: _PasswordHashOptions[T],\n) => {\n switch (alg) {\n case 'scrypt':\n\n if (!_.isSafeInteger(options.log2n)) throw Error('Invalid options');\n if (!_.isSafeInteger(options.blockSize)) throw Error('Invalid options');\n if (!_.isSafeInteger(options.parallel)) throw Error('Invalid options');\n if (!_.isSafeInteger(options.keySize)) throw Error('Invalid options');\n if (!_.isSafeInteger(options.saltSize)) throw Error('Invalid options');\n\n const _opts: ScryptOptions = {\n N: 1 << options.log2n,\n blockSize: options.blockSize,\n parallelization: options.parallel,\n };\n\n const derivedKey = await _scrypt(password, salt, options.keySize, _opts);\n\n return derivedKey.toString('base64');\n\n default: throw Error('Invalid algorithm');\n }\n}\n\nexport const passwordHash = async <T extends keyof _PasswordHashOptions>(\n alg: T,\n password: string,\n options: _PasswordHashOptions[T],\n) => {\n const salt = randomBytes(options.saltSize);\n return {\n alg,\n salt: salt.toString('base64'),\n derivedKey: await _passwordHash(alg, password, salt, options),\n ...options\n };\n}\n\nexport const verifyPassword = async <T extends keyof _PasswordHashOptions>(\n alg: T,\n password: string,\n options: _PasswordHashOptions[T] & { salt: string; derivedKey: string; },\n) => {\n if (!_.isString(options.salt)) return false;\n if (!_.isString(options.derivedKey)) return false;\n try {\n return options.derivedKey === await _passwordHash(alg, password, Buffer.from(options.salt, 'base64'), options);\n } catch {\n return false;\n }\n}","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { Awaitable } from '@o2ter/utils-js';\nimport { TValueWithoutObject } from '../../internals/types';\n\n/**\n * Interface for publish-subscribe operations.\n */\nexport interface TPubSub {\n\n /**\n * Subscribes to a channel.\n * @param channel - The name of the channel to subscribe to.\n * @param callback - The callback function to handle the event data.\n * @returns A function to unsubscribe from the channel.\n */\n subscribe(channel: string, callback: (payload: TValueWithoutObject) => void): VoidFunction;\n\n /**\n * Publishes an event to a channel.\n * @param channel - The name of the channel to publish to.\n * @param payload - The event data to publish.\n * @returns A promise that resolves when the event is published.\n */\n publish(channel: string, payload: TValueWithoutObject): Awaitable<void>;\n}\n","//\n// types.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport { TFileStorage } from '../file';\nimport { TStorage } from '../storage';\nimport { TSchema } from '../../internals/schema';\nimport { CookieOptions } from '@o2ter/server-js';\nimport { SignOptions, VerifyOptions } from 'jsonwebtoken';\nimport { PasswordHashOptions } from '../crypto/password';\nimport { TExtensions } from '../../internals/object/types';\nimport { TPubSub } from '../pubsub';\nimport { TUser } from '../../internals/object/user';\nimport { TRole } from '../../internals/object/role';\nimport { Awaitable } from '@o2ter/utils-js';\nimport { Logger } from '../../internals/proto';\n\nexport type ProtoServiceOptions<Ext> = {\n /**\n * The endpoint for the service.\n */\n endpoint: string;\n\n /**\n * The schema definitions for the service.\n */\n schema: Record<string, TSchema>;\n\n /**\n * Role resolver configuration.\n */\n roleResolver?: {\n /**\n * Keys to inherit roles.\n */\n inheritKeys?: string[];\n\n /**\n * Custom resolver function for roles.\n * @param user The user object.\n * @param defaultResolver The default resolver function.\n * @returns A promise that resolves to an array of roles.\n */\n resolver?: (\n user: TUser,\n defaultResolver: () => Promise<TRole[]>,\n ) => Awaitable<TRole[]>;\n };\n\n /**\n * Logger configuration.\n */\n logger?: Partial<Logger>;\n\n /**\n * Storage configuration.\n */\n storage: TStorage;\n\n /**\n * File storage configuration.\n */\n fileStorage: TFileStorage;\n\n /**\n * Pub/Sub configuration.\n */\n pubsub?: TPubSub;\n\n /**\n * Class extensions configuration.\n */\n classExtends?: TExtensions<Ext>;\n\n /**\n * Size of the object ID.\n */\n objectIdSize?: number;\n\n /**\n * Maximum fetch limit.\n */\n maxFetchLimit?: number;\n\n /**\n * Maximum upload size.\n */\n maxUploadSize?: number;\n\n /**\n * Cookie options.\n */\n cookieOptions?: CookieOptions;\n\n /**\n * JWT sign options.\n */\n jwtSignOptions?: SignOptions;\n\n /**\n * JWT verify options.\n */\n jwtVerifyOptions?: VerifyOptions;\n\n /**\n * JWT upload sign options.\n */\n jwtUploadSignOptions?: SignOptions;\n\n /**\n * JWT upload verify options.\n */\n jwtUploadVerifyOptions?: VerifyOptions;\n\n /**\n * Password hash options.\n */\n passwordHashOptions?: PasswordHashOptions;\n\n /**\n * Password policy options.\n */\n passwordPolicy?: {\n /**\n * Do not allow reusing previous passwords.\n */\n maxPasswordHistory?: number;\n\n /**\n * Custom validator callback for password strength.\n * @param password The password to validate.\n * @param user The user object (optional).\n * @returns A boolean or a promise that resolves to a boolean indicating whether the password is valid.\n */\n validatorCallback?: (password: string, user?: TUser) => Awaitable<boolean>;\n };\n};\n\nexport type ProtoServiceKeyOptions = {\n /**\n * JWT token for the service.\n */\n jwtToken: string;\n\n /**\n * Master users configuration.\n */\n masterUsers?: {\n /**\n * Username of the master user.\n */\n user: string;\n\n /**\n * Password of the master user.\n */\n pass: string;\n }[];\n};\n","//\n// index.ts\n//\n// The MIT License\n// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\nimport _ from 'lodash';\nimport jwt from 'jsonwebtoken';\nimport { afterCommitTasks, ProtoQuery, ProtoRelationQuery } from '../query';\nimport { ProtoInternal } from './internal';\nimport { CookieOptions, Request } from '@o2ter/server-js';\nimport { ProtoServiceOptions, ProtoServiceKeyOptions } from './types';\nimport { ProtoFunction, ProtoFunctionOptions, ProtoJobFunction, ProtoJobFunctionOptions, ProtoTriggerFunction } from '../../internals/proto/types';\nimport { sessionIsMaster, session, signUser, sessionWithToken, _Session } from './session';\nimport { _logLevels, EventData, Logger, ProtoType, TransactionOptions } from '../../internals/proto';\nimport { schedule } from '../schedule';\nimport { serialize, TSerializable } from '../../internals/codec';\nimport { PVK } from '../../internals/private';\nimport { TExtensions, TObjectType } from '../../internals/object/types';\nimport { TQuery } from '../../internals/query';\nimport { TUser } from '../../internals/object/user';\nimport { ExtraOptions } from '../../internals/options';\nimport { TValueWithoutObject, TValue } from '../../internals/types';\nimport { randomUUID } from '@o2ter/crypto-js';\nimport { TObject } from '../../internals/object';\nimport { asyncStream } from '@o2ter/utils-js';\nimport { TRole } from '../../internals/object/role';\nimport { PathName } from '../../internals/query/types';\nimport { QuerySelector } from '../query/dispatcher/parser';\nimport { _typeof, isRelation } from '../../internals/schema';\nimport { resolveDataType } from '../query/dispatcher/validator';\nimport { TQuerySelector } from '../../internals/query/types/selectors';\n\nexport const _serviceOf = (options?: ExtraOptions<any>) => options?.session instanceof ProtoService ? options?.session : undefined;\n\nexport class ProtoService<Ext = any> extends ProtoType<Ext> {\n\n /** @internal */\n [PVK]: ProtoInternal<Ext, this>;\n private _storage?: ProtoServiceOptions<Ext>['storage'];\n private _schedule = schedule(this);\n\n req?: Request;\n session?: _Session;\n\n constructor(options: ProtoServiceOptions<Ext> & ProtoServiceKeyOptions) {\n super();\n this[PVK] = new ProtoInternal({\n roleResolver: {},\n objectIdSize: 10,\n maxFetchLimit: 1000,\n maxUploadSize: 20 * 1024 * 1024,\n pubsub: {\n publish: () => void 0,\n subscribe: () => () => void 0,\n },\n classExtends: {} as TExtensions<Ext>,\n cookieOptions: { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true },\n jwtSignOptions: { expiresIn: '30d' },\n jwtVerifyOptions: {},\n jwtUploadSignOptions: { expiresIn: '1d' },\n jwtUploadVerifyOptions: {},\n passwordHashOptions: {\n alg: 'scrypt',\n log2n: 14,\n blockSize: 8,\n parallel: 1,\n keySize: 64,\n saltSize: 64,\n },\n logger: {},\n ...options,\n });\n }\n\n async shutdown() {\n this._schedule.destroy();\n this[PVK].shutdown();\n }\n\n get logger() {\n const logger = this[PVK].options.logger;\n const loggerLevel = logger.loggerLevel ?? 'warn';\n const callbacks = _.map(_logLevels, (x, i) => [x, (...args: any[]) => {\n if (loggerLevel !== 'all' && _.indexOf(_logLevels, loggerLevel) < i) return;\n const func = logger[x] ?? console[x];\n if (_.isFunction(func)) func(...args);\n }] as const);\n return {\n loggerLevel,\n ..._.fromPairs(callbacks as any),\n } as Logger;\n }\n\n classes(): string[] {\n return _.keys(this[PVK].options.schema);\n }\n\n Query<T extends string>(className: T): TQuery<T, Ext, boolean> {\n return new ProtoQuery<T, Ext, boolean>(className, this, {});\n }\n\n Relation<T extends string>(object: TObject, key: PathName<T>): TQuery<string, Ext, boolean> {\n const id = object.id;\n if (!id) throw Error('Invalid object');\n return new ProtoRelationQuery<Ext, boolean>(this, {\n relatedBy: {\n className: object.className,\n id: id,\n key,\n },\n });\n }\n\n InsecureQuery<T extends string>(className: T): TQuery<T, Ext, true> {\n return new ProtoQuery<T, Ext, true>(className, this, { insecure: true });\n }\n\n async sessionInfo() {\n if (this.session) return this.session;\n return this.req ? session(this, this.req) : undefined;\n }\n\n async currentUser(): Promise<TUser | undefined> {\n const session = await this.sessionInfo();\n return session?.user;\n }\n\n async _currentRoles(): Promise<TRole[]> {\n const session = await this.sessionInfo();\n return session?._roles ?? [];\n }\n\n async currentRoles(): Promise<string[]> {\n const roles = await this._currentRoles();\n return _.compact(_.map(roles, x => x.name));\n }\n\n get isMaster(): boolean {\n return this.req ? sessionIsMaster(this, this.req) === 'valid' : false;\n }\n\n get isInvalidMasterToken(): boolean {\n return this.req ? sessionIsMaster(this, this.req) === 'invalid' : false;\n }\n\n connect<R extends Request, T extends object>(\n req: R,\n attrs?: T | ((x: this & { req: R; }) => T)\n ): this & { req: R; } & T {\n const payload = _.create(this, { req });\n return _.assign(payload, _.isFunction(attrs) ? attrs(payload) : attrs)\n }\n\n async connectWithSessionToken<T extends object>(\n token: string,\n attrs?: T | ((x: this & { session?: _Session; }) => T)\n ): Promise<this & { session?: _Session; } & T> {\n const session = _.isString(token) ? await sessionWithToken(this, token) : undefined;\n if (Object.getPrototypeOf(this) instanceof ProtoService) {\n this.session = session;\n return _.assign(this, _.isFunction(attrs) ? attrs(this) : attrs);\n } else {\n const payload = _.create(this, { session });\n return _.assign(payload, _.isFunction(attrs) ? attrs(payload) : attrs);\n }\n }\n\n async userRoles(user: TUser) {\n const self = this;\n const { inheritKeys, resolver } = self[PVK].options.roleResolver;\n const defaultResolver = async () => {\n const schema = self.schema;\n const userKeys = _.filter(inheritKeys, k => {\n const type = resolveDataType(schema, 'Role', k);\n return !!type && isRelation(type) && type.target === 'User';\n });\n const roleKeys = _.filter(inheritKeys, k => {\n const type = resolveDataType(schema, 'Role', k);\n return !!type && isRelation(type) && type.target === 'Role';\n });\n let queue = await self.Query('Role')\n .or(_.map(_.uniq(['users', ...userKeys]), k => q => q.isIntersect(k, [user])))\n .includes('name')\n .find({ master: true });\n let roles = queue;\n while (!_.isEmpty(queue)) {\n queue = await self.Query('Role')\n .or(_.map(_.uniq(['roles', ...roleKeys]), k => q => q.isIntersect(k, queue)))\n .notContainedIn('_id', _.compact(_.map(roles, x => x.id)))\n .includes('name')\n .find({ master: true });\n roles = _.uniqBy([...roles, ...queue], x => x.id);\n }\n return roles;\n };\n if (resolver) return resolver(user, defaultResolver);\n return defaultResolver();\n }\n\n async becomeUser(\n req: Request,\n user: TUser,\n options?: {\n cookieOptions?: CookieOptions | undefined;\n jwtSignOptions?: jwt.SignOptions | undefined;\n }\n ) {\n if (!user.id) throw Error('Invalid user object');\n if (req.res) await signUser(this, req.res, user, options);\n }\n\n async logoutUser(\n req: Request,\n options?: {\n cookieOptions?: CookieOptions | undefined;\n jwtSignOptions?: jwt.SignOptions | undefined;\n }\n ) {\n if (req.res) await signUser(this, req.res, undefined, options);\n }\n\n verifyPassword(user: TUser, password: string, options: ExtraOptions<true>) {\n return this[PVK].verifyPassword(this, user, password, options);\n }\n\n setPassword(user: TUser, password: string, options: ExtraOptions<true>) {\n return this[PVK].setPassword(this, user, password, options);\n }\n\n unsetPassword(user: TUser, options: ExtraOptions<true>) {\n return this[PVK].unsetPassword(this, user, options);\n }\n\n get schema(): ProtoServiceOptions<Ext>['schema'] {\n return this[PVK].options.schema;\n }\n\n get storage(): ProtoServiceOptions<Ext>['storage'] {\n return this._storage ?? this[PVK].options.storage;\n }\n\n get fileStorage(): ProtoServiceOptions<Ext>['fileStorage'] {\n return this[PVK].options.fileStorage;\n }\n\n async config(options?: { master?: boolean; }) {\n return this[PVK].config(this, options);\n }\n configAcl(options: { master: true; }) {\n if (options.master !== true) throw Error('No permission');\n return this[PVK].configAcl();\n }\n async setConfig(values: Record<string, TValueWithoutObject>, options: { master: true; acl?: string[]; }) {\n if (options.master !== true) throw Error('No permission');\n await this[PVK].setConfig(values, options.acl);\n }\n\n run<R extends TSerializable | void = any>(\n name: string,\n params?: TSerializable,\n options?: ExtraOptions<boolean>\n ) {\n const payload = Object.setPrototypeOf({ params }, this);\n return this[PVK].run(this, name, payload, options) as Promise<R>;\n }\n\n define<P extends TSerializable = any, R extends TSerializable | void = any>(\n name: string,\n callback: ProtoFunction<Ext, P, R>,\n options?: Omit<ProtoFunctionOptions<Ext>, 'callback'>,\n ) {\n this[PVK].functions[name] = options ? { callback, ...options } : callback;\n }\n\n afterCreate<T extends string>(\n className: string,\n callback: ProtoTriggerFunction<T, Ext>,\n ) {\n if (_.isNil(this[PVK].triggers[className])) {\n this[PVK].triggers[className] = { create: [], update: [], delete: [] };\n }\n this[PVK].triggers[className].create.push(callback);\n }\n\n afterUpdate<T extends string>(\n className: string,\n callback: ProtoTriggerFunction<T, Ext>,\n ) {\n if (_.isNil(this[PVK].triggers[className])) {\n this[PVK].triggers[className] = { create: [], update: [], delete: [] };\n }\n this[PVK].triggers[className].update.push(callback);\n }\n\n afterDelete<T extends string>(\n className: string,\n callback: ProtoTriggerFunction<T, Ext>,\n ) {\n if (_.isNil(this[PVK].triggers[className])) {\n this[PVK].triggers[className] = { create: [], update: [], delete: [] };\n }\n this[PVK].triggers[className].delete.push(callback);\n }\n\n scheduleJob(name: string, params?: TValueWithoutObject, options?: ExtraOptions<boolean>) {\n return this[PVK].scheduleJob(this, name, params, options);\n }\n\n defineJob<P extends TValueWithoutObject = any>(\n name: string,\n callback: ProtoJobFunction<Ext, P>,\n options?: Omit<ProtoJobFunctionOptions<Ext>, 'callback'>,\n ) {\n this[PVK].jobs[name] = options ? { callback, ...options } : callback;\n }\n\n lockTable(className: string | string[], update: boolean) {\n return this.storage.lockTable(className, update);\n }\n\n async withTransaction<T>(\n callback: (connection: ProtoService<Ext>) => PromiseLike<T>,\n options?: TransactionOptions,\n ) {\n const tasks = afterCommitTasks.get(this) ?? [];\n const result = await this.storage.withTransaction((storage) => {\n const payload = _.create(this, { _storage: storage });\n afterCommitTasks.set(payload, tasks);\n return callback(payload);\n }, options);\n if (!afterCommitTasks.has(this)) {\n for (const task of tasks) task();\n }\n return result;\n }\n\n generateUploadToken(options: {\n maxUploadSize?: number;\n attributes?: Record<string, TValue>;\n jwtSignOptions?: jwt.SignOptions;\n } = {}) {\n return this[PVK].jwtSign({\n nonce: randomUUID(),\n maxUploadSize: options.maxUploadSize,\n attributes: JSON.parse(serialize(\n options.attributes ?? {},\n { objAttrs: ['_id'] },\n )),\n }, options?.jwtSignOptions ?? 'upload');\n }\n\n jwtSign(payload: any, options: jwt.SignOptions) {\n return this[PVK].jwtSign(payload, options);\n }\n\n jwtVerify(token: string, options: jwt.VerifyOptions = {}) {\n return this[PVK].jwtVerify(token, options);\n }\n\n notify(data: Record<string, TValueWithoutObject> & { _rperm?: string[]; }) {\n return this[PVK].notify(this, data);\n }\n\n listen(\n callback: (data: EventData) => void,\n selector?: TQuerySelector\n ) {\n const _selector = !_.isNil(selector) ? QuerySelector.decode(selector) : undefined;\n return this[PVK].listen(this, async data => {\n if (_selector && !_selector.eval(data)) return;\n await callback(data);\n });\n }\n\n refs(object: TObject, options?: ExtraOptions<boolean>) {\n if (!object.id) throw Error('Invalid object');\n const self = this;\n return asyncStream(async function* () {\n const objects = await self[PVK].refs(self, object, options);\n for await (const object of objects) yield self.rebind(object) as TObjectType<string, Ext>;\n });\n }\n\n async gc(classNames?: string | string[]) {\n const time = new Date();\n for (const className of _.castArray(classNames ?? this.classes())) {\n if (className === 'File') {\n const found = this.storage.find({\n className: 'File',\n filter: QuerySelector.decode({ _expired_at: { $lt: time } }),\n matches: {},\n groupMatches: {},\n includes: ['_id', '_expired_at', 'token'],\n objectIdSize: 0\n });\n for await (const item of found) {\n const token = item.get('token');\n if (!_.isEmpty(token)) await this.fileStorage.destroy(this, token);\n }\n }\n await this.storage.delete({\n className,\n filter: QuerySelector.decode({ _expired_at: { $lt: time } }),\n includes: ['_id', '_expired_at'],\n matches: {},\n groupMatches: {},\n objectIdSize: 0\n });\n }\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;AAEA;AACA;AACA;AACA;AACA;AACO;AACA;AACP;AACA;AACA;AACO;AAEA;AACA;AACA;AACP;AACA;;AChBO;AACP;AACA;;ACDA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACO;AACP;AACA;;ACTA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACO;AACA;AACA;;AC3CA;AACA;AACA;AACA;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACP;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACO;AACP;AACA;AACA;AACA;;AC7BO;AACA;AACA;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxQO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACFA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChMO;AACP;AACO;AACA;AACP;AACA;AACA;AACO;AACP;AACA;AACO;AACA;;ACTP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnFO;AACA;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACMO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAcO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzVA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjOO;AACP;AACA;AACO;AACA;AACA;AACA;AACA;AACA;AACP;AACA;AACA;AACA;;ACZO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAaO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9PA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;;ACRO;AACP;AACA;AACA;AACA;AACA;AASO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBO;AACP;AACA;AACA;AACA;AACA;AACA;;ACCO;AACP;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;;ACXA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACRO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/GO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;"}
|