create-sonamu 0.1.13 → 0.1.15

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/catalog.json CHANGED
@@ -12,8 +12,8 @@
12
12
  "@aws-sdk/ecr-public": "^3.958.0",
13
13
  "@aws-sdk/lib-storage": "^3.971.0",
14
14
  "@aws-sdk/s3-request-presigner": "^3.958.0",
15
- "@better-auth/passkey": "^1.4.18",
16
- "@better-auth/sso": "^1.4.18",
15
+ "@better-auth/passkey": "~1.4.18",
16
+ "@better-auth/sso": "~1.4.18",
17
17
  "@biomejs/biome": "^2.3.13",
18
18
  "@biomejs/js-api": "^4.0.0",
19
19
  "@biomejs/wasm-nodejs": "^2.3.7",
@@ -79,6 +79,7 @@
79
79
  "@swc/cli": "^0.7.8",
80
80
  "@swc/core": "^1.13.5",
81
81
  "@tailwindcss/postcss": "^4.0.0",
82
+ "@tailwindcss/typography": "^0.5.19",
82
83
  "@tailwindcss/vite": "^4.1.17",
83
84
  "@tanstack/react-query": "^5.90.12",
84
85
  "@tanstack/react-query-devtools": "^5.91.1",
@@ -91,6 +92,7 @@
91
92
  "@types/lodash-es": "^4.17.12",
92
93
  "@types/luxon": "^3.0.3",
93
94
  "@types/mime-types": "^3.0.1",
95
+ "@types/minimist": "^1.2.5",
94
96
  "@types/node": "25.0.7",
95
97
  "@types/pg": "^8.15.6",
96
98
  "@types/picomatch": "^4.0.0",
@@ -111,7 +113,7 @@
111
113
  "axios": "^1.13.2",
112
114
  "bcrypt": "^6.0.0",
113
115
  "bentocache": "^1.5.0",
114
- "better-auth": "^1.4.18",
116
+ "better-auth": "~1.4.18",
115
117
  "c12": "^3.3.2",
116
118
  "c8": "^10.1.3",
117
119
  "chalk": "^4.1.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sonamu",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Create a new Sonamu project",
5
5
  "keywords": [
6
6
  "sonamu",
@@ -0,0 +1,55 @@
1
+ {
2
+ "languages": {
3
+ "JavaScript": {
4
+ "format_on_save": "on",
5
+ "code_actions_on_format": {
6
+ "source.organizeImports.biome": true,
7
+ "source.fixAll.biome": true,
8
+ },
9
+ "prettier": { "allowed": false },
10
+ "formatter": {
11
+ "language_server": {
12
+ "name": "biome",
13
+ },
14
+ },
15
+ "language_servers": ["!typescript-language-server", "vtsls", "biome"],
16
+ },
17
+ "TypeScript": {
18
+ "format_on_save": "on",
19
+ "code_actions_on_format": {
20
+ "source.organizeImports.biome": true,
21
+ "source.fixAll.biome": true,
22
+ },
23
+ "prettier": { "allowed": false },
24
+ "formatter": {
25
+ "language_server": {
26
+ "name": "biome",
27
+ },
28
+ },
29
+ "language_servers": ["!typescript-language-server", "vtsls", "biome"],
30
+ },
31
+ "TSX": {
32
+ "format_on_save": "on",
33
+ "code_actions_on_format": {
34
+ "source.organizeImports.biome": true,
35
+ "source.fixAll.biome": true,
36
+ },
37
+ "prettier": { "allowed": false },
38
+ "formatter": {
39
+ "language_server": {
40
+ "name": "biome",
41
+ },
42
+ },
43
+ "language_servers": ["!typescript-language-server", "vtsls", "biome", "tailwindcss-language-server"],
44
+ },
45
+ "JSON": {
46
+ "format_on_save": "on",
47
+ "formatter": {
48
+ "language_server": {
49
+ "name": "biome",
50
+ },
51
+ },
52
+ "language_servers": ["biome"],
53
+ },
54
+ },
55
+ }
@@ -61,5 +61,5 @@ Thumbs.db
61
61
  .slack-confirm-*
62
62
 
63
63
  # Claude
64
- .claude/skills/sonamu/
64
+ .claude/skills/sonamu
65
65
  .claude/CLAUDE.md
@@ -6,7 +6,7 @@
6
6
  "format": "biome format --write",
7
7
  "check": "biome check"
8
8
  },
