Skip to content

feat(search-api-server): serve the search API as a bootable process and Docker image#646

Open
ddeboer wants to merge 2 commits into
mainfrom
feat/search-graphql-docker
Open

feat(search-api-server): serve the search API as a bootable process and Docker image#646
ddeboer wants to merge 2 commits into
mainfrom
feat/search-graphql-docker

Conversation

@ddeboer

@ddeboer ddeboer commented Jul 23, 2026

Copy link
Copy Markdown
Member

Part of #600 (layer 3 of 3: the prebuilt Docker image; the handler, layer 2, shipped in #637).

Adds @lde/search-api-server: the served search API as a bootable process and prebuilt Docker image (ghcr.io/ldelements/search-api-server) – mount a schema-declaration module, set TYPESENSE_* env vars, get /graphql (POST execution, self-contained playground, ?sdl) plus /health, with CORS and depth/cost limits on by default. The composition layer that binds the deliberately engine-agnostic @lde/search-api-graphql handler to @lde/search-typesense.

Design (ADR 15)

  • Schema input: a plain-data declaration module, not SHACL. Batteries-included served GraphQL search API + self-contained playground #600 assumed mounted SHACL + search: definitions, but that generator is GraphQL search API #495’s still-open scope. The mount is instead an .mjs default-exporting SearchType declarations (validated at boot by searchSchema() – the “declarations built outside TypeScript” path the runtime validation exists for), because a mounted module cannot resolve bare imports anyway. When GraphQL search API #495 lands, mounted SHACL becomes a second source for the same schema.
  • A separate package, because a Typesense-bound server cannot live in @lde/search-api-graphql without breaking its engine-agnosticism.
  • The image installs the published package from npm instead of Docker-building the workspace: a few-line Dockerfile, and each image corresponds one-to-one to a provenance-attested npm version. The new docker.yml workflow triggers on the package’s release tag, waits for the npm publish (the release run tags before it publishes), then pushes :<version> and :latest to ghcr.
  • Boot-or-fail: schema validation, engine collection resolution and config problems all fail the boot with a diagnosis (config reports every problem in one error), never the first query.

Also

  • feat(search): validateSearchType now rejects an unknown field kind (new unknown-kind issue reason). Previously a typo’d kind in a plain-JS declaration passed every kind-dependent rule vacuously – exactly the path the mounted schema module relies on.

Acceptance criteria covered (of #600)

After merge

@lde/search-api-server is new on npm: the first version needs the manual Trusted-Publishing bootstrap before the release run and the Docker workflow can succeed.

- validateSearchType silently accepted a kind outside the FieldKind union:
  every kind-dependent rule passed vacuously, deferring the failure to
  whatever consumer read the declaration first
- guards the plain-JS declaration path (a mounted schema module, a SHACL
  generator) that the runtime validation exists for
- adds the 'unknown-kind' issue reason
@ddeboer
ddeboer force-pushed the feat/search-graphql-docker branch from 9fa0a8e to 1a3a7af Compare July 23, 2026 14:01
…nd Docker image

- new composition package binding the engine-agnostic search-api-graphql
  handler to a Typesense engine: environment config, a mounted plain-data
  schema-declaration module (validated at boot), and a node:http server
  answering /graphql, /health and a root redirect
- the search-api-server bin boots from environment variables alone and
  reports every configuration problem in one error
- Dockerfile installs the published package from npm, so each image
  corresponds to a provenance-attested version; the Docker workflow builds
  and pushes ghcr.io/ldelements/search-api-server on each release tag,
  waiting for the npm publish the release run does after tagging
- recorded as ADR 15
@ddeboer
ddeboer force-pushed the feat/search-graphql-docker branch from 1a3a7af to 41e2650 Compare July 23, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant