@nextsparkjs/core 0.1.0-beta.171 → 0.1.0-beta.173

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.
@@ -1 +1 @@
1
- {"version":3,"file":"team.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/team.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAOpD,MAAM,WAAW,mBAAoB,SAAQ,IAAI;IAC/C,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI;IAC3C,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAMD,qBAAa,WAAW;IAKtB;;;;;;;;;OASG;WACU,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAY3E;;;;;;;;OAQG;WACU,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW1D;;;;;;;;OAQG;WACU,SAAS,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAO9C;;;;;;;;OAQG;WACU,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAK1C;;;;;;;;OAQG;WACU,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA2CrE;;;;;;;;;OASG;WACU,kBAAkB,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IA2BtC;;;;;;;;OAQG;WACU,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7C,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KACrB,GAAG,IAAI,CAAC;IAmBT;;;;;;;;OAQG;WACU,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgB1D;;;;;;;;;;OAUG;WACU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsEjE;;;;;;;;;;OAUG;WACU,MAAM,CACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IA+DhB;;;;;;;;;OASG;WACU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoClE;;;;;;;;;OASG;WACU,eAAe,CAC1B,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC;IAoBnB;;;;;;;;;OASG;WACU,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmC5D;;;;;;;;;;OAUG;WACU,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB3E;;;;;;;;OAQG;WACU,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAYtD"}
1
+ {"version":3,"file":"team.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/team.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAOpD,MAAM,WAAW,mBAAoB,SAAQ,IAAI;IAC/C,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI;IAC3C,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAMD,qBAAa,WAAW;IAKtB;;;;;;;;;OASG;WACU,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAY3E;;;;;;;;OAQG;WACU,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW1D;;;;;;;;OAQG;WACU,SAAS,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAO9C;;;;;;;;OAQG;WACU,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAK1C;;;;;;;;OAQG;WACU,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA2CrE;;;;;;;;;OASG;WACU,kBAAkB,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IA2BtC;;;;;;;;OAQG;WACU,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7C,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KACrB,GAAG,IAAI,CAAC;IAmBT;;;;;;;;OAQG;WACU,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgB1D;;;;;;;;;;OAUG;WACU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsEjE;;;;;;;;;;OAUG;WACU,MAAM,CACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IA+DhB;;;;;;;;;OASG;WACU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoClE;;;;;;;;;OASG;WACU,eAAe,CAC1B,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC;IAoBnB;;;;;;;;;OASG;WACU,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmC5D;;;;;;;;;;OAUG;WACU,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0B3E;;;;;;;;OAQG;WACU,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAYtD"}
@@ -410,7 +410,10 @@ class TeamService {
410
410
  throw new Error("User ID and Team ID are required");
411
411
  }
412
412
  const member = await queryOneWithRLS(
413
- 'SELECT id FROM "team_members" WHERE "teamId" = $1 AND "userId" = $2',
413
+ `SELECT tm.id
414
+ FROM "team_members" tm
415
+ INNER JOIN "teams" t ON t.id = tm."teamId"
416
+ WHERE tm."teamId" = $1 AND tm."userId" = $2 AND t."deletedAt" IS NULL`,
414
417
  [teamId, userId],
415
418
  userId
416
419
  );
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-06-22T20:21:00.466Z",
2
+ "generated": "2026-06-23T13:21:29.773Z",
3
3
  "totalClasses": 1081,
