@nextsparkjs/core 0.1.0-beta.56 → 0.1.0-beta.58

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 (48) hide show
  1. package/dist/styles/classes.json +1 -1
  2. package/dist/templates/app/api/csp-report/route.ts +6 -75
  3. package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +2 -2
  4. package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +2 -2
  5. package/dist/templates/app/api/v1/billing/cancel/route.ts +5 -2
  6. package/dist/templates/app/api/v1/billing/change-plan/route.ts +5 -2
  7. package/dist/templates/app/api/v1/billing/check-action/route.ts +5 -2
  8. package/dist/templates/app/api/v1/billing/checkout/route.ts +5 -2
  9. package/dist/templates/app/api/v1/billing/portal/route.ts +5 -2
  10. package/dist/templates/app/api/v1/teams/[teamId]/invitations/route.ts +4 -4
  11. package/dist/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +2 -2
  12. package/dist/templates/app/api/v1/teams/[teamId]/invoices/route.ts +2 -2
  13. package/dist/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +4 -4
  14. package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +4 -4
  15. package/dist/templates/app/api/v1/teams/[teamId]/route.ts +6 -6
  16. package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +2 -2
  17. package/dist/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +4 -4
  18. package/dist/templates/app/api/v1/teams/route.ts +4 -4
  19. package/dist/templates/app/api/v1/teams/switch/route.ts +2 -2
  20. package/dist/templates/app/dashboard/(main)/patterns/page.tsx +1 -1
  21. package/dist/templates/app/globals.css +8 -5
  22. package/dist/templates/contents/themes/starter/config/features.config.ts +156 -0
  23. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/patterns.cy.ts +19 -19
  24. package/package.json +1 -1
  25. package/scripts/build/registry.mjs +7 -0
  26. package/scripts/build/theme.mjs +18 -14
  27. package/templates/app/api/csp-report/route.ts +6 -75
  28. package/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +2 -2
  29. package/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +2 -2
  30. package/templates/app/api/v1/billing/cancel/route.ts +5 -2
  31. package/templates/app/api/v1/billing/change-plan/route.ts +5 -2
  32. package/templates/app/api/v1/billing/check-action/route.ts +5 -2
  33. package/templates/app/api/v1/billing/checkout/route.ts +5 -2
  34. package/templates/app/api/v1/billing/portal/route.ts +5 -2
  35. package/templates/app/api/v1/teams/[teamId]/invitations/route.ts +4 -4
  36. package/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +2 -2
  37. package/templates/app/api/v1/teams/[teamId]/invoices/route.ts +2 -2
  38. package/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +4 -4
  39. package/templates/app/api/v1/teams/[teamId]/members/route.ts +4 -4
  40. package/templates/app/api/v1/teams/[teamId]/route.ts +6 -6
  41. package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +2 -2
  42. package/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +4 -4
  43. package/templates/app/api/v1/teams/route.ts +4 -4
  44. package/templates/app/api/v1/teams/switch/route.ts +2 -2
  45. package/templates/app/dashboard/(main)/patterns/page.tsx +1 -1
  46. package/templates/app/globals.css +8 -5
  47. package/templates/contents/themes/starter/config/features.config.ts +156 -0
  48. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/patterns.cy.ts +19 -19
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-01-20T12:53:37.046Z",
2
+ "generated": "2026-01-20T16:36:54.178Z",
3
3
  "totalClasses": 1047,
