katanakit-js 2.1.6 → 2.2.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/CHANGELOG.md CHANGED
@@ -13,6 +13,11 @@ Current development version. This is the first release published under the
13
13
 
14
14
  ### Added
15
15
 
16
+ - **Vue adapter** — new `katanakit-js/adapters/vue` subpath exporting the
17
+ `useKatanaFetch` composable, which bridges KatanaKit Safe Results to Vue 3
18
+ reactivity (`data`, `error`, `loading`, `refetch`). Accepts a reactive `Ref`
19
+ of `UrlOptions` and refetches automatically on change. `vue` is an optional
20
+ peer dependency.
16
21
  - **Nuxt adapter** — new `katanakit-js/adapters/nuxt` subpath exporting three
17
22
  pure helpers that bridge KatanaKit Safe Results to Nuxt/Nitro server routes:
18
23
  `useUnwrap(result, context?)`, `useSafeResponse(result)` and
package/README.md CHANGED
@@ -6,9 +6,9 @@ Observer, Factory, Strategy, Facade and Adapter).
6
6
 
7
7
  It runs in the browser, in Node.js (>= 22.18) and in Bun, ships with an Astro
8
8
  `getStaticPaths` adapter, an RSS 2.0 generator, a site-config/SEO module, an
9
- optional Express server reference and a Nuxt (Nitro/H3) adapter. Importing a
10
- module never triggers side effects, and every async operation returns a **Safe
11
- Result** instead of throwing.
9
+ optional Express server reference, a Nuxt (Nitro/H3) adapter and a Vue 3
10
+ composable. Importing a module never triggers side effects, and every async
11
+ operation returns a **Safe Result** instead of throwing.
12
12
 
13
13
  - **Version:** 2.1.4
14
14
  - **npm package:** `katanakit-js`
@@ -36,8 +36,8 @@ storage and DOM across every framework.
36
36
  on HTTP errors.
37
37
  - **Hexagonal architecture** — a pure `core` layer (services), an
38
38
  `infrastructure` layer (browser/runtime adapters), an `adapters` layer
39
- (Astro, Express, Nuxt), a `config` layer (site config + SEO) and a single
40
- source of truth for contracts and types in `src/types/`.
39
+ (Astro, Express, Nuxt, Vue), a `config` layer (site config + SEO) and a
40
+ single source of truth for contracts and types in `src/types/`.
41
41
  - **Design patterns** — Singleton facades, Strategy (logger, storage,
42
42
  crypto/UUID), Factory (errors, debounce/throttle), Observer (signals,
43
43
  IntersectionObserver, media queries), Facade and Adapter, all exposed as
@@ -77,6 +77,9 @@ published as package **subpaths** of the same `katanakit-js` package:
77
77
  // Nuxt / Nitro adapter helpers (no extra dependency; h3 ships with Nuxt)
78
78
  import { useUnwrap } from "katanakit-js/adapters/nuxt";
79
79
 
80
+ // Vue 3 composable (requires vue as a peer dependency)
81
+ import { useKatanaFetch } from "katanakit-js/adapters/vue";
82
+
80
83
  // Express reference server (requires express as a peer dependency)
81
84
  import { ServerExpress } from "katanakit-js/adapters/express";
