From 8d256128d2bb4d420fa9bd31c8beee9468611b88 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Thu, 5 Sep 2024 13:28:55 -0400 Subject: [PATCH] chore(docs/examples): add dynamic headers (#1065) --- ...__dynamicHeaders.output-encoder.output.txt | 0 ..._headers__dynamicHeaders.output-encoder.ts | 3 ++ ...rt-http_headers__dynamicHeaders.output.txt | 10 +++++ .../transport-http_headers__dynamicHeaders.ts | 23 ++++++++++ .../generate-tests.ts | 22 ++++++--- ...ted|generated_arguments__arguments.test.ts | 2 +- tests/examples/raw.test.ts | 2 +- .../examples/raw_rawString__rawString.test.ts | 2 +- ...awString_rawTyped__rawString-typed.test.ts | 2 +- .../examples/raw_rawTyped__raw-typed.test.ts | 2 +- .../transport-http_RequestInput.test.ts | 2 +- tests/examples/transport-http_abort.test.ts | 2 +- tests/examples/transport-http_fetch.test.ts | 2 +- ...sport-http_headers__dynamicHeaders.test.ts | 20 +++++++++ tests/examples/transport-memory.test.ts | 2 +- website/.vitepress/configExamples.ts | 8 ++++ website/content/examples/dynamicHeaders.md | 45 +++++++++++++++++++ .../examples/dynamicHeaders.output-encoder.md | 19 ++++++++ .../examples/transport-http_RequestInput.md | 6 +-- .../content/guides/_example_links/headers.md | 1 + .../guides/_example_links/transport-http.md | 2 +- .../_example_links/transport-http_headers.md | 1 + 22 files changed, 160 insertions(+), 18 deletions(-) create mode 100644 examples/transport-http_headers__dynamicHeaders.output-encoder.output.txt create mode 100644 examples/transport-http_headers__dynamicHeaders.output-encoder.ts create mode 100644 examples/transport-http_headers__dynamicHeaders.output.txt create mode 100644 examples/transport-http_headers__dynamicHeaders.ts create mode 100644 tests/examples/transport-http_headers__dynamicHeaders.test.ts create mode 100644 website/content/examples/dynamicHeaders.md create mode 100644 website/content/examples/dynamicHeaders.output-encoder.md create mode 100644 website/content/guides/_example_links/headers.md create mode 100644 website/content/guides/_example_links/transport-http_headers.md diff --git a/examples/transport-http_headers__dynamicHeaders.output-encoder.output.txt b/examples/transport-http_headers__dynamicHeaders.output-encoder.output.txt new file mode 100644 index 000000000..e69de29bb diff --git a/examples/transport-http_headers__dynamicHeaders.output-encoder.ts b/examples/transport-http_headers__dynamicHeaders.output-encoder.ts new file mode 100644 index 000000000..ae1e9b86d --- /dev/null +++ b/examples/transport-http_headers__dynamicHeaders.output-encoder.ts @@ -0,0 +1,3 @@ +export const encode = (value: string) => { + return value.replace(/'x-sent-at-time': '\d+'/g, `'x-sent-at-time': 'DYNAMIC_VALUE'`) +} diff --git a/examples/transport-http_headers__dynamicHeaders.output.txt b/examples/transport-http_headers__dynamicHeaders.output.txt new file mode 100644 index 000000000..3414a8878 --- /dev/null +++ b/examples/transport-http_headers__dynamicHeaders.output.txt @@ -0,0 +1,10 @@ +{ + url: 'https://countries.trevorblades.com/graphql', + body: '{"query":"{ languages { code } }"}', + method: 'POST', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', + 'content-type': 'application/json', + 'x-sent-at-time': 'DYNAMIC_VALUE' + } +} \ No newline at end of file diff --git a/examples/transport-http_headers__dynamicHeaders.ts b/examples/transport-http_headers__dynamicHeaders.ts new file mode 100644 index 000000000..74e90347c --- /dev/null +++ b/examples/transport-http_headers__dynamicHeaders.ts @@ -0,0 +1,23 @@ +import { Graffle } from '../src/entrypoints/main.js' +import { publicGraphQLSchemaEndpoints, show } from './$helpers.js' + +const graffle = Graffle + .create({ + schema: publicGraphQLSchemaEndpoints.SocialStudies, + }) + .use(async ({ pack }) => { + return await pack({ + input: { + ...pack.input, + headers: { + 'X-Sent-At-Time': Date.now().toString(), + }, + }, + }) + }) + .use(async ({ exchange }) => { + show(exchange.input.request) + return exchange() + }) + +await graffle.rawString({ document: `{ languages { code } }` }) diff --git a/scripts/generate-examples-derivatives/generate-tests.ts b/scripts/generate-examples-derivatives/generate-tests.ts index 89f3efab6..2326b3c66 100644 --- a/scripts/generate-examples-derivatives/generate-tests.ts +++ b/scripts/generate-examples-derivatives/generate-tests.ts @@ -1,4 +1,6 @@ +import { globby } from 'globby' import * as FS from 'node:fs/promises' +import * as Path from 'node:path' import { deleteFiles } from '../lib/deleteFiles.js' import { readFiles } from '../lib/readFiles.js' @@ -8,32 +10,42 @@ export const generateTests = async () => { const files = await readFiles({ pattern: `./examples/*.ts`, - options: { ignore: [`./examples/$*`] }, + options: { ignore: [`./examples/$*`, `./examples/*.output.*`, `./examples/*.output-encoder.*`] }, }) + const encoderFilePaths = await globby(`./examples/*.output-encoder.ts`) + + const outputDir = Path.join(process.cwd(), `./tests/examples`) await Promise.all(files.map(async (file) => { + const encoderFilePath = encoderFilePaths.find((encoderFilePath) => + encoderFilePath.match(new RegExp(`${file.name}.output-encoder.ts`)) !== null + ) const code = `// @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' import stripAnsi from 'strip-ansi' -import { expect, test } from 'vitest' +import { expect, test } from 'vitest'${ + encoderFilePath + ? `\nimport { encode } from '${Path.relative(outputDir, encoderFilePath.replace(`.ts`, `.js`))}'` + : `` + } test(\`${file.name}\`, async () => { const result = await execaCommand(\`pnpm tsx ./examples/${file.name}.ts\`) expect(result.exitCode).toBe(0) // Examples should output their data results. - const exampleResult = stripAnsi(result.stdout) + const exampleResult = ${encoderFilePath ? `encode(stripAnsi(result.stdout))` : `stripAnsi(result.stdout)`} // If ever outputs vary by Node version, you can use this to snapshot by Node version. // const nodeMajor = process.version.match(/v(\\d+)/)?.[1] ?? \`unknown\` await expect(exampleResult).toMatchFileSnapshot(\`../../${file.path.dir}/${file.name}.output.txt\`) }) ` - await FS.writeFile(`./tests/examples/${file.name}.test.ts`, code) + await FS.writeFile(Path.join(outputDir, `${file.name}.test.ts`), code) })) console.log(`Generated a test for each example.`) diff --git a/tests/examples/generated|generated_arguments__arguments.test.ts b/tests/examples/generated|generated_arguments__arguments.test.ts index 64eb0382e..10fcbc164 100644 --- a/tests/examples/generated|generated_arguments__arguments.test.ts +++ b/tests/examples/generated|generated_arguments__arguments.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/raw.test.ts b/tests/examples/raw.test.ts index 5e2bd45d1..ef845b2ef 100644 --- a/tests/examples/raw.test.ts +++ b/tests/examples/raw.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/raw_rawString__rawString.test.ts b/tests/examples/raw_rawString__rawString.test.ts index 5997accaf..906f546ef 100644 --- a/tests/examples/raw_rawString__rawString.test.ts +++ b/tests/examples/raw_rawString__rawString.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/raw_rawString_rawTyped__rawString-typed.test.ts b/tests/examples/raw_rawString_rawTyped__rawString-typed.test.ts index 8eb9f88c7..f40d0028e 100644 --- a/tests/examples/raw_rawString_rawTyped__rawString-typed.test.ts +++ b/tests/examples/raw_rawString_rawTyped__rawString-typed.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/raw_rawTyped__raw-typed.test.ts b/tests/examples/raw_rawTyped__raw-typed.test.ts index f3bdfdf8f..8fa66d2e8 100644 --- a/tests/examples/raw_rawTyped__raw-typed.test.ts +++ b/tests/examples/raw_rawTyped__raw-typed.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/transport-http_RequestInput.test.ts b/tests/examples/transport-http_RequestInput.test.ts index 2a815e863..d991d8560 100644 --- a/tests/examples/transport-http_RequestInput.test.ts +++ b/tests/examples/transport-http_RequestInput.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/transport-http_abort.test.ts b/tests/examples/transport-http_abort.test.ts index 60c59e37b..8d9915487 100644 --- a/tests/examples/transport-http_abort.test.ts +++ b/tests/examples/transport-http_abort.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/transport-http_fetch.test.ts b/tests/examples/transport-http_fetch.test.ts index 9f5f2c525..7ce07e80a 100644 --- a/tests/examples/transport-http_fetch.test.ts +++ b/tests/examples/transport-http_fetch.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/tests/examples/transport-http_headers__dynamicHeaders.test.ts b/tests/examples/transport-http_headers__dynamicHeaders.test.ts new file mode 100644 index 000000000..b1cd180f3 --- /dev/null +++ b/tests/examples/transport-http_headers__dynamicHeaders.test.ts @@ -0,0 +1,20 @@ +// @vitest-environment node + +// WARNING: +// This test is generated by scripts/generate-example-derivatives/generate.ts +// Do not modify this file directly. + +import { execaCommand } from 'execa' +import stripAnsi from 'strip-ansi' +import { expect, test } from 'vitest' +import { encode } from '../../examples/transport-http_headers__dynamicHeaders.output-encoder.js' + +test(`transport-http_headers__dynamicHeaders`, async () => { + const result = await execaCommand(`pnpm tsx ./examples/transport-http_headers__dynamicHeaders.ts`) + expect(result.exitCode).toBe(0) + // Examples should output their data results. + const exampleResult = encode(stripAnsi(result.stdout)) + // If ever outputs vary by Node version, you can use this to snapshot by Node version. + // const nodeMajor = process.version.match(/v(\d+)/)?.[1] ?? `unknown` + await expect(exampleResult).toMatchFileSnapshot(`../.././examples/transport-http_headers__dynamicHeaders.output.txt`) +}) diff --git a/tests/examples/transport-memory.test.ts b/tests/examples/transport-memory.test.ts index 154fd5ccf..7088beb66 100644 --- a/tests/examples/transport-memory.test.ts +++ b/tests/examples/transport-memory.test.ts @@ -1,7 +1,7 @@ // @vitest-environment node // WARNING: -// This test is generated by scripts/generate-test-examples.ts +// This test is generated by scripts/generate-example-derivatives/generate.ts // Do not modify this file directly. import { execaCommand } from 'execa' diff --git a/website/.vitepress/configExamples.ts b/website/.vitepress/configExamples.ts index df3edb0bf..a1de93144 100644 --- a/website/.vitepress/configExamples.ts +++ b/website/.vitepress/configExamples.ts @@ -5,6 +5,14 @@ export const sidebarExamples: DefaultTheme.SidebarItem[] = [ 'text': 'Transport Memory', 'link': '/examples/transport-memory', }, + { + 'text': 'DynamicHeaders', + 'link': '/examples/dynamicHeaders', + }, + { + 'text': 'DynamicHeaders.output Encoder', + 'link': '/examples/dynamicHeaders.output-encoder', + }, { 'text': 'Transport Http Fetch', 'link': '/examples/transport-http_fetch', diff --git a/website/content/examples/dynamicHeaders.md b/website/content/examples/dynamicHeaders.md new file mode 100644 index 000000000..d2d1546de --- /dev/null +++ b/website/content/examples/dynamicHeaders.md @@ -0,0 +1,45 @@ +--- +aside: false +--- + +# DynamicHeaders + +```ts twoslash +import { Graffle } from 'graffle' + +const graffle = Graffle + .create({ + schema: `https://countries.trevorblades.com/graphql`, + }) + .use(async ({ pack }) => { + return await pack({ + input: { + ...pack.input, + headers: { + 'X-Sent-At-Time': Date.now().toString(), + }, + }, + }) + }) + .use(async ({ exchange }) => { + console.log(exchange.input.request) + return exchange() + }) + +await graffle.rawString({ document: `{ languages { code } }` }) +``` + +#### Output + +```txt +{ + url: 'https://countries.trevorblades.com/graphql', + body: '{"query":"{ languages { code } }"}', + method: 'POST', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', + 'content-type': 'application/json', + 'x-sent-at-time': '1725556925194' + } +} +``` diff --git a/website/content/examples/dynamicHeaders.output-encoder.md b/website/content/examples/dynamicHeaders.output-encoder.md new file mode 100644 index 000000000..6603223c6 --- /dev/null +++ b/website/content/examples/dynamicHeaders.output-encoder.md @@ -0,0 +1,19 @@ +--- +aside: false +--- + +# DynamicHeaders.output Encoder + +```ts twoslash +export const encode = (snapshot: string) => { + return snapshot.replace( + /x-sent-at-time: '\d+'/, + `x-sent-at-time: 'DYNAMIC_VALUE'`, + ) +} +``` + +#### Output + +```txt +``` diff --git a/website/content/examples/transport-http_RequestInput.md b/website/content/examples/transport-http_RequestInput.md index beae2328a..daa7e6ba1 100644 --- a/website/content/examples/transport-http_RequestInput.md +++ b/website/content/examples/transport-http_RequestInput.md @@ -33,9 +33,9 @@ await graffle.rawString({ document: `{ languages { code } }` }) body: '{"query":"{ languages { code } }"}', method: 'POST', headers: Headers { - authorization: 'Bearer MY_TOKEN', - accept: 'application/graphql-response+json', - 'content-type': 'application/json' + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', + 'content-type': 'application/json', + authorization: 'Bearer MY_TOKEN' }, mode: 'cors' } diff --git a/website/content/guides/_example_links/headers.md b/website/content/guides/_example_links/headers.md new file mode 100644 index 000000000..a86d14503 --- /dev/null +++ b/website/content/guides/_example_links/headers.md @@ -0,0 +1 @@ +###### Examples -> [DynamicHeaders.output Encoder](../../examples/dynamicHeaders.output-encoder.md) / [DynamicHeaders](../../examples/dynamicHeaders.md) diff --git a/website/content/guides/_example_links/transport-http.md b/website/content/guides/_example_links/transport-http.md index 4928decda..8b7c40899 100644 --- a/website/content/guides/_example_links/transport-http.md +++ b/website/content/guides/_example_links/transport-http.md @@ -1 +1 @@ -###### Examples -> [Transport Http RequestInput](../../examples/transport-http_RequestInput.md) / [Transport Http Abort](../../examples/transport-http_abort.md) / [Transport Http Fetch](../../examples/transport-http_fetch.md) +###### Examples -> [Transport Http RequestInput](../../examples/transport-http_RequestInput.md) / [Transport Http Abort](../../examples/transport-http_abort.md) / [Transport Http Fetch](../../examples/transport-http_fetch.md) / [DynamicHeaders.output Encoder](../../examples/dynamicHeaders.output-encoder.md) / [DynamicHeaders](../../examples/dynamicHeaders.md) diff --git a/website/content/guides/_example_links/transport-http_headers.md b/website/content/guides/_example_links/transport-http_headers.md new file mode 100644 index 000000000..a86d14503 --- /dev/null +++ b/website/content/guides/_example_links/transport-http_headers.md @@ -0,0 +1 @@ +###### Examples -> [DynamicHeaders.output Encoder](../../examples/dynamicHeaders.output-encoder.md) / [DynamicHeaders](../../examples/dynamicHeaders.md)