@wrelik/auth 0.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @wrelik/auth
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ad849e3: Initial release of all wrelik-kit packages.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [ad849e3]
12
+ - @wrelik/errors@0.1.0
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@wrelik/auth",
3
+ "version": "0.1.0",
4
+ "main": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "exports": {
7
+ ".": "./dist/index.js",
8
+ "./next": "./dist/next.js"
9
+ },
10
+ "dependencies": {
11
+ "@clerk/backend": "^0.38.0",
12
+ "@wrelik/errors": "0.1.0"
13
+ },
14
+ "peerDependencies": {
15
+ "@clerk/nextjs": "^4.29.0"
16
+ },
17
+ "devDependencies": {
18
+ "tsup": "^8.0.1",
19
+ "vitest": "^1.2.2",
20
+ "@wrelik/eslint-config": "0.1.0",
21
+ "@wrelik/tsconfig": "0.1.0"
22
+ },
23
+ "scripts": {
24
+ "build": "tsup src/index.ts src/next.ts --format cjs,esm --dts --clean",
25
+ "lint": "eslint src/",
26
+ "test": "vitest run --passWithNoTests"
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { requireUser, fromClerkAuth } from './index';
3
+ import { AuthRequiredError } from '@wrelik/errors';
4
+
5
+ describe('@wrelik/auth', () => {
6
+ it('should throw AuthRequiredError if user is null', () => {
7
+ const session = { userId: null, tenantId: null, roles: [] };
8
+ expect(() => requireUser(session)).toThrow(AuthRequiredError);
9
+ });
10
+
11
+ it('should return userId if session is valid', () => {
12
+ const session = { userId: 'user_123', tenantId: null, roles: [] };
13
+ expect(requireUser(session)).toBe('user_123');
14
+ });
15
+
16
+ it('should correctly parse Clerk auth object', () => {
17
+ const clerkAuth = {
18
+ userId: 'user_123',
19
+ orgId: 'org_456',
20
+ sessionClaims: { publicMetadata: { roles: ['admin'] } },
21
+ } as any;
22
+
23
+ const session = fromClerkAuth(clerkAuth);
24
+ expect(session.userId).toBe('user_123');
25
+ expect(session.tenantId).toBe('org_456');
26
+ expect(session.roles).toContain('admin');
27
+ });
28
+ });
package/src/index.ts ADDED
@@ -0,0 +1,50 @@
1
+ import { AuthRequiredError, PermissionDeniedError, TenantRequiredError } from '@wrelik/errors';
2
+ import type { SignedInAuthObject, SignedOutAuthObject } from '@clerk/backend';
3
+
4
+ export interface WorkflowSession {
5
+ userId: string | null;
6
+ tenantId: string | null;
7
+ roles: string[];
8
+ }
9
+
10
+ export function fromClerkAuth(
11
+ auth: SignedInAuthObject | SignedOutAuthObject | null,
12
+ ): WorkflowSession {
13
+ if (!auth || !auth.userId) {
14
+ return { userId: null, tenantId: null, roles: [] };
15
+ }
16
+
17
+ const roles = ((auth.sessionClaims?.publicMetadata as any)?.roles as string[]) || [];
18
+
19
+ return {
20
+ userId: auth.userId,
21
+ tenantId: auth.orgId || null,
22
+ roles,
23
+ };
24
+ }
25
+
26
+ export function requireUser(session: WorkflowSession | null): string {
27
+ if (!session || !session.userId) {
28
+ throw new AuthRequiredError();
29
+ }
30
+ return session.userId;
31
+ }
32
+
33
+ export function requireTenant(session: WorkflowSession | null): string {
34
+ requireUser(session);
35
+ if (!session || !session.tenantId) {
36
+ throw new TenantRequiredError();
37
+ }
38
+ return session.tenantId;
39
+ }
40
+
41
+ export function hasRole(session: WorkflowSession | null, role: string): boolean {
42
+ if (!session || !session.userId) return false;
43
+ return session.roles.includes(role);
44
+ }
45
+
46
+ export function requireRole(session: WorkflowSession | null, role: string) {
47
+ if (!hasRole(session, role)) {
48
+ throw new PermissionDeniedError(`Role ${role} required`);
49
+ }
50
+ }
package/src/next.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { auth } from '@clerk/nextjs';
2
+ import { fromClerkAuth, type WorkflowSession } from './index';
3
+
4
+ export function getSession(): WorkflowSession {
5
+ const clerkAuth = auth();
6
+ return fromClerkAuth(clerkAuth);
7
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "@wrelik/tsconfig/next.json",
3
+ "compilerOptions": {
4
+ "incremental": false,
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src"]
8
+ }