@react-spa-scaffold/mcp 2.1.1 → 2.3.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.
- package/README.md +2 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -0
- package/dist/constants.js.map +1 -1
- package/dist/features/definitions/auth.d.ts +3 -0
- package/dist/features/definitions/auth.d.ts.map +1 -0
- package/dist/features/definitions/auth.js +17 -0
- package/dist/features/definitions/auth.js.map +1 -0
- package/dist/features/definitions/core.d.ts.map +1 -1
- package/dist/features/definitions/core.js +16 -1
- package/dist/features/definitions/core.js.map +1 -1
- package/dist/features/definitions/database.d.ts +3 -0
- package/dist/features/definitions/database.d.ts.map +1 -0
- package/dist/features/definitions/database.js +45 -0
- package/dist/features/definitions/database.js.map +1 -0
- package/dist/features/definitions/deployment.d.ts +3 -0
- package/dist/features/definitions/deployment.d.ts.map +1 -0
- package/dist/features/definitions/deployment.js +14 -0
- package/dist/features/definitions/deployment.js.map +1 -0
- package/dist/features/definitions/forms.d.ts.map +1 -1
- package/dist/features/definitions/forms.js +4 -0
- package/dist/features/definitions/forms.js.map +1 -1
- package/dist/features/definitions/index.d.ts +3 -0
- package/dist/features/definitions/index.d.ts.map +1 -1
- package/dist/features/definitions/index.js +3 -0
- package/dist/features/definitions/index.js.map +1 -1
- package/dist/features/definitions/mobile.d.ts.map +1 -1
- package/dist/features/definitions/mobile.js +11 -2
- package/dist/features/definitions/mobile.js.map +1 -1
- package/dist/features/definitions/observability.js +1 -1
- package/dist/features/definitions/observability.js.map +1 -1
- package/dist/features/definitions/routing.d.ts.map +1 -1
- package/dist/features/definitions/routing.js +2 -1
- package/dist/features/definitions/routing.js.map +1 -1
- package/dist/features/definitions/state.d.ts.map +1 -1
- package/dist/features/definitions/state.js +9 -2
- package/dist/features/definitions/state.js.map +1 -1
- package/dist/features/definitions/testing.d.ts.map +1 -1
- package/dist/features/definitions/testing.js +4 -2
- package/dist/features/definitions/testing.js.map +1 -1
- package/dist/features/registry.d.ts.map +1 -1
- package/dist/features/registry.js +4 -1
- package/dist/features/registry.js.map +1 -1
- package/dist/features/types.test.js +6 -2
- package/dist/features/types.test.js.map +1 -1
- package/dist/resources/docs.d.ts.map +1 -1
- package/dist/resources/docs.js +5 -0
- package/dist/resources/docs.js.map +1 -1
- package/dist/tools/add-features.js +1 -1
- package/dist/tools/add-features.js.map +1 -1
- package/dist/utils/docs.d.ts.map +1 -1
- package/dist/utils/docs.js +2 -0
- package/dist/utils/docs.js.map +1 -1
- package/dist/utils/scaffold/claude-md/index.d.ts.map +1 -1
- package/dist/utils/scaffold/claude-md/index.js +3 -1
- package/dist/utils/scaffold/claude-md/index.js.map +1 -1
- package/dist/utils/scaffold/claude-md/sections.d.ts +2 -0
- package/dist/utils/scaffold/claude-md/sections.d.ts.map +1 -1
- package/dist/utils/scaffold/claude-md/sections.js +132 -2
- package/dist/utils/scaffold/claude-md/sections.js.map +1 -1
- package/dist/utils/scaffold/compute.js +1 -1
- package/dist/utils/scaffold/compute.js.map +1 -1
- package/dist/utils/scaffold/generators.d.ts +2 -2
- package/dist/utils/scaffold/generators.d.ts.map +1 -1
- package/dist/utils/scaffold/generators.js +64 -22
- package/dist/utils/scaffold/generators.js.map +1 -1
- package/package.json +1 -1
- package/templates/.env.example +44 -10
- package/templates/.github/workflows/ci.yml +12 -4
- package/templates/.github/workflows/deploy.yml +59 -0
- package/templates/CLAUDE.md +251 -2
- package/templates/docs/ARCHITECTURE.md +13 -12
- package/templates/docs/AUTHENTICATION.md +325 -0
- package/templates/docs/CODING_STANDARDS.md +65 -0
- package/templates/docs/DEPLOYMENT.md +268 -0
- package/templates/docs/E2E_TESTING.md +133 -11
- package/templates/docs/SUPABASE_INTEGRATION.md +310 -0
- package/templates/docs/TESTING.md +195 -77
- package/templates/e2e/auth/auth.setup.ts +60 -0
- package/templates/e2e/fixtures/index.ts +24 -2
- package/templates/e2e/tests/profile.auth.spec.ts +103 -0
- package/templates/e2e/tests/profile.spec.ts +64 -0
- package/templates/e2e/tests/register-form.spec.ts +38 -0
- package/templates/gitignore +5 -0
- package/templates/package.json +15 -3
- package/templates/playwright.config.ts +39 -4
- package/templates/src/App.tsx +32 -19
- package/templates/src/components/layout/Header.test.tsx +17 -1
- package/templates/src/components/layout/Header.tsx +13 -1
- package/templates/src/components/shared/AccountButton/AccountButton.test.tsx +30 -0
- package/templates/src/components/shared/AccountButton/AccountButton.tsx +38 -0
- package/templates/src/components/shared/AccountButton/index.ts +1 -0
- package/templates/src/components/shared/ErrorBoundary/ErrorBoundary.test.tsx +4 -4
- package/templates/src/components/shared/ErrorBoundary/ErrorBoundary.tsx +55 -53
- package/templates/src/components/shared/ProfileSync/ProfileSync.test.tsx +44 -0
- package/templates/src/components/shared/ProfileSync/ProfileSync.tsx +104 -0
- package/templates/src/components/shared/ProfileSync/index.ts +1 -0
- package/templates/src/components/shared/ProtectedRoute/ProtectedRoute.test.tsx +43 -0
- package/templates/src/components/shared/ProtectedRoute/ProtectedRoute.tsx +35 -0
- package/templates/src/components/shared/ProtectedRoute/index.ts +1 -0
- package/templates/src/components/shared/index.ts +5 -2
- package/templates/src/contexts/clerkContext.tsx +45 -0
- package/templates/src/contexts/performanceContext.tsx +3 -3
- package/templates/src/contexts/supabaseContext.test.tsx +59 -0
- package/templates/src/contexts/supabaseContext.tsx +87 -0
- package/templates/src/hooks/index.ts +40 -2
- package/templates/src/hooks/supabase/index.ts +12 -0
- package/templates/src/hooks/supabase/useProfiles.test.tsx +207 -0
- package/templates/src/hooks/supabase/useProfiles.ts +213 -0
- package/templates/src/hooks/supabase/useSupabaseQuery.test.tsx +150 -0
- package/templates/src/hooks/supabase/useSupabaseQuery.ts +91 -0
- package/templates/src/hooks/useCopyFeedback.test.ts +129 -0
- package/templates/src/hooks/useCopyFeedback.ts +41 -0
- package/templates/src/hooks/useDebouncedCallback.test.ts +164 -0
- package/templates/src/hooks/useDebouncedCallback.ts +47 -0
- package/templates/src/hooks/useDocumentTitle.test.ts +59 -0
- package/templates/src/hooks/useDocumentTitle.ts +31 -0
- package/templates/src/hooks/useIOSViewportReset.test.ts +58 -0
- package/templates/src/hooks/useIOSViewportReset.ts +18 -0
- package/templates/src/hooks/useKeyboardShortcut.test.ts +86 -0
- package/templates/src/hooks/useKeyboardShortcuts.ts +44 -0
- package/templates/src/hooks/useLocalStorage.test.ts +111 -0
- package/templates/src/hooks/useLocalStorage.ts +77 -0
- package/templates/src/hooks/useSyncedFormData.test.ts +75 -0
- package/templates/src/hooks/useSyncedFormData.ts +21 -0
- package/templates/src/hooks/useSyncedState.test.ts +119 -0
- package/templates/src/hooks/useSyncedState.ts +30 -0
- package/templates/src/index.css +1 -0
- package/templates/src/lib/api.test.ts +30 -38
- package/templates/src/lib/api.ts +1 -7
- package/templates/src/lib/config.ts +54 -4
- package/templates/src/lib/constants.ts +10 -0
- package/templates/src/lib/createSelectors.test.ts +136 -0
- package/templates/src/lib/createSelectors.ts +31 -0
- package/templates/src/lib/env.ts +36 -14
- package/templates/src/lib/index.ts +5 -2
- package/templates/src/lib/routes.ts +1 -0
- package/templates/src/lib/sentry.ts +58 -0
- package/templates/src/lib/storage.ts +6 -2
- package/templates/src/lib/supabase/client.ts +58 -0
- package/templates/src/lib/supabase/index.ts +5 -0
- package/templates/src/main.tsx +19 -31
- package/templates/src/mocks/constants.ts +31 -0
- package/templates/src/mocks/fixtures/index.ts +3 -1
- package/templates/src/mocks/fixtures/profiles.ts +55 -0
- package/templates/src/mocks/fixtures/users.ts +91 -0
- package/templates/src/mocks/handlers/index.ts +2 -1
- package/templates/src/mocks/handlers/supabase.ts +64 -0
- package/templates/src/mocks/handlers/todos.ts +1 -1
- package/templates/src/mocks/index.ts +6 -0
- package/templates/src/pages/Profile.test.tsx +263 -0
- package/templates/src/pages/Profile.tsx +171 -0
- package/templates/src/pages/index.ts +1 -0
- package/templates/src/stores/preferencesStore.ts +35 -9
- package/templates/src/test/clerkMock.tsx +137 -0
- package/templates/src/test/fetchMock.ts +58 -0
- package/templates/src/test/index.ts +51 -2
- package/templates/src/test/mocks.ts +128 -1
- package/templates/src/test/providers.tsx +10 -4
- package/templates/src/test/supabaseMock.ts +112 -0
- package/templates/src/test-setup.ts +42 -2
- package/templates/src/types/database.ts +46 -0
- package/templates/src/types/index.ts +1 -0
- package/templates/src/types/supabase.ts +167 -0
- package/templates/src/vite-env.d.ts +6 -0
- package/templates/supabase/migrations/20260104000000_create_profiles_table.sql +67 -0
- package/templates/vitest.config.ts +9 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];
|
|
2
|
+
|
|
3
|
+
export type Database = {
|
|
4
|
+
// Allows to automatically instantiate createClient with right options
|
|
5
|
+
// instead of createClient<Database, { PostgrestVersion: 'XX' }>(URL, KEY)
|
|
6
|
+
__InternalSupabase: {
|
|
7
|
+
PostgrestVersion: '14.1';
|
|
8
|
+
};
|
|
9
|
+
public: {
|
|
10
|
+
Tables: {
|
|
11
|
+
profiles: {
|
|
12
|
+
Row: {
|
|
13
|
+
avatar_url: string | null;
|
|
14
|
+
created_at: string | null;
|
|
15
|
+
email: string;
|
|
16
|
+
full_name: string | null;
|
|
17
|
+
id: string;
|
|
18
|
+
updated_at: string | null;
|
|
19
|
+
};
|
|
20
|
+
Insert: {
|
|
21
|
+
avatar_url?: string | null;
|
|
22
|
+
created_at?: string | null;
|
|
23
|
+
email: string;
|
|
24
|
+
full_name?: string | null;
|
|
25
|
+
id: string;
|
|
26
|
+
updated_at?: string | null;
|
|
27
|
+
};
|
|
28
|
+
Update: {
|
|
29
|
+
avatar_url?: string | null;
|
|
30
|
+
created_at?: string | null;
|
|
31
|
+
email?: string;
|
|
32
|
+
full_name?: string | null;
|
|
33
|
+
id?: string;
|
|
34
|
+
updated_at?: string | null;
|
|
35
|
+
};
|
|
36
|
+
Relationships: [];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
Views: {
|
|
40
|
+
[_ in never]: never;
|
|
41
|
+
};
|
|
42
|
+
Functions: {
|
|
43
|
+
[_ in never]: never;
|
|
44
|
+
};
|
|
45
|
+
Enums: {
|
|
46
|
+
[_ in never]: never;
|
|
47
|
+
};
|
|
48
|
+
CompositeTypes: {
|
|
49
|
+
[_ in never]: never;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type DatabaseWithoutInternals = Omit<Database, '__InternalSupabase'>;
|
|
55
|
+
|
|
56
|
+
type DefaultSchema = DatabaseWithoutInternals[Extract<keyof Database, 'public'>];
|
|
57
|
+
|
|
58
|
+
export type Tables<
|
|
59
|
+
DefaultSchemaTableNameOrOptions extends
|
|
60
|
+
| keyof (DefaultSchema['Tables'] & DefaultSchema['Views'])
|
|
61
|
+
| { schema: keyof DatabaseWithoutInternals },
|
|
62
|
+
TableName extends DefaultSchemaTableNameOrOptions extends {
|
|
63
|
+
schema: keyof DatabaseWithoutInternals;
|
|
64
|
+
}
|
|
65
|
+
? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Tables'] &
|
|
66
|
+
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Views'])
|
|
67
|
+
: never = never,
|
|
68
|
+
> = DefaultSchemaTableNameOrOptions extends {
|
|
69
|
+
schema: keyof DatabaseWithoutInternals;
|
|
70
|
+
}
|
|
71
|
+
? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Tables'] &
|
|
72
|
+
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Views'])[TableName] extends {
|
|
73
|
+
Row: infer R;
|
|
74
|
+
}
|
|
75
|
+
? R
|
|
76
|
+
: never
|
|
77
|
+
: DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema['Tables'] & DefaultSchema['Views'])
|
|
78
|
+
? (DefaultSchema['Tables'] & DefaultSchema['Views'])[DefaultSchemaTableNameOrOptions] extends {
|
|
79
|
+
Row: infer R;
|
|
80
|
+
}
|
|
81
|
+
? R
|
|
82
|
+
: never
|
|
83
|
+
: never;
|
|
84
|
+
|
|
85
|
+
export type TablesInsert<
|
|
86
|
+
DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables'] | { schema: keyof DatabaseWithoutInternals },
|
|
87
|
+
TableName extends DefaultSchemaTableNameOrOptions extends {
|
|
88
|
+
schema: keyof DatabaseWithoutInternals;
|
|
89
|
+
}
|
|
90
|
+
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Tables']
|
|
91
|
+
: never = never,
|
|
92
|
+
> = DefaultSchemaTableNameOrOptions extends {
|
|
93
|
+
schema: keyof DatabaseWithoutInternals;
|
|
94
|
+
}
|
|
95
|
+
? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Tables'][TableName] extends {
|
|
96
|
+
Insert: infer I;
|
|
97
|
+
}
|
|
98
|
+
? I
|
|
99
|
+
: never
|
|
100
|
+
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables']
|
|
101
|
+
? DefaultSchema['Tables'][DefaultSchemaTableNameOrOptions] extends {
|
|
102
|
+
Insert: infer I;
|
|
103
|
+
}
|
|
104
|
+
? I
|
|
105
|
+
: never
|
|
106
|
+
: never;
|
|
107
|
+
|
|
108
|
+
export type TablesUpdate<
|
|
109
|
+
DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables'] | { schema: keyof DatabaseWithoutInternals },
|
|
110
|
+
TableName extends DefaultSchemaTableNameOrOptions extends {
|
|
111
|
+
schema: keyof DatabaseWithoutInternals;
|
|
112
|
+
}
|
|
113
|
+
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Tables']
|
|
114
|
+
: never = never,
|
|
115
|
+
> = DefaultSchemaTableNameOrOptions extends {
|
|
116
|
+
schema: keyof DatabaseWithoutInternals;
|
|
117
|
+
}
|
|
118
|
+
? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions['schema']]['Tables'][TableName] extends {
|
|
119
|
+
Update: infer U;
|
|
120
|
+
}
|
|
121
|
+
? U
|
|
122
|
+
: never
|
|
123
|
+
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables']
|
|
124
|
+
? DefaultSchema['Tables'][DefaultSchemaTableNameOrOptions] extends {
|
|
125
|
+
Update: infer U;
|
|
126
|
+
}
|
|
127
|
+
? U
|
|
128
|
+
: never
|
|
129
|
+
: never;
|
|
130
|
+
|
|
131
|
+
export type Enums<
|
|
132
|
+
DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema['Enums'] | { schema: keyof DatabaseWithoutInternals },
|
|
133
|
+
EnumName extends DefaultSchemaEnumNameOrOptions extends {
|
|
134
|
+
schema: keyof DatabaseWithoutInternals;
|
|
135
|
+
}
|
|
136
|
+
? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions['schema']]['Enums']
|
|
137
|
+
: never = never,
|
|
138
|
+
> = DefaultSchemaEnumNameOrOptions extends {
|
|
139
|
+
schema: keyof DatabaseWithoutInternals;
|
|
140
|
+
}
|
|
141
|
+
? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions['schema']]['Enums'][EnumName]
|
|
142
|
+
: DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema['Enums']
|
|
143
|
+
? DefaultSchema['Enums'][DefaultSchemaEnumNameOrOptions]
|
|
144
|
+
: never;
|
|
145
|
+
|
|
146
|
+
export type CompositeTypes<
|
|
147
|
+
PublicCompositeTypeNameOrOptions extends
|
|
148
|
+
| keyof DefaultSchema['CompositeTypes']
|
|
149
|
+
| { schema: keyof DatabaseWithoutInternals },
|
|
150
|
+
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
|
|
151
|
+
schema: keyof DatabaseWithoutInternals;
|
|
152
|
+
}
|
|
153
|
+
? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes']
|
|
154
|
+
: never = never,
|
|
155
|
+
> = PublicCompositeTypeNameOrOptions extends {
|
|
156
|
+
schema: keyof DatabaseWithoutInternals;
|
|
157
|
+
}
|
|
158
|
+
? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes'][CompositeTypeName]
|
|
159
|
+
: PublicCompositeTypeNameOrOptions extends keyof DefaultSchema['CompositeTypes']
|
|
160
|
+
? DefaultSchema['CompositeTypes'][PublicCompositeTypeNameOrOptions]
|
|
161
|
+
: never;
|
|
162
|
+
|
|
163
|
+
export const Constants = {
|
|
164
|
+
public: {
|
|
165
|
+
Enums: {},
|
|
166
|
+
},
|
|
167
|
+
} as const;
|
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
interface ImportMetaEnv {
|
|
4
4
|
readonly VITE_APP_NAME: string;
|
|
5
5
|
readonly VITE_APP_URL: string;
|
|
6
|
+
readonly VITE_API_URL?: string;
|
|
7
|
+
readonly VITE_SENTRY_DSN?: string;
|
|
8
|
+
readonly VITE_CLERK_PUBLISHABLE_KEY?: string;
|
|
9
|
+
readonly MODE: 'development' | 'production' | 'test';
|
|
10
|
+
readonly DEV: boolean;
|
|
11
|
+
readonly PROD: boolean;
|
|
6
12
|
}
|
|
7
13
|
|
|
8
14
|
interface ImportMeta {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
-- ============================================================
|
|
2
|
+
-- PROFILES TABLE (linked to Clerk user_id)
|
|
3
|
+
-- ============================================================
|
|
4
|
+
|
|
5
|
+
-- Create the table
|
|
6
|
+
CREATE TABLE IF NOT EXISTS profiles (
|
|
7
|
+
id TEXT PRIMARY KEY, -- Clerk user_id (from auth.uid())
|
|
8
|
+
email TEXT NOT NULL,
|
|
9
|
+
full_name TEXT,
|
|
10
|
+
avatar_url TEXT,
|
|
11
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
12
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- Enable Row Level Security
|
|
16
|
+
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
|
|
17
|
+
|
|
18
|
+
-- ============================================================
|
|
19
|
+
-- RLS POLICIES
|
|
20
|
+
-- Using auth.jwt()->>'sub' for Clerk compatibility (string IDs)
|
|
21
|
+
-- ============================================================
|
|
22
|
+
|
|
23
|
+
-- Users can view their own profile
|
|
24
|
+
-- NOTE: Using auth.jwt()->>'sub' instead of auth.uid() because
|
|
25
|
+
-- Clerk user IDs are strings (e.g., user_xxx), not UUIDs
|
|
26
|
+
CREATE POLICY "Users can view own profile"
|
|
27
|
+
ON profiles FOR SELECT TO authenticated
|
|
28
|
+
USING (id = (select auth.jwt()->>'sub'));
|
|
29
|
+
|
|
30
|
+
-- Users can insert their own profile (first login)
|
|
31
|
+
CREATE POLICY "Users can insert own profile"
|
|
32
|
+
ON profiles FOR INSERT TO authenticated
|
|
33
|
+
WITH CHECK (id = (select auth.jwt()->>'sub'));
|
|
34
|
+
|
|
35
|
+
-- Users can update their own profile
|
|
36
|
+
CREATE POLICY "Users can update own profile"
|
|
37
|
+
ON profiles FOR UPDATE TO authenticated
|
|
38
|
+
USING (id = (select auth.jwt()->>'sub'))
|
|
39
|
+
WITH CHECK (id = (select auth.jwt()->>'sub'));
|
|
40
|
+
|
|
41
|
+
-- Users can delete their own profile
|
|
42
|
+
CREATE POLICY "Users can delete own profile"
|
|
43
|
+
ON profiles FOR DELETE TO authenticated
|
|
44
|
+
USING (id = (select auth.jwt()->>'sub'));
|
|
45
|
+
|
|
46
|
+
-- ============================================================
|
|
47
|
+
-- AUTO-UPDATE TIMESTAMP TRIGGER
|
|
48
|
+
-- ============================================================
|
|
49
|
+
|
|
50
|
+
-- Function to update updated_at (with secure search_path)
|
|
51
|
+
CREATE OR REPLACE FUNCTION public.update_updated_at()
|
|
52
|
+
RETURNS TRIGGER
|
|
53
|
+
LANGUAGE plpgsql
|
|
54
|
+
SECURITY DEFINER
|
|
55
|
+
SET search_path = ''
|
|
56
|
+
AS $$
|
|
57
|
+
BEGIN
|
|
58
|
+
NEW.updated_at = NOW();
|
|
59
|
+
RETURN NEW;
|
|
60
|
+
END;
|
|
61
|
+
$$;
|
|
62
|
+
|
|
63
|
+
-- Trigger for profiles
|
|
64
|
+
CREATE TRIGGER profiles_updated_at
|
|
65
|
+
BEFORE UPDATE ON profiles
|
|
66
|
+
FOR EACH ROW
|
|
67
|
+
EXECUTE FUNCTION update_updated_at();
|
|
@@ -21,7 +21,15 @@ export default defineConfig({
|
|
|
21
21
|
coverage: {
|
|
22
22
|
provider: 'v8',
|
|
23
23
|
reporter: ['text', 'json', 'html', 'lcov'],
|
|
24
|
-
exclude: [
|
|
24
|
+
exclude: [
|
|
25
|
+
'**/*.test.{ts,tsx}',
|
|
26
|
+
'**/index.ts',
|
|
27
|
+
'src/types/**',
|
|
28
|
+
'src/components/ui/**',
|
|
29
|
+
'src/mocks/**',
|
|
30
|
+
'src/test/**', // Test utilities and mocks
|
|
31
|
+
'src/lib/sentry.ts', // Production-only, lazily loaded
|
|
32
|
+
],
|
|
25
33
|
thresholds: {
|
|
26
34
|
lines: 80,
|
|
27
35
|
functions: 80,
|