deps.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* eslint-disable @typescript-eslint/no-var-requires */
  2. import { type Stream } from './cmap/connect';
  3. import { MongoMissingDependencyError } from './error';
  4. import type { Callback } from './utils';
  5. function makeErrorModule(error: any) {
  6. const props = error ? { kModuleError: error } : {};
  7. return new Proxy(props, {
  8. get: (_: any, key: any) => {
  9. if (key === 'kModuleError') {
  10. return error;
  11. }
  12. throw error;
  13. },
  14. set: () => {
  15. throw error;
  16. }
  17. });
  18. }
  19. export let Kerberos: typeof import('kerberos') | { kModuleError: MongoMissingDependencyError } =
  20. makeErrorModule(
  21. new MongoMissingDependencyError(
  22. 'Optional module `kerberos` not found. Please install it to enable kerberos authentication'
  23. )
  24. );
  25. export function getKerberos(): typeof Kerberos | { kModuleError: MongoMissingDependencyError } {
  26. try {
  27. // Ensure you always wrap an optional require in the try block NODE-3199
  28. Kerberos = require('kerberos');
  29. return Kerberos;
  30. } catch {
  31. return Kerberos;
  32. }
  33. }
  34. export interface KerberosClient {
  35. step(challenge: string): Promise<string>;
  36. step(challenge: string, callback: Callback<string>): void;
  37. wrap(challenge: string, options: { user: string }): Promise<string>;
  38. wrap(challenge: string, options: { user: string }, callback: Callback<string>): void;
  39. unwrap(challenge: string): Promise<string>;
  40. unwrap(challenge: string, callback: Callback<string>): void;
  41. }
  42. type ZStandardLib = {
  43. /**
  44. * Compress using zstd.
  45. * @param buf - Buffer to be compressed.
  46. */
  47. compress(buf: Buffer, level?: number): Promise<Buffer>;
  48. /**
  49. * Decompress using zstd.
  50. */
  51. decompress(buf: Buffer): Promise<Buffer>;
  52. };
  53. export let ZStandard: ZStandardLib | { kModuleError: MongoMissingDependencyError } =
  54. makeErrorModule(
  55. new MongoMissingDependencyError(
  56. 'Optional module `@mongodb-js/zstd` not found. Please install it to enable zstd compression'
  57. )
  58. );
  59. export function getZstdLibrary(): typeof ZStandard | { kModuleError: MongoMissingDependencyError } {
  60. try {
  61. ZStandard = require('@mongodb-js/zstd');
  62. return ZStandard;
  63. } catch {
  64. return ZStandard;
  65. }
  66. }
  67. /**
  68. * @internal
  69. * Copy of the AwsCredentialIdentityProvider interface from [`smithy/types`](https://socket.dev/npm/package/\@smithy/types/files/1.1.1/dist-types/identity/awsCredentialIdentity.d.ts),
  70. * the return type of the aws-sdk's `fromNodeProviderChain().provider()`.
  71. */
  72. export interface AWSCredentials {
  73. accessKeyId: string;
  74. secretAccessKey: string;
  75. sessionToken: string;
  76. expiration?: Date;
  77. }
  78. type CredentialProvider = {
  79. fromNodeProviderChain(
  80. this: void,
  81. options: { clientConfig: { region: string } }
  82. ): () => Promise<AWSCredentials>;
  83. fromNodeProviderChain(this: void): () => Promise<AWSCredentials>;
  84. };
  85. export function getAwsCredentialProvider():
  86. | CredentialProvider
  87. | { kModuleError: MongoMissingDependencyError } {
  88. try {
  89. // Ensure you always wrap an optional require in the try block NODE-3199
  90. const credentialProvider = require('@aws-sdk/credential-providers');
  91. return credentialProvider;
  92. } catch {
  93. return makeErrorModule(
  94. new MongoMissingDependencyError(
  95. 'Optional module `@aws-sdk/credential-providers` not found.' +
  96. ' Please install it to enable getting aws credentials via the official sdk.'
  97. )
  98. );
  99. }
  100. }
  101. /** @internal */
  102. export type GcpMetadata =
  103. | typeof import('gcp-metadata')
  104. | { kModuleError: MongoMissingDependencyError };
  105. export function getGcpMetadata(): GcpMetadata {
  106. try {
  107. // Ensure you always wrap an optional require in the try block NODE-3199
  108. const credentialProvider = require('gcp-metadata');
  109. return credentialProvider;
  110. } catch {
  111. return makeErrorModule(
  112. new MongoMissingDependencyError(
  113. 'Optional module `gcp-metadata` not found.' +
  114. ' Please install it to enable getting gcp credentials via the official sdk.'
  115. )
  116. );
  117. }
  118. }
  119. /** @internal */
  120. export type SnappyLib = {
  121. /**
  122. * In order to support both we must check the return value of the function
  123. * @param buf - Buffer to be compressed
  124. */
  125. compress(buf: Buffer): Promise<Buffer>;
  126. /**
  127. * In order to support both we must check the return value of the function
  128. * @param buf - Buffer to be compressed
  129. */
  130. uncompress(buf: Buffer, opt: { asBuffer: true }): Promise<Buffer>;
  131. };
  132. export function getSnappy(): SnappyLib | { kModuleError: MongoMissingDependencyError } {
  133. try {
  134. // Ensure you always wrap an optional require in the try block NODE-3199
  135. const value = require('snappy');
  136. return value;
  137. } catch (cause) {
  138. const kModuleError = new MongoMissingDependencyError(
  139. 'Optional module `snappy` not found. Please install it to enable snappy compression',
  140. { cause }
  141. );
  142. return { kModuleError };
  143. }
  144. }
  145. export type SocksLib = {
  146. SocksClient: {
  147. createConnection(options: {
  148. command: 'connect';
  149. destination: { host: string; port: number };
  150. proxy: {
  151. /** host and port are ignored because we pass existing_socket */
  152. host: 'iLoveJavaScript';
  153. port: 0;
  154. type: 5;
  155. userId?: string;
  156. password?: string;
  157. };
  158. timeout?: number;
  159. /** We always create our own socket, and pass it to this API for proxy negotiation */
  160. existing_socket: Stream;
  161. }): Promise<{ socket: Stream }>;
  162. };
  163. };
  164. export function getSocks(): SocksLib | { kModuleError: MongoMissingDependencyError } {
  165. try {
  166. // Ensure you always wrap an optional require in the try block NODE-3199
  167. const value = require('socks');
  168. return value;
  169. } catch (cause) {
  170. const kModuleError = new MongoMissingDependencyError(
  171. 'Optional module `socks` not found. Please install it to connections over a SOCKS5 proxy',
  172. { cause }
  173. );
  174. return { kModuleError };
  175. }
  176. }
  177. interface AWS4 {
  178. /**
  179. * Created these inline types to better assert future usage of this API
  180. * @param options - options for request
  181. * @param credentials - AWS credential details, sessionToken should be omitted entirely if its false-y
  182. */
  183. sign(
  184. this: void,
  185. options: {
  186. path: '/';
  187. body: string;
  188. host: string;
  189. method: 'POST';
  190. headers: {
  191. 'Content-Type': 'application/x-www-form-urlencoded';
  192. 'Content-Length': number;
  193. 'X-MongoDB-Server-Nonce': string;
  194. 'X-MongoDB-GS2-CB-Flag': 'n';
  195. };
  196. service: string;
  197. region: string;
  198. },
  199. credentials:
  200. | {
  201. accessKeyId: string;
  202. secretAccessKey: string;
  203. sessionToken: string;
  204. }
  205. | {
  206. accessKeyId: string;
  207. secretAccessKey: string;
  208. }
  209. | undefined
  210. ): {
  211. headers: {
  212. Authorization: string;
  213. 'X-Amz-Date': string;
  214. };
  215. };
  216. }
  217. export let aws4: AWS4 | { kModuleError: MongoMissingDependencyError } = makeErrorModule(
  218. new MongoMissingDependencyError(
  219. 'Optional module `aws4` not found. Please install it to enable AWS authentication'
  220. )
  221. );
  222. try {
  223. // Ensure you always wrap an optional require in the try block NODE-3199
  224. aws4 = require('aws4');
  225. } catch {} // eslint-disable-line
  226. /** A utility function to get the instance of mongodb-client-encryption, if it exists. */
  227. export function getMongoDBClientEncryption():
  228. | typeof import('mongodb-client-encryption')
  229. | { kModuleError: MongoMissingDependencyError } {
  230. let mongodbClientEncryption = null;
  231. try {
  232. // NOTE(NODE-3199): Ensure you always wrap an optional require literally in the try block
  233. // Cannot be moved to helper utility function, bundlers search and replace the actual require call
  234. // in a way that makes this line throw at bundle time, not runtime, catching here will make bundling succeed
  235. mongodbClientEncryption = require('mongodb-client-encryption');
  236. } catch (cause) {
  237. const kModuleError = new MongoMissingDependencyError(
  238. 'Optional module `mongodb-client-encryption` not found. Please install it to use auto encryption or ClientEncryption.',
  239. { cause }
  240. );
  241. return { kModuleError };
  242. }
  243. return mongodbClientEncryption;
  244. }