82
85
  ```
@@ -347,6 +350,54 @@ JSON response object) and `useEventResponse(event, result)` (set the H3 event
347
350
  status code and return data/error). See the
348
351
  [API Reference](docs/API-Reference.md#nuxt-adapter--katanakit-jsadaptersnuxt).
349
352
 
353
+ ## Vue adapter
354
+
355
+ `useKatanaFetch` is a Vue 3 composable that bridges KatanaKit's Safe Results to
356
+ Vue's reactivity system. It exposes `data`, `error`, `loading` and a `refetch`
357
+ function, and it never throws on HTTP errors.
358
+
359
+ ```ts
360
+ import { useInit } from "katanakit-js";
361
+ import { useKatanaFetch } from "katanakit-js/adapters/vue";
362
+
363
+ useInit({
364
+ pokeapi: {
365
+ baseUri: "https://pokeapi.co/api/v2",
366
+ endpoints: { pokemonById: "/pokemon/:id/" },
367
+ },
368
+ });
369
+ ```
370
+
371
+ ```vue
372
+ <script setup lang="ts">
373
+ import { useKatanaFetch } from "katanakit-js/adapters/vue";
374
+
375
+ interface Pokemon { name: string; id: number; }
376
+
377
+ const { data: pokemon, error, loading } = useKatanaFetch<Pokemon>(
378
+ "pokeapi",
379
+ "pokemonById",
380
+ { params: { id: 25 } },
381
+ );
382
+ </script>
383
+
384
+ <template>
385
+ <div v-if="loading">Loading…</div>
386
+ <div v-else-if="error">{{ error.message }}</div>
387
+ <div v-else>{{ pokemon?.name }}</div>
388
+ </template>
389
+ ```
390
+
391
+ Pass a `Ref` as the options argument to refetch automatically when it changes:
392
+
393
+ ```ts
394
+ const id = ref(25);
395
+ const { data } = useKatanaFetch("pokeapi", "pokemonById", computed(() => ({ params: { id: id.value } })));
396
+ ```
397
+
398
+ `vue` is an optional peer dependency — install it only if you use this adapter.
399
+ See the [API Reference](docs/API-Reference.md#vue-adapter--katanakit-jsadaptersvue).
400
+
350
401
  ## Express server (optional)
351
402
 
352
403
  The Express reference adapter is exposed only through its own subpath so it
@@ -389,11 +440,12 @@ project. A `ProductController` and a demo `router` are also exported.
389
440
  | SEO | `useHeadTags` and friends | `useGenerateMetaTags`, `useTitle`, `useRssHeadLink` + typed `SiteConfig` |
390
441
  | Config | `siteConfig` / `SiteConfig` | single source for site metadata, RSS and SEO defaults |
391
442
  | Nuxt | `katanakit-js/adapters/nuxt`| `useUnwrap`, `useSafeResponse`, `useEventResponse` (pure functions) |
443
+ | Vue | `katanakit-js/adapters/vue` | `useKatanaFetch` composable (`data`, `error`, `loading`, `refetch`) |
392
444
  | Server | `katanakit-js/adapters/express` | `ServerExpress`, `router`, `ProductController` (optional reference) |
393
445
 
394
446
  The Astro, RSS, SEO and config modules plus all core/infrastructure services
395
- are re-exported from the main barrel. The Nuxt and Express adapters are only
396
- available through their subpaths.
447
+ are re-exported from the main barrel. The Nuxt, Vue and Express adapters are
448
+ only available through their subpaths.
397
449
 
398
450
  ## Project structure (hexagonal)
399
451
 
@@ -412,10 +464,11 @@ katanakit/
412
464
  │ ├── adapters/ # framework adapters
413
465
  │ │ ├── astro/ # AstroService + RssService
414
466
  │ │ ├── express/ # ServerExpress reference (subpath export)
415
- │ │ └── nuxt/ # Nuxt helpers (subpath export)
467
+ │ │ ├── nuxt/ # Nuxt helpers (subpath export)
468
+ │ │ └── vue/ # Vue composable (subpath export)
416
469
  │ ├── config/ # siteConfig (SiteConfig) + SEO helpers
417
470
  │ └── prisma/ # Prisma schema, contract types and db client
418
- ├── tests/ # Vitest suite (57 tests across 7 files)
471
+ ├── tests/ # Vitest suite (60 tests across 8 files)
419
472
  ├── examples/ # runnable demos
420
473
  ├── docs/ # Getting Started, Architecture, API Reference, Roadmap
421
474
  ├── CONTRIBUTING.md
@@ -0,0 +1,2 @@
1
+ export * from "./vue.service.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./vue.service.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { type MaybeRef, type Ref } from "vue";
2
+ import type { ApiError, UrlOptions } from "../../types/index.js";
3
+ /**
4
+ * Reactive state exposed by the {@link useKatanaFetch} composable.
5
+ */
6
+ export interface KatanaFetchState<T> {
7
+ /** The resolved data on success, `null` otherwise. */
8
+ data: Ref<T | null>;
9
+ /** The Safe Result error on failure, `null` otherwise. */
10
+ error: Ref<ApiError | null>;
11
+ /** Whether a request is in flight. */
12
+ loading: Ref<boolean>;
13
+ /** Re-runs the request manually. */
14
+ refetch: () => Promise<void>;
15
+ }
16
+ /**
17
+ * Vue 3 composable that wraps KatanaKit's `useGet` with the reactivity system.
18
+ * It bridges the Safe Result pattern to idiomatic Vue state (`data`, `error`,
19
+ * `loading`) and never throws on HTTP errors.
20
+ *
21
+ * When `options` is a Vue `Ref`, the request re-runs automatically whenever the
22
+ * ref changes (deep watch), so URL params or query params can drive refetching.
23
+ *
24
+ * @param apiName - Name of the registered API (see `useInit`).
25
+ * @param endpointName - Name of the endpoint inside that API.
26
+ * @param options - Optional `UrlOptions` (path/query params), plain or reactive.
27
+ * @returns Reactive `{ data, error, loading, refetch }`.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * import { useKatanaFetch } from "katanakit-js/adapters/vue";
32
+ *
33
+ * const { data, error, loading } = useKatanaFetch<{ name: string }>(
34
+ * "pokeapi",
35
+ * "pokemonById",
36
+ * { params: { id: 25 } },
37
+ * );
38
+ * ```
39
+ */
40
+ export declare function useKatanaFetch<T>(apiName: string, endpointName: string, options?: MaybeRef<UrlOptions>): KatanaFetchState<T>;
41
+ //# sourceMappingURL=vue.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.service.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/vue.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,QAAQ,EAAE,KAAK,GAAG,EAAiC,MAAM,KAAK,CAAC;AAGpF,OAAO,KAAK,EAAE,QAAQ,EAAe,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAClC,sDAAsD;IACtD,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,0DAA0D;IAC1D,KAAK,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC5B,sCAAsC;IACtC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,oCAAoC;IACpC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,GAC5B,gBAAgB,CAAC,CAAC,CAAC,CA6BrB"}
@@ -0,0 +1,51 @@
1
+ import { isRef, ref, shallowRef, unref, watch } from "vue";
2
+ import { useGet } from "../../core/services/http.service.js";
3
+ /**
4
+ * Vue 3 composable that wraps KatanaKit's `useGet` with the reactivity system.
5
+ * It bridges the Safe Result pattern to idiomatic Vue state (`data`, `error`,
6
+ * `loading`) and never throws on HTTP errors.
7
+ *
8
+ * When `options` is a Vue `Ref`, the request re-runs automatically whenever the
9
+ * ref changes (deep watch), so URL params or query params can drive refetching.
10
+ *
11
+ * @param apiName - Name of the registered API (see `useInit`).
12
+ * @param endpointName - Name of the endpoint inside that API.
13
+ * @param options - Optional `UrlOptions` (path/query params), plain or reactive.
14
+ * @returns Reactive `{ data, error, loading, refetch }`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { useKatanaFetch } from "katanakit-js/adapters/vue";
19
+ *
20
+ * const { data, error, loading } = useKatanaFetch<{ name: string }>(
21
+ * "pokeapi",
22
+ * "pokemonById",
23
+ * { params: { id: 25 } },
24
+ * );
25
+ * ```
26
+ */
27
+ export function useKatanaFetch(apiName, endpointName, options) {
28
+ const data = shallowRef(null);
29
+ const error = ref(null);
30
+ const loading = ref(true);
31
+ const refetch = async () => {
32
+ loading.value = true;
33
+ error.value = null;
34
+ const result = await useGet(apiName, endpointName, unref(options));
35
+ if (result.ok) {
36
+ data.value = result.data;
37
+ }
38
+ else {
39
+ error.value = result.error;
40
+ }
41
+ loading.value = false;
42
+ };
43
+ // Refetch automatically when a reactive options ref changes.
44
+ if (isRef(options)) {
45
+ watch(options, refetch, { deep: true });
46
+ }
47
+ // Initial fetch on setup.
48
+ void refetch();
49
+ return { data, error, loading, refetch };
50
+ }
51
+ //# sourceMappingURL=vue.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.service.js","sourceRoot":"","sources":["../../../src/adapters/vue/vue.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAA2B,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC;AAEpF,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAiB7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,cAAc,CAC7B,OAAe,EACf,YAAoB,EACpB,OAA8B;IAE9B,MAAM,IAAI,GAAG,UAAU,CAAW,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,GAAG,CAAkB,IAAI,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAE1B,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACzC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;QACrB,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAEnB,MAAM,MAAM,GAAmB,MAAM,MAAM,CAAI,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtF,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;QAC1B,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC5B,CAAC;QAED,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC,CAAC;IAEF,6DAA6D;IAC7D,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,0BAA0B;IAC1B,KAAK,OAAO,EAAE,CAAC;IAEf,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "katanakit-js",
3
- "version": "2.1.6",
3
+ "version": "2.2.1",
4
4
  "description": "KatanaKit — a sharp, framework-agnostic TypeScript service toolkit organized with hexagonal architecture.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,6 +18,10 @@
