Comparing 3.20.0...3.21.0 · NpgsqlRest/NpgsqlRest · GitHub
Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NpgsqlRest/NpgsqlRest
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.20.0
Choose a base ref
...
head repository: NpgsqlRest/NpgsqlRest
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.21.0
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 8 commits
  • 55 files changed
  • 1 contributor

Commits on Jul 11, 2026

  1. fix(cli): --validate must not crash on a missing required env var

    Also for the 3.20.0 release:
    - docs: update README.md (Dart client, React Query hooks, MCP tool
      schemas/llms.txt, HTTP QUERY, OpenAPI 3.0/3.1, test count 2,484)
    - docs: update .claude/skills/npgsqlrest (SKILL.md, annotations-reference.md,
      regenerated configuration-reference.jsonc)
    - docs: add QUERY to the http/proxy/proxy_out --annotations syntax strings
    - test: fix WireMock port collision (SqlFileHttpClientTypeFixture 50954 -> 50956)
      that intermittently failed the parallel Proxy fixtures
    vbilopav committed Jul 11, 2026
    Configuration menu
    Copy the full SHA
    d4d5e38 View commit details
    Browse the repository at this point in the history
  2. fix(cli): add missing single, void, skip, returns, mcp, openapi entri…

    …es to --annotations reference
    
    bump version 3.20.1
    vbilopav committed Jul 11, 2026
    Configuration menu
    Copy the full SHA
    825ac01 View commit details
    Browse the repository at this point in the history
  3. feat(config): env var fallback values ({!NAME:fallback}) unified acro…

    …ss config, static files and annotations
    
    Completes the placeholder grammar with a third form, applied with the same
    rules in all three substitution systems:
    
      {NAME}           - optional: replaced when set, left untouched otherwise
      {!NAME}          - required: replaced when set, startup fails otherwise
      {!NAME:fallback} - replaced when set, otherwise the literal fallback text
                         is used - never fails
    
    The fallback starts after the first ':' and runs to the closing brace (may
    contain ':', not '}'). Only the bang form takes a fallback: a plain
    {NAME:...} is never treated as an env placeholder, because the shipped
    defaults themselves contain brace-colon content that naive parsing would
    destroy - Serilog OutputTemplate ({Timestamp:HH:mm:ss.fff}), the
    ClientAnalyticsData JS object, HtmlHeader CSS ({border:1px...}) and the
    TsClient ErrorType TS type.
    
    The default connection string now uses fallbacks matching the standard
    PostgreSQL defaults, with only the database name required:
    
      Host={!PGHOST:localhost};Port={!PGPORT:5432};Database={!PGDATABASE};
      Username={!PGUSER:postgres};Password={!PGPASSWORD:postgres}
    
    With no environment configured, startup fails with exactly one actionable
    error naming PGDATABASE; setting only PGDATABASE connects to a stock local
    PostgreSQL. Verified end-to-end with --validate in both scenarios.
    
    Per system:
    
    - Config (Config.ResolveEnv): the fallback resolves in the non-throwing
      --config/--validate mode too (it IS the effective value), while an unset
      {!NAME} without fallback still keeps its literal placeholder there.
    - Static files (StaticFiles:ParseContentOptions:AvailableEnvVars) and
      annotations/HTTP custom types (NpgsqlRest:AvailableEnvVars): resolution
      order env value -> configured default -> inline fallback -> empty; also
      applies to listed claims absent on the request, and a null routine
      parameter now yields the inline fallback ({!_plan:free} -> "free").
      Unlisted names stay literal in every form - the strict forms never widen
      the allowlist (and never consume CSS/JS brace content).
    - Formatter.TryResolveToken keys the strict forms off a '!NAME' dictionary
      entry registered only for names that resolved to a real value; the client
      registers these automatically (Builder.GetSubstitutionEnvVars,
      DefaultResponseParser, endpoint replacements dict). Library users
      populating SubstitutionEnvironmentVariables directly register them
      themselves (documented on the property).
    - The build-time unknown-placeholder warning validates the name part of
      {!name} / {!name:fallback} tokens, so typos are still caught.
    
    Suite green: 2516 tests (33 new). Skill reference regenerated from
    --config (connection string kept in template form - --config resolves
    fallbacks against the generating environment).
    
    Changelog: v3.20.1 Features section.
    vbilopav committed Jul 11, 2026
    Configuration menu
    Copy the full SHA
    d095ef7 View commit details
    Browse the repository at this point in the history
  4. feat(config): load ./.env by default (Config:EnvFile), real environme…

    …nt always wins
    
    The default configuration now ships with "Config:EnvFile": "./.env".
    Combined with the fallback connection string, the minimal setup is a
    single file: create .env next to the configuration with one line,
    PGDATABASE=mydb, and run npgsqlrest.
    
    Behavior:
    
    - Variables already present in the process environment always win - the
      file only fills in missing ones, matching the cross-platform dotenv
      convention (Node dotenv, python-dotenv, godotenv, dotenvy, Compose).
      BEHAVIOR CHANGE for existing EnvFile users: before 3.20.1 the file
      overwrote the environment. Within the file a repeated key keeps its
      last value.
    - The default ./.env (relative to the working directory) is optional:
      when absent, startup logs an information message with the mute remedy
      (set Config:EnvFile to null), never a warning - clean production
      deployments stay warning-free. A missing CUSTOM path logs a warning
      (an explicitly named file that is not there is a misconfiguration).
    - A successful load logs how many variables the file contributed and how
      many were kept from the real environment.
    - The "./.env" default lives only in the shipped appsettings.json, not
      in code: configurations that omit the EnvFile key keep loading nothing
      (no upgrade surprise for minimal configs, --config output stays
      truthful, "EnvFile": null still disables everything). ConfigDefaults
      deliberately stays null for the same reason.
    
    The file loads during Config.Build, before logging is configured, so the
    outcome is recorded on Config.EnvFileState (path, loaded/skipped counts)
    and logged by Program once the logger exists - the same deferred pattern
    ValidateConfigKeys uses.
    
    7 new tests (ConfigTests/EnvFileTests.cs); suite 2523 green. Verified
    end-to-end: default config + one-line .env starts the server; a real
    env var beats the file's value; both log lines render as designed.
    
    Changelog: v3.20.1 Features section. Skill reference regenerated.
    vbilopav committed Jul 11, 2026
    Configuration menu
    Copy the full SHA
    0ca6409 View commit details
    Browse the repository at this point in the history

