Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
47 changes: 47 additions & 0 deletions packages/@aws-cdk/toolkit/lib/api/io/private/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,53 @@ export function withAction(ioHost: IIoHost, action: ToolkitAction) {
};
}

export function withoutColor(ioHost: IIoHost): IIoHost {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about how we feel about this but it currently replaces style as well, i.e. chalk.bold

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's fine

return {
notify: async <T>(msg: IoMessage<T>) => {
await ioHost.notify({
...msg,
message: stripColor(msg.message),
});
},
requestResponse: async <T, U>(msg: IoRequest<T, U>) => {
return ioHost.requestResponse({
...msg,
message: stripColor(msg.message),
});
},
};
}

function stripColor(msg: string): string {
return msg.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
}

/**
* An IoHost wrapper that strips out emojis from the message before
* sending the message to the given IoHost
*/
export function withoutEmojis(ioHost: IIoHost): IIoHost {
return {
notify: async <T>(msg: IoMessage<T>) => {
await ioHost.notify({
...msg,
message: stripEmojis(msg.message),
});
},
requestResponse: async <T, U>(msg: IoRequest<T, U>) => {
return ioHost.requestResponse({
...msg,
message: stripEmojis(msg.message),
});
},
};
}

function stripEmojis(msg: string): string {
// https://www.unicode.org/reports/tr51/#def_emoji_presentation
return msg.replace(/\p{Emoji_Presentation}/gu, '');
}

// @todo these cannot be awaited WTF
export function asSdkLogger(ioHost: IIoHost, action: ToolkitAction): Logger {
return new class implements Logger {
Expand Down
32 changes: 28 additions & 4 deletions packages/@aws-cdk/toolkit/lib/toolkit/toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { CachedCloudAssemblySource, IdentityCloudAssemblySource, StackAssembly,
import { ALL_STACKS, CloudAssemblySourceBuilder } from '../api/cloud-assembly/private';
import { ToolkitError } from '../api/errors';
import { IIoHost, IoMessageCode, IoMessageLevel } from '../api/io';
import { asSdkLogger, withAction, Timer, confirm, error, highlight, info, success, warn, ActionAwareIoHost, debug, result } from '../api/io/private';
import { asSdkLogger, withAction, Timer, confirm, error, highlight, info, success, warn, ActionAwareIoHost, debug, result, withoutEmojis, withoutColor } from '../api/io/private';

/**
* The current action being performed by the CLI. 'none' represents the absence of an action.
Expand Down Expand Up @@ -47,6 +47,23 @@ export interface ToolkitOptions {
*/
ioHost?: IIoHost;

/**
* Allow emojis in messages sent to the IoHost.
*
* @default true
*/
emojis?: boolean;

/**
* Whether to allow ANSI colors and formatting in IoHost messages.
* Setting this value to `falsez enforces that no color or style shows up
* in messages sent to the IoHost.
* Setting this value to true is a no-op; it is equivalent to the default.
*
* @default - detects color from the TTY status of the IoHost
*/
color?: boolean;

/**
* Configuration options for the SDK.
*/
Expand Down Expand Up @@ -77,9 +94,9 @@ export class Toolkit extends CloudAssemblySourceBuilder implements AsyncDisposab
public readonly toolkitStackName: string;

/**
* @todo should probably be public in one way or the other.
* The IoHost of this Toolkit
*/
private readonly ioHost: IIoHost;
public readonly ioHost: IIoHost;
private _sdkProvider?: SdkProvider;

public constructor(private readonly props: ToolkitOptions = {}) {
Expand All @@ -91,7 +108,14 @@ export class Toolkit extends CloudAssemblySourceBuilder implements AsyncDisposab
if (props.ioHost) {
globalIoHost.registerIoHost(props.ioHost as any);
}
this.ioHost = globalIoHost as IIoHost;
let ioHost = globalIoHost as IIoHost;
if (props.emojis === false) {
ioHost = withoutEmojis(ioHost);
}
if (props.color === false) {
ioHost = withoutColor(ioHost);
}
this.ioHost = ioHost;
}

public async dispose(): Promise<void> {
Expand Down
45 changes: 44 additions & 1 deletion packages/@aws-cdk/toolkit/test/toolkit/toolkit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,47 @@
* - Source Builders: Tests for the Cloud Assembly Source Builders are in `test/api/cloud-assembly/source-builder.test.ts`
*/

test('test', () => expect(true).toBe(true));
import * as chalk from 'chalk';
import { Toolkit } from '../../lib';
import { TestIoHost } from '../_helpers';

test('emojis can be stripped from message', async () => {
const ioHost = new TestIoHost();
const toolkit = new Toolkit({ ioHost, emojis: false });

await toolkit.ioHost.notify({
message: '💯Smile123😀',
action: 'deploy',
level: 'info',
code: 'CDK_TOOLKIT_I0000',
time: new Date(),
});

expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'deploy',
level: 'info',
code: 'CDK_TOOLKIT_I0000',
message: 'Smile123',
}));
});

test('color can be stripped from message', async () => {
const ioHost = new TestIoHost();
const toolkit = new Toolkit({ ioHost, color: false });

await toolkit.ioHost.notify({
message: chalk.red('RED') + chalk.bold('BOLD') + chalk.blue('BLUE'),
action: 'deploy',
level: 'info',
code: 'CDK_TOOLKIT_I0000',
time: new Date(),
});

expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'deploy',
level: 'info',
code: 'CDK_TOOLKIT_I0000',
message: 'REDBOLDBLUE',
}));
});