Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental zod parser #449

Merged
merged 9 commits into from
Nov 17, 2024
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
tool:
- ux
- uml2ts
- zod2uml
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/build-docker
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
tool:
- ux
- uml2ts
- zod2uml
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/build-docker
Expand All @@ -34,6 +35,7 @@ jobs:
matrix:
tool:
- uml2ts
- zod2uml
target:
- bun-linux-x64
- bun-linux-arm64
Expand Down
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ else
TEST_FLAGS := --github-output --race --trace
endif

build: generate bin/ux bin/devops .make/buf_build packages/tdl/dist packages/ts/dist
build: generate .make/buf_build build_go build_ts

build_go: bin/ux bin/devops
build_ts: bin/uml2ts bin/zod2uml packages/tdl/dist packages/ts/dist

test: .make/go_test .make/ts_test
generate: ${GO_PB_SRC}
docker: .make/docker_ux .make/docker_uml2ts
docker: .make/docker_ux .make/docker_uml2ts .make/docker_zod2uml
format: .make/dprint .make/go_fmt .make/buf_format
lint: .make/buf_lint .make/go_lint
tidy: go.sum
Expand Down Expand Up @@ -68,6 +72,9 @@ bin/ux: $(shell $(DEVOPS) list --go --exclude-tests)
bin/uml2ts: $(shell $(DEVOPS) list --ts --exclude-tests)
bun build --cwd packages/uml2ts index.ts --compile --outfile ${WORKING_DIR}/$@

bin/zod2uml: $(shell $(DEVOPS) list --ts --exclude-tests)
bun build --cwd packages/zod2uml index.ts --compile --outfile ${WORKING_DIR}/$@

bin/devops: $(shell $(DEVOPS) list --go --exclude-tests)
go -C cmd/devops build -o ${WORKING_DIR}/$@

Expand Down Expand Up @@ -103,6 +110,10 @@ go.sum: go.mod ${GO_SRC}
docker build -f docker/uml2ts/Dockerfile -t uml2ts ${WORKING_DIR}
@touch $@

