Skip to content

Commit

Permalink
docs: Update arktype and remix examples
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavoguichard committed Jul 15, 2024
1 parent f11075d commit 468d111
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 302 deletions.
2 changes: 1 addition & 1 deletion examples/arktype/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ This simple example can be a reference to adapt composable-functions to any othe

There are two approaches to use composable-functions with a custom parser:
- Create an adapter function that will receive a schema and return a schema in the shape of a `ParserSchena`. Example: [the `adapt` function](./src/adapters.ts). This is our preferred approach and we wrote a [post about it](https://dev.to/seasonedcc/using-arktype-in-place-of-zod-how-to-adapt-parsers-3bd5).
- Create your custom `withSchema` and `applySchema` that will validate your input and context and return a `Result`. Example: [the `withArkSchema` and `applyArkSchema` functions](./src/adapters.ts).
- Create your custom `applySchema` that will validate your input and context and return a `Result`. Example: [the `applyArkSchema` function](./src/adapters.ts).

Check out the [`./src`](./src/) directory to understand how we implemented both approaches with [`arktype`](https://github.com/arktypeio/arktype).
4 changes: 2 additions & 2 deletions examples/arktype/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"tsx": "^4.15.8"
},
"dependencies": {
"arktype": "2.0.0-dev.26",
"arktype": "2.0.0-dev.29",
"composable-functions": "file:../../npm",
"typescript": "^5.5.2"
"typescript": "^5.5.3"
}
}
38 changes: 19 additions & 19 deletions examples/arktype/pnpm-lock.yaml

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

24 changes: 4 additions & 20 deletions examples/arktype/src/adapters.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import {
ApplySchemaReturn,
composable,
Composable,
ComposableWithSchema,
ContextError,
failure,
InputError,
ParserSchema,
UnpackData,
} from 'composable-functions'
import { type, Type } from 'arktype'