18
18
  "./adapters/nuxt": {
19
19
  "types": "./dist/adapters/nuxt/index.d.ts",
20
20
  "import": "./dist/adapters/nuxt/index.js"
21
+ },
22
+ "./adapters/vue": {
23
+ "types": "./dist/adapters/vue/index.d.ts",
24
+ "import": "./dist/adapters/vue/index.js"
21
25
  }
22
26
  },
23
27
  "files": [
@@ -63,6 +67,7 @@
63
67
  "astro",
64
68
  "express",
65
69
  "nuxt",
70
+ "vue",
66
71
  "singleton",
67
72
  "observer",
68
73
  "factory"
@@ -80,7 +85,8 @@
80
85
  "@prisma/orm-postgres": ">=8.0.0-rc.0",
81
86
  "cors": ">=2.8.0",
82
87
  "dotenv": ">=16.0.0",
83
- "express": ">=5.0.0"
88
+ "express": ">=5.0.0",
89
+ "vue": ">=3.0.0"
84
90
  },
85
91
  "peerDependenciesMeta": {
86
92
  "@prisma/orm-postgres": {
@@ -94,6 +100,9 @@
94
100
  },
95
101
  "express": {
96
102
  "optional": true
103
+ },
104
+ "vue": {
105
+ "optional": true
97
106
  }
98
107
  },
99
108
  "devDependencies": {
@@ -112,6 +121,7 @@
112
121
  "prisma": "8.0.0-rc.12",
113
122
  "typescript": "^7.0.2",
114
123
  "vite": "^8.2.2",
115
- "vitest": "^5.0.0"
124
+ "vitest": "^5.0.0",
125
+ "vue": "^3.5.0"
116
126
  }
117
127
  }