mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
1c4f519e36
## 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.
72 lines
2.6 KiB
Rust
72 lines
2.6 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use napi_derive::napi;
|
|
|
|
use oxc::diagnostics::OxcDiagnostic;
|
|
use oxc_relay::{RelayLanguage, RelayOptions};
|
|
|
|
/// Options for the Relay transform.
|
|
///
|
|
/// `lang`, `sourceType`, and `sourcemap` configure the surrounding Oxc
|
|
/// parse/codegen pipeline; the remaining fields mirror the options of
|
|
/// `babel-plugin-relay` / `@swc/plugin-relay`.
|
|
#[napi(object)]
|
|
#[derive(Default, Debug)]
|
|
pub struct TransformOptions {
|
|
/// Treat the source as `js`, `jsx`, `ts`, `tsx`, or `dts`.
|
|
#[napi(ts_type = "'js' | 'jsx' | 'ts' | 'tsx' | 'dts'")]
|
|
pub lang: Option<String>,
|
|
|
|
/// Treat the source as script, module, CommonJS, or infer it from syntax.
|
|
#[napi(ts_type = "'script' | 'module' | 'commonjs' | 'unambiguous'")]
|
|
pub source_type: Option<String>,
|
|
|
|
/// Generate a source map.
|
|
///
|
|
/// @default false
|
|
pub sourcemap: Option<bool>,
|
|
|
|
/// Directory `relay-compiler` emits all artifacts to (its
|
|
/// `artifactDirectory` setting). When set, artifacts are imported via a
|
|
/// relative path from the file being transformed to this directory; the
|
|
/// path is computed lexically, so both must either be absolute or relative
|
|
/// to the same base directory. When unset, artifacts are imported from the
|
|
/// `__generated__` directory next to the file being transformed.
|
|
pub artifact_directory: Option<String>,
|
|
|
|
/// Artifact language, determining the imported file extension:
|
|
/// `Name.graphql.ts` for `typescript`, `Name.graphql.js` otherwise.
|
|
///
|
|
/// @default 'javascript'
|
|
#[napi(ts_type = "'typescript' | 'javascript' | 'flow'")]
|
|
pub language: Option<String>,
|
|
|
|
/// Emit a hoisted default import per `graphql` tag instead of an inline
|
|
/// `require()` call.
|
|
///
|
|
/// Defaults to `true`, matching `babel-plugin-relay` since Relay v17.
|
|
/// `@swc/plugin-relay` and Next.js default to `false`.
|
|
///
|
|
/// @default true
|
|
pub eager_es_modules: Option<bool>,
|
|
}
|
|
|
|
impl TransformOptions {
|
|
pub(crate) fn resolve(self) -> Result<RelayOptions, OxcDiagnostic> {
|
|
let language = match self.language.as_deref() {
|
|
None => RelayLanguage::default(),
|
|
Some("typescript") => RelayLanguage::Typescript,
|
|
Some("javascript") => RelayLanguage::Javascript,
|
|
Some("flow") => RelayLanguage::Flow,
|
|
Some(value) => {
|
|
return Err(OxcDiagnostic::error(format!("Invalid `language` option: `{value}`.")));
|
|
}
|
|
};
|
|
Ok(RelayOptions {
|
|
artifact_directory: self.artifact_directory.map(PathBuf::from),
|
|
language,
|
|
eager_es_modules: self.eager_es_modules.unwrap_or(true),
|
|
})
|
|
}
|
|
}
|