Expand All @@ -31,8 +28,8 @@ function adapt<T extends Type>(schema: T): ParserSchema<T['infer']> {
*/
function applyArkSchema<I, C>(inputSchema?: Type<I>, contextSchema?: Type<C>) {
//
return <R, Input, Context>(
fn: Composable<(input: Input, context: Context) => R>,
return <R, Input extends I, Context extends C>(
fn: (input: Input, context: Context) => R,
) => {
const callable = ((input?: unknown, context?: unknown) => {
const ctxResult = (contextSchema ?? type('unknown'))(context)
Expand All @@ -55,24 +52,11 @@ function applyArkSchema<I, C>(inputSchema?: Type<I>, contextSchema?: Type<C>) {
: []
return failure([...inputErrors, ...ctxErrors])
}
return fn(result as Input, ctxResult as Context)
return composable(fn)(result as Input, ctxResult as Context)
}) as ApplySchemaReturn<I, C, typeof fn>
;(callable as any).kind = 'composable' as const
return callable
}
}

function withArkSchema<I, C>(
inputSchema?: Type<I>,
contextSchema?: Type<C>,
): <Fn extends (input: I, context: C) => unknown>(
fn: Fn,
) => ComposableWithSchema<UnpackData<Composable<Fn>>> {
return (handler) =>
applyArkSchema(
inputSchema,
contextSchema,
)(composable(handler)) as ComposableWithSchema<any>
}

export { adapt, withArkSchema, applyArkSchema }
export { adapt, applyArkSchema }
8 changes: 4 additions & 4 deletions examples/arktype/src/usage.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { composable, withSchema } from 'composable-functions'
import { applyArkSchema, withArkSchema, adapt } from './adapters'
import { applySchema, composable } from 'composable-functions'
import { applyArkSchema, adapt } from './adapters'
import { type } from 'arktype'

const appliedFn = applyArkSchema(type({ a: 'number', b: 'number' }))(
composable(({ a, b }: { a: number; b: number }) => a + b),
)
const withFn = withArkSchema(
const withFn = applyArkSchema(
type({ a: 'number' }),
type({ b: 'number' }),
)(({ a }, { b }) => a + b)

const withAdapt = withSchema(adapt(type({ a: 'number', b: 'number' })))(
const withAdapt = applySchema(adapt(type({ a: 'number', b: 'number' })))(
({ a, b }) => a + b,
)

Expand Down
4 changes: 2 additions & 2 deletions examples/remix/app/business/colors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as z from 'zod'
import { withSchema } from 'composable-functions'
import { applySchema } from 'composable-functions'
import { makeService } from 'make-service'

const reqRes = makeService('https://reqres.in/api')
Expand All @@ -22,7 +22,7 @@ const getColor = async ({ id }: { id: string }) => {
return response.json(z.object({ data: colorSchema }))
}

const mutateColor = withSchema(
const mutateColor = applySchema(
z.object({
id: z.string(),
color: z.string().min(1, 'Color is required'),
Expand Down
6 changes: 3 additions & 3 deletions examples/remix/app/business/gpd.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { z } from 'zod'
import { withSchema } from 'composable-functions'
import { applySchema } from 'composable-functions'
import { createCookie } from '@remix-run/node'

const cookie = createCookie('gpd', {
maxAge: 20, // seconds
})

const getGPDInfo = withSchema(
const getGPDInfo = applySchema(
z.any(),
// The "context" knows there can be cookie information in the Request
z.object({ agreed: z.boolean().optional() }),
)(async (_input, { agreed }) => {
return { agreed }
})

const agreeToGPD = withSchema(
const agreeToGPD = applySchema(
// Agreeing to the GPD is user input
z.object({ agree: z.preprocess((v) => v === 'true', z.boolean()) }),
)(async ({ agree }) => ({ agreed: agree }))
Expand Down
4 changes: 2 additions & 2 deletions examples/remix/app/routes/color.$id.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node'
import { Form, Link, useActionData, useLoaderData } from '@remix-run/react'
import { withSchema, inputFromForm } from 'composable-functions'
import { applySchema, inputFromForm } from 'composable-functions'
import tinycolor from 'tinycolor2'
import { getColor, mutateColor } from '~/business/colors'
import { actionResponse, loaderResponseOrThrow } from '~/lib'
import { z } from 'zod'

export const loader = async ({ params }: LoaderFunctionArgs) => {
const result = await withSchema(z.object({ id: z.string() }))(getColor)(
const result = await applySchema(z.object({ id: z.string() }))(getColor)(
params,
)
return loaderResponseOrThrow(result)
Expand Down
24 changes: 12 additions & 12 deletions examples/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,30 @@
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/node": "^2.10.0",
"@remix-run/react": "^2.10.0",
"@remix-run/serve": "^2.10.0",
"@remix-run/node": "^2.10.2",
"@remix-run/react": "^2.10.2",
"@remix-run/serve": "^2.10.2",
"@types/tinycolor2": "^1.4.6",
"composable-functions": "file:../../npm",
"isbot": "^5.1.10",
"isbot": "^5.1.13",
"make-service": "^3.0.0",
"postcss": "^8.4.38",
"postcss": "^8.4.39",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tinycolor2": "^1.6.0",
"zod": "^3.23.8"
},
"devDependencies": {
"@remix-run/dev": "^2.10.0",
"@remix-run/eslint-config": "^2.10.0",
"@remix-run/dev": "^2.10.2",
"@remix-run/eslint-config": "^2.10.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.14.1",
"@typescript-eslint/parser": "^7.14.1",
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.16.0",
"eslint": "^8.57.0",
"tailwindcss": "^3.4.4",
"typescript": "^5.5.2",
"vite": "^5.3.1",
"tailwindcss": "^3.4.5",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vite-tsconfig-paths": "^4.3.2"
},
"engines": {
Expand Down
Loading

0 comments on commit 468d111

Please sign in to comment.