create-edhor-stack 0.1.0

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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/STACK.md +1086 -0
  4. package/dist/index.js +3181 -0
  5. package/package.json +44 -0
  6. package/templates/apps/api-elysia/package.json +21 -0
  7. package/templates/apps/api-elysia/src/index.ts +59 -0
  8. package/templates/apps/api-elysia/src/lib/eden.ts +25 -0
  9. package/templates/apps/api-elysia/src/lib/env.ts +18 -0
  10. package/templates/apps/api-elysia/src/routes/health.ts +13 -0
  11. package/templates/apps/api-elysia/src/routes/users.ts +117 -0
  12. package/templates/apps/api-elysia/tsconfig.json +15 -0
  13. package/templates/apps/api-hono/package.json +20 -0
  14. package/templates/apps/api-hono/src/index.ts +66 -0
  15. package/templates/apps/api-hono/src/lib/env.ts +18 -0
  16. package/templates/apps/api-hono/src/routes/health.ts +20 -0
  17. package/templates/apps/api-hono/src/routes/users.ts +110 -0
  18. package/templates/apps/api-hono/tsconfig.json +15 -0
  19. package/templates/apps/mobile/.env.example +9 -0
  20. package/templates/apps/mobile/app/_layout.tsx +16 -0
  21. package/templates/apps/mobile/app/index.tsx +39 -0
  22. package/templates/apps/mobile/app.json +37 -0
  23. package/templates/apps/mobile/assets/adaptive-icon.png +0 -0
  24. package/templates/apps/mobile/assets/favicon.png +0 -0
  25. package/templates/apps/mobile/assets/icon.png +0 -0
  26. package/templates/apps/mobile/assets/splash-icon.png +0 -0
  27. package/templates/apps/mobile/package.json +39 -0
  28. package/templates/apps/mobile/src/api/client.ts +51 -0
  29. package/templates/apps/mobile/src/api/index.ts +3 -0
  30. package/templates/apps/mobile/src/api/queries.ts +24 -0
  31. package/templates/apps/mobile/src/api/schemas.ts +32 -0
  32. package/templates/apps/mobile/src/lib/env.ts +40 -0
  33. package/templates/apps/mobile/src/lib/query-client.ts +28 -0
  34. package/templates/apps/mobile/src/lib/result.ts +45 -0
  35. package/templates/apps/mobile/src/lib/store.ts +63 -0
  36. package/templates/apps/mobile/tsconfig.json +10 -0
  37. package/templates/apps/web/.env.example +11 -0
  38. package/templates/apps/web/package.json +29 -0
  39. package/templates/apps/web/src/lib/env.ts +52 -0
  40. package/templates/apps/web/src/lib/queries.ts +27 -0
  41. package/templates/apps/web/src/lib/query-client.ts +11 -0
  42. package/templates/apps/web/src/router.tsx +17 -0
  43. package/templates/apps/web/src/routes/__root.tsx +32 -0
  44. package/templates/apps/web/src/routes/index.tsx +16 -0
  45. package/templates/apps/web/src/styles.css +26 -0
  46. package/templates/apps/web/tsconfig.json +10 -0
  47. package/templates/apps/web/vite.config.ts +21 -0
  48. package/templates/base/.claude/settings.json +33 -0
  49. package/templates/base/.claude/skills/add-api-endpoint.md +137 -0
  50. package/templates/base/.claude/skills/add-component.md +79 -0
  51. package/templates/base/.claude/skills/add-route.md +134 -0
  52. package/templates/base/.claude/skills/add-store.md +158 -0
  53. package/templates/base/.husky/pre-commit +1 -0
  54. package/templates/base/.lintstagedrc +4 -0
  55. package/templates/base/.node-version +1 -0
  56. package/templates/base/AGENTS.md +135 -0
  57. package/templates/base/CLAUDE.md.hbs +139 -0
  58. package/templates/base/Dockerfile +32 -0
  59. package/templates/base/biome.json +52 -0
  60. package/templates/base/fly.toml.hbs +20 -0
  61. package/templates/base/gitignore +36 -0
  62. package/templates/base/package.json.hbs +22 -0
  63. package/templates/base/tsconfig.json +14 -0
  64. package/templates/base/turbo.json +22 -0
  65. package/templates/packages/shared/package.json +17 -0
  66. package/templates/packages/shared/src/index.ts +4 -0
  67. package/templates/packages/shared/src/schemas.ts +50 -0
  68. package/templates/packages/shared/src/types.ts +47 -0
  69. package/templates/packages/shared/src/utils.ts +87 -0
  70. package/templates/packages/shared/tsconfig.json +14 -0
  71. package/templates/packages/stripe/package.json +18 -0
  72. package/templates/packages/stripe/src/client.ts +110 -0
  73. package/templates/packages/stripe/src/index.ts +3 -0
  74. package/templates/packages/stripe/src/schemas.ts +65 -0
  75. package/templates/packages/stripe/src/webhooks.ts +91 -0
  76. package/templates/packages/stripe/tsconfig.json +14 -0
  77. package/templates/packages/ui/components.json +19 -0
  78. package/templates/packages/ui/package.json +29 -0
  79. package/templates/packages/ui/src/components/button.tsx +58 -0
  80. package/templates/packages/ui/src/index.ts +5 -0
  81. package/templates/packages/ui/src/lib/utils.ts +6 -0
  82. package/templates/packages/ui/src/styles.css +120 -0
  83. package/templates/packages/ui/tsconfig.json +10 -0
