[ts] enable "resolveJsonModule" and disable existing failures (#78855)

Co-authored-by: spalger <spalger@users.noreply.github.com>
This commit is contained in:
Spencer 2020-09-30 15:44:43 -07:00 committed by GitHub
parent 886ad8504b
commit 06d1628a00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 69 additions and 36 deletions

View file

@ -39,6 +39,8 @@
// Resolve modules in the same way as Node.js. Aka make `require` works the // Resolve modules in the same way as Node.js. Aka make `require` works the
// same in TypeScript as it does in Node.js. // same in TypeScript as it does in Node.js.
"moduleResolution": "node", "moduleResolution": "node",
// "resolveJsonModule" allows for importing, extracting types from and generating .json files.
"resolveJsonModule": true,
// Disallow inconsistently-cased references to the same file. // Disallow inconsistently-cased references to the same file.
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
// Forbid unused local variables as the rule was deprecated by ts-lint // Forbid unused local variables as the rule was deprecated by ts-lint

9
typings/index.d.ts vendored
View file

@ -35,15 +35,6 @@ declare module '*.svg' {
export default content; export default content;
} }
// allow JSON files to be imported directly without lint errors
// see: https://github.com/palantir/tslint/issues/1264#issuecomment-228433367
// and: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#arbitrary-expressions-are-forbidden-in-export-assignments-in-ambient-contexts
declare module '*.json' {
const json: any;
// eslint-disable-next-line import/no-default-export
export default json;
}
type MethodKeysOf<T> = { type MethodKeysOf<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T]; }[keyof T];

View file

