Skip to content

Commit

Permalink
fix(types): resolve type errors after typescript upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
uladkasach committed Feb 12, 2023
1 parent 50e45fb commit b81f850
Show file tree
Hide file tree
Showing 23 changed files with 47 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const grabTypeDefinitionsForReferencedDatabaseProvidedFunctions = ({
.flat();
const referencedFunctionNames = references
.filter((ref) => !!ref.functionReferencePath)
.map((ref) => ref.functionReferencePath!.split('.')[0])
.map((ref) => ref.functionReferencePath!.split('.')[0]!)
.map((str) => str.toUpperCase()); // NOTE: we cast all fn names to UPPER_CASE
const uniqueReferencedFunctionNames = [...new Set(referencedFunctionNames)];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import uuid from 'uuid';

// tslint:disable-line no-unused
// import { dbConnection } from '../../../utils/database';
// import { sqlQueryFindSuggestionById } from '../generated/queries';
// import { fromDatabaseObject } from './fromDatabaseObject';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('breakSqlIntoNestedSqlArraysAtParentheses', () => {
const sql = "SELECT CONCAT('hel', 'lo');";
const nestedSqlArray = breakSqlIntoNestedSqlArraysAtParentheses({ sql });
expect(nestedSqlArray).toHaveLength(3);
expect(nestedSqlArray[1][0][0]).toEqual('(');
expect(nestedSqlArray[1][0].slice(-1)[0]).toEqual(')');
expect(nestedSqlArray[1]![0]![0]).toEqual('(');
expect(nestedSqlArray[1]![0]!.slice(-1)[0]).toEqual(')');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ FROM ice_cream s

// should have got the reference
expect(references.length).toEqual(1);
expect(references[0].sql).toEqual(sqlParts[1]);
expect(references[0]!.sql).toEqual(sqlParts[1]);

// it should have replaced the sql in the referenced sql parts for the subquery
expect(referencedSqlParts[1]).toMatch(/__SSQ:[\w-]+__/);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import uuid from 'uuid';

import { uuid } from '../../../../../deps';
import { SqlSubqueryReference } from '../../../../../domain/objects/SqlSubqueryReference';
import { getTokenForSqlSubqueryReference } from './getTokenForSubqueryReference';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ SELECT upsert_plane(
);
`.trim();
const tokens = extractInputVariableTokensFromQuerySql({ sql });
expect(tokens).toEqual([':model', ':ownerId', ':pin']);
expect(tokens).toEqual([':domain', ':ownerId', ':pin']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ export const extractInputVariablesFromQuerySql = ({ sql }: { sql: string }) => {
const tokenToSuffixedTokensMap: { [index: string]: string[] } = {};
const suffixedInputVariableTokens = inputVariableTokens.map((token) => {
if (!tokenToSuffixedTokensMap[token]) tokenToSuffixedTokensMap[token] = [];
const tokenOccurrenceIndex = tokenToSuffixedTokensMap[token].length;
const tokenOccurrenceIndex = tokenToSuffixedTokensMap[token]!.length;
const suffixedToken = `${token}#${tokenOccurrenceIndex + 1}`; // note: we use `#` since it does not need to be escaped in regexp and its makes sense for an index due to it meaning "number"
tokenToSuffixedTokensMap[token].push(suffixedToken);
tokenToSuffixedTokensMap[token]!.push(suffixedToken);
return suffixedToken;
});

