katanakit-js 2.1.6 → 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 +73 -385
- 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/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 +44 -0
- package/dist/adapters/vue/vue.service.d.ts.map +1 -0
- package/dist/adapters/vue/vue.service.js +85 -0
- package/dist/adapters/vue/vue.service.js.map +1 -0
- 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 -115
- package/CHANGELOG.md +0 -96
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 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.
|
|
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), a `config` layer (site config + SEO) and a single
|
|
40
|
-
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,384 +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"`).
|
|
15
|
+
### CDN (ESM)
|
|
70
16
|
|
|
71
|
-
|
|
17
|
+
In the browser, use jsDelivr **`/+esm`** so named exports and dependencies resolve:
|
|
72
18
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
import { useUnwrap } from "katanakit-js/adapters/nuxt";
|
|
79
|
-
|
|
80
|
-
// Express reference server (requires express as a peer dependency)
|
|
81
|
-
import { ServerExpress } from "katanakit-js/adapters/express";
|
|
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>
|
|
82
24
|
```
|
|
83
25
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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) |
|
|
89
31
|
|
|
90
|
-
|
|
91
|
-
git clone https://github.com/senseikatana/katanakit.git
|
|
92
|
-
cd katanakit
|
|
93
|
-
bun install
|
|
94
|
-
bun run build # outputs to dist/
|
|
95
|
-
```
|
|
32
|
+
Pin a version in production (e.g. `@2.8.0/+esm`). There is no IIFE/UMD build.
|
|
96
33
|
|
|
97
34
|
## Quick Start
|
|
98
35
|
|
|
99
|
-
Everything below is importable from the main barrel `katanakit-js`.
|
|
100
|
-
|
|
101
|
-
### HTTP client
|
|
102
|
-
|
|
103
36
|
```ts
|
|
104
|
-
import {
|
|
37
|
+
import { useInitApis, useGetApi, useLogger } from "katanakit-js";
|
|
38
|
+
|
|
39
|
+
useLogger("boot");
|
|
105
40
|
|
|
106
|
-
//
|
|
107
|
-
|
|
41
|
+
// Register your APIs once
|
|
42
|
+
useInitApis({
|
|
108
43
|
pokeapi: {
|
|
109
44
|
baseUri: "https://pokeapi.co/api/v2",
|
|
110
|
-
endpoints: {
|
|
111
|
-
pokemonById: "/pokemon/:id/",
|
|
112
|
-
pokemons: "/pokemons/",
|
|
113
|
-
},
|
|
45
|
+
endpoints: { pokemonById: "/pokemon/:id/" },
|
|
114
46
|
},
|
|
115
47
|
});
|
|
116
48
|
|
|
117
|
-
//
|
|
118
|
-
const
|
|
119
|
-
params: { id: "pikachu" },
|
|
120
|
-
});
|
|
121
|
-
// => "https://pokeapi.co/api/v2/pokemon/pikachu/"
|
|
122
|
-
|
|
123
|
-
// 3. Fetch with a Safe Result (no throwing on HTTP errors).
|
|
124
|
-
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", {
|
|
125
51
|
params: { id: 25 },
|
|
126
52
|
});
|
|
127
53
|
|
|
128
54
|
if (result.ok) {
|
|
129
|
-
console.log(result.data.name);
|
|
55
|
+
console.log(result.data.name); // "pikachu"
|
|
130
56
|
} else {
|
|
131
|
-
console.error(result.error.message
|
|
57
|
+
console.error(result.error.message);
|
|
132
58
|
}
|
|
133
|
-
|
|
134
|
-
// 4. POST JSON.
|
|
135
|
-
await usePost("pokeapi", "pokemons", { name: "charmander" });
|
|
136
59
|
```
|
|
137
60
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
```ts
|
|
141
|
-
import {
|
|
142
|
-
useLog,
|
|
143
|
-
useSetStorage,
|
|
144
|
-
useGetStorage,
|
|
145
|
-
useRemoveStorage,
|
|
146
|
-
useAddClass,
|
|
147
|
-
useGetRoot,
|
|
148
|
-
} from "katanakit-js";
|
|
149
|
-
|
|
150
|
-
useLog("Hello", { user: "John" }); // info level
|
|
151
|
-
useLog("error", "Something failed", { code: 500 }); // error level
|
|
152
|
-
|
|
153
|
-
useSetStorage("theme", "dark");
|
|
154
|
-
const theme = useGetStorage<string>("theme"); // "dark"
|
|
155
|
-
useRemoveStorage("theme");
|
|
156
|
-
|
|
157
|
-
useAddClass(useGetRoot()!, "dark-mode");
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Storage is SSR-safe: when `window` is unavailable an in-memory fallback is used
|
|
161
|
-
automatically, so imports never crash in Node/Bun.
|
|
162
|
-
|
|
163
|
-
## Astro adapter
|
|
164
|
-
|
|
165
|
-
KatanaKit converts arbitrary collections into the payload Astro's
|
|
166
|
-
`getStaticPaths` expects, wrapped in a Safe Result.
|
|
167
|
-
|
|
168
|
-
```ts
|
|
169
|
-
// src/pages/blog/[slug].astro
|
|
170
|
-
import { AstroService } from "katanakit-js";
|
|
171
|
-
|
|
172
|
-
export async function getStaticPaths() {
|
|
173
|
-
const { useGetStaticPaths } = AstroService.getInstance();
|
|
174
|
-
|
|
175
|
-
return useGetStaticPaths(getCollection, "blog", {
|
|
176
|
-
param: "slug",
|
|
177
|
-
valueFrom: (entry) => entry.slug ?? entry.id,
|
|
178
|
-
propsFrom: (entry) => entry.data,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Also available: `usePathsFrom`, `useFindEntry`, `useGeneratePagination`,
|
|
184
|
-
`usePathsFromValues` and `useExtractUniqueValues`. See the
|
|
185
|
-
[API Reference](docs/API-Reference.md#astro--astroservice).
|
|
61
|
+
## Features
|
|
186
62
|
|
|
187
|
-
|
|
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
|
|
188
68
|
|
|
189
|
-
|
|
190
|
-
(`@astrojs/rss` is not required).
|
|
69
|
+
## Framework usage
|
|
191
70
|
|
|
192
|
-
|
|
193
|
-
// src/pages/rss.xml.ts
|
|
194
|
-
import { RssService } from "katanakit-js";
|
|
195
|
-
import { getCollection } from "astro:content";
|
|
196
|
-
|
|
197
|
-
const { useCreateRssEndpoint } = RssService.getInstance();
|
|
198
|
-
|
|
199
|
-
export const GET = useCreateRssEndpoint({
|
|
200
|
-
title: "My Blog",
|
|
201
|
-
description: "Posts about TypeScript",
|
|
202
|
-
site: "https://example.com",
|
|
203
|
-
items: async () => {
|
|
204
|
-
const posts = await getCollection("blog");
|
|
205
|
-
return posts.map((post) => ({
|
|
206
|
-
title: post.data.title,
|
|
207
|
-
pubDate: post.data.date,
|
|
208
|
-
link: `/blog/${post.slug}/`,
|
|
209
|
-
description: post.data.description,
|
|
210
|
-
}));
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
```
|
|
71
|
+
All common `use*` helpers (`useLogger`, `useInitApis`, `useGetApi`, formatter, dates, utils, theme, …) are on the **main barrel** `katanakit-js`.
|
|
214
72
|
|
|
215
|
-
|
|
73
|
+
### Astro (npm)
|
|
216
74
|
|
|
217
75
|
```astro
|
|
218
76
|
---
|
|
219
|
-
|
|
77
|
+
// Frontmatter = server
|
|
78
|
+
import { useLogger, useGetApi, useInitApis } from "katanakit-js";
|
|
79
|
+
useInitApis({ /* ... */ });
|
|
80
|
+
const result = await useGetApi("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
220
81
|
---
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
`useCreateRssEndpointFromConfig(siteConfig, items)` builds the same endpoint
|
|
227
|
-
from your `SiteConfig`. See the [API Reference](docs/API-Reference.md#rss--rssservice).
|
|
228
|
-
|
|
229
|
-
## Site config and SEO
|
|
230
|
-
|
|
231
|
-
Centralize your site metadata in a typed `SiteConfig` and derive every `<head>`
|
|
232
|
-
tag from it.
|
|
233
|
-
|
|
234
|
-
```ts
|
|
235
|
-
// src/config/site.config.ts
|
|
236
|
-
import { type SiteConfig } from "katanakit-js";
|
|
237
|
-
|
|
238
|
-
export const siteConfig: SiteConfig = {
|
|
239
|
-
site: "https://myblog.com",
|
|
240
|
-
title: "My Blog",
|
|
241
|
-
description: "A blog about TypeScript and Astro",
|
|
242
|
-
lang: "en",
|
|
243
|
-
author: "John Doe",
|
|
244
|
-
ogImage: "/og-default.png",
|
|
245
|
-
twitter: "johndoe",
|
|
246
|
-
rss: { enabled: true, path: "/rss.xml", limit: 20 },
|
|
247
|
-
seo: { noindex: false, canonical: true, openGraph: true, twitterCard: true, jsonLd: true },
|
|
248
|
-
nav: [
|
|
249
|
-
{ label: "Home", href: "/" },
|
|
250
|
-
{ label: "Blog", href: "/blog" },
|
|
251
|
-
{ label: "GitHub", href: "https://github.com/senseikatana/katanakit", external: true },
|
|
252
|
-
],
|
|
253
|
-
};
|
|
82
|
+
<script>
|
|
83
|
+
// Client script — Vite bundles the same package
|
|
84
|
+
import { useLogger } from "katanakit-js";
|
|
85
|
+
useLogger("client");
|
|
86
|
+
</script>
|
|
254
87
|
```
|
|
255
88
|
|
|
256
|
-
|
|
257
|
-
Twitter Card and JSON-LD) in your layout:
|
|
89
|
+
### Astro (CDN client)
|
|
258
90
|
|
|
259
91
|
```astro
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
interface Props {
|
|
266
|
-
title: string;
|
|
267
|
-
description?: string;
|
|
268
|
-
ogType?: "website" | "article";
|
|
269
|
-
publishedTime?: string;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const { title, description, ogType, publishedTime } = Astro.props;
|
|
273
|
-
const headTags = useHeadTags(siteConfig, {
|
|
274
|
-
title,
|
|
275
|
-
description,
|
|
276
|
-
url: new URL(Astro.url.pathname, siteConfig.site).href,
|
|
277
|
-
ogType,
|
|
278
|
-
publishedTime,
|
|
279
|
-
});
|
|
280
|
-
---
|
|
281
|
-
<html lang={siteConfig.lang}>
|
|
282
|
-
<head>
|
|
283
|
-
<meta charset="utf-8" />
|
|
284
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
285
|
-
<Fragment set:html={headTags} />
|
|
286
|
-
</head>
|
|
287
|
-
<body>
|
|
288
|
-
<slot />
|
|
289
|
-
</body>
|
|
290
|
-
</html>
|
|
92
|
+
<script is:inline type="module">
|
|
93
|
+
import { useLogger } from "https://cdn.jsdelivr.net/npm/katanakit-js/+esm";
|
|
94
|
+
useLogger("cdn");
|
|
95
|
+
</script>
|
|
291
96
|
```
|
|
292
97
|
|
|
293
|
-
|
|
98
|
+
### Vue / Nuxt / vanilla
|
|
294
99
|
|
|
295
100
|
```ts
|
|
296
|
-
|
|
297
|
-
import {
|
|
298
|
-
import {
|
|
299
|
-
import { getCollection } from "astro:content";
|
|
300
|
-
|
|
301
|
-
const { useCreateRssEndpointFromConfig } = RssService.getInstance();
|
|
302
|
-
|
|
303
|
-
export const GET = useCreateRssEndpointFromConfig(siteConfig, async () => {
|
|
304
|
-
const posts = await getCollection("blog");
|
|
305
|
-
return posts.map((post) => ({
|
|
306
|
-
title: post.data.title,
|
|
307
|
-
pubDate: post.data.date,
|
|
308
|
-
link: `/blog/${post.slug}/`,
|
|
309
|
-
description: post.data.description,
|
|
310
|
-
}));
|
|
311
|
-
});
|
|
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
|
|
312
104
|
```
|
|
313
105
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
```ts
|
|
321
|
-
import { useInit, useGet } from "katanakit-js";
|
|
322
|
-
import { useUnwrap } from "katanakit-js/adapters/nuxt";
|
|
323
|
-
|
|
324
|
-
// server/plugins/api.ts — register your APIs once
|
|
325
|
-
useInit({
|
|
326
|
-
pokeapi: {
|
|
327
|
-
baseUri: "https://pokeapi.co/api/v2",
|
|
328
|
-
endpoints: { pokemonById: "/pokemon/:id/" },
|
|
329
|
-
},
|
|
330
|
-
});
|
|
106
|
+
```html
|
|
107
|
+
<!-- vanilla -->
|
|
108
|
+
<script type="module">
|
|
109
|
+
import { useLogger } from "https://cdn.jsdelivr.net/npm/katanakit-js/+esm";
|
|
110
|
+
</script>
|
|
331
111
|
```
|
|
332
112
|
|
|
333
|
-
|
|
334
|
-
// server/api/pokemon/[id].ts
|
|
335
|
-
import { useGet } from "katanakit-js";
|
|
336
|
-
import { useUnwrap } from "katanakit-js/adapters/nuxt";
|
|
337
|
-
|
|
338
|
-
export default defineEventHandler(async (event) => {
|
|
339
|
-
const id = getRouterParam(event, "id");
|
|
340
|
-
const result = await useGet("pokeapi", "pokemonById", { params: { id } });
|
|
341
|
-
return useUnwrap(result, `Pokemon ${id}`); // returns data, or throws an H3-compatible error
|
|
342
|
-
});
|
|
343
|
-
```
|
|
113
|
+
See [Getting Started](https://senseikatana.github.io/katanakit-js/docs/guides/getting-started) for full recipes.
|
|
344
114
|
|
|
345
|
-
|
|
346
|
-
JSON response object) and `useEventResponse(event, result)` (set the H3 event
|
|
347
|
-
status code and return data/error). See the
|
|
348
|
-
[API Reference](docs/API-Reference.md#nuxt-adapter--katanakit-jsadaptersnuxt).
|
|
115
|
+
## Framework Adapters
|
|
349
116
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
import { ServerExpress } from "katanakit-js/adapters/express";
|
|
357
|
-
|
|
358
|
-
ServerExpress.getInstance().useStart(); // http://localhost:3000
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
It expects `express` (and `cors`/`dotenv` if used) to be installed in your
|
|
362
|
-
project. A `ProductController` and a demo `router` are also exported.
|
|
363
|
-
|
|
364
|
-
## Services at a glance
|
|
365
|
-
|
|
366
|
-
| Area | Service / module | Highlights |
|
|
367
|
-
| --------- | --------------------------- | ------------------------------------------------------------------- |
|
|
368
|
-
| HTTP | `FetchApiManager` | `useInit`, `useGetApis`, `useBuildUrl`, `useFetch`, `useGet`, `usePost`, `usePut`, `useDelete` |
|
|
369
|
-
| Logging | `LoggerService` | `useLog`, `useError`, `useClear`, `useTable`, pluggable `LogStrategy` |
|
|
370
|
-
| Storage | `StorageService` | `useGetStorage`, `useSetStorage`, `useRemoveStorage`, `useClearStorage` (SSR-safe) |
|
|
371
|
-
| DOM | `DomService` | `useQuerySelector`, `useAddClass`, `useOn`, `useSetText`, ... |
|
|
372
|
-
| Reactive | `ReactiveService` | `useCreateSignal`, `useCreateEffect`, `useCreateMemo`, `useCreateToggle`, `useCreateStorageSignal`, `useCreateDebouncedSignal`, `useCreateBatch` |
|
|
373
|
-
| Format | `FormatterService` | `useFormatNumber`, `useFormatCurrency`, `useJsonStringify`, `useUpperCase`, `useCapitalize`, ... |
|
|
374
|
-
| Convert | `ConverterService` | `useToCelsius`, `useToFahrenheit`, `useToMiles`, `useToKilos`, ... |
|
|
375
|
-
| Errors | `ErrorFactoryService` | `useBadRequest`, `useUnauthorized`, `useForbidden`, `useNotFound`, `useInternal`, `useCustom` |
|
|
376
|
-
| Generate | `GeneratorService` | `useUuid`, `useSlugify`, `useNumericId`, `useToken`, `useEncrypt` |
|
|
377
|
-
| Dates | `DatesService` | `useFormat`, `useNow`, `useAddDays`, `useIsBefore`, `useLastDayOfMonth`, ... (Temporal) |
|
|
378
|
-
| Geometry | `GeometryUtils` | `area`, `perimeter`, `volume` static helpers (`useCircle`, `useSphere`, ...) |
|
|
379
|
-
| Timing | `TimingService` | `useDelay`, `useSetTimeout`, `useInterval`, `useDebounce`, `useThrottle`, `useRepeat`, `useRace` |
|
|
380
|
-
| Utils | `DataUtils` / `SystemUtils` | `useUnique`, `useGroupBy`, `useDeepClone`, `useSleep`, `useRetry`, `useRound`, ... |
|
|
381
|
-
| Viewport | `ViewportService` | scroll, fullscreen, visibility, `usePrefersReducedMotion` |
|
|
382
|
-
| Sensors | `SensorsUtils` | `useGetGeolocation`, `useGetMediaStream`, `useVibrate`, `useGetBattery`, ... |
|
|
383
|
-
| Observer | `ObserverService` | `useCreate`, `useObserve`, `useObserveAll`, `useDisconnect` |
|
|
384
|
-
| LazyLoad | `LazyLoaderService` | `useInit`, `useStop`, `useStopAll` for `img[data-src]` |
|
|
385
|
-
| Worker | `WorkerService` | `useRun`, `useCreatePool`, `useRunPool`, `useTerminate` |
|
|
386
|
-
| Theme | `ThemeService` | `useInitTheme`, `useSetThemeMode`, `useToggleTheme`, `useResetTheme` |
|
|
387
|
-
| Astro | `AstroService` | `useGetStaticPaths`, `usePathsFrom`, `useGeneratePagination`, ... |
|
|
388
|
-
| RSS | `RssService` | `useGenerateRss`, `useRssLinkTag`, `useCreateRssEndpoint`, `useCreateRssEndpointFromConfig` |
|
|
389
|
-
| SEO | `useHeadTags` and friends | `useGenerateMetaTags`, `useTitle`, `useRssHeadLink` + typed `SiteConfig` |
|
|
390
|
-
| Config | `siteConfig` / `SiteConfig` | single source for site metadata, RSS and SEO defaults |
|
|
391
|
-
| Nuxt | `katanakit-js/adapters/nuxt`| `useUnwrap`, `useSafeResponse`, `useEventResponse` (pure functions) |
|
|
392
|
-
| Server | `katanakit-js/adapters/express` | `ServerExpress`, `router`, `ProductController` (optional reference) |
|
|
393
|
-
|
|
394
|
-
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.
|
|
397
|
-
|
|
398
|
-
## Project structure (hexagonal)
|
|
399
|
-
|
|
400
|
-
```
|
|
401
|
-
katanakit/
|
|
402
|
-
├── package.json # name: katanakit-js, ESM, exports map
|
|
403
|
-
├── prisma.config.ts # Prisma ORM config (contract + connection)
|
|
404
|
-
├── src/
|
|
405
|
-
│ ├── index.ts # main barrel (public API)
|
|
406
|
-
│ ├── types/ # single source of truth: contracts & types
|
|
407
|
-
│ ├── core/
|
|
408
|
-
│ │ └── services/ # pure services (no I/O): logger, http, ...
|
|
409
|
-
│ ├── infrastructure/ # browser/runtime adapters
|
|
410
|
-
│ │ ├── dom/ storage/ viewport/ sensors/
|
|
411
|
-
│ │ └── observer/ worker/ theme/
|
|
412
|
-
│ ├── adapters/ # framework adapters
|
|
413
|
-
│ │ ├── astro/ # AstroService + RssService
|
|
414
|
-
│ │ ├── express/ # ServerExpress reference (subpath export)
|
|
415
|
-
│ │ └── nuxt/ # Nuxt helpers (subpath export)
|
|
416
|
-
│ ├── config/ # siteConfig (SiteConfig) + SEO helpers
|
|
417
|
-
│ └── prisma/ # Prisma schema, contract types and db client
|
|
418
|
-
├── tests/ # Vitest suite (57 tests across 7 files)
|
|
419
|
-
├── examples/ # runnable demos
|
|
420
|
-
├── docs/ # Getting Started, Architecture, API Reference, Roadmap
|
|
421
|
-
├── CONTRIBUTING.md
|
|
422
|
-
└── SECURITY.md
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
All internal source imports are relative and carry an explicit `.js` extension
|
|
426
|
-
(pure ESM, `module: nodenext`). The `@/` alias (mapped to `src/`) is configured
|
|
427
|
-
for the test suite and the examples.
|
|
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` |
|
|
428
123
|
|
|
429
124
|
## Documentation
|
|
430
125
|
|
|
431
|
-
- [Getting Started](docs/
|
|
432
|
-
- [Architecture](docs/
|
|
433
|
-
- [API Reference](docs/
|
|
434
|
-
- [Roadmap](docs/
|
|
435
|
-
- [
|
|
436
|
-
- [Changelog](CHANGELOG.md)
|
|
437
|
-
|
|
438
|
-
## Contributing
|
|
439
|
-
|
|
440
|
-
Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
441
|
-
the development contract (hexagonal layering, `use*` convention, `.js` ESM
|
|
442
|
-
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)
|
|
443
131
|
|
|
444
132
|
## License
|
|
445
133
|
|
|
446
|
-
|
|
134
|
+
MIT
|
|
@@ -1,18 +1,106 @@
|
|
|
1
|
-
import type { AstroPath, AstroServiceResult, CollectionEntryLike,
|
|
1
|
+
import type { AstroPath, AstroServiceResult, CollectionEntryLike, PaginationProps, PathsOptions } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Convert a collection into Astro-compatible static paths.
|
|
4
|
+
*
|
|
5
|
+
* @param items - Collection items to convert
|
|
6
|
+
* @param options - Configuration for param name, value extraction and props
|
|
7
|
+
* @returns Array of Astro paths with params and props
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // In Astro's getStaticPaths()
|
|
12
|
+
* const posts = await getCollection("blog");
|
|
13
|
+
* const paths = useAstroPathsFrom(posts, {
|
|
14
|
+
* param: "slug",
|
|
15
|
+
* valueFrom: (post) => post.slug,
|
|
16
|
+
* propsFrom: (post) => ({ title: post.data.title }),
|
|
17
|
+
* });
|
|
18
|
+
* // [{ params: { slug: "hello-world" }, props: { title: "Hello World" } }]
|
|
19
|
+
* ```
|
|
5
20
|
*/
|
|
6
|
-
export declare
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
export declare function useAstroPathsFrom<T, TParam extends string = "slug", TProps = T>(items: T[], options?: PathsOptions<T, TParam, TProps>): AstroPath<TParam, TProps>[];
|
|
22
|
+
/**
|
|
23
|
+
* Fetch a collection and transform it into safe Astro paths.
|
|
24
|
+
* Returns a result object instead of throwing on error.
|
|
25
|
+
*
|
|
26
|
+
* @param getCollectionFn - Astro's getCollection function
|
|
27
|
+
* @param collectionName - Name of the collection to fetch
|
|
28
|
+
* @param options - Path generation options
|
|
29
|
+
* @returns Safe result with data or error
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* export async function getStaticPaths() {
|
|
34
|
+
* const result = await useAstroGetStaticPaths(getCollection, "blog");
|
|
35
|
+
* if (result.ok) return result.data;
|
|
36
|
+
* TODO: traer el useLogger('error', result.error)
|
|
37
|
+
* console.error(result.error);
|
|
38
|
+
* return [];
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function useAstroGetStaticPaths<TData = unknown, TParam extends string = "slug", TProps = CollectionEntryLike<TData>>(getCollectionFn: (collection: string) => Promise<CollectionEntryLike<TData>[]>, collectionName: string, options?: PathsOptions<CollectionEntryLike<TData>, TParam, TProps>): Promise<AstroServiceResult<AstroPath<TParam, TProps>[]>>;
|
|
43
|
+
/**
|
|
44
|
+
* Find a collection entry by slug or custom key.
|
|
45
|
+
*
|
|
46
|
+
* @param items - Collection items to search
|
|
47
|
+
* @param value - Value to match (slug, id, etc.)
|
|
48
|
+
* @param keyFrom - Optional function to extract the key from an item
|
|
49
|
+
* @returns Matched item or null
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const posts = await getCollection("blog");
|
|
54
|
+
* const post = useAstroFindEntry(posts, "hello-world");
|
|
55
|
+
* if (post) console.log(post.data.title);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function useAstroFindEntry<T>(items: T[], value: string, keyFrom?: (item: T) => string | number): T | null;
|
|
59
|
+
/**
|
|
60
|
+
* Generate paginated Astro paths from a list of items.
|
|
61
|
+
*
|
|
62
|
+
* @param items - Items to paginate
|
|
63
|
+
* @param pageSize - Number of items per page
|
|
64
|
+
* @param param - URL param name for page number
|
|
65
|
+
* @returns Array of Astro paths with pagination props
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* const posts = await getCollection("blog");
|
|
70
|
+
* const pages = useAstroGeneratePagination(posts, 10);
|
|
71
|
+
* // [{ params: { page: undefined }, props: { items: [...], currentPage: 1, totalPages: 3 } },
|
|
72
|
+
* // { params: { page: "2" }, props: { items: [...], currentPage: 2, totalPages: 3 } }, ...]
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function useAstroGeneratePagination<T, TParam extends string = "page">(items: T[], pageSize?: number, param?: TParam): AstroPath<TParam, PaginationProps<T>>[];
|
|
76
|
+
/**
|
|
77
|
+
* Convert simple values into Astro paths.
|
|
78
|
+
*
|
|
79
|
+
* @param values - Array of string or number values
|
|
80
|
+
* @param param - URL param name
|
|
81
|
+
* @returns Array of Astro paths
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const categories = ["tech", "design", "business"];
|
|
86
|
+
* const paths = useAstroPathsFromValues(categories, "category");
|
|
87
|
+
* // [{ params: { category: "tech" }, props: "tech" }, ...]
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function useAstroPathsFromValues<TParam extends string = "slug">(values: (string | number)[], param?: TParam): AstroPath<TParam, string | number>[];
|
|
91
|
+
/**
|
|
92
|
+
* Extract unique values from a collection, supporting single values or arrays.
|
|
93
|
+
*
|
|
94
|
+
* @param items - Collection items
|
|
95
|
+
* @param keyFrom - Function to extract value(s) from each item
|
|
96
|
+
* @returns Array of unique values
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* const posts = [{ tags: ["ts", "react"] }, { tags: ["ts", "vue"] }];
|
|
101
|
+
* const tags = useAstroExtractUniqueValues(posts, (p) => p.tags);
|
|
102
|
+
* // ["ts", "react", "vue"]
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export declare function useAstroExtractUniqueValues<T, V>(items: T[], keyFrom: (item: T) => V | V[]): V[];
|
|
18
106
|
//# sourceMappingURL=astro.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"astro.service.d.ts","sourceRoot":"","sources":["../../../src/adapters/astro/astro.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,SAAS,EACT,kBAAkB,EAClB,mBAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"astro.service.d.ts","sourceRoot":"","sources":["../../../src/adapters/astro/astro.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,SAAS,EACT,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,CAAC,EAC9E,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,GAAE,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAM,GAC3C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAkB7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,sBAAsB,CAC3C,KAAK,GAAG,OAAO,EACf,MAAM,SAAS,MAAM,GAAG,MAAM,EAC9B,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,EAEnC,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,EAC9E,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,YAAY,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAM,GACpE,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAe1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAClC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,GACpC,CAAC,GAAG,IAAI,CAQV;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,GAAG,MAAM,EAC3E,KAAK,EAAE,CAAC,EAAE,EACV,QAAQ,SAAK,EACb,KAAK,GAAE,MAAyB,GAC9B,SAAS,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAYzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM,EACrE,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAC3B,KAAK,GAAE,MAAyB,GAC9B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,CAKtC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAEhG"}
|