feat(go): PostgREST/Supabase query dialect in generated services (parity with TS #36/#56-#60) - #118
Open
cultron wants to merge 1 commit into
Open
feat(go): PostgREST/Supabase query dialect in generated services (parity with TS #36/#56-#60)#118cultron wants to merge 1 commit into
cultron wants to merge 1 commit into
Conversation
…ity with TS #36/#56-#60) Port the @apso/crud PostgREST dialect to the Go (Gin+GORM) generator so generated services accept the same PostgREST URL conventions as the TypeScript services. The incumbent nestjsx dialect is unchanged (byte-identical output; ParseQueryParams is retained and still delegates to the nestjsx parser). Generated query util (utils/query.go): - DetectDialect mirrors crud/src/dialect.ts: X-Crud-Dialect header wins (postgrest|nestjsx else 400); else param-shape (select/order or bare col=op.value => postgrest; fields/filter/join/sort/s/or/per_page => nestjsx; both => 400 ambiguous; limit/offset/page/cache neutral; default nestjsx). - PostgREST parser mirrors postgrest-request/src/postgrest-parser.ts: select=a,b (+ alias:col rename #57, + embeds rel(cols) as GORM preloads), col=op.value for eq/neq/gt/gte/lt/lte/like/ilike/in/is and not.<op>, or=(...)/and=(...) logical groups incl. nesting (#56), order=col.asc|desc[.nullsfirst|nullslast], limit/offset. Operator mapping and *->% like/ilike wildcard match the TS core. - cs/cd/ov/fts (and other advanced ops) are recognized and rejected clearly as deferred (#54), not silently mishandled. Response shaping and errors: - PostgREST path returns a bare JSON array (no envelope) via FindAllBare (#58); nestjsx keeps its {data,count,total,page,pageCount} envelope. - Unknown filter/sort/select column on the postgrest path is a *QueryError the handler maps to 400, not 500 (#60). nestjsx keeps silently dropping unknown columns. - Handler threads the X-Crud-Dialect header + query into utils.ParseQuery and branches on opts.Bare. Deferred / scoped for Go: embedded ON-clause filters (#59). The Go embed path uses GORM Preload, which has no embed-level predicate, so an rel.col= filter is treated as a root filter rather than shaping only embedded rows. select embeds still project relation columns. This is the only intentional gap vs the TS TypeORM join path. Tests (test/lib/generators/go.test.ts): assert the emitted Go for detection, operator map, deferred-op rejection, or=/and= groups, alias rename, order nulls, bare-array + offset, unknown-column 400, and unchanged nestjsx entry point. A go-build test generates a full sample service and compiles it with the real Go toolchain. npm build + the go-generator jest suite are green (46 tests). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
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
Ports the
@apso/crudPostgREST/Supabase dialect to the Go (Gin+GORM) generator, so generated services accept the same PostgREST URL conventions as our TypeScript services (@apso/crud+@apso/postgrest-request). This is the Go port of the TS dialect; the incumbent nestjsx dialect is unchanged (byte-identical output —ParseQueryParamsis retained and still delegates to the nestjsx parser).Extends (does not replace) the generated
utils/query.goand threads a dialect step through the generated handler + service.Dialect detection (mirrors
crud/src/dialect.ts)X-Crud-Dialectheader wins:postgrest|nestjsx, any other value ⇒ 400.select/orderor a barecol=op.value⇒ postgrest;fields/filter/join/sort/s/or/per_page⇒ nestjsx; both families ⇒ 400 (ambiguous);limit/offset/page/cacheare dialect-neutral; default nestjsx.oris a nestjsx-signal key, so a PostgRESTor=()group must be forced via the header (or accompany another postgrest signal without a nestjsx one).select+ortogether is an intentional 400.Operators / behaviors implemented (parity with
postgrest-parser.ts)select=a,b,alias:coloutput rename ⇒col AS alias(CLI first pivot: new command surface, architecture refactor, tests #57),::typecast stripped, embedsrel(cols)⇒ GORM preloads.col=op.valueandnot.<op>:eq, neq, gt, gte, lt, lte, like, ilike, in, is(incl.is.null/is.true/is.false,not.in, negations).like/iliketranslate the PostgREST*wildcard to SQL%and apply the pattern verbatim.or=(...)/and=(...), including nestedor(...)/and(...), ANDed with the flat column filters (Plat 1269 #56).order=col.asc|desc[.nullsfirst|nullslast]⇒ORDER BY col DIR [NULLS FIRST|LAST].limit/offset⇒ bare JSON array (no envelope), offset windows the array (feat: MCP server + CLI modernization #58); nestjsx keeps its{data,count,total,page,pageCount}envelope.*QueryError), not 500 (Feature: auto-detect codegen/schema issues from real usage and (opt-in) auto-file GitHub issues #60); nestjsx still silently drops unknown columns. Bad header / ambiguous mix / bad operator ⇒ 400.Deferred
cs,cd,ov,fts(and other advanced operators) — recognized and rejected clearly as deferred (Plat 1288 #54), never silently mishandled.Preload, which has no embed-level predicate, so anrel.col=filter is treated as a root filter rather than shaping only embedded rows.selectembeds still project relation columns. This is the only intentional gap vs the TS TypeORM join path.nestjsx unchanged
The nestjsx parsing, filter/or/sort/join handling, and envelope response are untouched.
ParseQueryParamsstill exists and delegates toparseNestjsxParams.Tests
or=/and=groups, alias rename, order nulls, bare-array + offset, unknown-column 400, and the unchanged nestjsx entry point.go buildtest generates a full sample service and compiles it with the real Go toolchain.npm run build+ the go-generator jest suite are green (46 tests; full repo suite 334 green). Verified locally with additional GORM+sqlite runtime tests (eq, or=() via header, order+limit+offset bare windowing, like wildcard, unknown-column 400) — all passing.Do not merge — left green for review.
🤖 Generated with Claude Code