// now go through the sql and replace each occurrence of a token with its suffixed,ordered identity (e.g., `WHERE (:until is null OR message.created_at <= :until)` => `WHERE (:until#1 is null OR message.created_at <= :until#2)`)
const suffixedTokenSql = Object.keys(tokenToSuffixedTokensMap).reduce(
(sqlNow, thisToken) => {
const suffixedTokens = tokenToSuffixedTokensMap[thisToken];
const suffixedTokens = tokenToSuffixedTokensMap[thisToken]!;
let sqlToUpdate = sqlNow;
suffixedTokens.forEach((suffixedToken) => {
sqlToUpdate = sqlToUpdate.replace(
Expand Down Expand Up @@ -93,7 +93,7 @@ export const extractInputVariablesFromQuerySql = ({ sql }: { sql: string }) => {
(definitionWithSuffixedToken) => {
const tokenForSuffixedToken = suffixedTokenToTokenMap[
`:${definitionWithSuffixedToken.name}`
].replace(':', '');
]!.replace(':', '');
return new TypeDefinitionOfQueryInputVariable({
...definitionWithSuffixedToken,
name: tokenForSuffixedToken,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DataType } from '../../../../domain';
import { TypeDefinitionOfQueryInputVariable } from '../../../../domain/objects/TypeDefinitionOfQueryInputVariable';
import { TypeDefinitionReference } from '../../../../domain/objects/TypeDefinitionReference';
import { DataType } from '../../../../model';
import { extractTypeDefinitionFromInputVariableSql } from './extractTypeDefinitionFromInputVariableSql';

describe('extractTypeDefinitionFromInputVariableSql', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DataType } from '../../../../domain';
import { TypeDefinitionOfQueryInputVariable } from '../../../../domain/objects/TypeDefinitionOfQueryInputVariable';
import { TypeDefinitionReference } from '../../../../domain/objects/TypeDefinitionReference';
import { DataType } from '../../../../model';
import { throwErrorIfTableReferencePathImpliesTable } from '../common/throwErrorIfTableReferencePathImpliesTable';

export const extractTypeDefinitionFromInputVariableSql = ({
Expand Down Expand Up @@ -59,16 +59,17 @@ export const extractTypeDefinitionFromInputVariableSql = ({
// check if this token is used in a function. If so, its equivalent to whatever is at that index of the function params
const reg = `\\s+(\\w+\\((?:\\s*[:\\w#]+,)*(?:\\s*${tokenWithOptionalTypecastingRegexString},?)(?:\\s*[:\\w#]+,?)*\\s?\\))`; // note: this reg matches the whole function def (e.g., `upsert_image(:url,:caption,:credit)`)
const [
___, // tslint:disable-line no-unused
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
___,
tokenInsideFunctionMatch, // check if "functionName(arg1?, :token, arg2?)"
] = new RegExp(reg).exec(sql) ?? [];
if (tokenInsideFunctionMatch) {
// grab the function name
const functionName = tokenInsideFunctionMatch.split('(')[0].trim();
const functionName = tokenInsideFunctionMatch.split('(')[0]!.trim();

// figure out where in the array the token is
const sqlAfterOpen = tokenInsideFunctionMatch.split('(')[1];
const sqlBetweenOpenAndClose = sqlAfterOpen.split(')')[0];
const sqlAfterOpen = tokenInsideFunctionMatch.split('(')[1]!;
const sqlBetweenOpenAndClose = sqlAfterOpen.split(')')[0]!;
const parametersArray = sqlBetweenOpenAndClose
.split(',')
.map((str) => str.trim());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ describe('extractSelectExpressionsFromQuerySql', () => {
filePath: `${__dirname}/../../../__test_assets__/queries/select_suggestion.sql`,
});
const defs = extractSelectExpressionsFromQuerySql({ sql });
expect(defs.slice(-1)[0].alias).toEqual('updated_at');
expect(defs.slice(-1)[0].typeReference.tableReferencePath).toEqual(
expect(defs.slice(-1)[0]!.alias).toEqual('updated_at');
expect(defs.slice(-1)[0]!.typeReference.tableReferencePath).toEqual(
'v.created_at',
);
expect(defs).toMatchSnapshot();
Expand All @@ -25,8 +25,8 @@ describe('extractSelectExpressionsFromQuerySql', () => {
filePath: `${__dirname}/../../../__test_assets__/queries/upsert_suggestion.sql`,
});
const defs = extractSelectExpressionsFromQuerySql({ sql });
expect(defs[0].alias).toEqual('id');
expect(defs[0].typeReference.functionReferencePath).toEqual(
expect(defs[0]!.alias).toEqual('id');
expect(defs[0]!.typeReference.functionReferencePath).toEqual(
'upsert_suggestion.output',
);
expect(defs).toMatchSnapshot();
Expand All @@ -36,8 +36,8 @@ describe('extractSelectExpressionsFromQuerySql', () => {
filePath: `${__dirname}/../../../__test_assets__/queries/find_users_by_last_name.sql`,
});
const defs = extractSelectExpressionsFromQuerySql({ sql });
expect(defs[1].alias).toEqual('full_name');
expect(defs[1].typeReference.functionReferencePath).toEqual(
expect(defs[1]!.alias).toEqual('full_name');
expect(defs[1]!.typeReference.functionReferencePath).toEqual(
'concat.output',
);
expect(defs).toMatchSnapshot();
Expand All @@ -47,8 +47,8 @@ describe('extractSelectExpressionsFromQuerySql', () => {
filePath: `${__dirname}/../__test_assets__/find_with_subselect_in_select_expressions.sql`,
});
const defs = extractSelectExpressionsFromQuerySql({ sql });
expect(defs[3].alias).toEqual('ingredient_ids');
expect(defs[3].typeReference.functionReferencePath).toEqual(
expect(defs[3]!.alias).toEqual('ingredient_ids');
expect(defs[3]!.typeReference.functionReferencePath).toEqual(
'group_concat.output',
);
expect(defs).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const extractSelectExpressionsFromQuerySql = ({
throw new Error('no "select" keyword found; unexpected'); // fail fast
if (partsSplitOnSelect.length > 2)
throw new Error('more than one "select" keyword found; unexpected'); // should have been flattened out
return partsSplitOnSelect[1];
return partsSplitOnSelect[1]!;
})();
const everythingBetweenSelectAndFrom = (() => {
const partsSplitOnFromAfterSelect = everythingAfterSelect.split(
Expand All @@ -38,7 +38,7 @@ export const extractSelectExpressionsFromQuerySql = ({
if (partsSplitOnFromAfterSelect.length > 2) {
throw new Error('more than one "from" keyword found; unexpected'); // should have been flattened out
}
return partsSplitOnFromAfterSelect[0];
return partsSplitOnFromAfterSelect[0]!;
})();

// 3. cast commas inside of parens into pipes, so that we treat them as unique tokens when splitting "property lines" by comma
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TypeDefinitionOfQuerySelectExpression } from '../../../../domain';
import { SqlSubqueryReference } from '../../../../domain/objects/SqlSubqueryReference';
import { TypeDefinitionReference } from '../../../../model/valueObjects/TypeDefinitionReference';
import { TypeDefinitionReference } from '../../../../domain/objects/TypeDefinitionReference';
import { extractTypeDefinitionFromSelectExpressionSql } from './extractTypeDefinitionFromSelectExpressionSql';

describe('extractTypeDefinitionFromSelectExpressionSql', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ select expressions that reference a function must have an alias defined, per bes
if (specifiedAlias) return specifiedAlias;
if (inASubquery) return '__subquery_placeholder_name__'; // we wont use this alias anywhere, since we're in a subquery and subquery just returns one value; therefore, we can give it a fake name as a placeholder
if (typeReference.tableReferencePath)
return typeReference.tableReferencePath.split('.').slice(-1)[0];
return typeReference.tableReferencePath.split('.').slice(-1)[0]!;
throw new Error('could not define alias for sql expression; unexpected');
})();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ export const extractTypeDefinitionReferenceFromSubqueryReferenceToken = ({
}

// 4. the reference type of this expression is the single reference type of that subquery
return selectExpressions[0].typeReference;
return selectExpressions[0]!.typeReference;
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ export const extractTableReferenceSqlSetFromQuerySql = ({
throw new Error('no "from" keyword found'); // fail fast; allow this being caught above
if (partsSplitOnFrom.length > 2)
throw new Error('more than one "from" keyword found; not yet supported'); // TODO: https://github.com/uladkasach/sql-code-generator/issues/2
return `FROM ${partsSplitOnFrom[1]}`; // inclusive, since we include "from"
return `FROM ${partsSplitOnFrom[1]!}`; // inclusive, since we include "from"
})();
const everythingBetweenFromAndWhere = (() => {
const partsSplitOnFromAfterSelect =
everythingAfterFromInclusive.split(/(?:WHERE|where)/g);
if (partsSplitOnFromAfterSelect.length > 2) {
throw new Error('more than one "where" keyword found; not yet supported'); // TODO: https://github.com/uladkasach/sql-code-generator/issues/2
}
return partsSplitOnFromAfterSelect[0];
return partsSplitOnFromAfterSelect[0]!;
})();

// 3. split token on each table reference type "FROM", "JOIN", "INNER JOIN", and "LEFT JOIN"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,28 @@ export const extractTypeDefinitionFromTableReference = ({
sql: string;
}) => {
// see if it matches a persisted table reference
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
const [_, tableName] = new RegExp(TABLE_NAME_MATCHER_REGEX).exec(sql) ?? []; // tslint:disable-line no-unused

// see if it matches a function output reference
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
const [__, functionName] = tableName
? [, null]
: new RegExp(FUNCTION_NAME_MATCHER_REGEX).exec(sql) ?? []; // tslint:disable-line no-unused

// make sure it matches one of the above
if (!tableName && !functionName)
if (!tableName || !functionName)
throw new Error(
'could not identify the referenced table from table reference sql; unexpected',
); // fail fast

// grab the alias, if any
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
const [___, specifiedAlias] =
new RegExp(SPECIFIED_ALIAS_MATCHER_REGEX).exec(sql) ?? []; // tslint:disable-line no-unused

// define the name, considering whether alias was given
const alias = specifiedAlias ?? tableName ?? functionName;
const alias: string = specifiedAlias ?? tableName ?? functionName;

// return the full definition
return new TypeDefinitionOfQueryTableReference({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const extractResourceTypeAndNameFromDDL = ({ ddl }: { ddl: string }) => {
const type = regexTypeMatchToTypeEnum[regexTypeMatch];

// extract the name
const name = extractionMatches[2];
const name = extractionMatches[2]!;

// return type and name
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const extractInputsFromFunctionSql = ({ sql }: { sql: string }) => {
const strippedSql: string = strip(sql);

// 1. grab the insides of the inputs definition
const sqlBeforeReturns = strippedSql.split(/(?:returns|RETURNS)/)[0];
const sqlBeforeReturns = strippedSql.split(/(?:returns|RETURNS)/)[0]!;
const innerSqlAndAfter = sqlBeforeReturns.split('(').slice(1).join('('); // drop the part before the first '('
const innerSql = innerSqlAndAfter.split(')').slice(0, -1).join(')'); // drop the part after the last ')'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const extractTypeDefinitionFromFunctionInputSql = ({
sql: string;
}) => {
// 1. extract the name; its typically the first string
const name = sql.split(' ')[0].replace(/[^a-zA-Z_]+/gi, '');
const name = sql.split(' ')[0]!.replace(/[^a-zA-Z_]+/gi, '');

// 2. extract the root type;
const primaryType = extractDataTypeFromColumnOrArgumentDefinitionSql({ sql });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const extractTypeDefinitionFromColumnSql = ({
sql: string;
}) => {
// 1. extract the name; its typically the first string
const name = sql.split(' ')[0].replace(/[^a-zA-Z_]+/gi, '');
const name = sql.split(' ')[0]!.replace(/[^a-zA-Z_]+/gi, '');

// 2. extract the root type;
const primaryType = extractDataTypeFromColumnOrArgumentDefinitionSql({ sql });
Expand All @@ -17,7 +17,7 @@ export const extractTypeDefinitionFromColumnSql = ({

// 4. define the full type definition; note: array => union
const type = [primaryType, isNullable ? DataType.NULL : null].filter(
(type) => !!type,
(thisType) => !!thisType,
) as DataType[];

// 5. return the definition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const extractTypeDefinitionFromTableSql = ({
const strippedSql: string = strip(sql);

// 1. drop everything after the first `;` - the table ddl does not have `;` inside. (this will make sure we exclude lines like "create index ..." and etc)
const sqlBeforeFirstSemiColon = strippedSql.split(';')[0];
const sqlBeforeFirstSemiColon = strippedSql.split(';')[0]!;
// strippedSql.replace(/CREATE INDEX [\w\d_]+ ON [\w\d_]+ USING [\w\d_]+ \([\w\d_,]+\);/gi, '');

// 2. grab the insides of the "create" (i.e., 'CREATE TABLE ... (__INSIDES__) ...' => '__INSIDES__')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const defineTypescriptTypeFromFunctionReference = ({

// grab the function name from the reference definition
const [functionName, inputOrOutput, inputPropertyIndex] =
reference.functionReferencePath.split('.');
reference.functionReferencePath.split('.') as [string, string, string];

// grab the typescript name for this function
const functionTypescriptName = castResourceNameToTypescriptTypeName({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TypeDefinition } from '../../../domain';
import { TypeDefinitionOfQuery } from '../../../domain/objects/TypeDefinitionOfQuery';
import { TypeDefinitionOfQueryInputVariable } from '../../../model/valueObjects/TypeDefinitionOfQueryInputVariable';
import { TypeDefinitionOfQueryInputVariable } from '../../../domain/objects/TypeDefinitionOfQueryInputVariable';
import { castQueryNameToTypescriptTypeName } from '../common/castQueryNameToTypescriptTypeName';
import { defineTypescriptTypeFromDataTypeArrayOrReference } from '../common/defineTypescriptTypeFromDataTypeArrayOrReference';
import { defineTypescriptTypeFromReference } from '../common/defineTypescriptTypeFromReference/defineTypescriptTypeFromReference';
Expand All @@ -21,14 +21,14 @@ export const defineTypescriptTypesForQuery = ({
const inputVariableNameToTypeDefinitionsMap =
definition.inputVariables.reduce((summary, thisDefinition) => {
if (!summary[thisDefinition.name]) summary[thisDefinition.name] = [];
summary[thisDefinition.name].push(thisDefinition);
summary[thisDefinition.name]!.push(thisDefinition);
return summary;
}, {} as Record<string, TypeDefinitionOfQueryInputVariable[]>);
const typescriptInputInterfacePropertyDefinitions = Object.keys(
inputVariableNameToTypeDefinitionsMap,
).map((inputVariableName) => {
// grab all the types for this input variable (there can be more than one, because an input variable can be used more than once in the same query. e.g., `WHERE x is null OR x = y`)
const types = inputVariableNameToTypeDefinitionsMap[inputVariableName].map(
const types = inputVariableNameToTypeDefinitionsMap[inputVariableName]!.map(
(def) => def.type,
);

Expand Down

0 comments on commit b81f850

Please sign in to comment.