Skip to content

Commit

Permalink
refactor(cli): texture lib (#6280)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Jan 9, 2025
1 parent 817c4e7 commit 52e3be3
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 83 deletions.
2 changes: 1 addition & 1 deletion integration-tests/tests/api/policy/policy-check.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,11 @@ describe('Schema policy checks', () => {
' - Description is required for type Query (source: policy-require-description)',
' - Description is required for type User (source: policy-require-description)',
'',
'',
'⚠ Detected 1 warning',
'',
' - Deprecation reason is required for field foo in type Query. (source: policy-require-deprecation-reason)',
'',
'',
'ℹ Detected 3 changes',
'',
' Safe changes:',
Expand Down
19 changes: 5 additions & 14 deletions packages/libraries/cli/src/base-command.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import colors from 'colors';
import { print, type GraphQLError } from 'graphql';
import type { ExecutionResult } from 'graphql';
import { http } from '@graphql-hive/core';
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
import { Command, Errors, Flags, Interfaces } from '@oclif/core';
import { Config, GetConfigurationValueType, ValidConfigurationKeys } from './helpers/config';
import { Texture } from './helpers/texture/texture';

export type Flags<T extends typeof Command> = Interfaces.InferredFlags<
(typeof BaseCommand)['baseFlags'] & T['flags']
Expand Down Expand Up @@ -53,28 +53,19 @@ export default abstract class BaseCommand<T extends typeof Command> extends Comm
}

success(...args: any[]) {
this.log(colors.green('✔'), ...args);
this.log(Texture.success(...args));
}

fail(...args: any[]) {
this.log(colors.red('✖'), ...args);
this.log(Texture.failure(...args));
}

info(...args: any[]) {
this.log(colors.yellow('ℹ'), ...args);
this.log(Texture.info(...args));
}

infoWarning(...args: any[]) {
this.log(colors.yellow('⚠'), ...args);
}

bolderize(msg: string) {
const findSingleQuotes = /'([^']+)'/gim;
const findDoubleQuotes = /"([^"]+)"/gim;

return msg
.replace(findSingleQuotes, (_: string, value: string) => colors.bold(value))
.replace(findDoubleQuotes, (_: string, value: string) => colors.bold(value));
this.log(Texture.warning(...args));
}

