Skip to content

Commit

Permalink
chore: remove deps from angularcli to fully get rid of tslint
Browse files Browse the repository at this point in the history
  • Loading branch information
Cammisuli committed Dec 4, 2021
1 parent f60e704 commit 6b77797
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 62 deletions.
24 changes: 22 additions & 2 deletions libs/schema/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import { Option as CliOption, OptionType } from '@angular/cli/models/interface';
import { Schema } from '@nrwl/tao/src/shared/params';

export enum OptionType {
Any = 'any',
Array = 'array',
Boolean = 'boolean',
Number = 'number',
String = 'string',
}

export type OptionPropertyDescription = Schema['properties'][number];

export type CliOption = {
name: string;
required?: boolean;
positional?: number;
alias?: string;
hidden?: boolean;
deprecated?: boolean | string;
} & OptionPropertyDescription;

export interface Option extends Omit<CliOption, 'default'> {
tooltip?: string;
itemTooltips?: ItemTooltips;
items?: string[] | ItemsWithEnum;
aliases: string[];
default?: string[] | string | number | boolean | undefined;
}

Expand All @@ -19,7 +39,7 @@ export interface ItemsWithEnum {
export type XPrompt = string | LongFormXPrompt;
export interface LongFormXPrompt {
message: string;
type: 'confirmation' | 'input' | 'list';
type: 'confirmation' | 'input' | 'list' | string;
multiselect?: boolean;
items?: (string | OptionItemLabelValue)[];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class TelemetryParameters {
}

require(key: string): void {
// eslint-disable-next-line no-prototype-builtins
if (!this.params.hasOwnProperty(key)) {
throw new Error(
`Telemetry ${this.type} does not have a parameter of ${key}`
Expand Down
3 changes: 2 additions & 1 deletion libs/server/src/lib/telemetry/user.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Store} from "../stores/store";
import { Store } from '../stores/store';

export type UserState = 'untracked' | 'tracked';

Expand All @@ -8,6 +8,7 @@ export class User {
let state: UserState = 'tracked';

if (!id) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
id = require('uuid/v4')();
store.set('uuid', id);
}
Expand Down
37 changes: 20 additions & 17 deletions libs/server/src/lib/utils/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { normalizeSchema } from './utils';
import { OptionType } from '@angular/cli/models/interface';
import { LongFormXPrompt, Option } from '@nx-console/schema';
import {
LongFormXPrompt,
Option,
OptionType,
OptionPropertyDescription,
} from '@nx-console/schema';
import { Schema } from '@nrwl/tao/src/shared/params';

describe('utils', () => {
describe('normalizeSchema', () => {
const mockOption: any = {
name: 'style',
const mockOption: OptionPropertyDescription = {
description: 'The file extension to be used for style files.',
type: OptionType.String,
aliases: [],
};
const getSchema = async (
options: any[],
options: Schema['properties'],
required: string[] = []
): Promise<Option[]> => {
const r = await normalizeSchema({
Expand All @@ -22,12 +25,12 @@ describe('utils', () => {
};

it('should mark fields as required if they are listed in the required array', async () => {
const r = await getSchema([mockOption], ['0']);
const r = await getSchema({ mockOption }, ['mockOption']);
expect(r[0].required).toBeTruthy();
});

it('should not mark fields as required otherwise', async () => {
const r = await getSchema([mockOption]);
const r = await getSchema({ mockOption });
expect(r[0].required).toBeFalsy();
});

Expand All @@ -48,7 +51,7 @@ describe('utils', () => {
...mockOption,
enum: ['test'],
};
const r = await getSchema([option]);
const r = await getSchema({ option });
expect(r[0].items).toEqual(['test']);
});

Expand All @@ -70,7 +73,7 @@ describe('utils', () => {
...mockOption,
'x-prompt': xPromptMessage,
};
const r = await getSchema([option]);
const r = await getSchema({ option });
expect(r[0].tooltip).toBe(xPromptMessage);
});

Expand All @@ -79,12 +82,12 @@ describe('utils', () => {
message: 'test',
type: 'confirmation',
};
const option = {
const option: OptionPropertyDescription = {
...mockOption,
enum: [...Array(11).keys()],
'x-prompt': xPrompt,
enum: [...Array(11).keys()].map((i) => i.toString()),
'x-prompt': xPrompt as any,
};
const r = await getSchema([option]);
const r = await getSchema({ option });
expect(r[0].tooltip).toBe(xPrompt.message);
});

Expand All @@ -97,7 +100,7 @@ describe('utils', () => {
items: xPromptItems,
},
};
const r = await getSchema([option]);
const r = await getSchema({ option });
expect(r[0].itemTooltips).toEqual({
css: xPromptItems[0].label,
scss: xPromptItems[1].label,
Expand All @@ -113,7 +116,7 @@ describe('utils', () => {
items: xPromptItems,
},
};
const r = await getSchema([option]);
const r = await getSchema({ option });
expect(r[0].items).toEqual([
xPromptItems[0].value,
xPromptItems[1].value,
Expand All @@ -129,7 +132,7 @@ describe('utils', () => {
items: ['test'],
},
};
const r = await getSchema([option]);
const r = await getSchema({ option });
expect(r[0].items).toEqual(['test']);
});
});
Expand Down
58 changes: 38 additions & 20 deletions libs/server/src/lib/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { schema } from '@angular-devkit/core';
import { standardFormats } from '@angular-devkit/schematics/src/formats';
import { Option as CliOption } from '@angular/cli/models/interface';
import { parseJsonSchemaToOptions } from '@angular/cli/utilities/json-schema';
import { Schema } from '@nrwl/tao/src/shared/params';
import * as path from 'path';
import type { WorkspaceJsonConfiguration } from '@nrwl/devkit';

import {
ItemsWithEnum,
ItemTooltips,
LongFormXPrompt,
Option,
OptionItemLabelValue,
XPrompt,
CliOption,
} from '@nx-console/schema';

import { readdirSync, statSync } from 'fs';
import { readFile, stat } from 'fs/promises';
import {
Expand All @@ -19,7 +20,6 @@ import {
printParseErrorCode,
} from 'jsonc-parser';
import { readdir } from 'fs/promises';
import * as path from 'path';
import { getOutputChannel } from './output-channel';

export interface GeneratorDefaults {
Expand Down Expand Up @@ -185,7 +185,6 @@ export async function readAndCacheJsonFile(
json: {},
};
}

const fullFilePath = path.join(basedir, filePath);
try {
const stats = await stat(fullFilePath);
Expand All @@ -206,33 +205,29 @@ export async function readAndCacheJsonFile(
};
}

const registry = new schema.CoreSchemaRegistry(standardFormats);

export async function normalizeSchema(
s: {
properties: { [k: string]: any };
required: string[];
},
s: Schema,
projectDefaults?: GeneratorDefaults
): Promise<Option[]> {
const options: CliOption[] = await parseJsonSchemaToOptions(registry, s);
const options = schemaToOptions(s);
const requiredFields = new Set(s.required || []);

const nxOptions = options.map((option) => {
const xPrompt: XPrompt = s.properties[option.name]['x-prompt'];
const xPrompt: XPrompt | undefined = option['x-prompt'];
const workspaceDefault = projectDefaults && projectDefaults[option.name];
const $default = s.properties[option.name].$default;
const $default = option.$default;

const nxOption: Option = {
...option,
required: isFieldRequired(requiredFields, option, xPrompt, $default),
aliases: option.alias ? [option.alias] : [],
...(workspaceDefault !== undefined && { default: workspaceDefault }),
...($default && { $default }),
...(option.enum && { items: option.enum.map((item) => item.toString()) }),
// Strongly suspect items does not belong in the Option schema.
// Angular Option doesn't have the items property outside of x-prompt,
// but items is used in @schematics/angular - guard
...getItems(s.properties[option.name]),
...getItems(option),
};

if (xPrompt) {
Expand Down Expand Up @@ -285,8 +280,8 @@ export async function normalizeSchema(

function isFieldRequired(
requiredFields: Set<string>,
nxOption: Option,
xPrompt: XPrompt,
nxOption: CliOption,
xPrompt: XPrompt | undefined,
$default: any
): boolean {
// checks schema.json requiredFields and xPrompt for required
Expand All @@ -300,11 +295,11 @@ function isFieldRequired(
);
}

function getItems(option: Option): { items: string[] } | undefined {
function getItems(option: CliOption): { items: string[] } | undefined {
return (
option.items && {
items:
(option.items as ItemsWithEnum)?.enum ||
(option.items as ItemsWithEnum).enum ||
((option.items as string[]).length && option.items),
}
);
Expand Down Expand Up @@ -377,3 +372,26 @@ export function toWorkspaceFormat(w: any): WorkspaceJsonConfiguration {
}
return w;
}

function schemaToOptions(schema: Schema): CliOption[] {
return Object.keys(schema.properties).reduce<CliOption[]>((acc, curr) => {
const currentProperties = schema.properties[curr];
const $default = currentProperties.$default;
const $defaultIndex =
$default?.['$source'] === 'argv' ? $default['index'] : undefined;
const positional: number | undefined =
typeof $defaultIndex === 'number' ? $defaultIndex : undefined;

const visible = currentProperties.visible ?? true;
if (!visible || (currentProperties as any).hidden) {
return acc;
}

acc.push({
name: curr,
positional,
...currentProperties,
});
return acc;
}, []);
}
3 changes: 1 addition & 2 deletions libs/vscode-ui/components/src/lib/field/field.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Option } from '@nx-console/schema';
import { OptionType } from '@angular/cli/models/interface';
import { Option, OptionType } from '@nx-console/schema';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Component, DebugElement, ViewChild } from '@angular/core';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { OptionType } from '@angular/cli/models/interface';
import { Option } from '@nx-console/schema';
import { Option, OptionType } from '@nx-console/schema';
import { MultipleSelectComponent } from './multiple-select.component';
import { FieldItemsPipe } from '../field-items/field-items.pipe';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Component, DebugElement, ViewChild } from '@angular/core';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { OptionType } from '@angular/cli/models/interface';
import { Option } from '@nx-console/schema';
import { Option, OptionType } from '@nx-console/schema';
import { SelectComponent } from './select.component';
import { FieldItemsPipe } from '../field-items/field-items.pipe';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { OptionType } from '@angular/cli/models/interface';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';

import { TaskExecutionSchema } from '@nx-console/schema';
import { OptionType, TaskExecutionSchema } from '@nx-console/schema';
import { TASK_EXECUTION_SCHEMA } from './task-execution-form.schema';
import { VscodeUiComponentsModule } from '@nx-console/vscode-ui/components';
import { ArgumentListModule } from '@nx-console/vscode-ui/argument-list';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ import { TASK_EXECUTION_SCHEMA } from './task-execution-form.schema';
import {
TaskExecutionSchema,
TaskExecutionMessage,
ItemsWithEnum
ItemsWithEnum,
OptionType,
Option,
} from '@nx-console/schema';
import { OptionType, Value } from '@angular/cli/models/interface';

declare global {
interface Window {
Expand Down Expand Up @@ -196,11 +197,26 @@ export class TaskExecutionFormComponent implements OnInit, AfterViewChecked {
) {}

ngOnInit() {
this.architectSubject.next(this.initialSchema);
const optionFilter = (option: Option) =>
!(
option.type === OptionType.Array &&
option.items &&
(option.items as string[]).length === 0
);

this.architectSubject.next({
...this.initialSchema,
// remove array options that have no items
// TODO: add support for these types of items in the form
options: this.initialSchema.options.filter(optionFilter),
});

window.SET_TASK_EXECUTION_SCHEMA = (schema) => {
this.ngZone.run(() => {
this.architectSubject.next(schema);
this.architectSubject.next({
...schema,
options: schema.options.filter(optionFilter),
});

setTimeout(() => {
this.scrollToTop();
Expand Down Expand Up @@ -284,7 +300,7 @@ export class TaskExecutionFormComponent implements OnInit, AfterViewChecked {
!validValueSet.has(control.value)) ||
// multiselect values are Array, check if all values are in Set
(Array.isArray(control.value) &&
!control.value.every((value: Value) => validValueSet.has(value)))
!control.value.every((value) => validValueSet.has(value)))
) {
return {
enum: 'Please select a value from the auto-completable list',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { OptionType } from '@angular/cli/models/interface';
import { TaskExecutionSchema } from '@nx-console/schema';
import { OptionType, TaskExecutionSchema } from '@nx-console/schema';
import { TaskExecutionFormComponent } from './task-execution-form.component';
import { TASK_EXECUTION_SCHEMA } from './task-execution-form.schema';
import { VscodeUiFeatureTaskExecutionFormModule } from './vscode-ui-feature-task-execution-form.module';
Expand Down
Loading

0 comments on commit 6b77797

Please sign in to comment.