Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/e2e-tests/test/e2e-oidc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ describe('OIDC auth e2e', function () {

// Internal hack to get a state-share server as e.g. Compass or the VSCode extension would
let handle = await shell.executeLine(
'db.getMongo()._serviceProvider.currentClientOptions.parentState.getStateShareServer()'
'db.getMongo()._serviceProvider._sp.currentClientOptions.parentState.getStateShareServer()'
);
// `handle` can include the next prompt when returned by `shell.executeLine()`,
// so look for the longest prefix of it that is valid JSON.
Expand Down
7 changes: 5 additions & 2 deletions packages/service-provider-core/src/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {
AutoEncryptionOptions,
Collection,
} from './all-transport-types';
import type { ConnectionExtraInfo } from './index';
import type { ConnectionExtraInfo, ServiceProvider } from './index';
import type { ReplPlatform } from './platform';
import type {
AWSEncryptionKeyOptions,
Expand Down Expand Up @@ -90,7 +90,10 @@ export default interface Admin {
* @param uri
* @param options
*/
getNewConnection(uri: string, options: MongoClientOptions): Promise<any>; // returns the ServiceProvider instance
getNewConnection(
uri: string,
options: MongoClientOptions
): Promise<ServiceProvider>;

/**
* Return the URI for the current connection, if this ServiceProvider is connected.
Expand Down
55 changes: 55 additions & 0 deletions packages/shell-api/src/custom-inspect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { InspectOptions, inspect as _inspect } from 'util';

const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom');

function customDocumentInspect(
this: Document,
depth: number,
inspectOptions: InspectOptions,
inspect: typeof _inspect
) {
const newInspectOptions = {
...inspectOptions,
depth: Infinity,
maxArrayLength: Infinity,
maxStringLength: Infinity,
};

// reuse the standard inpect logic for an object without causing infinite
// recursion
const copyToInspect: any = Array.isArray(this) ? this.slice() : { ...this };
delete copyToInspect[customInspectSymbol];
return inspect(copyToInspect, newInspectOptions);
}

function addInspectSymbol(obj: any) {
if (!(obj as any)[customInspectSymbol]) {
Object.defineProperty(obj, customInspectSymbol, {
value: customDocumentInspect,
enumerable: false,
writable: true,
configurable: true,
});
}
}

export function addCustomInspect(obj: any) {
if (Array.isArray(obj)) {
addInspectSymbol(obj);
for (const item of obj) {
addCustomInspect(item);
}
} else if (
obj &&
typeof obj === 'object' &&
obj !== null &&
!obj._bsontype &&
!(obj instanceof Date) &&
!(obj instanceof RegExp)
) {
addInspectSymbol(obj);
for (const value of Object.values(obj)) {
addCustomInspect(value);
}
}
}
142 changes: 142 additions & 0 deletions packages/shell-api/src/deep-inspect-aggregation-cursor-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import type {
Document,
ReadConcernLike,
ReadPreferenceLike,
ServiceProviderAggregationCursor,
} from '@mongosh/service-provider-core';
import type { PickMethodsByReturnType } from './pick-methods-by-return-type';
import { addCustomInspect } from './custom-inspect';

export class DeepInspectAggregationCursorWrapper<TSchema = Document>
implements ServiceProviderAggregationCursor<TSchema>
{
_cursor: ServiceProviderAggregationCursor<TSchema>;

constructor(cursor: ServiceProviderAggregationCursor<TSchema>) {
this._cursor = cursor;
}

project = forwardedMethod('project');
skip = forwardedMethod('skip');
sort = forwardedMethod('sort');
explain = forwardedMethod('explain');
addCursorFlag = forwardedMethod('addCursorFlag');
withReadPreference = (readPreference: ReadPreferenceLike) => {
this._cursor.withReadPreference(readPreference);
return this;
};
withReadConcern(readConcern: ReadConcernLike) {
this._cursor.withReadConcern(readConcern);
return this;
}
batchSize = forwardedMethod('batchSize');
hasNext = forwardedMethod('hasNext');
close = forwardedMethod('close');
maxTimeMS = forwardedMethod('maxTimeMS');
bufferedCount = forwardedMethod('bufferedCount');

next = forwardResultPromise<TSchema, 'next'>('next');
tryNext = forwardResultPromise<TSchema, 'tryNext'>('tryNext');

toArray = forwardResultsPromise<TSchema, 'toArray'>('toArray');
readBufferedDocuments = forwardResults<TSchema, 'readBufferedDocuments'>(
'readBufferedDocuments'
);

get closed(): boolean {
return this._cursor.closed;
}

async *[Symbol.asyncIterator]() {
yield* this._cursor;
return;
}
}

function forwardResultPromise<
TSchema,
K extends keyof PickMethodsByReturnType<
ServiceProviderAggregationCursor<TSchema>,
Promise<TSchema | null>
>
>(
key: K
): (
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
) => ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
return async function (
this: DeepInspectAggregationCursorWrapper,
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
): // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore The returntype already contains a promise
ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
const result = await (this._cursor[key] as any)(...args);
if (result) {
addCustomInspect(result);
}
return result;
};
}

function forwardResultsPromise<
TSchema,
K extends keyof PickMethodsByReturnType<
ServiceProviderAggregationCursor<TSchema>,
Promise<TSchema[]>
>
>(
key: K
): (
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
) => ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
return async function (
this: DeepInspectAggregationCursorWrapper,
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
): // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore The returntype already contains a promise
ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
const results = await (this._cursor[key] as any)(...args);
addCustomInspect(results);
return results;
};
}

function forwardResults<
TSchema,
K extends keyof PickMethodsByReturnType<
ServiceProviderAggregationCursor<TSchema>,
TSchema[]
>
>(
key: K
): (
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
) => ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
return function (
this: DeepInspectAggregationCursorWrapper,
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
): ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
const results = (this._cursor[key] as any)(...args);
addCustomInspect(results);
return results;
};
}

function forwardedMethod<
TSchema,
K extends keyof PickMethodsByReturnType<
ServiceProviderAggregationCursor<TSchema>,
any
>
>(
key: K
): (
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
) => ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
return function (
this: DeepInspectAggregationCursorWrapper,
...args: Parameters<Required<ServiceProviderAggregationCursor<TSchema>>[K]>
): ReturnType<Required<ServiceProviderAggregationCursor<TSchema>>[K]> {
return (this._cursor[key] as any)(...args);
};
}
80 changes: 80 additions & 0 deletions packages/shell-api/src/deep-inspect-change-stream-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type {
Document,
ResumeToken,
ServiceProviderChangeStream,
} from '@mongosh/service-provider-core';
import type { PickMethodsByReturnType } from './pick-methods-by-return-type';
import { addCustomInspect } from './custom-inspect';

export class DeepInspectChangeStreamWrapper<TSchema = Document>
implements ServiceProviderChangeStream<TSchema>
{
_cursor: ServiceProviderChangeStream<TSchema>;

constructor(cursor: ServiceProviderChangeStream<TSchema>) {
this._cursor = cursor;
}

get resumeToken(): ResumeToken {
return this._cursor.resumeToken;
}

hasNext = forwardedMethod('hasNext');
close = forwardedMethod('close');

next = forwardResultPromise<TSchema, 'next'>('next');
tryNext = forwardResultPromise<TSchema, 'tryNext'>('tryNext');

get closed(): boolean {
return this._cursor.closed;
}

async *[Symbol.asyncIterator]() {
yield* this._cursor;
return;
}
}

function forwardResultPromise<
TSchema,
K extends keyof PickMethodsByReturnType<
ServiceProviderChangeStream<TSchema>,
Promise<TSchema | null>
>
>(
key: K
): (
...args: Parameters<Required<ServiceProviderChangeStream<TSchema>>[K]>
) => ReturnType<Required<ServiceProviderChangeStream<TSchema>>[K]> {
return async function (
this: DeepInspectChangeStreamWrapper,
...args: Parameters<Required<ServiceProviderChangeStream<TSchema>>[K]>
): // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore The returntype already contains a promise
ReturnType<Required<ServiceProviderChangeStream<TSchema>>[K]> {
const result = await (this._cursor[key] as any)(...args);
if (result) {
addCustomInspect(result);
}
return result;
};
}

function forwardedMethod<
TSchema,
K extends keyof PickMethodsByReturnType<
ServiceProviderChangeStream<TSchema>,
any
>
>(
key: K
): (
...args: Parameters<Required<ServiceProviderChangeStream<TSchema>>[K]>
) => ReturnType<Required<ServiceProviderChangeStream<TSchema>>[K]> {
return function (
this: DeepInspectChangeStreamWrapper,
...args: Parameters<Required<ServiceProviderChangeStream<TSchema>>[K]>
): ReturnType<Required<ServiceProviderChangeStream<TSchema>>[K]> {
return (this._cursor[key] as any)(...args);
};
}
Loading
Loading