katanakit-js 3.2.2 → 4.0.0
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 +142 -35
- package/dist/adapters/angular/fetch.d.ts +37 -0
- package/dist/adapters/angular/fetch.d.ts.map +1 -0
- package/dist/adapters/angular/fetch.js +67 -0
- package/dist/adapters/angular/fetch.js.map +1 -0
- package/dist/adapters/angular/index.d.ts +4 -0
- package/dist/adapters/angular/index.d.ts.map +1 -0
- package/dist/adapters/angular/index.js +4 -0
- package/dist/adapters/angular/index.js.map +1 -0
- package/dist/adapters/angular/query.d.ts +107 -0
- package/dist/adapters/angular/query.d.ts.map +1 -0
- package/dist/adapters/angular/query.js +166 -0
- package/dist/adapters/angular/query.js.map +1 -0
- package/dist/adapters/angular/watch.d.ts +34 -0
- package/dist/adapters/angular/watch.d.ts.map +1 -0
- package/dist/adapters/angular/watch.js +38 -0
- package/dist/adapters/angular/watch.js.map +1 -0
- package/dist/adapters/assistant/assistant.service.js +1 -1
- package/dist/adapters/assistant/assistant.service.js.map +1 -1
- package/dist/adapters/astro/astro.service.d.ts +0 -1
- package/dist/adapters/astro/astro.service.d.ts.map +1 -1
- package/dist/adapters/astro/astro.service.js +0 -1
- package/dist/adapters/astro/astro.service.js.map +1 -1
- package/dist/adapters/express/products.controller.d.ts.map +1 -1
- package/dist/adapters/express/products.controller.js +3 -1
- package/dist/adapters/express/products.controller.js.map +1 -1
- package/dist/adapters/notion/notion.service.d.ts +4 -2
- package/dist/adapters/notion/notion.service.d.ts.map +1 -1
- package/dist/adapters/notion/notion.service.js +19 -5
- package/dist/adapters/notion/notion.service.js.map +1 -1
- package/dist/adapters/react/fetch.d.ts +44 -0
- package/dist/adapters/react/fetch.d.ts.map +1 -0
- package/dist/adapters/react/fetch.js +74 -0
- package/dist/adapters/react/fetch.js.map +1 -0
- package/dist/adapters/react/index.d.ts +4 -0
- package/dist/adapters/react/index.d.ts.map +1 -0
- package/dist/adapters/react/index.js +4 -0
- package/dist/adapters/react/index.js.map +1 -0
- package/dist/adapters/react/query.d.ts +104 -0
- package/dist/adapters/react/query.d.ts.map +1 -0
- package/dist/adapters/react/query.js +200 -0
- package/dist/adapters/react/query.js.map +1 -0
- package/dist/adapters/react/watch.d.ts +37 -0
- package/dist/adapters/react/watch.d.ts.map +1 -0
- package/dist/adapters/react/watch.js +39 -0
- package/dist/adapters/react/watch.js.map +1 -0
- package/dist/adapters/solid/fetch.d.ts +43 -0
- package/dist/adapters/solid/fetch.d.ts.map +1 -0
- package/dist/adapters/solid/fetch.js +72 -0
- package/dist/adapters/solid/fetch.js.map +1 -0
- package/dist/adapters/solid/index.d.ts +4 -0
- package/dist/adapters/solid/index.d.ts.map +1 -0
- package/dist/adapters/solid/index.js +4 -0
- package/dist/adapters/solid/index.js.map +1 -0
- package/dist/adapters/solid/query.d.ts +102 -0
- package/dist/adapters/solid/query.d.ts.map +1 -0
- package/dist/adapters/solid/query.js +163 -0
- package/dist/adapters/solid/query.js.map +1 -0
- package/dist/adapters/solid/watch.d.ts +32 -0
- package/dist/adapters/solid/watch.d.ts.map +1 -0
- package/dist/adapters/solid/watch.js +36 -0
- package/dist/adapters/solid/watch.js.map +1 -0
- package/dist/adapters/svelte/fetch.d.ts +40 -0
- package/dist/adapters/svelte/fetch.d.ts.map +1 -0
- package/dist/adapters/svelte/fetch.js +75 -0
- package/dist/adapters/svelte/fetch.js.map +1 -0
- package/dist/adapters/svelte/index.d.ts +4 -0
- package/dist/adapters/svelte/index.d.ts.map +1 -0
- package/dist/adapters/svelte/index.js +4 -0
- package/dist/adapters/svelte/index.js.map +1 -0
- package/dist/adapters/svelte/query.d.ts +108 -0
- package/dist/adapters/svelte/query.d.ts.map +1 -0
- package/dist/adapters/svelte/query.js +172 -0
- package/dist/adapters/svelte/query.js.map +1 -0
- package/dist/adapters/svelte/watch.d.ts +32 -0
- package/dist/adapters/svelte/watch.d.ts.map +1 -0
- package/dist/adapters/svelte/watch.js +41 -0
- package/dist/adapters/svelte/watch.js.map +1 -0
- package/dist/adapters/vue/query.d.ts.map +1 -1
- package/dist/adapters/vue/query.js +8 -6
- package/dist/adapters/vue/query.js.map +1 -1
- package/dist/adapters/vue/vue.service.d.ts +9 -5
- package/dist/adapters/vue/vue.service.d.ts.map +1 -1
- package/dist/adapters/vue/vue.service.js +7 -3
- package/dist/adapters/vue/vue.service.js.map +1 -1
- package/dist/adapters/wordpress/wordpress.service.d.ts +2 -1
- package/dist/adapters/wordpress/wordpress.service.d.ts.map +1 -1
- package/dist/adapters/wordpress/wordpress.service.js +10 -5
- package/dist/adapters/wordpress/wordpress.service.js.map +1 -1
- package/dist/core/services/agent.service.d.ts.map +1 -1
- package/dist/core/services/agent.service.js +9 -1
- package/dist/core/services/agent.service.js.map +1 -1
- package/dist/core/services/dates.service.d.ts.map +1 -1
- package/dist/core/services/dates.service.js +2 -1
- package/dist/core/services/dates.service.js.map +1 -1
- package/dist/core/services/http.service.d.ts +26 -5
- package/dist/core/services/http.service.d.ts.map +1 -1
- package/dist/core/services/http.service.js +30 -6
- package/dist/core/services/http.service.js.map +1 -1
- package/dist/core/services/query.service.d.ts +4 -0
- package/dist/core/services/query.service.d.ts.map +1 -1
- package/dist/core/services/query.service.js +66 -55
- package/dist/core/services/query.service.js.map +1 -1
- package/dist/core/services/reactive.service.d.ts.map +1 -1
- package/dist/core/services/reactive.service.js +0 -3
- package/dist/core/services/reactive.service.js.map +1 -1
- package/dist/core/services/utils.service.d.ts.map +1 -1
- package/dist/core/services/utils.service.js +3 -0
- package/dist/core/services/utils.service.js.map +1 -1
- package/dist/infrastructure/dom/dom.service.d.ts.map +1 -1
- package/dist/infrastructure/dom/dom.service.js +15 -3
- package/dist/infrastructure/dom/dom.service.js.map +1 -1
- package/dist/infrastructure/storage/storage.service.d.ts.map +1 -1
- package/dist/infrastructure/storage/storage.service.js +12 -2
- package/dist/infrastructure/storage/storage.service.js.map +1 -1
- package/dist/prisma/assistant.store.d.ts +3 -0
- package/dist/prisma/assistant.store.d.ts.map +1 -1
- package/dist/prisma/assistant.store.js +12 -6
- package/dist/prisma/assistant.store.js.map +1 -1
- package/dist/prisma/use-prisma.d.ts +5 -4
- package/dist/prisma/use-prisma.d.ts.map +1 -1
- package/dist/prisma/use-prisma.js +5 -4
- package/dist/prisma/use-prisma.js.map +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +249 -185
- package/dist/prisma/db.d.ts +0 -4
- package/dist/prisma/db.d.ts.map +0 -1
- package/dist/prisma/db.js +0 -12
- package/dist/prisma/db.js.map +0 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ npm install katanakit-js
|
|
|
9
9
|
# or
|
|
10
10
|
bun add katanakit-js
|
|
11
11
|
# or
|
|
12
|
-
|
|
12
|
+
bun add katanakit-js
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
### CDN (ESM)
|
|
@@ -171,14 +171,66 @@ if (result.ok) {
|
|
|
171
171
|
|
|
172
172
|
### 6. Build URLs without fetching
|
|
173
173
|
|
|
174
|
+
`useBuildUrl` constructs a full URL from your registered APIs **without making
|
|
175
|
+
a request**. Use it to generate links, image sources, or pass URLs to libraries
|
|
176
|
+
that handle their own fetching.
|
|
177
|
+
|
|
178
|
+
#### Generate navigation links
|
|
179
|
+
|
|
174
180
|
```ts
|
|
175
181
|
import { useBuildUrl } from "katanakit-js";
|
|
176
182
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
query: {
|
|
183
|
+
// Build a download link
|
|
184
|
+
const downloadUrl = useBuildUrl("myApi", "export", {
|
|
185
|
+
query: { format: "pdf", lang: "es" },
|
|
186
|
+
});
|
|
187
|
+
// → "https://api.myapp.com/v1/export?format=pdf&lang=es"
|
|
188
|
+
|
|
189
|
+
// Use in a template
|
|
190
|
+
<a href={downloadUrl}>Download PDF</a>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### Generate image/file URLs
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
// Build an image URL for <img src>
|
|
197
|
+
const avatarUrl = useBuildUrl("myApi", "userAvatar", {
|
|
198
|
+
params: { id: 42 },
|
|
199
|
+
query: { size: "large" },
|
|
200
|
+
});
|
|
201
|
+
// → "https://api.myapp.com/v1/users/42/avatar?size=large"
|
|
202
|
+
|
|
203
|
+
<img src={avatarUrl} alt="User avatar" />
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### Pass to third-party libraries
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
// Charts, maps, analytics — libraries that fetch their own data
|
|
210
|
+
const chartDataUrl = useBuildUrl("myApi", "analytics", {
|
|
211
|
+
query: { range: "7d", metric: "visits" },
|
|
212
|
+
});
|
|
213
|
+
new Chart(canvas, { data: chartDataUrl });
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### Debug before fetching
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
// See the full URL before making the request
|
|
220
|
+
console.log("Will fetch:", useBuildUrl("myApi", "users", {
|
|
221
|
+
query: { page: 1, per_page: 20 },
|
|
222
|
+
}));
|
|
223
|
+
// → "https://api.myapp.com/v1/users?page=1&per_page=20"
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### SSR: construct URLs server-side
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
// In Astro, Next.js, or Nuxt server code
|
|
230
|
+
const apiUrl = useBuildUrl("notion", "database", {
|
|
231
|
+
params: { id: "db-123" },
|
|
180
232
|
});
|
|
181
|
-
//
|
|
233
|
+
// Pass to client component or pre-render
|
|
182
234
|
```
|
|
183
235
|
|
|
184
236
|
### 7. FormData and raw bodies
|
|
@@ -195,7 +247,7 @@ await usePost("myApi", "upload", form);
|
|
|
195
247
|
|
|
196
248
|
### Full example
|
|
197
249
|
|
|
198
|
-
See [`examples/api-manager/demo.ts`](https://github.com/senseikatana/katanakit
|
|
250
|
+
See [`examples/api-manager/demo.ts`](https://github.com/senseikatana/katanakit/tree/main/examples/api-manager) for a runnable demo
|
|
199
251
|
covering all CRUD operations, auth injection, URL building, and error handling
|
|
200
252
|
against a real API (JSONPlaceholder).
|
|
201
253
|
|
|
@@ -286,6 +338,27 @@ when you want sessions, persistence, and channels (REST, Telegram, WhatsApp). Fa
|
|
|
286
338
|
follow the Safe Result pattern: they **never throw**. Check `result.ok` and read `result.data`
|
|
287
339
|
or `result.error`.
|
|
288
340
|
|
|
341
|
+
### When to use Kitt
|
|
342
|
+
|
|
343
|
+
Kitt is a **lightweight, zero-dependency** wrapper for OpenAI-compatible APIs.
|
|
344
|
+
Use it when you need:
|
|
345
|
+
|
|
346
|
+
- **One-shot chat** — ask a question, get an answer (`useChat`)
|
|
347
|
+
- **Tool-calling agents** — autonomous loops that read/write/run (`useRunAgent`)
|
|
348
|
+
- **Session-aware bots** — REST, Telegram, WhatsApp channels (`useReply`)
|
|
349
|
+
|
|
350
|
+
### When to use alternatives
|
|
351
|
+
|
|
352
|
+
| Need | Use instead |
|
|
353
|
+
|------|------------|
|
|
354
|
+
| Streaming token-by-token | [Vercel AI SDK](https://sdk.vercel.ai) |
|
|
355
|
+
| RAG with embeddings | [LangChain.js](https://js.langchain.com) |
|
|
356
|
+
| Multi-agent orchestration | [CrewAI](https://github.com/crewAIInc/crewAI) |
|
|
357
|
+
| Full chatbot framework | [Botpress](https://botpress.com) |
|
|
358
|
+
|
|
359
|
+
Kitt stays small (0 dependencies) because it does one thing well:
|
|
360
|
+
**chat completions with tool calls, using any OpenAI-compatible endpoint.**
|
|
361
|
+
|
|
289
362
|
### Low-level API
|
|
290
363
|
|
|
291
364
|
```ts
|
|
@@ -360,7 +433,7 @@ Also on the main barrel:
|
|
|
360
433
|
| `useResetSession` | `(sessionId) => Promise<void>` |
|
|
361
434
|
| `useCreateMemoryStore` | `() => ConversationStore` |
|
|
362
435
|
|
|
363
|
-
Then start a channel (see below). Copy keys from [`.env.example`](https://github.com/senseikatana/katanakit
|
|
436
|
+
Then start a channel (see below). Copy keys from [`.env.example`](https://github.com/senseikatana/katanakit/blob/main/.env.example):
|
|
364
437
|
|
|
365
438
|
```env
|
|
366
439
|
DASHSCOPE_API_KEY=
|
|
@@ -379,10 +452,10 @@ DATABASE_URL=
|
|
|
379
452
|
|
|
380
453
|
| Script | Starts |
|
|
381
454
|
|--------|--------|
|
|
382
|
-
| `
|
|
383
|
-
| `
|
|
384
|
-
| `
|
|
385
|
-
| `
|
|
455
|
+
| `bun run assistant:dev` | REST assistant. Uses Prisma when `DATABASE_URL` is set. |
|
|
456
|
+
| `bun run telegram:dev` | Telegram long polling. Requires `TELEGRAM_BOT_TOKEN`. |
|
|
457
|
+
| `bun run whatsapp:dev` | WhatsApp webhook. Requires `WHATSAPP_*`. |
|
|
458
|
+
| `bun run assistant:demo` | Demo in `examples/assistant/`. Set `KITT_CHANNEL=rest\|telegram\|whatsapp`. |
|
|
386
459
|
|
|
387
460
|
### REST
|
|
388
461
|
|
|
@@ -442,7 +515,7 @@ await useStartTelegramPolling();
|
|
|
442
515
|
2. Send `/newbot` — choose a name and a username.
|
|
443
516
|
3. Copy the token.
|
|
444
517
|
4. Set `TELEGRAM_BOT_TOKEN`.
|
|
445
|
-
5. Run `
|
|
518
|
+
5. Run `bun run telegram:dev` (long polling, no public URL).
|
|
446
519
|
6. Optional webhook: expose HTTPS and call `useHandleTelegramUpdate(update)` on inbound updates.
|
|
447
520
|
|
|
448
521
|
### WhatsApp (Meta Cloud API)
|
|
@@ -465,7 +538,7 @@ useStartWhatsApp();
|
|
|
465
538
|
2. Add the WhatsApp product.
|
|
466
539
|
3. Copy the temporary or permanent token, the Phone number ID, and the **App Secret**.
|
|
467
540
|
4. Set `WHATSAPP_TOKEN`, `WHATSAPP_PHONE_NUMBER_ID`, `WHATSAPP_VERIFY_TOKEN`, and `WHATSAPP_APP_SECRET`.
|
|
468
|
-
5. Run `
|
|
541
|
+
5. Run `bun run whatsapp:dev`.
|
|
469
542
|
6. Expose public HTTPS (Cloudflare Tunnel or ngrok) to `GET`/`POST` `/whatsapp/webhook`.
|
|
470
543
|
7. In Meta, set the webhook URL and verify token; subscribe to `messages`.
|
|
471
544
|
|
|
@@ -496,11 +569,11 @@ owns the database, run `prisma contract emit` then `prisma db init` in that app.
|
|
|
496
569
|
|
|
497
570
|
### Real use case
|
|
498
571
|
|
|
499
|
-
[`examples/assistant/`](https://github.com/senseikatana/katanakit
|
|
572
|
+
[`examples/assistant/`](https://github.com/senseikatana/katanakit/tree/main/examples/assistant) is a generic digital assistant with two demo tools:
|
|
500
573
|
`readFile` on `knowledge-base.md` and `saveNote` to `notes.jsonl`.
|
|
501
574
|
|
|
502
575
|
```bash
|
|
503
|
-
|
|
576
|
+
bun run assistant:demo
|
|
504
577
|
# KITT_CHANNEL=rest|telegram|whatsapp
|
|
505
578
|
```
|
|
506
579
|
|
|
@@ -540,7 +613,7 @@ const result = await useGetApi("pokeapi", "pokemonById", { params: { id: 25 } })
|
|
|
540
613
|
|
|
541
614
|
```ts
|
|
542
615
|
import { useLogger, useInitApis, useGetApi } from "katanakit-js";
|
|
543
|
-
import {
|
|
616
|
+
import { useRequest } from "katanakit-js/adapters/vue"; // Vue only
|
|
544
617
|
import { useUnwrap } from "katanakit-js/adapters/nuxt"; // Nuxt only
|
|
545
618
|
```
|
|
546
619
|
|
|
@@ -559,7 +632,7 @@ See [Getting Started](https://senseikatana.com/katanakit-js/docs/guides/getting-
|
|
|
559
632
|
|---------|--------|-------------|
|
|
560
633
|
| **Express** | `katanakit-js/adapters/express` | Reference server with CORS and hardened headers |
|
|
561
634
|
| **Nuxt** | `katanakit-js/adapters/nuxt` | `useUnwrap`, `useSafeResponse`, `useEventResponse` |
|
|
562
|
-
| **Vue** | `katanakit-js/adapters/vue` | `
|
|
635
|
+
| **Vue** | `katanakit-js/adapters/vue` | `useRequest` composable with reactivity |
|
|
563
636
|
| **Astro** | `katanakit-js` or `katanakit-js/adapters/astro` | `AstroService`, `RssService` |
|
|
564
637
|
| **Assistant** | `katanakit-js/adapters/assistant` | REST digital assistant (`useStartAssistant`) |
|
|
565
638
|
| **Telegram** | `katanakit-js/adapters/telegram` | BotFather bot (`useInitTelegram`, `useStartTelegramPolling`) |
|
|
@@ -775,15 +848,15 @@ if (users.ok) users.data.results.forEach(u => console.log(u.name));
|
|
|
775
848
|
|
|
776
849
|
| Framework | Example | Description |
|
|
777
850
|
|-----------|---------|-------------|
|
|
778
|
-
| **Vue 3** | [`examples/notion/vue-blog.vue`](https://github.com/senseikatana/katanakit
|
|
779
|
-
| **Vue 3** | [`examples/notion/vue-post.vue`](https://github.com/senseikatana/katanakit
|
|
780
|
-
| **Nuxt 3** | [`examples/notion/nuxt-blog.vue`](https://github.com/senseikatana/katanakit
|
|
781
|
-
| **Nuxt 3** | [`examples/notion/nuxt-post.vue`](https://github.com/senseikatana/katanakit
|
|
782
|
-
| **Astro** | [`examples/notion/astro-blog.astro`](https://github.com/senseikatana/katanakit
|
|
783
|
-
| **Astro** | [`examples/notion/astro-[slug].astro`](https://github.com/senseikatana/katanakit
|
|
784
|
-
| **Next.js** | [`examples/notion/next-blog.tsx`](https://github.com/senseikatana/katanakit
|
|
785
|
-
| **Next.js** | [`examples/notion/next-[slug].tsx`](https://github.com/senseikatana/katanakit
|
|
786
|
-
| **Node.js** | [`examples/notion/demo.ts`](https://github.com/senseikatana/katanakit
|
|
851
|
+
| **Vue 3** | [`examples/notion/vue-blog.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/vue-blog.vue) | Blog listing with `useQuery` composable |
|
|
852
|
+
| **Vue 3** | [`examples/notion/vue-post.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/vue-post.vue) | Single post view |
|
|
853
|
+
| **Nuxt 3** | [`examples/notion/nuxt-blog.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/nuxt-blog.vue) | SSR blog listing with `useAsyncData` |
|
|
854
|
+
| **Nuxt 3** | [`examples/notion/nuxt-post.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/nuxt-post.vue) | SSR single post view |
|
|
855
|
+
| **Astro** | [`examples/notion/astro-blog.astro`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/astro-blog.astro) | Static blog listing |
|
|
856
|
+
| **Astro** | [`examples/notion/astro-[slug].astro`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/astro-[slug].astro) | Dynamic `[slug]` route |
|
|
857
|
+
| **Next.js** | [`examples/notion/next-blog.tsx`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/next-blog.tsx) | Server component blog listing |
|
|
858
|
+
| **Next.js** | [`examples/notion/next-[slug].tsx`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/next-[slug].tsx) | Dynamic `[slug]` page |
|
|
859
|
+
| **Node.js** | [`examples/notion/demo.ts`](https://github.com/senseikatana/katanakit/tree/main/examples/notion/demo.ts) | Runnable demo covering all Notion operations |
|
|
787
860
|
|
|
788
861
|
### WordPress
|
|
789
862
|
|
|
@@ -1114,15 +1187,49 @@ const full = await useWpGetPosts({
|
|
|
1114
1187
|
|
|
1115
1188
|
| Framework | Example | Description |
|
|
1116
1189
|
|-----------|---------|-------------|
|
|
1117
|
-
| **Vue 3** | [`examples/wordpress/vue-blog.vue`](https://github.com/senseikatana/katanakit
|
|
1118
|
-
| **Vue 3** | [`examples/wordpress/vue-post.vue`](https://github.com/senseikatana/katanakit
|
|
1119
|
-
| **Nuxt 3** | [`examples/wordpress/nuxt-blog.vue`](https://github.com/senseikatana/katanakit
|
|
1120
|
-
| **Nuxt 3** | [`examples/wordpress/nuxt-post.vue`](https://github.com/senseikatana/katanakit
|
|
1121
|
-
| **Astro** | [`examples/wordpress/astro-blog.astro`](https://github.com/senseikatana/katanakit
|
|
1122
|
-
| **Astro** | [`examples/wordpress/astro-[slug].astro`](https://github.com/senseikatana/katanakit
|
|
1123
|
-
| **Next.js** | [`examples/wordpress/next-blog.tsx`](https://github.com/senseikatana/katanakit
|
|
1124
|
-
| **Next.js** | [`examples/wordpress/next-[slug].tsx`](https://github.com/senseikatana/katanakit
|
|
1125
|
-
| **Node.js** | [`examples/wordpress/demo.ts`](https://github.com/senseikatana/katanakit
|
|
1190
|
+
| **Vue 3** | [`examples/wordpress/vue-blog.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/vue-blog.vue) | Blog listing with categories, featured images, `_embed` |
|
|
1191
|
+
| **Vue 3** | [`examples/wordpress/vue-post.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/vue-post.vue) | Single post view with embedded author |
|
|
1192
|
+
| **Nuxt 3** | [`examples/wordpress/nuxt-blog.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/nuxt-blog.vue) | SSR blog listing with `useAsyncData` |
|
|
1193
|
+
| **Nuxt 3** | [`examples/wordpress/nuxt-post.vue`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/nuxt-post.vue) | SSR single post view |
|
|
1194
|
+
| **Astro** | [`examples/wordpress/astro-blog.astro`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/astro-blog.astro) | Static blog listing |
|
|
1195
|
+
| **Astro** | [`examples/wordpress/astro-[slug].astro`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/astro-[slug].astro) | Dynamic `[slug]` route |
|
|
1196
|
+
| **Next.js** | [`examples/wordpress/next-blog.tsx`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/next-blog.tsx) | Server component blog listing |
|
|
1197
|
+
| **Next.js** | [`examples/wordpress/next-[slug].tsx`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/next-[slug].tsx) | Dynamic `[slug]` page |
|
|
1198
|
+
| **Node.js** | [`examples/wordpress/demo.ts`](https://github.com/senseikatana/katanakit/tree/main/examples/wordpress/demo.ts) | Runnable demo covering all WP operations, `_fields`, `_embed`, ACF |
|
|
1199
|
+
|
|
1200
|
+
## Contributing
|
|
1201
|
+
|
|
1202
|
+
We welcome contributions from the community! Whether it's fixing a bug, adding
|
|
1203
|
+
a feature, or improving documentation, every contribution helps make KatanaKit
|
|
1204
|
+
better for everyone.
|
|
1205
|
+
|
|
1206
|
+
### Quick start
|
|
1207
|
+
|
|
1208
|
+
```bash
|
|
1209
|
+
git clone https://github.com/senseikatana/katanakit.git
|
|
1210
|
+
cd katanakit-js
|
|
1211
|
+
git checkout dev
|
|
1212
|
+
bun install
|
|
1213
|
+
bun run check # verify everything works
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
### Ways to contribute
|
|
1217
|
+
|
|
1218
|
+
- **Report bugs** — [Open an issue](https://github.com/senseikatana/katanakit/issues) with a clear description and reproduction steps
|
|
1219
|
+
- **Suggest features** — [Start a discussion](https://github.com/senseikatana/katanakit/discussions) to propose new ideas
|
|
1220
|
+
- **Submit a PR** — Fork the repo, create a branch from `dev`, make your changes, and open a PR
|
|
1221
|
+
- **Improve docs** — Fix typos, add examples, or clarify explanations
|
|
1222
|
+
- **Add adapters** — Build integrations for new APIs or frameworks
|
|
1223
|
+
|
|
1224
|
+
### PR guidelines
|
|
1225
|
+
|
|
1226
|
+
1. Branch from `dev` (not `main`)
|
|
1227
|
+
2. Follow the `use*` naming convention
|
|
1228
|
+
3. Add TypeScript types in `src/types/index.ts`
|
|
1229
|
+
4. Run `bun run check` before submitting
|
|
1230
|
+
5. Update `CHANGELOG.md` if the public API changed
|
|
1231
|
+
|
|
1232
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development contract.
|
|
1126
1233
|
|
|
1127
1234
|
## Documentation
|
|
1128
1235
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Signal } from "@angular/core";
|
|
2
|
+
import type { ApiError, UrlOptions } from "../../types/index.js";
|
|
3
|
+
/** Reactive state exposed by the {@link useRequest} factory (Angular signals). */
|
|
4
|
+
export interface RequestState<T = unknown> {
|
|
5
|
+
data: Signal<T | null>;
|
|
6
|
+
error: Signal<ApiError | null>;
|
|
7
|
+
loading: Signal<boolean>;
|
|
8
|
+
refetch: () => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Angular signal factory that wraps KatanaKit's HTTP GET. Bridges the Safe
|
|
12
|
+
* Result pattern to Angular signals and never throws on HTTP errors.
|
|
13
|
+
*
|
|
14
|
+
* Must be called within an injection context (component field initializer,
|
|
15
|
+
* constructor, or service) so it can abort in-flight requests via `DestroyRef`.
|
|
16
|
+
* Stale responses are ignored via a request version counter.
|
|
17
|
+
*
|
|
18
|
+
* @param apiName - Name of the registered API (see `useInitApis`).
|
|
19
|
+
* @param endpointName - Name of the endpoint inside that API.
|
|
20
|
+
* @param options - Optional `UrlOptions` (path/query params).
|
|
21
|
+
* @returns Signals `{ data, error, loading }` plus `refetch`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { Component } from "@angular/core";
|
|
26
|
+
* import { useRequest } from "katanakit-js/adapters/angular";
|
|
27
|
+
*
|
|
28
|
+
* @Component({ selector: "app-pokemon", template: `@if (loading()) { Loading… } @else { {{ data()?.name }} }` })
|
|
29
|
+
* export class PokemonComponent {
|
|
30
|
+
* readonly result = useRequest<{ name: string }>("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
31
|
+
* readonly data = this.result.data;
|
|
32
|
+
* readonly loading = this.result.loading;
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function useRequest<T>(apiName: string, endpointName: string, options?: UrlOptions): RequestState<T>;
|
|
37
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/adapters/angular/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,MAAM,EAAU,MAAM,eAAe,CAAC;AAGxE,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEjE,kFAAkF;AAClF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACxC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC3B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,UAAU,GAClB,YAAY,CAAC,CAAC,CAAC,CA6CjB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DestroyRef, inject, signal } from "@angular/core";
|
|
2
|
+
import { useFetch } from "../../core/services/http.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* Angular signal factory that wraps KatanaKit's HTTP GET. Bridges the Safe
|
|
5
|
+
* Result pattern to Angular signals and never throws on HTTP errors.
|
|
6
|
+
*
|
|
7
|
+
* Must be called within an injection context (component field initializer,
|
|
8
|
+
* constructor, or service) so it can abort in-flight requests via `DestroyRef`.
|
|
9
|
+
* Stale responses are ignored via a request version counter.
|
|
10
|
+
*
|
|
11
|
+
* @param apiName - Name of the registered API (see `useInitApis`).
|
|
12
|
+
* @param endpointName - Name of the endpoint inside that API.
|
|
13
|
+
* @param options - Optional `UrlOptions` (path/query params).
|
|
14
|
+
* @returns Signals `{ data, error, loading }` plus `refetch`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { Component } from "@angular/core";
|
|
19
|
+
* import { useRequest } from "katanakit-js/adapters/angular";
|
|
20
|
+
*
|
|
21
|
+
* @Component({ selector: "app-pokemon", template: `@if (loading()) { Loading… } @else { {{ data()?.name }} }` })
|
|
22
|
+
* export class PokemonComponent {
|
|
23
|
+
* readonly result = useRequest<{ name: string }>("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
24
|
+
* readonly data = this.result.data;
|
|
25
|
+
* readonly loading = this.result.loading;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function useRequest(apiName, endpointName, options) {
|
|
30
|
+
const destroyRef = inject(DestroyRef);
|
|
31
|
+
const data = signal(null);
|
|
32
|
+
const error = signal(null);
|
|
33
|
+
const loading = signal(true);
|
|
34
|
+
let version = 0;
|
|
35
|
+
let controller = null;
|
|
36
|
+
let disposed = false;
|
|
37
|
+
const refetch = async () => {
|
|
38
|
+
const current = ++version;
|
|
39
|
+
controller?.abort();
|
|
40
|
+
const next = new AbortController();
|
|
41
|
+
controller = next;
|
|
42
|
+
loading.set(true);
|
|
43
|
+
error.set(null);
|
|
44
|
+
const result = await useFetch(apiName, endpointName, {
|
|
45
|
+
method: "GET",
|
|
46
|
+
urlOptions: options,
|
|
47
|
+
signal: next.signal,
|
|
48
|
+
});
|
|
49
|
+
if (disposed || current !== version)
|
|
50
|
+
return;
|
|
51
|
+
if (result.ok) {
|
|
52
|
+
data.set(result.data);
|
|
53
|
+
error.set(null);
|
|
54
|
+
}
|
|
55
|
+
else if (!next.signal.aborted) {
|
|
56
|
+
error.set(result.error);
|
|
57
|
+
}
|
|
58
|
+
loading.set(false);
|
|
59
|
+
};
|
|
60
|
+
destroyRef.onDestroy(() => {
|
|
61
|
+
disposed = true;
|
|
62
|
+
controller?.abort();
|
|
63
|
+
});
|
|
64
|
+
void refetch();
|
|
65
|
+
return { data, error, loading, refetch };
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/adapters/angular/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAe,MAAM,EAAE,MAAM,eAAe,CAAC;AAExE,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAW/D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,UAAU,CACzB,OAAe,EACf,YAAoB,EACpB,OAAoB;IAEpB,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAEtC,MAAM,IAAI,GAAG,MAAM,CAAW,IAAI,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE7B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,UAAU,GAA2B,IAAI,CAAC;IAC9C,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,OAAO,GAAG,EAAE,OAAO,CAAC;QAC1B,UAAU,EAAE,KAAK,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,UAAU,GAAG,IAAI,CAAC;QAElB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEhB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAI,OAAO,EAAE,YAAY,EAAE;YACvD,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC,CAAC;QAEH,IAAI,QAAQ,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO;QAE5C,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACjC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,CAAC;IAEF,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE;QACzB,QAAQ,GAAG,IAAI,CAAC;QAChB,UAAU,EAAE,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,KAAK,OAAO,EAAE,CAAC;IAEf,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/angular/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/angular/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type Signal } from "@angular/core";
|
|
2
|
+
import { type QueryClient, type QueryKey, type QueryState } from "../../core/services/query.service.js";
|
|
3
|
+
import type { ApiError, FetchResult } from "../../types/index.js";
|
|
4
|
+
/** Configuration for `useQuery` (Angular signal factory). */
|
|
5
|
+
export interface UseQueryConfig<T = unknown> {
|
|
6
|
+
/** Cache key (stable array). */
|
|
7
|
+
queryKey: QueryKey;
|
|
8
|
+
/** Fetcher function returning a Safe Result. */
|
|
9
|
+
queryFn: () => Promise<FetchResult<T>>;
|
|
10
|
+
/** Time in ms before cached data is stale (default: 0). */
|
|
11
|
+
staleTime?: number;
|
|
12
|
+
/** Time in ms to keep unused data (default: 5 min). */
|
|
13
|
+
cacheTime?: number;
|
|
14
|
+
/** Retry count on failure (default: 3). */
|
|
15
|
+
retry?: number;
|
|
16
|
+
/** Base delay for exponential backoff (default: 1000). */
|
|
17
|
+
retryDelay?: number;
|
|
18
|
+
/** Whether the query is enabled (default: true). */
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Reactive return value of `useQuery` (Angular signals). */
|
|
22
|
+
export interface UseQueryReturn<T = unknown> {
|
|
23
|
+
data: Signal<T | null>;
|
|
24
|
+
error: Signal<ApiError | null>;
|
|
25
|
+
isLoading: Signal<boolean>;
|
|
26
|
+
isSuccess: Signal<boolean>;
|
|
27
|
+
isError: Signal<boolean>;
|
|
28
|
+
isStale: Signal<boolean>;
|
|
29
|
+
status: Signal<QueryState<T>["status"]>;
|
|
30
|
+
/** Manually refetch the query. */
|
|
31
|
+
refetch: () => Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/** Configuration for `useMutation`. */
|
|
34
|
+
export interface UseMutationConfig<TData = unknown, TVariables = unknown> {
|
|
35
|
+
mutationFn: (variables: TVariables) => Promise<FetchResult<TData>>;
|
|
36
|
+
onSuccess?: (data: TData, variables: TVariables) => void;
|
|
37
|
+
onError?: (error: ApiError, variables: TVariables) => void;
|
|
38
|
+
onSettled?: (data: TData | null, error: ApiError | null, variables: TVariables) => void;
|
|
39
|
+
}
|
|
40
|
+
/** Reactive return value of `useMutation`. */
|
|
41
|
+
export interface UseMutationReturn<TData = unknown, TVariables = unknown> {
|
|
42
|
+
data: Signal<TData | null>;
|
|
43
|
+
error: Signal<ApiError | null>;
|
|
44
|
+
isLoading: Signal<boolean>;
|
|
45
|
+
isSuccess: Signal<boolean>;
|
|
46
|
+
isError: Signal<boolean>;
|
|
47
|
+
status: Signal<"idle" | "loading" | "success" | "error">;
|
|
48
|
+
/** Execute the mutation. */
|
|
49
|
+
mutate: (variables: TVariables) => Promise<void>;
|
|
50
|
+
/** Reset the mutation state. */
|
|
51
|
+
reset: () => void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Angular signal factory that wraps the {@link QueryClient}.
|
|
55
|
+
* Integrates with the API manager — your `queryFn` typically calls `useGetApi`
|
|
56
|
+
* or `useFetch` and returns the Safe Result.
|
|
57
|
+
*
|
|
58
|
+
* Must be called within an injection context (component field initializer,
|
|
59
|
+
* constructor, or a service) so the returned query can auto-cleanup via
|
|
60
|
+
* `DestroyRef`. Requires Angular 16+ signals.
|
|
61
|
+
*
|
|
62
|
+
* @param config - Query configuration.
|
|
63
|
+
* @param client - Optional QueryClient instance (uses global singleton by default).
|
|
64
|
+
* @returns Signals `{ data, error, isLoading, isSuccess, isError, isStale, status }` plus `refetch`.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { Component, inject } from "@angular/core";
|
|
69
|
+
* import { useQuery } from "katanakit-js/adapters/angular";
|
|
70
|
+
* import { useGetApi } from "katanakit-js";
|
|
71
|
+
*
|
|
72
|
+
* @Component({ selector: "app-pokemon", template: `@if (isLoading()) { Loading… } @else { {{ data()?.name }} }` })
|
|
73
|
+
* export class PokemonComponent {
|
|
74
|
+
* readonly data = useQuery({ queryKey: ["pokemon", 25], queryFn: () => useGetApi("pokeapi", "pokemonById", { params: { id: 25 } }) }).data;
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function useQuery<T>(config: UseQueryConfig<T>, client?: QueryClient): UseQueryReturn<T>;
|
|
79
|
+
/**
|
|
80
|
+
* Angular signal factory for mutations (POST/PUT/PATCH/DELETE).
|
|
81
|
+
* Does not cache — returns a `mutate` function that executes the mutation.
|
|
82
|
+
*
|
|
83
|
+
* Must be called within an injection context. Requires Angular 16+ signals.
|
|
84
|
+
*
|
|
85
|
+
* @param config - Mutation configuration.
|
|
86
|
+
* @returns Signals plus `{ mutate, reset }`.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* import { Component } from "@angular/core";
|
|
91
|
+
* import { useMutation, useQueryClient } from "katanakit-js/adapters/angular";
|
|
92
|
+
* import { usePost } from "katanakit-js";
|
|
93
|
+
*
|
|
94
|
+
* @Component({ selector: "app-create", template: `<button [disabled]="isLoading()" (click)="mutate('Ada')">Create</button>` })
|
|
95
|
+
* export class CreateUserComponent {
|
|
96
|
+
* private readonly qc = useQueryClient();
|
|
97
|
+
* readonly result = useMutation({
|
|
98
|
+
* mutationFn: (name: string) => usePost("api", "createUser", { name }),
|
|
99
|
+
* onSuccess: () => this.qc.invalidateQueries({ queryKey: ["users"] }),
|
|
100
|
+
* });
|
|
101
|
+
* readonly isLoading = this.result.isLoading;
|
|
102
|
+
* readonly mutate = this.result.mutate;
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function useMutation<TData = unknown, TVariables = unknown>(config: UseMutationConfig<TData, TVariables>): UseMutationReturn<TData, TVariables>;
|
|
107
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/adapters/angular/query.ts"],"names":[],"mappings":"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"}
|