Skip to content

Commit 9b6a6af

Browse files
feat(typegen): Go Type Gen (#687)
* feat(typegen): add route for go * feat(typegen): cleanup server.ts and set up local typegen for go * feat(typegen): create go table structs * feat(typegen): create go view/matview structs * feat(typegen): create go composite type structs * feat(typegen): go: handle range types * feat(typegen): go: test * feat(typegen): go: format * feat(typegen): separate go types by operation and add nullable types * feat(typegen): go: format * feat(typegen): go: handle empty tables * chore: update snapshot --------- Co-authored-by: Bobbie Soedirgo <[email protected]>
1 parent e49ebcd commit 9b6a6af

File tree

7 files changed

+1097
-5
lines changed

7 files changed

+1097
-5
lines changed

README.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,14 @@ To start developing, run `npm run dev`. It will set up the database with Docker
100100

101101
If you are fixing a bug, you should create a new test case. To test your changes, add the `-u` flag to `vitest` on the `test:run` script, run `npm run test`, and then review the git diff of the snapshots. Depending on your change, you may see `id` fields being changed - this is expected and you are free to commit it, as long as it passes the CI. Don't forget to remove the `-u` flag when committing.
102102

103-
To make changes to the TypeScript type generation, run `npm run gen:types:typescript` while you have `npm run dev` running.
103+
To make changes to the type generation, run `npm run gen:types:<lang>` while you have `npm run dev` running,
104+
where `<lang>` is one of:
105+
106+
- `typescript`
107+
- `go`
108+
104109
To use your own database connection string instead of the provided test database, run:
105-
`PG_META_DB_URL=postgresql://postgres:postgres@localhost:5432/postgres npm run gen:types:typescript`
110+
`PG_META_DB_URL=postgresql://postgres:postgres@localhost:5432/postgres npm run gen:types:<lang>`
106111

107112
## Licence
108113

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"build": "tsc -p tsconfig.json && cpy 'src/lib/sql/*.sql' dist/lib/sql",
2424
"docs:export": "PG_META_EXPORT_DOCS=true node --loader ts-node/esm src/server/server.ts > openapi.json",
2525
"gen:types:typescript": "PG_META_GENERATE_TYPES=typescript node --loader ts-node/esm src/server/server.ts",
26+
"gen:types:go": "PG_META_GENERATE_TYPES=go node --loader ts-node/esm src/server/server.ts",
2627
"start": "node dist/server/server.js",
2728
"dev": "trap 'npm run db:clean' INT && run-s db:clean db:run && nodemon --exec node --loader ts-node/esm src/server/server.ts | pino-pretty --colorize",
2829
"test": "run-s db:clean db:run test:run db:clean",

src/server/routes/generators/go.ts

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { FastifyInstance } from 'fastify'
2+
import { PostgresMeta } from '../../../lib/index.js'
3+
import { DEFAULT_POOL_CONFIG } from '../../constants.js'
4+
import { extractRequestForLogging } from '../../utils.js'
5+
import { apply as applyGoTemplate } from '../../templates/go.js'
6+
import { getGeneratorMetadata } from '../../../lib/generators.js'
7+
8+
export default async (fastify: FastifyInstance) => {
9+
fastify.get<{
10+
Headers: { pg: string }
11+
Querystring: {
12+
excluded_schemas?: string
13+
included_schemas?: string
14+
}
15+
}>('/', async (request, reply) => {
16+
const connectionString = request.headers.pg
17+
const excludedSchemas =
18+
request.query.excluded_schemas?.split(',').map((schema) => schema.trim()) ?? []
19+
const includedSchemas =
20+
request.query.included_schemas?.split(',').map((schema) => schema.trim()) ?? []
21+
22+
const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
23+
const { data: generatorMeta, error: generatorMetaError } = await getGeneratorMetadata(pgMeta, {
24+
includedSchemas,
25+
excludedSchemas,
26+
})
27+
if (generatorMetaError) {
28+
request.log.error({ error: generatorMetaError, request: extractRequestForLogging(request) })
29+
reply.code(500)
30+
return { error: generatorMetaError.message }
31+
}
32+
33+
return applyGoTemplate(generatorMeta)
34+
})
35+
}

src/server/routes/index.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import TablesRoute from './tables.js'
1818
import TriggersRoute from './triggers.js'
1919
import TypesRoute from './types.js'
2020
import ViewsRoute from './views.js'
21-
import TypeGenRoute from './generators/typescript.js'
21+
import TypeScriptTypeGenRoute from './generators/typescript.js'
22+
import GoTypeGenRoute from './generators/go.js'
2223
import { PG_CONNECTION, CRYPTO_KEY } from '../constants.js'
2324

2425
export default async (fastify: FastifyInstance) => {
@@ -62,5 +63,6 @@ export default async (fastify: FastifyInstance) => {
6263
fastify.register(TriggersRoute, { prefix: '/triggers' })
6364
fastify.register(TypesRoute, { prefix: '/types' })
6465
fastify.register(ViewsRoute, { prefix: '/views' })
65-
fastify.register(TypeGenRoute, { prefix: '/generators/typescript' })
66+
fastify.register(TypeScriptTypeGenRoute, { prefix: '/generators/typescript' })
67+
fastify.register(GoTypeGenRoute, { prefix: '/generators/go' })
6668
}

src/server/server.ts

+38
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
PG_META_PORT,
1515
} from './constants.js'
1616
import { apply as applyTypescriptTemplate } from './templates/typescript.js'
17+
import { apply as applyGoTemplate } from './templates/go.js'
18+
import { getGeneratorMetadata } from '../lib/generators.js'
1719

1820
const logger = pino({
1921
formatters: {
@@ -27,6 +29,37 @@ const logger = pino({
2729
const app = buildApp({ logger })
2830
const adminApp = buildAdminApp({ logger })
2931

32+
async function getTypeOutput(): Promise<string | null> {
33+
const pgMeta: PostgresMeta = new PostgresMeta({
34+
...DEFAULT_POOL_CONFIG,
35+
connectionString: PG_CONNECTION,
36+
})
37+
const { data: generatorMetadata, error: generatorMetadataError } = await getGeneratorMetadata(
38+
pgMeta,
39+
{
40+
includedSchemas: GENERATE_TYPES_INCLUDED_SCHEMAS,
41+
}
42+
)
43+
if (generatorMetadataError) {
44+
throw new Error(generatorMetadataError.message)
45+
}
46+
47+
let output: string | null = null
48+
switch (GENERATE_TYPES) {
49+
case 'typescript':
50+
output = await applyTypescriptTemplate({
51+
...generatorMetadata,
52+
detectOneToOneRelationships: GENERATE_TYPES_DETECT_ONE_TO_ONE_RELATIONSHIPS,
53+
})
54+
break
55+
case 'go':
56+
output = applyGoTemplate(generatorMetadata)
57+
break
58+
}
59+
60+
return output
61+
}
62+
3063
if (EXPORT_DOCS) {
3164
// TODO: Move to a separate script.
3265
await app.ready()
@@ -154,3 +187,8 @@ if (EXPORT_DOCS) {
154187
adminApp.listen({ port: adminPort, host: PG_META_HOST })
155188
})
156189
}
190+
191+
app.listen({ port: PG_META_PORT, host: PG_META_HOST }, () => {
192+
const adminPort = PG_META_PORT + 1
193+
adminApp.listen({ port: adminPort, host: PG_META_HOST })
194+
})

0 commit comments

Comments
 (0)