9
- "packageManager": "pnpm@10.25.0",
9
+ "packageManager": "pnpm@10.32.0",
10
10
  "devDependencies": {
11
11
  "@biomejs/biome": "^2.3.13",
12
12
  "@types/node": "^25",
@@ -32,14 +32,14 @@
32
32
  "@swc/core": "^1.13.5",
33
33
  "ai": "^6.0.1",
34
34
  "bcrypt": "^6.0.0",
35
- "better-auth": "^1.4.18",
35
+ "better-auth": "~1.4.18",
36
36
  "chalk": "^4.1.2",
37
37
  "date-fns": "^4.1.0",
38
38
  "dotenv": "^16",
39
39
  "knex": "^3.1.0",
40
40
  "pg": "^8.16.3",
41
41
  "radashi": "^12.2.0",
42
- "sonamu": "^0.8.10",
42
+ "sonamu": "^0.8.12",
43
43
  "zod": "^4.3.6"
44
44
  },
45
45
  "devDependencies": {
@@ -10,11 +10,11 @@
10
10
  "preview": "vite preview"
11
11
  },
12
12
  "dependencies": {
13
- "@sonamu-kit/react-components": "^0.2.2",
13
+ "@sonamu-kit/react-components": "^0.2.3",
14
14
  "@tanstack/react-query": "^5.90.12",
15
15
  "@tanstack/react-router": "1.143.11",
16
16
  "axios": "^1.13.2",
17
- "better-auth": "^1.4.18",
17
+ "better-auth": "~1.4.18",
18
18
  "clsx": "^2.1.1",
19
19
  "dotenv": "^16",
20
20
  "eventsource": "^4.1.0",
@@ -17,8 +17,8 @@ function App({ children }: AppProps) {
17
17
  useEffect(() => {
18
18
  // 브라우저 locale 감지
19
19
  const browserLocale = navigator.language.split("-")[0];
20
- if (SUPPORTED_LOCALES.includes(browserLocale as typeof SUPPORTED_LOCALES[number])) {
21
- setLocale(browserLocale as typeof SUPPORTED_LOCALES[number]);
20
+ if (SUPPORTED_LOCALES.includes(browserLocale as (typeof SUPPORTED_LOCALES)[number])) {
21
+ setLocale(browserLocale as (typeof SUPPORTED_LOCALES)[number]);
22
22
  }
23
23
  }, []);
24
24
 
@@ -47,7 +47,9 @@ const userMenuItems: MenuItemProps[] = [
47
47
  export default function Sidebar({ className }: SidebarProps) {
48
48
  const pathname = useRouterState({ select: (s) => s.location.pathname });
49
49
  const { auth } = useSonamuContext();
50
- const { user, logout } = auth;
50
+ const session = auth?.useSession?.();
51
+ const user = session?.data?.user ?? null;
52
+ const logout = () => auth?.signOut?.();
51
53
 
52
54
  // 경로에 따라 메뉴 및 타이틀 분기
53
55
  const isAdmin = pathname.startsWith("/admin");
@@ -70,7 +72,7 @@ export default function Sidebar({ className }: SidebarProps) {
70
72
  </div>
71
73
  {user && (
72
74
  <div className="text-sm text-sidebar-foreground/70 mt-1">
73
- {user.username ?? user.email ?? "User"}
75
+ {user.name ?? user.email ?? "User"}
74
76
  </div>
75
77
  )}
76
78
  </SidebarHeader>
@@ -1,59 +1,37 @@
1
1
  import {
2
2
  type SonamuFile,
3
- SonamuProvider,
3
+ SonamuProvider as BaseSonamuProvider,
4
4
  useSonamuBaseContext,
5
5
  } from "@sonamu-kit/react-components";
6
6
  import type { ReactNode } from "react";
7
7
  import type { DictKey, MergedDictionary } from "@/i18n/sd.generated";
8
8
  import { SD } from "@/i18n/sd.generated";
9
9
 
10
- // TODO: User 엔티티 추가 후 아래 타입들을 지정하세요
11
- // - UserSubsetSS: 세션에 저장되는 User 타입 (예: import type { UserSubsetSS } from "@/services/sonamu.generated")
12
- // - UserLoginParams: 로그인 파라미터 타입 (예: import type { UserLoginParams } from "@/services/user/user.types")
10
+ // TODO: User 엔티티 추가 후 authOptions를 설정하세요
11
+ // import type { BetterAuthClientOptions } from "better-auth/client";
12
+ // import { inferAdditionalFields } from "better-auth/client/plugins";
13
+ // const authOptions = { plugins: [...] } satisfies BetterAuthClientOptions;
14
+
13
15
  export function useSonamuContext() {
14
- return useSonamuBaseContext<MergedDictionary, any, any>();
16
+ return useSonamuBaseContext<MergedDictionary>();
15
17
  }
16
18
 
17
- export function useSonamuConfig() {
18
- // Auth 설정
19
- // TODO: User 엔티티 추가 auth 로직을 구현하세요
20
- const auth = {
21
- user: null,
22
- loading: false,
23
- login: async (_loginParams: any) => {
24
- // TODO: Implement login logic
25
- console.log("Login not implemented yet");
26
- },
27
- logout: async () => {
28
- // TODO: Implement logout logic
29
- console.log("Logout not implemented yet");
30
- },
31
- refetch: async () => {
32
- // 세션 정보 다시 불러오기
33
- },
34
- };
35
-
36
- // Uploader 설정
37
- // TODO: File 엔티티 추가 후 FileService.useUploadMutation()을 사용하세요
38
- const uploader = async (files: File[]): Promise<SonamuFile[]> => {
39
- if (files.length === 0) {
40
- return [];
41
- }
42
- console.log("File upload not implemented yet");
19
+ // Uploader 설정
20
+ // TODO: File 엔티티 추가 후 FileService.useUploadMutation()을 사용하세요
21
+ const uploader = async (files: File[]): Promise<SonamuFile[]> => {
22
+ if (files.length === 0) {
43
23
  return [];
44
- };
24
+ }
25
+ console.log("File upload not implemented yet");
26
+ return [];
27
+ };
45
28
 
46
- // SD 설정
47
- const sd = <K extends DictKey>(key: K): ReturnType<typeof SD<K>> => SD(key);
48
-
49
- return { auth, uploader, SD: sd };
50
- }
29
+ const sd = <K extends DictKey>(key: K): ReturnType<typeof SD<K>> => SD(key);
51
30
 
52
- export function SonamuProviderWrapper({ children }: { children: ReactNode }) {
53
- const config = useSonamuConfig();
31
+ export function SonamuProvider({ children }: { children: ReactNode }) {
54
32
  return (
55
- <SonamuProvider<MergedDictionary, any, any> {...config}>
33
+ <BaseSonamuProvider<MergedDictionary> uploader={uploader} SD={sd}>
56
34
  {children}
57
- </SonamuProvider>
35
+ </BaseSonamuProvider>
58
36
  );
59
37
  }
@@ -19,8 +19,7 @@ export default {
19
19
  "common.login": "Login",
20
20
  "common.logout": "Logout",
21
21
  "common.manage": "Manage",
22
- "common.results": (count: number) =>
23
- plural(count, `${count} result`, `${count} results`),
22
+ "common.results": (count: number) => plural(count, `${count} result`, `${count} results`),
24
23
  "common.save": "Save",
25
24
  "common.search": "Search",
26
25
  "common.searchPlaceholder": "Search...",
@@ -1,7 +1,7 @@
1
1
  import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
2
2
  import { createRootRouteWithContext, HeadContent, Outlet, Scripts } from "@tanstack/react-router";
3
3
  import App from "@/App";
4
- import { SonamuProviderWrapper } from "@/contexts/sonamu-provider";
4
+ import { SonamuProvider } from "@/contexts/sonamu-provider";
5
5
 
6
6
  export interface RouterContext {
7
7
  queryClient: QueryClient;
@@ -30,11 +30,11 @@ function RootComponent() {
30
30
  <body>
31
31
  <div id="root">
32
32
  <QueryClientProvider client={queryClient}>
33
- <SonamuProviderWrapper>
33
+ <SonamuProvider>
34
34
  <App>
35
35
  <Outlet />
36
36
  </App>
37
- </SonamuProviderWrapper>
37
+ </SonamuProvider>
38
38
  </QueryClientProvider>
39
39
  </div>
40
40
  <Scripts />
@@ -9,7 +9,7 @@ function AdminDashboard() {
9
9
  <div>
10
10
  <h1 className="text-2xl font-bold mb-4">Admin Dashboard</h1>
11
11
  <p className="text-gray-600">Welcome to the admin panel. Start building your application.</p>
12
-
12
+
13
13
  {/* TODO: 대시보드 위젯 추가 */}
14
14
  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-8">
15
15
  <div className="p-6 bg-gray-50 rounded-lg border">
@@ -9,7 +9,7 @@ function HomePage() {
9
9
  <div>
10
10
  <h1 className="text-2xl font-bold mb-4">Welcome to Sonamu</h1>
11
11
  <p className="text-gray-600">Start building your application.</p>
12
-
12
+
13
13
  {/* TODO: 사용자용 콘텐츠 추가 */}
14
14
  <div className="mt-8">
15
15
  <p className="text-sm text-gray-500">
@@ -221,14 +221,13 @@ export type ApplySonamuFilter<
221
221
  TNumericKeys extends Exclude<keyof TEntity, TOmitKeys> = never,
222
222
  > = FilterQuery<Omit<TEntity, TOmitKeys>, TNumericKeys>;
223
223
 
224
-
225
224
  /**
226
225
  * 필드명과 값을 기반으로 FilterPropType을 추론
227
226
  */
228
227
  export function getFieldPropType(
229
228
  fieldName: string,
230
229
  value: any,
231
- numericColumns: readonly string[]
230
+ numericColumns: readonly string[],
232
231
  ): FilterPropType {
233
232
  // numeric 타입 체크 (명시적으로 지정된 컬럼)
234
233
  if (numericColumns.includes(fieldName)) {