### Start Example Database Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md Run this command to start the example PostgreSQL database using Docker. ```bash npm run start-example-db ``` -------------------------------- ### Install Dependencies Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md Install the necessary dependencies for the Schemalint example. ```bash npm install ``` -------------------------------- ### Schemalint Configuration File Example Source: https://github.com/kristiandupont/schemalint/blob/main/README.md An example of a `.schemalintrc.js` configuration file, demonstrating connection settings, schemas to lint, enabled rules, and ignore patterns. ```javascript /** @type {import("schemalint").Config } */ module.exports = { // Connection configuration. See: https://node-postgres.com/apis/client connection: { host: "localhost", user: "postgres", password: "postgres", database: "acme", charset: "utf8", }, // Schemas to be linted. schemas: [{ name: "public" }], // Rules to be checked. The key is the rule name and the value is an array // whose first value is the severity ("error" to enable the rule, "off" to // disable it) and the rest are rule-specific parameters. rules: { "name-casing": ["error", "snake"], "name-inflection": ["error", "singular"], "prefer-jsonb-to-json": ["error"], "prefer-text-to-varchar": ["error"], }, // (Optional) Use the `ignores` array to exclude specific targets and // rules. The targets are identified by the `identifier` (exact) or the // `identifierPattern` (regex). For the rules, use the `rule` (exact) or // the `rulePattern` (regex). ignores: [ { identifier: "public.sessions", rule: "name-inflection" }, { identifierPattern: "public\.knex_migrations.*", rulePattern: ".*" }, ], // (Optional) Use the `plugins` array to load custom rules. The paths are // `require`d as Node.js modules from the current working directory. plugins: ["./custom-rules"], }; ``` -------------------------------- ### Install and Run Schemalint CLI Source: https://context7.com/kristiandupont/schemalint/llms.txt Install schemalint using npm and run it from the command line. You can use the default configuration file or specify a custom one. Use --help for options and --version for the current version. ```bash npm install -D schemalint ``` ```bash npx schemalint ``` ```bash npx schemalint --config ./path/to/config.js ``` ```bash npx schemalint --help ``` ```bash npx schemalint --version ``` -------------------------------- ### Schemalint Output Example Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md This is an example of the output you might see after running Schemalint, indicating schema violations and suggested fixes. ```text schema-lint Connecting to dvdrental on localhost public.address.address: error prefer-text-to-varchar : Prefer text to varchar types public.address.address2: error prefer-text-to-varchar : Prefer text to varchar types public.address.district: error prefer-text-to-varchar : Prefer text to varchar types public.address.postal_code: error prefer-text-to-varchar : Prefer text to varchar types public.address.phone: error prefer-text-to-varchar : Prefer text to varchar types public.category.name: error prefer-text-to-varchar : Prefer text to varchar types public.country.country: error prefer-text-to-varchar : Prefer text to varchar types public.customer.first_name: error prefer-text-to-varchar : Prefer text to varchar types public.customer.last_name: error prefer-text-to-varchar : Prefer text to varchar types public.customer.email: error prefer-text-to-varchar : Prefer text to varchar types public.film.title: error prefer-text-to-varchar : Prefer text to varchar types public.staff.first_name: error prefer-text-to-varchar : Prefer text to varchar types public.staff.last_name: error prefer-text-to-varchar : Prefer text to varchar types public.staff.email: error prefer-text-to-varchar : Prefer text to varchar types public.staff.username: error prefer-text-to-varchar : Prefer text to varchar types public.staff.password: error prefer-text-to-varchar : Prefer text to varchar types Suggested fix ALTER TABLE "address" ALTER COLUMN "address" TYPE TEXT; ALTER TABLE "address" ALTER COLUMN "address2" TYPE TEXT; ALTER TABLE "address" ALTER COLUMN "district" TYPE TEXT; ALTER TABLE "address" ALTER COLUMN "postal_code" TYPE TEXT; ALTER TABLE "address" ALTER COLUMN "phone" TYPE TEXT; ALTER TABLE "category" ALTER COLUMN "name" TYPE TEXT; ALTER TABLE "country" ALTER COLUMN "country" TYPE TEXT; ALTER TABLE "customer" ALTER COLUMN "first_name" TYPE TEXT; ALTER TABLE "customer" ALTER COLUMN "last_name" TYPE TEXT; ALTER TABLE "customer" ALTER COLUMN "email" TYPE TEXT; ALTER TABLE "film" ALTER COLUMN "title" TYPE TEXT; ALTER TABLE "staff" ALTER COLUMN "first_name" TYPE TEXT; ALTER TABLE "staff" ALTER COLUMN "last_name" TYPE TEXT; ALTER TABLE "staff" ALTER COLUMN "email" TYPE TEXT; ALTER TABLE "staff" ALTER COLUMN "username" TYPE TEXT; ALTER TABLE "staff" ALTER COLUMN "password" TYPE TEXT; error Command failed with exit code 1. ``` -------------------------------- ### Install Schemalint with npm Source: https://github.com/kristiandupont/schemalint/blob/main/README.md Installs Schemalint as a development dependency using npm. ```bash $ npm i -D schemalint ``` -------------------------------- ### Schemalint Configuration File Example Source: https://context7.com/kristiandupont/schemalint/llms.txt A JavaScript configuration file for Schemalint. It defines PostgreSQL connection details, schemas to lint, global rules, ignores, and custom plugins. ```javascript /** @type {import("schemalint").Config } */ module.exports = { // PostgreSQL connection configuration (node-postgres ClientConfig) connection: { host: "localhost", port: 5432, user: "postgres", password: "postgres", database: "myapp", charset: "utf8", }, // Schemas to be linted schemas: [ { name: "public" }, { name: "api", // Schema-specific rules (merged with global rules) rules: { "row-level-security": ["error", { enforced: true }], }, }, ], // Global rules configuration rules: { "name-casing": ["error", "snake"], "name-inflection": ["error", "singular"], "prefer-jsonb-to-json": ["error"], "prefer-text-to-varchar": ["error"], "prefer-timestamptz-to-timestamp": ["error"], "prefer-identity-to-serial": ["error"], "require-primary-key": ["error"], "index-referencing-column": ["error"], }, // Optional: Ignore specific rules for specific identifiers ignores: [ { identifier: "public.sessions", rule: "name-inflection" }, { identifierPattern: "public\.knex_migrations.*", rulePattern: ".*" }, ], // Optional: Load custom rule plugins plugins: ["./custom-rules"], }; ``` -------------------------------- ### Example Schemalint Error and Suggestion Source: https://github.com/kristiandupont/schemalint/blob/main/README.md Illustrates a typical error message from Schemalint, highlighting a rule violation and providing a suggested SQL fix. ```text public.actor.first_name: error prefer-text-to-varchar : Prefer text to varchar types Suggested fix ALTER TABLE "public"."actor" ALTER COLUMN "first_name" TYPE TEXT; ``` -------------------------------- ### Configure row-level-security Rule (enabled) Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure this rule to ensure tables have row-level security enabled. This example shows the configuration for enabling RLS. ```javascript // Configuration rules: { 'row-level-security': ['error', { enforced: true }], } // Example output for violation: // public.sensitive_data: error row-level-security : Row-level security is disabled // // Suggested fix: // ALTER TABLE "public"."sensitive_data" ENABLE ROW LEVEL SECURITY; // For enforced violation: // public.sensitive_data: error row-level-security : Row-level security is not enforced // // Suggested fix: // ALTER TABLE "public"."sensitive_data" FORCE ROW LEVEL SECURITY; ``` -------------------------------- ### Schemalint 'name-casing' Rule Configuration Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure the 'name-casing' rule to enforce consistent naming conventions (snake, dash, camel, pascal) for database objects. Example output shows a violation and suggested SQL fix. ```javascript // Configuration rules: { 'name-casing': ['error', 'snake'], // Default: snake_case } // Example output for violation: // public.MemberProfile: error name-casing : The table MemberProfile seems to be pascal-cased rather than snake-cased. // // Suggested fix: // ALTER TABLE "MemberProfile" RENAME TO "member_profile"; ``` -------------------------------- ### Schemalint 'prefer-text-to-varchar' Rule Configuration Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure the 'prefer-text-to-varchar' rule to enforce the use of TEXT data types over VARCHAR in PostgreSQL for better performance. Example output shows a violation and suggested SQL fix. ```javascript // Configuration rules: { 'prefer-text-to-varchar': ['error'], } // Example output for violation: // public.actor.first_name: error prefer-text-to-varchar : Prefer text to varchar types // // Suggested fix: // ALTER TABLE "public"."actor" ALTER COLUMN "first_name" TYPE TEXT; ``` -------------------------------- ### Custom Rule: Identifier Naming Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md Defines a custom Schemalint rule named `identifier-naming`. This rule is intended as a starting point for creating your own custom validation logic. ```javascript /** @type {import("../../src/Rule").Rule} */ export const rule = { name: "identifier-naming", description: "Prefer snake_case for identifiers", // @ts-ignore validate: (schema) => { const errors = []; for (const table of schema.tables) { for (const column of table.columns) { if (/[A-Z]/u.test(column.name)) { errors.push({ message: `Prefer snake_case for identifiers`, identifier: column.identifier, }); } } } return errors; }, }; ``` -------------------------------- ### Schemalint 'prefer-jsonb-to-json' Rule Configuration Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure the 'prefer-jsonb-to-json' rule to enforce the use of JSONB data types over JSON in PostgreSQL for improved performance and indexing. Example output shows a violation and suggested SQL fix. ```javascript // Configuration rules: { 'prefer-jsonb-to-json': ['error'], } // Example output for violation: // public.settings.preferences: error prefer-jsonb-to-json : Prefer JSONB to JSON types // // Suggested fix: // ALTER TABLE "public"."settings" ALTER COLUMN "preferences" TYPE JSONB; ``` -------------------------------- ### Custom Rule: Last Updated Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md Defines a custom Schemalint rule named `last-updated`. This rule is intended as a starting point for creating your own custom validation logic. ```javascript /** @type {import("../../src/Rule").Rule} */ export const rule = { name: "last-updated", description: "Prefer columns to have a last_updated column", // @ts-ignore validate: (schema) => { const errors = []; for (const table of schema.tables) { if (!table.columns.some((c) => c.name === "last_updated")) { errors.push({ message: `Prefer columns to have a last_updated column`, identifier: table.identifier, }); } } return errors; }, }; ``` -------------------------------- ### Schemalint 'name-inflection' Rule Configuration Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure the 'name-inflection' rule to enforce singular or plural naming for tables and views. The default option is 'singular'. Example output shows a violation. ```javascript // Configuration rules: { 'name-inflection': ['error', 'singular'], } // Example output for violation: // public.users: error name-inflection : Expected singular names, but 'users' seems to be plural ``` -------------------------------- ### Run Schemalint Source: https://github.com/kristiandupont/schemalint/blob/main/README.md Executes Schemalint from the command line. Requires a `.schemalintrc.js` configuration file in the current directory. ```bash $ npx schemalint ``` -------------------------------- ### Run Schemalint Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md Execute Schemalint using the configuration file in the current folder. This command can also be run as `npx schemalint`. ```bash npm run lint:schema # or just `npx schemalint` ``` -------------------------------- ### Configure Schemalint with Custom Rules and Ignores Source: https://context7.com/kristiandupont/schemalint/llms.txt This JavaScript configuration file demonstrates how to load custom rules via plugins and define ignore patterns for specific rules and database objects. ```javascript // .schemalintrc.js module.exports = { plugins: ['./custom-rules'], rules: { 'identifier-naming': ['error'], }, // ... }; // Configuration module.exports = { // ... connection and schemas ... rules: { 'name-casing': ['error', 'snake'], 'name-inflection': ['error', 'singular'], 'prefer-text-to-varchar': ['error'], }, ignores: [ // Exact match: ignore name-inflection for public.sessions table { identifier: 'public.sessions', rule: 'name-inflection' }, // Regex pattern: ignore all rules for actor table and its columns { identifierPattern: '^public\.actor.*', rulePattern: '.*' }, // Ignore prefer-text-to-varchar for specific column { identifier: 'public.city.city', rule: 'prefer-text-to-varchar' }, // Ignore all rules for migration tables { identifierPattern: 'public\.knex_migrations.*', rulePattern: '.*' }, ], }; ``` -------------------------------- ### Configure reference-actions Rule Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure this rule to enforce specific ON UPDATE and ON DELETE actions for foreign key constraints. ```javascript // Configuration rules: { 'reference-actions': ['error', { onUpdate: 'NO ACTION', onDelete: 'CASCADE', }], } // Example output for violation: // public.orders.orders_customer_id_fkey: error reference-actions : Reference action ON DELETE expected to be "CASCADE" but got "NO ACTION" // // Suggested fix: // ALTER TABLE "public"."orders" DROP CONSTRAINT "orders_customer_id_fkey", ADD CONSTRAINT "orders_customer_id_fkey" FOREIGN KEY ("customer_id") REFERENCES "customers"("id") ON UPDATE NO ACTION ON DELETE CASCADE; ``` -------------------------------- ### Configure require-primary-key Rule with ignorePattern Source: https://context7.com/kristiandupont/schemalint/llms.txt Configure this rule to ensure all tables have a primary key, with an option to ignore specific tables using a pattern. ```javascript // Configuration rules: { 'require-primary-key': ['error', { ignorePattern: 'public\.knex_migrations.*' }], } // Example output for violation: // public.audit_logs: error require-primary-key : The table public.audit_logs does not have a primary key defined // // Suggested fix: // ALTER TABLE "public.audit_logs" ADD PRIMARY KEY (); ``` -------------------------------- ### Export Custom Rules via Index File Source: https://context7.com/kristiandupont/schemalint/llms.txt This JavaScript file serves as an entry point for custom rules, exporting the 'identifierNaming' rule for use by Schemalint plugins. ```javascript // custom-rules/index.js const identifierNaming = require('./identifierNaming'); module.exports = { identifierNaming }; ``` -------------------------------- ### Configure prefer-jsonb-to-json rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Recommends using 'jsonb' over 'json' in PostgreSQL for better performance and indexing capabilities. ```javascript rules: { 'prefer-jsonb-to-json': ['error'], }, ``` -------------------------------- ### Configure require-primary-key rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Ensures that tables have a primary key defined. Allows ignoring specific tables using 'ignorePattern'. ```javascript rules: { 'require-primary-key': ['error', { ignorePattern: 'information_schema.*' }], }, ``` -------------------------------- ### Configure prefer-identity-to-serial rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Encourages the use of SQL standard identity columns over PostgreSQL's serial columns for improved usability. ```javascript rules: { 'prefer-identity-to-serial': ['error'], }, ``` -------------------------------- ### Enforce Specific Foreign Key Reference Actions Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Configure specific ON UPDATE and ON DELETE actions for foreign key constraints. If an action is not specified, any action is permitted. ```javascript rules: { 'reference-actions': ['error', { onUpdate: 'NO ACTION', onDelete: 'CASCADE', }], } ``` -------------------------------- ### Configure name-inflection rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Enforces singular or plural naming for tables. Defaults to 'singular'. ```javascript rules: { 'name-inflection': ['error', 'singular'], }, ``` -------------------------------- ### Configure name-casing rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Enforces correct casing for table, view, and column names. Supports 'snake', 'dash', 'camel', and 'pascal' casing schemes. ```javascript rules: { 'name-casing': ['error', 'snake'], }, ``` -------------------------------- ### Process Database Schema with Schemalint Source: https://context7.com/kristiandupont/schemalint/llms.txt Use the `processDatabase` function from the 'schemalint' library to lint a database schema programmatically. It returns an exit code indicating success or failure. ```typescript import { processDatabase } from "schemalint"; const config = { connection: { host: "localhost", user: "postgres", password: "postgres", database: "myapp", }, schemas: [{ name: "public" }], rules: { "name-casing": ["error", "snake"], "prefer-text-to-varchar": ["error"], }, }; // Returns exit code: 0 for success, 1 if issues found const exitCode = await processDatabase(config); console.log(exitCode === 0 ? "No issues" : "Issues found"); ``` -------------------------------- ### Configure mandatory-columns Rule Source: https://context7.com/kristiandupont/schemalint/llms.txt Use this configuration to require specific columns in tables with defined properties like type and nullability. ```javascript // Configuration rules: { 'mandatory-columns': ['error', { created_at: { expandedType: 'pg_catalog.timestamptz', isNullable: false, }, updated_at: { expandedType: 'pg_catalog.timestamptz', isNullable: false, }, }], } // Example output for violation: // public.users: error mandatory-columns : Mandatory column "created_at" is missing // public.products.updated_at: error mandatory-columns : Column "updated_at" has properties {"isNullable":true} but expected {"isNullable":false} ``` -------------------------------- ### Export Custom Rules Source: https://github.com/kristiandupont/schemalint/blob/main/example/README.md Exports custom Schemalint rules defined in this directory. This file serves as an entry point for importing custom rules into Schemalint. ```javascript import { rule as identifierNaming } from "./identifierNaming.js"; import { rule as lastUpdated } from "./lastUpdated.js"; export const rules = { "identifier-naming": identifierNaming, "last-updated": lastUpdated, }; ``` -------------------------------- ### Configure prefer-timestamptz-to-timestamp rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Promotes the use of 'timestamptz' over 'timestamp' in PostgreSQL to correctly handle timezones. ```javascript rules: { 'prefer-timestamptz-to-timestamp': ['error'], }, ``` -------------------------------- ### Configure prefer-timestamptz-to-timestamp Rule Source: https://context7.com/kristiandupont/schemalint/llms.txt Use this configuration to enforce the use of TIMESTAMPTZ over TIMESTAMP for proper timezone handling and UTC storage. ```javascript // Configuration rules: { 'prefer-timestamptz-to-timestamp': ['error'], } // Example output for violation: // public.events.created_at: error prefer-timestamptz-to-timestamp : Prefer TIMESTAMPTZ to type TIMESTAMP // // Suggested fix: // ALTER TABLE "public"."events" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ; ``` -------------------------------- ### Configure prefer-text-with-check-to-enum rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Suggests using TEXT columns with CHECK constraints instead of ENUM types in PostgreSQL due to ENUM's limitations. ```javascript rules: { 'prefer-text-with-check-to-enum': ['error'], }, ``` -------------------------------- ### Configure index-referencing-column Rule Source: https://context7.com/kristiandupont/schemalint/llms.txt Use this configuration to ensure that foreign key referencing columns have an index, improving query performance. ```javascript // Configuration rules: { 'index-referencing-column': ['error'], } // Example output for violation: // public.orders.orders_customer_id_fkey: error index-referencing-column : No index found on referencing column(s) customer_id // // Suggested fix: // CREATE INDEX ON "public"."orders" ("customer_id"); ``` -------------------------------- ### Configure prefer-text-to-varchar rule Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Encourages the use of the 'text' data type over 'varchar' in PostgreSQL for columns without a maximum length. ```javascript rules: { 'prefer-text-to-varchar': ['error'], }, ``` -------------------------------- ### Implement Custom Rule for Identifier Naming Source: https://context7.com/kristiandupont/schemalint/llms.txt This JavaScript code defines a custom Schemalint rule to enforce the 'tablename_id' naming convention for primary key columns. It requires the schema object and a report function to log violations. ```javascript // custom-rules/identifierNaming.js /** @type {import('schemalint').Rule} */ const identifierNaming = { name: 'identifier-naming', docs: { description: 'Primary key columns should follow "tablename_id" convention', url: 'https://example.com/docs/identifier-naming', }, process({ schemaObject, report }) { schemaObject.tables.forEach(({ columns, name: tableName }) => { const idColumns = columns.filter((c) => c.isPrimaryKey); if (idColumns.length === 1) { const [idColumn] = idColumns; const expectedName = `${tableName}_id`; if (idColumn.name !== expectedName) { report({ rule: this.name, identifier: `${schemaObject.name}.${tableName}`, message: `Primary key "${idColumn.name}" doesn't follow convention. Expected: ${expectedName}`, suggestedMigration: `ALTER TABLE "${tableName}" RENAME COLUMN "${idColumn.name}" TO "${expectedName}";`, }); } } }); }, }; module.exports = identifierNaming; ``` -------------------------------- ### Enforce Mandatory Columns with Properties Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Ensure that tables contain specific columns with required properties, such as 'expandedType' and 'isNullable'. Note that PostgreSQL appends new columns to the end of a table. ```javascript rules: { 'mandatory-columns': ['error', { created_at: { expandedType: 'pg_catalog.timestamptz', isNullable: false, } }], } ``` -------------------------------- ### Enforce Index on Referencing Column Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md Use this rule to ensure that foreign key constraints have an index on the referencing column. This can improve DELETE and UPDATE performance on the referenced table. ```javascript rules: { 'index-referencing-column': ['error'], } ``` -------------------------------- ### Enforce Row-Level Security Source: https://github.com/kristiandupont/schemalint/blob/main/src/rules/README.md This rule checks that row-level security is enabled for tables. Optionally, enforce that RLS is actively enforced using the 'enforced' option. ```javascript rules: { 'row-level-security': ['error', {enforced: true}], } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.