Files
oxc-project__oxc/napi/transform-relay/README.md
Boshen 1c4f519e36 feat(napi): add Relay transform plugin (#25503)
## What

Ports the Relay `graphql` tagged template transform (babel-plugin-relay / swc_relay) as an individual napi transform, per #24914:

- **`crates/oxc_relay`** — the core transform as its own crate (modeled on `oxc_react_compiler`): replaces `graphql` tagged templates with references to relay-compiler artifacts. Definition names are extracted textually like `swc_relay` (equivalent to `\b(fragment|mutation|query|subscription)\s+(\w+)` with `#` comments stripped; hand-rolled scanner, no regex dependency).
- **`napi/transform-relay`** (`oxc-transform-relay`) — standalone napi package copied from the `napi/transform-react` template: parse → semantic → relay traverse → codegen. Only `graphql` tags are rewritten; TypeScript/JSX syntax is preserved untouched, so the output composes with any downstream toolchain.

## Options

| option | default | behavior |
|---|---|---|
| `artifactDirectory` | unset | when set, the import path is computed lexically relative to the transformed file (babel-plugin-relay `getRelativeImportPath` semantics — swc emits absolute paths instead); unset → `./__generated__/` next to the file |
| `language` | `javascript` | `typescript` imports `Name.graphql.ts`, otherwise `Name.graphql.js` |
| `eagerEsModules` | `true` | hoisted default imports (babel-plugin-relay ≥ v17 parity); `false` emits inline `require()` (`@swc/plugin-relay` / Next.js behavior) |

A `graphql` tag with no extractable definition name produces an error diagnostic (babel throws; swc silently skips).

Not supported, documented in both READMEs: dev-mode artifact hash validation, `jsModuleFormat: "haste"`, `isDevVariableName`, swc's Next.js-specific `projects`/`pagesDir`, and GraphQL document validation.

closes #24914

---

Implemented with Claude Code.
2026-08-13 13:56:01 +00:00

49 lines
2.3 KiB
Markdown

# Oxc Relay Transform
Native Node.js bindings for Oxc's Rust port of the Relay transform
([babel-plugin-relay](https://github.com/facebook/relay/tree/main/packages/babel-plugin-relay) /
[@swc/plugin-relay](https://github.com/swc-project/plugins/tree/main/packages/relay)).
The API follows `oxc-transform`: pass a filename, source text, and optional
options to either `transformSync` or `transform`. `graphql` tagged template
expressions are replaced with references to the artifact files generated by
`relay-compiler`; everything else — including TypeScript and JSX syntax — is
preserved untouched, so the output composes with any downstream toolchain.
```javascript
import { transformSync } from "oxc-transform-relay";
const result = transformSync("src/Component.tsx", "const data = graphql`query FooQuery { id }`;");
console.log(result.code);
// import _FooQuery from "./__generated__/FooQuery.graphql.js";
// const data = _FooQuery;
```
`errors` contains every diagnostic reported by parsing and the transform; when
it is non-empty, `code` is empty.
## Options
- `artifactDirectory` — directory `relay-compiler` emits all artifacts to (its
`artifactDirectory` setting). When set, artifacts are imported via a relative
path computed lexically from the file being transformed, so pass the filename
and directory either both absolute or both relative to the same base
directory. When unset, artifacts are imported from the `__generated__`
directory next to the file being transformed.
- `language` — `"typescript"`, `"javascript"` (default), or `"flow"`. Artifacts
are imported as `Name.graphql.ts` for `"typescript"` and `Name.graphql.js`
otherwise.
- `eagerEsModules` — emit a hoisted default import per `graphql` tag (default,
matching `babel-plugin-relay` since Relay v17) instead of an inline
`require()` call (`@swc/plugin-relay` and Next.js behavior).
- `lang`, `sourceType`, `sourcemap` — configure the surrounding Oxc
parse/codegen pipeline, as in `oxc-transform`.
## Limitations
Compared to `babel-plugin-relay`: no development-mode artifact hash validation,
no `jsModuleFormat: "haste"`, no `isDevVariableName`, and the GraphQL definition
name is extracted textually (like `@swc/plugin-relay`) rather than by parsing
the document, so documents are not validated.