DX overhaul, gacela 1.19 / router 0.13 upgrade, CORS + LUD-06 fix, tooling#25
Merged
Merged
Conversation
Developer-experience pass across the library plus the framework upgrade
that the new gacela-router 0.13 release unblocks.
DX / correctness:
- Build LNURL-pay metadata via a shared LnurlPayMetadata value object using
json_encode instead of string concatenation (a quote in the description no
longer produces invalid JSON); removes duplication between CallbackUrl and
InvoiceGenerator.
- Wire HttpApi to catch Symfony transport/HTTP errors and JsonException and
return null, so the backend surfaces a clean "unreachable" error instead of
leaking a stack trace (the graceful path was previously dead code).
- Remove dump($e) from the controller; normalize error responses to the LNURL
{status, reason} shape.
- Add a BackendType enum and clear errors in LightningConfig::addBackendsFile
(missing file, invalid JSON, missing/unknown type); add addBackend() to
register backends programmatically without a JSON file.
- Centralize app-config keys in ConfigKey so the config writer/reader cannot
drift; fix the nonsensical REQUEST_URI receiver default.
- Add return-shape docblocks to the facade/generator for IDE autocomplete.
- Rename the misleadingly named nostr.json backends file to backends.json.
- Rewrite the README (install, config, HTTP API, programmatic use, reference).
Gacela upgrade (gacela 1.19, router 0.13, container 0.10, phpstan-ext 0.4):
- Add SendableRange::__set_state for gacela's var_export'd merged-config cache.
- Add generic @extends params for the now-templated gacela base classes.
- Swap deprecated DocBlockResolverAwareTrait for ServiceResolverAwareTrait.
Tests: add coverage for metadata escaping, the backend-type enum, programmatic
addBackend, and the hardened backends-file error paths.
LNURL-pay (LUD-06) mandates the callback response carry the bolt11 invoice in a field named 'pr'. The response keyed it 'bolt11', so spec-compliant wallets saw the invoice as missing. Rename the output key to 'pr' (the internal InvoiceTransfer property and the LNbits API field stay 'bolt11').
Use gacela-router 0.13's new middleware support:
- CorsMiddleware sets Access-Control-Allow-Origin on every response and
answers OPTIONS preflight directly, so browser-based wallets can call the
LNURL endpoints. The route is registered for GET and OPTIONS so preflight
reaches the middleware.
- InvoiceExceptionHandler is registered as the router's global handler for
Exception, rendering any uncaught error as the LNURL {status, reason}
object. The controller no longer needs its own try/catch.
Tests: unit-cover the middleware's preflight short-circuit / delegation and
the handler's error rendering (process-isolated for the header() calls).
- PHPUnit 9.6 -> 10.5: migrated phpunit.xml to the 10.x schema (coverage <source>, deprecated attributes removed, cache directory added). Tests needed no code changes. - PHPStan 1.12 -> 2.2: clean at level max, no code changes required. - Rector 1.2 -> 2.0: applied its new suggestions (narrow a test fake's return type, sort named arguments to constructor-declaration order). - Remove symfony/var-dumper: it only backed the dump() call removed earlier.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A developer-experience pass over the library, plus the gacela stack upgrade that the new
gacela-project/router0.13 release unblocks, a LUD-06 wire-format fix, router middleware, and modernized dev tooling.Reviewed commit-by-commit for a clean history.
1. DX overhaul (
485e954)LnurlPayMetadatavalue object usingjson_encodeinstead of string concatenation — a quote in the description no longer produces invalid JSON. Removes duplication betweenCallbackUrlandInvoiceGenerator.HttpApinow catches Symfony transport/HTTP errors +JsonExceptionand returnsnull, so the backend surfaces a clean "unreachable" error instead of leaking a stack trace (that graceful path was previously dead code).dump($e)from the controller; normalize errors to the LNURL{status, reason}shape.BackendTypeenum and clear errors inaddBackendsFile(missing file, invalid JSON, missing/unknown type); addaddBackend()to register backends programmatically without a JSON file.ConfigKeyso the config writer/reader can't drift; fix the nonsensicalREQUEST_URIreceiver default.nostr.jsonbackends file tobackends.json.2. LUD-06
prkey fix (d5fc11e)LUD-06 mandates the callback response carry the bolt11 invoice under a field named
pr. The response keyed itbolt11, so spec-compliant wallets saw the invoice as missing. Renamed the output key topr(the internalInvoiceTransferproperty and the LNbits API field staybolt11).3. gacela 1.19 / router 0.13 upgrade (
485e954)gacela 1.9.1 -> 1.19,router 0.12.1 -> 0.13,container 0.6 -> 0.10,phpstan-extension 0.3 -> 0.4. Required fixes (caught by a live server smoke test, not the unit suite):SendableRange::__set_statefor gacela'svar_export'd merged-config file cache.@extendsparams for the now-templated gacela base classes.DocBlockResolverAwareTrait->ServiceResolverAwareTrait(deprecated).4. CORS middleware + global exception handler (
f2bca2d)Uses router 0.13's new middleware support:
CorsMiddlewaresetsAccess-Control-Allow-Origin: *on every response and answersOPTIONSpreflight directly (route registered forGET+OPTIONS).InvoiceExceptionHandlerregistered as the router's globalExceptionhandler, rendering any uncaught error as the LNURL error object — the controller no longer needs a try/catch.5. Tooling modernization (
66e8cdd)PHPUnit
9.6 -> 10.5(config migrated to the 10.x schema), PHPStan1.12 -> 2.2(clean at level max), Rector1.2 -> 2.0(applied its new suggestions). Removed now-unusedsymfony/var-dumper.Testing
composer test-allgreen: psalm (98.9% type coverage), phpstan 2 level max, PHPUnit 10 (26 tests), rector 2 — all clean.pr-keyed invoice,Backend "LnBits" unreachablepath, CORS header on GET,OPTIONSpreflight (200), and the global error handler — 0 fatals.Notes
gacela-project/gacelaconstraint is^1.19; the upgrade depended ongacela-project/router0.13 (which requirescontainer ^0.10).nostr.json->backends.jsonrename and thebolt11->prresponse key.