Skip to content

Commit

Permalink
Add blueprint API (#4)
Browse files Browse the repository at this point in the history
* Add Usage

* Add test fixture

* Add @seamapi/types

* Export blueprint API

* Remove todo module

* Update describe
  • Loading branch information
razor-x authored Jun 17, 2024
1 parent 9cca930 commit 1456577
Show file tree
Hide file tree
Showing 25 changed files with 288 additions and 44 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,30 @@ Build tools for the Seam API using this blueprint.

TODO

## Motivation

TODO

## Installation

Add this as a dependency to your project using [npm] with

```
$ npm install @seamapi/blueprint
$ npm install --save-dev @seamapi/blueprint
```

[npm]: https://www.npmjs.com/

## Usage

```ts
import { createBlueprint } from '@seamapi/blueprint'
import * as types from '@seamapi/types'

const blueprint = createBlueprint(types)
console.log(JSON.stringify(blueprint)
```
## Development and Testing
### Quickstart
Expand Down
24 changes: 24 additions & 0 deletions examples/blueprint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Builder, Command, Describe, Handler } from 'landlubber'

import { createBlueprint, type TypesModule } from '@seamapi/blueprint'

interface Options {
moduleName: string
}

export const command: Command = 'blueprint [moduleName]'

export const describe: Describe = 'Create a blueprint from a module'

export const builder: Builder = {
moduleName: {
type: 'string',
default: '@seamapi/types/connect',
describe: 'Module name or path to import',
},
}

export const handler: Handler<Options> = async ({ moduleName, logger }) => {
const types = (await import(moduleName)) as TypesModule
logger.info({ data: createBlueprint(types) }, 'blueprint')
}
4 changes: 2 additions & 2 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import landlubber from 'landlubber'

import * as todo from './todo.js'
import * as blueprint from './blueprint.js'

const commands = [todo]
const commands = [blueprint]

await landlubber(commands).parse()
23 changes: 0 additions & 23 deletions examples/todo.ts

This file was deleted.

26 changes: 25 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"npm": ">= 9.0.0"
},
"devDependencies": {
"@seamapi/types": "1.184.0",
"@types/node": "^20.8.10",
"ava": "^6.0.1",
"c8": "^10.1.2",
Expand All @@ -83,6 +84,7 @@
"tsc-alias": "^1.8.2",
"tsup": "^8.0.1",
"tsx": "^4.6.2",
"typescript": "~5.3.3"
"typescript": "~5.3.3",
"zod": "^3.23.8"
}
}
15 changes: 15 additions & 0 deletions src/lib/blueprint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Openapi } from './openapi.js'

export interface Blueprint {
name: string
}

export interface TypesModule {
openapi: Openapi
}

export const createBlueprint = ({ openapi }: TypesModule): Blueprint => {
return {
name: openapi.info.title,
}
}
6 changes: 5 additions & 1 deletion src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export { todo } from './todo.js'
export {
type Blueprint,
createBlueprint,
type TypesModule,
} from './blueprint.js'
5 changes: 5 additions & 0 deletions src/lib/openapi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface Openapi {
info: {
title: string
}
}
7 changes: 0 additions & 7 deletions src/lib/todo.test.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/lib/todo.ts

This file was deleted.

10 changes: 10 additions & 0 deletions test/blueprint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import test from 'ava'

import { createBlueprint } from '@seamapi/blueprint'

import * as types from './fixtures/types/index.js'

test('createBlueprint', (t) => {
const blueprint = createBlueprint(types)
t.snapshot(blueprint, 'blueprint')
})
8 changes: 8 additions & 0 deletions test/fixtures/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as schemas from './schemas.js'

export { schemas }

export * from './model-types.js'
export { default as openapi } from './openapi.js'
export * from './route-schemas.js'
export * from './route-types.js'
5 changes: 5 additions & 0 deletions test/fixtures/types/model-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { z } from 'zod'

import type { foo } from './schemas.js'

