feat!: require project id and move client API under /projects/{projectID}#2
Closed
jeroenrinzema wants to merge 2 commits into
Closed
feat!: require project id and move client API under /projects/{projectID}#2jeroenrinzema wants to merge 2 commits into
jeroenrinzema wants to merge 2 commits into
Conversation
…tID}
The Lunogram Client API now scopes every endpoint to a project via the
URL: /api/client/... becomes /api/client/projects/{projectID}/....
NewClient now takes a required projectID (a UUID) and returns an error if
it is empty or malformed. The project segment is injected centrally in the
transport (clientPath), so resource methods pass project-relative paths.
This is a hard, intentional breaking change with no backwards compatibility.
It depends on the corresponding platform change that requires the project
in the URL, and should merge once that ships.
Contributor
Author
|
Superseded by #3. The spec-driven SDK in #3 retargets to |
jeroenrinzema
added a commit
that referenced
this pull request
Jun 25, 2026
Migrate the SDK to spec-driven code generation, mirroring the js-sdk
template. The low-level type layer is now generated from the platform's
vendored OpenAPI spec; the hand-written facade (NewClient, functional
options, the /api/client/projects/{projectID} prefix, google/uuid
validation, Bearer auth) stays single-point and unchanged.
Layout:
- spec/client.yaml: vendored, pinned spec (see spec/SOURCE.md for the
source repo, spec path, and pinned ref). No platform release needed —
any ref is fetchable via the raw URL.
- gen/: spec-generated types (client.gen.go, DO-NOT-EDIT) via
oapi-codegen v2.7.0, wired through go:generate and a go.mod tool
dependency so `go generate` is deterministic with no separate install.
gen/types.go is a hand-written companion for the spec's x-go-type
references (pagination params), mirroring the platform's own pattern.
- conformance_test.go: asserts every facade request/response type shares
the exact JSON wire shape of its generated spec counterpart, so a spec
change surfaces as a failing test rather than a silent runtime mismatch.
CI:
- ci.yml: regenerate from the spec and fail on drift (git diff gen), then
build, vet, gofmt, and test.
- spec-sync.yml: weekly cron + manual; re-fetch the spec at the pin in
spec/SOURCE.md, regenerate, and open a PR on change.
The public API is unchanged from #2; the ! marks the build-system and
dependency shift (go.mod tool directive, generated low-level layer).
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.
Breaking change
The Lunogram Client API now requires the project UUID as a path segment.
Every authenticated endpoint moves from
/api/client/...to/api/client/projects/{projectID}/.... Auth is unchanged (same API key/token);only the URL gains the project. This is a hard cut with no backwards
compatibility.
To match, the SDK now takes the project ID as a required construction
parameter. Callers supply it once when building the client; the SDK injects
/projects/{projectID}into every Client API path automatically. You never passthe project per call.
Before / after
NewClient(apiKey, projectID string, opts ...Option) (*Client, error)validatesthat
projectIDis a non-empty UUID and returns an error otherwise. Functionaloptions (
WithBaseURL,WithHTTPClient,WithTimeout) are unchanged.Path changes (old → new)
All Client API endpoints implemented by this SDK:
/api/client/users/api/client/projects/{projectID}/users/api/client/users/events/api/client/projects/{projectID}/users/events/api/client/users/scheduled/api/client/projects/{projectID}/users/scheduled/api/client/organizations/api/client/projects/{projectID}/organizations/api/client/organizations/users/api/client/projects/{projectID}/organizations/users/api/client/organizations/events/api/client/projects/{projectID}/organizations/events/api/client/organizations/scheduled/api/client/projects/{projectID}/organizations/scheduledThe prefix is injected in one place (
Client.clientPathinclient.go), soresource methods now pass project-relative paths (e.g.
/users). The broaderplatform contract also moves inbox/devices/push/auth-methods endpoints under
/projects/{projectID}; those are not currently implemented in this SDK, so noSDK code references them.
How it's wired
Clientgains aprojectIDfield, set and validated inNewClient.clientPath(path)returns"/api/client/projects/" + projectID + path; thetransport (
do) builds the URL viac.baseURL + c.clientPath(path).users.go,organizations.go,scheduled.go) passproject-relative paths — no per-call project handling.
Files touched
client.go— requiredprojectID, UUID validation,clientPath, transport.users.go,organizations.go,scheduled.go— project-relative paths.integration_test.go— construct via new signature; read/skip onLUNOGRAM_PROJECT_ID.README.md— project-scoping docs, updated quick start and option snippets.Validation
go build ./...,go vet ./...,gofmt -l .(clean), andgo test ./...allpass. Integration tests skip without live-API env vars, as before.
Dependency
This depends on the corresponding platform change that requires the project in
the Client API URL. It should merge once that ships.