Commits on Jul 12, 2026

  1. feat(cli): --install-skill [global] - install the Claude Code skill f…

    …rom the binary
    
    New command replacing the platform-specific curl/Invoke-WebRequest
    installation instructions:
    
      npgsqlrest --install-skill          # ./.claude/skills/npgsqlrest (project)
      npgsqlrest --install-skill global   # ~/.claude/skills/npgsqlrest (user)
    
    Behavior:
    
    - Downloads the three skill files (SKILL.md, annotations-reference.md,
      configuration-reference.jsonc) from the release branch matching the
      running version (assembly Major.Minor.Build, e.g. "3.20.1") - release
      refs are branches in this repository - so the installed skill always
      matches the installed binary. Falls back to master with a printed note
      when the version branch is not available.
    - All files come from the same git ref and are downloaded fully into
      memory before anything is written, so a network failure never leaves a
      partial install behind. Failure exits 1.
    - Project scope prints a reminder to commit the folder so the whole team
      (and CI agents) get the skill; upgrading is re-running the command.
    - The download base is overridable via NPGSQLREST_SKILL_BASE_URL (tests,
      enterprise mirrors) with the same {base}/{ref}/path/{file} layout.
    - Global scope resolves the user profile via SpecialFolder.UserProfile
      (HOME on unix, USERPROFILE on Windows).
    
    5 new tests (CliTests/InstallSkillTests.cs) run the real binary against
    a local Kestrel stand-in for raw.githubusercontent.com: version-branch
    install, master fallback, global scope with a fake HOME, unreachable
    server (exit 1, no partial files), unknown-scope usage error. Suite 2528
    green. Verified against real GitHub: installs from the live 3.20.1
    branch.
    
    --help documents both forms; SKILL.md notes the command as the fix for
    version drift. Changelog: v3.20.1 Features section.
    vbilopav committed Jul 12, 2026
    Configuration menu
    Copy the full SHA
    88e954c View commit details
    Browse the repository at this point in the history
  2. feat(cli): new ANSI-block logo with two-tone colors and tagline

    Replaces the generic figlet-slant banner with a two-block composition:
    NPGSQL in ANSI-shadow blocks (cyan) with REST offset beneath (dark
    yellow) and a dim tagline - "PostgreSQL -> REST, no code, just SQL".
    
    Logo() now sets Console.OutputEncoding to UTF-8 (guarded), so the block
    glyphs render correctly on legacy Windows consoles with OEM codepages.
    The logo only prints on interactive CLI commands (--help, --version,
    --install-skill, ...), never in server logs.
    vbilopav committed Jul 12, 2026
    Configuration menu
    Copy the full SHA
    8d45155 View commit details
    Browse the repository at this point in the history
  3. feat(multi-connection): per-connection routine discovery (ReadMetadat…

    …aFromConnections), routed endpoint verification (VerifyRoutedEndpoints), connection routing fixes
    
    Routine metadata was always discovered on a SINGLE connection while the
    `connection` annotation only changed where a request executes - assuming
    every named connection has identical routine metadata. True for replicas
    and shards; wrong for OLTP + OLAP/DW setups, which had to duplicate
    routines on the default database just to get them discovered.
    
    NpgsqlRest:RoutineOptions:ReadMetadataFromConnections (string[]):
    
    - Routine metadata is read from EACH listed connection (one RoutineSource
      per name; all other RoutineOptions settings and global filters shared).
    - Endpoints EXECUTE on the connection they were discovered from - an
      explicit `connection` annotation still wins. Replace semantics: include
      the main connection's name to keep serving its routines.
    - Implicitly enables multiple connections (no UseMultipleConnections
      needed; Information log notes it). Unknown names fail startup naming
      the available ones. Null/absent = previous single-discovery behavior.
    - Library level: IEndpointSource gains ConnectionName as a default
      interface member (external sources keep compiling), settable on
      RoutineSource; CreateAndOpenSourceConnection takes an optional
      per-source connection name overriding MetadataQueryConnectionName.
    - CompositeTypeCache is now keyed per database with reload-on-switch -
      previously a one-time init guard made a second database's composite
      types a silent no-op. Safe: sources run sequentially and every cache
      consumer is build-time (metadata baked into TypeDescriptors).
    - Cross-source path collisions warn at startup naming both sources and
      connections (same-source collisions remain the silent function-overload
      mechanism); later source wins.
    - Watch mode fingerprints each RoutineSource on ITS discovery connection
      (one poller per distinct target) instead of always the primary.
    
    NpgsqlRest:RoutineOptions:VerifyRoutedEndpoints (None|Warn|Fail):
    
    - Opt-in startup check for endpoints routed to a different connection
      than they were discovered on: one batched to_regprocedure/to_regclass
      round-trip per distinct target; Warn logs each missing routine naming
      the connection and endpoints, Fail stops startup with an aggregated
      error. Checks CONTENT - connectivity remains
      ConnectionSettings:TestConnectionStrings' job.
    
    Fixes:
    
    - `connection <main-name>` now resolves (main connection registered in
      the routable dictionaries under its real name, sharing the same pool
      as unrouted requests); MetadataQueryConnectionName accepts the main
      name too (previously a startup throw).
    - Multi-host main no longer builds a duplicate pool for the "_default"
      alias - same instance as the main data source.
    - The `connection=name` annotation form is validated (was none - the
      guard was commented out); both parse forms share one check that also
      consults DataSources, so multi-host-only names stop false-warning.
    - Client connection dictionaries are case-insensitive, matching
      IConfiguration key semantics (space-form annotations lowercase names).
    
    12 new tests against REAL second databases with different schemas
    (Database.CreateSecondDatabase): per-connection discovery/execution,
    annotation override, collision last-wins + warning, per-database
    composite shapes, Warn/Fail verification, per-source resolution. Suite
    2540 green. E2E verified with the built client: two databases served
    with zero annotations, implicit enablement, main-name routing, Warn/Fail
    modes, --watch restarting on alt-database changes.
    
    Also: version 3.20.1 was never released - its changelog (env var
    fallbacks, EnvFile default, --install-skill, new logo) is folded into
    changelog/v3.21.0.md and every 3.20.1 reference in code, tests, and the
    skill now reads 3.21.0. Version bump to 3.21.0 follows separately.
    vbilopav committed Jul 12, 2026
    Configuration menu
    Copy the full SHA
    1b64e53 View commit details
    Browse the repository at this point in the history
  4. bump version 3.21.0

    vbilopav committed Jul 12, 2026
    Configuration menu
    Copy the full SHA
    bb718f4 View commit details
    Browse the repository at this point in the history
Loading