katanakit-js 2.2.1 → 2.12.9
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 +72 -437
- package/dist/adapters/astro/astro.service.d.ts +103 -15
- package/dist/adapters/astro/astro.service.d.ts.map +1 -1
- package/dist/adapters/astro/astro.service.js +145 -75
- package/dist/adapters/astro/astro.service.js.map +1 -1
- package/dist/adapters/astro/index.d.ts +1 -1
- package/dist/adapters/astro/index.d.ts.map +1 -1
- package/dist/adapters/astro/index.js +1 -1
- package/dist/adapters/astro/index.js.map +1 -1
- package/dist/adapters/astro/rss.service.d.ts +85 -105
- package/dist/adapters/astro/rss.service.d.ts.map +1 -1
- package/dist/adapters/astro/rss.service.js +172 -168
- package/dist/adapters/astro/rss.service.js.map +1 -1
- package/dist/adapters/astro/seo.service.d.ts +10 -0
- package/dist/adapters/astro/seo.service.d.ts.map +1 -0
- package/dist/adapters/astro/seo.service.js +3 -0
- package/dist/adapters/astro/seo.service.js.map +1 -0
- package/dist/adapters/express/app.d.ts +30 -1
- package/dist/adapters/express/app.d.ts.map +1 -1
- package/dist/adapters/express/app.js +31 -3
- package/dist/adapters/express/app.js.map +1 -1
- package/dist/adapters/express/index.d.ts +2 -2
- package/dist/adapters/express/index.d.ts.map +1 -1
- package/dist/adapters/express/index.js +2 -2
- package/dist/adapters/express/index.js.map +1 -1
- package/dist/adapters/express/main.js +2 -2
- package/dist/adapters/express/main.js.map +1 -1
- package/dist/adapters/express/products.controller.d.ts +67 -8
- package/dist/adapters/express/products.controller.d.ts.map +1 -1
- package/dist/adapters/express/products.controller.js +105 -49
- package/dist/adapters/express/products.controller.js.map +1 -1
- package/dist/adapters/express/server.d.ts +37 -13
- package/dist/adapters/express/server.d.ts.map +1 -1
- package/dist/adapters/express/server.js +118 -53
- package/dist/adapters/express/server.js.map +1 -1
- package/dist/adapters/nuxt/nuxt.service.d.ts +8 -6
- package/dist/adapters/nuxt/nuxt.service.d.ts.map +1 -1
- package/dist/adapters/nuxt/nuxt.service.js +34 -10
- package/dist/adapters/nuxt/nuxt.service.js.map +1 -1
- package/dist/adapters/vue/vue.service.d.ts +5 -2
- package/dist/adapters/vue/vue.service.d.ts.map +1 -1
- package/dist/adapters/vue/vue.service.js +41 -7
- package/dist/adapters/vue/vue.service.js.map +1 -1
- package/dist/config/index.d.ts +2 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/seo-meta.types.d.ts +177 -0
- package/dist/config/seo-meta.types.d.ts.map +1 -0
- package/dist/config/seo-meta.types.js +11 -0
- package/dist/config/seo-meta.types.js.map +1 -0
- package/dist/config/seo.service.d.ts +41 -58
- package/dist/config/seo.service.d.ts.map +1 -1
- package/dist/config/seo.service.js +468 -136
- package/dist/config/seo.service.js.map +1 -1
- package/dist/config/site.config.d.ts +10 -50
- package/dist/config/site.config.d.ts.map +1 -1
- package/dist/config/site.config.js +8 -36
- package/dist/config/site.config.js.map +1 -1
- package/dist/core/index.d.ts +1 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/services/dates.service.d.ts +149 -22
- package/dist/core/services/dates.service.d.ts.map +1 -1
- package/dist/core/services/dates.service.js +201 -54
- package/dist/core/services/dates.service.js.map +1 -1
- package/dist/core/services/error.service.d.ts +32 -20
- package/dist/core/services/error.service.d.ts.map +1 -1
- package/dist/core/services/error.service.js +44 -32
- package/dist/core/services/error.service.js.map +1 -1
- package/dist/core/services/formatter.service.d.ts +245 -35
- package/dist/core/services/formatter.service.d.ts.map +1 -1
- package/dist/core/services/formatter.service.js +281 -57
- package/dist/core/services/formatter.service.js.map +1 -1
- package/dist/core/services/generator.service.d.ts +115 -26
- package/dist/core/services/generator.service.d.ts.map +1 -1
- package/dist/core/services/generator.service.js +191 -56
- package/dist/core/services/generator.service.js.map +1 -1
- package/dist/core/services/geometry.service.d.ts +369 -39
- package/dist/core/services/geometry.service.d.ts.map +1 -1
- package/dist/core/services/geometry.service.js +424 -66
- package/dist/core/services/geometry.service.js.map +1 -1
- package/dist/core/services/http.service.d.ts +244 -21
- package/dist/core/services/http.service.d.ts.map +1 -1
- package/dist/core/services/http.service.js +419 -98
- package/dist/core/services/http.service.js.map +1 -1
- package/dist/core/services/logger.service.d.ts +95 -29
- package/dist/core/services/logger.service.d.ts.map +1 -1
- package/dist/core/services/logger.service.js +167 -41
- package/dist/core/services/logger.service.js.map +1 -1
- package/dist/core/services/reactive.service.d.ts +146 -19
- package/dist/core/services/reactive.service.d.ts.map +1 -1
- package/dist/core/services/reactive.service.js +278 -137
- package/dist/core/services/reactive.service.js.map +1 -1
- package/dist/core/services/timing.service.d.ts +142 -20
- package/dist/core/services/timing.service.d.ts.map +1 -1
- package/dist/core/services/timing.service.js +324 -185
- package/dist/core/services/timing.service.js.map +1 -1
- package/dist/core/services/utils.service.d.ts +228 -43
- package/dist/core/services/utils.service.d.ts.map +1 -1
- package/dist/core/services/utils.service.js +305 -125
- package/dist/core/services/utils.service.js.map +1 -1
- package/dist/infrastructure/dom/dom.service.d.ts +307 -44
- package/dist/infrastructure/dom/dom.service.d.ts.map +1 -1
- package/dist/infrastructure/dom/dom.service.js +408 -129
- package/dist/infrastructure/dom/dom.service.js.map +1 -1
- package/dist/infrastructure/index.d.ts +0 -3
- package/dist/infrastructure/index.d.ts.map +1 -1
- package/dist/infrastructure/index.js +0 -3
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/infrastructure/observer/observer.service.d.ts +124 -31
- package/dist/infrastructure/observer/observer.service.d.ts.map +1 -1
- package/dist/infrastructure/observer/observer.service.js +227 -131
- package/dist/infrastructure/observer/observer.service.js.map +1 -1
- package/dist/infrastructure/sensors/sensors.service.d.ts +154 -22
- package/dist/infrastructure/sensors/sensors.service.d.ts.map +1 -1
- package/dist/infrastructure/sensors/sensors.service.js +264 -112
- package/dist/infrastructure/sensors/sensors.service.js.map +1 -1
- package/dist/infrastructure/storage/storage.service.d.ts +123 -45
- package/dist/infrastructure/storage/storage.service.d.ts.map +1 -1
- package/dist/infrastructure/storage/storage.service.js +236 -66
- package/dist/infrastructure/storage/storage.service.js.map +1 -1
- package/dist/infrastructure/theme/theme.service.d.ts +93 -29
- package/dist/infrastructure/theme/theme.service.d.ts.map +1 -1
- package/dist/infrastructure/theme/theme.service.js +198 -96
- package/dist/infrastructure/theme/theme.service.js.map +1 -1
- package/dist/infrastructure/viewport/viewport.service.d.ts +233 -35
- package/dist/infrastructure/viewport/viewport.service.d.ts.map +1 -1
- package/dist/infrastructure/viewport/viewport.service.js +358 -139
- package/dist/infrastructure/viewport/viewport.service.js.map +1 -1
- package/dist/infrastructure/worker/worker.service.d.ts +84 -38
- package/dist/infrastructure/worker/worker.service.d.ts.map +1 -1
- package/dist/infrastructure/worker/worker.service.js +234 -133
- package/dist/infrastructure/worker/worker.service.js.map +1 -1
- package/dist/prisma/index.d.ts +2 -0
- package/dist/prisma/index.d.ts.map +1 -0
- package/dist/prisma/index.js +2 -0
- package/dist/prisma/index.js.map +1 -0
- package/dist/prisma/schema.json +11 -33
- package/dist/prisma/use-prisma.d.ts +68 -0
- package/dist/prisma/use-prisma.d.ts.map +1 -0
- package/dist/prisma/use-prisma.js +82 -0
- package/dist/prisma/use-prisma.js.map +1 -0
- package/dist/types/index.d.ts +20 -12
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +124 -125
- package/CHANGELOG.md +0 -101
package/README.md
CHANGED
|
@@ -1,61 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
KatanaKit is a sharp, framework-agnostic **TypeScript service toolkit** organized
|
|
4
|
-
with **hexagonal architecture** and built on proven design patterns (Singleton,
|
|
5
|
-
Observer, Factory, Strategy, Facade and Adapter).
|
|
6
|
-
|
|
7
|
-
It runs in the browser, in Node.js (>= 22.18) and in Bun, ships with an Astro
|
|
8
|
-
`getStaticPaths` adapter, an RSS 2.0 generator, a site-config/SEO module, an
|
|
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
|
-
|
|
13
|
-
- **Version:** 2.1.4
|
|
14
|
-
- **npm package:** `katanakit-js`
|
|
15
|
-
- **Repository:** [senseikatana/katanakit](https://github.com/senseikatana/katanakit)
|
|
16
|
-
(development happens on the `dev` branch)
|
|
17
|
-
- **License:** MIT
|
|
18
|
-
|
|
19
|
-
## Why
|
|
20
|
-
|
|
21
|
-
Modern frontend and full-stack apps keep reimplementing the same plumbing:
|
|
22
|
-
fetching an API safely, logging, persisting to storage, querying the DOM,
|
|
23
|
-
reacting to state changes, generating slugs, formatting dates and money,
|
|
24
|
-
building RSS/SEO output. KatanaKit provides all of that as a single, typed and
|
|
25
|
-
tree-shakeable set of `use*` services with a consistent API: one `useInit` for
|
|
26
|
-
your APIs, one `useFetch` that returns a Safe Result, one way to do logging,
|
|
27
|
-
storage and DOM across every framework.
|
|
1
|
+
# `katanakit-js`
|
|
28
2
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- **Safe URL construction** — builds URLs from a JSON-defined API registry using
|
|
32
|
-
the native `URL` API and `encodeURIComponent`; only `http:`/`https:` schemes
|
|
33
|
-
are allowed (prevents `javascript:` URLs and SSRF).
|
|
34
|
-
- **Safe Result** — every `useFetch` returns a discriminated union
|
|
35
|
-
`{ data, error, url, status, ok }` (Astro Actions style) instead of throwing
|
|
36
|
-
on HTTP errors.
|
|
37
|
-
- **Hexagonal architecture** — a pure `core` layer (services), an
|
|
38
|
-
`infrastructure` layer (browser/runtime adapters), an `adapters` layer
|
|
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
|
-
- **Design patterns** — Singleton facades, Strategy (logger, storage,
|
|
42
|
-
crypto/UUID), Factory (errors, debounce/throttle), Observer (signals,
|
|
43
|
-
IntersectionObserver, media queries), Facade and Adapter, all exposed as
|
|
44
|
-
`use*` methods (like React hooks) with safe destructured exports.
|
|
45
|
-
- **Consistent `use*` API** — every public method is prefixed with `use`
|
|
46
|
-
(`useInit`, `useFetch`, `useLog`, `useCreateSignal`, ...); the only exception
|
|
47
|
-
is `getInstance()`.
|
|
48
|
-
- **Pure ESM** — relative imports use explicit `.js` extensions and
|
|
49
|
-
`module: nodenext`; bundlers and Node resolve the package cleanly.
|
|
50
|
-
- **Zero side effects on import** — importing a module never triggers network
|
|
51
|
-
calls, timers, storage writes or DOM mutations.
|
|
52
|
-
- **SSR-safe** — browser-only adapters guard or fall back gracefully
|
|
53
|
-
(in-memory storage, main-thread worker execution) when `window` is
|
|
54
|
-
unavailable.
|
|
55
|
-
- **Optional heavy dependencies** — only `@js-temporal/polyfill` is a runtime
|
|
56
|
-
dependency; `express`, `cors`, `dotenv` and `@prisma/orm-postgres` are
|
|
57
|
-
optional peer dependencies.
|
|
58
|
-
- **Fully typed** — strict TypeScript with generated `.d.ts` declarations.
|
|
3
|
+
A sharp, framework-agnostic TypeScript service toolkit organized with hexagonal architecture.
|
|
59
4
|
|
|
60
5
|
## Installation
|
|
61
6
|
|
|
@@ -63,437 +8,127 @@ storage and DOM across every framework.
|
|
|
63
8
|
npm install katanakit-js
|
|
64
9
|
# or
|
|
65
10
|
bun add katanakit-js
|
|
11
|
+
# or
|
|
12
|
+
yarn add katanakit-js
|
|
66
13
|
```
|
|
67
14
|
|
|
68
|
-
|
|
69
|
-
should use `moduleResolution: "nodenext"` (or `"bundler"`).
|
|
70
|
-
|
|
71
|
-
### Framework adapters
|
|
72
|
-
|
|
73
|
-
The root import is framework-agnostic. Framework-specific entry points are
|
|
74
|
-
published as package **subpaths** of the same `katanakit-js` package:
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
// Nuxt / Nitro adapter helpers (no extra dependency; h3 ships with Nuxt)
|
|
78
|
-
import { useUnwrap } from "katanakit-js/adapters/nuxt";
|
|
15
|
+
### CDN (ESM)
|
|
79
16
|
|
|
80
|
-
|
|
81
|
-
import { useKatanaFetch } from "katanakit-js/adapters/vue";
|
|
17
|
+
In the browser, use jsDelivr **`/+esm`** so named exports and dependencies resolve:
|
|
82
18
|
|
|
83
|
-
|
|
84
|
-
|
|
19
|
+
```html
|
|
20
|
+
<script type="module">
|
|
21
|
+
import { useLogger, useGetApi, useInitApis } from "https://cdn.jsdelivr.net/npm/katanakit-js/+esm";
|
|
22
|
+
useLogger("ready");
|
|
23
|
+
</script>
|
|
85
24
|
```
|
|
86
25
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
26
|
+
| CDN | URL |
|
|
27
|
+
|-----|-----|
|
|
28
|
+
| **jsDelivr `/+esm`** (recommended) | `https://cdn.jsdelivr.net/npm/katanakit-js/+esm` |
|
|
29
|
+
| **esm.sh** | `https://esm.sh/katanakit-js` |
|
|
30
|
+
| **Raw ESM file** | `https://cdn.jsdelivr.net/npm/katanakit-js/dist/index.js` (needs bundler or import map) |
|
|
92
31
|
|
|
93
|
-
|
|
94
|
-
git clone https://github.com/senseikatana/katanakit.git
|
|
95
|
-
cd katanakit
|
|
96
|
-
bun install
|
|
97
|
-
bun run build # outputs to dist/
|
|
98
|
-
```
|
|
32
|
+
Pin a version in production (e.g. `@2.8.0/+esm`). There is no IIFE/UMD build.
|
|
99
33
|
|
|
100
34
|
## Quick Start
|
|
101
35
|
|
|
102
|
-
Everything below is importable from the main barrel `katanakit-js`.
|
|
103
|
-
|
|
104
|
-
### HTTP client
|
|
105
|
-
|
|
106
36
|
```ts
|
|
107
|
-
import {
|
|
37
|
+
import { useInitApis, useGetApi, useLogger } from "katanakit-js";
|
|
38
|
+
|
|
39
|
+
useLogger("boot");
|
|
108
40
|
|
|
109
|
-
//
|
|
110
|
-
|
|
41
|
+
// Register your APIs once
|
|
42
|
+
useInitApis({
|
|
111
43
|
pokeapi: {
|
|
112
44
|
baseUri: "https://pokeapi.co/api/v2",
|
|
113
|
-
endpoints: {
|
|
114
|
-
pokemonById: "/pokemon/:id/",
|
|
115
|
-
pokemons: "/pokemons/",
|
|
116
|
-
},
|
|
45
|
+
endpoints: { pokemonById: "/pokemon/:id/" },
|
|
117
46
|
},
|
|
118
47
|
});
|
|
119
48
|
|
|
120
|
-
//
|
|
121
|
-
const
|
|
122
|
-
params: { id: "pikachu" },
|
|
123
|
-
});
|
|
124
|
-
// => "https://pokeapi.co/api/v2/pokemon/pikachu/"
|
|
125
|
-
|
|
126
|
-
// 3. Fetch with a Safe Result (no throwing on HTTP errors).
|
|
127
|
-
const result = await useGet<{ name: string }>("pokeapi", "pokemonById", {
|
|
49
|
+
// Fetch with Safe Result — no try/catch needed for HTTP failures
|
|
50
|
+
const result = await useGetApi<{ name: string }>("pokeapi", "pokemonById", {
|
|
128
51
|
params: { id: 25 },
|
|
129
52
|
});
|
|
130
53
|
|
|
131
54
|
if (result.ok) {
|
|
132
|
-
console.log(result.data.name);
|
|
55
|
+
console.log(result.data.name); // "pikachu"
|
|
133
56
|
} else {
|
|
134
|
-
console.error(result.error.message
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 4. POST JSON.
|
|
138
|
-
await usePost("pokeapi", "pokemons", { name: "charmander" });
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Logger, storage and DOM
|
|
142
|
-
|
|
143
|
-
```ts
|
|
144
|
-
import {
|
|
145
|
-
useLog,
|
|
146
|
-
useSetStorage,
|
|
147
|
-
useGetStorage,
|
|
148
|
-
useRemoveStorage,
|
|
149
|
-
useAddClass,
|
|
150
|
-
useGetRoot,
|
|
151
|
-
} from "katanakit-js";
|
|
152
|
-
|
|
153
|
-
useLog("Hello", { user: "John" }); // info level
|
|
154
|
-
useLog("error", "Something failed", { code: 500 }); // error level
|
|
155
|
-
|
|
156
|
-
useSetStorage("theme", "dark");
|
|
157
|
-
const theme = useGetStorage<string>("theme"); // "dark"
|
|
158
|
-
useRemoveStorage("theme");
|
|
159
|
-
|
|
160
|
-
useAddClass(useGetRoot()!, "dark-mode");
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Storage is SSR-safe: when `window` is unavailable an in-memory fallback is used
|
|
164
|
-
automatically, so imports never crash in Node/Bun.
|
|
165
|
-
|
|
166
|
-
## Astro adapter
|
|
167
|
-
|
|
168
|
-
KatanaKit converts arbitrary collections into the payload Astro's
|
|
169
|
-
`getStaticPaths` expects, wrapped in a Safe Result.
|
|
170
|
-
|
|
171
|
-
```ts
|
|
172
|
-
// src/pages/blog/[slug].astro
|
|
173
|
-
import { AstroService } from "katanakit-js";
|
|
174
|
-
|
|
175
|
-
export async function getStaticPaths() {
|
|
176
|
-
const { useGetStaticPaths } = AstroService.getInstance();
|
|
177
|
-
|
|
178
|
-
return useGetStaticPaths(getCollection, "blog", {
|
|
179
|
-
param: "slug",
|
|
180
|
-
valueFrom: (entry) => entry.slug ?? entry.id,
|
|
181
|
-
propsFrom: (entry) => entry.data,
|
|
182
|
-
});
|
|
57
|
+
console.error(result.error.message);
|
|
183
58
|
}
|
|
184
59
|
```
|
|
185
60
|
|
|
186
|
-
|
|
187
|
-
`usePathsFromValues` and `useExtractUniqueValues`. See the
|
|
188
|
-
[API Reference](docs/API-Reference.md#astro--astroservice).
|
|
61
|
+
## Features
|
|
189
62
|
|
|
190
|
-
|
|
63
|
+
- **Safe Results** — HTTP (and other fallible) operations return `{ data, error, ok }` instead of throwing
|
|
64
|
+
- **Zero side effects** — importing any module is safe. No `fetch` calls, no `console.log`, no storage writes
|
|
65
|
+
- **Hexagonal architecture** — pure core, infrastructure adapters, framework adapters
|
|
66
|
+
- **Tree-shakeable** — destructured re-exports from Singleton facades
|
|
67
|
+
- **SSR-safe** — all infrastructure adapters guard or fall back gracefully in server environments
|
|
191
68
|
|
|
192
|
-
|
|
193
|
-
(`@astrojs/rss` is not required).
|
|
69
|
+
## Framework usage
|
|
194
70
|
|
|
195
|
-
|
|
196
|
-
// src/pages/rss.xml.ts
|
|
197
|
-
import { RssService } from "katanakit-js";
|
|
198
|
-
import { getCollection } from "astro:content";
|
|
199
|
-
|
|
200
|
-
const { useCreateRssEndpoint } = RssService.getInstance();
|
|
201
|
-
|
|
202
|
-
export const GET = useCreateRssEndpoint({
|
|
203
|
-
title: "My Blog",
|
|
204
|
-
description: "Posts about TypeScript",
|
|
205
|
-
site: "https://example.com",
|
|
206
|
-
items: async () => {
|
|
207
|
-
const posts = await getCollection("blog");
|
|
208
|
-
return posts.map((post) => ({
|
|
209
|
-
title: post.data.title,
|
|
210
|
-
pubDate: post.data.date,
|
|
211
|
-
link: `/blog/${post.slug}/`,
|
|
212
|
-
description: post.data.description,
|
|
213
|
-
}));
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
```
|
|
71
|
+
All common `use*` helpers (`useLogger`, `useInitApis`, `useGetApi`, formatter, dates, utils, theme, …) are on the **main barrel** `katanakit-js`.
|
|
217
72
|
|
|
218
|
-
|
|
73
|
+
### Astro (npm)
|
|
219
74
|
|
|
220
75
|
```astro
|
|
221
76
|
---
|
|
222
|
-
|
|
77
|
+
// Frontmatter = server
|
|
78
|
+
import { useLogger, useGetApi, useInitApis } from "katanakit-js";
|
|
79
|
+
useInitApis({ /* ... */ });
|
|
80
|
+
const result = await useGetApi("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
223
81
|
---
|
|
224
|
-
<
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
`useCreateRssEndpointFromConfig(siteConfig, items)` builds the same endpoint
|
|
230
|
-
from your `SiteConfig`. See the [API Reference](docs/API-Reference.md#rss--rssservice).
|
|
231
|
-
|
|
232
|
-
## Site config and SEO
|
|
233
|
-
|
|
234
|
-
Centralize your site metadata in a typed `SiteConfig` and derive every `<head>`
|
|
235
|
-
tag from it.
|
|
236
|
-
|
|
237
|
-
```ts
|
|
238
|
-
// src/config/site.config.ts
|
|
239
|
-
import { type SiteConfig } from "katanakit-js";
|
|
240
|
-
|
|
241
|
-
export const siteConfig: SiteConfig = {
|
|
242
|
-
site: "https://myblog.com",
|
|
243
|
-
title: "My Blog",
|
|
244
|
-
description: "A blog about TypeScript and Astro",
|
|
245
|
-
lang: "en",
|
|
246
|
-
author: "John Doe",
|
|
247
|
-
ogImage: "/og-default.png",
|
|
248
|
-
twitter: "johndoe",
|
|
249
|
-
rss: { enabled: true, path: "/rss.xml", limit: 20 },
|
|
250
|
-
seo: { noindex: false, canonical: true, openGraph: true, twitterCard: true, jsonLd: true },
|
|
251
|
-
nav: [
|
|
252
|
-
{ label: "Home", href: "/" },
|
|
253
|
-
{ label: "Blog", href: "/blog" },
|
|
254
|
-
{ label: "GitHub", href: "https://github.com/senseikatana/katanakit", external: true },
|
|
255
|
-
],
|
|
256
|
-
};
|
|
82
|
+
<script>
|
|
83
|
+
// Client script — Vite bundles the same package
|
|
84
|
+
import { useLogger } from "katanakit-js";
|
|
85
|
+
useLogger("client");
|
|
86
|
+
</script>
|
|
257
87
|
```
|
|
258
88
|
|
|
259
|
-
|
|
260
|
-
Twitter Card and JSON-LD) in your layout:
|
|
89
|
+
### Astro (CDN client)
|
|
261
90
|
|
|
262
91
|
```astro
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
import { useHeadTags } from "katanakit-js";
|
|
267
|
-
|
|
268
|
-
interface Props {
|
|
269
|
-
title: string;
|
|
270
|
-
description?: string;
|
|
271
|
-
ogType?: "website" | "article";
|
|
272
|
-
publishedTime?: string;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const { title, description, ogType, publishedTime } = Astro.props;
|
|
276
|
-
const headTags = useHeadTags(siteConfig, {
|
|
277
|
-
title,
|
|
278
|
-
description,
|
|
279
|
-
url: new URL(Astro.url.pathname, siteConfig.site).href,
|
|
280
|
-
ogType,
|
|
281
|
-
publishedTime,
|
|
282
|
-
});
|
|
283
|
-
---
|
|
284
|
-
<html lang={siteConfig.lang}>
|
|
285
|
-
<head>
|
|
286
|
-
<meta charset="utf-8" />
|
|
287
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
288
|
-
<Fragment set:html={headTags} />
|
|
289
|
-
</head>
|
|
290
|
-
<body>
|
|
291
|
-
<slot />
|
|
292
|
-
</body>
|
|
293
|
-
</html>
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
The RSS endpoint consumes the same config:
|
|
297
|
-
|
|
298
|
-
```ts
|
|
299
|
-
// src/pages/rss.xml.ts
|
|
300
|
-
import { RssService } from "katanakit-js";
|
|
301
|
-
import { siteConfig } from "@/config/site.config";
|
|
302
|
-
import { getCollection } from "astro:content";
|
|
303
|
-
|
|
304
|
-
const { useCreateRssEndpointFromConfig } = RssService.getInstance();
|
|
305
|
-
|
|
306
|
-
export const GET = useCreateRssEndpointFromConfig(siteConfig, async () => {
|
|
307
|
-
const posts = await getCollection("blog");
|
|
308
|
-
return posts.map((post) => ({
|
|
309
|
-
title: post.data.title,
|
|
310
|
-
pubDate: post.data.date,
|
|
311
|
-
link: `/blog/${post.slug}/`,
|
|
312
|
-
description: post.data.description,
|
|
313
|
-
}));
|
|
314
|
-
});
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
## Nuxt adapter
|
|
318
|
-
|
|
319
|
-
New in 2.1.4. Three pure helper functions bridge KatanaKit's Safe Results to
|
|
320
|
-
Nuxt/Nitro server routes. They are **not** singleton services — just exported
|
|
321
|
-
functions — and they avoid a hard dependency on `h3` (it ships with Nuxt).
|
|
322
|
-
|
|
323
|
-
```ts
|
|
324
|
-
import { useInit, useGet } from "katanakit-js";
|
|
325
|
-
import { useUnwrap } from "katanakit-js/adapters/nuxt";
|
|
326
|
-
|
|
327
|
-
// server/plugins/api.ts — register your APIs once
|
|
328
|
-
useInit({
|
|
329
|
-
pokeapi: {
|
|
330
|
-
baseUri: "https://pokeapi.co/api/v2",
|
|
331
|
-
endpoints: { pokemonById: "/pokemon/:id/" },
|
|
332
|
-
},
|
|
333
|
-
});
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
```ts
|
|
337
|
-
// server/api/pokemon/[id].ts
|
|
338
|
-
import { useGet } from "katanakit-js";
|
|
339
|
-
import { useUnwrap } from "katanakit-js/adapters/nuxt";
|
|
340
|
-
|
|
341
|
-
export default defineEventHandler(async (event) => {
|
|
342
|
-
const id = getRouterParam(event, "id");
|
|
343
|
-
const result = await useGet("pokeapi", "pokemonById", { params: { id } });
|
|
344
|
-
return useUnwrap(result, `Pokemon ${id}`); // returns data, or throws an H3-compatible error
|
|
345
|
-
});
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
The other helpers are `useSafeResponse(result)` (shape the result as a clean
|
|
349
|
-
JSON response object) and `useEventResponse(event, result)` (set the H3 event
|
|
350
|
-
status code and return data/error). See the
|
|
351
|
-
[API Reference](docs/API-Reference.md#nuxt-adapter--katanakit-jsadaptersnuxt).
|
|
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
|
-
);
|
|
92
|
+
<script is:inline type="module">
|
|
93
|
+
import { useLogger } from "https://cdn.jsdelivr.net/npm/katanakit-js/+esm";
|
|
94
|
+
useLogger("cdn");
|
|
382
95
|
</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
96
|
```
|
|
390
97
|
|
|
391
|
-
|
|
98
|
+
### Vue / Nuxt / vanilla
|
|
392
99
|
|
|
393
100
|
```ts
|
|
394
|
-
|
|
395
|
-
|
|
101
|
+
import { useLogger, useInitApis, useGetApi } from "katanakit-js";
|
|
102
|
+
import { useKatanaFetch } from "katanakit-js/adapters/vue"; // Vue only
|
|
103
|
+
import { useUnwrap } from "katanakit-js/adapters/nuxt"; // Nuxt only
|
|
396
104
|
```
|
|
397
105
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
The Express reference adapter is exposed only through its own subpath so it
|
|
404
|
-
never bloats the main bundle:
|
|
405
|
-
|
|
406
|
-
```ts
|
|
407
|
-
import { ServerExpress } from "katanakit-js/adapters/express";
|
|
408
|
-
|
|
409
|
-
ServerExpress.getInstance().useStart(); // http://localhost:3000
|
|
106
|
+
```html
|
|
107
|
+
<!-- vanilla -->
|
|
108
|
+
<script type="module">
|
|
109
|
+
import { useLogger } from "https://cdn.jsdelivr.net/npm/katanakit-js/+esm";
|
|
110
|
+
</script>
|
|
410
111
|
```
|
|
411
112
|
|
|
412
|
-
|
|
413
|
-
project. A `ProductController` and a demo `router` are also exported.
|
|
414
|
-
|
|
415
|
-
## Services at a glance
|
|
416
|
-
|
|
417
|
-
| Area | Service / module | Highlights |
|
|
418
|
-
| --------- | --------------------------- | ------------------------------------------------------------------- |
|
|
419
|
-
| HTTP | `FetchApiManager` | `useInit`, `useGetApis`, `useBuildUrl`, `useFetch`, `useGet`, `usePost`, `usePut`, `useDelete` |
|
|
420
|
-
| Logging | `LoggerService` | `useLog`, `useError`, `useClear`, `useTable`, pluggable `LogStrategy` |
|
|
421
|
-
| Storage | `StorageService` | `useGetStorage`, `useSetStorage`, `useRemoveStorage`, `useClearStorage` (SSR-safe) |
|
|
422
|
-
| DOM | `DomService` | `useQuerySelector`, `useAddClass`, `useOn`, `useSetText`, ... |
|
|
423
|
-
| Reactive | `ReactiveService` | `useCreateSignal`, `useCreateEffect`, `useCreateMemo`, `useCreateToggle`, `useCreateStorageSignal`, `useCreateDebouncedSignal`, `useCreateBatch` |
|
|
424
|
-
| Format | `FormatterService` | `useFormatNumber`, `useFormatCurrency`, `useJsonStringify`, `useUpperCase`, `useCapitalize`, ... |
|
|
425
|
-
| Convert | `ConverterService` | `useToCelsius`, `useToFahrenheit`, `useToMiles`, `useToKilos`, ... |
|
|
426
|
-
| Errors | `ErrorFactoryService` | `useBadRequest`, `useUnauthorized`, `useForbidden`, `useNotFound`, `useInternal`, `useCustom` |
|
|
427
|
-
| Generate | `GeneratorService` | `useUuid`, `useSlugify`, `useNumericId`, `useToken`, `useEncrypt` |
|
|
428
|
-
| Dates | `DatesService` | `useFormat`, `useNow`, `useAddDays`, `useIsBefore`, `useLastDayOfMonth`, ... (Temporal) |
|
|
429
|
-
| Geometry | `GeometryUtils` | `area`, `perimeter`, `volume` static helpers (`useCircle`, `useSphere`, ...) |
|
|
430
|
-
| Timing | `TimingService` | `useDelay`, `useSetTimeout`, `useInterval`, `useDebounce`, `useThrottle`, `useRepeat`, `useRace` |
|
|
431
|
-
| Utils | `DataUtils` / `SystemUtils` | `useUnique`, `useGroupBy`, `useDeepClone`, `useSleep`, `useRetry`, `useRound`, ... |
|
|
432
|
-
| Viewport | `ViewportService` | scroll, fullscreen, visibility, `usePrefersReducedMotion` |
|
|
433
|
-
| Sensors | `SensorsUtils` | `useGetGeolocation`, `useGetMediaStream`, `useVibrate`, `useGetBattery`, ... |
|
|
434
|
-
| Observer | `ObserverService` | `useCreate`, `useObserve`, `useObserveAll`, `useDisconnect` |
|
|
435
|
-
| LazyLoad | `LazyLoaderService` | `useInit`, `useStop`, `useStopAll` for `img[data-src]` |
|
|
436
|
-
| Worker | `WorkerService` | `useRun`, `useCreatePool`, `useRunPool`, `useTerminate` |
|
|
437
|
-
| Theme | `ThemeService` | `useInitTheme`, `useSetThemeMode`, `useToggleTheme`, `useResetTheme` |
|
|
438
|
-
| Astro | `AstroService` | `useGetStaticPaths`, `usePathsFrom`, `useGeneratePagination`, ... |
|
|
439
|
-
| RSS | `RssService` | `useGenerateRss`, `useRssLinkTag`, `useCreateRssEndpoint`, `useCreateRssEndpointFromConfig` |
|
|
440
|
-
| SEO | `useHeadTags` and friends | `useGenerateMetaTags`, `useTitle`, `useRssHeadLink` + typed `SiteConfig` |
|
|
441
|
-
| Config | `siteConfig` / `SiteConfig` | single source for site metadata, RSS and SEO defaults |
|
|
442
|
-
| Nuxt | `katanakit-js/adapters/nuxt`| `useUnwrap`, `useSafeResponse`, `useEventResponse` (pure functions) |
|
|
443
|
-
| Vue | `katanakit-js/adapters/vue` | `useKatanaFetch` composable (`data`, `error`, `loading`, `refetch`) |
|
|
444
|
-
| Server | `katanakit-js/adapters/express` | `ServerExpress`, `router`, `ProductController` (optional reference) |
|
|
445
|
-
|
|
446
|
-
The Astro, RSS, SEO and config modules plus all core/infrastructure services
|
|
447
|
-
are re-exported from the main barrel. The Nuxt, Vue and Express adapters are
|
|
448
|
-
only available through their subpaths.
|
|
449
|
-
|
|
450
|
-
## Project structure (hexagonal)
|
|
113
|
+
See [Getting Started](https://senseikatana.github.io/katanakit-js/docs/guides/getting-started) for full recipes.
|
|
451
114
|
|
|
452
|
-
|
|
453
|
-
katanakit/
|
|
454
|
-
├── package.json # name: katanakit-js, ESM, exports map
|
|
455
|
-
├── prisma.config.ts # Prisma ORM config (contract + connection)
|
|
456
|
-
├── src/
|
|
457
|
-
│ ├── index.ts # main barrel (public API)
|
|
458
|
-
│ ├── types/ # single source of truth: contracts & types
|
|
459
|
-
│ ├── core/
|
|
460
|
-
│ │ └── services/ # pure services (no I/O): logger, http, ...
|
|
461
|
-
│ ├── infrastructure/ # browser/runtime adapters
|
|
462
|
-
│ │ ├── dom/ storage/ viewport/ sensors/
|
|
463
|
-
│ │ └── observer/ worker/ theme/
|
|
464
|
-
│ ├── adapters/ # framework adapters
|
|
465
|
-
│ │ ├── astro/ # AstroService + RssService
|
|
466
|
-
│ │ ├── express/ # ServerExpress reference (subpath export)
|
|
467
|
-
│ │ ├── nuxt/ # Nuxt helpers (subpath export)
|
|
468
|
-
│ │ └── vue/ # Vue composable (subpath export)
|
|
469
|
-
│ ├── config/ # siteConfig (SiteConfig) + SEO helpers
|
|
470
|
-
│ └── prisma/ # Prisma schema, contract types and db client
|
|
471
|
-
├── tests/ # Vitest suite (60 tests across 8 files)
|
|
472
|
-
├── examples/ # runnable demos
|
|
473
|
-
├── docs/ # Getting Started, Architecture, API Reference, Roadmap
|
|
474
|
-
├── CONTRIBUTING.md
|
|
475
|
-
└── SECURITY.md
|
|
476
|
-
```
|
|
115
|
+
## Framework Adapters
|
|
477
116
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
117
|
+
| Adapter | Import | Description |
|
|
118
|
+
|---------|--------|-------------|
|
|
119
|
+
| **Express** | `katanakit-js/adapters/express` | Reference server with CORS and hardened headers |
|
|
120
|
+
| **Nuxt** | `katanakit-js/adapters/nuxt` | `useUnwrap`, `useSafeResponse`, `useEventResponse` |
|
|
121
|
+
| **Vue** | `katanakit-js/adapters/vue` | `useKatanaFetch` composable with reactivity |
|
|
122
|
+
| **Astro** | `katanakit-js` or `katanakit-js/adapters/astro` | `AstroService`, `RssService` |
|
|
481
123
|
|
|
482
124
|
## Documentation
|
|
483
125
|
|
|
484
|
-
- [Getting Started](docs/
|
|
485
|
-
- [Architecture](docs/
|
|
486
|
-
- [API Reference](docs/
|
|
487
|
-
- [Roadmap](docs/
|
|
488
|
-
- [
|
|
489
|
-
- [Changelog](CHANGELOG.md)
|
|
490
|
-
|
|
491
|
-
## Contributing
|
|
492
|
-
|
|
493
|
-
Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
494
|
-
the development contract (hexagonal layering, `use*` convention, `.js` ESM
|
|
495
|
-
imports, tests, scripts) before opening a pull request.
|
|
126
|
+
- [Getting Started](https://senseikatana.github.io/katanakit-js/docs/guides/getting-started)
|
|
127
|
+
- [Architecture](https://senseikatana.github.io/katanakit-js/docs/guides/architecture)
|
|
128
|
+
- [API Reference](https://senseikatana.github.io/katanakit-js/docs/api)
|
|
129
|
+
- [Roadmap](https://senseikatana.github.io/katanakit-js/docs/guides/roadmap)
|
|
130
|
+
- [Changelog](https://senseikatana.github.io/katanakit-js/docs/changelog)
|
|
496
131
|
|
|
497
132
|
## License
|
|
498
133
|
|
|
499
|
-
|
|
134
|
+
MIT
|