Skip to content

Commit 8a8f3e5

Browse files
committed
llm update
1 parent fdf9ff6 commit 8a8f3e5

6 files changed

Lines changed: 279 additions & 8 deletions

File tree

examples/typescript-node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "typescript-node",
3-
"version": "3.1.0",
3+
"version": "3.1.1",
44
"description": "",
55
"private": true,
66
"main": "index.js",

packages/graphql-zeus-core/README.md

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,76 @@ Strongly Typed GraphQL from the team at [GraphQL Editor](https://graphqleditor.c
44

55
GraphQL Zeus is the absolute best way to interact with your GraphQL endpoints in a type-safe way. Zeus uses your schema to generate Typescript types and strongly typed clients to unlock the power, efficiency, productivity and safety of Typescript on your GraphQL requests.
66

7+
## LLM Quickstart
8+
9+
- This package documents how to use the generated client. For a working reference, see `examples/typescript-node/src/index.ts`.
10+
- Typical generated entry points: `./zeus/index.ts` and `./zeus/typedDocumentNode.ts`.
11+
12+
```ts
13+
import {
14+
Gql,
15+
Zeus,
16+
Thunder,
17+
Selector,
18+
fields,
19+
GraphQLTypes,
20+
InputType,
21+
ZeusScalars,
22+
$,
23+
} from './zeus';
24+
import { typedGql } from './zeus/typedDocumentNode';
25+
26+
// 1) Query/mutation with variables
27+
const created = await Gql('mutation')(
28+
{
29+
addCard: [
30+
{ card: { Attack: $('Attack', 'Int!'), Defense: 1, name: 'A', description: 'B' } },
31+
{ id: true, '...on Card': { Attack: true } },
32+
],
33+
},
34+
{ variables: { Attack: 1 } },
35+
);
36+
37+
// 2) Reusable selections and inferred types
38+
const q = Selector('Query')({ drawCard: { id: true, Attack: true } });
39+
type DrawCard = InputType<GraphQLTypes['Query'], typeof q>;
40+
const { drawCard } = await Gql('query')(q);
41+
42+
// 3) Aliases and string generation
43+
const gqlStr = Zeus('query', {
44+
__alias: { myCards: { listCards: { name: true } } },
45+
});
46+
47+
// 4) TypedDocumentNode for Apollo/urql
48+
const byId = typedGql('query')({ cardById: [{ cardId: $('id', 'String!') }, { name: true }] });
49+
50+
// 5) Custom fetch without losing types
51+
const thunder = Thunder(async (query) => {
52+
const r = await fetch('https://your.graphql/endpoint', {
53+
method: 'POST',
54+
headers: { 'Content-Type': 'application/json' },
55+
body: JSON.stringify({ query }),
56+
});
57+
const j = await r.json();
58+
return j.data;
59+
});
60+
const data = await thunder('query')({ drawCard: { id: true, Attack: true } });
61+
62+
// 6) Scalars encode/decode (one place)
63+
const scalars = ZeusScalars({
64+
JSON: { encode: JSON.stringify, decode: (e) => e as unknown },
65+
});
66+
await Gql('query', { scalars })({ drawCard: { info: true } });
67+
68+
// 7) Spread all scalar fields of a type
69+
await Gql('query')({ drawCard: { ...fields('Card') } });
70+
```
71+
72+
Tips
73+
- Prefer `Gql` for a preconfigured Chain, `Zeus` for building raw query strings, and `typedGql` when integrating with GraphQL clients.
74+
- Variables use the `$` helper: `$('name', 'String!')` both declares and types the variable.
75+
- Interface/union selections use inline fragments: `'...on Type': { ... }`.
76+
777
## Features
878

979
⚡️ Types mapped from your schema\
@@ -212,6 +282,71 @@ const queryWithSelectionSet = await chain('query')({
212282
});
213283
```
214284

285+
### FromSelector: Infer Types From Selectors
286+
287+
Use `FromSelector` to convert a selector into a concrete TypeScript type for a given schema type.
288+
289+
```ts
290+
import { Selector, FromSelector } from './zeus';
291+
292+
const nameableSelector = Selector('Nameable')({
293+
__typename: true,
294+
name: true,
295+
'...on Card': { description: true },
296+
'...on EffectCard': { effectSize: true },
297+
'...on CardStack': { cards: { id: true } },
298+
});
299+
300+
type Nameable = FromSelector<typeof nameableSelector, 'Nameable'>;
301+
302+
const handle = (n: Nameable) => {
303+
if (n.__typename === 'Card') n.description;
304+
if (n.__typename === 'EffectCard') n.effectSize;
305+
if (n.__typename === 'CardStack') n.cards;
306+
};
307+
```
308+
309+
### Composing Selectors
310+
311+
Pass selections as values to compose queries dynamically using `ComposableSelector`.
312+
313+
```ts
314+
import { Gql, ComposableSelector } from './zeus';
315+
316+
const withCardById = <T extends ComposableSelector<'Card'>>(id: string, selection: T) =>
317+
Gql('query')({
318+
cardById: [{ cardId: id }, selection],
319+
});
320+
321+
const a = await withCardById('12', { id: true });
322+
const b = await withCardById('12', { Attack: true, Defense: true });
323+
```
324+
325+
Or build on existing selections by spreading the returned selection objects:
326+
327+
```ts
328+
const base = Selector('Card')({ id: true, name: true });
329+
const extended = Selector('Card')({ ...base, Attack: true });
330+
```
331+
332+
### FromSelector + ZeusScalars
333+
334+
Thread custom scalar decoders/encoders into your inferred types by supplying the third generic to `FromSelector`.
335+
336+
```ts
337+
import { ZeusScalars, Selector, FromSelector } from './zeus';
338+
339+
const scalars = ZeusScalars({
340+
JSON: { encode: JSON.stringify, decode: (e) => e as { power: number } },
341+
ID: { decode: (e) => Number(e) },
342+
});
343+
344+
const cardSel = Selector('Card')({ id: true, info: true }); // info is JSON
345+
346+
type CardWithScalars = FromSelector<typeof cardSel, 'Card', typeof scalars>;
347+
// CardWithScalars['info'] is now { power: number }
348+
```
349+
215350
### Inferring the response type
216351
217352
Sometimes you might want to infer the response type. In that case, it is best to use selectors:
@@ -755,4 +890,4 @@ onMessage.on(({ message }) => {
755890
onMessage.ws.close();
756891
```
757892

758-
While you can use `wsChain('query')` or `wsChain('mutation')`, [Apollo strongly discourages this practice.](https://www.apollographql.com/docs/react/data/subscriptions/#3-split-communication-by-operation-recommended)
893+
While you can use `wsChain('query')` or `wsChain('mutation')`, [Apollo strongly discourages this practice.](https://www.apollographql.com/docs/react/data/subscriptions/#3-split-communication-by-operation-recommended)

packages/graphql-zeus-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-zeus-core",
3-
"version": "7.1.0",
3+
"version": "7.1.1",
44
"private": false,
55
"main": "./lib/index.js",
66
"author": "GraphQL Editor, Artur Czemiel",

packages/graphql-zeus-jsonschema/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-zeus-jsonschema",
3-
"version": "7.1.0",
3+
"version": "7.1.1",
44
"private": false,
55
"main": "./lib/index.js",
66
"author": "GraphQL Editor, Artur Czemiel",

packages/graphql-zeus/README.md

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,75 @@ Strongly Typed GraphQL from the team at [GraphQL Editor](https://graphqleditor.c
44

55
GraphQL Zeus is the absolute best way to interact with your GraphQL endpoints in a type-safe way. Zeus uses your schema to generate Typescript types and strongly typed clients to unlock the power, efficiency, productivity and safety of Typescript on your GraphQL requests.
66

7+
## LLM Quickstart
8+
9+
- Generate client code from a schema or URL
10+
- `npx graphql-zeus https://your.graphql/endpoint ./zeus --typescript`
11+
- Outputs `./zeus/index.ts` (+ `./zeus/typedDocumentNode.ts`)
12+
- Use the generated helpers in your app (based on examples/typescript-node/src/index.ts)
13+
14+
```ts
15+
// From the generated folder
16+
import {
17+
Gql,
18+
Zeus,
19+
$,
20+
Selector,
21+
GraphQLTypes,
22+
InputType,
23+
fields,
24+
ZeusScalars,
25+
Thunder,
26+
} from './zeus';
27+
import { typedGql } from './zeus/typedDocumentNode';
28+
29+
// Query/mutation with variables (typed end-to-end)
30+
const addCard = await Gql('mutation')(
31+
{
32+
addCard: [
33+
{ card: { Attack: $('Attack', 'Int!'), Defense: 2, name: 'AA', description: 'DD' } },
34+
{ id: true, info: true },
35+
],
36+
},
37+
{ variables: { Attack: 1 } },
38+
);
39+
40+
// Build reusable selections and infer types
41+
const q = Selector('Query')({ drawCard: { id: true, Attack: true } });
42+
type DrawCard = InputType<GraphQLTypes['Query'], typeof q>;
43+
44+
// Spread all scalar fields of a type
45+
const res = await Gql('query')({ drawCard: { ...fields('Card') } });
46+
47+
// Aliases and raw query string generation
48+
const queryStr = Zeus('query', { __alias: { myCards: { listCards: { name: true } } } });
49+
50+
// TypedDocumentNode for Apollo/urql
51+
const byId = typedGql('query')({ cardById: [{ cardId: $('id', 'String!') }, { name: true }] });
52+
53+
// Custom fetch while keeping response types
54+
const thunder = Thunder(async (query) => {
55+
const r = await fetch('https://your.graphql/endpoint', {
56+
method: 'POST',
57+
headers: { 'Content-Type': 'application/json' },
58+
body: JSON.stringify({ query }),
59+
});
60+
const j = await r.json();
61+
return j.data;
62+
});
63+
const data = await thunder('query')({ drawCard: { id: true } });
64+
65+
// Scalar encoders/decoders in one place
66+
const scalars = ZeusScalars({
67+
JSON: { encode: JSON.stringify, decode: (e) => e as unknown },
68+
});
69+
await Gql('query', { scalars })({ drawCard: { info: true } });
70+
```
71+
72+
Notes
73+
- Generated helpers are framework-agnostic and work in Node, browser and RN.
74+
- See a full working usage in `examples/typescript-node/src/index.ts`.
75+
776
## Features
877

978
⚡️ Types mapped from your schema\
@@ -254,6 +323,73 @@ const queryWithSelectionSet = await chain('query')({
254323
});
255324
```
256325

326+
### FromSelector: Infer Types From Selectors
327+
328+
Use `FromSelector` to derive a concrete TypeScript type from a selector for a specific GraphQL type.
329+
330+
```ts
331+
import { Selector, FromSelector } from './zeus';
332+
333+
const nameableSelector = Selector('Nameable')({
334+
__typename: true,
335+
name: true,
336+
'...on Card': { description: true },
337+
'...on EffectCard': { effectSize: true },
338+
'...on CardStack': { cards: { id: true } },
339+
});
340+
341+
type Nameable = FromSelector<typeof nameableSelector, 'Nameable'>;
342+
343+
// Discriminate on __typename safely
344+
const handle = (n: Nameable) => {
345+
if (n.__typename === 'Card') n.description;
346+
if (n.__typename === 'EffectCard') n.effectSize;
347+
if (n.__typename === 'CardStack') n.cards;
348+
};
349+
```
350+
351+
### Composing Selectors
352+
353+
You can pass reusable selections around using `ComposableSelector` to compose queries dynamically.
354+
355+
```ts
356+
import { Gql, ComposableSelector } from './zeus';
357+
358+
const withCardById = <T extends ComposableSelector<'Card'>>(id: string, selection: T) =>
359+
Gql('query')({
360+
cardById: [{ cardId: id }, selection],
361+
});
362+
363+
// usage
364+
const r1 = await withCardById('1', { id: true });
365+
const r2 = await withCardById('1', { Attack: true, Defense: true });
366+
```
367+
368+
You can also build on existing selections by spreading:
369+
370+
```ts
371+
const baseCard = Selector('Card')({ id: true, name: true });
372+
const detailedCard = Selector('Card')({ ...baseCard, Attack: true, Defense: true });
373+
```
374+
375+
### FromSelector + ZeusScalars
376+
377+
When you use custom scalar encoders/decoders via `ZeusScalars`, you can thread that information into `FromSelector` so fields resolve to their decoded types.
378+
379+
```ts
380+
import { ZeusScalars, Selector, FromSelector } from './zeus';
381+
382+
const scalars = ZeusScalars({
383+
JSON: { encode: JSON.stringify, decode: (e) => e as { power: number } },
384+
ID: { decode: (e) => Number(e) },
385+
});
386+
387+
const cardSel = Selector('Card')({ id: true, info: true }); // info: JSON
388+
389+
type CardWithScalars = FromSelector<typeof cardSel, 'Card', typeof scalars>;
390+
// CardWithScalars['info'] is now { power: number }
391+
```
392+
257393
### Inferring the response type
258394
259395
Sometimes you might want to infer the response type. In that case, it is best to use selectors:
@@ -797,4 +933,4 @@ onMessage.on(({ message }) => {
797933
onMessage.ws.close();
798934
```
799935

800-
While you can use `wsChain('query')` or `wsChain('mutation')`, [Apollo strongly discourages this practice.](https://www.apollographql.com/docs/react/data/subscriptions/#3-split-communication-by-operation-recommended)
936+
While you can use `wsChain('query')` or `wsChain('mutation')`, [Apollo strongly discourages this practice.](https://www.apollographql.com/docs/react/data/subscriptions/#3-split-communication-by-operation-recommended)

packages/graphql-zeus/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-zeus",
3-
"version": "7.1.0",
3+
"version": "7.1.1",
44
"private": false,
55
"scripts": {
66
"start": "ttsc --watch",
@@ -26,8 +26,8 @@
2626
"dependencies": {
2727
"config-maker": "^0.0.6",
2828
"cross-fetch": "^3.0.4",
29-
"graphql-zeus-core": "^7.1.0",
30-
"graphql-zeus-jsonschema": "^7.1.0",
29+
"graphql-zeus-core": "^7.1.1",
30+
"graphql-zeus-jsonschema": "^7.1.1",
3131
"yargs": "^16.1.1"
3232
}
3333
}

0 commit comments

Comments
 (0)