-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
name: Release | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
release: | ||
name: Release | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Use pnpm 8.x | ||
uses: pnpm/action-setup@v2 | ||
with: | ||
version: 8 | ||
|
||
- name: Use Node.js 20.x | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: 20 | ||
cache: 'pnpm' | ||
|
||
- name: Install Dependencies | ||
run: pnpm install | ||
|
||
- name: Biome CI | ||
run: pnpm exec biome ci . | ||
|
||
- name: Build | ||
run: pnpm build | ||
|
||
- name: Semantic Release | ||
uses: cycjimmy/semantic-release-action@v3 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
HUSKY: 0 | ||
id: semantic | ||
with: | ||
semantic_version: 19.0.5 | ||
extra_plugins: | | ||
@semantic-release/[email protected] | ||
@semantic-release/[email protected] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/cdk.out | ||
/node_modules | ||
/dist |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
echo $(head -n1 $1) | npx commitlint --color |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Copyright (c) 2023, Ben Scholzen 'DASPRiD' | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
2. Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# JSON:API support for Koa with Zod | ||
|
||
[![Release](https://github.com/DASPRiD/koa-jsonapi-zod/actions/workflows/release.yml/badge.svg)](https://github.com/DASPRiD/mikro-orm-js-joda/actions/workflows/release.yml) | ||
|
||
This package provides support for working with JSON:API in Koa, taking all guesswork out of the equation. | ||
|
||
## Installation | ||
|
||
### npm | ||
```bash | ||
npm i koa-jsonapi-zod | ||
``` | ||
|
||
### pnpm | ||
```bash | ||
pnpm add koa-jsonapi-zod | ||
``` | ||
|
||
## Usage | ||
|
||
In order to serialize your entities into valid JSON:API responses, you have to set up a serialize manager which is | ||
composed of several entity serializers. You also have access to several utility functions meant for parsing incoming | ||
requests, as well as a middleware which takes care of handling requests and responses. | ||
|
||
For a complete example, have a look under [examples/complete](examples/complete). | ||
|
||
### Middlewares | ||
|
||
This package exports two middlewares, `jsonApiRequestMiddleware` and `jsonApiErrorMiddleware`. | ||
|
||
The former takes care of validating incoming requests and formatting responses accordingly. You can exclude specific | ||
paths from being handled by the middleware (e.g. RPC endpoints). This middleware should be registered as early as | ||
possible. | ||
|
||
The error middleware is a convenience middleware which traps all errors and creates appropriate error responses. You | ||
can also supply a logger function as an option, which allows you to log specific errors. This middleware should be | ||
registered right after the request middleware. | ||
|
||
For more details, see `index.ts` in the complete example. | ||
|
||
### Features not covered in the example | ||
|
||
#### Serialization context | ||
|
||
In some instances your serializers might require context about a request. One instance of this is where you want to | ||
expose specific fields of an entity only when the user has permission to access these. In that case you should define | ||
your serialization context first: | ||
|
||
```typescript | ||
type SerializerContext = { | ||
permissions?: string[]; | ||
}; | ||
``` | ||
|
||
You can the define that context as generic parameter in both the `SerializeManager` as well as your `EntitySerializer` | ||
instances. Since the context is always an optional property, you can then perform checks like this in e.g. your | ||
`getAttributes()` implementation: | ||
|
||
```typescript | ||
const attributes: Record<string, unknown> = { | ||
foo: "bar", | ||
baz: "bat", | ||
}; | ||
|
||
if (options.context?.permissions?.includes("read:secret")) { | ||
attributes.secret = "super secrtet information"; | ||
} | ||
``` | ||
|
||
#### Filtering | ||
|
||
You can add filters to list handlers as well. JSON:API does not define the structure of filters itself, except that the | ||
`filter` property should be used for this. Whether you make that property an object or a plain string is up to you. | ||
Simply provide a `Zod` schema to the `filterSchema` property, and you will get a `filter` property on the result back. | ||
|
||
#### Pagination | ||
|
||
Similar to filters you can also supply a `pageSchema` property, which will result in a `page` result. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
{ | ||
"$schema": "https://biomejs.dev/schemas/1.5.2/schema.json", | ||
"organizeImports": { | ||
"enabled": true | ||
}, | ||
"files": { | ||
"include": [ | ||
"biome.json", | ||
"commitlint.config.cjs", | ||
"release.config.cjs", | ||
"src/**/*", | ||
"examples/*/src/**/*" | ||
] | ||
}, | ||
"linter": { | ||
"enabled": true, | ||
"rules": { | ||
"recommended": true, | ||
"nursery": { | ||
"noEmptyTypeParameters": "error", | ||
"noInvalidUseBeforeDeclaration": "error", | ||
"noUnusedImports": "error", | ||
"noUnusedPrivateClassMembers": "error", | ||
"noUselessLoneBlockStatements": "error", | ||
"noUselessTernary": "error", | ||
"useExportType": "error", | ||
"useImportType": "error", | ||
"useForOf": "error", | ||
"useGroupedTypeImport": "error" | ||
}, | ||
"complexity": { | ||
"noExcessiveCognitiveComplexity": "warn", | ||
"useSimplifiedLogicExpression": "error" | ||
}, | ||
"correctness": { | ||
"noNewSymbol": "error" | ||
}, | ||
"style": { | ||
"useBlockStatements": "error", | ||
"useCollapsedElseIf": "error", | ||
"useShorthandArrayType": "error", | ||
"useShorthandAssign": "error", | ||
"useSingleCaseStatement": "error" | ||
}, | ||
"suspicious": { | ||
"noApproximativeNumericConstant": "warn", | ||
"noConsoleLog": "error" | ||
} | ||
} | ||
}, | ||
"formatter": { | ||
"indentStyle": "space", | ||
"indentWidth": 4, | ||
"lineWidth": 100 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = { extends: ["@commitlint/config-conventional"] }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Complete Example | ||
|
||
This is a complete example showcasing all features of `koa-jsonapi-zod`. It utilizes Mikro ORM as data source, but you | ||
can of course use any other data source. | ||
|
||
To run the example, simply execute `pnpm start`. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "complete", | ||
"type": "module", | ||
"dependencies": { | ||
"@js-joda/core": "^5.6.1", | ||
"@mikro-orm/core": "^6.1.0", | ||
"@mikro-orm/sqlite": "^6.1.0", | ||
"flat": "^6.0.1", | ||
"http-errors": "^2.0.0", | ||
"koa": "^2.15.0", | ||
"koa-bodyparser": "^4.4.1", | ||
"koa-jsonapi-zod": "workspace:*", | ||
"koa-tree-router": "^0.12.1", | ||
"mikro-orm-js-joda": "^1.0.1", | ||
"zod": "^3.22.4" | ||
}, | ||
"devDependencies": { | ||
"@types/http-errors": "^2.0.4", | ||
"@types/koa": "^2.14.0", | ||
"@types/koa-bodyparser": "^4.3.12", | ||
"tsx": "^4.7.0", | ||
"typescript": "^5.3.3" | ||
}, | ||
"scripts": { | ||
"start": "tsx watch src/index.ts" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { randomUUID } from "crypto"; | ||
import { ZonedDateTime } from "@js-joda/core"; | ||
import { Entity, ManyToOne, PrimaryKey, Property, type Ref, Reference, t } from "@mikro-orm/core"; | ||
import { ZonedDateTimeType } from "mikro-orm-js-joda"; | ||
import { Person } from "./Person.js"; | ||
|
||
@Entity() | ||
export class Article { | ||
@PrimaryKey({ type: t.uuid }) | ||
public readonly id: string = randomUUID(); | ||
|
||
@Property({ type: ZonedDateTimeType }) | ||
public readonly createdAt = ZonedDateTime.now(); | ||
|
||
@Property({ type: ZonedDateTimeType, onUpdate: () => ZonedDateTime.now() }) | ||
public readonly updatedAt = ZonedDateTime.now(); | ||
|
||
@Property({ type: t.text }) | ||
public title: string; | ||
|
||
@ManyToOne(() => Person, { ref: true }) | ||
public author: Ref<Person>; | ||
|
||
public constructor(title: string, author: Person) { | ||
this.title = title; | ||
this.author = Reference.create(author); | ||
} | ||
} |