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 +5 -0
- package/README.md +62 -9
- package/dist/adapters/vue/index.d.ts +2 -0
- package/dist/adapters/vue/index.d.ts.map +1 -0
- package/dist/adapters/vue/index.js +2 -0
- package/dist/adapters/vue/index.js.map +1 -0
- package/dist/adapters/vue/vue.service.d.ts +41 -0
- package/dist/adapters/vue/vue.service.d.ts.map +1 -0
- package/dist/adapters/vue/vue.service.js +51 -0
- package/dist/adapters/vue/vue.service.js.map +1 -0
- package/package.json +13 -3
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
|
|
10
|
-
module never triggers side effects, and every async
|
|
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
|
|
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
|
|
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
|
-
│ │
|
|
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 (
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
|
@@ -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
|
|
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
|
}
|