@m1kapp/kit 0.0.26 → 0.0.28
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 +36 -0
- package/bin/stats.mjs +4 -5
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +4 -4
- package/dist/index.mjs +4 -4
- package/dist/meta.json +337 -133
- package/dist/pwa.js +1 -1
- package/dist/pwa.mjs +1 -1
- package/dist/server.d.mts +118 -1
- package/dist/server.d.ts +118 -1
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -750,6 +750,42 @@ export const GET = handler(async () => {
|
|
|
750
750
|
});
|
|
751
751
|
```
|
|
752
752
|
|
|
753
|
+
### 서버 유틸 (의존성 0)
|
|
754
|
+
|
|
755
|
+
API 라우트에서 자주 손으로 만들던 것들 — 전부 `@m1kapp/kit/server`에 있어요.
|
|
756
|
+
|
|
757
|
+
```ts
|
|
758
|
+
import {
|
|
759
|
+
requireEnv, fetchWithRetry, withRetry, recoverJsonFromText,
|
|
760
|
+
scrapeOg, todayKST, dateInTz, idToSlug, slugToId, appHost,
|
|
761
|
+
} from "@m1kapp/kit/server";
|
|
762
|
+
|
|
763
|
+
// 필수 env 검증 (없으면 500 throw, 있으면 타입된 객체)
|
|
764
|
+
const { XAI_API_KEY } = requireEnv(["XAI_API_KEY"]);
|
|
765
|
+
|
|
766
|
+
// fetch + 타임아웃 + 429/5xx 자동 재시도 (마지막 응답 반환)
|
|
767
|
+
const res = await fetchWithRetry(url, { headers: { authorization: `Bearer ${XAI_API_KEY}` } });
|
|
768
|
+
|
|
769
|
+
// 아무 async나 재시도 (Neon 콜드스타트 등)
|
|
770
|
+
const rows = await withRetry(() => db.query.users.findMany(), {
|
|
771
|
+
shouldRetry: (e) => String(e).includes("fetch failed"),
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
// LLM 응답에서 JSON 복구 (```json 펜스·트레일링 콤마·노이즈 제거)
|
|
775
|
+
const data = recoverJsonFromText<{ items: string[] }>(llmReply);
|
|
776
|
+
|
|
777
|
+
// Open Graph 스크래핑
|
|
778
|
+
const og = await scrapeOg("example.com"); // { title, description, image, siteName, url }
|
|
779
|
+
|
|
780
|
+
// 타임존 날짜
|
|
781
|
+
todayKST(); // "2026-06-04"
|
|
782
|
+
dateInTz(Date.now(), "America/New_York");
|
|
783
|
+
|
|
784
|
+
// base62 slug + 호스트
|
|
785
|
+
idToSlug(42, 1000); // "..." (slugToId로 역변환)
|
|
786
|
+
const base = `https://${appHost("m1k.app")}`;
|
|
787
|
+
```
|
|
788
|
+
|
|
753
789
|
---
|
|
754
790
|
|
|
755
791
|
## Utils
|
package/bin/stats.mjs
CHANGED
|
@@ -155,11 +155,10 @@ for (const name of allImports) {
|
|
|
155
155
|
// 카테고리별 사용 수 (loc 0이어도 카운트 — "Tab"도 사용한 거니까)
|
|
156
156
|
usedByCategory[meta.category] = (usedByCategory[meta.category] || 0) + 1;
|
|
157
157
|
|
|
158
|
-
// LOC 절약은 소스 파일 단위로 1
|
|
159
|
-
|
|
160
|
-
if (meta.source
|
|
161
|
-
|
|
162
|
-
if (meta.loc > 0) {
|
|
158
|
+
// LOC 절약은 소스 파일 단위로 1번만. 대표(loc>0)만 카운트하므로 import
|
|
159
|
+
// 순서와 무관 — 비대표(loc 0)가 먼저 와도 source를 선점하지 않는다.
|
|
160
|
+
if (meta.loc > 0 && !(meta.source && countedSources.has(meta.source))) {
|
|
161
|
+
if (meta.source) countedSources.add(meta.source);
|
|
163
162
|
usedFeatures.push({ name, loc: meta.loc, category: meta.category });
|
|
164
163
|
savedLines += meta.loc;
|
|
165
164
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -49,15 +49,24 @@ interface AppShellProps {
|
|
|
49
49
|
* Accent color (any CSS color) propagated to kit components as `--kit-accent`.
|
|
50
50
|
* Lets you re-skin the whole shell — Switch, SegmentedControl, ChatBubble,
|
|
51
51
|
* ActionCard, ListRow… — in one place. e.g. accent="#e2603f"
|
|
52
|
+
*
|
|
53
|
+
* When `accent` is a hex color, a contrasting foreground (`--kit-accent-fg`,
|
|
54
|
+
* black/white) is derived automatically so labels on the accent stay legible.
|
|
52
55
|
*/
|
|
53
56
|
accent?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Foreground color used *on top of* the accent (`--kit-accent-fg`). Defaults
|
|
59
|
+
* to an auto-derived black/white for hex accents, else white. Set this when
|
|
60
|
+
* `accent` is a non-hex CSS color (named/rgb/hsl) and the default contrasts poorly.
|
|
61
|
+
*/
|
|
62
|
+
accentFg?: string;
|
|
54
63
|
style?: CSSProperties;
|
|
55
64
|
}
|
|
56
65
|
/**
|
|
57
66
|
* Mobile app-like container with rounded corners, shadow, and ring.
|
|
58
67
|
* Centers content and constrains width for a phone-like viewport.
|
|
59
68
|
*/
|
|
60
|
-
declare function AppShell({ children, className, maxWidth, maxHeight, accent, style, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
69
|
+
declare function AppShell({ children, className, maxWidth, maxHeight, accent, accentFg, style, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
61
70
|
interface AppShellHeaderProps {
|
|
62
71
|
children: ReactNode;
|
|
63
72
|
className?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -49,15 +49,24 @@ interface AppShellProps {
|
|
|
49
49
|
* Accent color (any CSS color) propagated to kit components as `--kit-accent`.
|
|
50
50
|
* Lets you re-skin the whole shell — Switch, SegmentedControl, ChatBubble,
|
|
51
51
|
* ActionCard, ListRow… — in one place. e.g. accent="#e2603f"
|
|
52
|
+
*
|
|
53
|
+
* When `accent` is a hex color, a contrasting foreground (`--kit-accent-fg`,
|
|
54
|
+
* black/white) is derived automatically so labels on the accent stay legible.
|
|
52
55
|
*/
|
|
53
56
|
accent?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Foreground color used *on top of* the accent (`--kit-accent-fg`). Defaults
|
|
59
|
+
* to an auto-derived black/white for hex accents, else white. Set this when
|
|
60
|
+
* `accent` is a non-hex CSS color (named/rgb/hsl) and the default contrasts poorly.
|
|
61
|
+
*/
|
|
62
|
+
accentFg?: string;
|
|
54
63
|
style?: CSSProperties;
|
|
55
64
|
}
|
|
56
65
|
/**
|
|
57
66
|
* Mobile app-like container with rounded corners, shadow, and ring.
|
|
58
67
|
* Centers content and constrains width for a phone-like viewport.
|
|
59
68
|
*/
|
|
60
|
-
declare function AppShell({ children, className, maxWidth, maxHeight, accent, style, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
69
|
+
declare function AppShell({ children, className, maxWidth, maxHeight, accent, accentFg, style, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
61
70
|
interface AppShellHeaderProps {
|
|
62
71
|
children: ReactNode;
|
|
63
72
|
className?: string;
|