katanakit-js 2.14.0 → 2.14.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/README.md +141 -0
- package/package.json +23 -19
package/README.md
CHANGED
|
@@ -58,6 +58,147 @@ if (result.ok) {
|
|
|
58
58
|
}
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
## HTTP Client — API Manager
|
|
62
|
+
|
|
63
|
+
The core of KatanaKit is a **typed, registry-based HTTP client**. You register
|
|
64
|
+
your APIs once, then fetch by name — the client builds URLs, handles serialization,
|
|
65
|
+
and returns a **Safe Result** (`{ ok, data, error }`) that never throws on HTTP errors.
|
|
66
|
+
|
|
67
|
+
### 1. Register your APIs
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { useInitApis } from "katanakit-js";
|
|
71
|
+
|
|
72
|
+
useInitApis({
|
|
73
|
+
// A public REST API
|
|
74
|
+
jsonplaceholder: {
|
|
75
|
+
baseUri: "https://jsonplaceholder.typicode.com",
|
|
76
|
+
endpoints: {
|
|
77
|
+
posts: "/posts",
|
|
78
|
+
postById: "/posts/:id",
|
|
79
|
+
},
|
|
80
|
+
// Applied automatically to specific endpoints (overridable per-call)
|
|
81
|
+
defaultQueryParams: {
|
|
82
|
+
posts: { _limit: 10 },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// Your own backend
|
|
87
|
+
myApi: {
|
|
88
|
+
baseUri: "https://api.myapp.com/v1",
|
|
89
|
+
endpoints: {
|
|
90
|
+
users: "/users",
|
|
91
|
+
userById: "/users/:id",
|
|
92
|
+
createUser: "/users",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2. GET — list and read
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { useGetApi } from "katanakit-js";
|
|
102
|
+
|
|
103
|
+
// List (uses defaultQueryParams: _limit=10)
|
|
104
|
+
const list = await useGetApi<{ id: number; title: string }[]>("jsonplaceholder", "posts");
|
|
105
|
+
if (list.ok) console.log(list.data);
|
|
106
|
+
|
|
107
|
+
// Read by ID — :id is replaced by params
|
|
108
|
+
const post = await useGetApi<{ title: string }>("jsonplaceholder", "postById", {
|
|
109
|
+
params: { id: 1 },
|
|
110
|
+
});
|
|
111
|
+
if (post.ok) console.log(post.data.title);
|
|
112
|
+
|
|
113
|
+
// Override default query params
|
|
114
|
+
const filtered = await useGetApi("jsonplaceholder", "posts", {
|
|
115
|
+
query: { _limit: 5, userId: 1 },
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 3. POST, PUT, PATCH, DELETE
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { usePost, usePut, usePatch, useDelete } from "katanakit-js";
|
|
123
|
+
|
|
124
|
+
// POST — body is auto-serialized to JSON
|
|
125
|
+
const created = await usePost<{ id: number }>("myApi", "createUser", {
|
|
126
|
+
name: "Alice",
|
|
127
|
+
email: "alice@example.com",
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// PUT — full replacement (body + path params)
|
|
131
|
+
const updated = await usePut("myApi", "userById", { name: "Bob" }, { params: { id: 42 } });
|
|
132
|
+
|
|
133
|
+
// PATCH — partial update
|
|
134
|
+
const patched = await usePatch("myApi", "userById", { name: "Charlie" }, { params: { id: 42 } });
|
|
135
|
+
|
|
136
|
+
// DELETE
|
|
137
|
+
const deleted = await useDelete("myApi", "userById", { params: { id: 42 } });
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 4. Auth tokens — inject headers per call
|
|
141
|
+
|
|
142
|
+
There's no global interceptor — pass `headers` directly. This keeps things explicit and testable.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
const result = await useFetch("myApi", "users", {
|
|
146
|
+
method: "GET",
|
|
147
|
+
headers: {
|
|
148
|
+
Authorization: `Bearer ${getToken()}`,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 5. Error handling — the Safe Result pattern
|
|
154
|
+
|
|
155
|
+
Every fetch returns `{ ok, data, error, status, url }`. No try/catch needed for HTTP failures.
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const result = await useGetApi("myApi", "userById", { params: { id: 99999 } });
|
|
159
|
+
|
|
160
|
+
if (result.ok) {
|
|
161
|
+
// result.data is typed
|
|
162
|
+
console.log(result.data);
|
|
163
|
+
} else {
|
|
164
|
+
// result.error is always structured
|
|
165
|
+
console.log(result.error.status); // 404
|
|
166
|
+
console.log(result.error.message); // "HTTP Error: Not Found"
|
|
167
|
+
console.log(result.error.details); // parsed response body (if any)
|
|
168
|
+
console.log(result.url); // the URL that was called
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 6. Build URLs without fetching
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import { useBuildUrl } from "katanakit-js";
|
|
176
|
+
|
|
177
|
+
const url = useBuildUrl("jsonplaceholder", "postById", {
|
|
178
|
+
params: { id: 7 },
|
|
179
|
+
query: { _limit: 3 },
|
|
180
|
+
});
|
|
181
|
+
// "https://jsonplaceholder.typicode.com/posts/7?_limit=3"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 7. FormData and raw bodies
|
|
185
|
+
|
|
186
|
+
`usePost`/`usePut`/`usePatch` auto-detect `FormData`, `Blob`, `URLSearchParams`,
|
|
187
|
+
`ArrayBuffer`, `ReadableStream`, and `string` — these are sent as-is without
|
|
188
|
+
forcing `Content-Type: application/json`.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
const form = new FormData();
|
|
192
|
+
form.append("file", blob);
|
|
193
|
+
await usePost("myApi", "upload", form);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Full example
|
|
197
|
+
|
|
198
|
+
See [`examples/api-manager/demo.ts`](examples/api-manager/) for a runnable demo
|
|
199
|
+
covering all CRUD operations, auth injection, URL building, and error handling
|
|
200
|
+
against a real API (JSONPlaceholder).
|
|
201
|
+
|
|
61
202
|
## Features
|
|
62
203
|
|
|
63
204
|
- **Safe Results** — HTTP (and other fallible) operations return `{ data, error, ok }` instead of throwing
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "katanakit-js",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.1",
|
|
4
4
|
"description": "KatanaKit — a sharp, framework-agnostic TypeScript service toolkit organized with hexagonal architecture.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
"telegram:dev": "tsx src/adapters/telegram/main.ts",
|
|
74
74
|
"whatsapp:dev": "tsx src/adapters/whatsapp/main.ts",
|
|
75
75
|
"assistant:demo": "tsx examples/assistant/demo.ts",
|
|
76
|
+
"api:demo": "tsx examples/api-manager/demo.ts",
|
|
76
77
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
77
78
|
"check": "biome check ./src && tsc --noEmit && vitest run",
|
|
78
79
|
"fix": "biome check --write ./src && tsc --noEmit && vitest run",
|
|
@@ -80,9 +81,9 @@
|
|
|
80
81
|
"bump:patch": "yarn version patch --all && git commit -am \"chore: release v$(node -p \"require('./package.json').version\")\" && git tag \"v$(node -p \"require('./package.json').version\")\"",
|
|
81
82
|
"bump:minor": "yarn version minor --all && git commit -am \"chore: release v$(node -p \"require('./package.json').version\")\" && git tag \"v$(node -p \"require('./package.json').version\")\"",
|
|
82
83
|
"bump:major": "yarn version major --all && git commit -am \"chore: release v$(node -p \"require('./package.json').version\")\" && git tag \"v$(node -p \"require('./package.json').version\")\"",
|
|
83
|
-
"release": "yarn build && yarn bump:patch &&
|
|
84
|
-
"release:minor": "yarn build && yarn bump:minor &&
|
|
85
|
-
"release:major": "yarn build && yarn bump:major &&
|
|
84
|
+
"release": "yarn build && yarn bump:patch && npm publish --access public && git push && git push --tags && gh release create \"v$(node -p \"require('./package.json').version\")\" --generate-notes",
|
|
85
|
+
"release:minor": "yarn build && yarn bump:minor && npm publish --access public && git push && git push --tags && gh release create \"v$(node -p \"require('./package.json').version\")\" --generate-notes",
|
|
86
|
+
"release:major": "yarn build && yarn bump:major && npm publish --access public && git push && git push --tags && gh release create \"v$(node -p \"require('./package.json').version\")\" --generate-notes",
|
|
86
87
|
"version:sync": "node -e \"const v=require('child_process').execSync('git tag --sort=-v:refname').toString().split('\\n')[0].replace('v',''); ['package.json','docs/package.json'].forEach(f=>{const p=require('./'+f); p.version=v; require('fs').writeFileSync(f,JSON.stringify(p,null,2)+'\\n')}); console.log('Synced to v'+v)\"",
|
|
87
88
|
"docs:dev": "yarn workspace katanakit-docs run dev",
|
|
88
89
|
"docs:build": "yarn workspace katanakit-docs run build",
|
|
@@ -115,7 +116,7 @@
|
|
|
115
116
|
"unpkg": "./dist/index.js",
|
|
116
117
|
"jsdelivr": "./dist/index.js",
|
|
117
118
|
"dependencies": {
|
|
118
|
-
"@js-temporal/polyfill": "
|
|
119
|
+
"@js-temporal/polyfill": "0.5.1",
|
|
119
120
|
"@prisma/orm-postgres": "8.0.0-rc.8"
|
|
120
121
|
},
|
|
121
122
|
"peerDependencies": {
|
|
@@ -139,21 +140,24 @@
|
|
|
139
140
|
}
|
|
140
141
|
},
|
|
141
142
|
"devDependencies": {
|
|
142
|
-
"@biomejs/biome": "
|
|
143
|
-
"@types/
|
|
144
|
-
"@types/
|
|
145
|
-
"@types/express": "
|
|
146
|
-
"@types/
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"express": "^5.2.1",
|
|
143
|
+
"@biomejs/biome": "2.5.12",
|
|
144
|
+
"@types/cors": "2.8.19",
|
|
145
|
+
"@types/express": "5.0.6",
|
|
146
|
+
"@types/express-rate-limit": "6.0.2",
|
|
147
|
+
"@types/node": "26.5.0",
|
|
148
|
+
"cors": "2.8.6",
|
|
149
|
+
"dotenv": "17.4.2",
|
|
150
|
+
"express": "5.2.1",
|
|
151
151
|
"prisma": "8.0.0-rc.13",
|
|
152
|
-
"tsx": "
|
|
153
|
-
"typescript": "
|
|
154
|
-
"vite": "
|
|
155
|
-
"vitest": "
|
|
156
|
-
"vue": "
|
|
152
|
+
"tsx": "4.23.13",
|
|
153
|
+
"typescript": "7.0.2",
|
|
154
|
+
"vite": "8.2.2",
|
|
155
|
+
"vitest": "5.0.0",
|
|
156
|
+
"vue": "3.5.42"
|
|
157
|
+
},
|
|
158
|
+
"resolutions": {
|
|
159
|
+
"pathe": "2.0.3",
|
|
160
|
+
"jsbi": "4.3.2"
|
|
157
161
|
},
|
|
158
162
|
"packageManager": "yarn@4.18.0"
|
|
159
163
|
}
|