@odvi/create-dtt-framework 0.1.3 → 0.1.6

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 (111) hide show
  1. package/dist/commands/create.d.ts.map +1 -1
  2. package/dist/commands/create.js +16 -13
  3. package/dist/commands/create.js.map +1 -1
  4. package/package.json +3 -2
  5. package/template/.env.example +106 -0
  6. package/template/components.json +22 -0
  7. package/template/docs/framework/01-overview.md +289 -0
  8. package/template/docs/framework/02-techstack.md +503 -0
  9. package/template/docs/framework/api-layer.md +681 -0
  10. package/template/docs/framework/clerk-authentication.md +649 -0
  11. package/template/docs/framework/cli-installation.md +564 -0
  12. package/template/docs/framework/deployment/ci-cd.md +907 -0
  13. package/template/docs/framework/deployment/digitalocean.md +991 -0
  14. package/template/docs/framework/deployment/domain-setup.md +972 -0
  15. package/template/docs/framework/deployment/environment-variables.md +862 -0
  16. package/template/docs/framework/deployment/monitoring.md +927 -0
  17. package/template/docs/framework/deployment/production-checklist.md +649 -0
  18. package/template/docs/framework/deployment/vercel.md +791 -0
  19. package/template/docs/framework/environment-variables.md +646 -0
  20. package/template/docs/framework/health-check-system.md +583 -0
  21. package/template/docs/framework/implementation.md +559 -0
  22. package/template/docs/framework/snowflake-integration.md +594 -0
  23. package/template/docs/framework/state-management.md +615 -0
  24. package/template/docs/framework/supabase-integration.md +582 -0
  25. package/template/docs/framework/testing-guide.md +544 -0
  26. package/template/docs/framework/what-did-i-miss.md +526 -0
  27. package/template/drizzle.config.ts +11 -0
  28. package/template/next.config.js +21 -0
  29. package/template/postcss.config.js +5 -0
  30. package/template/prettier.config.js +4 -0
  31. package/template/public/favicon.ico +0 -0
  32. package/template/src/app/(auth)/layout.tsx +4 -0
  33. package/template/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +10 -0
  34. package/template/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx +10 -0
  35. package/template/src/app/(dashboard)/dashboard/page.tsx +8 -0
  36. package/template/src/app/(dashboard)/health/page.tsx +16 -0
  37. package/template/src/app/(dashboard)/layout.tsx +17 -0
  38. package/template/src/app/api/[[...route]]/route.ts +11 -0
  39. package/template/src/app/api/debug-files/route.ts +33 -0
  40. package/template/src/app/api/webhooks/clerk/route.ts +112 -0
  41. package/template/src/app/layout.tsx +28 -0
  42. package/template/src/app/page.tsx +12 -0
  43. package/template/src/app/providers.tsx +20 -0
  44. package/template/src/components/layouts/navbar.tsx +14 -0
  45. package/template/src/components/shared/loading-spinner.tsx +6 -0
  46. package/template/src/components/ui/badge.tsx +46 -0
  47. package/template/src/components/ui/button.tsx +62 -0
  48. package/template/src/components/ui/card.tsx +92 -0
  49. package/template/src/components/ui/collapsible.tsx +33 -0
  50. package/template/src/components/ui/scroll-area.tsx +58 -0
  51. package/template/src/components/ui/sheet.tsx +139 -0
  52. package/template/src/config/__tests__/env.test.ts +164 -0
  53. package/template/src/config/__tests__/site.test.ts +46 -0
  54. package/template/src/config/env.ts +36 -0
  55. package/template/src/config/site.ts +10 -0
  56. package/template/src/env.js +44 -0
  57. package/template/src/features/__tests__/health-check-config.test.ts +142 -0
  58. package/template/src/features/__tests__/health-check-types.test.ts +201 -0
  59. package/template/src/features/documentation/components/doc-sidebar.tsx +109 -0
  60. package/template/src/features/documentation/components/doc-viewer.tsx +70 -0
  61. package/template/src/features/documentation/index.tsx +92 -0
  62. package/template/src/features/documentation/utils/doc-loader.ts +177 -0
  63. package/template/src/features/health-check/components/health-dashboard.tsx +374 -0
  64. package/template/src/features/health-check/config.ts +71 -0
  65. package/template/src/features/health-check/index.ts +4 -0
  66. package/template/src/features/health-check/stores/health-store.ts +14 -0
  67. package/template/src/features/health-check/types.ts +18 -0
  68. package/template/src/hooks/__tests__/use-debounce.test.tsx +28 -0
  69. package/template/src/hooks/queries/use-health-checks.ts +16 -0
  70. package/template/src/hooks/utils/use-debounce.ts +20 -0
  71. package/template/src/lib/__tests__/utils.test.ts +52 -0
  72. package/template/src/lib/__tests__/validators.test.ts +114 -0
  73. package/template/src/lib/nextbank/client.ts +67 -0
  74. package/template/src/lib/snowflake/client.ts +102 -0
  75. package/template/src/lib/supabase/admin.ts +7 -0
  76. package/template/src/lib/supabase/client.ts +7 -0
  77. package/template/src/lib/supabase/server.ts +23 -0
  78. package/template/src/lib/utils.ts +6 -0
  79. package/template/src/lib/validators.ts +9 -0
  80. package/template/src/middleware.ts +22 -0
  81. package/template/src/server/api/index.ts +22 -0
  82. package/template/src/server/api/middleware/auth.ts +19 -0
  83. package/template/src/server/api/middleware/logger.ts +4 -0
  84. package/template/src/server/api/routes/health/clerk.ts +214 -0
  85. package/template/src/server/api/routes/health/database.ts +141 -0
  86. package/template/src/server/api/routes/health/edge-functions.ts +107 -0
  87. package/template/src/server/api/routes/health/framework.ts +48 -0
  88. package/template/src/server/api/routes/health/index.ts +102 -0
  89. package/template/src/server/api/routes/health/nextbank.ts +46 -0
  90. package/template/src/server/api/routes/health/snowflake.ts +83 -0
  91. package/template/src/server/api/routes/health/storage.ts +177 -0
  92. package/template/src/server/api/routes/users.ts +79 -0
  93. package/template/src/server/db/index.ts +17 -0
  94. package/template/src/server/db/queries/users.ts +8 -0
  95. package/template/src/server/db/schema/__tests__/health-checks.test.ts +31 -0
  96. package/template/src/server/db/schema/__tests__/users.test.ts +46 -0
  97. package/template/src/server/db/schema/health-checks.ts +11 -0
  98. package/template/src/server/db/schema/index.ts +2 -0
  99. package/template/src/server/db/schema/users.ts +16 -0
  100. package/template/src/server/db/schema.ts +1 -0
  101. package/template/src/stores/__tests__/ui-store.test.ts +87 -0
  102. package/template/src/stores/ui-store.ts +14 -0
  103. package/template/src/styles/globals.css +129 -0
  104. package/template/src/test/mocks/clerk.ts +35 -0
  105. package/template/src/test/mocks/snowflake.ts +28 -0
  106. package/template/src/test/mocks/supabase.ts +37 -0
  107. package/template/src/test/setup.ts +69 -0
  108. package/template/src/test/utils/test-helpers.ts +158 -0
  109. package/template/src/types/index.ts +14 -0
  110. package/template/tsconfig.json +43 -0
  111. package/template/vitest.config.ts +44 -0