@ -43,6 +43,7 @@ describe('ErrorGroupOverview -> List', () => {
<MemoryRouter> <MemoryRouter>
<MockApmPluginContextWrapper> <MockApmPluginContextWrapper>
<MockUrlParamsContextProvider> <MockUrlParamsContextProvider>
{/* @ts-expect-error invalid json props */}
<ErrorGroupList items={props.items} serviceName="opbeans-python" /> <ErrorGroupList items={props.items} serviceName="opbeans-python" />
</MockUrlParamsContextProvider> </MockUrlParamsContextProvider>
</MockApmPluginContextWrapper> </MockApmPluginContextWrapper>

View file

@ -15,6 +15,7 @@ import mockTransaction from './mockTransaction.json';
describe('DiscoverTransactionLink component', () => { describe('DiscoverTransactionLink component', () => {
it('should render with data', () => { it('should render with data', () => {
// @ts-expect-error invalid json mock
const transaction: Transaction = mockTransaction; const transaction: Transaction = mockTransaction;
expect( expect(
@ -25,6 +26,7 @@ describe('DiscoverTransactionLink component', () => {
describe('getDiscoverQuery', () => { describe('getDiscoverQuery', () => {
it('should return the correct query params object', () => { it('should return the correct query params object', () => {
// @ts-expect-error invalid json mock
const transaction: Transaction = mockTransaction; const transaction: Transaction = mockTransaction;
const result = getDiscoverQuery(transaction); const result = getDiscoverQuery(transaction);
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();

View file

@ -10,6 +10,7 @@ import expectedGroupedData from './mock_responses/group_resource_nodes_grouped.j
describe('groupResourceNodes', () => { describe('groupResourceNodes', () => {
it('should group external nodes', () => { it('should group external nodes', () => {
// @ts-expect-error invalid json mock
const responseWithGroups = groupResourceNodes(preGroupedData); const responseWithGroups = groupResourceNodes(preGroupedData);
expect(responseWithGroups.elements).toHaveLength( expect(responseWithGroups.elements).toHaveLength(
expectedGroupedData.elements.length expectedGroupedData.elements.length
@ -17,7 +18,7 @@ describe('groupResourceNodes', () => {
for (const element of responseWithGroups.elements) { for (const element of responseWithGroups.elements) {
const expectedElement = expectedGroupedData.elements.find( const expectedElement = expectedGroupedData.elements.find(
({ data: { id } }: { data: { id: string } }) => id === element.data.id ({ data: { id } }: { data: { id: string } }) => id === element.data.id
); )!;
expect(element).toMatchObject(expectedElement); expect(element).toMatchObject(expectedElement);
} }
}); });

View file

@ -31,6 +31,7 @@ describe('getServiceAnnotations', () => {
searchAggregatedTransactions: false, searchAggregatedTransactions: false,
}), }),
{ {
// @ts-expect-error invalid json mock
mockResponse: () => noVersions, mockResponse: () => noVersions,
} }
); );
@ -50,6 +51,7 @@ describe('getServiceAnnotations', () => {
searchAggregatedTransactions: false, searchAggregatedTransactions: false,
}), }),
{ {
// @ts-expect-error invalid json mock
mockResponse: () => oneVersion, mockResponse: () => oneVersion,
} }
); );
@ -74,6 +76,7 @@ describe('getServiceAnnotations', () => {
searchAggregatedTransactions: false, searchAggregatedTransactions: false,
}), }),
{ {
// @ts-expect-error invalid json mock
mockResponse: () => responses.shift(), mockResponse: () => responses.shift(),
} }
); );

View file

@ -61,6 +61,7 @@ export function demodata(): ExpressionFunctionDefinition<
{ id: 'project', name: 'project', meta: { type: 'string' } }, { id: 'project', name: 'project', meta: { type: 'string' } },
{ id: 'percent_uptime', name: 'percent_uptime', meta: { type: 'number' } }, { id: 'percent_uptime', name: 'percent_uptime', meta: { type: 'number' } },
], ],
// @ts-expect-error invalid json mock
rows: sortBy(demoRows, 'time'), rows: sortBy(demoRows, 'time'),
}; };
} else if (args.type === DemoRows.SHIRTS) { } else if (args.type === DemoRows.SHIRTS) {

View file

@ -11,4 +11,11 @@ import test from './workpads/test.json';
export * from './utils'; export * from './utils';
export type WorkpadNames = keyof typeof sharedWorkpads; export type WorkpadNames = keyof typeof sharedWorkpads;
export const sharedWorkpads = { hello, austin, test }; export const sharedWorkpads = {
// TODO: the automatic types for these JSON files are insufficient, and "austin" is so massive
// that Typescript refuses to type it. These should be converted to TypeScript and typed to fit
// the requirements. "austin" should also be reduced to the necessary data
hello: hello as any,
austin: austin as any,
test: test as any,
};

View file

@ -16,6 +16,7 @@ export const createApolloClient = (fetch: HttpHandler) => {
const cache = new InMemoryCache({ const cache = new InMemoryCache({
addTypename: false, addTypename: false,
fragmentMatcher: new IntrospectionFragmentMatcher({ fragmentMatcher: new IntrospectionFragmentMatcher({
// @ts-expect-error apollo-cache-inmemory types don't match actual introspection data
introspectionQueryResultData, introspectionQueryResultData,
}), }),
}); });

View file

@ -21,6 +21,7 @@ describe('AnnotationDescriptionList', () => {
}); });
test('Initialization with annotation.', () => { test('Initialization with annotation.', () => {
// @ts-expect-error mock data is too loosely typed
const wrapper = shallowWithIntl(<AnnotationDescriptionList annotation={mockAnnotations[0]} />); const wrapper = shallowWithIntl(<AnnotationDescriptionList annotation={mockAnnotations[0]} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });

View file

@ -51,6 +51,7 @@ describe('DeleteAction', () => {
it('should display a tooltip when isDisabled prop is true.', () => { it('should display a tooltip when isDisabled prop is true.', () => {
const { container } = render( const { container } = render(
// @ts-expect-error mock data is incorrectly typed
<DeleteActionName isDisabled={true} item={mockAnalyticsListItem} /> <DeleteActionName isDisabled={true} item={mockAnalyticsListItem} />
); );
@ -59,6 +60,7 @@ describe('DeleteAction', () => {
it('should not display a tooltip when isDisabled prop is false.', () => { it('should not display a tooltip when isDisabled prop is false.', () => {
const { container } = render( const { container } = render(
// @ts-expect-error mock data is incorrectly typed
<DeleteActionName isDisabled={false} item={mockAnalyticsListItem} /> <DeleteActionName isDisabled={false} item={mockAnalyticsListItem} />
); );
@ -78,8 +80,12 @@ describe('DeleteAction', () => {
{deleteAction.isModalVisible && <DeleteActionModal {...deleteAction} />} {deleteAction.isModalVisible && <DeleteActionModal {...deleteAction} />}
<button <button
data-test-subj="mlAnalyticsJobDeleteButton" data-test-subj="mlAnalyticsJobDeleteButton"
onClick={() => deleteAction.openModal(mockAnalyticsListItem)} onClick={() => {
// @ts-expect-error mock data is incorrectly typed
deleteAction.openModal(mockAnalyticsListItem);
}}
> >
{/* @ts-expect-error mock data is incorrectly typed */}
<DeleteActionName isDisabled={false} item={mockAnalyticsListItem} /> <DeleteActionName isDisabled={false} item={mockAnalyticsListItem} />
</button> </button>
</> </>

View file

@ -10,6 +10,7 @@ import { getAnnotationLevels } from './timeseries_chart_annotations';
describe('Timeseries Chart Annotations: getAnnotationLevels()', () => { describe('Timeseries Chart Annotations: getAnnotationLevels()', () => {
test('getAnnotationLevels()', () => { test('getAnnotationLevels()', () => {
// @ts-expect-error mock data is too loosely typed
const levels = getAnnotationLevels(mockAnnotationsOverlap); const levels = getAnnotationLevels(mockAnnotationsOverlap);
expect(levels).toEqual({ A: 0, B: 1, C: 2, D: 2 }); expect(levels).toEqual({ A: 0, B: 1, C: 2, D: 2 });
}); });

View file

@ -144,6 +144,7 @@ describe('ML - validateTimeRange', () => {
it('invalid time field', () => { it('invalid time field', () => {
const mockSearchResponseInvalid = cloneDeep(mockSearchResponse); const mockSearchResponseInvalid = cloneDeep(mockSearchResponse);
// @ts-expect-error creating intentionally invalid data
mockSearchResponseInvalid.fieldCaps = undefined; mockSearchResponseInvalid.fieldCaps = undefined;
const duration = { start: 0, end: 1 }; const duration = { start: 0, end: 1 };
return validateTimeRange( return validateTimeRange(

View file

@ -26,6 +26,7 @@ describe('getLinks helper', () => {
const mockCache = new InMemoryCache({ const mockCache = new InMemoryCache({
dataIdFromObject: () => null, dataIdFromObject: () => null,
fragmentMatcher: new IntrospectionFragmentMatcher({ fragmentMatcher: new IntrospectionFragmentMatcher({
// @ts-expect-error apollo-cache-inmemory types don't match actual introspection data
introspectionQueryResultData, introspectionQueryResultData,
}), }),
}); });

View file

@ -17,6 +17,7 @@ export function composeLibs(core: CoreStart): AppFrontendLibs {
const cache = new InMemoryCache({ const cache = new InMemoryCache({
dataIdFromObject: () => null, dataIdFromObject: () => null,
fragmentMatcher: new IntrospectionFragmentMatcher({ fragmentMatcher: new IntrospectionFragmentMatcher({
// @ts-expect-error apollo-cache-inmemory types don't match actual introspection data
introspectionQueryResultData, introspectionQueryResultData,
}), }),
}); });

View file

@ -7,8 +7,11 @@
import { uniq } from 'lodash/fp'; import { uniq } from 'lodash/fp';
import { db } from 'suricata-sid-db'; import { db } from 'suricata-sid-db';
const has = <T>(obj: T, key: string | number | symbol): key is keyof T =>
Object.prototype.hasOwnProperty.call(obj, key);
export const getLinksFromSignature = (id: number): string[] => { export const getLinksFromSignature = (id: number): string[] => {
const refs = db[id]; const refs = has(db, id) ? db[id] : null;
if (refs != null) { if (refs != null) {
return uniq(refs); return uniq(refs);
} else { } else {

View file

@ -8,7 +8,6 @@ import signalsMapping from './signals_mapping.json';
import ecsMapping from './ecs_mapping.json'; import ecsMapping from './ecs_mapping.json';
export const getSignalsTemplate = (index: string) => { export const getSignalsTemplate = (index: string) => {
ecsMapping.mappings.properties.signal = signalsMapping.mappings.properties.signal;
const template = { const template = {
settings: { settings: {
index: { index: {
@ -24,7 +23,13 @@ export const getSignalsTemplate = (index: string) => {
}, },
}, },
index_patterns: [`${index}-*`], index_patterns: [`${index}-*`],
mappings: ecsMapping.mappings, mappings: {
...ecsMapping.mappings,
properties: {
...ecsMapping.mappings.properties,
signal: signalsMapping.mappings.properties.signal,
},
},
version: 1, version: 1,
}; };
return template; return template;

View file

@ -33,12 +33,14 @@ describe('get_existing_prepackaged_rules', () => {
}); });
test('should throw an exception if a pre-packaged rule is not valid', () => { test('should throw an exception if a pre-packaged rule is not valid', () => {
// @ts-expect-error intentionally invalid argument
expect(() => getPrepackagedRules([{ not_valid_made_up_key: true }])).toThrow( expect(() => getPrepackagedRules([{ not_valid_made_up_key: true }])).toThrow(
'name: "(rule name unknown)", rule_id: "(rule rule_id unknown)" within the folder rules/prepackaged_rules is not a valid detection engine rule. Expect the system to not work with pre-packaged rules until this rule is fixed or the file is removed. Error is: Invalid value "undefined" supplied to "description",Invalid value "undefined" supplied to "risk_score",Invalid value "undefined" supplied to "name",Invalid value "undefined" supplied to "severity",Invalid value "undefined" supplied to "type",Invalid value "undefined" supplied to "rule_id",Invalid value "undefined" supplied to "version", Full rule contents are:\n{\n "not_valid_made_up_key": true\n}' 'name: "(rule name unknown)", rule_id: "(rule rule_id unknown)" within the folder rules/prepackaged_rules is not a valid detection engine rule. Expect the system to not work with pre-packaged rules until this rule is fixed or the file is removed. Error is: Invalid value "undefined" supplied to "description",Invalid value "undefined" supplied to "risk_score",Invalid value "undefined" supplied to "name",Invalid value "undefined" supplied to "severity",Invalid value "undefined" supplied to "type",Invalid value "undefined" supplied to "rule_id",Invalid value "undefined" supplied to "version", Full rule contents are:\n{\n "not_valid_made_up_key": true\n}'
); );
}); });
test('should throw an exception with a message having rule_id and name in it', () => { test('should throw an exception with a message having rule_id and name in it', () => {
// @ts-expect-error intentionally invalid argument
expect(() => getPrepackagedRules([{ name: 'rule name', rule_id: 'id-123' }])).toThrow( expect(() => getPrepackagedRules([{ name: 'rule name', rule_id: 'id-123' }])).toThrow(
'name: "rule name", rule_id: "id-123" within the folder rules/prepackaged_rules is not a valid detection engine rule. Expect the system to not work with pre-packaged rules until this rule is fixed or the file is removed. Error is: Invalid value "undefined" supplied to "description",Invalid value "undefined" supplied to "risk_score",Invalid value "undefined" supplied to "severity",Invalid value "undefined" supplied to "type",Invalid value "undefined" supplied to "version", Full rule contents are:\n{\n "name": "rule name",\n "rule_id": "id-123"\n}' 'name: "rule name", rule_id: "id-123" within the folder rules/prepackaged_rules is not a valid detection engine rule. Expect the system to not work with pre-packaged rules until this rule is fixed or the file is removed. Error is: Invalid value "undefined" supplied to "description",Invalid value "undefined" supplied to "risk_score",Invalid value "undefined" supplied to "severity",Invalid value "undefined" supplied to "type",Invalid value "undefined" supplied to "version", Full rule contents are:\n{\n "name": "rule name",\n "rule_id": "id-123"\n}'
); );

View file

@ -15,6 +15,8 @@ import {
AddPrepackagedRulesSchemaDecoded, AddPrepackagedRulesSchemaDecoded,
} from '../../../../common/detection_engine/schemas/request/add_prepackaged_rules_schema'; } from '../../../../common/detection_engine/schemas/request/add_prepackaged_rules_schema';
import { BadRequestError } from '../errors/bad_request_error'; import { BadRequestError } from '../errors/bad_request_error';
// TODO: convert rules files to TS and add explicit type definitions
import { rawRules } from './prepackaged_rules'; import { rawRules } from './prepackaged_rules';
/** /**
@ -49,5 +51,7 @@ export const validateAllPrepackagedRules = (
}); });
}; };
export const getPrepackagedRules = (rules = rawRules): AddPrepackagedRulesSchemaDecoded[] => export const getPrepackagedRules = (
validateAllPrepackagedRules(rules); // @ts-expect-error mock data is too loosely typed
rules: AddPrepackagedRulesSchema[] = rawRules
): AddPrepackagedRulesSchemaDecoded[] => validateAllPrepackagedRules(rules);

View file

@ -12,11 +12,12 @@ import { getTransformProgress, isCompletedBatchTransform } from './transform_sta
const getRow = (statsId: string) => { const getRow = (statsId: string) => {
return { return {
// @ts-expect-error mock data does not actually match TransformListRow type
...(mockTransformListRow as TransformListRow), ...(mockTransformListRow as TransformListRow),
stats: { stats: {
...mockTransformStats.transforms.find( ...(mockTransformStats.transforms as Array<TransformListRow['stats']>).find(
(stats: TransformListRow['stats']) => stats.id === statsId (stats) => stats.id === statsId
), )!,
}, },
}; };
}; };

View file

@ -17,6 +17,7 @@ jest.mock('../../../../../app/app_dependencies');
describe('Transform: Transform List Actions <StartAction />', () => { describe('Transform: Transform List Actions <StartAction />', () => {
test('Minimal initialization', () => { test('Minimal initialization', () => {
// @ts-expect-error mock data is too loosely typed
const item: TransformListRow = transformListRow; const item: TransformListRow = transformListRow;
const props: StartActionNameProps = { const props: StartActionNameProps = {
forceDisable: false, forceDisable: false,

View file

@ -17,6 +17,7 @@ jest.mock('../../../../../app/app_dependencies');
describe('Transform: Transform List Actions <StopAction />', () => { describe('Transform: Transform List Actions <StopAction />', () => {
test('Minimal initialization', () => { test('Minimal initialization', () => {
// @ts-expect-error mock data is too loosely typed
const item: TransformListRow = transformListRow; const item: TransformListRow = transformListRow;
const props: StopActionNameProps = { const props: StopActionNameProps = {
forceDisable: false, forceDisable: false,

View file

@ -15,14 +15,15 @@ describe('Transform: isCompletedBatchTransform()', () => {
// check the transform config/state against the conditions // check the transform config/state against the conditions
// that will be used by isCompletedBatchTransform() // that will be used by isCompletedBatchTransform()
// followed by a call to isCompletedBatchTransform() itself // followed by a call to isCompletedBatchTransform() itself
// @ts-expect-error mock data is too loosely typed
const row = mockTransformListRow as TransformListRow; const row = mockTransformListRow as TransformListRow;
expect(row.stats.checkpointing.last.checkpoint === 1).toBe(true); expect(row.stats.checkpointing.last.checkpoint === 1).toBe(true);
expect(row.config.sync === undefined).toBe(true); expect(row.config.sync === undefined).toBe(true);
expect(row.stats.state === TRANSFORM_STATE.STOPPED).toBe(true); expect(row.stats.state === TRANSFORM_STATE.STOPPED).toBe(true);
expect(isCompletedBatchTransform(mockTransformListRow)).toBe(true); expect(isCompletedBatchTransform(row)).toBe(true);
// adapt the mock config to resemble a non-completed transform. // adapt the mock config to resemble a non-completed transform.
row.stats.checkpointing.last.checkpoint = 0; row.stats.checkpointing.last.checkpoint = 0;
expect(isCompletedBatchTransform(mockTransformListRow)).toBe(false); expect(isCompletedBatchTransform(row)).toBe(false);
}); });
}); });

View file

@ -31,6 +31,7 @@ describe('Transform: Transform List <ExpandedRow />', () => {
test('Minimal initialization', async () => { test('Minimal initialization', async () => {
const mlShared = await getMlSharedImports(); const mlShared = await getMlSharedImports();
// @ts-expect-error mock data is too loosely typed
const item: TransformListRow = transformListRow; const item: TransformListRow = transformListRow;
const { getByText, getByTestId } = render( const { getByText, getByTestId } = render(

View file

@ -25,6 +25,7 @@ const defaultProps = {
*/ */
describe('CheckupTab', () => { describe('CheckupTab', () => {
test('render with deprecations', () => { test('render with deprecations', () => {
// @ts-expect-error mock data is too loosely typed
expect(shallow(<CheckupTab {...defaultProps} />)).toMatchSnapshot(); expect(shallow(<CheckupTab {...defaultProps} />)).toMatchSnapshot();
}); });

View file

@ -34,6 +34,7 @@ describe('getUpgradeAssistantStatus', () => {
}); });
beforeEach(() => { beforeEach(() => {
// @ts-expect-error mock data is too loosely typed
deprecationsResponse = _.cloneDeep(fakeDeprecations); deprecationsResponse = _.cloneDeep(fakeDeprecations);
}); });

View file

@ -47,6 +47,7 @@ export function InfraOpsGraphQLClientFactoryProvider({ getService }: FtrProvider
return new ApolloClient({ return new ApolloClient({
cache: new InMemoryCache({ cache: new InMemoryCache({
fragmentMatcher: new IntrospectionFragmentMatcher({ fragmentMatcher: new IntrospectionFragmentMatcher({
// @ts-expect-error apollo-cache-inmemory types don't match actual introspection data
introspectionQueryResultData, introspectionQueryResultData,
}), }),
}), }),

View file

@ -46,6 +46,7 @@ export function SecuritySolutionGraphQLClientFactoryProvider({ getService }: Ftr
return new ApolloClient({ return new ApolloClient({
cache: new InMemoryCache({ cache: new InMemoryCache({
fragmentMatcher: new IntrospectionFragmentMatcher({ fragmentMatcher: new IntrospectionFragmentMatcher({
// @ts-expect-error apollo-cache-inmemory types don't match actual introspection data
introspectionQueryResultData, introspectionQueryResultData,
}), }),
}), }),

View file

@ -15,7 +15,6 @@
"plugins/licensing/**/*" "plugins/licensing/**/*"
], ],
"compilerOptions": { "compilerOptions": {
"outDir": ".",
"paths": { "paths": {
"kibana/public": ["src/core/public"], "kibana/public": ["src/core/public"],
"kibana/server": ["src/core/server"], "kibana/server": ["src/core/server"],

View file

@ -34,15 +34,6 @@ type Writable<T> = {
-readonly [K in keyof T]: T[K]; -readonly [K in keyof T]: T[K];
}; };
// allow JSON files to be imported directly without lint errors
// see: https://github.com/palantir/tslint/issues/1264#issuecomment-228433367
// and: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#arbitrary-expressions-are-forbidden-in-export-assignments-in-ambient-contexts
declare module '*.json' {
const json: any;
// eslint-disable-next-line import/no-default-export
export default json;
}
// Storybook references this module. It's @ts-ignored in the codebase but when // Storybook references this module. It's @ts-ignored in the codebase but when
// built into its dist it strips that out. Add it here to avoid a type checking // built into its dist it strips that out. Add it here to avoid a type checking
// error. // error.