cushin-monorepo 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/.claude/settings.local.json +44 -0
- package/CHANGELOG.md +93 -0
- package/LICENSE +0 -0
- package/README.md +482 -0
- package/biome.json +34 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1552 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +84 -0
- package/dist/config/index.js +69 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +43 -0
- package/dist/config/schema.js +14 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +1666 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/client.d.ts +40 -0
- package/dist/runtime/client.js +260 -0
- package/dist/runtime/client.js.map +1 -0
- package/package.json +41 -0
- package/packages/api-codegen/CHANGELOG.md +86 -0
- package/packages/api-codegen/biome.json +34 -0
- package/packages/api-codegen/dist/cli.js +1038 -0
- package/packages/api-codegen/dist/cli.js.map +1 -0
- package/packages/api-codegen/dist/index.d.ts +103 -0
- package/packages/api-codegen/dist/index.js +1026 -0
- package/packages/api-codegen/dist/index.js.map +1 -0
- package/packages/api-codegen/node_modules/.bin/acorn +21 -0
- package/packages/api-codegen/node_modules/.bin/conventional-changelog +21 -0
- package/packages/api-codegen/node_modules/.bin/conventional-commits-parser +21 -0
- package/packages/api-codegen/node_modules/.bin/esbuild +21 -0
- package/packages/api-codegen/node_modules/.bin/eslint +21 -0
- package/packages/api-codegen/node_modules/.bin/jiti +21 -0
- package/packages/api-codegen/node_modules/.bin/next +21 -0
- package/packages/api-codegen/node_modules/.bin/tsc +21 -0
- package/packages/api-codegen/node_modules/.bin/tsserver +21 -0
- package/packages/api-codegen/node_modules/.bin/tsup +21 -0
- package/packages/api-codegen/node_modules/.bin/tsup-node +21 -0
- package/packages/api-codegen/node_modules/.bin/vitest +21 -0
- package/packages/api-codegen/package.json +88 -0
- package/packages/api-runtime/CHANGELOG.md +46 -0
- package/packages/api-runtime/README.md +95 -0
- package/packages/api-runtime/dist/chunk-3FFXWCVP.js +17 -0
- package/packages/api-runtime/dist/chunk-3FFXWCVP.js.map +1 -0
- package/packages/api-runtime/dist/chunk-EZ5P7OPH.js +267 -0
- package/packages/api-runtime/dist/chunk-EZ5P7OPH.js.map +1 -0
- package/packages/api-runtime/dist/client.d.ts +40 -0
- package/packages/api-runtime/dist/client.js +13 -0
- package/packages/api-runtime/dist/client.js.map +1 -0
- package/packages/api-runtime/dist/index.d.ts +3 -0
- package/packages/api-runtime/dist/index.js +21 -0
- package/packages/api-runtime/dist/index.js.map +1 -0
- package/packages/api-runtime/dist/schema.d.ts +45 -0
- package/packages/api-runtime/dist/schema.js +11 -0
- package/packages/api-runtime/dist/schema.js.map +1 -0
- package/packages/api-runtime/node_modules/.bin/esbuild +21 -0
- package/packages/api-runtime/node_modules/.bin/jiti +21 -0
- package/packages/api-runtime/node_modules/.bin/tsc +21 -0
- package/packages/api-runtime/node_modules/.bin/tsserver +21 -0
- package/packages/api-runtime/node_modules/.bin/tsup +21 -0
- package/packages/api-runtime/node_modules/.bin/tsup-node +21 -0
- package/packages/api-runtime/package.json +54 -0
- package/packages/cli/CHANGELOG.md +34 -0
- package/packages/cli/biome.json +34 -0
- package/packages/cli/dist/index.d.ts +27 -0
- package/packages/cli/dist/index.js +183 -0
- package/packages/cli/dist/index.js.map +1 -0
- package/packages/cli/node_modules/.bin/esbuild +21 -0
- package/packages/cli/node_modules/.bin/jiti +21 -0
- package/packages/cli/node_modules/.bin/tsc +21 -0
- package/packages/cli/node_modules/.bin/tsserver +21 -0
- package/packages/cli/node_modules/.bin/tsup +21 -0
- package/packages/cli/node_modules/.bin/tsup-node +21 -0
- package/packages/cli/package.json +47 -0
- package/pnpm-workspace.yaml +2 -0
- package/test-config.js +9 -0
- package/test-content-type-handling.mjs +100 -0
- package/test-endpoints-config.mjs +144 -0
- package/test-formdata-content-type-protection.mjs +127 -0
- package/test-formdata-runtime.mjs +127 -0
- package/test-full-integration.mjs +90 -0
- package/test-headers-formdata.mjs +97 -0
- package/test-headers-runtime.mjs +106 -0
- package/test-headers.mjs +79 -0
- package/test-internal-calls.mjs +57 -0
- package/test-ky-formdata.mjs +81 -0
- package/test-output/actions.ts +134 -0
- package/test-output/client.ts +81 -0
- package/test-output/hooks.ts +182 -0
- package/test-output/index.ts +9 -0
- package/test-output/prefetchs.ts +25 -0
- package/test-output/queries.ts +78 -0
- package/test-output/query-keys.ts +16 -0
- package/test-output/query-options.ts +38 -0
- package/test-output/server-client.ts +32 -0
- package/test-output/types.ts +61 -0
- package/test-real-endpoints.mjs +132 -0
- package/test-runtime-params.mjs +160 -0
- package/test-simple-config.mjs +71 -0
- package/tsconfig.base.json +29 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changesets
|
|
2
|
+
|
|
3
|
+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
|
4
|
+
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
|
5
|
+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
6
|
+
|
|
7
|
+
We have a quick list of common questions to get you started engaging with this project in
|
|
8
|
+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
|
3
|
+
"changelog": "@changesets/cli/changelog",
|
|
4
|
+
"commit": false,
|
|
5
|
+
"fixed": [],
|
|
6
|
+
"linked": [],
|
|
7
|
+
"access": "public",
|
|
8
|
+
"baseBranch": "main",
|
|
9
|
+
"updateInternalDependencies": "patch",
|
|
10
|
+
"ignore": [],
|
|
11
|
+
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
|
|
12
|
+
"onlyUpdatePeerDependentsWhenOutOfRange": true
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(pnpm install:*)",
|
|
5
|
+
"Bash(pnpm build:*)",
|
|
6
|
+
"Bash(node /home/hash/work/node/api-codegen/packages/api-codegen/dist/cli.js:*)",
|
|
7
|
+
"Bash(tree:*)",
|
|
8
|
+
"Bash(mkdir:*)",
|
|
9
|
+
"Bash(node /home/hash/work/node/codegen/test-import.mjs:*)",
|
|
10
|
+
"Bash(node /home/hash/work/node/codegen/packages/test-package/test.mjs:*)",
|
|
11
|
+
"Bash(cat:*)",
|
|
12
|
+
"Bash(pnpm changeset:*)",
|
|
13
|
+
"Bash(pnpm version-packages:*)",
|
|
14
|
+
"Bash(git add:*)",
|
|
15
|
+
"Bash(git commit:*)",
|
|
16
|
+
"Bash(npx tsc:*)",
|
|
17
|
+
"Bash(pnpm typecheck:*)",
|
|
18
|
+
"Bash(node test.mjs:*)",
|
|
19
|
+
"Bash(git --git-dir=/home/hash/work/node/codegen/.git --work-tree=/home/hash/work/node/codegen status:*)",
|
|
20
|
+
"Bash(bash -c \"cd /home/hash/work/node/codegen && git status\")",
|
|
21
|
+
"Bash(bash -c 'cd /home/hash/work/node/codegen && pnpm changeset')",
|
|
22
|
+
"Bash(bash -c 'export HOME=/home/hash && cd /home/hash/work/node/codegen && /home/hash/work/node/codegen/node_modules/.bin/changeset version':*)",
|
|
23
|
+
"Bash(export HOME=/home/hash:*)",
|
|
24
|
+
"Bash(/usr/bin/bash:*)",
|
|
25
|
+
"Bash(node /home/hash/work/node/codegen/test-runtime-params.mjs:*)",
|
|
26
|
+
"Bash(node /home/hash/work/node/codegen/test-full-integration.mjs:*)",
|
|
27
|
+
"Bash(node /home/hash/work/node/codegen/test-internal-calls.mjs:*)",
|
|
28
|
+
"Bash(pnpm publish:*)",
|
|
29
|
+
"Bash(node test-full-integration.mjs:*)",
|
|
30
|
+
"Bash(node /home/hash/work/node/codegen/packages/api-codegen/dist/cli.js generate:*)",
|
|
31
|
+
"Bash(node test-headers-formdata.mjs:*)",
|
|
32
|
+
"Bash(node test-headers.mjs:*)",
|
|
33
|
+
"Bash(node test-headers-runtime.mjs:*)",
|
|
34
|
+
"Bash(node test-formdata-runtime.mjs:*)",
|
|
35
|
+
"Bash(pnpm -F @cushin/api-runtime build:*)",
|
|
36
|
+
"Bash(node test-ky-formdata.mjs:*)",
|
|
37
|
+
"Bash(pnpm add:*)",
|
|
38
|
+
"Bash(node test-content-type-handling.mjs:*)",
|
|
39
|
+
"Bash(node test-formdata-content-type-protection.mjs:*)"
|
|
40
|
+
],
|
|
41
|
+
"deny": [],
|
|
42
|
+
"ask": []
|
|
43
|
+
}
|
|
44
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
## <small>4.0.5 (2025-12-19)</small>
|
|
2
|
+
|
|
3
|
+
* feat: add custom headers support for endpoints - allows per-endpoint header configuration for API keys, tracking, and metadata
|
|
4
|
+
* feat: add automatic FormData detection and handling - runtime client now detects FormData bodies and handles Content-Type correctly
|
|
5
|
+
* docs: add comprehensive CUSTOM_HEADERS.md documentation with examples for file uploads, React hooks, and Next.js server actions
|
|
6
|
+
* docs: update README with custom headers and FormData usage examples
|
|
7
|
+
|
|
8
|
+
## <small>2.0.6 (2025-12-18)</small>
|
|
9
|
+
|
|
10
|
+
* fix: handle undefined params in server-client and client type definitions - endpoints without params, query, or body no longer require passing undefined
|
|
11
|
+
|
|
12
|
+
## <small>1.0.5 (2025-11-24)</small>
|
|
13
|
+
|
|
14
|
+
* fix: add jiti loader to support TypeScript endpoint files ([eac2867](https://github.com/cushin-org/api-codegen/commit/eac2867))
|
|
15
|
+
* fix: remove unused imports ([7c46e10](https://github.com/cushin-org/api-codegen/commit/7c46e10))
|
|
16
|
+
* fix: resolve build and npm deployment errors ([cef18d7](https://github.com/cushin-org/api-codegen/commit/cef18d7))
|
|
17
|
+
* chore: bump version to 1.0.1 - fix build and npm deployment errors ([6bda5b4](https://github.com/cushin-org/api-codegen/commit/6bda5b4))
|
|
18
|
+
* chore: bump version to 1.0.2 ([5d3a6cd](https://github.com/cushin-org/api-codegen/commit/5d3a6cd))
|
|
19
|
+
* chore: bump version to 1.0.3 ([d7f2489](https://github.com/cushin-org/api-codegen/commit/d7f2489))
|
|
20
|
+
* chore: bump version to 1.0.4 ([7aa777e](https://github.com/cushin-org/api-codegen/commit/7aa777e))
|
|
21
|
+
* chore: bump version to 1.0.4 ([a94bed3](https://github.com/cushin-org/api-codegen/commit/a94bed3))
|
|
22
|
+
* chore: remove unused packed file ([694d3a8](https://github.com/cushin-org/api-codegen/commit/694d3a8))
|
|
23
|
+
* docs: update CHANGELOG ([01b2c9c](https://github.com/cushin-org/api-codegen/commit/01b2c9c))
|
|
24
|
+
* docs: update document for cli ([e27c4fa](https://github.com/cushin-org/api-codegen/commit/e27c4fa))
|
|
25
|
+
* docs: update github username ([98b86f0](https://github.com/cushin-org/api-codegen/commit/98b86f0))
|
|
26
|
+
* Add GitHub Actions workflow for npm publish ([0298a75](https://github.com/cushin-org/api-codegen/commit/0298a75))
|
|
27
|
+
* init project ([d0847c2](https://github.com/cushin-org/api-codegen/commit/d0847c2))
|
|
28
|
+
* update README ([65b6962](https://github.com/cushin-org/api-codegen/commit/65b6962))
|
|
29
|
+
* update README ([e1866ed](https://github.com/cushin-org/api-codegen/commit/e1866ed))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## <small>1.0.4 (2025-11-24)</small>
|
|
34
|
+
|
|
35
|
+
* fix: add jiti loader to support TypeScript endpoint files ([eac2867](https://github.com/cushin-org/api-codegen/commit/eac2867))
|
|
36
|
+
* fix: remove unused imports ([7c46e10](https://github.com/cushin-org/api-codegen/commit/7c46e10))
|
|
37
|
+
* fix: resolve build and npm deployment errors ([cef18d7](https://github.com/cushin-org/api-codegen/commit/cef18d7))
|
|
38
|
+
* chore: bump version to 1.0.1 - fix build and npm deployment errors ([6bda5b4](https://github.com/cushin-org/api-codegen/commit/6bda5b4))
|
|
39
|
+
* chore: bump version to 1.0.2 ([5d3a6cd](https://github.com/cushin-org/api-codegen/commit/5d3a6cd))
|
|
40
|
+
* chore: bump version to 1.0.3 ([d7f2489](https://github.com/cushin-org/api-codegen/commit/d7f2489))
|
|
41
|
+
* chore: bump version to 1.0.4 ([7aa777e](https://github.com/cushin-org/api-codegen/commit/7aa777e))
|
|
42
|
+
* chore: bump version to 1.0.4 ([a94bed3](https://github.com/cushin-org/api-codegen/commit/a94bed3))
|
|
43
|
+
* chore: remove unused packed file ([694d3a8](https://github.com/cushin-org/api-codegen/commit/694d3a8))
|
|
44
|
+
* docs: update CHANGELOG ([01b2c9c](https://github.com/cushin-org/api-codegen/commit/01b2c9c))
|
|
45
|
+
* docs: update document for cli ([e27c4fa](https://github.com/cushin-org/api-codegen/commit/e27c4fa))
|
|
46
|
+
* docs: update github username ([98b86f0](https://github.com/cushin-org/api-codegen/commit/98b86f0))
|
|
47
|
+
* Add GitHub Actions workflow for npm publish ([0298a75](https://github.com/cushin-org/api-codegen/commit/0298a75))
|
|
48
|
+
* init project ([d0847c2](https://github.com/cushin-org/api-codegen/commit/d0847c2))
|
|
49
|
+
* update README ([65b6962](https://github.com/cushin-org/api-codegen/commit/65b6962))
|
|
50
|
+
* update README ([e1866ed](https://github.com/cushin-org/api-codegen/commit/e1866ed))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## <small>1.0.4 (2025-11-24)</small>
|
|
55
|
+
|
|
56
|
+
* chore: bump version to 1.0.1 - fix build and npm deployment errors ([6bda5b4](https://github.com/cushin-org/api-codegen/commit/6bda5b4))
|
|
57
|
+
* chore: bump version to 1.0.2 ([5d3a6cd](https://github.com/cushin-org/api-codegen/commit/5d3a6cd))
|
|
58
|
+
* chore: bump version to 1.0.3 ([d7f2489](https://github.com/cushin-org/api-codegen/commit/d7f2489))
|
|
59
|
+
* chore: bump version to 1.0.4 ([a94bed3](https://github.com/cushin-org/api-codegen/commit/a94bed3))
|
|
60
|
+
* chore: remove unused packed file ([694d3a8](https://github.com/cushin-org/api-codegen/commit/694d3a8))
|
|
61
|
+
* fix: add jiti loader to support TypeScript endpoint files ([eac2867](https://github.com/cushin-org/api-codegen/commit/eac2867))
|
|
62
|
+
* fix: resolve build and npm deployment errors ([cef18d7](https://github.com/cushin-org/api-codegen/commit/cef18d7))
|
|
63
|
+
* docs: update CHANGELOG ([01b2c9c](https://github.com/cushin-org/api-codegen/commit/01b2c9c))
|
|
64
|
+
* docs: update document for cli ([e27c4fa](https://github.com/cushin-org/api-codegen/commit/e27c4fa))
|
|
65
|
+
* docs: update github username ([98b86f0](https://github.com/cushin-org/api-codegen/commit/98b86f0))
|
|
66
|
+
* Add GitHub Actions workflow for npm publish ([0298a75](https://github.com/cushin-org/api-codegen/commit/0298a75))
|
|
67
|
+
* init project ([d0847c2](https://github.com/cushin-org/api-codegen/commit/d0847c2))
|
|
68
|
+
* update README ([65b6962](https://github.com/cushin-org/api-codegen/commit/65b6962))
|
|
69
|
+
* update README ([e1866ed](https://github.com/cushin-org/api-codegen/commit/e1866ed))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## <small>1.0.2 (2025-11-22)</small>
|
|
74
|
+
|
|
75
|
+
* docs: update document for cli ([e27c4fa](https://github.com/cushin-org/api-codegen/commit/e27c4fa))
|
|
76
|
+
* docs: update github username ([98b86f0](https://github.com/cushin-org/api-codegen/commit/98b86f0))
|
|
77
|
+
* Add GitHub Actions workflow for npm publish ([0298a75](https://github.com/cushin-org/api-codegen/commit/0298a75))
|
|
78
|
+
* init project ([d0847c2](https://github.com/cushin-org/api-codegen/commit/d0847c2))
|
|
79
|
+
* update README ([65b6962](https://github.com/cushin-org/api-codegen/commit/65b6962))
|
|
80
|
+
* update README ([e1866ed](https://github.com/cushin-org/api-codegen/commit/e1866ed))
|
|
81
|
+
* fix: resolve build and npm deployment errors ([cef18d7](https://github.com/cushin-org/api-codegen/commit/cef18d7))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# 1.0.0 (2025-11-22)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
### Bug Fixes
|
|
89
|
+
|
|
90
|
+
* resolve build and npm deployment errors ([cef18d7](https://github.com/hashdotlee/api-codegen/commit/cef18d795e2ac83818b3a06b7bb38bdecc46295b))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
package/LICENSE
ADDED
|
File without changes
|
package/README.md
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
# @cushin/api-codegen
|
|
2
|
+
|
|
3
|
+
Type-safe API client generator for React/Next.js applications with automatic hooks and server actions generation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Type-Safe**: Full TypeScript support with Zod schema validation
|
|
8
|
+
- 🔄 **Auto-Generated**: Generate React Query hooks, Server Actions, and Server Queries
|
|
9
|
+
- 🚀 **Framework Agnostic**: Works with Vite, Next.js, and more
|
|
10
|
+
- 🔐 **Auth Built-in**: Token refresh, automatic retry with customizable callbacks
|
|
11
|
+
- 📦 **Zero Config**: Simple configuration with sensible defaults
|
|
12
|
+
- 🎨 **Customizable**: Custom templates and generation options
|
|
13
|
+
- 📤 **File Uploads**: Automatic FormData detection and handling
|
|
14
|
+
- 🔧 **Custom Headers**: Per-endpoint header configuration for API keys and metadata
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @cushin/api-codegen ky zod
|
|
20
|
+
# or
|
|
21
|
+
pnpm add @cushin/api-codegen ky zod
|
|
22
|
+
# or
|
|
23
|
+
yarn add @cushin/api-codegen ky zod
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For React Query support (client-side):
|
|
27
|
+
```bash
|
|
28
|
+
npm install @tanstack/react-query
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### 1. Initialize Configuration
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx @cushin/api-codegen init --provider vite
|
|
37
|
+
# or for Next.js
|
|
38
|
+
npx @cushin/api-codegen init --provider nextjs
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This creates `api-codegen.config.js`:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
/** @type {import('@cushin/api-codegen').UserConfig} */
|
|
45
|
+
export default {
|
|
46
|
+
provider: 'vite',
|
|
47
|
+
endpoints: './lib/api/config/endpoints.ts',
|
|
48
|
+
output: './lib/api/generated',
|
|
49
|
+
baseUrl: process.env.VITE_API_URL,
|
|
50
|
+
generateHooks: true,
|
|
51
|
+
generateClient: true,
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 2. Define Your API Endpoints
|
|
56
|
+
|
|
57
|
+
Create your endpoints configuration file:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// lib/api/config/endpoints.ts
|
|
61
|
+
import { z } from 'zod';
|
|
62
|
+
import { defineConfig, defineEndpoint } from '@cushin/api-codegen';
|
|
63
|
+
|
|
64
|
+
// Define your schemas
|
|
65
|
+
const UserSchema = z.object({
|
|
66
|
+
id: z.string(),
|
|
67
|
+
name: z.string(),
|
|
68
|
+
email: z.string().email(),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const CreateUserSchema = z.object({
|
|
72
|
+
name: z.string(),
|
|
73
|
+
email: z.string().email(),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Define your endpoints
|
|
77
|
+
export const apiConfig = defineConfig({
|
|
78
|
+
baseUrl: 'https://api.example.com',
|
|
79
|
+
endpoints: {
|
|
80
|
+
// GET request
|
|
81
|
+
getUser: defineEndpoint({
|
|
82
|
+
path: '/users/:id',
|
|
83
|
+
method: 'GET',
|
|
84
|
+
params: z.object({ id: z.string() }),
|
|
85
|
+
response: UserSchema,
|
|
86
|
+
tags: ['users', 'query'],
|
|
87
|
+
description: 'Get user by ID',
|
|
88
|
+
}),
|
|
89
|
+
|
|
90
|
+
// GET with query params
|
|
91
|
+
listUsers: defineEndpoint({
|
|
92
|
+
path: '/users',
|
|
93
|
+
method: 'GET',
|
|
94
|
+
query: z.object({
|
|
95
|
+
page: z.number().optional(),
|
|
96
|
+
limit: z.number().optional(),
|
|
97
|
+
}),
|
|
98
|
+
response: z.array(UserSchema),
|
|
99
|
+
tags: ['users', 'query'],
|
|
100
|
+
}),
|
|
101
|
+
|
|
102
|
+
// POST request
|
|
103
|
+
createUser: defineEndpoint({
|
|
104
|
+
path: '/users',
|
|
105
|
+
method: 'POST',
|
|
106
|
+
body: CreateUserSchema,
|
|
107
|
+
response: UserSchema,
|
|
108
|
+
tags: ['users', 'mutation'],
|
|
109
|
+
}),
|
|
110
|
+
|
|
111
|
+
// PUT request with params
|
|
112
|
+
updateUser: defineEndpoint({
|
|
113
|
+
path: '/users/:id',
|
|
114
|
+
method: 'PUT',
|
|
115
|
+
params: z.object({ id: z.string() }),
|
|
116
|
+
body: CreateUserSchema,
|
|
117
|
+
response: UserSchema,
|
|
118
|
+
tags: ['users', 'mutation'],
|
|
119
|
+
}),
|
|
120
|
+
|
|
121
|
+
// DELETE request
|
|
122
|
+
deleteUser: defineEndpoint({
|
|
123
|
+
path: '/users/:id',
|
|
124
|
+
method: 'DELETE',
|
|
125
|
+
params: z.object({ id: z.string() }),
|
|
126
|
+
response: z.object({ success: z.boolean() }),
|
|
127
|
+
tags: ['users', 'mutation'],
|
|
128
|
+
}),
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 3. Generate Code
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx @cushin/api-codegen generate
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This generates:
|
|
140
|
+
- `generated/types.ts` - Type definitions
|
|
141
|
+
- `generated/client.ts` - API client
|
|
142
|
+
- `generated/hooks.ts` - React Query hooks
|
|
143
|
+
- `generated/actions.ts` - Server Actions (Next.js only)
|
|
144
|
+
- `generated/queries.ts` - Server Queries (Next.js only)
|
|
145
|
+
|
|
146
|
+
### 4. Initialize Client (Vite)
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// lib/auth/provider.tsx
|
|
150
|
+
import { initializeAPIClient } from '@/lib/api/generated/client';
|
|
151
|
+
|
|
152
|
+
export function AuthProvider({ children }) {
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
initializeAPIClient({
|
|
155
|
+
getTokens: () => {
|
|
156
|
+
const token = localStorage.getItem('access_token');
|
|
157
|
+
return token ? { accessToken: token } : null;
|
|
158
|
+
},
|
|
159
|
+
setTokens: (tokens) => {
|
|
160
|
+
localStorage.setItem('access_token', tokens.accessToken);
|
|
161
|
+
},
|
|
162
|
+
clearTokens: () => {
|
|
163
|
+
localStorage.removeItem('access_token');
|
|
164
|
+
},
|
|
165
|
+
onAuthError: () => {
|
|
166
|
+
router.push('/login');
|
|
167
|
+
},
|
|
168
|
+
onRefreshToken: async () => {
|
|
169
|
+
const response = await fetch('/api/auth/refresh', {
|
|
170
|
+
method: 'POST',
|
|
171
|
+
credentials: 'include',
|
|
172
|
+
});
|
|
173
|
+
const data = await response.json();
|
|
174
|
+
return data.accessToken;
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
}, []);
|
|
178
|
+
|
|
179
|
+
return <>{children}</>;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 5. Use Generated Hooks
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// components/UserList.tsx
|
|
187
|
+
import { useListUsers, useCreateUser, useDeleteUser } from '@/lib/api/generated/hooks';
|
|
188
|
+
|
|
189
|
+
export function UserList() {
|
|
190
|
+
// Query hook
|
|
191
|
+
const { data: users, isLoading } = useListUsers({
|
|
192
|
+
page: 1,
|
|
193
|
+
limit: 10,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Mutation hooks
|
|
197
|
+
const createUser = useCreateUser({
|
|
198
|
+
onSuccess: () => {
|
|
199
|
+
console.log('User created!');
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const deleteUser = useDeleteUser();
|
|
204
|
+
|
|
205
|
+
const handleCreate = () => {
|
|
206
|
+
createUser.mutate({
|
|
207
|
+
name: 'John Doe',
|
|
208
|
+
email: 'john@example.com',
|
|
209
|
+
});
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const handleDelete = (id: string) => {
|
|
213
|
+
deleteUser.mutate({ id });
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
if (isLoading) return <div>Loading...</div>;
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div>
|
|
220
|
+
<button onClick={handleCreate}>Create User</button>
|
|
221
|
+
{users?.map((user) => (
|
|
222
|
+
<div key={user.id}>
|
|
223
|
+
{user.name}
|
|
224
|
+
<button onClick={() => handleDelete(user.id)}>Delete</button>
|
|
225
|
+
</div>
|
|
226
|
+
))}
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Next.js Usage
|
|
233
|
+
|
|
234
|
+
### Server Components
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// app/users/page.tsx
|
|
238
|
+
import { listUsersQuery } from '@/lib/api/generated/queries';
|
|
239
|
+
|
|
240
|
+
export default async function UsersPage() {
|
|
241
|
+
const users = await listUsersQuery({ page: 1, limit: 10 });
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<div>
|
|
245
|
+
{users.map((user) => (
|
|
246
|
+
<div key={user.id}>{user.name}</div>
|
|
247
|
+
))}
|
|
248
|
+
</div>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Server Actions
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// app/users/actions.ts
|
|
257
|
+
'use client';
|
|
258
|
+
|
|
259
|
+
import { createUserAction, deleteUserAction } from '@/lib/api/generated/actions';
|
|
260
|
+
import { useTransition } from 'react';
|
|
261
|
+
|
|
262
|
+
export function UserForm() {
|
|
263
|
+
const [isPending, startTransition] = useTransition();
|
|
264
|
+
|
|
265
|
+
const handleSubmit = async (formData: FormData) => {
|
|
266
|
+
startTransition(async () => {
|
|
267
|
+
const result = await createUserAction({
|
|
268
|
+
name: formData.get('name') as string,
|
|
269
|
+
email: formData.get('email') as string,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
if (result.success) {
|
|
273
|
+
console.log('User created:', result.data);
|
|
274
|
+
} else {
|
|
275
|
+
console.error('Error:', result.error);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
return <form action={handleSubmit}>...</form>;
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Configuration
|
|
285
|
+
|
|
286
|
+
### Full Configuration Options
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
/** @type {import('@cushin/api-codegen').UserConfig} */
|
|
290
|
+
export default {
|
|
291
|
+
// Required: Provider type
|
|
292
|
+
provider: 'vite' | 'nextjs',
|
|
293
|
+
|
|
294
|
+
// Required: Path to endpoints configuration
|
|
295
|
+
endpoints: './lib/api/config/endpoints.ts',
|
|
296
|
+
|
|
297
|
+
// Required: Output directory
|
|
298
|
+
output: './lib/api/generated',
|
|
299
|
+
|
|
300
|
+
// Optional: Base URL (can also be set at runtime)
|
|
301
|
+
baseUrl: process.env.VITE_API_URL,
|
|
302
|
+
|
|
303
|
+
// Optional: Generation flags
|
|
304
|
+
generateHooks: true, // Generate React Query hooks
|
|
305
|
+
generateClient: true, // Generate API client
|
|
306
|
+
generateServerActions: true, // Next.js only
|
|
307
|
+
generateServerQueries: true, // Next.js only
|
|
308
|
+
|
|
309
|
+
// Optional: Advanced options
|
|
310
|
+
options: {
|
|
311
|
+
useClientDirective: true, // Add 'use client' to generated files
|
|
312
|
+
hookPrefix: 'use', // Prefix for hook names (e.g., useGetUser)
|
|
313
|
+
actionSuffix: 'Action', // Suffix for action names (e.g., createUserAction)
|
|
314
|
+
customImports: {
|
|
315
|
+
// Add custom imports to generated files
|
|
316
|
+
hooks: ['import { customHook } from "./custom"'],
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## CLI Commands
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
# Generate code from config
|
|
326
|
+
npx @cushin/api-codegen generate
|
|
327
|
+
|
|
328
|
+
# Generate with specific config file
|
|
329
|
+
npx @cushin/api-codegen generate --config ./custom.config.js
|
|
330
|
+
|
|
331
|
+
# Initialize new config
|
|
332
|
+
npx @cushin/api-codegen init --provider nextjs
|
|
333
|
+
|
|
334
|
+
# Validate configuration
|
|
335
|
+
npx @cushin/api-codegen validate
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Advanced Usage
|
|
339
|
+
|
|
340
|
+
### Custom Headers
|
|
341
|
+
|
|
342
|
+
Add custom headers to specific endpoints for API keys, tracking, or other metadata:
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
defineEndpoint({
|
|
346
|
+
path: '/api/data',
|
|
347
|
+
method: 'POST',
|
|
348
|
+
body: z.object({ name: z.string() }),
|
|
349
|
+
response: z.object({ id: z.string() }),
|
|
350
|
+
headers: {
|
|
351
|
+
'X-API-Key': process.env.THIRD_PARTY_API_KEY,
|
|
352
|
+
'X-Custom-Header': 'custom-value',
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### FormData Support
|
|
358
|
+
|
|
359
|
+
The client automatically detects and handles FormData for file uploads:
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// Define endpoint (no body schema needed for FormData)
|
|
363
|
+
const uploadAvatar = defineEndpoint({
|
|
364
|
+
path: '/users/:userId/avatar',
|
|
365
|
+
method: 'POST',
|
|
366
|
+
params: z.object({ userId: z.string() }),
|
|
367
|
+
response: z.object({ avatarUrl: z.string() }),
|
|
368
|
+
headers: {
|
|
369
|
+
'X-Upload-Source': 'web-app', // Optional custom headers
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// Usage
|
|
374
|
+
const formData = new FormData();
|
|
375
|
+
formData.append('avatar', fileBlob, 'avatar.jpg');
|
|
376
|
+
|
|
377
|
+
const result = await apiClient.uploadAvatar(
|
|
378
|
+
{ userId: '123' },
|
|
379
|
+
formData
|
|
380
|
+
);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
See [CUSTOM_HEADERS.md](./CUSTOM_HEADERS.md) for detailed documentation and examples.
|
|
384
|
+
|
|
385
|
+
### Custom Base URL per Endpoint
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
defineEndpoint({
|
|
389
|
+
path: '/auth/login',
|
|
390
|
+
method: 'POST',
|
|
391
|
+
baseUrl: 'https://auth.example.com', // Override base URL
|
|
392
|
+
body: LoginSchema,
|
|
393
|
+
response: TokenSchema,
|
|
394
|
+
});
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Multiple Endpoints Files
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
// lib/api/config/modules/users.ts
|
|
401
|
+
export const userEndpoints = {
|
|
402
|
+
getUser: defineEndpoint({ ... }),
|
|
403
|
+
createUser: defineEndpoint({ ... }),
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// lib/api/config/endpoints.ts
|
|
407
|
+
import { userEndpoints } from './modules/users';
|
|
408
|
+
import { productEndpoints } from './modules/products';
|
|
409
|
+
|
|
410
|
+
export const apiConfig = defineConfig({
|
|
411
|
+
baseUrl: 'https://api.example.com',
|
|
412
|
+
endpoints: {
|
|
413
|
+
...userEndpoints,
|
|
414
|
+
...productEndpoints,
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Custom Auth Logic
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
initializeAPIClient({
|
|
423
|
+
getTokens: () => {
|
|
424
|
+
// Custom token retrieval
|
|
425
|
+
return yourAuthStore.getTokens();
|
|
426
|
+
},
|
|
427
|
+
setTokens: (tokens) => {
|
|
428
|
+
// Custom token storage
|
|
429
|
+
yourAuthStore.setTokens(tokens);
|
|
430
|
+
},
|
|
431
|
+
clearTokens: () => {
|
|
432
|
+
// Custom cleanup
|
|
433
|
+
yourAuthStore.clearTokens();
|
|
434
|
+
},
|
|
435
|
+
onRefreshToken: async () => {
|
|
436
|
+
// Custom refresh logic
|
|
437
|
+
const newToken = await yourRefreshFunction();
|
|
438
|
+
return newToken;
|
|
439
|
+
},
|
|
440
|
+
onAuthError: () => {
|
|
441
|
+
// Custom error handling
|
|
442
|
+
yourRouter.push('/login');
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Type Safety
|
|
448
|
+
|
|
449
|
+
All generated code is fully typed:
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
// IntelliSense knows the exact shape
|
|
453
|
+
const { data } = useGetUser({ id: '123' });
|
|
454
|
+
// ^? { id: string; name: string; email: string; }
|
|
455
|
+
|
|
456
|
+
// TypeScript will error on invalid params
|
|
457
|
+
const { data } = useGetUser({ id: 123 }); // ❌ Type error
|
|
458
|
+
const { data } = useGetUser({ wrongParam: '123' }); // ❌ Type error
|
|
459
|
+
|
|
460
|
+
// Mutation inputs are also typed
|
|
461
|
+
createUser.mutate({
|
|
462
|
+
name: 'John',
|
|
463
|
+
email: 'invalid', // ❌ Type error: invalid email format
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Best Practices
|
|
468
|
+
|
|
469
|
+
1. **Organize endpoints by feature/module**
|
|
470
|
+
2. **Use descriptive endpoint names**
|
|
471
|
+
3. **Add descriptions to endpoints for better documentation**
|
|
472
|
+
4. **Use tags for query invalidation**
|
|
473
|
+
5. **Define reusable schemas**
|
|
474
|
+
6. **Keep baseUrl in environment variables**
|
|
475
|
+
|
|
476
|
+
## Contributing
|
|
477
|
+
|
|
478
|
+
Contributions are welcome! Please read our contributing guide.
|
|
479
|
+
|
|
480
|
+
## License
|
|
481
|
+
|
|
482
|
+
MIT © Le Viet Hoang
|
package/biome.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.2.5/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": false,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": false
|
|
7
|
+
},
|
|
8
|
+
"files": {
|
|
9
|
+
"ignoreUnknown": false
|
|
10
|
+
},
|
|
11
|
+
"formatter": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"indentStyle": "space"
|
|
14
|
+
},
|
|
15
|
+
"linter": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"rules": {
|
|
18
|
+
"recommended": true
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"javascript": {
|
|
22
|
+
"formatter": {
|
|
23
|
+
"quoteStyle": "double"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"assist": {
|
|
27
|
+
"enabled": true,
|
|
28
|
+
"actions": {
|
|
29
|
+
"source": {
|
|
30
|
+
"organizeImports": "on"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|