Back to Woocommerce

GraphQL Schema Surface

plugins/woocommerce/src/Api/Infrastructure/Schema/README.md

10.9.04.8 KB
Original Source

GraphQL Schema Surface

This directory is the sole point of contact between autogenerated GraphQL code and the underlying GraphQL engine (currently webonyx/graphql-php, renamespaced under Automattic\WooCommerce\Vendor\GraphQL\*).

Why it exists

The dual-code API architecture treats the GraphQL engine as an implementation detail: given a set of code-API classes under src/Api/, ApiBuilder regenerates the autogenerated tree, and switching engines should be a matter of updating templates and regenerating. That contract only holds as long as the autogenerated output never references engine-specific symbols directly.

WooCommerce plugins that reuse this infrastructure commit their autogenerated trees to their own repos. If those trees imported from Automattic\WooCommerce\Vendor\GraphQL\*, an engine switch in WooCommerce would break every already-committed plugin. Routing every engine reference through this namespace prevents that: the generator emits imports from Automattic\WooCommerce\Api\Infrastructure\Schema\* only, and the classes here translate to whichever engine is current.

What's in here

Every symbol a generated resolver, type, or root-type class can touch at runtime:

SymbolUsed by generated code as
SchemaRoot schema object constructed in each autogenerated GraphQLController::build_schema().
ObjectTypeOutput types, pagination connection/edge types, root Query/Mutation, scalar-result wrappers.
InputObjectTypeInput types.
EnumTypeEnums.
InterfaceTypeInterface types.
CustomScalarTypeCustom scalars.
TypeStatic facade: int(), string(), boolean(), float(), id(), nonNull($inner), listOf($inner).
ErrorThrown directly from resolver code when surfacing a GraphQL-spec error (e.g. the UNAUTHORIZED error in authorize()-backed resolvers).
ResolveInfoFourth-parameter type hint on every resolver's resolve() method. Registered via class_alias in aliases.php.
AST\StringValueNodeReferenced via instanceof inside custom scalar parseLiteral() callbacks. Registered via class_alias in aliases.php.

Three implementation patterns

  • Subclass (Schema, ObjectType, InputObjectType, EnumType, InterfaceType, CustomScalarType, Error) — extends the webonyx class with an empty body. Today the subclass is a no-op indirection; in a future migration the constructor would translate the webonyx-shaped config array into whatever the new engine expects. Webonyx accepts subclasses of its own types wherever it accepts the parent, so there's no runtime friction today.
  • Static facade (Type) — delegates each static method to the webonyx equivalent. Return types are intentionally omitted so a future migration can change the concrete return class without breaking callers.
  • Class alias (ResolveInfo, AST\StringValueNode) — used when the engine itself constructs the instances and hands them to resolver code. Subclassing doesn't help because the engine creates the parent class directly. The aliases are registered eagerly in aliases.php, wired in via composer.json's autoload.files entry so they run at every boot (plain Composer autoload and the Jetpack autoloader both honour this list). A future engine switch replaces the alias with a real class whose public shape matches what generated code expects.

Rules

  • No implementation logic in the subclasses. They exist to be stable FQCNs, nothing more. Behaviour that would diverge from the webonyx parent is engine-specific and belongs in a per-engine adapter, not in the surface.
  • Generated code references this namespace only, never Vendor\GraphQL\*. If a template needs a webonyx symbol that isn't here, add it here first.
  • Versioning is implicit in the namespace. If a future change would break already-committed plugin code, add a sibling namespace (e.g. Api\Infrastructure\Schema\V2) and teach ApiBuilder to emit against it; keep the current surface until the last dependent plugin has migrated.

Adding a new symbol

  1. Add a subclass / facade method / alias file in the matching style.
  2. Update the template that needs it to import from this namespace.
  3. Regenerate core (pnpm build:api) and confirm the Autogenerated/ diff is imports-only.
  4. Add a row to the table above.

Engine migration checklist

If WooCommerce switches off webonyx, the changes localized to this directory are:

  1. Each subclass's constructor accepts the webonyx-shaped config array and translates internally to the new engine's shape.
  2. Each class alias becomes a real class whose public members mirror what generated code accesses.
  3. Type's static methods return the new engine's equivalents.

Generated code already committed to plugin repos keeps working without the plugins having to regenerate.