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 <bobbie@soedirgo.dev>
1 parent e49ebcd commit 9b6a6af

File tree

7 files changed

+1097
-5
lines changed

7 files changed

+1097
-5
lines changed

README.md

Lines changed: 7 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 35 additions & 0 deletions
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

Lines changed: 4 additions & 2 deletions
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

Lines changed: 38 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy