diff --git a/AGENTS.md b/AGENTS.md index fad4947..d0f1152 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ The PostgreSQL implementation of `@antelopejs/interface-database` and `@antelope ## Versioning -- Both implemented interfaces stay capped below the next minor (`interface-database` `>=0.4.0 <0.5.0`, `interface-database-catalog` `>=0.0.3 <0.1.0`), because a new minor can add required handlers. `pnpm lint` enforces it with `antelopejs-check-interface-ranges`. +- Both implemented interfaces stay capped below the next minor (`interface-database` `>=0.4.0 <0.5.0`, `interface-database-catalog` `>=0.0.3 <0.1.0`), because a new minor can add required handlers. `pnpm run checks` enforces it with its `dependency:ranges` step. - When a dependency range changes, update the compatibility table in `README.md` too. - A release that needs action from users gets an `### Upgrade notes` section in `CHANGELOG.md`, above the generated entries. @@ -76,50 +76,51 @@ Verify a boundary against the imports a developer or agent would plausibly write ### What enforces what -| Rule | Enforced by | -| ------------------------------------------------------------------------------ | --------------------------------------------------- | -| Formatting | oxfmt | -| Lint findings are errors; no rule warns | oxlint preset | -| Comments are TSDoc, directives, or `SAFETY:` only | `antelopejs/no-comments` | -| Every test asserts | `antelopejs/require-assertion` | -| Tests read no files outside fixtures, helpers, locales | `antelopejs/no-fs-read-in-tests` | -| Tests import the code under test from local source, not their own package name | `antelopejs/no-self-import-in-tests` | -| No assertion that restates a constant | `antelopejs/no-constant-value-assertion` | -| No test whose only check is "is a function" | `antelopejs/no-typeof-function-only-test` | -| String-keyed object tables are read through own keys only | `antelopejs/no-inherited-key-lookup` | -| A type guard checks each member it narrows to; keys with `Object.hasOwn` | `antelopejs/no-presence-only-type-guard` | -| A type guard checks the nested elements and values it claims | review; no tool | -| A startup read does not decide an insert another replica can race | `antelopejs/no-read-then-insert` | -| `Object.assign` writes no `unknown`, `any` or mistyped value over a field | `antelopejs/no-unsafe-object-assign` | -| Every file type-aware lint reads is listed by a tsconfig | `antelopejs/require-tsconfig-include` | -| Params ≤ 5, function ≤ 120 lines, file ≤ 500 lines, depth ≤ 4, complexity ≤ 20 | `eslint/max-*`, `eslint/complexity` | -| Cleanup preserves declarations, runtime exports and DMS auto-imports | `antelopejs-api-diff ` | -| Comment-only changes preserve JavaScript emit | `antelopejs-comment-proof ` | -| PR-body proof tables are copied unedited from the current head | `antelopejs-body-check ` | -| PR-body findings-left lines are live diagnostics at HEAD | `antelopejs-body-check ` | -| Receiver, positional and unpublished-module behaviour | `antelopejs-api-diff --probe ` | -| Directive and `SAFETY:` reasons are true of the code | review; no tool | -| Evasion-only and patched-internal findings go under Attention | review; no tool | -| No-upward rules reject same-tier peers | review and import probes | -| No `@ts-ignore` | `typescript/ban-ts-comment` | -| No once-used type parameter standing in for `unknown` | `typescript/no-unnecessary-type-parameters` | -| No `any` passed, assigned or returned where a type is declared | `typescript/no-unsafe-{argument,assignment,return}` | -| Files ≤ 20,000 bytes, tests and agent files included | `antelopejs-check-size` (pre-commit) | -| Suppressions stay within `guardrails.suppressions.json` | `antelopejs-suppressions` (pre-commit, checks) | -| No lint config switches off a rule to stay under the budget | `antelopejs-suppressions` (pre-commit, checks) | -| No added directive disables the `SAFETY:`, comment or test rules | `antelopejs-suppressions` (pre-commit, checks) | -| An added suppression gives a specific reason | `antelopejs-suppressions` (pre-commit, checks) | -| A directive in a file a change touches suppresses something and gives a reason | `antelopejs-suppressions` (pre-commit, checks) | -| A block disable is closed in its file | `antelopejs-suppressions` (pre-commit, checks) | -| Types check | `tsc` (pre-push) | -| No dead files, exports, or dependencies | knip | -| Managed files match the pack | `antelopejs-sync --check` | -| A CI gate reads `needs.` only of jobs in its `needs` | `antelopejs-sync --check` | -| Entry-only rules exempt no tracked outsider | `antelopejs-sync --check` | -| A DMS layer's `build/backend-boundary.ts` is the pack's plugin | `antelopejs-sync --check` | -| No `skipLibCheck` in the root tsconfig or one `typecheck` or `build` uses | `antelopejs-sync --check` | -| `build` skips the lib check only over what `typecheck` checks | `antelopejs-sync --check` | -| `release` runs `typecheck` | `antelopejs-sync --check` | -| A test names the wrong implementation it catches | review; no tool | +| Rule | Enforced by | +| ---------------------------------------------------------------------------------- | --------------------------------------------------- | +| Formatting | oxfmt | +| Lint findings are errors; no rule warns | oxlint preset | +| Comments are TSDoc, directives, or `SAFETY:` only | `antelopejs/no-comments` | +| Every test asserts | `antelopejs/require-assertion` | +| Tests read no files outside fixtures, helpers, locales | `antelopejs/no-fs-read-in-tests` | +| Tests import the code under test from local source, not their own package name | `antelopejs/no-self-import-in-tests` | +| No assertion that restates a constant | `antelopejs/no-constant-value-assertion` | +| No test whose only check is "is a function" | `antelopejs/no-typeof-function-only-test` | +| String-keyed object tables are read through own keys only | `antelopejs/no-inherited-key-lookup` | +| A type guard checks each member it narrows to; keys with `Object.hasOwn` | `antelopejs/no-presence-only-type-guard` | +| A type guard checks the nested elements and values it claims | review; no tool | +| A startup read does not decide an insert another replica can race | `antelopejs/no-read-then-insert` | +| An awaited function or a promise resolves to no unrun database query | `antelopejs/no-unrun-query` | +| `Object.assign` writes no `unknown`, `any` or mistyped value over a field | `antelopejs/no-unsafe-object-assign` | +| Every file type-aware lint reads is listed by a tsconfig that resolves its imports | `antelopejs/require-tsconfig-include` | +| Params ≤ 5, function ≤ 120 lines, file ≤ 500 lines, depth ≤ 4, complexity ≤ 20 | `eslint/max-*`, `eslint/complexity` | +| Cleanup preserves declarations, runtime exports and DMS auto-imports | `antelopejs-api-diff ` | +| Comment-only changes preserve JavaScript emit | `antelopejs-comment-proof ` | +| PR-body proof tables are copied unedited from the current head | `antelopejs-body-check ` | +| PR-body findings-left lines are live diagnostics at HEAD | `antelopejs-body-check ` | +| Receiver, positional and unpublished-module behaviour | `antelopejs-api-diff --probe ` | +| Directive and `SAFETY:` reasons are true of the code | review; no tool | +| Evasion-only and patched-internal findings go under Attention | review; no tool | +| No-upward rules reject same-tier peers | review and import probes | +| No `@ts-ignore` | `typescript/ban-ts-comment` | +| No once-used type parameter standing in for `unknown` | `typescript/no-unnecessary-type-parameters` | +| No `any` passed, assigned or returned where a type is declared | `typescript/no-unsafe-{argument,assignment,return}` | +| Files ≤ 20,000 bytes, tests and agent files included | `antelopejs-check-size` (pre-commit) | +| Suppressions stay within `guardrails.suppressions.json` | `antelopejs-suppressions` (pre-commit, checks) | +| No lint config switches off a rule to stay under the budget | `antelopejs-suppressions` (pre-commit, checks) | +| No added directive disables the `SAFETY:`, comment or test rules | `antelopejs-suppressions` (pre-commit, checks) | +| An added suppression gives a specific reason | `antelopejs-suppressions` (pre-commit, checks) | +| A directive in a file a change touches suppresses something and gives a reason | `antelopejs-suppressions` (pre-commit, checks) | +| A block disable is closed in its file | `antelopejs-suppressions` (pre-commit, checks) | +| Types check | `tsc` (pre-push) | +| No dead files, exports, or dependencies | knip | +| Managed files match the pack | `antelopejs-sync --check` | +| A CI gate reads `needs.` only of jobs in its `needs` | `antelopejs-sync --check` | +| Entry-only rules exempt no tracked outsider | `antelopejs-sync --check` | +| A DMS layer's `build/backend-boundary.ts` is the pack's plugin | `antelopejs-sync --check` | +| No `skipLibCheck` in the root tsconfig or one `typecheck` or `build` uses | `antelopejs-sync --check` | +| `build` skips the lib check only over what `typecheck` checks | `antelopejs-sync --check` | +| `release` runs `typecheck` | `antelopejs-sync --check` | +| A test names the wrong implementation it catches | review; no tool | diff --git a/README.md b/README.md index c7a9f7c..d95ae3d 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ export default defineConfig({ source: { type: "package", package: "@antelopejs/postgres", - version: "^0.2.0", + version: ">=0.4.0 <0.5.0", }, config: { url: "postgres://postgres@localhost:5432/my-project", @@ -118,7 +118,7 @@ This repository documents what is specific to the PostgreSQL backend: | Package | Supported | Tested with | | ---------------------------------------- | ---------------- | ----------- | -| `@antelopejs/interface-core` | `>=0.1.1 <1.0.0` | `0.4.0` | +| `@antelopejs/interface-core` | `>=0.5.0 <0.6.0` | `0.5.1` | | `@antelopejs/interface-database` | `>=0.4.0 <0.5.0` | `0.4.0` | | `@antelopejs/interface-database-catalog` | `>=0.0.3 <0.1.0` | `0.0.3` | diff --git a/guardrails.suppressions.json b/guardrails.suppressions.json index 89787b1..c90846b 100644 --- a/guardrails.suppressions.json +++ b/guardrails.suppressions.json @@ -1,6 +1,6 @@ { "rules": { - "anti-slop/no-unknown-parameters": 1 + "anti-slop/no-unknown-parameters": 0 }, "tsExpectError": 0, "tsIgnore": 0, diff --git a/package.json b/package.json index cb1c1f0..735b318 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "build": "rimraf dist && tsc", "format": "oxfmt .", "lint:fix": "oxlint --fix", - "lint": "oxlint && antelopejs-check-interface-ranges", + "lint": "oxlint", "prepack": "pnpm run build", "release": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run prepack && release-it", "test": "docker pull -q postgres:18-alpine >/dev/null 2>&1 & pnpm run build && scripts/test.sh", @@ -51,14 +51,14 @@ "suppressions:update": "antelopejs-suppressions --update" }, "dependencies": { - "@antelopejs/interface-core": ">=0.1.1 <1.0.0", + "@antelopejs/interface-core": ">=0.5.0 <0.6.0", "@antelopejs/interface-database": ">=0.4.0 <0.5.0", "@antelopejs/interface-database-catalog": ">=0.0.3 <0.1.0", "pg": "^8.22.0" }, "devDependencies": { - "@antelopejs/core": "^1.21.0", - "@antelopejs/tooling-configs": "^0.5.8", + "@antelopejs/core": "~1.23.1", + "@antelopejs/tooling-configs": ">=0.7.0 <0.8.0", "@testcontainers/postgresql": "^12.0.4", "@types/chai": "^4.3.20", "@types/mocha": "^10.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 84417a5..c89bba3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,24 +9,24 @@ importers: .: dependencies: '@antelopejs/interface-core': - specifier: '>=0.1.1 <1.0.0' - version: 0.4.0 + specifier: '>=0.5.0 <0.6.0' + version: 0.5.1 '@antelopejs/interface-database': specifier: '>=0.4.0 <0.5.0' - version: 0.4.0(@antelopejs/interface-core@0.4.0) + version: 0.4.0(@antelopejs/interface-core@0.5.1) '@antelopejs/interface-database-catalog': specifier: '>=0.0.3 <0.1.0' - version: 0.0.3(@antelopejs/interface-core@0.4.0) + version: 0.0.3(@antelopejs/interface-core@0.5.1) pg: specifier: ^8.22.0 version: 8.22.0 devDependencies: '@antelopejs/core': - specifier: ^1.21.0 - version: 1.21.0 + specifier: ~1.23.1 + version: 1.23.1 '@antelopejs/tooling-configs': - specifier: ^0.5.8 - version: 0.5.8(eslint-plugin-perfectionist@5.11.0(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3))(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001)) + specifier: '>=0.7.0 <0.8.0' + version: 0.7.0(eslint-plugin-perfectionist@5.11.0(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3))(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001)) '@testcontainers/postgresql': specifier: ^12.0.4 version: 12.0.4 @@ -81,13 +81,13 @@ importers: packages: - '@antelopejs/core@1.21.0': - resolution: {integrity: sha512-0+qxASgc1sF8MihvGYfrAy6m3XTPcrFJeeIH69ivI0cvtYmj71cjzTeXdKghBZb4ndTMQ2IXeKbK6zxrG2w4Tw==} + '@antelopejs/core@1.23.1': + resolution: {integrity: sha512-0hTjFw5vHNwwTE6HYCvEHErKkJR9MiehE1UmY3P1M0LEky5j+TPWYcf7+Qtzp9U6ErYb+cRljHCzRaBu2pEbIw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - '@antelopejs/interface-core@0.4.0': - resolution: {integrity: sha512-IPX6dtt3KHknclN4mLOYeRYL2Odz1Pts+dtaZul62NghsBUX/0OFHD4Qhoaf+Beva4hjInbaF918ajr4Z5HVWQ==} + '@antelopejs/interface-core@0.5.1': + resolution: {integrity: sha512-ON/7TYA1yyT8UznzKi6vnwyjRU3byNE0OcFXBmf8dE/dqp8hKjeWHVyA2EUPOngmEimCLw4idZqOS5DJqMJx3g==} '@antelopejs/interface-database-catalog@0.0.3': resolution: {integrity: sha512-ZT7bZ0ycEs8VvEgNGQTGMAzKiFQC1BOYOM2f2e+vFuCN/1VPBZZFxg3XOmHClTzdW/RzX2k7lasfMyaVOUzOCA==} @@ -99,8 +99,8 @@ packages: peerDependencies: '@antelopejs/interface-core': '>=0.2.4 <1.0.0' - '@antelopejs/tooling-configs@0.5.8': - resolution: {integrity: sha512-F4q6E2HWXEF0f6MHHOCQGheRzaNkX4e8JeYI92x6KajWJIkk8HroThU8jmIaP7Q23w6fIv8fveHtyc7pJ2hQHg==} + '@antelopejs/tooling-configs@0.7.0': + resolution: {integrity: sha512-FtE+vFwTpQR1hgWWSdiylEtn8SaJ6L7B4F7TTyy97cYaj/qvpX/l5QDebJw/A/RQ/Tt1FVYtgKV+lzFFbjau7w==} engines: {node: '>=22.18.0'} hasBin: true peerDependencies: @@ -1074,6 +1074,10 @@ packages: resolution: {integrity: sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript/typescript6@6.0.2': + resolution: {integrity: sha512-mbCddXd+jm7hfx7w2YU64/Av4/NqqeG3GoRZgxPcgoTxYjhrcfJRw9ULch71SS4G+Q3bOXFhRvPqjguN0Hyp5w==} + hasBin: true + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -2813,6 +2817,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} @@ -2956,9 +2965,9 @@ packages: snapshots: - '@antelopejs/core@1.21.0': + '@antelopejs/core@1.23.1': dependencies: - '@antelopejs/interface-core': 0.4.0 + '@antelopejs/interface-core': 0.5.1 '@clack/prompts': 1.8.1 '@types/proper-lockfile': 4.1.4 commander: 13.1.0 @@ -2971,24 +2980,25 @@ snapshots: semver: 7.8.5 typescript: 5.9.3 - '@antelopejs/interface-core@0.4.0': + '@antelopejs/interface-core@0.5.1': dependencies: reflect-metadata: 0.2.2 - '@antelopejs/interface-database-catalog@0.0.3(@antelopejs/interface-core@0.4.0)': + '@antelopejs/interface-database-catalog@0.0.3(@antelopejs/interface-core@0.5.1)': dependencies: - '@antelopejs/interface-core': 0.4.0 + '@antelopejs/interface-core': 0.5.1 - '@antelopejs/interface-database@0.4.0(@antelopejs/interface-core@0.4.0)': + '@antelopejs/interface-database@0.4.0(@antelopejs/interface-core@0.5.1)': dependencies: - '@antelopejs/interface-core': 0.4.0 + '@antelopejs/interface-core': 0.5.1 - '@antelopejs/tooling-configs@0.5.8(eslint-plugin-perfectionist@5.11.0(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3))(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001))': + '@antelopejs/tooling-configs@0.7.0(eslint-plugin-perfectionist@5.11.0(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3))(knip@6.34.0)(oxfmt@0.66.0)(oxlint@1.81.0(oxlint-tsgolint@7.0.2001))': dependencies: '@oxlint/plugins': 1.81.0 + '@typescript/typescript6': 6.0.2 dts-bundle-generator: 9.5.1 minimatch: 10.2.6 - typescript: 5.9.3 + semver: 7.8.5 yaml: 2.9.1 optionalDependencies: eslint-plugin-perfectionist: 5.11.0(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3) @@ -3731,6 +3741,10 @@ snapshots: '@typescript-eslint/types': 8.69.0 eslint-visitor-keys: 5.0.1 + '@typescript/typescript6@6.0.2': + dependencies: + '@typescript/old': typescript@6.0.3 + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -5677,6 +5691,8 @@ snapshots: typescript@5.9.3: {} + typescript@6.0.3: {} + ufo@1.6.4: {} unbash@4.0.11: {} diff --git a/src/implementations/database/member.ts b/src/implementations/database/member.ts index 5f006e4..f14c93c 100644 --- a/src/implementations/database/member.ts +++ b/src/implementations/database/member.ts @@ -121,7 +121,6 @@ function IsConstantJson(value: unknown): value is ConstantJson { * never walked. The order is the order the kinds were always told apart in, which is what makes a * `ValueProxy` a proxy before it is an object. */ -// oxlint-disable-next-line anti-slop/no-unknown-parameters -- value is any caller-supplied query argument or document member (a ValueProxy, a Date, a Buffer, a nested document, any JSON), and this function is the classifier that parses it into a Member kind; a named type would only relabel unknown export function ClassifyMember(value: unknown): Member { const document: DocumentView | undefined = IsDocument(value) ? {