4
4
  "classes": [
5
5
  "!text-2xl",
@@ -115,6 +115,13 @@ export async function POST(req: NextRequest) {
115
115
  const isOAuthCallback = pathname.includes('/api/auth/callback/');
116
116
  const isSignupRequest = isSignupAttempt || isOAuthCallback;
117
117
 
118
+ // A first-time OTP sign-in (emailOTP plugin with disableSignUp:false) auto-creates
119
+ // the user, so it is an implicit signup that can also carry an intent. It is a
120
+ // sign-in endpoint, so it is deliberately NOT part of `isSignupRequest` above
121
+ // (no registration-mode gating) — it only participates in the intent wrapping
122
+ // below, exactly like header/OAuth signup.
123
+ const isOtpSignin = pathname.includes('/sign-in/email-otp');
124
+
118
125
  if (isSignupRequest) {
119
126
  const registrationMode = AUTH_CONFIG?.registration?.mode ?? 'open';
120
127
  const teamsMode = TEAMS_CONFIG.mode;
@@ -160,10 +167,15 @@ export async function POST(req: NextRequest) {
160
167
  // Read the optional signup intent and run the signup within request-scoped
161
168
  // context so the user.create.after hook can map it to an initial team role
162
169
  // (AUTH_CONFIG.signupIntent). Header-based signup carries it in the
163
- // `x-signup-intent` header; OAuth callbacks (incl. form_post-mode providers
164
- // that POST the callback) can't, so they fall back to the `signup-intent`
165
- // cookie set by the client before the OAuth flow (see the GET handler).
166
- const signupIntent = isSignupAttempt
170
+ // `x-signup-intent` header; a first-time OTP sign-in carries it the same way
171
+ // (header preferred, `signup-intent` cookie fallback); OAuth callbacks (incl.
172
+ // form_post-mode providers that POST the callback) can't send a header, so
173
+ // they fall back to the cookie set by the client before the OAuth flow (see
174
+ // the GET handler). The value only ever maps to an app-configured role via
175
+ // roleMap (never an arbitrary role) and the user.create.after hook runs only
176
+ // when a user is actually created, so wrapping an existing-user sign-in is a
177
+ // no-op — there is no escalation surface.
178
+ const signupIntent = (isSignupAttempt || isOtpSignin)
167
179
  ? (req.headers.get('x-signup-intent') || req.cookies.get('signup-intent')?.value || undefined)
168
180
  : isOAuthCallback
169
181
  ? (req.cookies.get('signup-intent')?.value || undefined)
@@ -66,8 +66,13 @@ export const GET = withRateLimitTier(withApiLogging(async (req: NextRequest): Pr
66
66
  }
67
67
 
68
68
  // Build WHERE clause based on filters
69
- // If scope=all (superadmin), don't filter by user
70
- let whereClause = requestAllTeams ? 'WHERE 1=1' : 'WHERE tm."userId" = $1'
69
+ // If scope=all (superadmin), don't filter by user.
70
+ // For a user's own list, exclude soft-deleted teams: a member (e.g. the former
71
+ // owner of a discarded personal team) keeps their team_members row, so without
72
+ // this filter a stale active-team pointer to a deleted team resurfaces in the
73
+ // list and the client team resolver (which matches on membership, not deletedAt)
74
+ // re-selects it. scope=all stays unfiltered so admins can still see deleted teams.
75
+ let whereClause = requestAllTeams ? 'WHERE 1=1' : 'WHERE tm."userId" = $1 AND t."deletedAt" IS NULL'
71
76
  const queryValues: unknown[] = requestAllTeams ? [] : [authResult.user!.id]
72
77
  let paramCount = requestAllTeams ? 1 : 2
73
78
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/core",
3
- "version": "0.1.0-beta.171",
3
+ "version": "0.1.0-beta.173",
4
4
  "description": "NextSpark - The complete SaaS framework for Next.js",
5
5
  "license": "MIT",
6
6
  "author": "NextSpark <hello@nextspark.dev>",
@@ -469,7 +469,7 @@
469
469
  "tailwind-merge": "^3.3.1",
470
470
  "uuid": "^13.0.0",
471
471
  "zod": "^4.1.5",
472
- "@nextsparkjs/testing": "0.1.0-beta.171"
472
+ "@nextsparkjs/testing": "0.1.0-beta.173"
473
473
  },
474
474
  "scripts": {
475
475
  "postinstall": "node scripts/postinstall.mjs || true",
@@ -115,6 +115,13 @@ export async function POST(req: NextRequest) {
115
115
  const isOAuthCallback = pathname.includes('/api/auth/callback/');
116
116
  const isSignupRequest = isSignupAttempt || isOAuthCallback;
117
117
 
118
+ // A first-time OTP sign-in (emailOTP plugin with disableSignUp:false) auto-creates
119
+ // the user, so it is an implicit signup that can also carry an intent. It is a
120
+ // sign-in endpoint, so it is deliberately NOT part of `isSignupRequest` above
121
+ // (no registration-mode gating) — it only participates in the intent wrapping
122
+ // below, exactly like header/OAuth signup.
123
+ const isOtpSignin = pathname.includes('/sign-in/email-otp');
124
+
118
125
  if (isSignupRequest) {
119
126
  const registrationMode = AUTH_CONFIG?.registration?.mode ?? 'open';
120
127
  const teamsMode = TEAMS_CONFIG.mode;
@@ -160,10 +167,15 @@ export async function POST(req: NextRequest) {
160
167
  // Read the optional signup intent and run the signup within request-scoped
161
168
  // context so the user.create.after hook can map it to an initial team role
162
169
  // (AUTH_CONFIG.signupIntent). Header-based signup carries it in the
163
- // `x-signup-intent` header; OAuth callbacks (incl. form_post-mode providers
164
- // that POST the callback) can't, so they fall back to the `signup-intent`
165
- // cookie set by the client before the OAuth flow (see the GET handler).
166
- const signupIntent = isSignupAttempt
170
+ // `x-signup-intent` header; a first-time OTP sign-in carries it the same way
171
+ // (header preferred, `signup-intent` cookie fallback); OAuth callbacks (incl.
172
+ // form_post-mode providers that POST the callback) can't send a header, so
173
+ // they fall back to the cookie set by the client before the OAuth flow (see
174
+ // the GET handler). The value only ever maps to an app-configured role via
175
+ // roleMap (never an arbitrary role) and the user.create.after hook runs only
176
+ // when a user is actually created, so wrapping an existing-user sign-in is a
177
+ // no-op — there is no escalation surface.
178
+ const signupIntent = (isSignupAttempt || isOtpSignin)
167
179
  ? (req.headers.get('x-signup-intent') || req.cookies.get('signup-intent')?.value || undefined)
168
180
  : isOAuthCallback
169
181
  ? (req.cookies.get('signup-intent')?.value || undefined)
@@ -66,8 +66,13 @@ export const GET = withRateLimitTier(withApiLogging(async (req: NextRequest): Pr
66
66
  }
67
67
 
68
68
  // Build WHERE clause based on filters
69
- // If scope=all (superadmin), don't filter by user
70
- let whereClause = requestAllTeams ? 'WHERE 1=1' : 'WHERE tm."userId" = $1'
69
+ // If scope=all (superadmin), don't filter by user.
70
+ // For a user's own list, exclude soft-deleted teams: a member (e.g. the former
71
+ // owner of a discarded personal team) keeps their team_members row, so without
72
+ // this filter a stale active-team pointer to a deleted team resurfaces in the
73
+ // list and the client team resolver (which matches on membership, not deletedAt)
74
+ // re-selects it. scope=all stays unfiltered so admins can still see deleted teams.
75
+ let whereClause = requestAllTeams ? 'WHERE 1=1' : 'WHERE tm."userId" = $1 AND t."deletedAt" IS NULL'
71
76
  const queryValues: unknown[] = requestAllTeams ? [] : [authResult.user!.id]
72
77
  let paramCount = requestAllTeams ? 1 : 2
73
78