@@ -0,0 +1,37 @@
1
+ import { vi } from 'vitest';
2
+
3
+ // Mock Supabase client
4
+ export const mockSupabaseClient = {
5
+ from: vi.fn(() => mockSupabaseClient),
6
+ select: vi.fn(() => mockSupabaseClient),
7
+ insert: vi.fn(() => mockSupabaseClient),
8
+ update: vi.fn(() => mockSupabaseClient),
9
+ delete: vi.fn(() => mockSupabaseClient),
10
+ eq: vi.fn(() => mockSupabaseClient),
11
+ order: vi.fn(() => mockSupabaseClient),
12
+ limit: vi.fn(() => mockSupabaseClient),
13
+ single: vi.fn(),
14
+ maybeSingle: vi.fn(),
15
+ rpc: vi.fn(),
16
+ auth: {
17
+ getUser: vi.fn(),
18
+ signInWithPassword: vi.fn(),
19
+ signOut: vi.fn(),
20
+ onAuthStateChange: vi.fn(),
21
+ },
22
+ storage: {
23
+ from: vi.fn(() => ({
24
+ upload: vi.fn(),
25
+ download: vi.fn(),
26
+ remove: vi.fn(),
27
+ list: vi.fn(),
28
+ getPublicUrl: vi.fn(),
29
+ })),
30
+ },
31
+ };
32
+
33
+ vi.mock('@supabase/supabase-js', () => ({
34
+ createClient: vi.fn(() => mockSupabaseClient),
35
+ }));
36
+
37
+ export default mockSupabaseClient;
@@ -0,0 +1,69 @@
1
+ import '@testing-library/jest-dom';
2
+ import { cleanup } from '@testing-library/react';
3
+ import { afterEach, vi } from 'vitest';
4
+
5
+ // Cleanup after each test
6
+ afterEach(() => {
7
+ cleanup();
8
+ });
9
+
10
+ // Mock window.matchMedia
11
+ Object.defineProperty(window, 'matchMedia', {
12
+ writable: true,
13
+ value: vi.fn().mockImplementation((query) => ({
14
+ matches: false,
15
+ media: query,
16
+ onchange: null,
17
+ addListener: vi.fn(),
18
+ removeListener: vi.fn(),
19
+ addEventListener: vi.fn(),
20
+ removeEventListener: vi.fn(),
21
+ dispatchEvent: vi.fn(),
22
+ })),
23
+ });
24
+
25
+ // Mock IntersectionObserver
26
+ global.IntersectionObserver = class IntersectionObserver {
27
+ constructor() {}
28
+ disconnect() {}
29
+ observe() {}
30
+ takeRecords() {
31
+ return [];
32
+ }
33
+ unobserve() {}
34
+ } as any;
35
+
36
+ // Mock ResizeObserver
37
+ global.ResizeObserver = class ResizeObserver {
38
+ constructor() {}
39
+ disconnect() {}
40
+ observe() {}
41
+ unobserve() {}
42
+ } as any;
43
+
44
+ // Mock requestAnimationFrame
45
+ global.requestAnimationFrame = (callback: FrameRequestCallback) => {
46
+ return setTimeout(callback, 0) as unknown as number;
47
+ };
48
+
49
+ global.cancelAnimationFrame = (id: number) => {
50
+ clearTimeout(id);
51
+ };
52
+
53
+ // Suppress console errors in tests (optional, can be removed for debugging)
54
+ const originalError = console.error;
55
+ beforeAll(() => {
56
+ console.error = (...args: any[]) => {
57
+ if (
58
+ typeof args[0] === 'string' &&
59
+ args[0].includes('Warning: ReactDOM.render')
60
+ ) {
61
+ return;
62
+ }
63
+ originalError.call(console, ...args);
64
+ };
65
+ });
66
+
67
+ afterAll(() => {
68
+ console.error = originalError;
69
+ });
@@ -0,0 +1,158 @@
1
+ import type { RenderOptions } from '@testing-library/react';
2
+ import { render } from '@testing-library/react';
3
+ import type { ReactElement } from 'react';
4
+ import { vi, beforeEach, afterEach } from 'vitest';
5
+
6
+ /**
7
+ * Custom render function that includes providers if needed
8
+ */
9
+ export function renderWithProviders(
10
+ ui: ReactElement,
11
+ options?: Omit<RenderOptions, 'wrapper'>
12
+ ) {
13
+ return render(ui, options);
14
+ }
15
+
16
+ /**
17
+ * Create a mock function that returns a resolved value
18
+ */
19
+ export function mockResolved<T>(value: T) {
20
+ return vi.fn().mockResolvedValue(value);
21
+ }
22
+
23
+ /**
24
+ * Create a mock function that returns a rejected value
25
+ */
26
+ export function mockRejected(error: Error | string) {
27
+ return vi.fn().mockRejectedValue(error instanceof Error ? error : new Error(error));
28
+ }
29
+
30
+ /**
31
+ * Wait for a specified amount of time
32
+ */
33
+ export function wait(ms: number): Promise<void> {
34
+ return new Promise((resolve) => setTimeout(resolve, ms));
35
+ }
36
+
37
+ /**
38
+ * Create a mock user object
39
+ */
40
+ export function createMockUser(overrides: Partial<any> = {}) {
41
+ return {
42
+ id: 'user-123',
43
+ email: 'test@example.com',
44
+ firstName: 'Test',
45
+ lastName: 'User',
46
+ imageUrl: 'https://example.com/avatar.jpg',
47
+ clerkOrgId: 'org-123',
48
+ createdAt: new Date(),
49
+ updatedAt: new Date(),
50
+ ...overrides,
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Create a mock health check result
56
+ */
57
+ export function createMockHealthCheck(overrides: Partial<any> = {}) {
58
+ return {
59
+ status: 'healthy',
60
+ responseTimeMs: 100,
61
+ message: 'Service is healthy',
62
+ ...overrides,
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Create a mock service health object
68
+ */
69
+ export function createMockServiceHealth(overrides: Partial<any> = {}) {
70
+ return {
71
+ name: 'Test Service',
72
+ icon: 'test-icon',
73
+ status: 'healthy',
74
+ responseTimeMs: 100,
75
+ checks: [
76
+ {
77
+ name: 'Test Check',
78
+ endpoint: '/test/endpoint',
79
+ status: 'healthy',
80
+ responseTimeMs: 50,
81
+ },
82
+ ],
83
+ ...overrides,
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Mock console methods to suppress warnings in tests
89
+ */
90
+ export function suppressConsoleWarnings() {
91
+ const originalWarn = console.warn;
92
+ const originalError = console.error;
93
+
94
+ beforeEach(() => {
95
+ console.warn = vi.fn();
96
+ console.error = vi.fn();
97
+ });
98
+
99
+ afterEach(() => {
100
+ console.warn = originalWarn;
101
+ console.error = originalError;
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Create a mock fetch response
107
+ */
108
+ export function createMockResponse(
109
+ data: any,
110
+ status: number = 200,
111
+ ok: boolean = true
112
+ ) {
113
+ return {
114
+ ok,
115
+ status,
116
+ json: vi.fn().mockResolvedValue(data),
117
+ text: vi.fn().mockResolvedValue(JSON.stringify(data)),
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Mock localStorage
123
+ */
124
+ export function mockLocalStorage() {
125
+ const store: Record<string, string> = {};
126
+
127
+ return {
128
+ getItem: (key: string) => store[key] ?? null,
129
+ setItem: (key: string, value: string) => {
130
+ store[key] = value;
131
+ },
132
+ removeItem: (key: string) => {
133
+ delete store[key];
134
+ },
135
+ clear: () => {
136
+ Object.keys(store).forEach((key) => delete store[key]);
137
+ },
138
+ get length() {
139
+ return Object.keys(store).length;
140
+ },
141
+ key: (index: number) => Object.keys(store)[index] ?? null,
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Create a mock router
147
+ */
148
+ export function createMockRouter() {
149
+ return {
150
+ push: vi.fn(),
151
+ replace: vi.fn(),
152
+ prefetch: vi.fn(),
153
+ back: vi.fn(),
154
+ pathname: '/',
155
+ query: {},
156
+ asPath: '/',
157
+ };
158
+ }
@@ -0,0 +1,14 @@
1
+ // Global type definitions placeholder
2
+
3
+ export interface User {
4
+ id: string
5
+ email: string
6
+ firstName?: string
7
+ lastName?: string
8
+ imageUrl?: string
9
+ clerkOrgId?: string
10
+ createdAt: Date
11
+ updatedAt: Date
12
+ }
13
+
14
+ export type HealthStatus = 'healthy' | 'unhealthy' | 'error' | 'pending' | 'unconfigured'
@@ -0,0 +1,43 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Base Options: */
4
+ "esModuleInterop": true,
5
+ "skipLibCheck": true,
6
+ "target": "es2022",
7
+ "allowJs": true,
8
+ "resolveJsonModule": true,
9
+ "moduleDetection": "force",
10
+ "isolatedModules": true,
11
+ "verbatimModuleSyntax": true,
12
+
13
+ /* Strictness */
14
+ "strict": true,
15
+ "noUncheckedIndexedAccess": true,
16
+ "checkJs": true,
17
+
18
+ /* Bundled projects */
19
+ "lib": ["dom", "dom.iterable", "ES2022"],
20
+ "noEmit": true,
21
+ "module": "ESNext",
22
+ "moduleResolution": "Bundler",
23
+ "jsx": "preserve",
24
+ "plugins": [{ "name": "next" }],
25
+ "incremental": true,
26
+
27
+ /* Path Aliases */
28
+ "baseUrl": ".",
29
+ "paths": {
30
+ "~/*": ["./src/*"],
31
+ "@/*": ["./src/*"]
32
+ }
33
+ },
34
+ "include": [
35
+ "next-env.d.ts",
36
+ "**/*.ts",
37
+ "**/*.tsx",
38
+ "**/*.cjs",
39
+ "**/*.js",
40
+ ".next/types/**/*.ts"
41
+ ],
42
+ "exclude": ["node_modules", "generated", "cli", "src/test", "**/*.test.ts", "**/*.test.tsx", "vitest.config.ts", "drizzle.config.ts", "supabase"]
43
+ }
@@ -0,0 +1,44 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ import react from '@vitejs/plugin-react';
3
+ import path from 'path';
4
+
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ test: {
8
+ globals: true,
9
+ environment: 'jsdom',
10
+ setupFiles: ['./src/test/setup.ts'],
11
+ include: ['**/__tests__/**/*.{test,spec}.{ts,tsx}', '**/*.{test,spec}.{ts,tsx}'],
12
+ exclude: ['node_modules', 'dist', '.next', 'coverage'],
13
+ coverage: {
14
+ provider: 'v8',
15
+ reporter: ['text', 'json', 'html', 'lcov'],
16
+ exclude: [
17
+ 'node_modules/',
18
+ '.next/',
19
+ 'dist/',
20
+ 'coverage/',
21
+ '**/*.config.{js,ts}',
22
+ '**/types/**',
23
+ '**/test/**',
24
+ '**/__tests__/**',
25
+ '**/*.d.ts',
26
+ '**/mockData.ts',
27
+ 'src/middleware.ts',
28
+ 'src/env.js',
29
+ ],
30
+ all: true,
31
+ lines: 80,
32
+ functions: 80,
33
+ branches: 80,
34
+ statements: 80,
35
+ },
36
+ testTimeout: 10000,
37
+ hookTimeout: 10000,
38
+ },
39
+ resolve: {
40
+ alias: {
41
+ '@': path.resolve(__dirname, './src'),
42
+ },
43
+ },
44
+ });