@digilogiclabs/create-saas-app 2.7.0 → 2.7.2
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/dist/.tsbuildinfo +1 -1
- package/dist/generators/template-generator.d.ts.map +1 -1
- package/dist/generators/template-generator.js +18 -12
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/shared/auth/firebase/web/src/lib/auth-session.ts +25 -0
- package/dist/templates/shared/auth/keycloak/web/src/lib/auth-session.ts +24 -0
- package/dist/templates/shared/auth/supabase/web/src/lib/auth-session.ts +37 -0
- package/dist/templates/shared/config/web/next.config.mjs +1 -0
- package/dist/templates/shared/contact/web/{app → src/app}/api/contact/route.ts +4 -4
- package/{src/templates/shared/database/supabase/web → dist/templates/shared/database/supabase/web/src}/lib/supabase/server.ts +1 -1
- package/dist/templates/shared/loading/web/src/app/loading.tsx +9 -0
- package/dist/templates/shared/payments/web/{app → src/app}/api/webhooks/stripe/route.ts +1 -1
- package/{src/templates/shared/security/web → dist/templates/shared/security/web/src}/lib/api-security.ts +7 -3
- package/dist/templates/web/ai-platform/template/middleware.ts +55 -55
- package/dist/templates/web/ai-platform/template/src/lib/supabase/server.ts +27 -27
- package/dist/templates/web/iot-dashboard/template/middleware.ts +56 -56
- package/dist/templates/web/iot-dashboard/template/src/lib/supabase/server.ts +27 -27
- package/dist/templates/web/marketplace/template/middleware.ts +56 -56
- package/dist/templates/web/marketplace/template/src/lib/supabase/server.ts +27 -27
- package/dist/templates/web/micro-saas/template/middleware.ts +1 -1
- package/dist/templates/web/micro-saas/template/src/lib/supabase/server.ts +29 -29
- package/dist/templates/web/ui-auth-ai/template/package.json +1 -3
- package/dist/templates/web/ui-auth-ai/template/src/app/error.tsx +75 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/loading.tsx +39 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +4 -7
- package/package.json +1 -1
- package/src/templates/shared/auth/firebase/web/src/lib/auth-session.ts +25 -0
- package/src/templates/shared/auth/keycloak/web/src/lib/auth-session.ts +24 -0
- package/src/templates/shared/auth/supabase/web/src/lib/auth-session.ts +37 -0
- package/src/templates/shared/config/web/next.config.mjs +1 -0
- package/src/templates/shared/contact/web/{app → src/app}/api/contact/route.ts +4 -4
- package/{dist/templates/shared/database/supabase/web → src/templates/shared/database/supabase/web/src}/lib/supabase/server.ts +1 -1
- package/src/templates/shared/loading/web/src/app/loading.tsx +9 -0
- package/src/templates/shared/payments/web/{app → src/app}/api/webhooks/stripe/route.ts +1 -1
- package/{dist/templates/shared/security/web → src/templates/shared/security/web/src}/lib/api-security.ts +7 -3
- package/src/templates/web/ai-platform/template/middleware.ts +55 -55
- package/src/templates/web/ai-platform/template/src/lib/supabase/server.ts +27 -27
- package/src/templates/web/iot-dashboard/template/middleware.ts +56 -56
- package/src/templates/web/iot-dashboard/template/src/lib/supabase/server.ts +27 -27
- package/src/templates/web/marketplace/template/middleware.ts +56 -56
- package/src/templates/web/marketplace/template/src/lib/supabase/server.ts +27 -27
- package/src/templates/web/micro-saas/template/middleware.ts +1 -1
- package/src/templates/web/micro-saas/template/src/lib/supabase/server.ts +29 -29
- package/src/templates/web/ui-auth-ai/template/package.json +1 -3
- package/src/templates/web/ui-auth-ai/template/src/app/error.tsx +75 -0
- package/src/templates/web/ui-auth-ai/template/src/app/loading.tsx +39 -0
- package/src/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +4 -7
- package/dist/templates/shared/loading/web/app/loading.tsx +0 -5
- package/dist/templates/web/base/template.backup/.env.example +0 -15
- package/dist/templates/web/ui-auth/template.backup/.env.example +0 -15
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx.backup +0 -391
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx.bak +0 -391
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx.backup +0 -391
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx.bak +0 -391
- package/dist/templates/web/ui-only/template.backup/.env.example +0 -15
- package/src/templates/shared/loading/web/app/loading.tsx +0 -5
- /package/dist/templates/shared/admin/web/{app → src/app}/admin/layout.tsx +0 -0
- /package/dist/templates/shared/audit/web/{lib → src/lib}/audit.ts +0 -0
- /package/dist/templates/shared/auth/keycloak/web/{app → src/app}/api/auth/federated-logout/route.ts +0 -0
- /package/dist/templates/shared/beta/web/{app → src/app}/api/beta-settings/route.ts +0 -0
- /package/dist/templates/shared/beta/web/{app → src/app}/api/validate-beta-code/route.ts +0 -0
- /package/dist/templates/shared/beta/web/{lib → src/lib}/beta/settings.ts +0 -0
- /package/dist/templates/shared/cache/web/{lib → src/lib}/cache.ts +0 -0
- /package/dist/templates/shared/config/web/{lib → src/lib}/config.ts +0 -0
- /package/dist/templates/shared/contact/web/{app → src/app}/contact/page.tsx +0 -0
- /package/dist/templates/shared/database/postgresql/web/{lib → src/lib}/db/drizzle.ts +0 -0
- /package/dist/templates/shared/database/postgresql/web/{lib → src/lib}/db/schema.ts +0 -0
- /package/dist/templates/shared/database/supabase/web/{lib → src/lib}/supabase/client.ts +0 -0
- /package/dist/templates/shared/database/supabase/web/{lib → src/lib}/supabase/service.ts +0 -0
- /package/dist/templates/shared/email/web/{lib → src/lib}/email/branding.ts +0 -0
- /package/dist/templates/shared/email/web/{lib → src/lib}/email/client.ts +0 -0
- /package/dist/templates/shared/error-pages/web/{app → src/app}/error.tsx +0 -0
- /package/dist/templates/shared/error-pages/web/{app → src/app}/global-error.tsx +0 -0
- /package/dist/templates/shared/error-pages/web/{app → src/app}/not-found.tsx +0 -0
- /package/dist/templates/shared/health/web/{app → src/app}/api/health/route.ts +0 -0
- /package/dist/templates/shared/legal/web/{app → src/app}/(legal)/privacy/page.tsx +0 -0
- /package/dist/templates/shared/legal/web/{app → src/app}/(legal)/terms/page.tsx +0 -0
- /package/dist/templates/shared/legal/web/{lib → src/lib}/legal-config.ts +0 -0
- /package/dist/templates/shared/observability/web/{lib → src/lib}/observability.ts +0 -0
- /package/dist/templates/shared/platform/web/{lib → src/lib}/platform.ts +0 -0
- /package/dist/templates/shared/redis/web/{lib → src/lib}/rate-limit-store.ts +0 -0
- /package/dist/templates/shared/redis/web/{lib → src/lib}/redis.ts +0 -0
- /package/dist/templates/shared/seo/web/{app → src/app}/api/og/route.tsx +0 -0
- /package/dist/templates/shared/seo/web/{app → src/app}/robots.ts +0 -0
- /package/dist/templates/shared/seo/web/{app → src/app}/sitemap.ts +0 -0
- /package/dist/templates/shared/utils/web/{lib → src/lib}/api-response.ts +0 -0
- /package/dist/templates/shared/utils/web/{lib → src/lib}/utils.ts +0 -0
- /package/src/templates/shared/admin/web/{app → src/app}/admin/layout.tsx +0 -0
- /package/src/templates/shared/audit/web/{lib → src/lib}/audit.ts +0 -0
- /package/src/templates/shared/auth/keycloak/web/{app → src/app}/api/auth/federated-logout/route.ts +0 -0
- /package/src/templates/shared/beta/web/{app → src/app}/api/beta-settings/route.ts +0 -0
- /package/src/templates/shared/beta/web/{app → src/app}/api/validate-beta-code/route.ts +0 -0
- /package/src/templates/shared/beta/web/{lib → src/lib}/beta/settings.ts +0 -0
- /package/src/templates/shared/cache/web/{lib → src/lib}/cache.ts +0 -0
- /package/src/templates/shared/config/web/{lib → src/lib}/config.ts +0 -0
- /package/src/templates/shared/contact/web/{app → src/app}/contact/page.tsx +0 -0
- /package/src/templates/shared/database/postgresql/web/{lib → src/lib}/db/drizzle.ts +0 -0
- /package/src/templates/shared/database/postgresql/web/{lib → src/lib}/db/schema.ts +0 -0
- /package/src/templates/shared/database/supabase/web/{lib → src/lib}/supabase/client.ts +0 -0
- /package/src/templates/shared/database/supabase/web/{lib → src/lib}/supabase/service.ts +0 -0
- /package/src/templates/shared/email/web/{lib → src/lib}/email/branding.ts +0 -0
- /package/src/templates/shared/email/web/{lib → src/lib}/email/client.ts +0 -0
- /package/src/templates/shared/error-pages/web/{app → src/app}/error.tsx +0 -0
- /package/src/templates/shared/error-pages/web/{app → src/app}/global-error.tsx +0 -0
- /package/src/templates/shared/error-pages/web/{app → src/app}/not-found.tsx +0 -0
- /package/src/templates/shared/health/web/{app → src/app}/api/health/route.ts +0 -0
- /package/src/templates/shared/legal/web/{app → src/app}/(legal)/privacy/page.tsx +0 -0
- /package/src/templates/shared/legal/web/{app → src/app}/(legal)/terms/page.tsx +0 -0
- /package/src/templates/shared/legal/web/{lib → src/lib}/legal-config.ts +0 -0
- /package/src/templates/shared/observability/web/{lib → src/lib}/observability.ts +0 -0
- /package/src/templates/shared/platform/web/{lib → src/lib}/platform.ts +0 -0
- /package/src/templates/shared/redis/web/{lib → src/lib}/rate-limit-store.ts +0 -0
- /package/src/templates/shared/redis/web/{lib → src/lib}/redis.ts +0 -0
- /package/src/templates/shared/seo/web/{app → src/app}/api/og/route.tsx +0 -0
- /package/src/templates/shared/seo/web/{app → src/app}/robots.ts +0 -0
- /package/src/templates/shared/seo/web/{app → src/app}/sitemap.ts +0 -0
- /package/src/templates/shared/utils/web/{lib → src/lib}/api-response.ts +0 -0
- /package/src/templates/shared/utils/web/{lib → src/lib}/utils.ts +0 -0
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
import { createServerClient } from '@supabase/ssr'
|
|
2
|
-
import { NextResponse, type NextRequest } from 'next/server'
|
|
3
|
-
|
|
4
|
-
export async function middleware(request: NextRequest) {
|
|
5
|
-
let supabaseResponse = NextResponse.next({
|
|
6
|
-
request,
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
const supabase = createServerClient(
|
|
10
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
11
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
12
|
-
{
|
|
13
|
-
cookies: {
|
|
14
|
-
getAll() {
|
|
15
|
-
return request.cookies.getAll()
|
|
16
|
-
},
|
|
17
|
-
setAll(cookiesToSet) {
|
|
18
|
-
cookiesToSet.forEach(({ name, value }) =>
|
|
19
|
-
request.cookies.set(name, value)
|
|
20
|
-
)
|
|
21
|
-
supabaseResponse = NextResponse.next({
|
|
22
|
-
request,
|
|
23
|
-
})
|
|
24
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
25
|
-
supabaseResponse.cookies.set(name, value, options)
|
|
26
|
-
)
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
const {
|
|
33
|
-
data: { user },
|
|
34
|
-
} = await supabase.auth.getUser()
|
|
35
|
-
|
|
36
|
-
// Redirect to login if accessing protected route without auth
|
|
37
|
-
if (
|
|
38
|
-
!user &&
|
|
39
|
-
(request.nextUrl.pathname.startsWith('/dashboard') ||
|
|
40
|
-
request.nextUrl.pathname.startsWith('/devices') ||
|
|
41
|
-
request.nextUrl.pathname.startsWith('/analytics') ||
|
|
42
|
-
request.nextUrl.pathname.startsWith('/alerts'))
|
|
43
|
-
) {
|
|
44
|
-
const url = request.nextUrl.clone()
|
|
45
|
-
url.pathname = '/login'
|
|
46
|
-
return NextResponse.redirect(url)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return supabaseResponse
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const config = {
|
|
53
|
-
matcher: [
|
|
54
|
-
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
|
|
55
|
-
],
|
|
56
|
-
}
|
|
1
|
+
import { createServerClient } from '@supabase/ssr'
|
|
2
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
3
|
+
|
|
4
|
+
export async function middleware(request: NextRequest) {
|
|
5
|
+
let supabaseResponse = NextResponse.next({
|
|
6
|
+
request,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
const supabase = createServerClient(
|
|
10
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
11
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
12
|
+
{
|
|
13
|
+
cookies: {
|
|
14
|
+
getAll() {
|
|
15
|
+
return request.cookies.getAll()
|
|
16
|
+
},
|
|
17
|
+
setAll(cookiesToSet: Array<{ name: string; value: string; options?: Record<string, unknown> }>) {
|
|
18
|
+
cookiesToSet.forEach(({ name, value }) =>
|
|
19
|
+
request.cookies.set(name, value)
|
|
20
|
+
)
|
|
21
|
+
supabaseResponse = NextResponse.next({
|
|
22
|
+
request,
|
|
23
|
+
})
|
|
24
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
25
|
+
supabaseResponse.cookies.set(name, value, options)
|
|
26
|
+
)
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const {
|
|
33
|
+
data: { user },
|
|
34
|
+
} = await supabase.auth.getUser()
|
|
35
|
+
|
|
36
|
+
// Redirect to login if accessing protected route without auth
|
|
37
|
+
if (
|
|
38
|
+
!user &&
|
|
39
|
+
(request.nextUrl.pathname.startsWith('/dashboard') ||
|
|
40
|
+
request.nextUrl.pathname.startsWith('/devices') ||
|
|
41
|
+
request.nextUrl.pathname.startsWith('/analytics') ||
|
|
42
|
+
request.nextUrl.pathname.startsWith('/alerts'))
|
|
43
|
+
) {
|
|
44
|
+
const url = request.nextUrl.clone()
|
|
45
|
+
url.pathname = '/login'
|
|
46
|
+
return NextResponse.redirect(url)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return supabaseResponse
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const config = {
|
|
53
|
+
matcher: [
|
|
54
|
+
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
|
|
55
|
+
],
|
|
56
|
+
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { createServerClient } from '@supabase/ssr'
|
|
2
|
-
import { cookies } from 'next/headers'
|
|
3
|
-
|
|
4
|
-
export async function createClient() {
|
|
5
|
-
const cookieStore = await cookies()
|
|
6
|
-
|
|
7
|
-
return createServerClient(
|
|
8
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
9
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
10
|
-
{
|
|
11
|
-
cookies: {
|
|
12
|
-
getAll() {
|
|
13
|
-
return cookieStore.getAll()
|
|
14
|
-
},
|
|
15
|
-
setAll(cookiesToSet) {
|
|
16
|
-
try {
|
|
17
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
18
|
-
cookieStore.set(name, value, options)
|
|
19
|
-
)
|
|
20
|
-
} catch {
|
|
21
|
-
// Server Component context
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
)
|
|
27
|
-
}
|
|
1
|
+
import { createServerClient } from '@supabase/ssr'
|
|
2
|
+
import { cookies } from 'next/headers'
|
|
3
|
+
|
|
4
|
+
export async function createClient() {
|
|
5
|
+
const cookieStore = await cookies()
|
|
6
|
+
|
|
7
|
+
return createServerClient(
|
|
8
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
9
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
10
|
+
{
|
|
11
|
+
cookies: {
|
|
12
|
+
getAll() {
|
|
13
|
+
return cookieStore.getAll()
|
|
14
|
+
},
|
|
15
|
+
setAll(cookiesToSet: Array<{ name: string; value: string; options?: Record<string, unknown> }>) {
|
|
16
|
+
try {
|
|
17
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
18
|
+
cookieStore.set(name, value, options)
|
|
19
|
+
)
|
|
20
|
+
} catch {
|
|
21
|
+
// Server Component context
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
import { createServerClient } from '@supabase/ssr'
|
|
2
|
-
import { NextResponse, type NextRequest } from 'next/server'
|
|
3
|
-
|
|
4
|
-
export async function middleware(request: NextRequest) {
|
|
5
|
-
let supabaseResponse = NextResponse.next({
|
|
6
|
-
request,
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
const supabase = createServerClient(
|
|
10
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
11
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
12
|
-
{
|
|
13
|
-
cookies: {
|
|
14
|
-
getAll() {
|
|
15
|
-
return request.cookies.getAll()
|
|
16
|
-
},
|
|
17
|
-
setAll(cookiesToSet) {
|
|
18
|
-
cookiesToSet.forEach(({ name, value }) =>
|
|
19
|
-
request.cookies.set(name, value)
|
|
20
|
-
)
|
|
21
|
-
supabaseResponse = NextResponse.next({
|
|
22
|
-
request,
|
|
23
|
-
})
|
|
24
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
25
|
-
supabaseResponse.cookies.set(name, value, options)
|
|
26
|
-
)
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
const {
|
|
33
|
-
data: { user },
|
|
34
|
-
} = await supabase.auth.getUser()
|
|
35
|
-
|
|
36
|
-
// Redirect to login if accessing protected route without auth
|
|
37
|
-
if (
|
|
38
|
-
!user &&
|
|
39
|
-
(request.nextUrl.pathname.startsWith('/dashboard') ||
|
|
40
|
-
request.nextUrl.pathname.startsWith('/products/new') ||
|
|
41
|
-
request.nextUrl.pathname.startsWith('/orders') ||
|
|
42
|
-
request.nextUrl.pathname.startsWith('/payouts'))
|
|
43
|
-
) {
|
|
44
|
-
const url = request.nextUrl.clone()
|
|
45
|
-
url.pathname = '/login'
|
|
46
|
-
return NextResponse.redirect(url)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return supabaseResponse
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const config = {
|
|
53
|
-
matcher: [
|
|
54
|
-
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
|
|
55
|
-
],
|
|
56
|
-
}
|
|
1
|
+
import { createServerClient } from '@supabase/ssr'
|
|
2
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
3
|
+
|
|
4
|
+
export async function middleware(request: NextRequest) {
|
|
5
|
+
let supabaseResponse = NextResponse.next({
|
|
6
|
+
request,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
const supabase = createServerClient(
|
|
10
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
11
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
12
|
+
{
|
|
13
|
+
cookies: {
|
|
14
|
+
getAll() {
|
|
15
|
+
return request.cookies.getAll()
|
|
16
|
+
},
|
|
17
|
+
setAll(cookiesToSet: Array<{ name: string; value: string; options?: Record<string, unknown> }>) {
|
|
18
|
+
cookiesToSet.forEach(({ name, value }) =>
|
|
19
|
+
request.cookies.set(name, value)
|
|
20
|
+
)
|
|
21
|
+
supabaseResponse = NextResponse.next({
|
|
22
|
+
request,
|
|
23
|
+
})
|
|
24
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
25
|
+
supabaseResponse.cookies.set(name, value, options)
|
|
26
|
+
)
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const {
|
|
33
|
+
data: { user },
|
|
34
|
+
} = await supabase.auth.getUser()
|
|
35
|
+
|
|
36
|
+
// Redirect to login if accessing protected route without auth
|
|
37
|
+
if (
|
|
38
|
+
!user &&
|
|
39
|
+
(request.nextUrl.pathname.startsWith('/dashboard') ||
|
|
40
|
+
request.nextUrl.pathname.startsWith('/products/new') ||
|
|
41
|
+
request.nextUrl.pathname.startsWith('/orders') ||
|
|
42
|
+
request.nextUrl.pathname.startsWith('/payouts'))
|
|
43
|
+
) {
|
|
44
|
+
const url = request.nextUrl.clone()
|
|
45
|
+
url.pathname = '/login'
|
|
46
|
+
return NextResponse.redirect(url)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return supabaseResponse
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const config = {
|
|
53
|
+
matcher: [
|
|
54
|
+
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
|
|
55
|
+
],
|
|
56
|
+
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { createServerClient } from '@supabase/ssr'
|
|
2
|
-
import { cookies } from 'next/headers'
|
|
3
|
-
|
|
4
|
-
export async function createClient() {
|
|
5
|
-
const cookieStore = await cookies()
|
|
6
|
-
|
|
7
|
-
return createServerClient(
|
|
8
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
9
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
10
|
-
{
|
|
11
|
-
cookies: {
|
|
12
|
-
getAll() {
|
|
13
|
-
return cookieStore.getAll()
|
|
14
|
-
},
|
|
15
|
-
setAll(cookiesToSet) {
|
|
16
|
-
try {
|
|
17
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
18
|
-
cookieStore.set(name, value, options)
|
|
19
|
-
)
|
|
20
|
-
} catch {
|
|
21
|
-
// Server Component context
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
)
|
|
27
|
-
}
|
|
1
|
+
import { createServerClient } from '@supabase/ssr'
|
|
2
|
+
import { cookies } from 'next/headers'
|
|
3
|
+
|
|
4
|
+
export async function createClient() {
|
|
5
|
+
const cookieStore = await cookies()
|
|
6
|
+
|
|
7
|
+
return createServerClient(
|
|
8
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
9
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
10
|
+
{
|
|
11
|
+
cookies: {
|
|
12
|
+
getAll() {
|
|
13
|
+
return cookieStore.getAll()
|
|
14
|
+
},
|
|
15
|
+
setAll(cookiesToSet: Array<{ name: string; value: string; options?: Record<string, unknown> }>) {
|
|
16
|
+
try {
|
|
17
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
18
|
+
cookieStore.set(name, value, options)
|
|
19
|
+
)
|
|
20
|
+
} catch {
|
|
21
|
+
// Server Component context
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -14,7 +14,7 @@ export async function middleware(request: NextRequest) {
|
|
|
14
14
|
getAll() {
|
|
15
15
|
return request.cookies.getAll()
|
|
16
16
|
},
|
|
17
|
-
setAll(cookiesToSet) {
|
|
17
|
+
setAll(cookiesToSet: Array<{ name: string; value: string; options?: Record<string, unknown> }>) {
|
|
18
18
|
cookiesToSet.forEach(({ name, value }) =>
|
|
19
19
|
request.cookies.set(name, value)
|
|
20
20
|
)
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { createServerClient } from '@supabase/ssr'
|
|
2
|
-
import { cookies } from 'next/headers'
|
|
3
|
-
|
|
4
|
-
export async function createClient() {
|
|
5
|
-
const cookieStore = await cookies()
|
|
6
|
-
|
|
7
|
-
return createServerClient(
|
|
8
|
-
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
9
|
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
10
|
-
{
|
|
11
|
-
cookies: {
|
|
12
|
-
getAll() {
|
|
13
|
-
return cookieStore.getAll()
|
|
14
|
-
},
|
|
15
|
-
setAll(cookiesToSet) {
|
|
16
|
-
try {
|
|
17
|
-
cookiesToSet.forEach(({ name, value, options }) =>
|
|
18
|
-
cookieStore.set(name, value, options)
|
|
19
|
-
)
|
|
20
|
-
} catch {
|
|
21
|
-
// The `setAll` method was called from a Server Component.
|
|
22
|
-
// This can be ignored if you have middleware refreshing
|
|
23
|
-
// user sessions.
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
)
|
|
29
|
-
}
|
|
1
|
+
import { createServerClient } from '@supabase/ssr'
|
|
2
|
+
import { cookies } from 'next/headers'
|
|
3
|
+
|
|
4
|
+
export async function createClient() {
|
|
5
|
+
const cookieStore = await cookies()
|
|
6
|
+
|
|
7
|
+
return createServerClient(
|
|
8
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
9
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
10
|
+
{
|
|
11
|
+
cookies: {
|
|
12
|
+
getAll() {
|
|
13
|
+
return cookieStore.getAll()
|
|
14
|
+
},
|
|
15
|
+
setAll(cookiesToSet: Array<{ name: string; value: string; options?: Record<string, unknown> }>) {
|
|
16
|
+
try {
|
|
17
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
18
|
+
cookieStore.set(name, value, options)
|
|
19
|
+
)
|
|
20
|
+
} catch {
|
|
21
|
+
// The `setAll` method was called from a Server Component.
|
|
22
|
+
// This can be ignored if you have middleware refreshing
|
|
23
|
+
// user sessions.
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -18,9 +18,7 @@
|
|
|
18
18
|
"clsx": "^2.0.0",
|
|
19
19
|
"tailwindcss": "^3.3.0",
|
|
20
20
|
"autoprefixer": "^10.4.16",
|
|
21
|
-
"postcss": "^8.4.31"
|
|
22
|
-
"@digilogiclabs/saas-factory-ai": "^4.0.2",
|
|
23
|
-
"@digilogiclabs/saas-factory-ai-types": "^4.0.2"{{/ai.enabled}}
|
|
21
|
+
"postcss": "^8.4.31"
|
|
24
22
|
},
|
|
25
23
|
"devDependencies": {
|
|
26
24
|
"@types/node": "^20.0.0",
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react'
|
|
4
|
+
import { Button, Card } from '@digilogiclabs/saas-factory-ui'
|
|
5
|
+
import { AlertTriangle, RefreshCw, Home } from 'lucide-react'
|
|
6
|
+
import Link from 'next/link'
|
|
7
|
+
|
|
8
|
+
interface ErrorProps {
|
|
9
|
+
error: Error & { digest?: string }
|
|
10
|
+
reset: () => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default function Error({ error, reset }: ErrorProps) {
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
console.error('Application error:', error)
|
|
16
|
+
}, [error])
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="min-h-screen bg-gradient-to-br from-red-50 to-orange-100 dark:from-slate-900 dark:to-slate-800 flex items-center justify-center p-4">
|
|
20
|
+
<Card className="p-8 max-w-lg w-full">
|
|
21
|
+
<div className="flex flex-col items-center space-y-6 text-center">
|
|
22
|
+
<div className="w-16 h-16 bg-red-100 dark:bg-red-900 rounded-full flex items-center justify-center">
|
|
23
|
+
<AlertTriangle className="w-8 h-8 text-red-600 dark:text-red-400" />
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div>
|
|
27
|
+
<h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
|
|
28
|
+
Something went wrong!
|
|
29
|
+
</h1>
|
|
30
|
+
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
31
|
+
We encountered an unexpected error. This has been logged and our team will look into it.
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
{process.env.NODE_ENV === 'development' && (
|
|
35
|
+
<details className="mt-4 text-left">
|
|
36
|
+
<summary className="cursor-pointer text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
|
|
37
|
+
Error details (development only)
|
|
38
|
+
</summary>
|
|
39
|
+
<div className="mt-2 p-3 bg-gray-100 dark:bg-gray-800 rounded text-xs font-mono text-gray-700 dark:text-gray-300 overflow-auto max-h-40">
|
|
40
|
+
<div className="mb-2">
|
|
41
|
+
<strong>Message:</strong> {error.message}
|
|
42
|
+
</div>
|
|
43
|
+
{error.digest && (
|
|
44
|
+
<div className="mb-2">
|
|
45
|
+
<strong>Digest:</strong> {error.digest}
|
|
46
|
+
</div>
|
|
47
|
+
)}
|
|
48
|
+
{error.stack && (
|
|
49
|
+
<div>
|
|
50
|
+
<strong>Stack:</strong>
|
|
51
|
+
<pre className="whitespace-pre-wrap mt-1">{error.stack}</pre>
|
|
52
|
+
</div>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
</details>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div className="flex flex-col sm:flex-row gap-3 w-full">
|
|
60
|
+
<Button onClick={reset} className="flex-1" size="lg">
|
|
61
|
+
<RefreshCw className="w-4 h-4 mr-2" />
|
|
62
|
+
Try again
|
|
63
|
+
</Button>
|
|
64
|
+
<Link href="/" className="flex-1">
|
|
65
|
+
<Button variant="outline" className="w-full" size="lg">
|
|
66
|
+
<Home className="w-4 h-4 mr-2" />
|
|
67
|
+
Go home
|
|
68
|
+
</Button>
|
|
69
|
+
</Link>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</Card>
|
|
73
|
+
</div>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Card, SkeletonCard, SkeletonText } from '@digilogiclabs/saas-factory-ui'
|
|
2
|
+
|
|
3
|
+
export default function Loading() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800">
|
|
6
|
+
<div className="max-w-4xl mx-auto px-4 py-16">
|
|
7
|
+
{/* Header skeleton */}
|
|
8
|
+
<div className="flex justify-end mb-8">
|
|
9
|
+
<SkeletonText className="h-8 w-24" />
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
{/* Hero skeleton */}
|
|
13
|
+
<div className="text-center mb-16">
|
|
14
|
+
<SkeletonText className="h-6 w-32 mx-auto mb-6" />
|
|
15
|
+
<SkeletonText className="h-12 w-64 mx-auto mb-6" />
|
|
16
|
+
<SkeletonText className="h-6 w-96 mx-auto mb-8" />
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
{/* Feature cards skeleton */}
|
|
20
|
+
<div className="grid md:grid-cols-3 gap-6 mb-16">
|
|
21
|
+
{Array.from({ length: 3 }).map((_, i) => (
|
|
22
|
+
<SkeletonCard key={i} />
|
|
23
|
+
))}
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
{/* CTA skeleton */}
|
|
27
|
+
<Card className="p-8">
|
|
28
|
+
<div className="flex flex-col items-center space-y-4">
|
|
29
|
+
<div className="relative">
|
|
30
|
+
<div className="w-12 h-12 border-4 border-gray-200 dark:border-gray-700 rounded-full animate-spin"></div>
|
|
31
|
+
<div className="absolute top-0 left-0 w-12 h-12 border-4 border-blue-600 border-t-transparent rounded-full animate-spin"></div>
|
|
32
|
+
</div>
|
|
33
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Loading...</p>
|
|
34
|
+
</div>
|
|
35
|
+
</Card>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
)
|
|
39
|
+
}
|
package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { ThemeProvider } from 'next-themes'
|
|
5
|
-
import { DLLProvider } from '@digilogiclabs/app-sdk'
|
|
6
5
|
import { Toaster } from '@digilogiclabs/saas-factory-ui'
|
|
7
6
|
import { AppThemeProvider } from './theme-provider'
|
|
8
7
|
|
|
@@ -19,12 +18,10 @@ export function AppProviders({ children }: AppProvidersProps) {
|
|
|
19
18
|
disableTransitionOnChange
|
|
20
19
|
storageKey="{{packageName}}-theme"
|
|
21
20
|
>
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</AppThemeProvider>
|
|
27
|
-
</DLLProvider>
|
|
21
|
+
<AppThemeProvider themeColor="{{themeColor}}">
|
|
22
|
+
{children}
|
|
23
|
+
<Toaster />
|
|
24
|
+
</AppThemeProvider>
|
|
28
25
|
</ThemeProvider>
|
|
29
26
|
)
|
|
30
27
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth session adapter for Firebase.
|
|
3
|
+
* Provides a consistent getSession() interface for api-security.ts.
|
|
4
|
+
*/
|
|
5
|
+
import 'server-only';
|
|
6
|
+
|
|
7
|
+
type Session = {
|
|
8
|
+
user?: {
|
|
9
|
+
id?: string;
|
|
10
|
+
email?: string | null;
|
|
11
|
+
name?: string | null;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export async function getSession(): Promise<Session | null> {
|
|
16
|
+
// Firebase server-side auth is typically handled via admin SDK
|
|
17
|
+
// or by verifying the ID token from cookies.
|
|
18
|
+
// Implement based on your Firebase setup.
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function getUser() {
|
|
23
|
+
const session = await getSession();
|
|
24
|
+
return session?.user ?? null;
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth session adapter for Keycloak (Auth.js).
|
|
3
|
+
* Provides a consistent getSession() interface for api-security.ts.
|
|
4
|
+
*/
|
|
5
|
+
import 'server-only';
|
|
6
|
+
|
|
7
|
+
type Session = {
|
|
8
|
+
user?: {
|
|
9
|
+
id?: string;
|
|
10
|
+
email?: string | null;
|
|
11
|
+
name?: string | null;
|
|
12
|
+
roles?: string[];
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function getSession(): Promise<Session | null> {
|
|
17
|
+
const { auth } = await import('@/auth');
|
|
18
|
+
return auth();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function getUser() {
|
|
22
|
+
const session = await getSession();
|
|
23
|
+
return session?.user ?? null;
|
|
24
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth session adapter for Supabase.
|
|
3
|
+
* Provides a consistent getSession() interface for api-security.ts.
|
|
4
|
+
*/
|
|
5
|
+
import 'server-only';
|
|
6
|
+
import { createClient } from '@/lib/supabase/server';
|
|
7
|
+
|
|
8
|
+
type Session = {
|
|
9
|
+
user?: {
|
|
10
|
+
id?: string;
|
|
11
|
+
email?: string | null;
|
|
12
|
+
name?: string | null;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function getSession(): Promise<Session | null> {
|
|
17
|
+
const supabase = await createClient();
|
|
18
|
+
const {
|
|
19
|
+
data: { user },
|
|
20
|
+
error,
|
|
21
|
+
} = await supabase.auth.getUser();
|
|
22
|
+
|
|
23
|
+
if (error || !user) return null;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
user: {
|
|
27
|
+
id: user.id,
|
|
28
|
+
email: user.email ?? null,
|
|
29
|
+
name: user.user_metadata?.name ?? user.user_metadata?.full_name ?? null,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function getUser() {
|
|
35
|
+
const session = await getSession();
|
|
36
|
+
return session?.user ?? null;
|
|
37
|
+
}
|
|
@@ -48,6 +48,7 @@ const nextConfig = {
|
|
|
48
48
|
// Stub main barrel only — subpaths like /auth and /security-headers
|
|
49
49
|
// are Edge-safe and must NOT be stubbed.
|
|
50
50
|
'@digilogiclabs/platform-core$': false,
|
|
51
|
+
'@digilogiclabs/app-sdk$': false,
|
|
51
52
|
'ioredis$': false,
|
|
52
53
|
'pg$': false,
|
|
53
54
|
'nodemailer$': false,
|