@nextsparkjs/core 0.1.0-beta.154 → 0.1.0-beta.155

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.
@@ -89,6 +89,24 @@ export declare function isSuperadmin(userRole: UserRole): boolean;
89
89
  * @returns True if action is allowed, false otherwise
90
90
  */
91
91
  export declare function canManageRole(actorRole: string, targetRole: string): boolean;
92
+ /**
93
+ * Check if a role can invite another role to the team
94
+ *
95
+ * Reads hierarchy from the merged permissions registry, so any roles added
96
+ * by consumers via additional config are supported automatically.
97
+ *
98
+ * Semantics: invitation is allowed when the actor's hierarchy level is
99
+ * greater than or equal to the target's hierarchy level. Peers can invite
100
+ * peers (e.g. admin → admin); a lower-ranked actor cannot invite a
101
+ * higher-ranked target.
102
+ *
103
+ * Missing hierarchy entries are treated as 0, mirroring canManageRole.
104
+ *
105
+ * @param actorRole - The role of the user issuing the invitation
106
+ * @param targetRole - The role the invitee would receive
107
+ * @returns True if the invitation is allowed, false otherwise
108
+ */
109
+ export declare function canInviteToRole(actorRole: string, targetRole: string): boolean;
92
110
  /**
93
111
  * Get human-readable role description
94
112
  *
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/lib/teams/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAUH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,WAAW,GACX,aAAa,GACb,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,0BAA0B,GAC1B,oBAAoB,GACpB,oBAAoB,GACpB,mBAAmB,GACnB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAAc,EAYhD,CAAA;AAuCD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAgC,CAAA;AAM7F;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,cAAc,EAC1B,aAAa,GAAE,OAAe,GAC7B,OAAO,CAWT;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,OAAe,GAC7B,cAAc,EAAE,CAQlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,cAAc,GACzB,OAAO,CAcT;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAExD;AAMD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAKT;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvD;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAI5C;AAMD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA0BvC"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/lib/teams/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAUH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,WAAW,GACX,aAAa,GACb,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,0BAA0B,GAC1B,oBAAoB,GACpB,oBAAoB,GACpB,mBAAmB,GACnB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAAc,EAYhD,CAAA;AAuCD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAgC,CAAA;AAM7F;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,cAAc,EAC1B,aAAa,GAAE,OAAe,GAC7B,OAAO,CAWT;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,OAAe,GAC7B,cAAc,EAAE,CAQlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,cAAc,GACzB,OAAO,CAcT;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAExD;AAMD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAKT;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAIT;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvD;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAI5C;AAMD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA0BvC"}
@@ -63,6 +63,10 @@ function canManageRole(actorRole, targetRole) {
63
63
  const hierarchy = getHierarchyFromRegistry();
64
64
  return (hierarchy[actorRole] ?? 0) > (hierarchy[targetRole] ?? 0);
65
65
  }
66
+ function canInviteToRole(actorRole, targetRole) {
67
+ const hierarchy = getHierarchyFromRegistry();
68
+ return (hierarchy[actorRole] ?? 0) >= (hierarchy[targetRole] ?? 0);
69
+ }
66
70
  function getRoleDescription(role) {
67
71
  const descriptions = getDescriptionsFromRegistry();
68
72
  return descriptions[role] ?? "No description available";
@@ -97,6 +101,7 @@ function validateRoleTransition(fromRole, toRole, actorRole) {
97
101
  }
98
102
  export {
99
103
  ALL_TEAM_PERMISSIONS,
104
+ canInviteToRole,
100
105
  canManageRole,
101
106
  checkTeamPermission,
102
107
  getInvitableRoles,
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-05-27T00:35:24.358Z",
2
+ "generated": "2026-05-27T12:11:22.327Z",
3
3
  "totalClasses": 1080,
4
4
  "classes": [
5
5
  "!text-2xl",
@@ -14,24 +14,12 @@ import { checkRateLimit, withRateLimitTier } from '@nextsparkjs/core/lib/api/rat
14
14
  import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
15
15
  import { inviteMemberSchema, memberListQuerySchema } from '@nextsparkjs/core/lib/teams/schema'
16
16
  import { TeamMemberService, MembershipService } from '@nextsparkjs/core/lib/services'
17
+ import { canInviteToRole } from '@nextsparkjs/core/lib/teams/permissions'
17
18
  import type { TeamMember, TeamInvitation, TeamRole, Team } from '@nextsparkjs/core/lib/teams/types'
18
19
  import { EmailFactory } from '@nextsparkjs/core/lib/email/factory'
19
20
  import { sendTeamInvitationEmail } from '@nextsparkjs/core/lib/email/send'
20
21
  import { I18N_CONFIG } from '@nextsparkjs/core/lib/config'
21
22
 
22
- // Role hierarchy for invite validation (higher number = more power)
23
- const ROLE_HIERARCHY: Record<TeamRole, number> = {
24
- owner: 4,
25
- admin: 3,
26
- member: 2,
27
- viewer: 1,
28
- }
29
-
30
- // Check if a user can invite to a specific role (same level or below)
31
- function canInviteToRole(actorRole: TeamRole, targetRole: TeamRole): boolean {
32
- return ROLE_HIERARCHY[actorRole] >= ROLE_HIERARCHY[targetRole]
33
- }
34
-
35
23
  // Handle CORS preflight
36
24
  export async function OPTIONS() {
37
25
  return handleCorsPreflightRequest()
@@ -226,7 +214,8 @@ export const POST = withRateLimitTier(withApiLogging(
226
214
  const body = await req.json()
227
215
  const validatedData = inviteMemberSchema.parse(body)
228
216
 
229
- // Check role hierarchy - users can only invite to same role or below
217
+ // Check role hierarchy via the merged permissions registry users can
218
+ // only invite to roles at the same level or below their own
230
219
  if (!canInviteToRole(userRole, validatedData.role)) {
231
220
  const response = createApiError(
232
221
  `You cannot invite members to a role higher than your own. Your role: ${userRole}, requested role: ${validatedData.role}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/core",
3
- "version": "0.1.0-beta.154",
3
+ "version": "0.1.0-beta.155",
4
4
  "description": "NextSpark - The complete SaaS framework for Next.js",
5
5
  "license": "MIT",
6
6
  "author": "NextSpark <hello@nextspark.dev>",
@@ -467,7 +467,7 @@
467
467
  "tailwind-merge": "^3.3.1",
468
468
  "uuid": "^13.0.0",
469
469
  "zod": "^4.1.5",
470
- "@nextsparkjs/testing": "0.1.0-beta.154"
470
+ "@nextsparkjs/testing": "0.1.0-beta.155"
471
471
  },
472
472
  "scripts": {
473
473
  "postinstall": "node scripts/postinstall.mjs || true",
@@ -14,24 +14,12 @@ import { checkRateLimit, withRateLimitTier } from '@nextsparkjs/core/lib/api/rat
14
14
  import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
15
15
  import { inviteMemberSchema, memberListQuerySchema } from '@nextsparkjs/core/lib/teams/schema'
16
16
  import { TeamMemberService, MembershipService } from '@nextsparkjs/core/lib/services'
17
+ import { canInviteToRole } from '@nextsparkjs/core/lib/teams/permissions'
17
18
  import type { TeamMember, TeamInvitation, TeamRole, Team } from '@nextsparkjs/core/lib/teams/types'
18
19
  import { EmailFactory } from '@nextsparkjs/core/lib/email/factory'
19
20
  import { sendTeamInvitationEmail } from '@nextsparkjs/core/lib/email/send'
20
21
  import { I18N_CONFIG } from '@nextsparkjs/core/lib/config'
21
22
 
22
- // Role hierarchy for invite validation (higher number = more power)
23
- const ROLE_HIERARCHY: Record<TeamRole, number> = {
24
- owner: 4,
25
- admin: 3,
26
- member: 2,
27
- viewer: 1,
28
- }
29
-
30
- // Check if a user can invite to a specific role (same level or below)
31
- function canInviteToRole(actorRole: TeamRole, targetRole: TeamRole): boolean {
32
- return ROLE_HIERARCHY[actorRole] >= ROLE_HIERARCHY[targetRole]
33
- }
34
-
35
23
  // Handle CORS preflight
36
24
  export async function OPTIONS() {
37
25
  return handleCorsPreflightRequest()
@@ -226,7 +214,8 @@ export const POST = withRateLimitTier(withApiLogging(
226
214
  const body = await req.json()
227
215
  const validatedData = inviteMemberSchema.parse(body)
228
216
 
229
- // Check role hierarchy - users can only invite to same role or below
217
+ // Check role hierarchy via the merged permissions registry users can
218
+ // only invite to roles at the same level or below their own
230
219
  if (!canInviteToRole(userRole, validatedData.role)) {
231
220
  const response = createApiError(
232
221
  `You cannot invite members to a role higher than your own. Your role: ${userRole}, requested role: ${validatedData.role}`,