4
4
  "classes": [
5
5
  "!text-2xl",
@@ -1,34 +1,12 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
- // Dynamic import for rate limiting - graceful fallback if not available
5
- let checkDistributedRateLimit: ((id: string, tier: string) => Promise<{ allowed: boolean; limit: number; remaining: number; resetTime: number; retryAfter?: number }>) | null = null;
6
- let createRateLimitErrorResponse: ((result: { allowed: boolean; limit: number; remaining: number; resetTime: number; retryAfter?: number }) => NextResponse) | null = null;
7
-
8
- // Try to load rate limiting functions
9
- try {
10
- const rateLimitModule = require('@nextsparkjs/core/lib/api');
11
- checkDistributedRateLimit = rateLimitModule.checkDistributedRateLimit;
12
- createRateLimitErrorResponse = rateLimitModule.createRateLimitErrorResponse;
13
- } catch {
14
- // Rate limiting not available - will skip rate limit checks
15
- console.warn('[CSP Report] Rate limiting not available - running without rate limits');
16
- }
17
-
18
4
  /**
19
5
  * CSP Violation Report Endpoint
20
6
  *
21
7
  * Receives Content-Security-Policy violation reports from browsers.
22
8
  * Reports are logged for monitoring and debugging CSP issues.
23
9
  *
24
- * Rate limiting: Uses 'api' tier (100 requests/minute per IP) to prevent abuse.
25
- * Falls back gracefully if rate limiting is not available.
26
- *
27
- * NOTE: This file exists in both apps/dev/app/api/csp-report/ and
28
- * packages/core/templates/app/api/csp-report/. The template version
29
- * is used when creating new projects from the core package.
30
- * Changes should be synchronized between both files.
31
- *
32
10
  * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#violation_report_syntax
33
11
  */
34
12
 
@@ -54,52 +32,8 @@ const getAllowedOrigin = () => {
54
32
  return process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000';
55
33
  };
56
34
 
57
- /**
58
- * Get client IP address from request headers.
59
- * Handles various proxy scenarios (X-Forwarded-For, X-Real-IP, etc.)
60
- */
61
- function getClientIp(request: NextRequest): string {
62
- const forwardedFor = request.headers.get('x-forwarded-for');
63
- if (forwardedFor) {
64
- const ips = forwardedFor.split(',').map(ip => ip.trim());
65
- if (ips[0]) return ips[0];
66
- }
67
- const realIp = request.headers.get('x-real-ip');
68
- if (realIp) return realIp;
69
- const cfIp = request.headers.get('cf-connecting-ip');
70
- if (cfIp) return cfIp;
71
- return 'unknown';
72
- }
73
-
74
35
  export async function POST(request: NextRequest) {
75
36
  const requestId = randomUUID().slice(0, 8);
76
- let rateLimitHeaders: Record<string, string> = {};
77
-
78
- // Rate limiting: 100 requests per minute per IP (api tier)
79
- // Skip if rate limiting is not available
80
- if (checkDistributedRateLimit && createRateLimitErrorResponse) {
81
- try {
82
- const clientIp = getClientIp(request);
83
- const rateLimitResult = await checkDistributedRateLimit(`csp-report:ip:${clientIp}`, 'api');
84
-
85
- if (!rateLimitResult.allowed) {
86
- console.warn(`[CSP Report ${requestId}] Rate limit exceeded for IP: ${clientIp}`);
87
- return createRateLimitErrorResponse(rateLimitResult);
88
- }
89
-
90
- // Store rate limit headers to include in response
91
- rateLimitHeaders = {
92
- 'X-RateLimit-Limit': rateLimitResult.limit.toString(),
93
- 'X-RateLimit-Remaining': rateLimitResult.remaining.toString(),
94
- 'X-RateLimit-Reset': rateLimitResult.resetTime.toString(),
95
- };
96
- } catch (rateLimitError) {
97
- // Log but continue without rate limiting
98
- console.warn(`[CSP Report ${requestId}] Rate limit check failed, continuing without:`, {
99
- error: rateLimitError instanceof Error ? rateLimitError.message : 'Unknown error',
100
- });
101
- }
102
- }
103
37
 
104
38
  try {
105
39
  const contentType = request.headers.get('content-type') || '';
@@ -107,7 +41,7 @@ export async function POST(request: NextRequest) {
107
41
  // CSP reports are sent as application/csp-report or application/json
108
42
  if (!contentType.includes('application/csp-report') && !contentType.includes('application/json')) {
109
43
  console.warn(`[CSP Report ${requestId}] Invalid content-type: ${contentType}`);
110
- return new Response('Invalid content type', { status: 400 });
44
+ return new NextResponse('Invalid content type', { status: 400 });
111
45
  }
112
46
 
113
47
  let rawBody: string | undefined;
@@ -120,7 +54,7 @@ export async function POST(request: NextRequest) {
120
54
  console.warn(`[CSP Report ${requestId}] Invalid report format - missing csp-report key`, {
121
55
  bodyPreview: rawBody.slice(0, 200),
122
56
  });
123
- return new Response('Invalid report format', { status: 400 });
57
+ return new NextResponse('Invalid report format', { status: 400 });
124
58
  }
125
59
 
126
60
  // Log the violation for monitoring
@@ -139,17 +73,14 @@ export async function POST(request: NextRequest) {
139
73
  });
140
74
 
141
75
  // Return 204 No Content - browsers don't expect a response body
142
- return new Response(null, {
143
- status: 204,
144
- headers: rateLimitHeaders,
145
- });
76
+ return new NextResponse(null, { status: 204 });
146
77
  } catch (parseError) {
147
78
  console.error(`[CSP Report ${requestId}] JSON parse error:`, {
148
79
  error: parseError instanceof Error ? parseError.message : 'Unknown error',
149
80
  bodyPreview: rawBody?.slice(0, 200),
150
81
  });
151
82
  // Still return 204 to not break browser behavior
152
- return new Response(null, { status: 204 });
83
+ return new NextResponse(null, { status: 204 });
153
84
  }
154
85
  } catch (error) {
155
86
  console.error(`[CSP Report ${requestId}] Unexpected error:`, {
@@ -157,14 +88,14 @@ export async function POST(request: NextRequest) {
157
88
  stack: error instanceof Error ? error.stack : undefined,
158
89
  });
159
90
  // Still return 204 to not break browser behavior
160
- return new Response(null, { status: 204 });
91
+ return new NextResponse(null, { status: 204 });
161
92
  }
162
93
  }
163
94
 
164
95
  // Handle preflight requests for CORS
165
96
  // Restrict to same origin instead of allowing all origins
166
97
  export async function OPTIONS() {
167
- return new Response(null, {
98
+ return new NextResponse(null, {
168
99
  status: 204,
169
100
  headers: {
170
101
  'Access-Control-Allow-Origin': getAllowedOrigin(),
@@ -25,7 +25,7 @@ interface RouteParams {
25
25
  export const PUT = withRateLimitTier(async (
26
26
  request: NextRequest,
27
27
  { params }: { params: Promise<RouteParams> }
28
- ) {
28
+ ) => {
29
29
  const { entity, id, childType, childId } = await params
30
30
 
31
31
  try {
@@ -150,7 +150,7 @@ export const PUT = withRateLimitTier(async (
150
150
  export const DELETE = withRateLimitTier(async (
151
151
  request: NextRequest,
152
152
  { params }: { params: Promise<RouteParams> }
153
- ) {
153
+ ) => {
154
154
  try {
155
155
  const { entity, id, childType, childId } = await params
156
156
 
@@ -25,7 +25,7 @@ interface RouteParams {
25
25
  export const GET = withRateLimitTier(async (
26
26
  request: NextRequest,
27
27
  { params }: { params: Promise<RouteParams> }
28
- ) {
28
+ ) => {
29
29
  const { entity, id, childType } = await params
30
30
 
31
31
  try {
@@ -90,7 +90,7 @@ export const GET = withRateLimitTier(async (
90
90
  export const POST = withRateLimitTier(async (
91
91
  request: NextRequest,
92
92
  { params }: { params: Promise<RouteParams> }
93
- ) {
93
+ ) => {
94
94
  const { entity, id, childType } = await params
95
95
 
96
96
  try {
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { NextRequest, NextResponse } from 'next/server'
11
11
  import { z } from 'zod'
12
- import { authenticateRequest, createAuthError } from '@nextsparkjs/core/lib/api/auth/dual-auth'
12
+ import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
13
13
  import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
14
14
  import {
15
15
  cancelSubscriptionAtPeriodEnd,
@@ -37,7 +37,10 @@ export const POST = withRateLimitTier(async (request: NextRequest) => {
37
37
  const authResult = await authenticateRequest(request)
38
38
 
39
39
  if (!authResult.success || !authResult.user) {
40
- return createAuthError('Unauthorized', 401)
40
+ return NextResponse.json(
41
+ { success: false, error: 'Unauthorized' },
42
+ { status: 401 }
43
+ )
41
44
  }
42
45
 
43
46
  // 2. Get team context
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { NextRequest, NextResponse } from 'next/server'
11
11
  import { z } from 'zod'
12
- import { authenticateRequest, createAuthError } from '@nextsparkjs/core/lib/api/auth/dual-auth'
12
+ import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
13
13
  import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
14
14
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
15
15
 
@@ -31,7 +31,10 @@ export const POST = withRateLimitTier(async (request: NextRequest) => {
31
31
  const authResult = await authenticateRequest(request)
32
32
 
33
33
  if (!authResult.success || !authResult.user) {
34
- return createAuthError('Unauthorized', 401)
34
+ return NextResponse.json(
35
+ { success: false, error: 'Unauthorized' },
36
+ { status: 401 }
37
+ )
35
38
  }
36
39
 
37
40
  // 2. Get team context
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { NextRequest, NextResponse } from 'next/server'
13
- import { authenticateRequest, createAuthError } from '@nextsparkjs/core/lib/api/auth/dual-auth'
13
+ import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
14
14
  import { MembershipService } from '@nextsparkjs/core/lib/services'
15
15
  import { z } from 'zod'
16
16
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
@@ -25,7 +25,10 @@ export const POST = withRateLimitTier(async (request: NextRequest) => {
25
25
  const authResult = await authenticateRequest(request)
26
26
 
27
27
  if (!authResult.success || !authResult.user) {
28
- return createAuthError('Unauthorized', 401)
28
+ return NextResponse.json(
29
+ { success: false, error: 'Unauthorized' },
30
+ { status: 401 }
31
+ )
29
32
  }
30
33
 
31
34
  // 2. Parse and validate request body
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { NextRequest, NextResponse } from 'next/server'
13
- import { authenticateRequest, createAuthError } from '@nextsparkjs/core/lib/api/auth/dual-auth'
13
+ import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
14
14
  import { createCheckoutSession } from '@nextsparkjs/core/lib/billing/gateways/stripe'
15
15
  import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
16
16
  import { z } from 'zod'
@@ -26,7 +26,10 @@ export const POST = withRateLimitTier(async (request: NextRequest) => {
26
26
  const authResult = await authenticateRequest(request)
27
27
 
28
28
  if (!authResult.success || !authResult.user) {
29
- return createAuthError('Unauthorized', 401)
29
+ return NextResponse.json(
30
+ { success: false, error: 'Unauthorized' },
31
+ { status: 401 }
32
+ )
30
33
  }
31
34
 
32
35
  // 2. Parse and validate request body
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { NextRequest, NextResponse } from 'next/server'
11
- import { authenticateRequest, createAuthError } from '@nextsparkjs/core/lib/api/auth/dual-auth'
11
+ import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
12
12
  import { createPortalSession } from '@nextsparkjs/core/lib/billing/gateways/stripe'
13
13
  import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
14
14
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
@@ -18,7 +18,10 @@ export const POST = withRateLimitTier(async (request: NextRequest) => {
18
18
  const authResult = await authenticateRequest(request)
19
19
 
20
20
  if (!authResult.success || !authResult.user) {
21
- return createAuthError('Unauthorized', 401)
21
+ return NextResponse.json(
22
+ { success: false, error: 'Unauthorized' },
23
+ { status: 401 }
24
+ )
22
25
  }
23
26
 
24
27
  // 2. Get team context
@@ -19,7 +19,7 @@ export async function OPTIONS() {
19
19
  }
20
20
 
21
21
  // GET /api/v1/teams/:teamId/invitations - List pending invitations for a team
22
- export const GET = withRateLimitTier('read', withApiLogging(
22
+ export const GET = withRateLimitTier(withApiLogging(
23
23
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
24
24
  try {
25
25
  // Authenticate using dual auth
@@ -99,10 +99,10 @@ export const GET = withRateLimitTier('read', withApiLogging(
99
99
  return addCorsHeaders(response)
100
100
  }
101
101
  }
102
- ))
102
+ ), 'read')
103
103
 
104
104
  // DELETE /api/v1/teams/:teamId/invitations/:invitationId - Cancel/revoke an invitation
105
- export const DELETE = withRateLimitTier('write', withApiLogging(
105
+ export const DELETE = withRateLimitTier(withApiLogging(
106
106
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
107
107
  try {
108
108
  // Authenticate using dual auth
@@ -169,4 +169,4 @@ export const DELETE = withRateLimitTier('write', withApiLogging(
169
169
  return addCorsHeaders(response)
170
170
  }
171
171
  }
172
- ))
172
+ ), 'write')
@@ -18,7 +18,7 @@ export async function OPTIONS() {
18
18
  }
19
19
 
20
20
  // GET /api/v1/teams/:teamId/invoices/:invoiceNumber - Get single invoice (owner only)
21
- export const GET = withRateLimitTier('read', withApiLogging(
21
+ export const GET = withRateLimitTier(withApiLogging(
22
22
  async (
23
23
  req: NextRequest,
24
24
  { params }: { params: Promise<{ teamId: string; invoiceNumber: string }> }
@@ -103,4 +103,4 @@ export const GET = withRateLimitTier('read', withApiLogging(
103
103
  return addCorsHeaders(response)
104
104
  }
105
105
  }
106
- ))
106
+ ), 'read')
@@ -20,7 +20,7 @@ export async function OPTIONS() {
20
20
  }
21
21
 
22
22
  // GET /api/v1/teams/:teamId/invoices - List team invoices (owner only)
23
- export const GET = withRateLimitTier('read', withApiLogging(
23
+ export const GET = withRateLimitTier(withApiLogging(
24
24
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
25
25
  try {
26
26
  // Authenticate using dual auth (API key OR session)
@@ -123,4 +123,4 @@ export const GET = withRateLimitTier('read', withApiLogging(
123
123
  return addCorsHeaders(response)
124
124
  }
125
125
  }
126
- ))
126
+ ), 'read')
@@ -20,7 +20,7 @@ export async function OPTIONS() {
20
20
  }
21
21
 
22
22
  // PATCH /api/v1/teams/:teamId/members/:memberId - Update member role
23
- export const PATCH = withRateLimitTier('write', withApiLogging(
23
+ export const PATCH = withRateLimitTier(withApiLogging(
24
24
  async (
25
25
  req: NextRequest,
26
26
  { params }: { params: Promise<{ teamId: string; memberId: string }> }
@@ -156,10 +156,10 @@ export const PATCH = withRateLimitTier('write', withApiLogging(
156
156
  return addCorsHeaders(response)
157
157
  }
158
158
  }
159
- ))
159
+ ), 'write')
160
160
 
161
161
  // DELETE /api/v1/teams/:teamId/members/:memberId - Remove member from team
162
- export const DELETE = withRateLimitTier('write', withApiLogging(
162
+ export const DELETE = withRateLimitTier(withApiLogging(
163
163
  async (
164
164
  req: NextRequest,
165
165
  { params }: { params: Promise<{ teamId: string; memberId: string }> }
@@ -261,4 +261,4 @@ export const DELETE = withRateLimitTier('write', withApiLogging(
261
261
  return addCorsHeaders(response)
262
262
  }
263
263
  }
264
- ))
264
+ ), 'write')
@@ -37,7 +37,7 @@ export async function OPTIONS() {
37
37
  }
38
38
 
39
39
  // GET /api/v1/teams/:teamId/members - List team members
40
- export const GET = withRateLimitTier('read', withApiLogging(
40
+ export const GET = withRateLimitTier(withApiLogging(
41
41
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
42
42
  try {
43
43
  // Authenticate using dual auth
@@ -159,10 +159,10 @@ export const GET = withRateLimitTier('read', withApiLogging(
159
159
  return addCorsHeaders(response)
160
160
  }
161
161
  }
162
- ))
162
+ ), 'read')
163
163
 
164
164
  // POST /api/v1/teams/:teamId/members - Invite new member (creates invitation)
165
- export const POST = withRateLimitTier('write', withApiLogging(
165
+ export const POST = withRateLimitTier(withApiLogging(
166
166
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
167
167
  try {
168
168
  // Authenticate using dual auth
@@ -355,4 +355,4 @@ export const POST = withRateLimitTier('write', withApiLogging(
355
355
  return addCorsHeaders(response)
356
356
  }
357
357
  }
358
- ))
358
+ ), 'write')
@@ -19,7 +19,7 @@ export async function OPTIONS() {
19
19
  }
20
20
 
21
21
  // GET /api/v1/teams/:teamId - Get team details
22
- export const GET = withRateLimitTier('read', withApiLogging(
22
+ export const GET = withRateLimitTier(withApiLogging(
23
23
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
24
24
  try {
25
25
  // Authenticate using dual auth
@@ -88,10 +88,10 @@ export const GET = withRateLimitTier('read', withApiLogging(
88
88
  return addCorsHeaders(response)
89
89
  }
90
90
  }
91
- ))
91
+ ), 'read')
92
92
 
93
93
  // PATCH /api/v1/teams/:teamId - Update team (owners/admins only)
94
- export const PATCH = withRateLimitTier('write', withApiLogging(
94
+ export const PATCH = withRateLimitTier(withApiLogging(
95
95
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
96
96
  try {
97
97
  // Authenticate using dual auth
@@ -229,10 +229,10 @@ export const PATCH = withRateLimitTier('write', withApiLogging(
229
229
  return addCorsHeaders(response)
230
230
  }
231
231
  }
232
- ))
232
+ ), 'write')
233
233
 
234
234
  // DELETE /api/v1/teams/:teamId - Delete team (owners only, NOT personal teams)
235
- export const DELETE = withRateLimitTier('write', withApiLogging(
235
+ export const DELETE = withRateLimitTier(withApiLogging(
236
236
  async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
237
237
  try {
238
238
  // Authenticate using dual auth
@@ -292,4 +292,4 @@ export const DELETE = withRateLimitTier('write', withApiLogging(
292
292
  return addCorsHeaders(response)
293
293
  }
294
294
  }
295
- ))
295
+ ), 'write')
@@ -13,7 +13,7 @@ interface RouteParams {
13
13
  params: Promise<{ teamId: string }>
14
14
  }
15
15
 
16
- export const GET = withRateLimitTier('read', async function GET(request: NextRequest, props: RouteParams) {
16
+ export const GET = withRateLimitTier(async function GET(request: NextRequest, props: RouteParams) {
17
17
  // Authenticate request
18
18
  const { auth, rateLimitResponse } = await validateAndAuthenticateRequest(request)
19
19
  if (rateLimitResponse) return rateLimitResponse
@@ -48,4 +48,4 @@ export const GET = withRateLimitTier('read', async function GET(request: NextReq
48
48
  console.error('[Billing API] Error fetching subscription:', error)
49
49
  return createApiError('Failed to fetch subscription', 500)
50
50
  }
51
- })
51
+ }, 'read')
@@ -15,7 +15,7 @@ interface RouteParams {
15
15
  params: Promise<{ teamId: string; limitSlug: string }>
16
16
  }
17
17
 
18
- export const GET = withRateLimitTier('read', async function GET(request: NextRequest, props: RouteParams) {
18
+ export const GET = withRateLimitTier(async function GET(request: NextRequest, props: RouteParams) {
19
19
  // Authenticate request
20
20
  const { auth, rateLimitResponse } = await validateAndAuthenticateRequest(request)
21
21
  if (rateLimitResponse) return rateLimitResponse
@@ -45,9 +45,9 @@ export const GET = withRateLimitTier('read', async function GET(request: NextReq
45
45
  console.error('[Billing API] Error checking quota:', error)
46
46
  return createApiError('Failed to check quota', 500)
47
47
  }
48
- })
48
+ }, 'read')
49
49
 
50
- export const POST = withRateLimitTier('write', async function POST(request: NextRequest, props: RouteParams) {
50
+ export const POST = withRateLimitTier(async function POST(request: NextRequest, props: RouteParams) {
51
51
  // Authenticate request
52
52
  const { auth, rateLimitResponse } = await validateAndAuthenticateRequest(request)
53
53
  if (rateLimitResponse) return rateLimitResponse
@@ -89,4 +89,4 @@ export const POST = withRateLimitTier('write', async function POST(request: Next
89
89
  const errorMessage = error instanceof Error ? error.message : 'Failed to track usage'
90
90
  return createApiError(errorMessage, 500)
91
91
  }
92
- })
92
+ }, 'write')
@@ -22,7 +22,7 @@ export async function OPTIONS() {
22
22
  }
23
23
 
24
24
  // GET /api/v1/teams - List user's teams
25
- export const GET = withRateLimitTier('read', withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
25
+ export const GET = withRateLimitTier(withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
26
26
  try {
27
27
  // Authenticate using dual auth
28
28
  const authResult = await authenticateRequest(req)
@@ -161,10 +161,10 @@ export const GET = withRateLimitTier('read', withApiLogging(async (req: NextRequ
161
161
  const response = createApiError('Internal server error', 500)
162
162
  return addCorsHeaders(response)
163
163
  }
164
- }))
164
+ }), 'read')
165
165
 
166
166
  // POST /api/v1/teams - Create new team
167
- export const POST = withRateLimitTier('write', withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
167
+ export const POST = withRateLimitTier(withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
168
168
  try {
169
169
  // Authenticate using dual auth
170
170
  const authResult = await authenticateRequest(req)
@@ -291,4 +291,4 @@ export const POST = withRateLimitTier('write', withApiLogging(async (req: NextRe
291
291
  const response = createApiError('Internal server error', 500)
292
292
  return addCorsHeaders(response)
293
293
  }
294
- }))
294
+ }), 'write')
@@ -21,7 +21,7 @@ export async function OPTIONS() {
21
21
  }
22
22
 
23
23
  // POST /api/v1/teams/switch - Switch active team context
24
- export const POST = withRateLimitTier('write', withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
24
+ export const POST = withRateLimitTier(withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
25
25
  try {
26
26
  // Authenticate using dual auth
27
27
  const authResult = await authenticateRequest(req)
@@ -86,4 +86,4 @@ export const POST = withRateLimitTier('write', withApiLogging(async (req: NextRe
86
86
  const response = createApiError('Internal server error', 500)
87
87
  return addCorsHeaders(response)
88
88
  }
89
- }))
89
+ }), 'write')
@@ -42,7 +42,7 @@ export default function PatternsListPage() {
42
42
  const router = useRouter()
43
43
 
44
44
  // Use the new centralized hook for entity configuration
45
- const { config: entityConfig, isLoading, error: configError, isOverride } = useEntityConfig(entityType)
45
+ const { config: entityConfig, isLoading, error: configError } = useEntityConfig(entityType)
46
46
 
47
47
  // Get current team for relation resolution
48
48
  const { teamId } = useTeam()
@@ -1,12 +1,15 @@
1
1
  /* =============================================
2
2
  GLOBAL STYLES - Import from Active Theme
3
3
 
4
- Este archivo importa los estilos del theme activo.
5
- NO editar directamente - todos los estilos están en:
4
+ This file imports styles from the active theme.
5
+ DO NOT edit directly - all styles are in:
6
6
  contents/themes/{theme}/styles/globals.css
7
7
 
8
- Para personalizar colores, tipografía y tokens, edita
9
- el archivo globals.css de tu theme activo.
8
+ This import is AUTO-SYNCED by the registry build process
9
+ to match NEXT_PUBLIC_ACTIVE_THEME from your .env file.
10
+
11
+ To customize colors, typography and tokens, edit
12
+ the globals.css file in your active theme.
10
13
  ============================================= */
11
14
 
12
- @import "../contents/themes/default/styles/globals.css";
15
+ @import "../contents/themes/starter/styles/globals.css";