Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions graphql/codegen/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ dist/
output-rq
output-orm/

examples/output/generated-sdk/
examples/output/generated-orm/

# Dependencies
node_modules/

Expand Down
77 changes: 0 additions & 77 deletions graphql/codegen/examples/download-schema.ts

This file was deleted.

240 changes: 240 additions & 0 deletions graphql/codegen/examples/orm-sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/**
* ORM SDK Example - Prisma-like API for GraphQL
* Run: pnpm exec tsx examples/orm-sdk.ts
*/
import {
createClient,
GraphQLRequestError,
} from '../examples/output/generated-orm';

const ENDPOINT = 'http://api.localhost:3000/graphql';
let db = createClient({ endpoint: ENDPOINT });

const section = (title: string) =>
console.log(`\n${'─'.repeat(50)}\n${title}\n${'─'.repeat(50)}`);

async function main() {
console.log('ORM SDK Demo\n');

// ─────────────────────────────────────────────────────────────────────────────
// 1. Login & Auth
// ─────────────────────────────────────────────────────────────────────────────
section('1. Login Mutation');
const loginResult = await db.mutation
.login(
{ input: { email: '[email protected]', password: 'password1111!@#$' } },
{ select: { apiToken: { select: { accessToken: true } } } }
)
.execute();

const token = loginResult.data?.login?.apiToken?.accessToken;
if (token) {
db = createClient({
endpoint: ENDPOINT,
headers: { Authorization: `Bearer ${token}` },
});
console.log('✓ Logged in, token:', token.slice(0, 30) + '...');
}

// ─────────────────────────────────────────────────────────────────────────────
// 2. findMany with pagination & ordering
// ─────────────────────────────────────────────────────────────────────────────
section('2. findMany - List with Pagination');
const users = await db.user
.findMany({
select: { id: true, username: true, displayName: true },
first: 3,
orderBy: ['USERNAME_ASC'],
where: {
username: { notStartsWithInsensitive: 'admin' },
},
})
.execute();
console.log(
'Users:',
users.data?.users?.nodes?.map((u) => u.username)
);
console.log(
'Total:',
users.data?.users?.totalCount,
'| HasNext:',
users.data?.users?.pageInfo.hasNextPage
);

// ─────────────────────────────────────────────────────────────────────────────
// 3. Complex Filters (PostGraphile Filter Plugin)
// ─────────────────────────────────────────────────────────────────────────────
section('3. PostGraphile Filters');

// String filters
const stringFilters = await db.user
.findMany({
select: { id: true, username: true },
first: 5,
where: { username: { includesInsensitive: 'seed' } },
})
.execute();
console.log(
'includesInsensitive "seed":',
stringFilters.data?.users?.nodes?.map((u) => u.username)
);

// AND/OR/NOT composition
const composed = await db.user
.findMany({
select: { id: true, username: true, type: true },
first: 5,
where: {
and: [
{ username: { isNull: false } },
{ or: [{ type: { equalTo: 0 } }, { type: { greaterThan: 5 } }] },
],
},
})
.execute();
console.log(
'AND/OR filter:',
composed.data?.users?.nodes?.map((u) => ({ u: u.username, t: u.type }))
);

// ─────────────────────────────────────────────────────────────────────────────
// 4. Relation Selection (Nested Objects)
// ─────────────────────────────────────────────────────────────────────────────
section('4. Relations & Nested Selection');
const tables = await db.table
.findMany({
select: {
name: true,
category: true,
database: { select: { schemaName: true } },
},
first: 3,
orderBy: ['NAME_ASC'],
})
.execute();
console.log(
'Tables with DB:',
tables.data?.tables?.nodes?.map(
(t) => `${t.name} (${t.database?.schemaName})`
)
);

// ─────────────────────────────────────────────────────────────────────────────
// 5. Foreign Key & Datetime Filters
// ─────────────────────────────────────────────────────────────────────────────
section('5. Foreign Key & Datetime Filters');
const dbId = tables.data?.tables?.nodes?.[0]?.database?.schemaName;
if (dbId) {
const dbResult = await db.database
.findMany({
select: { id: true },
first: 1,
where: { schemaName: { equalTo: dbId } },
})
.execute();
const databaseId = dbResult.data?.databases?.nodes?.[0]?.id;
if (databaseId) {
const filtered = await db.table
.findMany({
select: { name: true },
first: 5,
where: { databaseId: { equalTo: databaseId } },
})
.execute();
console.log(
'Tables in DB:',
filtered.data?.tables?.nodes?.map((t) => t.name)
);
}
}

const thirtyDaysAgo = new Date(
Date.now() - 30 * 24 * 60 * 60 * 1000
).toISOString();
const recentDbs = await db.database
.findMany({
select: { schemaName: true, createdAt: true },
first: 3,
where: { createdAt: { greaterThan: thirtyDaysAgo } },
orderBy: ['CREATED_AT_DESC'],
})
.execute();
console.log(
'Recent DBs:',
recentDbs.data?.databases?.nodes?.map((d) => d.schemaName)
);

// ─────────────────────────────────────────────────────────────────────────────
// 6. Custom Queries
// ─────────────────────────────────────────────────────────────────────────────
section('6. Custom Queries');
const currentUser = await db.query
.getCurrentUser({
select: { id: true, username: true, displayName: true },
})
.execute();
console.log('Current user:', currentUser.data?.getCurrentUser?.username);

// ─────────────────────────────────────────────────────────────────────────────
// 7. Error Handling: execute(), unwrap(), unwrapOr()
// ─────────────────────────────────────────────────────────────────────────────
section('7. Error Handling');

// execute() - discriminated union { ok, data, errors }
const result = await db.user
.findMany({ select: { id: true }, first: 1 })
.execute();
console.log(
'execute():',
result.ok
? `ok, ${result.data.users?.nodes?.length} users`
: `error: ${result.errors[0]?.message}`
);

// unwrap() - throws on error
try {
const data = await db.database
.findMany({ select: { id: true }, first: 1 })
.unwrap();
console.log('unwrap():', data.databases?.nodes?.length, 'databases');
} catch (e) {
if (e instanceof GraphQLRequestError)
console.log('unwrap() error:', e.message);
}

// unwrapOr() - returns default on error
const defaultData = {
users: {
nodes: [] as { id: string }[],
totalCount: 0,
pageInfo: { hasNextPage: false, hasPreviousPage: false },
},
};
const safeData = await db.user
.findMany({ select: { id: true }, first: 1 })
.unwrapOr(defaultData);
console.log('unwrapOr():', safeData.users?.nodes?.length ?? 0, 'users');

// ─────────────────────────────────────────────────────────────────────────────
// 8. toGraphQL() - Inspect generated queries
// ─────────────────────────────────────────────────────────────────────────────
section('8. toGraphQL() - Query Inspection');
const query = db.user.findMany({
select: {
id: true,
username: true,
userProfile: { select: { displayName: true } },
},
first: 5,
where: { username: { isNull: false } },
orderBy: ['USERNAME_ASC'],
});
console.log('Generated GraphQL:\n', query.toGraphQL());

console.log('\n✓ All demos completed!');
}

main().catch((e) => {
console.error('Failed:', e);
process.exit(1);
});
Empty file.
Loading