export type Foo = z.infer<typeof foo>
79 changes: 79 additions & 0 deletions test/fixtures/types/openapi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
export default {
openapi: '3.0.0',
info: { title: 'Foo', version: '1.0.0' },
servers: [{ url: 'https://example.com' }],
tags: [{ description: 'foos', name: '/foos' }],
components: {
schemas: {
foo: {
type: 'object',
properties: {
foo_id: {
description: 'Foo id',
format: 'uuid',
type: 'string',
},
name: {
description: 'Foo name',
type: 'string',
},
},
required: ['foo_id', 'name'],
},
},
},
paths: {
'/foos/get': {
get: {
operationId: 'foosGetGet',
responses: {
200: {
content: {
'application/json': {
schema: {
properties: {
ok: { type: 'boolean' },
foo: { $ref: '#/components/schemas/foo' },
},
required: ['foo', 'ok'],
type: 'object',
},
},
},
description: 'OK',
},
400: { description: 'Bad Request' },
401: { description: 'Unauthorized' },
},
security: [],
summary: '/foos/get',
tags: ['/foos'],
},
post: {
operationId: 'foosGetPost',
responses: {
200: {
content: {
'application/json': {
schema: {
properties: {
ok: { type: 'boolean' },
foo: { $ref: '#/components/schemas/foo' },
},
required: ['foo', 'ok'],
type: 'object',
},
},
},
description: 'OK',
},
400: { description: 'Bad Request' },
401: { description: 'Unauthorized' },
},
security: [],
summary: '/foos/get',
tags: ['/foos'],
},
},
},
}
13 changes: 13 additions & 0 deletions test/fixtures/types/route-schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from 'zod'

import * as schemas from './schemas.js'

export const routes = {
'/foos/get': {
auth: 'none',
methods: ['GET', 'POST'],
jsonResponse: z.object({
foo: schemas.foo,
}),
},
} as const
13 changes: 13 additions & 0 deletions test/fixtures/types/route-specs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from 'zod'

import * as schemas from './schemas.js'

export const routes = {
'/foos/get': {
auth: 'none',
methods: ['GET', 'POST'],
jsonResponse: z.object({
foo: schemas.foo,
}),
},
} as const
25 changes: 25 additions & 0 deletions test/fixtures/types/route-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export interface Routes {
'/foos/get': {
route: '/foos/get'
method: 'GET' | 'POST'
queryParams: Record<string, unknown>
jsonBody: Record<string, unknown>
commonParams: Record<string, unknown>
formData: Record<string, unknown>
jsonResponse: {
foo: {
foo_id: string
name: string
}
}
}
}

export type RouteResponse<Path extends keyof Routes> =
Routes[Path]['jsonResponse']

export type RouteRequestBody<Path extends keyof Routes> =
Routes[Path]['jsonBody'] & Routes[Path]['commonParams']

export type RouteRequestParams<Path extends keyof Routes> =
Routes[Path]['queryParams'] & Routes[Path]['commonParams']
6 changes: 6 additions & 0 deletions test/fixtures/types/schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { z } from 'zod'

export const foo = z.object({
foo_id: z.string().uuid(),
name: z.string(),
})
9 changes: 9 additions & 0 deletions test/seamapi-blueprint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { openapi } from '@seamapi/types/connect'
import test from 'ava'

import { createBlueprint } from '@seamapi/blueprint'

test('createBlueprint', (t) => {
const blueprint = createBlueprint({ openapi })
t.snapshot(blueprint, 'blueprint')
})
13 changes: 13 additions & 0 deletions test/snapshots/blueprint.test.ts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Snapshot report for `test/blueprint.test.ts`

The actual snapshot is saved in `blueprint.test.ts.snap`.

Generated by [AVA](https://avajs.dev).

## createBlueprint

> blueprint
{
name: 'Foo',
}
Binary file added test/snapshots/blueprint.test.ts.snap
Binary file not shown.
Loading

0 comments on commit 1456577

Please sign in to comment.