maybe<TArgs extends Record<string, any>, TKey extends keyof TArgs>({
Expand Down
3 changes: 2 additions & 1 deletion packages/libraries/cli/src/commands/config/delete.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Args } from '@oclif/core';
import Command from '../../base-command';
import { Texture } from '../../helpers/texture/texture';

export default class DeleteConfig extends Command<typeof DeleteConfig> {
static description = 'deletes specific cli configuration';
Expand All @@ -14,6 +15,6 @@ export default class DeleteConfig extends Command<typeof DeleteConfig> {
async run() {
const { args } = await this.parse(DeleteConfig);
this._userConfig!.delete(args.key);
this.success(this.bolderize(`Config flag "${args.key}" was deleted`));
this.success(Texture.boldQuotedWords(`Config flag "${args.key}" was deleted`));
}
}
3 changes: 2 additions & 1 deletion packages/libraries/cli/src/commands/config/set.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Args } from '@oclif/core';
import Command from '../../base-command';
import { allowedKeys, ValidConfigurationKeys } from '../../helpers/config';
import { Texture } from '../../helpers/texture/texture';

export default class SetConfig extends Command<typeof SetConfig> {
static description = 'updates specific cli configuration';
Expand All @@ -21,6 +22,6 @@ export default class SetConfig extends Command<typeof SetConfig> {
async run() {
const { args } = await this.parse(SetConfig);
this.userConfig.set(args.key as ValidConfigurationKeys, args.value);
this.success(this.bolderize(`Config flag "${args.key}" was set to "${args.value}"`));
this.success(Texture.boldQuotedWords(`Config flag "${args.key}" was set to "${args.value}"`));
}
}
16 changes: 9 additions & 7 deletions packages/libraries/cli/src/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,14 @@ export default class Dev extends Command<typeof Dev> {

if (compositionHasErrors(compositionResult)) {
if (compositionResult.errors) {
renderErrors.call(this, {
total: compositionResult.errors.length,
nodes: compositionResult.errors.map(error => ({
message: error.message,
})),
});
this.log(
renderErrors({
total: compositionResult.errors.length,
nodes: compositionResult.errors.map(error => ({
message: error.message,
})),
}),
);
}

input.onError('Composition failed');
Expand Down Expand Up @@ -371,7 +373,7 @@ export default class Dev extends Command<typeof Dev> {

if (!valid) {
if (compositionResult.errors) {
renderErrors.call(this, compositionResult.errors);
this.log(renderErrors(compositionResult.errors));
}

input.onError('Composition failed');
Expand Down
9 changes: 5 additions & 4 deletions packages/libraries/cli/src/commands/operations/check.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { buildSchema, GraphQLError, Source } from 'graphql';
import { InvalidDocument, validate } from '@graphql-inspector/core';
import { Args, Errors, Flags, ux } from '@oclif/core';
import { Args, Errors, Flags } from '@oclif/core';
import Command from '../../base-command';
import { graphql } from '../../gql';
import { graphqlEndpoint } from '../../helpers/config';
import { ACCESS_TOKEN_MISSING } from '../../helpers/errors';
import { loadOperations } from '../../helpers/operations';
import { Texture } from '../../helpers/texture/texture';

const fetchLatestVersionQuery = graphql(/* GraphQL */ `
query fetchLatestVersion {
Expand Down Expand Up @@ -164,7 +165,7 @@ export default class OperationsCheck extends Command<typeof OperationsCheck> {
return;
}

ux.styledHeader('Summary');
this.log(Texture.header('Summary'));
this.log(
[
`Total: ${operations.length}`,
Expand All @@ -175,7 +176,7 @@ export default class OperationsCheck extends Command<typeof OperationsCheck> {
].join('\n'),
);

ux.styledHeader('Details');
this.log(Texture.header('Details'));

this.printInvalidDocuments(operationsWithErrors);
this.exit(1);
Expand All @@ -198,7 +199,7 @@ export default class OperationsCheck extends Command<typeof OperationsCheck> {
private renderErrors(sourceName: string, errors: GraphQLError[]) {
this.fail(sourceName);
errors.forEach(e => {
this.log(` - ${this.bolderize(e.message)}`);
this.log(` - ${Texture.boldQuotedWords(e.message)}`);
});
this.log('');
}
Expand Down
15 changes: 5 additions & 10 deletions packages/libraries/cli/src/commands/schema/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,12 @@ export default class SchemaCheck extends Command<typeof SchemaCheck> {
} else if (!changes?.total) {
this.success('No changes');
} else {
renderChanges.call(this, changes);
this.log('');
this.log(renderChanges(changes));
}

const warnings = result.schemaCheck.warnings;
if (warnings?.total) {
renderWarnings.call(this, warnings);
this.log('');
this.log(renderWarnings(warnings));
}

if (result.schemaCheck.schemaCheck?.webUrl) {
Expand All @@ -257,20 +255,17 @@ export default class SchemaCheck extends Command<typeof SchemaCheck> {
const changes = result.schemaCheck.changes;
const errors = result.schemaCheck.errors;
const warnings = result.schemaCheck.warnings;
renderErrors.call(this, errors);
this.log(renderErrors(errors));

if (warnings?.total) {
renderWarnings.call(this, warnings);
this.log('');
this.log(renderWarnings(warnings));
}

if (changes && changes.total) {
this.log('');
renderChanges.call(this, changes);
this.log(renderChanges(changes));
}

if (result.schemaCheck.schemaCheck?.webUrl) {
this.log('');
this.log(`View full report:\n${result.schemaCheck.schemaCheck.webUrl}`);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/libraries/cli/src/commands/schema/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export default class SchemaDelete extends Command<typeof SchemaDelete> {
const errors = result.schemaDelete.errors;

if (errors) {
renderErrors.call(this, errors);
this.log(renderErrors(errors));
this.exit(1);
}
} catch (error) {
Expand Down
6 changes: 3 additions & 3 deletions packages/libraries/cli/src/commands/schema/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export default class SchemaPublish extends Command<typeof SchemaPublish> {
this.success('No changes. Skipping.');
} else {
if (changes) {
renderChanges.call(this, changes);
this.log(renderChanges(changes));
}
this.success('Schema published');
}
Expand All @@ -331,11 +331,11 @@ export default class SchemaPublish extends Command<typeof SchemaPublish> {
} else if (result.schemaPublish.__typename === 'SchemaPublishError') {
const changes = result.schemaPublish.changes;
const errors = result.schemaPublish.errors;
renderErrors.call(this, errors);
this.log(renderErrors(errors));

if (changes && changes.total) {
this.log('');
renderChanges.call(this, changes);
this.log(renderChanges(changes));
}
this.log('');

Expand Down
17 changes: 10 additions & 7 deletions packages/libraries/cli/src/commands/whoami.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import colors from 'colors';
import { Flags } from '@oclif/core';
import Command from '../base-command';
import { graphql } from '../gql';
import { graphqlEndpoint } from '../helpers/config';
import { ACCESS_TOKEN_MISSING } from '../helpers/errors';
import { Texture } from '../helpers/texture/texture';

const myTokenInfoQuery = graphql(/* GraphQL */ `
query myTokenInfo {
Expand Down Expand Up @@ -95,16 +95,19 @@ export default class WhoAmI extends Command<typeof WhoAmI> {
const targetUrl = `${projectUrl}/${target.slug}`;

const access = {
yes: colors.green('Yes'),
not: colors.red('No access'),
yes: Texture.colors.green('Yes'),
not: Texture.colors.red('No access'),
};

const print = createPrinter({
'Token name:': [colors.bold(tokenInfo.token.name)],
'Token name:': [Texture.colors.bold(tokenInfo.token.name)],
' ': [''],
'Organization:': [colors.bold(organization.slug), colors.dim(organizationUrl)],
'Project:': [colors.bold(project.slug), colors.dim(projectUrl)],
'Target:': [colors.bold(target.slug), colors.dim(targetUrl)],
'Organization:': [
Texture.colors.bold(organization.slug),
Texture.colors.dim(organizationUrl),
],
'Project:': [Texture.colors.bold(project.slug), Texture.colors.dim(projectUrl)],
'Target:': [Texture.colors.bold(target.slug), Texture.colors.dim(targetUrl)],
' ': [''],
'Access to schema:publish': [tokenInfo.canPublishSchema ? access.yes : access.not],
'Access to schema:check': [tokenInfo.canCheckSchema ? access.yes : access.not],
Expand Down
Loading

0 comments on commit 52e3be3

Please sign in to comment.