@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.
- package/dist/lib/services/team.service.d.ts.map +1 -1
- package/dist/lib/services/team.service.js +4 -1
- package/dist/styles/classes.json +1 -1
- package/dist/templates/app/api/auth/[...all]/route.ts +16 -4
- package/dist/templates/app/api/v1/teams/route.ts +7 -2
- package/package.json +2 -2
- package/templates/app/api/auth/[...all]/route.ts +16 -4
- package/templates/app/api/v1/teams/route.ts +7 -2
|
@@ -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;
|
|
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
|
-
|
|
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
|
);
|
package/dist/styles/classes.json
CHANGED
|
@@ -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;
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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;
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
|
|
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
|
-
|
|
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
|
|