diff --git a/.gitignore b/.gitignore index b7f3f8011..4c22f22d6 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ crates/pgt_treesitter_grammar/src/node-types.json crates/pgt_treesitter_grammar/src/parser.c crates/pgt_treesitter_grammar/src/parser.c.codex-session-id .codex-session-id + +site/ diff --git a/docs/codegen/src/rules_index.rs b/docs/codegen/src/rules_index.rs index 3d2c95292..88cd3e17c 100644 --- a/docs/codegen/src/rules_index.rs +++ b/docs/codegen/src/rules_index.rs @@ -69,7 +69,7 @@ fn generate_group( write!( content, - "| [{rule_name}](./{dashed_rule}) | {summary} | {properties} |" + "| [{rule_name}](./rules/{dashed_rule}.md) | {summary} | {properties} |" )?; writeln!(content)?; diff --git a/docs/codegen/src/rules_sources.rs b/docs/codegen/src/rules_sources.rs index a25430d5b..fe239e395 100644 --- a/docs/codegen/src/rules_sources.rs +++ b/docs/codegen/src/rules_sources.rs @@ -48,12 +48,15 @@ pub fn generate_rule_sources(docs_dir: &Path) -> anyhow::Result<()> { for (rule_name, metadata) in rules { let kebab_rule_name = Case::Kebab.convert(rule_name); if metadata.sources.is_empty() { - exclusive_rules.insert((rule_name.to_string(), format!("../rules/{kebab_rule_name}"))); + exclusive_rules.insert(( + rule_name.to_string(), + format!("./rules/{kebab_rule_name}.md"), + )); } else { for source in metadata.sources { let source_set = SourceSet { rule_name: rule_name.to_string(), - link: format!("../rules/{kebab_rule_name}"), + link: format!("./rules/{kebab_rule_name}.md"), source_link: source.to_rule_url(), source_rule_name: source.as_rule_name().to_string(), }; diff --git a/docs/codegen/src/splinter_docs.rs b/docs/codegen/src/splinter_docs.rs index 0e8fea9cd..8ca275b99 100644 --- a/docs/codegen/src/splinter_docs.rs +++ b/docs/codegen/src/splinter_docs.rs @@ -86,9 +86,10 @@ fn generate_splinter_rule_doc( writeln!(content, "{}", splinter_meta.description)?; writeln!(content)?; - // Add "Learn More" link with remediation URL from trait - let remediation = splinter_meta.remediation; - writeln!(content, "[Learn More]({remediation})")?; + // Add remediation section + writeln!(content, "## Remediation")?; + writeln!(content)?; + writeln!(content, "{}", splinter_meta.remediation)?; writeln!(content)?; // Add SQL query section (with metadata stripped) diff --git a/docs/configuration.md b/docs/configuration.md index d39f66fd7..453551011 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -103,5 +103,5 @@ In the following example, we include all files, except those in any test/ folder ``` #### Control files via VCS -You can ignore files ignored by your [VCS](/guides/vcs_integration.md). +You can ignore files ignored by your [VCS](guides/vcs_integration.md). diff --git a/docs/getting_started.md b/docs/getting_started.md index 48a91a3a1..6cba66d34 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -8,7 +8,7 @@ Install via your package manager if you use one: pnpm add -D -E @postgres-language-server/cli ``` -Alternatively, most [editor integrations](/guides/ide_setup) will manage the installation for you, or you can install it as a [standalone executable](/manual_installation). +Alternatively, most [editor integrations](guides/ide_setup.md) will manage the installation for you, or you can install it as a [standalone executable](manual_installation.md). ## Configuration @@ -88,6 +88,6 @@ The Postgres Language Server is available as an extension in your favorite edito Run `postgres-language-server check` in your CI pipeline to lint your schema changes and enforce code quality across your team. We provide a [GitHub Action](https://github.com/supabase-community/postgres-language-server-cli-action) to setup the Postgres Language Server in your runner. -See the [Continuous Integration](/guides/continuous_integration) guide for an example. +See the [Continuous Integration](guides/continuous_integration.md) guide for an example. diff --git a/docs/guides/suppressions.md b/docs/guides/suppressions.md index 2e5141595..fe4f8e788 100644 --- a/docs/guides/suppressions.md +++ b/docs/guides/suppressions.md @@ -90,5 +90,5 @@ alter table tasks drop column created_at; ## Notes -- Trying to suppress diagnostics that have already been disabled in your [configuration file](/#configuration) will show a warning. +- Trying to suppress diagnostics that have already been disabled in your [configuration file](../configuration.md) will show a warning. - Trying to suppress diagnostics that don't haven't been raised will also show a warning. diff --git a/docs/index.md b/docs/index.md index ff8a2a544..4c55f46c1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,10 +14,10 @@ The language server is built on Postgres' own parser `libpg_query` to ensure 100 The following features are available today: -- [Syntax Diagnostics](/features/syntax_diagnostics) -- [Linting](/features/linting) -- [Type Checking](/features/type_checking) -- [PL/pgSQL Support](/features/plpgsql) -- [Autocompletion & Hover](/features/editor_features) +- [Syntax Diagnostics](features/syntax_diagnostics.md) +- [Linting](features/linting.md) +- [Type Checking](features/type_checking.md) +- [PL/pgSQL Support](features/plpgsql.md) +- [Autocompletion & Hover](features/editor_features.md) For future plans and opportunities to contribute, please check out the issues and discussions. Any contributions are welcome! diff --git a/docs/reference/rule_sources.md b/docs/reference/rule_sources.md index 06dfa5db8..f61c78d02 100644 --- a/docs/reference/rule_sources.md +++ b/docs/reference/rule_sources.md @@ -6,39 +6,39 @@ _No exclusive rules available._ ### Eugene | Eugene Rule Name | Rule Name | | ---- | ---- | -| [E11](https://kaveland.no/eugene/hints/E11/index.html) |[addSerialColumn](../rules/add-serial-column) | -| [E3](https://kaveland.no/eugene/hints/E3/index.html) |[preferJsonb](../rules/prefer-jsonb) | -| [E4](https://kaveland.no/eugene/hints/E4/index.html) |[runningStatementWhileHoldingAccessExclusive](../rules/running-statement-while-holding-access-exclusive) | -| [E9](https://kaveland.no/eugene/hints/E9/index.html) |[lockTimeoutWarning](../rules/lock-timeout-warning) | -| [W12](https://kaveland.no/eugene/hints/W12/index.html) |[multipleAlterTable](../rules/multiple-alter-table) | -| [W13](https://kaveland.no/eugene/hints/W13/index.html) |[creatingEnum](../rules/creating-enum) | +| [E11](https://kaveland.no/eugene/hints/E11/index.html) |[addSerialColumn](./rules/add-serial-column.md) | +| [E3](https://kaveland.no/eugene/hints/E3/index.html) |[preferJsonb](./rules/prefer-jsonb.md) | +| [E4](https://kaveland.no/eugene/hints/E4/index.html) |[runningStatementWhileHoldingAccessExclusive](./rules/running-statement-while-holding-access-exclusive.md) | +| [E9](https://kaveland.no/eugene/hints/E9/index.html) |[lockTimeoutWarning](./rules/lock-timeout-warning.md) | +| [W12](https://kaveland.no/eugene/hints/W12/index.html) |[multipleAlterTable](./rules/multiple-alter-table.md) | +| [W13](https://kaveland.no/eugene/hints/W13/index.html) |[creatingEnum](./rules/creating-enum.md) | ### Squawk | Squawk Rule Name | Rule Name | | ---- | ---- | -| [adding-field-with-default](https://squawkhq.com/docs/adding-field-with-default) |[addingFieldWithDefault](../rules/adding-field-with-default) | -| [adding-foreign-key-constraint](https://squawkhq.com/docs/adding-foreign-key-constraint) |[addingForeignKeyConstraint](../rules/adding-foreign-key-constraint) | -| [adding-not-null-field](https://squawkhq.com/docs/adding-not-null-field) |[addingNotNullField](../rules/adding-not-null-field) | -| [adding-required-field](https://squawkhq.com/docs/adding-required-field) |[addingRequiredField](../rules/adding-required-field) | -| [adding-serial-primary-key-field](https://squawkhq.com/docs/adding-serial-primary-key-field) |[addingPrimaryKeyConstraint](../rules/adding-primary-key-constraint) | -| [ban-char-field](https://squawkhq.com/docs/ban-char-field) |[banCharField](../rules/ban-char-field) | -| [ban-concurrent-index-creation-in-transaction](https://squawkhq.com/docs/ban-concurrent-index-creation-in-transaction) |[banConcurrentIndexCreationInTransaction](../rules/ban-concurrent-index-creation-in-transaction) | -| [ban-drop-column](https://squawkhq.com/docs/ban-drop-column) |[banDropColumn](../rules/ban-drop-column) | -| [ban-drop-database](https://squawkhq.com/docs/ban-drop-database) |[banDropDatabase](../rules/ban-drop-database) | -| [ban-drop-not-null](https://squawkhq.com/docs/ban-drop-not-null) |[banDropNotNull](../rules/ban-drop-not-null) | -| [ban-drop-table](https://squawkhq.com/docs/ban-drop-table) |[banDropTable](../rules/ban-drop-table) | -| [ban-truncate-cascade](https://squawkhq.com/docs/ban-truncate-cascade) |[banTruncateCascade](../rules/ban-truncate-cascade) | -| [changing-column-type](https://squawkhq.com/docs/changing-column-type) |[changingColumnType](../rules/changing-column-type) | -| [constraint-missing-not-valid](https://squawkhq.com/docs/constraint-missing-not-valid) |[constraintMissingNotValid](../rules/constraint-missing-not-valid) | -| [disallow-unique-constraint](https://squawkhq.com/docs/disallow-unique-constraint) |[disallowUniqueConstraint](../rules/disallow-unique-constraint) | -| [prefer-big-int](https://squawkhq.com/docs/prefer-big-int) |[preferBigInt](../rules/prefer-big-int) | -| [prefer-bigint-over-int](https://squawkhq.com/docs/prefer-bigint-over-int) |[preferBigintOverInt](../rules/prefer-bigint-over-int) | -| [prefer-bigint-over-smallint](https://squawkhq.com/docs/prefer-bigint-over-smallint) |[preferBigintOverSmallint](../rules/prefer-bigint-over-smallint) | -| [prefer-identity](https://squawkhq.com/docs/prefer-identity) |[preferIdentity](../rules/prefer-identity) | -| [prefer-robust-stmts](https://squawkhq.com/docs/prefer-robust-stmts) |[preferRobustStmts](../rules/prefer-robust-stmts) | -| [prefer-text-field](https://squawkhq.com/docs/prefer-text-field) |[preferTextField](../rules/prefer-text-field) | -| [prefer-timestamptz](https://squawkhq.com/docs/prefer-timestamptz) |[preferTimestamptz](../rules/prefer-timestamptz) | -| [renaming-column](https://squawkhq.com/docs/renaming-column) |[renamingColumn](../rules/renaming-column) | -| [renaming-table](https://squawkhq.com/docs/renaming-table) |[renamingTable](../rules/renaming-table) | -| [require-concurrent-index-creation](https://squawkhq.com/docs/require-concurrent-index-creation) |[requireConcurrentIndexCreation](../rules/require-concurrent-index-creation) | -| [require-concurrent-index-deletion](https://squawkhq.com/docs/require-concurrent-index-deletion) |[requireConcurrentIndexDeletion](../rules/require-concurrent-index-deletion) | -| [transaction-nesting](https://squawkhq.com/docs/transaction-nesting) |[transactionNesting](../rules/transaction-nesting) | +| [adding-field-with-default](https://squawkhq.com/docs/adding-field-with-default) |[addingFieldWithDefault](./rules/adding-field-with-default.md) | +| [adding-foreign-key-constraint](https://squawkhq.com/docs/adding-foreign-key-constraint) |[addingForeignKeyConstraint](./rules/adding-foreign-key-constraint.md) | +| [adding-not-null-field](https://squawkhq.com/docs/adding-not-null-field) |[addingNotNullField](./rules/adding-not-null-field.md) | +| [adding-required-field](https://squawkhq.com/docs/adding-required-field) |[addingRequiredField](./rules/adding-required-field.md) | +| [adding-serial-primary-key-field](https://squawkhq.com/docs/adding-serial-primary-key-field) |[addingPrimaryKeyConstraint](./rules/adding-primary-key-constraint.md) | +| [ban-char-field](https://squawkhq.com/docs/ban-char-field) |[banCharField](./rules/ban-char-field.md) | +| [ban-concurrent-index-creation-in-transaction](https://squawkhq.com/docs/ban-concurrent-index-creation-in-transaction) |[banConcurrentIndexCreationInTransaction](./rules/ban-concurrent-index-creation-in-transaction.md) | +| [ban-drop-column](https://squawkhq.com/docs/ban-drop-column) |[banDropColumn](./rules/ban-drop-column.md) | +| [ban-drop-database](https://squawkhq.com/docs/ban-drop-database) |[banDropDatabase](./rules/ban-drop-database.md) | +| [ban-drop-not-null](https://squawkhq.com/docs/ban-drop-not-null) |[banDropNotNull](./rules/ban-drop-not-null.md) | +| [ban-drop-table](https://squawkhq.com/docs/ban-drop-table) |[banDropTable](./rules/ban-drop-table.md) | +| [ban-truncate-cascade](https://squawkhq.com/docs/ban-truncate-cascade) |[banTruncateCascade](./rules/ban-truncate-cascade.md) | +| [changing-column-type](https://squawkhq.com/docs/changing-column-type) |[changingColumnType](./rules/changing-column-type.md) | +| [constraint-missing-not-valid](https://squawkhq.com/docs/constraint-missing-not-valid) |[constraintMissingNotValid](./rules/constraint-missing-not-valid.md) | +| [disallow-unique-constraint](https://squawkhq.com/docs/disallow-unique-constraint) |[disallowUniqueConstraint](./rules/disallow-unique-constraint.md) | +| [prefer-big-int](https://squawkhq.com/docs/prefer-big-int) |[preferBigInt](./rules/prefer-big-int.md) | +| [prefer-bigint-over-int](https://squawkhq.com/docs/prefer-bigint-over-int) |[preferBigintOverInt](./rules/prefer-bigint-over-int.md) | +| [prefer-bigint-over-smallint](https://squawkhq.com/docs/prefer-bigint-over-smallint) |[preferBigintOverSmallint](./rules/prefer-bigint-over-smallint.md) | +| [prefer-identity](https://squawkhq.com/docs/prefer-identity) |[preferIdentity](./rules/prefer-identity.md) | +| [prefer-robust-stmts](https://squawkhq.com/docs/prefer-robust-stmts) |[preferRobustStmts](./rules/prefer-robust-stmts.md) | +| [prefer-text-field](https://squawkhq.com/docs/prefer-text-field) |[preferTextField](./rules/prefer-text-field.md) | +| [prefer-timestamptz](https://squawkhq.com/docs/prefer-timestamptz) |[preferTimestamptz](./rules/prefer-timestamptz.md) | +| [renaming-column](https://squawkhq.com/docs/renaming-column) |[renamingColumn](./rules/renaming-column.md) | +| [renaming-table](https://squawkhq.com/docs/renaming-table) |[renamingTable](./rules/renaming-table.md) | +| [require-concurrent-index-creation](https://squawkhq.com/docs/require-concurrent-index-creation) |[requireConcurrentIndexCreation](./rules/require-concurrent-index-creation.md) | +| [require-concurrent-index-deletion](https://squawkhq.com/docs/require-concurrent-index-deletion) |[requireConcurrentIndexDeletion](./rules/require-concurrent-index-deletion.md) | +| [transaction-nesting](https://squawkhq.com/docs/transaction-nesting) |[transactionNesting](./rules/transaction-nesting.md) | diff --git a/docs/reference/rules.md b/docs/reference/rules.md index 9d798987c..411e6427e 100644 --- a/docs/reference/rules.md +++ b/docs/reference/rules.md @@ -12,39 +12,39 @@ Rules that detect potential safety issues in your code. | Rule name | Description | Properties | | --- | --- | --- | -| [addSerialColumn](./add-serial-column) | Adding a column with a SERIAL type or GENERATED ALWAYS AS ... STORED causes a full table rewrite. | ✅ | -| [addingFieldWithDefault](./adding-field-with-default) | Adding a column with a DEFAULT value may lead to a table rewrite while holding an ACCESS EXCLUSIVE lock. | ✅ | -| [addingForeignKeyConstraint](./adding-foreign-key-constraint) | Adding a foreign key constraint requires a table scan and a SHARE ROW EXCLUSIVE lock on both tables, which blocks writes. | ✅ | -| [addingNotNullField](./adding-not-null-field) | Setting a column NOT NULL blocks reads while the table is scanned. | ✅ | -| [addingPrimaryKeyConstraint](./adding-primary-key-constraint) | Adding a primary key constraint results in locks and table rewrites. | ✅ | -| [addingRequiredField](./adding-required-field) | Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required. | | -| [banCharField](./ban-char-field) | Using CHAR(n) or CHARACTER(n) types is discouraged. | | -| [banConcurrentIndexCreationInTransaction](./ban-concurrent-index-creation-in-transaction) | Concurrent index creation is not allowed within a transaction. | ✅ | -| [banDropColumn](./ban-drop-column) | Dropping a column may break existing clients. | ✅ | -| [banDropDatabase](./ban-drop-database) | Dropping a database may break existing clients (and everything else, really). | | -| [banDropNotNull](./ban-drop-not-null) | Dropping a NOT NULL constraint may break existing clients. | ✅ | -| [banDropTable](./ban-drop-table) | Dropping a table may break existing clients. | ✅ | -| [banTruncateCascade](./ban-truncate-cascade) | Using `TRUNCATE`'s `CASCADE` option will truncate any tables that are also foreign-keyed to the specified tables. | | -| [changingColumnType](./changing-column-type) | Changing a column type may break existing clients. | | -| [constraintMissingNotValid](./constraint-missing-not-valid) | Adding constraints without NOT VALID blocks all reads and writes. | | -| [creatingEnum](./creating-enum) | Creating enum types is not recommended for new applications. | | -| [disallowUniqueConstraint](./disallow-unique-constraint) | Disallow adding a UNIQUE constraint without using an existing index. | | -| [lockTimeoutWarning](./lock-timeout-warning) | Taking a dangerous lock without setting a lock timeout can cause indefinite blocking. | ✅ | -| [multipleAlterTable](./multiple-alter-table) | Multiple ALTER TABLE statements on the same table should be combined into a single statement. | ✅ | -| [preferBigInt](./prefer-big-int) | Prefer BIGINT over smaller integer types. | | -| [preferBigintOverInt](./prefer-bigint-over-int) | Prefer BIGINT over INT/INTEGER types. | | -| [preferBigintOverSmallint](./prefer-bigint-over-smallint) | Prefer BIGINT over SMALLINT types. | | -| [preferIdentity](./prefer-identity) | Prefer using IDENTITY columns over serial columns. | | -| [preferJsonb](./prefer-jsonb) | Prefer JSONB over JSON types. | | -| [preferRobustStmts](./prefer-robust-stmts) | Prefer statements with guards for robustness in migrations. | | -| [preferTextField](./prefer-text-field) | Prefer using TEXT over VARCHAR(n) types. | | -| [preferTimestamptz](./prefer-timestamptz) | Prefer TIMESTAMPTZ over TIMESTAMP types. | | -| [renamingColumn](./renaming-column) | Renaming columns may break existing queries and application code. | | -| [renamingTable](./renaming-table) | Renaming tables may break existing queries and application code. | | -| [requireConcurrentIndexCreation](./require-concurrent-index-creation) | Creating indexes non-concurrently can lock the table for writes. | | -| [requireConcurrentIndexDeletion](./require-concurrent-index-deletion) | Dropping indexes non-concurrently can lock the table for reads. | | -| [runningStatementWhileHoldingAccessExclusive](./running-statement-while-holding-access-exclusive) | Running additional statements while holding an ACCESS EXCLUSIVE lock blocks all table access. | ✅ | -| [transactionNesting](./transaction-nesting) | Detects problematic transaction nesting that could lead to unexpected behavior. | | +| [addSerialColumn](./rules/add-serial-column.md) | Adding a column with a SERIAL type or GENERATED ALWAYS AS ... STORED causes a full table rewrite. | ✅ | +| [addingFieldWithDefault](./rules/adding-field-with-default.md) | Adding a column with a DEFAULT value may lead to a table rewrite while holding an ACCESS EXCLUSIVE lock. | ✅ | +| [addingForeignKeyConstraint](./rules/adding-foreign-key-constraint.md) | Adding a foreign key constraint requires a table scan and a SHARE ROW EXCLUSIVE lock on both tables, which blocks writes. | ✅ | +| [addingNotNullField](./rules/adding-not-null-field.md) | Setting a column NOT NULL blocks reads while the table is scanned. | ✅ | +| [addingPrimaryKeyConstraint](./rules/adding-primary-key-constraint.md) | Adding a primary key constraint results in locks and table rewrites. | ✅ | +| [addingRequiredField](./rules/adding-required-field.md) | Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required. | | +| [banCharField](./rules/ban-char-field.md) | Using CHAR(n) or CHARACTER(n) types is discouraged. | | +| [banConcurrentIndexCreationInTransaction](./rules/ban-concurrent-index-creation-in-transaction.md) | Concurrent index creation is not allowed within a transaction. | ✅ | +| [banDropColumn](./rules/ban-drop-column.md) | Dropping a column may break existing clients. | ✅ | +| [banDropDatabase](./rules/ban-drop-database.md) | Dropping a database may break existing clients (and everything else, really). | | +| [banDropNotNull](./rules/ban-drop-not-null.md) | Dropping a NOT NULL constraint may break existing clients. | ✅ | +| [banDropTable](./rules/ban-drop-table.md) | Dropping a table may break existing clients. | ✅ | +| [banTruncateCascade](./rules/ban-truncate-cascade.md) | Using `TRUNCATE`'s `CASCADE` option will truncate any tables that are also foreign-keyed to the specified tables. | | +| [changingColumnType](./rules/changing-column-type.md) | Changing a column type may break existing clients. | | +| [constraintMissingNotValid](./rules/constraint-missing-not-valid.md) | Adding constraints without NOT VALID blocks all reads and writes. | | +| [creatingEnum](./rules/creating-enum.md) | Creating enum types is not recommended for new applications. | | +| [disallowUniqueConstraint](./rules/disallow-unique-constraint.md) | Disallow adding a UNIQUE constraint without using an existing index. | | +| [lockTimeoutWarning](./rules/lock-timeout-warning.md) | Taking a dangerous lock without setting a lock timeout can cause indefinite blocking. | ✅ | +| [multipleAlterTable](./rules/multiple-alter-table.md) | Multiple ALTER TABLE statements on the same table should be combined into a single statement. | ✅ | +| [preferBigInt](./rules/prefer-big-int.md) | Prefer BIGINT over smaller integer types. | | +| [preferBigintOverInt](./rules/prefer-bigint-over-int.md) | Prefer BIGINT over INT/INTEGER types. | | +| [preferBigintOverSmallint](./rules/prefer-bigint-over-smallint.md) | Prefer BIGINT over SMALLINT types. | | +| [preferIdentity](./rules/prefer-identity.md) | Prefer using IDENTITY columns over serial columns. | | +| [preferJsonb](./rules/prefer-jsonb.md) | Prefer JSONB over JSON types. | | +| [preferRobustStmts](./rules/prefer-robust-stmts.md) | Prefer statements with guards for robustness in migrations. | | +| [preferTextField](./rules/prefer-text-field.md) | Prefer using TEXT over VARCHAR(n) types. | | +| [preferTimestamptz](./rules/prefer-timestamptz.md) | Prefer TIMESTAMPTZ over TIMESTAMP types. | | +| [renamingColumn](./rules/renaming-column.md) | Renaming columns may break existing queries and application code. | | +| [renamingTable](./rules/renaming-table.md) | Renaming tables may break existing queries and application code. | | +| [requireConcurrentIndexCreation](./rules/require-concurrent-index-creation.md) | Creating indexes non-concurrently can lock the table for writes. | | +| [requireConcurrentIndexDeletion](./rules/require-concurrent-index-deletion.md) | Dropping indexes non-concurrently can lock the table for reads. | | +| [runningStatementWhileHoldingAccessExclusive](./rules/running-statement-while-holding-access-exclusive.md) | Running additional statements while holding an ACCESS EXCLUSIVE lock blocks all table access. | ✅ | +| [transactionNesting](./rules/transaction-nesting.md) | Detects problematic transaction nesting that could lead to unexpected behavior. | | [//]: # (END RULES_INDEX) diff --git a/docs/reference/rules/auth-rls-initplan.md b/docs/reference/rules/auth-rls-initplan.md index 17163a8f4..19e564902 100644 --- a/docs/reference/rules/auth-rls-initplan.md +++ b/docs/reference/rules/auth-rls-initplan.md @@ -11,7 +11,9 @@ Detects if calls to \`current_setting()\` and \`auth.()\` in RLS policies are being unnecessarily re-evaluated for each row -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0003_auth_rls_initplan) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0003_auth_rls_initplan ## SQL Query diff --git a/docs/reference/rules/auth-users-exposed.md b/docs/reference/rules/auth-users-exposed.md index 70d8c7160..996e0f803 100644 --- a/docs/reference/rules/auth-users-exposed.md +++ b/docs/reference/rules/auth-users-exposed.md @@ -11,7 +11,9 @@ Detects if auth.users is exposed to anon or authenticated roles via a view or materialized view in schemas exposed to PostgREST, potentially compromising user data security. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0002_auth_users_exposed) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0002_auth_users_exposed ## SQL Query diff --git a/docs/reference/rules/duplicate-index.md b/docs/reference/rules/duplicate-index.md index 7a89fcdb7..afb466d8f 100644 --- a/docs/reference/rules/duplicate-index.md +++ b/docs/reference/rules/duplicate-index.md @@ -8,7 +8,9 @@ Detects cases where two ore more identical indexes exist. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0009_duplicate_index) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0009_duplicate_index ## SQL Query diff --git a/docs/reference/rules/extension-in-public.md b/docs/reference/rules/extension-in-public.md index 9bd981959..668ee1609 100644 --- a/docs/reference/rules/extension-in-public.md +++ b/docs/reference/rules/extension-in-public.md @@ -8,7 +8,9 @@ Detects extensions installed in the \`public\` schema. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0014_extension_in_public) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0014_extension_in_public ## SQL Query diff --git a/docs/reference/rules/extension-versions-outdated.md b/docs/reference/rules/extension-versions-outdated.md index e6cf12a9b..9f546ab14 100644 --- a/docs/reference/rules/extension-versions-outdated.md +++ b/docs/reference/rules/extension-versions-outdated.md @@ -8,7 +8,9 @@ Detects extensions that are not using the default (recommended) version. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0022_extension_versions_outdated) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0022_extension_versions_outdated ## SQL Query diff --git a/docs/reference/rules/fkey-to-auth-unique.md b/docs/reference/rules/fkey-to-auth-unique.md index 5151d07c2..c705d60aa 100644 --- a/docs/reference/rules/fkey-to-auth-unique.md +++ b/docs/reference/rules/fkey-to-auth-unique.md @@ -11,7 +11,9 @@ Detects user defined foreign keys to unique constraints in the auth schema. -[Learn More](Drop the foreign key constraint that references the auth schema.) +## Remediation + +Drop the foreign key constraint that references the auth schema. ## SQL Query diff --git a/docs/reference/rules/foreign-table-in-api.md b/docs/reference/rules/foreign-table-in-api.md index 35a77cb03..6695df14a 100644 --- a/docs/reference/rules/foreign-table-in-api.md +++ b/docs/reference/rules/foreign-table-in-api.md @@ -11,7 +11,9 @@ Detects foreign tables that are accessible over APIs. Foreign tables do not respect row level security policies. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api ## SQL Query diff --git a/docs/reference/rules/function-search-path-mutable.md b/docs/reference/rules/function-search-path-mutable.md index c9e1f72a1..f6d50c47b 100644 --- a/docs/reference/rules/function-search-path-mutable.md +++ b/docs/reference/rules/function-search-path-mutable.md @@ -8,7 +8,9 @@ Detects functions where the search_path parameter is not set. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0011_function_search_path_mutable) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0011_function_search_path_mutable ## SQL Query diff --git a/docs/reference/rules/insecure-queue-exposed-in-api.md b/docs/reference/rules/insecure-queue-exposed-in-api.md index a8fe64534..e140b1f87 100644 --- a/docs/reference/rules/insecure-queue-exposed-in-api.md +++ b/docs/reference/rules/insecure-queue-exposed-in-api.md @@ -11,7 +11,9 @@ Detects cases where an insecure Queue is exposed over Data APIs -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0019_insecure_queue_exposed_in_api) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0019_insecure_queue_exposed_in_api ## SQL Query diff --git a/docs/reference/rules/materialized-view-in-api.md b/docs/reference/rules/materialized-view-in-api.md index e118218aa..29650bcd1 100644 --- a/docs/reference/rules/materialized-view-in-api.md +++ b/docs/reference/rules/materialized-view-in-api.md @@ -11,7 +11,9 @@ Detects materialized views that are accessible over the Data APIs. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0016_materialized_view_in_api) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0016_materialized_view_in_api ## SQL Query diff --git a/docs/reference/rules/multiple-permissive-policies.md b/docs/reference/rules/multiple-permissive-policies.md index cbcf37650..57a86e488 100644 --- a/docs/reference/rules/multiple-permissive-policies.md +++ b/docs/reference/rules/multiple-permissive-policies.md @@ -8,7 +8,9 @@ Detects if multiple permissive row level security policies are present on a table for the same \`role\` and \`action\` (e.g. insert). Multiple permissive policies are suboptimal for performance as each policy must be executed for every relevant query. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0006_multiple_permissive_policies) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0006_multiple_permissive_policies ## SQL Query diff --git a/docs/reference/rules/no-primary-key.md b/docs/reference/rules/no-primary-key.md index 70042250b..b37953bd5 100644 --- a/docs/reference/rules/no-primary-key.md +++ b/docs/reference/rules/no-primary-key.md @@ -8,7 +8,9 @@ Detects if a table does not have a primary key. Tables without a primary key can be inefficient to interact with at scale. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0004_no_primary_key) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0004_no_primary_key ## SQL Query diff --git a/docs/reference/rules/policy-exists-rls-disabled.md b/docs/reference/rules/policy-exists-rls-disabled.md index e4f46c702..d69b17031 100644 --- a/docs/reference/rules/policy-exists-rls-disabled.md +++ b/docs/reference/rules/policy-exists-rls-disabled.md @@ -8,7 +8,9 @@ Detects cases where row level security (RLS) policies have been created, but RLS has not been enabled for the underlying table. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0007_policy_exists_rls_disabled) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0007_policy_exists_rls_disabled ## SQL Query diff --git a/docs/reference/rules/rls-disabled-in-public.md b/docs/reference/rules/rls-disabled-in-public.md index 339bace74..017de2960 100644 --- a/docs/reference/rules/rls-disabled-in-public.md +++ b/docs/reference/rules/rls-disabled-in-public.md @@ -11,7 +11,9 @@ Detects cases where row level security (RLS) has not been enabled on tables in schemas exposed to PostgREST -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0013_rls_disabled_in_public) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0013_rls_disabled_in_public ## SQL Query diff --git a/docs/reference/rules/rls-enabled-no-policy.md b/docs/reference/rules/rls-enabled-no-policy.md index 644f874b3..e6a592ffe 100644 --- a/docs/reference/rules/rls-enabled-no-policy.md +++ b/docs/reference/rules/rls-enabled-no-policy.md @@ -8,7 +8,9 @@ Detects cases where row level security (RLS) has been enabled on a table but no RLS policies have been created. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0008_rls_enabled_no_policy) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0008_rls_enabled_no_policy ## SQL Query diff --git a/docs/reference/rules/rls-references-user-metadata.md b/docs/reference/rules/rls-references-user-metadata.md index 955c68512..cbe07ca23 100644 --- a/docs/reference/rules/rls-references-user-metadata.md +++ b/docs/reference/rules/rls-references-user-metadata.md @@ -11,7 +11,9 @@ Detects when Supabase Auth user_metadata is referenced insecurely in a row level security (RLS) policy. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0015_rls_references_user_metadata) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0015_rls_references_user_metadata ## SQL Query diff --git a/docs/reference/rules/security-definer-view.md b/docs/reference/rules/security-definer-view.md index 8dde33a3e..e8c0c90e0 100644 --- a/docs/reference/rules/security-definer-view.md +++ b/docs/reference/rules/security-definer-view.md @@ -11,7 +11,9 @@ Detects views defined with the SECURITY DEFINER property. These views enforce Postgres permissions and row level security policies (RLS) of the view creator, rather than that of the querying user -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0010_security_definer_view) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0010_security_definer_view ## SQL Query diff --git a/docs/reference/rules/table-bloat.md b/docs/reference/rules/table-bloat.md index 808410b7a..25bc165af 100644 --- a/docs/reference/rules/table-bloat.md +++ b/docs/reference/rules/table-bloat.md @@ -8,7 +8,9 @@ Detects if a table has excess bloat and may benefit from maintenance operations like vacuum full or cluster. -[Learn More](Consider running vacuum full (WARNING: incurs downtime) and tweaking autovacuum settings to reduce bloat.) +## Remediation + +Consider running vacuum full (WARNING: incurs downtime) and tweaking autovacuum settings to reduce bloat. ## SQL Query diff --git a/docs/reference/rules/unindexed-foreign-keys.md b/docs/reference/rules/unindexed-foreign-keys.md index 2a978ec65..9990f0468 100644 --- a/docs/reference/rules/unindexed-foreign-keys.md +++ b/docs/reference/rules/unindexed-foreign-keys.md @@ -8,7 +8,9 @@ Identifies foreign key constraints without a covering index, which can impact database performance. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0001_unindexed_foreign_keys) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0001_unindexed_foreign_keys ## SQL Query diff --git a/docs/reference/rules/unsupported-reg-types.md b/docs/reference/rules/unsupported-reg-types.md index 6922bd008..3012668d0 100644 --- a/docs/reference/rules/unsupported-reg-types.md +++ b/docs/reference/rules/unsupported-reg-types.md @@ -8,7 +8,9 @@ Identifies columns using unsupported reg* types outside pg_catalog schema, which prevents database upgrades using pg_upgrade. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=unsupported_reg_types) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=unsupported_reg_types ## SQL Query diff --git a/docs/reference/rules/unused-index.md b/docs/reference/rules/unused-index.md index e0f5d1d83..a6fd84a6b 100644 --- a/docs/reference/rules/unused-index.md +++ b/docs/reference/rules/unused-index.md @@ -8,7 +8,9 @@ Detects if an index has never been used and may be a candidate for removal. -[Learn More](https://supabase.com/docs/guides/database/database-linter?lint=0005_unused_index) +## Remediation + +https://supabase.com/docs/guides/database/database-linter?lint=0005_unused_index ## SQL Query diff --git a/uv.lock b/uv.lock index 0f36c0844..e40fa998b 100644 --- a/uv.lock +++ b/uv.lock @@ -211,7 +211,7 @@ wheels = [ ] [[package]] -name = "postgrestools" +name = "postgres-language-server" version = "0.1.0" source = { virtual = "." } dependencies = [