@@ -0,0 +1,139 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ {{name}} is a Bun + Turborepo monorepo scaffolded with [create-edhor-stack](https://github.com/your-username/create-edhor-stack).
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Root (monorepo)
13
+ bun dev # Start all apps in development
14
+ bun build # Build all apps and packages
15
+ bun lint # Lint with Biome
16
+ bun check # Lint + format with auto-fix
17
+ bun clean # Clean all build artifacts
18
+
19
+ # Filter to specific app
20
+ bun dev --filter=web # Start web app only
21
+ bun dev --filter=mobile # Start mobile app only
22
+ ```
23
+
24
+ ## Architecture
25
+
26
+ ### Monorepo Structure
27
+
28
+ ```
29
+ {{name}}/
30
+ ├── apps/
31
+ │ ├── web/ # TanStack Start web application
32
+ │ │ ├── src/
33
+ │ │ │ ├── routes/ # File-based routing
34
+ │ │ │ └── lib/ # Utilities, query client
35
+ │ │ └── package.json
36
+ │ └── mobile/ # Expo React Native application
37
+ │ ├── app/ # Expo Router screens
38
+ │ ├── src/
39
+ │ │ ├── api/ # API client, schemas, queries
40
+ │ │ ├── lib/ # Store, utils, query client
41
+ │ │ └── hooks/ # Custom React hooks
42
+ │ └── package.json
43
+ ├── packages/
44
+ │ └── ui/ # Shared UI components (shadcn/ui)
45
+ ├── turbo.json # Turborepo configuration
46
+ ├── biome.json # Linting & formatting rules
47
+ └── package.json # Root workspace configuration
48
+ ```
49
+
50
+ ### Tech Stack
51
+
52
+ | Layer | Technology |
53
+ |-------|------------|
54
+ | Package Manager | Bun |
55
+ | Monorepo | Turborepo |
56
+ | Web Framework | TanStack Start |
57
+ | Mobile Framework | Expo SDK 54 + Expo Router |
58
+ | State (Server) | TanStack Query |
59
+ | State (Client) | Zustand (mobile) |
60
+ | Validation | Zod |
61
+ | Styling | Tailwind CSS v4, shadcn/ui |
62
+ | Icons | Lucide |
63
+ | Linting | Biome |
64
+
65
+ ### Key Patterns
66
+
67
+ **State Management (Mobile)**:
68
+ - Multiple specialized Zustand stores with `persist()` middleware
69
+ - Use selectors to prevent re-renders: `useAppStore(state => state.theme)`
70
+ - Never destructure the whole store
71
+
72
+ **API Layer**:
73
+ - `fetchValidated()` wraps fetch with Zod schema validation
74
+ - Query options factories for React Query consistency
75
+ - Offline-first configuration with 7-day cache
76
+
77
+ **Routing**:
78
+ - Web: TanStack Router file-based routing in `src/routes/`
79
+ - Mobile: Expo Router file-based routing in `app/`
80
+
81
+ ### Import Alias
82
+
83
+ All imports use `@/` prefix mapping to `src/`:
84
+
85
+ ```typescript
86
+ import { useAppStore } from '@/lib/store';
87
+ import { fetchValidated } from '@/api/client';
88
+ ```
89
+
90
+ ## Code Style
91
+
92
+ Enforced by Biome (`biome.json`):
93
+ - 2-space indentation, 100-char line width
94
+ - Single quotes, ES5 trailing commas, semicolons
95
+ - `useImportType` for type-only imports
96
+ - No unused imports (error), no unused variables (warn)
97
+
98
+ Section comments format:
99
+ ```typescript
100
+ // ============================================================================
101
+ // SECTION NAME
102
+ // ============================================================================
103
+ ```
104
+
105
+ ## Development Guidelines
106
+
107
+ ### Adding a New Route (Web)
108
+
109
+ 1. Create file in `apps/web/src/routes/` (e.g., `dashboard.tsx`)
110
+ 2. Export Route with `createFileRoute`
111
+ 3. Use route loaders for data fetching
112
+
113
+ ### Adding a New Screen (Mobile)
114
+
115
+ 1. Create file in `apps/mobile/app/` (e.g., `settings.tsx`)
116
+ 2. Use `useLocalSearchParams` for dynamic routes
117
+ 3. Connect to Zustand stores via selectors
118
+
119
+ ### Adding API Endpoints
120
+
121
+ 1. Define Zod schema in `src/api/schemas.ts`
122
+ 2. Create query options in `src/api/queries.ts`
123
+ 3. Use `fetchValidated()` for type-safe fetching
124
+
125
+ ## AI Agent Instructions
126
+
127
+ See [AGENTS.md](./AGENTS.md) for multi-agent workflow documentation.
128
+
129
+ ### Preferred Approaches
130
+
131
+ - **TDD**: Write failing tests first, then implement
132
+ - **Small commits**: Commit after each logical change
133
+ - **DRY/YAGNI**: Don't over-engineer, build what's needed
134
+
135
+ ### Before Making Changes
136
+
137
+ 1. Read relevant files to understand context
138
+ 2. Check existing patterns in similar files
139
+ 3. Run `bun check` before committing
@@ -0,0 +1,32 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # Build stage
4
+ FROM oven/bun:1 AS builder
5
+ WORKDIR /app
6
+
7
+ # Copy package files
8
+ COPY package.json bun.lock* ./
9
+ COPY apps/web/package.json ./apps/web/
10
+ COPY packages/*/package.json ./packages/
11
+
12
+ # Install dependencies
13
+ RUN bun install --frozen-lockfile
14
+
15
+ # Copy source
16
+ COPY . .
17
+
18
+ # Build the web app
19
+ RUN bun run build --filter=web
20
+
21
+ # Production stage
22
+ FROM oven/bun:1-slim AS runner
23
+ WORKDIR /app
24
+
25
+ ENV NODE_ENV=production
26
+
27
+ # Copy built application
28
+ COPY --from=builder /app/apps/web/.output ./.output
29
+
30
+ # Run the server
31
+ EXPOSE 3000
32
+ CMD ["bun", "run", ".output/server/index.mjs"]
@@ -0,0 +1,52 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": true,
10
+ "includes": ["apps/**/*.ts", "apps/**/*.tsx", "packages/**/*.ts", "packages/**/*.tsx"]
11
+ },
12
+ "formatter": {
13
+ "enabled": true,
14
+ "indentStyle": "space",
15
+ "indentWidth": 2,
16
+ "lineWidth": 100
17
+ },
18
+ "assist": {
19
+ "actions": {
20
+ "source": {
21
+ "organizeImports": "on"
22
+ }
23
+ }
24
+ },
25
+ "linter": {
26
+ "enabled": true,
27
+ "rules": {
28
+ "recommended": true,
29
+ "correctness": {
30
+ "useExhaustiveDependencies": "warn",
31
+ "noUnusedImports": "error",
32
+ "noUnusedVariables": "warn"
33
+ },
34
+ "style": {
35
+ "noNonNullAssertion": "off",
36
+ "useConst": "error",
37
+ "useImportType": "error"
38
+ },
39
+ "suspicious": {
40
+ "noExplicitAny": "warn",
41
+ "noConsole": "off"
42
+ }
43
+ }
44
+ },
45
+ "javascript": {
46
+ "formatter": {
47
+ "quoteStyle": "double",
48
+ "trailingCommas": "es5",
49
+ "semicolons": "always"
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,20 @@
1
+ app = "{{name}}"
2
+ primary_region = "iad"
3
+
4
+ [build]
5
+
6
+ [http_service]
7
+ internal_port = 3000
8
+ force_https = true
9
+ auto_stop_machines = "stop"
10
+ auto_start_machines = true
11
+ min_machines_running = 0
12
+ processes = ["app"]
13
+
14
+ [env]
15
+ NODE_ENV = "production"
16
+
17
+ [[vm]]
18
+ memory = "512mb"
19
+ cpu_kind = "shared"
20
+ cpus = 1
@@ -0,0 +1,36 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build outputs
5
+ dist/
6
+ .output/
7
+ .vinxi/
8
+ .expo/
9
+ build/
10
+
11
+ # Turbo
12
+ .turbo/
13
+
14
+ # Environment
15
+ .env
16
+ .env.local
17
+ .env.*.local
18
+
19
+ # IDE
20
+ .idea/
21
+ .vscode/
22
+ *.swp
23
+ *.swo
24
+
25
+ # OS
26
+ .DS_Store
27
+ Thumbs.db
28
+
29
+ # Logs
30
+ *.log
31
+ npm-debug.log*
32
+
33
+ # Testing
34
+ coverage/
35
+ playwright-report/
36
+ test-results/
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "private": true,
4
+ "workspaces": ["apps/*", "packages/*"],
5
+ "scripts": {
6
+ "dev": "turbo dev",
7
+ "build": "turbo build",
8
+ "lint": "biome lint .",
9
+ "format": "biome format --write .",
10
+ "check": "biome check --write .",
11
+ "clean": "turbo clean && rm -rf node_modules",
12
+ "prepare": "husky"
13
+ },
14
+ "devDependencies": {
15
+ "@biomejs/biome": "2.3.11",
16
+ "husky": "^9.1.7",
17
+ "lint-staged": "^16.1.0",
18
+ "turbo": "^2.5.4",
19
+ "typescript": "^5.8.3"
20
+ },
21
+ "packageManager": "bun@1.3.5"
22
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true
13
+ }
14
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://turbo.build/schema.json",
3
+ "tasks": {
4
+ "build": {
5
+ "dependsOn": ["^build"],
6
+ "outputs": ["dist/**", ".output/**", ".vinxi/**"]
7
+ },
8
+ "dev": {
9
+ "cache": false,
10
+ "persistent": true
11
+ },
12
+ "lint": {
13
+ "dependsOn": ["^lint"]
14
+ },
15
+ "typecheck": {
16
+ "dependsOn": ["^build"]
17
+ },
18
+ "clean": {
19
+ "cache": false
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@{{name}}/shared",
3
+ "private": true,
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./schemas": "./src/schemas.ts",
8
+ "./types": "./src/types.ts",
9
+ "./utils": "./src/utils.ts"
10
+ },
11
+ "dependencies": {
12
+ "zod": "^3.24.0"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.8.0"
16
+ }
17
+ }
@@ -0,0 +1,4 @@
1
+ // Re-export everything from submodules
2
+ export * from './schemas';
3
+ export * from './types';
4
+ export * from './utils';
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+
3
+ // ============================================================================
4
+ // COMMON SCHEMAS
5
+ // ============================================================================
6
+
7
+ export const IdSchema = z.string().uuid();
8
+
9
+ export const PaginationSchema = z.object({
10
+ page: z.number().int().positive().default(1),
11
+ limit: z.number().int().positive().max(100).default(20),
12
+ });
13
+
14
+ export const TimestampsSchema = z.object({
15
+ createdAt: z.string().datetime(),
16
+ updatedAt: z.string().datetime(),
17
+ });
18
+
19
+ // ============================================================================
20
+ // USER SCHEMAS
21
+ // ============================================================================
22
+
23
+ export const UserSchema = z.object({
24
+ id: IdSchema,
25
+ email: z.string().email(),
26
+ name: z.string().min(1),
27
+ image: z.string().url().optional(),
28
+ });
29
+
30
+ export const CreateUserSchema = UserSchema.omit({ id: true });
31
+ export const UpdateUserSchema = UserSchema.partial().omit({ id: true });
32
+
33
+ // ============================================================================
34
+ // API RESPONSE SCHEMAS
35
+ // ============================================================================
36
+
37
+ export const ApiErrorSchema = z.object({
38
+ code: z.string(),
39
+ message: z.string(),
40
+ details: z.record(z.unknown()).optional(),
41
+ });
42
+
43
+ export const PaginatedResponseSchema = <T extends z.ZodTypeAny>(itemSchema: T) =>
44
+ z.object({
45
+ items: z.array(itemSchema),
46
+ total: z.number().int().nonnegative(),
47
+ page: z.number().int().positive(),
48
+ limit: z.number().int().positive(),
49
+ hasMore: z.boolean(),
50
+ });
@@ -0,0 +1,47 @@
1
+ import type { z } from 'zod';
2
+ import type {
3
+ UserSchema,
4
+ CreateUserSchema,
5
+ UpdateUserSchema,
6
+ PaginationSchema,
7
+ ApiErrorSchema,
8
+ } from './schemas';
9
+
10
+ // ============================================================================
11
+ // INFERRED TYPES FROM SCHEMAS
12
+ // ============================================================================
13
+
14
+ export type User = z.infer<typeof UserSchema>;
15
+ export type CreateUser = z.infer<typeof CreateUserSchema>;
16
+ export type UpdateUser = z.infer<typeof UpdateUserSchema>;
17
+ export type Pagination = z.infer<typeof PaginationSchema>;
18
+ export type ApiError = z.infer<typeof ApiErrorSchema>;
19
+
20
+ // ============================================================================
21
+ // UTILITY TYPES
22
+ // ============================================================================
23
+
24
+ export type PaginatedResponse<T> = {
25
+ items: T[];
26
+ total: number;
27
+ page: number;
28
+ limit: number;
29
+ hasMore: boolean;
30
+ };
31
+
32
+ export type Result<T, E = ApiError> =
33
+ | { ok: true; data: T }
34
+ | { ok: false; error: E };
35
+
36
+ // ============================================================================
37
+ // API TYPES
38
+ // ============================================================================
39
+
40
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
41
+
42
+ export type ApiEndpoint<TInput, TOutput> = {
43
+ method: HttpMethod;
44
+ path: string;
45
+ input: TInput;
46
+ output: TOutput;
47
+ };
@@ -0,0 +1,87 @@
1
+ import type { Result, ApiError } from './types';
2
+
3
+ // ============================================================================
4
+ // RESULT HELPERS
5
+ // ============================================================================
6
+
7
+ export const ok = <T>(data: T): Result<T, never> => ({ ok: true, data });
8
+ export const err = <E = ApiError>(error: E): Result<never, E> => ({ ok: false, error });
9
+
10
+ // ============================================================================
11
+ // STRING UTILS
12
+ // ============================================================================
13
+
14
+ export function slugify(text: string): string {
15
+ return text
16
+ .toLowerCase()
17
+ .trim()
18
+ .replace(/[^\w\s-]/g, '')
19
+ .replace(/[\s_-]+/g, '-')
20
+ .replace(/^-+|-+$/g, '');
21
+ }
22
+
23
+ export function truncate(text: string, maxLength: number, suffix = '...'): string {
24
+ if (text.length <= maxLength) return text;
25
+ return text.slice(0, maxLength - suffix.length) + suffix;
26
+ }
27
+
28
+ export function capitalize(text: string): string {
29
+ return text.charAt(0).toUpperCase() + text.slice(1);
30
+ }
31
+
32
+ // ============================================================================
33
+ // DATE UTILS
34
+ // ============================================================================
35
+
36
+ export function formatDate(date: Date | string, locale = 'en-US'): string {
37
+ const d = typeof date === 'string' ? new Date(date) : date;
38
+ return d.toLocaleDateString(locale, {
39
+ year: 'numeric',
40
+ month: 'long',
41
+ day: 'numeric',
42
+ });
43
+ }
44
+
45
+ export function formatRelativeTime(date: Date | string): string {
46
+ const d = typeof date === 'string' ? new Date(date) : date;
47
+ const now = new Date();
48
+ const diffMs = now.getTime() - d.getTime();
49
+ const diffSecs = Math.floor(diffMs / 1000);
50
+ const diffMins = Math.floor(diffSecs / 60);
51
+ const diffHours = Math.floor(diffMins / 60);
52
+ const diffDays = Math.floor(diffHours / 24);
53
+
54
+ if (diffSecs < 60) return 'just now';
55
+ if (diffMins < 60) return `${diffMins}m ago`;
56
+ if (diffHours < 24) return `${diffHours}h ago`;
57
+ if (diffDays < 7) return `${diffDays}d ago`;
58
+ return formatDate(d);
59
+ }
60
+
61
+ // ============================================================================
62
+ // OBJECT UTILS
63
+ // ============================================================================
64
+
65
+ export function omit<T extends object, K extends keyof T>(
66
+ obj: T,
67
+ keys: K[]
68
+ ): Omit<T, K> {
69
+ const result = { ...obj };
70
+ for (const key of keys) {
71
+ delete result[key];
72
+ }
73
+ return result;
74
+ }
75
+
76
+ export function pick<T extends object, K extends keyof T>(
77
+ obj: T,
78
+ keys: K[]
79
+ ): Pick<T, K> {
80
+ const result = {} as Pick<T, K>;
81
+ for (const key of keys) {
82
+ if (key in obj) {
83
+ result[key] = obj[key];
84
+ }
85
+ }
86
+ return result;
87
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "composite": true
12
+ },
13
+ "include": ["src/**/*"]
14
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@{{name}}/stripe",
3
+ "private": true,
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./client": "./src/client.ts",
8
+ "./webhooks": "./src/webhooks.ts",
9
+ "./schemas": "./src/schemas.ts"
10
+ },
11
+ "dependencies": {
12
+ "stripe": "^17.0.0",
13
+ "zod": "^3.24.0"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "^5.8.0"
17
+ }
18
+ }