@wrelik/auth 0.1.0 → 0.2.1
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/.turbo/turbo-build.log +31 -0
- package/CHANGELOG.md +25 -0
- package/DRX_Primary.code-workspace +14 -0
- package/dist/chunk-5WLTDLEP.mjs +31 -0
- package/dist/chunk-HWIZ2Q5U.mjs +17 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +76 -0
- package/dist/index.mjs +16 -0
- package/dist/next.d.mts +5 -0
- package/dist/next.d.ts +5 -0
- package/dist/next.js +53 -0
- package/dist/next.mjs +14 -0
- package/dist/react-native.d.mts +14 -0
- package/dist/react-native.d.ts +14 -0
- package/dist/react-native.js +76 -0
- package/dist/react-native.mjs +27 -0
- package/dist/shared-Z5LN5APr.d.mts +11 -0
- package/dist/shared-Z5LN5APr.d.ts +11 -0
- package/package.json +15 -6
- package/src/index.test.ts +1 -0
- package/src/index.ts +3 -32
- package/src/next.ts +1 -0
- package/src/react-native.ts +28 -0
- package/src/shared.test.ts +27 -0
- package/src/shared.ts +33 -0
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
> @wrelik/auth@0.2.1 build /home/runner/work/wrelik-kit/wrelik-kit/packages/auth
|
|
3
|
+
> tsup src/index.ts src/next.ts src/react-native.ts --format cjs,esm --dts --clean
|
|
4
|
+
|
|
5
|
+
[34mCLI[39m Building entry: src/index.ts, src/next.ts, src/react-native.ts
|
|
6
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
+
[34mCLI[39m tsup v8.5.1
|
|
8
|
+
[34mCLI[39m Target: es2019
|
|
9
|
+
[34mCLI[39m Cleaning output folder
|
|
10
|
+
[34mCJS[39m Build start
|
|
11
|
+
[34mESM[39m Build start
|
|
12
|
+
[32mCJS[39m [1mdist/index.js [22m[32m2.23 KB[39m
|
|
13
|
+
[32mCJS[39m [1mdist/react-native.js [22m[32m2.31 KB[39m
|
|
14
|
+
[32mCJS[39m [1mdist/next.js [22m[32m1.61 KB[39m
|
|
15
|
+
[32mCJS[39m ⚡️ Build success in 54ms
|
|
16
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m239.00 B[39m
|
|
17
|
+
[32mESM[39m [1mdist/next.mjs [22m[32m255.00 B[39m
|
|
18
|
+
[32mESM[39m [1mdist/chunk-HWIZ2Q5U.mjs [22m[32m391.00 B[39m
|
|
19
|
+
[32mESM[39m [1mdist/react-native.mjs [22m[32m593.00 B[39m
|
|
20
|
+
[32mESM[39m [1mdist/chunk-5WLTDLEP.mjs [22m[32m748.00 B[39m
|
|
21
|
+
[32mESM[39m ⚡️ Build success in 55ms
|
|
22
|
+
[34mDTS[39m Build start
|
|
23
|
+
[32mDTS[39m ⚡️ Build success in 4418ms
|
|
24
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m393.00 B[39m
|
|
25
|
+
[32mDTS[39m [1mdist/next.d.ts [22m[32m134.00 B[39m
|
|
26
|
+
[32mDTS[39m [1mdist/react-native.d.ts [22m[32m430.00 B[39m
|
|
27
|
+
[32mDTS[39m [1mdist/shared-Z5LN5APr.d.ts [22m[32m525.00 B[39m
|
|
28
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m395.00 B[39m
|
|
29
|
+
[32mDTS[39m [1mdist/next.d.mts [22m[32m135.00 B[39m
|
|
30
|
+
[32mDTS[39m [1mdist/react-native.d.mts [22m[32m432.00 B[39m
|
|
31
|
+
[32mDTS[39m [1mdist/shared-Z5LN5APr.d.mts [22m[32m525.00 B[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @wrelik/auth
|
|
2
2
|
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- adb2048: chore: test release flow with real patch version bump
|
|
8
|
+
|
|
9
|
+
## 0.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- a38ebcb: Add React Native / Expo support and enforce server-only boundaries.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [a38ebcb]
|
|
18
|
+
- @wrelik/errors@0.2.0
|
|
19
|
+
|
|
20
|
+
## 0.1.1
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Update publishConfig to access:public for all packages.
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @wrelik/errors@0.1.1
|
|
27
|
+
|
|
3
28
|
## 0.1.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/shared.ts
|
|
2
|
+
import { AuthRequiredError, PermissionDeniedError, TenantRequiredError } from "@wrelik/errors";
|
|
3
|
+
function requireUser(session) {
|
|
4
|
+
if (!session || !session.userId) {
|
|
5
|
+
throw new AuthRequiredError();
|
|
6
|
+
}
|
|
7
|
+
return session.userId;
|
|
8
|
+
}
|
|
9
|
+
function requireTenant(session) {
|
|
10
|
+
requireUser(session);
|
|
11
|
+
if (!session || !session.tenantId) {
|
|
12
|
+
throw new TenantRequiredError();
|
|
13
|
+
}
|
|
14
|
+
return session.tenantId;
|
|
15
|
+
}
|
|
16
|
+
function hasRole(session, role) {
|
|
17
|
+
if (!session || !session.userId) return false;
|
|
18
|
+
return session.roles.includes(role);
|
|
19
|
+
}
|
|
20
|
+
function requireRole(session, role) {
|
|
21
|
+
if (!hasRole(session, role)) {
|
|
22
|
+
throw new PermissionDeniedError(`Role ${role} required`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
requireUser,
|
|
28
|
+
requireTenant,
|
|
29
|
+
hasRole,
|
|
30
|
+
requireRole
|
|
31
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function fromClerkAuth(auth) {
|
|
3
|
+
var _a, _b;
|
|
4
|
+
if (!auth || !auth.userId) {
|
|
5
|
+
return { userId: null, tenantId: null, roles: [] };
|
|
6
|
+
}
|
|
7
|
+
const roles = ((_b = (_a = auth.sessionClaims) == null ? void 0 : _a.publicMetadata) == null ? void 0 : _b.roles) || [];
|
|
8
|
+
return {
|
|
9
|
+
userId: auth.userId,
|
|
10
|
+
tenantId: auth.orgId || null,
|
|
11
|
+
roles
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
fromClerkAuth
|
|
17
|
+
};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SignedInAuthObject, SignedOutAuthObject } from '@clerk/backend';
|
|
2
|
+
import { W as WorkflowSession } from './shared-Z5LN5APr.mjs';
|
|
3
|
+
export { h as hasRole, r as requireRole, a as requireTenant, b as requireUser } from './shared-Z5LN5APr.mjs';
|
|
4
|
+
|
|
5
|
+
declare function fromClerkAuth(auth: SignedInAuthObject | SignedOutAuthObject | null): WorkflowSession;
|
|
6
|
+
|
|
7
|
+
export { WorkflowSession, fromClerkAuth };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SignedInAuthObject, SignedOutAuthObject } from '@clerk/backend';
|
|
2
|
+
import { W as WorkflowSession } from './shared-Z5LN5APr.js';
|
|
3
|
+
export { h as hasRole, r as requireRole, a as requireTenant, b as requireUser } from './shared-Z5LN5APr.js';
|
|
4
|
+
|
|
5
|
+
declare function fromClerkAuth(auth: SignedInAuthObject | SignedOutAuthObject | null): WorkflowSession;
|
|
6
|
+
|
|
7
|
+
export { WorkflowSession, fromClerkAuth };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
fromClerkAuth: () => fromClerkAuth,
|
|
24
|
+
hasRole: () => hasRole,
|
|
25
|
+
requireRole: () => requireRole,
|
|
26
|
+
requireTenant: () => requireTenant,
|
|
27
|
+
requireUser: () => requireUser
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/shared.ts
|
|
32
|
+
var import_errors = require("@wrelik/errors");
|
|
33
|
+
function requireUser(session) {
|
|
34
|
+
if (!session || !session.userId) {
|
|
35
|
+
throw new import_errors.AuthRequiredError();
|
|
36
|
+
}
|
|
37
|
+
return session.userId;
|
|
38
|
+
}
|
|
39
|
+
function requireTenant(session) {
|
|
40
|
+
requireUser(session);
|
|
41
|
+
if (!session || !session.tenantId) {
|
|
42
|
+
throw new import_errors.TenantRequiredError();
|
|
43
|
+
}
|
|
44
|
+
return session.tenantId;
|
|
45
|
+
}
|
|
46
|
+
function hasRole(session, role) {
|
|
47
|
+
if (!session || !session.userId) return false;
|
|
48
|
+
return session.roles.includes(role);
|
|
49
|
+
}
|
|
50
|
+
function requireRole(session, role) {
|
|
51
|
+
if (!hasRole(session, role)) {
|
|
52
|
+
throw new import_errors.PermissionDeniedError(`Role ${role} required`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/index.ts
|
|
57
|
+
function fromClerkAuth(auth) {
|
|
58
|
+
var _a, _b;
|
|
59
|
+
if (!auth || !auth.userId) {
|
|
60
|
+
return { userId: null, tenantId: null, roles: [] };
|
|
61
|
+
}
|
|
62
|
+
const roles = ((_b = (_a = auth.sessionClaims) == null ? void 0 : _a.publicMetadata) == null ? void 0 : _b.roles) || [];
|
|
63
|
+
return {
|
|
64
|
+
userId: auth.userId,
|
|
65
|
+
tenantId: auth.orgId || null,
|
|
66
|
+
roles
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
fromClerkAuth,
|
|
72
|
+
hasRole,
|
|
73
|
+
requireRole,
|
|
74
|
+
requireTenant,
|
|
75
|
+
requireUser
|
|
76
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fromClerkAuth
|
|
3
|
+
} from "./chunk-HWIZ2Q5U.mjs";
|
|
4
|
+
import {
|
|
5
|
+
hasRole,
|
|
6
|
+
requireRole,
|
|
7
|
+
requireTenant,
|
|
8
|
+
requireUser
|
|
9
|
+
} from "./chunk-5WLTDLEP.mjs";
|
|
10
|
+
export {
|
|
11
|
+
fromClerkAuth,
|
|
12
|
+
hasRole,
|
|
13
|
+
requireRole,
|
|
14
|
+
requireTenant,
|
|
15
|
+
requireUser
|
|
16
|
+
};
|
package/dist/next.d.mts
ADDED
package/dist/next.d.ts
ADDED
package/dist/next.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/next.ts
|
|
21
|
+
var next_exports = {};
|
|
22
|
+
__export(next_exports, {
|
|
23
|
+
getSession: () => getSession
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(next_exports);
|
|
26
|
+
var import_nextjs = require("@clerk/nextjs");
|
|
27
|
+
|
|
28
|
+
// src/shared.ts
|
|
29
|
+
var import_errors = require("@wrelik/errors");
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
32
|
+
function fromClerkAuth(auth2) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
if (!auth2 || !auth2.userId) {
|
|
35
|
+
return { userId: null, tenantId: null, roles: [] };
|
|
36
|
+
}
|
|
37
|
+
const roles = ((_b = (_a = auth2.sessionClaims) == null ? void 0 : _a.publicMetadata) == null ? void 0 : _b.roles) || [];
|
|
38
|
+
return {
|
|
39
|
+
userId: auth2.userId,
|
|
40
|
+
tenantId: auth2.orgId || null,
|
|
41
|
+
roles
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/next.ts
|
|
46
|
+
function getSession() {
|
|
47
|
+
const clerkAuth = (0, import_nextjs.auth)();
|
|
48
|
+
return fromClerkAuth(clerkAuth);
|
|
49
|
+
}
|
|
50
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
51
|
+
0 && (module.exports = {
|
|
52
|
+
getSession
|
|
53
|
+
});
|
package/dist/next.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fromClerkAuth
|
|
3
|
+
} from "./chunk-HWIZ2Q5U.mjs";
|
|
4
|
+
import "./chunk-5WLTDLEP.mjs";
|
|
5
|
+
|
|
6
|
+
// src/next.ts
|
|
7
|
+
import { auth } from "@clerk/nextjs";
|
|
8
|
+
function getSession() {
|
|
9
|
+
const clerkAuth = auth();
|
|
10
|
+
return fromClerkAuth(clerkAuth);
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
getSession
|
|
14
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { W as WorkflowSession } from './shared-Z5LN5APr.mjs';
|
|
2
|
+
export { h as hasRole, r as requireRole, a as requireTenant, b as requireUser } from './shared-Z5LN5APr.mjs';
|
|
3
|
+
|
|
4
|
+
declare function mapClerkToSession(auth: {
|
|
5
|
+
userId?: string | null;
|
|
6
|
+
orgId?: string | null;
|
|
7
|
+
session?: {
|
|
8
|
+
user?: {
|
|
9
|
+
publicMetadata?: any;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
} | null): WorkflowSession;
|
|
13
|
+
|
|
14
|
+
export { WorkflowSession, mapClerkToSession };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { W as WorkflowSession } from './shared-Z5LN5APr.js';
|
|
2
|
+
export { h as hasRole, r as requireRole, a as requireTenant, b as requireUser } from './shared-Z5LN5APr.js';
|
|
3
|
+
|
|
4
|
+
declare function mapClerkToSession(auth: {
|
|
5
|
+
userId?: string | null;
|
|
6
|
+
orgId?: string | null;
|
|
7
|
+
session?: {
|
|
8
|
+
user?: {
|
|
9
|
+
publicMetadata?: any;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
} | null): WorkflowSession;
|
|
13
|
+
|
|
14
|
+
export { WorkflowSession, mapClerkToSession };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react-native.ts
|
|
21
|
+
var react_native_exports = {};
|
|
22
|
+
__export(react_native_exports, {
|
|
23
|
+
hasRole: () => hasRole,
|
|
24
|
+
mapClerkToSession: () => mapClerkToSession,
|
|
25
|
+
requireRole: () => requireRole,
|
|
26
|
+
requireTenant: () => requireTenant,
|
|
27
|
+
requireUser: () => requireUser
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(react_native_exports);
|
|
30
|
+
|
|
31
|
+
// src/shared.ts
|
|
32
|
+
var import_errors = require("@wrelik/errors");
|
|
33
|
+
function requireUser(session) {
|
|
34
|
+
if (!session || !session.userId) {
|
|
35
|
+
throw new import_errors.AuthRequiredError();
|
|
36
|
+
}
|
|
37
|
+
return session.userId;
|
|
38
|
+
}
|
|
39
|
+
function requireTenant(session) {
|
|
40
|
+
requireUser(session);
|
|
41
|
+
if (!session || !session.tenantId) {
|
|
42
|
+
throw new import_errors.TenantRequiredError();
|
|
43
|
+
}
|
|
44
|
+
return session.tenantId;
|
|
45
|
+
}
|
|
46
|
+
function hasRole(session, role) {
|
|
47
|
+
if (!session || !session.userId) return false;
|
|
48
|
+
return session.roles.includes(role);
|
|
49
|
+
}
|
|
50
|
+
function requireRole(session, role) {
|
|
51
|
+
if (!hasRole(session, role)) {
|
|
52
|
+
throw new import_errors.PermissionDeniedError(`Role ${role} required`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/react-native.ts
|
|
57
|
+
function mapClerkToSession(auth) {
|
|
58
|
+
var _a, _b, _c;
|
|
59
|
+
if (!auth || !auth.userId) {
|
|
60
|
+
return { userId: null, tenantId: null, roles: [] };
|
|
61
|
+
}
|
|
62
|
+
const roles = ((_c = (_b = (_a = auth.session) == null ? void 0 : _a.user) == null ? void 0 : _b.publicMetadata) == null ? void 0 : _c.roles) || [];
|
|
63
|
+
return {
|
|
64
|
+
userId: auth.userId,
|
|
65
|
+
tenantId: auth.orgId || null,
|
|
66
|
+
roles
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
hasRole,
|
|
72
|
+
mapClerkToSession,
|
|
73
|
+
requireRole,
|
|
74
|
+
requireTenant,
|
|
75
|
+
requireUser
|
|
76
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hasRole,
|
|
3
|
+
requireRole,
|
|
4
|
+
requireTenant,
|
|
5
|
+
requireUser
|
|
6
|
+
} from "./chunk-5WLTDLEP.mjs";
|
|
7
|
+
|
|
8
|
+
// src/react-native.ts
|
|
9
|
+
function mapClerkToSession(auth) {
|
|
10
|
+
var _a, _b, _c;
|
|
11
|
+
if (!auth || !auth.userId) {
|
|
12
|
+
return { userId: null, tenantId: null, roles: [] };
|
|
13
|
+
}
|
|
14
|
+
const roles = ((_c = (_b = (_a = auth.session) == null ? void 0 : _a.user) == null ? void 0 : _b.publicMetadata) == null ? void 0 : _c.roles) || [];
|
|
15
|
+
return {
|
|
16
|
+
userId: auth.userId,
|
|
17
|
+
tenantId: auth.orgId || null,
|
|
18
|
+
roles
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
hasRole,
|
|
23
|
+
mapClerkToSession,
|
|
24
|
+
requireRole,
|
|
25
|
+
requireTenant,
|
|
26
|
+
requireUser
|
|
27
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface WorkflowSession {
|
|
2
|
+
userId: string | null;
|
|
3
|
+
tenantId: string | null;
|
|
4
|
+
roles: string[];
|
|
5
|
+
}
|
|
6
|
+
declare function requireUser(session: WorkflowSession | null): string;
|
|
7
|
+
declare function requireTenant(session: WorkflowSession | null): string;
|
|
8
|
+
declare function hasRole(session: WorkflowSession | null, role: string): boolean;
|
|
9
|
+
declare function requireRole(session: WorkflowSession | null, role: string): void;
|
|
10
|
+
|
|
11
|
+
export { type WorkflowSession as W, requireTenant as a, requireUser as b, hasRole as h, requireRole as r };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface WorkflowSession {
|
|
2
|
+
userId: string | null;
|
|
3
|
+
tenantId: string | null;
|
|
4
|
+
roles: string[];
|
|
5
|
+
}
|
|
6
|
+
declare function requireUser(session: WorkflowSession | null): string;
|
|
7
|
+
declare function requireTenant(session: WorkflowSession | null): string;
|
|
8
|
+
declare function hasRole(session: WorkflowSession | null, role: string): boolean;
|
|
9
|
+
declare function requireRole(session: WorkflowSession | null, role: string): void;
|
|
10
|
+
|
|
11
|
+
export { type WorkflowSession as W, requireTenant as a, requireUser as b, hasRole as h, requireRole as r };
|
package/package.json
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrelik/auth",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/lwhite702/wrelik-kit.git",
|
|
10
|
+
"directory": "packages/auth"
|
|
11
|
+
},
|
|
4
12
|
"main": "./dist/index.js",
|
|
5
13
|
"types": "./dist/index.d.ts",
|
|
6
14
|
"exports": {
|
|
7
15
|
".": "./dist/index.js",
|
|
8
|
-
"./next": "./dist/next.js"
|
|
16
|
+
"./next": "./dist/next.js",
|
|
17
|
+
"./react-native": "./dist/react-native.js"
|
|
9
18
|
},
|
|
10
19
|
"dependencies": {
|
|
11
20
|
"@clerk/backend": "^0.38.0",
|
|
12
|
-
"@wrelik/errors": "0.
|
|
21
|
+
"@wrelik/errors": "0.2.0"
|
|
13
22
|
},
|
|
14
23
|
"peerDependencies": {
|
|
15
24
|
"@clerk/nextjs": "^4.29.0"
|
|
@@ -17,11 +26,11 @@
|
|
|
17
26
|
"devDependencies": {
|
|
18
27
|
"tsup": "^8.0.1",
|
|
19
28
|
"vitest": "^1.2.2",
|
|
20
|
-
"@wrelik/eslint-config": "0.1.
|
|
21
|
-
"@wrelik/tsconfig": "0.1.
|
|
29
|
+
"@wrelik/eslint-config": "0.1.1",
|
|
30
|
+
"@wrelik/tsconfig": "0.1.1"
|
|
22
31
|
},
|
|
23
32
|
"scripts": {
|
|
24
|
-
"build": "tsup src/index.ts src/next.ts --format cjs,esm --dts --clean",
|
|
33
|
+
"build": "tsup src/index.ts src/next.ts src/react-native.ts --format cjs,esm --dts --clean",
|
|
25
34
|
"lint": "eslint src/",
|
|
26
35
|
"test": "vitest run --passWithNoTests"
|
|
27
36
|
}
|
package/src/index.test.ts
CHANGED
|
@@ -18,6 +18,7 @@ describe('@wrelik/auth', () => {
|
|
|
18
18
|
userId: 'user_123',
|
|
19
19
|
orgId: 'org_456',
|
|
20
20
|
sessionClaims: { publicMetadata: { roles: ['admin'] } },
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
22
|
} as any;
|
|
22
23
|
|
|
23
24
|
const session = fromClerkAuth(clerkAuth);
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import { AuthRequiredError, PermissionDeniedError, TenantRequiredError } from '@wrelik/errors';
|
|
2
1
|
import type { SignedInAuthObject, SignedOutAuthObject } from '@clerk/backend';
|
|
2
|
+
import { type WorkflowSession } from './shared';
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
userId: string | null;
|
|
6
|
-
tenantId: string | null;
|
|
7
|
-
roles: string[];
|
|
8
|
-
}
|
|
4
|
+
export * from './shared';
|
|
9
5
|
|
|
10
6
|
export function fromClerkAuth(
|
|
11
7
|
auth: SignedInAuthObject | SignedOutAuthObject | null,
|
|
@@ -14,6 +10,7 @@ export function fromClerkAuth(
|
|
|
14
10
|
return { userId: null, tenantId: null, roles: [] };
|
|
15
11
|
}
|
|
16
12
|
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
14
|
const roles = ((auth.sessionClaims?.publicMetadata as any)?.roles as string[]) || [];
|
|
18
15
|
|
|
19
16
|
return {
|
|
@@ -22,29 +19,3 @@ export function fromClerkAuth(
|
|
|
22
19
|
roles,
|
|
23
20
|
};
|
|
24
21
|
}
|
|
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
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type WorkflowSession } from './shared';
|
|
2
|
+
|
|
3
|
+
export * from './shared';
|
|
4
|
+
|
|
5
|
+
// We accept the `useAuth` or `useUser` return value or similar from Clerk Expo
|
|
6
|
+
// but to be loose coupling, we defined it as any with some shape checks if needed.
|
|
7
|
+
// However, the requirement says "converts the Clerk Expo session/user representation".
|
|
8
|
+
export function mapClerkToSession(
|
|
9
|
+
auth: {
|
|
10
|
+
userId?: string | null;
|
|
11
|
+
orgId?: string | null;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
session?: { user?: { publicMetadata?: any } };
|
|
14
|
+
} | null,
|
|
15
|
+
): WorkflowSession {
|
|
16
|
+
if (!auth || !auth.userId) {
|
|
17
|
+
return { userId: null, tenantId: null, roles: [] };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// The roles might be in publicMetadata of the user object in session
|
|
21
|
+
const roles = (auth.session?.user?.publicMetadata?.roles as string[]) || [];
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
userId: auth.userId,
|
|
25
|
+
tenantId: auth.orgId || null,
|
|
26
|
+
roles,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { requireUser, requireTenant, hasRole } from './shared';
|
|
3
|
+
|
|
4
|
+
describe('Auth Shared', () => {
|
|
5
|
+
it('requireUser throws if no user', () => {
|
|
6
|
+
expect(() => requireUser(null)).toThrow('Authentication required');
|
|
7
|
+
expect(() => requireUser({ userId: null, tenantId: null, roles: [] })).toThrow(
|
|
8
|
+
'Authentication required',
|
|
9
|
+
);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('requireUser returns userId', () => {
|
|
13
|
+
expect(requireUser({ userId: 'u1', tenantId: null, roles: [] })).toBe('u1');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('requireTenant throws if no tenant', () => {
|
|
17
|
+
expect(() => requireTenant({ userId: 'u1', tenantId: null, roles: [] })).toThrow(
|
|
18
|
+
'Tenant context required',
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('hasRole checks roles', () => {
|
|
23
|
+
const session = { userId: 'u1', tenantId: 't1', roles: ['admin'] };
|
|
24
|
+
expect(hasRole(session, 'admin')).toBe(true);
|
|
25
|
+
expect(hasRole(session, 'user')).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
});
|
package/src/shared.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AuthRequiredError, PermissionDeniedError, TenantRequiredError } from '@wrelik/errors';
|
|
2
|
+
|
|
3
|
+
export interface WorkflowSession {
|
|
4
|
+
userId: string | null;
|
|
5
|
+
tenantId: string | null;
|
|
6
|
+
roles: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function requireUser(session: WorkflowSession | null): string {
|
|
10
|
+
if (!session || !session.userId) {
|
|
11
|
+
throw new AuthRequiredError();
|
|
12
|
+
}
|
|
13
|
+
return session.userId;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function requireTenant(session: WorkflowSession | null): string {
|
|
17
|
+
requireUser(session);
|
|
18
|
+
if (!session || !session.tenantId) {
|
|
19
|
+
throw new TenantRequiredError();
|
|
20
|
+
}
|
|
21
|
+
return session.tenantId;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function hasRole(session: WorkflowSession | null, role: string): boolean {
|
|
25
|
+
if (!session || !session.userId) return false;
|
|
26
|
+
return session.roles.includes(role);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function requireRole(session: WorkflowSession | null, role: string) {
|
|
30
|
+
if (!hasRole(session, role)) {
|
|
31
|
+
throw new PermissionDeniedError(`Role ${role} required`);
|
|
32
|
+
}
|
|
33
|
+
}
|