diff options
author | 2023-05-31 19:51:08 -0700 | |
---|---|---|
committer | 2023-05-31 19:51:08 -0700 | |
commit | 176fade220ccc254e5ad822c3bd211023e961074 (patch) | |
tree | 219fd3b10b97611aef5c0b296ebbfca4dddc16e8 | |
parent | 110d0752f333e4c32c9226e4a94e93f18837f9c7 (diff) | |
download | bun-176fade220ccc254e5ad822c3bd211023e961074.tar.gz bun-176fade220ccc254e5ad822c3bd211023e961074.tar.zst bun-176fade220ccc254e5ad822c3bd211023e961074.zip |
Remove bun-macro-relay and update docs (#3145)
* Update macro docs
* Remove bun-macro-relay
-rw-r--r-- | docs/bundler/macros.md | 57 | ||||
-rw-r--r-- | packages/bun-macro-relay/README.md | 123 | ||||
-rw-r--r-- | packages/bun-macro-relay/__generated__/FooOperation.graphql.ts | 3 | ||||
-rw-r--r-- | packages/bun-macro-relay/bun-macro-relay.tsx | 79 | ||||
-rwxr-xr-x | packages/bun-macro-relay/bun.lockb | bin | 1166 -> 0 bytes | |||
-rw-r--r-- | packages/bun-macro-relay/package.json | 15 | ||||
-rw-r--r-- | packages/bun-macro-relay/test/foo.tsx | 11 | ||||
-rw-r--r-- | packages/bun-macro-relay/tsconfig.json | 6 |
8 files changed, 57 insertions, 237 deletions
diff --git a/docs/bundler/macros.md b/docs/bundler/macros.md index 3ffa49502..0d6cda6fb 100644 --- a/docs/bundler/macros.md +++ b/docs/bundler/macros.md @@ -44,6 +44,63 @@ Bun Macros are import statements annotated using either: - `with { type: 'macro' }` — an [import attribute](https://github.com/tc39/proposal-import-attributes), a Stage 3 ECMA Scrd - `assert { type: 'macro' }` — an import assertion, an earlier incarnation of import attributes that has now been abandoned (but is [already supported](https://caniuse.com/mdn-javascript_statements_import_import_assertions) by a number of browsers and runtimes) +## Security considerations + +Macros must explicitly be imported with `{ type: "macro" }` in order to be executed at bundle-time. These imports have no effect if they are not called, unlike regular JavaScript imports which may have side effects. + +You can disable macros entirely by passing the `--no-macros` flag to Bun. It produces a build error like this: + +```js +error: Macros are disabled + +foo(); +^ +./hello.js:3:1 53 +``` + +To reduce the potential attack surface for malicious packages, macros cannot be _invoked_ from inside `node_modules/**/*`. If a package attempts to invoke a macro, you'll see an error like this: + +```js +error: For security reasons, macros cannot be run from node_modules. + +beEvil(); +^ +node_modules/evil/index.js:3:1 50 +``` + +Your application code can still import macros from `node_modules` and invoke them. + +```ts +import {macro} from "some-package" with { type: "macro" }; + +macro(); +``` + +## Export condition `"macro"` + +When shipping a library containing a macro to `npm` or another package registry, use the `"macro"` [export condition](https://nodejs.org/api/packages.html#conditional-exports) to provide a special version of your package exclusively for the macro environment. + +```jsonc#package.json +{ + "name": "my-package", + "exports": { + "import": "./index.js", + "require": "./index.js", + "default": "./index.js", + "macro": "./index.macro.js" + } +} +``` + +With this configuration, users can consume your package at runtime or at bundle-time using the same import specifier: + +```ts +import pkg from "my-package"; // runtime import +import {macro} from "my-package" with { type: "macro" }; // macro import +``` + +The first import will resolve to `./node_modules/my-package/index.js`, while the second will be resolved by Bun's bundler to `./node_modules/my-package/index.macro.js`. + ## Execution When Bun's transpiler sees a macro import, it calls the function inside the transpiler using Bun's JavaScript runtime and converts the return value from JavaScript into an AST node. These JavaScript functions are called at bundle-time, not runtime. diff --git a/packages/bun-macro-relay/README.md b/packages/bun-macro-relay/README.md deleted file mode 100644 index 157163af5..000000000 --- a/packages/bun-macro-relay/README.md +++ /dev/null @@ -1,123 +0,0 @@ -# bun-macro-relay - -This lets you use Facebook's [Relay](https://github.com/facebook/relay) framework (GraphQL) with bun. - -Specifically, this implements the bun equivalent of [`babel-plugin-relay`](https://github.com/facebook/relay/tree/main/packages/babel-plugin-relay). It parses `graphql` queries, but does not compile/save them to your artifacts directory, you still need [`relay-compiler`](https://github.com/facebook/relay/tree/main/packages/relay-compiler) for that. - -## Installation - -``` -npm install -D bun-macro-relay -``` - -## Usage - -With three lines in your project's `bunfig.toml`, `react-relay` works automatically with bun. - -Add this to your `bunfig.toml`: - -```toml -[macros] -react-relay = {graphql = "bun-macro-relay"} -relay-runtime = {graphql = "bun-macro-relay"} -``` - -This tells bun to automatically pretend every import statement to `react-relay` with a `graphql` import came from `macro:bun-macro-relay/bun-macro-relay.tsx`. - -Effectively, it applies this diff in-memory so you can use `bun-macro-relay` without making other changes to your code: - -```js -// bun will remap this import: -import { graphql } from "react-relay"; - -// To this: -import { graphql } from "macro:bun-macro-relay/bun-macro-relay.tsx"; -``` - -You can still use the other imports from `react-relay`. It only affects the `graphql` export from `react-relay`. - -```js -// bun will remap this import: -import { graphql, useFragment } from "react-relay"; - -// To this: -import { graphql } from "macro:bun-macro-relay/bun-macro-relay.tsx"; -import { useFragment } from "react-relay"; -``` - -Ultimately, the `graphql` import should no longer appear in transpiled output: - -```js -import { useFragment } from "react-relay"; -``` - -If you'd rather not modify your project's `package.json`, you can do this instead: - -```js -import { graphql } from "macro:bun-macro-relay"; -``` - -## Configuration - -For performance reasons, `bun-macro-relay` does not read `relay-config`. That means your Relay configuration will _not_ be honored. - -Fortunately, the only configuration option relevant to `bun-macro-relay` is modifying the artifacts directory (the directory where `relay-compiler` saves compiled `.graphql` files). - -You can still change that with `bun-macro-relay`. - -### Changing the artifacts directory - -Pass the `BUN_MACRO_RELAY_ARTIFACT_DIRECTORY` environment variable to bun: - -```bash -BUN_MACRO_RELAY_ARTIFACT_DIRECTORY="__generated__" bun -``` - -You can also save it in `.env`, `.env.local`, or `.env.dev`. The path should be relative to the directory containing the project's package.json without a leading `.` or `./`. You can also pass it an absolute path. - -## What does `bun-macro-relay` actually do? - -1. Parses GraphQL (using the same `graphql` npm package as babel-plugin-relay) -2. Injects an import to the correct compiled GraphQL file in the Relay artifacts directory -3. Replaces the use of the `graphql` template literal with the `default` import from the compiled GraphQL file. - -Here's an example. - -Input: - -```tsx -import { graphql, useLazyLoadQuery } from "react-relay"; - -const Tweet = () => { - const data = useLazyLoadQuery( - graphql` - query TweetQuery { - ...Tweet_tweet - } - `, - {} - ); - if (!data.tweet) return null; - return <TweetComponent tweet={data.tweet} />; -}; -``` - -Output: - -```jsx -import TweetQuery from "../__generated__/TweetQuery.graphql.ts"; -import { useLazyLoadQuery } from "react-relay"; - -const Tweet = () => { - const data = useLazyLoadQuery(TweetQuery, {}); - if (!data.tweet) return null; - return <TweetComponent tweet={data.tweet} />; -}; -``` - -bun automatically transpiles JSX & TypeScript, but that's not relevant to this example. - -### What does `bun-macro-relay` not do? - -1. This first version doesn't hash the contents of the `graphql` query, so it won't detect when the GraphQL query is out of sync with the compiled `.graphql` file in development. However, if you're running Relay's CLI, bun's hot module reloading will automatically update. As long as you run Relay's CLI, it shouldn't matter. This will be fixed eventually (have to expose a native MD5 hashing function) -2. Compile GraphQL. You still need to use `relay-compiler` for that. diff --git a/packages/bun-macro-relay/__generated__/FooOperation.graphql.ts b/packages/bun-macro-relay/__generated__/FooOperation.graphql.ts deleted file mode 100644 index 4c83371c9..000000000 --- a/packages/bun-macro-relay/__generated__/FooOperation.graphql.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class FooOperation {} - -export default FooOperation; diff --git a/packages/bun-macro-relay/bun-macro-relay.tsx b/packages/bun-macro-relay/bun-macro-relay.tsx deleted file mode 100644 index f7899698d..000000000 --- a/packages/bun-macro-relay/bun-macro-relay.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { parse, print } from "graphql/index.js"; -import { resolve } from "path"; - -// -// 1. Parse the GraphQL tag. -// 2. From the parsed GraphQL query, get the AST definition. -// 3. From the AST definition, inject an import to that file inside the artifact directory -// 4. (TODO) MD5 the printed source text -// 5. (TODO) At runtime, if md5 !== import.md5, then warn the user that the query has changed -// but the file hasn't been updated so it must be reloaded. -// 6. Replace the TemplateLiteral with the default identifier from the injected import -let artifactDirectory: string = `__generated__`; - -const { RELAY_ARTIFACT_DIRECTORY, BUN_MACRO_RELAY_ARTIFACT_DIRECTORY } = - Bun.env; - -if (RELAY_ARTIFACT_DIRECTORY) { - artifactDirectory = RELAY_ARTIFACT_DIRECTORY; -} - -if (BUN_MACRO_RELAY_ARTIFACT_DIRECTORY) { - artifactDirectory = BUN_MACRO_RELAY_ARTIFACT_DIRECTORY; -} - -artifactDirectory = resolve(artifactDirectory); - -export function graphql(node) { - let query; - - if (node instanceof <call />) { - query = node.arguments[0].toString(); - } else if (node instanceof <template />) { - query = node.toString(); - } - - if (typeof query !== "string" || query.length === 0) { - throw new Error("BunMacroRelay: Unexpected empty graphql string."); - } - - const ast = parse(query); - - if (ast.definitions.length === 0) { - throw new Error("BunMacroRelay: Unexpected empty graphql tag."); - } - - const definition = ast.definitions[0]; - - if ( - definition.kind !== "FragmentDefinition" && - definition.kind !== "OperationDefinition" - ) { - throw new Error( - `BunMacroRelay: Expected a fragment, mutation, query, or subscription, got "${definition.kind}"`, - ); - } - - const graphqlDefinition = definition; - - const definitionName = graphqlDefinition.name && graphqlDefinition.name.value; - if (!definitionName) { - throw new Error("GraphQL operations and fragments must contain names"); - } - - const identifiername = `${definitionName}_$gql`; - - const importStmt = ( - <import - default={identifiername} - path={`${artifactDirectory}/${definitionName}.graphql`} - /> - ); - - return ( - <> - <inject>{importStmt}</inject> - <id to={importStmt.namespace[identifiername]} pure /> - </> - ); -} diff --git a/packages/bun-macro-relay/bun.lockb b/packages/bun-macro-relay/bun.lockb Binary files differdeleted file mode 100755 index 03fefa6d0..000000000 --- a/packages/bun-macro-relay/bun.lockb +++ /dev/null diff --git a/packages/bun-macro-relay/package.json b/packages/bun-macro-relay/package.json deleted file mode 100644 index 772fd5f1c..000000000 --- a/packages/bun-macro-relay/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "bun-macro-relay", - "version": "0.1.2", - "module": "bun-macro-relay.tsx", - "license": "MIT", - "peerDependencies": { - "graphql": "^15.0.0" - }, - "devDependencies": { - "graphql": "^15.6.0" - }, - "files": [ - "bun-macro-relay.tsx" - ] -} diff --git a/packages/bun-macro-relay/test/foo.tsx b/packages/bun-macro-relay/test/foo.tsx deleted file mode 100644 index fbb54f551..000000000 --- a/packages/bun-macro-relay/test/foo.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { graphql } from "react-relay"; - -export const Foo = () => { - const definition = graphql` - query FooOperation { - foo - } - `; - - return <div>{definition.operation.name}</div>; -}; diff --git a/packages/bun-macro-relay/tsconfig.json b/packages/bun-macro-relay/tsconfig.json deleted file mode 100644 index 19d4ac2e6..000000000 --- a/packages/bun-macro-relay/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": {} - } -} |