Skip to content

Commit

Permalink
Merge branch 'renovate/typescript-4.x' of github.com:kristiandupont/s…
Browse files Browse the repository at this point in the history
…chemalint into renovate/typescript-4.x
  • Loading branch information
kristiandupont committed May 23, 2021
2 parents 0484b84 + 248c5a2 commit 7286390
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 123 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"eslint-plugin-prettier": "3.4.0",
"jest": "26.6.3",
"np": "7.5.0",
"prettier": "2.2.1",
"prettier": "2.3.0",
"testcontainers": "7.11.0",
"ts-jest": "26.5.6",
"typescript": "4.2.4"
Expand Down
29 changes: 13 additions & 16 deletions src/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,21 @@ function consoleReporter({ rule, identifier, message }) {
let anyIssues = false;
const suggestedMigrations = [];

const createReportFunction = (reporter, ignoreMatchers) => ({
rule,
identifier,
message,
suggestedMigration,
}) => {
if (ignoreMatchers.find((im) => im(rule, identifier))) {
// This one is ignored.
return;
}
const createReportFunction =
(reporter, ignoreMatchers) =>
({ rule, identifier, message, suggestedMigration }) => {
if (ignoreMatchers.find((im) => im(rule, identifier))) {
// This one is ignored.
return;
}

reporter({ rule, identifier, message });
reporter({ rule, identifier, message });

if (suggestedMigration) {
suggestedMigrations.push(suggestedMigration);
}
anyIssues = true;
};
if (suggestedMigration) {
suggestedMigrations.push(suggestedMigration);
}
anyIssues = true;
};

export async function processDatabase({
connection,
Expand Down
74 changes: 38 additions & 36 deletions src/rules/nameCasing.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,47 @@ export const nameCasing = {
name: 'name-casing',
docs: {
description: 'Enforce casing style of names',
url:
'https://github.com/kristiandupont/schemalint/tree/master/src/rules#name-casing',
url: 'https://github.com/kristiandupont/schemalint/tree/master/src/rules#name-casing',
},
process({ options, schemaObject, report }) {
const expectedCasing = (options.length && options[0]) || 'snake';
const validator = (entityType) => ({ name: entityName }) => {
const casing = detectCasing(entityName);
const matches = casing === null || casing === expectedCasing;
if (!matches) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${entityName}`,
message: `The ${entityType} ${entityName} seems to be ${casing}-cased rather than ${expectedCasing}-cased.`,
suggestedMigration: `ALTER ${entityType.toUpperCase()} "${entityName}" RENAME TO "${recase(
casing,
expectedCasing,
entityName
)}";`,
});
}
};
const columnValidator = (entityType) => ({ name: entityName }) => ({
name: columnName,
}) => {
const casing = detectCasing(columnName);
const matches = casing === null || casing === expectedCasing;
if (!matches) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${entityName}.${columnName}`,
message: `The column ${columnName} on the ${entityType} ${entityName} seems to be ${casing}-cased rather than ${expectedCasing}-cased.`,
suggestedMigration: `ALTER ${entityType.toUpperCase()} "${entityName}" RENAME COLUMN "${columnName}" TO "${recase(
casing,
expectedCasing,
columnName
)}";`,
});
}
};
const validator =
(entityType) =>
({ name: entityName }) => {
const casing = detectCasing(entityName);
const matches = casing === null || casing === expectedCasing;
if (!matches) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${entityName}`,
message: `The ${entityType} ${entityName} seems to be ${casing}-cased rather than ${expectedCasing}-cased.`,
suggestedMigration: `ALTER ${entityType.toUpperCase()} "${entityName}" RENAME TO "${recase(
casing,
expectedCasing,
entityName
)}";`,
});
}
};
const columnValidator =
(entityType) =>
({ name: entityName }) =>
({ name: columnName }) => {
const casing = detectCasing(columnName);
const matches = casing === null || casing === expectedCasing;
if (!matches) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${entityName}.${columnName}`,
message: `The column ${columnName} on the ${entityType} ${entityName} seems to be ${casing}-cased rather than ${expectedCasing}-cased.`,
suggestedMigration: `ALTER ${entityType.toUpperCase()} "${entityName}" RENAME COLUMN "${columnName}" TO "${recase(
casing,
expectedCasing,
columnName
)}";`,
});
}
};
schemaObject.tables.forEach((entity) => {
validator('table')(entity);
entity.columns.forEach(columnValidator('table')(entity));
Expand Down
29 changes: 15 additions & 14 deletions src/rules/nameInflection.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,24 @@ export const nameInflection = {
name: 'name-inflection',
docs: {
description: 'Enforce singluar or plural naming of tables and views',
url:
'https://github.com/kristiandupont/schemalint/tree/master/src/rules#name-inflection',
url: 'https://github.com/kristiandupont/schemalint/tree/master/src/rules#name-inflection',
},
process({ options, schemaObject, report }) {
const expectedPlurality = (options.length && options[0]) || 'singular';
const validator = (entityType) => ({ name: entityName }) => {
const plurality = detectInflection(entityName);
const matches =
plurality === expectedPlurality || plurality === 'unknown';
if (!matches) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${entityName}`,
message: `Expected ${expectedPlurality} names, but '${entityName}' seems to be ${plurality}`,
});
}
};
const validator =
(entityType) =>
({ name: entityName }) => {
const plurality = detectInflection(entityName);
const matches =
plurality === expectedPlurality || plurality === 'unknown';
if (!matches) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${entityName}`,
message: `Expected ${expectedPlurality} names, but '${entityName}' seems to be ${plurality}`,
});
}
};
schemaObject.tables.forEach(validator('table'));
schemaObject.views.forEach(validator('view'));
},
Expand Down
3 changes: 1 addition & 2 deletions src/rules/requirePrimaryKey.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ export const requirePrimaryKey = {
name: 'require-primary-key',
docs: {
description: 'Enforce primary key definition',
url:
'https://github.com/kristiandupont/schemalint/tree/master/src/rules#require-primary-key',
url: 'https://github.com/kristiandupont/schemalint/tree/master/src/rules#require-primary-key',
},
process({ options, schemaObject, report }) {
const ignorePatternsMatch =
Expand Down
104 changes: 54 additions & 50 deletions src/rules/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ export const preferJsonbToJson = {
url: '...',
},
process({ schemaObject, report }) {
const validator = ({ name: tableName }) => ({ name: columnName, type }) => {
if (type === 'json') {
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: 'Prefer JSONB to JSON types',
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE JSONB;`,
});
}
};
const validator =
({ name: tableName }) =>
({ name: columnName, type }) => {
if (type === 'json') {
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: 'Prefer JSONB to JSON types',
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE JSONB;`,
});
}
};
schemaObject.tables.forEach((table) =>
table.columns.forEach(validator(table))
);
Expand All @@ -28,16 +30,18 @@ export const preferTextToVarchar = {
url: '...',
},
process({ schemaObject, report }) {
const validator = ({ name: tableName }) => ({ name: columnName, type }) => {
if (type.startsWith('varchar')) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: `Prefer text to ${type} types`,
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE TEXT;`,
});
}
};
const validator =
({ name: tableName }) =>
({ name: columnName, type }) => {
if (type.startsWith('varchar')) {
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: `Prefer text to ${type} types`,
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE TEXT;`,
});
}
};
schemaObject.tables.forEach((table) =>
table.columns.forEach(validator(table))
);
Expand All @@ -53,16 +57,18 @@ export const preferTimestamptz = {
url: 'https://www.postgresqltutorial.com/postgresql-timestamp/',
},
process({ schemaObject, report }) {
const validator = ({ name: tableName }) => ({ name: columnName, type }) => {
if (type === 'timestamp') {
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: 'Prefer TIMESTAMPTZ to type TIMESTAMP',
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE TIMESTAMPTZ;`,
});
}
};
const validator =
({ name: tableName }) =>
({ name: columnName, type }) => {
if (type === 'timestamp') {
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: 'Prefer TIMESTAMPTZ to type TIMESTAMP',
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER COLUMN "${columnName}" TYPE TIMESTAMPTZ;`,
});
}
};
schemaObject.tables.forEach((table) =>
table.columns.forEach(validator(table))
);
Expand All @@ -77,30 +83,28 @@ export const preferIdentity = {
url: 'https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/',
},
process({ schemaObject, report }) {
const validator = ({ name: tableName }) => ({
name: columnName,
rawInfo,
defaultValue,
}) => {
if (
rawInfo.is_identity === 'NO' &&
defaultValue !== null &&
defaultValue.indexOf('nextval') >= 0
) {
let sequenceName = defaultValue.match("'(.*)'")[1];
sequenceName = sequenceName.replace(/"/g, '');
const validator =
({ name: tableName }) =>
({ name: columnName, rawInfo, defaultValue }) => {
if (
rawInfo.is_identity === 'NO' &&
defaultValue !== null &&
defaultValue.indexOf('nextval') >= 0
) {
let sequenceName = defaultValue.match("'(.*)'")[1];
sequenceName = sequenceName.replace(/"/g, '');

report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: 'Prefer IDENTITY to type SERIAL',
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER "${columnName}" DROP DEFAULT;
report({
rule: this.name,
identifier: `${schemaObject.name}.${tableName}.${columnName}`,
message: 'Prefer IDENTITY to type SERIAL',
suggestedMigration: `ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER "${columnName}" DROP DEFAULT;
DROP SEQUENCE "schema"."${sequenceName}";
ALTER TABLE "${schemaObject.name}"."${tableName}" ALTER "${columnName}" ADD GENERATED BY DEFAULT AS IDENTITY;
SELECT setval('"${sequenceName}"', max("${columnName}")) FROM "schema"."${tableName}";`,
});
}
};
});
}
};
schemaObject.tables.forEach((table) =>
table.columns.forEach(validator(table))
);
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4898,10 +4898,10 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"

prettier@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
prettier@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18"
integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==

pretty-format@^26.0.0, pretty-format@^26.6.2:
version "26.6.2"
Expand Down

0 comments on commit 7286390

Please sign in to comment.