.make/docker_zod2uml: ${TS_SRC} $(wildcard docker/zod2uml/*)
docker build -f docker/zod2uml/Dockerfile -t zod2uml ${WORKING_DIR}
@touch $@

.make/go_test: ${GO_SRC} | bin/ginkgo bin/ux bin/uml2ts
$(GINKGO) run ${TEST_FLAGS} $(sort $(dir $?))
@touch $@
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions docker/uml2ts/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ COPY package.json .
COPY packages/tdl/package.json packages/tdl/
COPY packages/ts/package.json packages/ts/
COPY packages/uml2ts/package.json packages/uml2ts/
COPY packages/zod/package.json packages/zod/
COPY packages/zod2uml/package.json packages/zod2uml/
COPY bun.lockb .

RUN bun install --frozen-lockfile --production
Expand Down
22 changes: 22 additions & 0 deletions docker/zod2uml/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
node_modules
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE
.vscode
Makefile
.env
.editorconfig
.idea
coverage*
.config
.github
.make
cli
docker
pkg
proto
src
39 changes: 39 additions & 0 deletions docker/zod2uml/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM oven/bun:1.1.34 AS base
ARG BUILDPLATFORM
WORKDIR /build

FROM --platform=$BUILDPLATFORM base AS install

RUN mkdir -p gen/proto/{es,ts} packages/{ts,uml,uml2ts}

# Need everything because the lockfile references everything
COPY package.json .
COPY packages/tdl/package.json packages/tdl/
COPY packages/ts/package.json packages/ts/
COPY packages/uml2ts/package.json packages/uml2ts/
COPY packages/zod/package.json packages/zod/
COPY packages/zod2uml/package.json packages/zod2uml/
COPY bun.lockb .

RUN bun install --frozen-lockfile --production

FROM --platform=$BUILDPLATFORM install AS build
COPY --from=install /build/node_modules .

COPY packages/tdl/ packages/tdl/
COPY packages/zod/ packages/zod/
COPY packages/zod2uml/ .

RUN bun build \
--compile \
--minify \
--sourcemap ./index.ts \
--outfile ./dist/zod2uml

FROM --platform=$BUILDPLATFORM ubuntu:noble-20241015 AS test
COPY --from=build /build/dist/zod2uml .

FROM --platform=$BUILDPLATFORM oven/bun:1.1.34-distroless
COPY --from=build /build/dist/zod2uml /bin/
ENTRYPOINT ["/bin/zod2uml"]
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,8 @@ github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 h1:vkHw5I/plNdTr435
github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231/go.mod h1:murToZ2N9hNJzewjHBgfFdXhZKjY3z5cYC1VXk+lbFE=
github.com/pulumi/esc v0.10.0 h1:jzBKzkLVW0mePeanDRfqSQoCJ5yrkux0jIwAkUxpRKE=
github.com/pulumi/esc v0.10.0/go.mod h1:2Bfa+FWj/xl8CKqRTWbWgDX0SOD4opdQgvYSURTGK2c=
github.com/pulumi/pulumi/pkg/v3 v3.138.0 h1:a+MMvCrvsju4YFVYEwPBtcW7XqsEIV3B+FMblisxEkM=
github.com/pulumi/pulumi/pkg/v3 v3.138.0/go.mod h1:xpaeNeKmM2KLafWwm8TlvJGbWtwEwlrK88U6FvXucpY=
github.com/pulumi/pulumi/pkg/v3 v3.139.0 h1:vWwAvEL0US8Z6emggo+OI/ZducMq9m9LKCJbEDbERvU=
github.com/pulumi/pulumi/pkg/v3 v3.139.0/go.mod h1:LtEg3PKYzbFnAKWFOENGRwGRNBpv16xKtbK+7esiSHU=
github.com/pulumi/pulumi/sdk/v3 v3.138.0 h1:1feN0YU1dHnbNw+cHaenmx3AgU0DEiKQbvjxaGQuShk=
github.com/pulumi/pulumi/sdk/v3 v3.138.0/go.mod h1:PvKsX88co8XuwuPdzolMvew5lZV+4JmZfkeSjj7A6dI=
github.com/pulumi/pulumi/sdk/v3 v3.139.0 h1:oBGP58b2Yw1HbPA3LHO/jHmOaVqFSEjw5BXd36ZbPLw=
github.com/pulumi/pulumi/sdk/v3 v3.139.0/go.mod h1:PvKsX88co8XuwuPdzolMvew5lZV+4JmZfkeSjj7A6dI=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
Expand Down
19 changes: 19 additions & 0 deletions packages/zod/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Field, Spec, Type } from '@unmango/tdl/v1alpha1/tdl';
import { create } from '@unmango/tdl/spec';
import { ZodObject, ZodType, type ZodSchema } from 'zod';

type Schema = Record<string, ZodSchema>;

export function parse(schema: Schema): Spec {
if (schema instanceof ZodObject) {
return create({
name: schema._def.description,
});
}

return create();
}

export function parseObject(name: string, schema: ZodType): Spec {
return create({ name });
}
15 changes: 15 additions & 0 deletions packages/zod/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "@unmango/2zod",
"module": "index.ts",
"type": "module",
"dependencies": {
"@unmango/tdl": "workspace:*",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}
7 changes: 7 additions & 0 deletions packages/zod/testdata/zod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { z } from 'zod';

const schema = z.object({
thing: z.string(),
}).describe('test');

export default schema;
27 changes: 27 additions & 0 deletions packages/zod/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}
51 changes: 51 additions & 0 deletions packages/zod2uml/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { parse, parseObject } from '@unmango/2zod';
import * as fs from 'fs/promises';
import * as path from 'path';
import { z, type ZodTypeAny } from 'zod';

if (process.argv.length !== 3) {
console.log('path to zod schema definition script is required');
process.exit(1);
}

const schemaPath = process.argv[2];
if (!await fs.exists(schemaPath)) {
console.log('not found: %s', schemaPath);
process.exit(1);
}

const module = z.record(z.string(), z.unknown());
const exports = module.parse(await import(schemaPath));

if (exports.default) {
if (!isZod(exports.default)) {
console.log('default export was not a supported zod type');
process.exit(1);
}

const ext = path.extname(schemaPath);
const name = path.basename(schemaPath, ext);
const spec = parseObject(name, exports.default);
console.log(JSON.stringify(spec));
} else {
const schemas: Record<string, ZodTypeAny> = {};
for (const [k, v] of Object.entries(exports)) {
if (!isZod(v)) {
console.log('exported member %s was not a supported zod type');
process.exit(1);
}

schemas[k] = v;
}

const spec = parse(schemas);
console.log(JSON.stringify(spec));
}

function isZod(x: unknown): x is ZodTypeAny {
if (!x?.constructor.name) {
return false;
}

return ['ZodObject'].includes(x.constructor.name);
}
16 changes: 16 additions & 0 deletions packages/zod2uml/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "zod2uml",
"license": "GPL-3.0-only",
"module": "index.ts",
"type": "module",
"dependencies": {
"@unmango/2zod": "workspace:*",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}
27 changes: 27 additions & 0 deletions packages/zod2uml/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}
Loading