Skip to content

Instantly share code, notes, and snippets.

@lorefnon
Created January 2, 2024 12:19
Show Gist options
  • Save lorefnon/67a0c14291597cbd6e4a5494a3052daf to your computer and use it in GitHub Desktop.
Save lorefnon/67a0c14291597cbd6e4a5494a3052daf to your computer and use it in GitHub Desktop.
Garph Kysely Batch Operation example
import sql, { Database } from "@leafac/sqlite";
import { g, InferResolvers, buildSchema } from 'garph'
import { createYoga, YogaInitialContext } from 'graphql-yoga'
import { createServer } from 'http'
import { groupBy } from "lodash"
import { Generated, Kysely, SqliteDialect } from 'kysely'
// Create in memory db instance
const db = new Database(":memory:");
// Setup schema
db.execute(sql`create table employee (id integer primary key autoincrement, name text);`)
.execute(sql`create table department (id integer primary key autoincrement, name text);`)
.execute(sql`create table employee_department (employee_id integer, department_id integer);`);
// Seed Data
db
.execute(sql`
insert into employee (id, name)
values (1, 'Rashiiq'), (2, 'Rana'), (3, 'Maya')
`)
.execute(sql`
insert into department (id, name)
values (1, 'Witchcraft'), (2, 'Extraterrestrial affairs')
`)
.execute(sql`
insert into employee_department (employee_id, department_id)
values (1, 1), (2, 1), (3, 2)`
)
const dialect = new SqliteDialect({
database: db,
})
interface DBSchema {
employee: {
id: Generated<number>,
name: string,
},
department: {
id: Generated<number>,
name: string,
},
employee_department: {
employee_id: number,
department_id: number,
},
}
export const kdb = new Kysely<DBSchema>({
dialect,
})
const EmployeeT = g.type('Employee', {
id: g.int(),
name: g.string(),
})
const DepartmentT = g.type('Department', {
id: g.int(),
name: g.string(),
employees: g.ref(EmployeeT).list().omitResolver()
});
const QueryT = g.type('Query', {
departments: g.ref(DepartmentT)
.list()
.description('Greets a person')
})
const resolvers: InferResolvers<{ Query: typeof QueryT, Department: typeof DepartmentT }, { context: YogaInitialContext }> = {
Query: {
departments: () => {
return kdb.selectFrom("department").selectAll().execute()
}
},
Department: {
employees: {
async loadBatch(queries) {
const deptIds = queries.map(_ => _.parent.id)
const allEmployees = await kdb.selectFrom("department")
.innerJoin("employee_department", "employee_department.department_id", "department.id")
.innerJoin("employee", "employee.id", "employee_department.employee_id")
.where("department.id", "in", deptIds)
.selectAll("employee")
.select("department.id as deptId")
.execute()
const employeesM = groupBy(allEmployees, _ => _.deptId)
return deptIds.map(_ => employeesM[_])
}
}
}
}
const schema = buildSchema({ g, resolvers })
const yoga = createYoga({ schema })
const server = createServer(yoga)
server.listen(4000, () => {
console.info('Server is running on http://localhost:4000/graphql')
})
{
"name": "garph-test-batch-loader",
"version": "1.0.0",
"main": "index.js",
"author": "lorefnon",
"license": "ISC",
"dependencies": {
"@leafac/sqlite": "^4.0.0",
"better-sqlite3": "^9.2.2",
"garph": "^0.6.4",
"graphql": "^16.8.1",
"graphql-yoga": "^5.1.0",
"kysely": "^0.27.0",
"lodash": "^4.17.21"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.8",
"@types/lodash": "^4.14.202",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment