eval.ts 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { Code, type Document } from '../bson';
  2. import type { Collection } from '../collection';
  3. import type { Db } from '../db';
  4. import { MongoServerError } from '../error';
  5. import { ReadPreference } from '../read_preference';
  6. import type { Server } from '../sdam/server';
  7. import type { ClientSession } from '../sessions';
  8. import type { Callback } from '../utils';
  9. import { CommandCallbackOperation, type CommandOperationOptions } from './command';
  10. /** @public */
  11. export interface EvalOptions extends CommandOperationOptions {
  12. nolock?: boolean;
  13. }
  14. /** @internal */
  15. export class EvalOperation extends CommandCallbackOperation<Document> {
  16. override options: EvalOptions;
  17. code: Code;
  18. parameters?: Document | Document[];
  19. constructor(
  20. db: Db | Collection,
  21. code: Code,
  22. parameters?: Document | Document[],
  23. options?: EvalOptions
  24. ) {
  25. super(db, options);
  26. this.options = options ?? {};
  27. this.code = code;
  28. this.parameters = parameters;
  29. // force primary read preference
  30. Object.defineProperty(this, 'readPreference', {
  31. value: ReadPreference.primary,
  32. configurable: false,
  33. writable: false
  34. });
  35. }
  36. override executeCallback(
  37. server: Server,
  38. session: ClientSession | undefined,
  39. callback: Callback<Document>
  40. ): void {
  41. let finalCode = this.code;
  42. let finalParameters: Document[] = [];
  43. // If not a code object translate to one
  44. if (!(finalCode && (finalCode as unknown as { _bsontype: string })._bsontype === 'Code')) {
  45. finalCode = new Code(finalCode as never);
  46. }
  47. // Ensure the parameters are correct
  48. if (this.parameters != null && typeof this.parameters !== 'function') {
  49. finalParameters = Array.isArray(this.parameters) ? this.parameters : [this.parameters];
  50. }
  51. // Create execution selector
  52. const cmd: Document = { $eval: finalCode, args: finalParameters };
  53. // Check if the nolock parameter is passed in
  54. if (this.options.nolock) {
  55. cmd.nolock = this.options.nolock;
  56. }
  57. // Execute the command
  58. super.executeCommandCallback(server, session, cmd, (err, result) => {
  59. if (err) return callback(err);
  60. if (result && result.ok === 1) {
  61. return callback(undefined, result.retval);
  62. }
  63. if (result) {
  64. callback(new MongoServerError({ message: `eval failed: ${result.errmsg}` }));
  65. return;
  66. }
  67. callback(err, result);
  68. });
  69. }
  70. }