-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(SLB-202): publish @amazeelabs/gatsby-plugin-operations
- Loading branch information
Showing
13 changed files
with
387 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.turbo | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
!build |
104 changes: 104 additions & 0 deletions
104
packages/npm/@amazeelabs/gatsby-plugin-operations/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# Gatsby operations | ||
|
||
This Gatsby plugin allows to use persisted query ids provided by | ||
[@amazeelabs/codegen-operation-ids] within templates and in the `createPages` | ||
hook. | ||
|
||
## Installation | ||
|
||
Install the package and configure the plugin within Gatsby. The only argument is | ||
the path to the file of generated operation ids: | ||
|
||
```js | ||
export const plugins = { | ||
{ | ||
resolve: '@amazeelabs/gatsby-plugin-operations', | ||
options: { | ||
operations: './node_modules/@custom/schema/build/operations.json', | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
To get proper type checking, you have to augment Gatsby type definitions, by | ||
placing this anywhere in the `src` directory: | ||
|
||
```typescript | ||
import { | ||
AnyOperationId, | ||
OperationResult, | ||
OperationVariables, | ||
} from '@custom/schema'; | ||
|
||
declare module '@amazeelabs/gatsby-plugin-operations' { | ||
export const graphql: <OperationId extends AnyOperationId>( | ||
id: OperationId, | ||
) => OperationResult<OperationId>; | ||
|
||
function useStaticQuery<Input extends any>(id: Input): Input; | ||
|
||
function graphqlQuery<OperationId extends AnyOperationId>( | ||
id: OperationId, | ||
vars?: OperationVariables<OperationId>, | ||
): Promise<{ | ||
data: OperationResult<OperationId>; | ||
errors?: Array<any>; | ||
}>; | ||
} | ||
``` | ||
|
||
This relies on the build output of [@amazeelabs/codegen-operation-ids] being | ||
exported by `@custom/schema`. | ||
|
||
## Usage | ||
|
||
### In templates | ||
|
||
For template queries, simply use `graphqlOperation` to define the query export. | ||
The query variable can be used directly to infer the template components | ||
properties. | ||
|
||
```typescript | ||
import { graphql } from '@amazeelabs/gatsby-plugin-operations'; | ||
import { ViewPageQuery } from '@custom/schema'; | ||
|
||
export const query = graphql(ViewPageQuery); | ||
export default function Page({ | ||
data, | ||
pageContext, | ||
}: PageProps<typeof query>) { | ||
return <div>...</div> | ||
} | ||
``` | ||
|
||
### In static queries | ||
|
||
To run a static query, one can use `graphql` in combination with | ||
`useStaticQuery`. This will yield a fully typed result of the requested query. | ||
|
||
```typescript | ||
import { useStaticQuery, graphql } from '@amazeelabs/gatsby-plugin-operations'; | ||
import { ListProductsQuery } from '@custom/schema'; | ||
|
||
const myResult = useStaticQuery(graphql(ListProductsQuery)); | ||
``` | ||
|
||
### In `gatsby-node.mjs` | ||
|
||
The `@amazeelabs/gatsby-plugin-operations` package provides a `graphqlQuery` | ||
function that works within the `createPages` hook. | ||
|
||
```typescript | ||
import { graphqlQuery } from '@amazeelabs/gatsby-plugin-operations'; | ||
import { ListPagesQuery } from '@custom/schema'; | ||
|
||
export const createPages({actions}) { | ||
const result = await graphqlQuery(ListPagesQuery); | ||
result.page.forEach((page) => { | ||
actions.createPage({}); | ||
}) | ||
} | ||
``` | ||
|
||
[@amazeelabs/codegen-operation-ids]: | ||
https://www.npmjs.com/package/@amazeelabs/codegen-operation-ids |
1 change: 1 addition & 0 deletions
1
packages/npm/@amazeelabs/gatsby-plugin-operations/gatsby-node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('./build/gatsby-node.js'); |
34 changes: 34 additions & 0 deletions
34
packages/npm/@amazeelabs/gatsby-plugin-operations/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "@amazeelabs/gatsby-plugin-operations", | ||
"version": "1.0.0", | ||
"description": "", | ||
"type": "commonjs", | ||
"main": "build/index.js", | ||
"types": "build/index.d.ts", | ||
"private": false, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"test": "vitest run", | ||
"prep": "tsc", | ||
"build": "pnpm prep" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"devDependencies": { | ||
"@babel/preset-react": "^7.23.3", | ||
"@babel/preset-typescript": "^7.23.3", | ||
"@babel/types": "^7.23.6", | ||
"@types/babel__core": "^7.20.5", | ||
"@types/node": "^18", | ||
"babel-plugin-tester": "^11.0.4", | ||
"typescript": "^5.3.3", | ||
"vitest": "^1.1.0", | ||
"gatsby": ">= 5" | ||
}, | ||
"dependencies": { | ||
"@babel/core": "^7.23.6" | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
packages/npm/@amazeelabs/gatsby-plugin-operations/src/gatsby-node.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { transformSync } from '@babel/core'; | ||
import type { GatsbyNode } from 'gatsby'; | ||
|
||
import { initialize } from './graphql.js'; | ||
import babelPlugin from './plugin.js'; | ||
|
||
export const onCreateBabelConfig: GatsbyNode['onCreateBabelConfig'] = ( | ||
{ actions }, | ||
options, | ||
) => { | ||
// Inject the babel plugin into webpack. | ||
actions.setBabelPlugin({ name: require.resolve('./plugin'), options }); | ||
}; | ||
|
||
/** | ||
* Replace query id's with gatsby graphql`` tags before queries are collected. | ||
*/ | ||
export const preprocessSource: GatsbyNode['preprocessSource'] = ( | ||
{ contents }, | ||
options, | ||
) => { | ||
const result = transformSync(contents, { | ||
plugins: [[babelPlugin, options]], | ||
presets: [ | ||
'@babel/preset-react', | ||
['@babel/preset-typescript', { isTSX: true, allExtensions: true }], | ||
], | ||
}); | ||
return result?.code ? result.code : contents; | ||
}; | ||
|
||
/** | ||
* Make persisted queries and the graphql function globally | ||
* available. | ||
*/ | ||
export const createPages: GatsbyNode['createPages'] = ( | ||
{ graphql }, | ||
options, | ||
) => { | ||
initialize(graphql, options.operations as string); | ||
}; |
29 changes: 29 additions & 0 deletions
29
packages/npm/@amazeelabs/gatsby-plugin-operations/src/graphql.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { readFileSync } from 'fs'; | ||
import type { CreatePagesArgs } from 'gatsby'; | ||
|
||
export let _graphql: CreatePagesArgs['graphql'] | undefined = undefined; | ||
let _operations: Record<string, string> | undefined = undefined; | ||
|
||
/** | ||
* Initialize the library. Happens in `./gatsby-node.ts` | ||
*/ | ||
export function initialize( | ||
graphql: CreatePagesArgs['graphql'], | ||
operations: string, | ||
) { | ||
_graphql = graphql; | ||
_operations = JSON.parse(readFileSync(operations).toString()); | ||
} | ||
|
||
/** | ||
* Execute a graphql query against gatsby. | ||
*/ | ||
export function graphqlQuery(id: string, vars?: any): any { | ||
if (!_graphql || !_operations) { | ||
throw new Error( | ||
'Plugin "@amazeelabs/gatsby-plugin-operations" not available. Make sure its configured in "gatsby-config.mjs" and that "graphqlQuery" is used within "createPages" only.', | ||
); | ||
} | ||
const operation = _operations?.[id]; | ||
return _graphql(operation, vars); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { graphqlQuery } from './graphql'; |
84 changes: 84 additions & 0 deletions
84
packages/npm/@amazeelabs/gatsby-plugin-operations/src/plugin.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { pluginTester } from 'babel-plugin-tester'; | ||
|
||
import plugin from './plugin.js'; | ||
|
||
pluginTester({ | ||
plugin, | ||
pluginOptions: { | ||
operations: `./test/operations.json`, | ||
}, | ||
babelOptions: { | ||
presets: [ | ||
'@babel/preset-react', | ||
['@babel/preset-typescript', { isTSX: true, allExtensions: true }], | ||
], | ||
}, | ||
tests: [ | ||
{ | ||
title: 'Page query', | ||
code: ` | ||
import { MyOperation } from '@custom/schema'; | ||
import { graphql } from '@amazeelabs/gatsby-plugin-operations'; | ||
export const query = graphql(MyOperation); | ||
`, | ||
output: ` | ||
import { MyOperation } from '@custom/schema'; | ||
import { graphql } from 'gatsby'; | ||
export const query = graphql\` | ||
{ | ||
field | ||
} | ||
\`;`, | ||
}, | ||
{ | ||
title: 'Static query', | ||
code: ` | ||
import { MyOperation } from '@custom/schema'; | ||
import { graphql, useStaticQuery } from '@amazeelabs/gatsby-plugin-operations'; | ||
function useData() { | ||
return useStaticQuery(graphql(MyOperation)); | ||
}`, | ||
output: ` | ||
import { MyOperation } from '@custom/schema'; | ||
import { graphql, useStaticQuery } from 'gatsby'; | ||
function useData() { | ||
return useStaticQuery( | ||
graphql\` | ||
{ | ||
field | ||
} | ||
\`, | ||
); | ||
}`, | ||
}, | ||
{ | ||
title: 'Typescript', | ||
code: ` | ||
import { MyOperation } from '@custom/schema'; | ||
import { graphql, useStaticQuery } from '@amazeelabs/gatsby-plugin-operations'; | ||
function useData() { | ||
return useStaticQuery(graphql(MyOperation)); | ||
} | ||
export function Component(props: { message: string }) { | ||
return <div>{props.message}</div>; | ||
} | ||
`, | ||
output: ` | ||
import { MyOperation } from '@custom/schema'; | ||
import { graphql, useStaticQuery } from 'gatsby'; | ||
function useData() { | ||
return useStaticQuery( | ||
graphql\` | ||
{ | ||
field | ||
} | ||
\`, | ||
); | ||
} | ||
export function Component(props) { | ||
return /*#__PURE__*/ React.createElement('div', null, props.message); | ||
}`, | ||
}, | ||
], | ||
}); |
64 changes: 64 additions & 0 deletions
64
packages/npm/@amazeelabs/gatsby-plugin-operations/src/plugin.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { PluginObj, PluginPass, types } from '@babel/core'; | ||
import { readFileSync } from 'fs'; | ||
|
||
function loadOperations(path: string) { | ||
const loadedOperations: Record<string, string> = {}; | ||
const loaded = JSON.parse(readFileSync(path).toString()); | ||
Object.keys(loaded).forEach((key) => { | ||
loadedOperations[key.split(':')[0]] = loaded[key]; | ||
}); | ||
return loadedOperations; | ||
} | ||
|
||
export default () => | ||
({ | ||
visitor: { | ||
ImportDeclaration(path) { | ||
if (path.node.source.value === '@amazeelabs/gatsby-plugin-operations') { | ||
path.replaceWith( | ||
types.importDeclaration( | ||
path.node.specifiers, | ||
types.stringLiteral('gatsby'), | ||
), | ||
); | ||
path.skip(); | ||
} | ||
}, | ||
CallExpression(path, { opts }) { | ||
const operations = loadOperations(opts.operations); | ||
if (path.node.callee.type === 'Identifier') { | ||
if (path.node.callee.name === 'graphql') { | ||
if ( | ||
!( | ||
path.node.arguments.length === 1 && | ||
path.node.arguments[0].type === 'Identifier' | ||
) | ||
) { | ||
return; | ||
} | ||
const operation = path.node.arguments[0].name; | ||
if (!operation || !operations[operation]) { | ||
return; | ||
} | ||
path.replaceWith( | ||
types.taggedTemplateExpression( | ||
types.identifier('graphql'), | ||
types.templateLiteral( | ||
[types.templateElement({ raw: operations[operation] })], | ||
[], | ||
), | ||
), | ||
); | ||
path.skip(); | ||
return; | ||
} | ||
} | ||
}, | ||
}, | ||
}) satisfies PluginObj< | ||
PluginPass & { | ||
opts: { | ||
operations: string; | ||
}; | ||
} | ||
>; |
3 changes: 3 additions & 0 deletions
3
packages/npm/@amazeelabs/gatsby-plugin-operations/test/operations.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"MyOperation:1234": "{ field }" | ||
} |
15 changes: 15 additions & 0 deletions
15
packages/npm/@amazeelabs/gatsby-plugin-operations/tsconfig.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "ESNext", | ||
"skipLibCheck": true, | ||
"strict": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"module": "CommonJS", | ||
"resolveJsonModule": true, | ||
"declaration": true, | ||
"declarationDir": "build", | ||
"lib": ["ESNext", "DOM"], | ||
"outDir": "build" | ||
}, | ||
"include": ["src"] | ||
} |
8 changes: 8 additions & 0 deletions
8
packages/npm/@amazeelabs/gatsby-plugin-operations/vitest.config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { defineConfig } from 'vitest/config'; | ||
|
||
export default defineConfig({ | ||
test: { | ||
globals: true, | ||
include: ['src/**/*.test.ts'], | ||
}, | ||
}); |