@hammadj/better-auth-scim 1.5.0-beta.9

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/src/types.ts ADDED
@@ -0,0 +1,70 @@
1
+ import type { User } from "better-auth";
2
+ import type { Member } from "better-auth/plugins";
3
+
4
+ export interface SCIMProvider {
5
+ id: string;
6
+ providerId: string;
7
+ scimToken: string;
8
+ organizationId?: string;
9
+ }
10
+
11
+ export type SCIMName = {
12
+ formatted?: string;
13
+ givenName?: string;
14
+ familyName?: string;
15
+ };
16
+
17
+ export type SCIMEmail = { value?: string; primary?: boolean };
18
+
19
+ export type SCIMOptions = {
20
+ /**
21
+ * Default list of SCIM providers for testing
22
+ * These will take precedence over the database when present
23
+ */
24
+ defaultSCIM?: Omit<SCIMProvider, "id">[];
25
+ /**
26
+ * A callback that runs before a new SCIM token is generated.
27
+ * @returns
28
+ */
29
+ beforeSCIMTokenGenerated?: ({
30
+ user,
31
+ member,
32
+ scimToken,
33
+ }: {
34
+ user: User;
35
+ member?: Member | null;
36
+ scimToken: string;
37
+ }) => Promise<void>;
38
+
39
+ /**
40
+ * A callback that runs before a new SCIM token is generated
41
+ * @returns
42
+ */
43
+ afterSCIMTokenGenerated?: ({
44
+ user,
45
+ member,
46
+ scimProvider,
47
+ }: {
48
+ user: User;
49
+ member?: Member | null;
50
+ scimToken: string;
51
+ scimProvider: SCIMProvider;
52
+ }) => Promise<void>;
53
+ /**
54
+ * Store the SCIM token in your database in a secure way
55
+ *
56
+ * @default "plain"
57
+ */
58
+ storeSCIMToken?:
59
+ | (
60
+ | "hashed"
61
+ | "plain"
62
+ | "encrypted"
63
+ | { hash: (scimToken: string) => Promise<string> }
64
+ | {
65
+ encrypt: (scimToken: string) => Promise<string>;
66
+ decrypt: (scimToken: string) => Promise<string>;
67
+ }
68
+ )
69
+ | undefined;
70
+ };
@@ -0,0 +1,213 @@
1
+ import * as z from "zod";
2
+
3
+ export const APIUserSchema = z.object({
4
+ userName: z.string().lowercase(),
5
+ externalId: z.string().optional(),
6
+ name: z
7
+ .object({
8
+ formatted: z.string().optional(),
9
+ givenName: z.string().optional(),
10
+ familyName: z.string().optional(),
11
+ })
12
+ .optional(),
13
+ emails: z
14
+ .array(
15
+ z.object({
16
+ value: z.email(),
17
+ primary: z.boolean().optional(),
18
+ }),
19
+ )
20
+ .optional(),
21
+ });
22
+
23
+ export const OpenAPIUserResourceSchema = {
24
+ type: "object",
25
+ properties: {
26
+ id: { type: "string" },
27
+ meta: {
28
+ type: "object",
29
+ properties: {
30
+ resourceType: { type: "string" },
31
+ created: { type: "string", format: "date-time" },
32
+ lastModified: { type: "string", format: "date-time" },
33
+ location: { type: "string" },
34
+ },
35
+ },
36
+ userName: { type: "string" },
37
+ name: {
38
+ type: "object",
39
+ properties: {
40
+ formatted: { type: "string" },
41
+ givenName: { type: "string" },
42
+ familyName: { type: "string" },
43
+ },
44
+ },
45
+ displayName: { type: "string" },
46
+ active: { type: "boolean" },
47
+ emails: {
48
+ type: "array",
49
+ items: {
50
+ type: "object",
51
+ properties: {
52
+ value: { type: "string" },
53
+ primary: { type: "boolean" },
54
+ },
55
+ },
56
+ },
57
+ schemas: {
58
+ type: "array",
59
+ items: { type: "string" },
60
+ },
61
+ },
62
+ } as const;
63
+
64
+ export const SCIMUserResourceSchema = {
65
+ id: "urn:ietf:params:scim:schemas:core:2.0:User",
66
+ schemas: ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
67
+ name: "User",
68
+ description: "User Account",
69
+ attributes: [
70
+ {
71
+ name: "id",
72
+ type: "string",
73
+ multiValued: false,
74
+ description: "Unique opaque identifier for the User",
75
+ required: false,
76
+ caseExact: true,
77
+ mutability: "readOnly",
78
+ returned: "default",
79
+ uniqueness: "server",
80
+ },
81
+ {
82
+ name: "userName",
83
+ type: "string",
84
+ multiValued: false,
85
+ description:
86
+ "Unique identifier for the User, typically used by the user to directly authenticate to the service provider",
87
+ required: true,
88
+ caseExact: false,
89
+ mutability: "readWrite",
90
+ returned: "default",
91
+ uniqueness: "server",
92
+ },
93
+ {
94
+ name: "displayName",
95
+ type: "string",
96
+ multiValued: false,
97
+ description:
98
+ "The name of the User, suitable for display to end-users. The name SHOULD be the full name of the User being described, if known.",
99
+ required: false,
100
+ caseExact: true,
101
+ mutability: "readOnly",
102
+ returned: "default",
103
+ uniqueness: "none",
104
+ },
105
+ {
106
+ name: "active",
107
+ type: "boolean",
108
+ multiValued: false,
109
+ description:
110
+ "A Boolean value indicating the User's administrative status.",
111
+ required: false,
112
+ mutability: "readOnly",
113
+ returned: "default",
114
+ },
115
+ {
116
+ name: "name",
117
+ type: "complex",
118
+ multiValued: false,
119
+ description: "The components of the user's real name.",
120
+ required: false,
121
+ subAttributes: [
122
+ {
123
+ name: "formatted",
124
+ type: "string",
125
+ multiValued: false,
126
+ description:
127
+ "The full name, including all middlenames, titles, and suffixes as appropriate, formatted for display(e.g., 'Ms. Barbara J Jensen, III').",
128
+ required: false,
129
+ caseExact: false,
130
+ mutability: "readWrite",
131
+ returned: "default",
132
+ uniqueness: "none",
133
+ },
134
+ {
135
+ name: "familyName",
136
+ type: "string",
137
+ multiValued: false,
138
+ description:
139
+ "The family name of the User, or last name in most Western languages (e.g., 'Jensen' given the fullname 'Ms. Barbara J Jensen, III').",
140
+ required: false,
141
+ caseExact: false,
142
+ mutability: "readWrite",
143
+ returned: "default",
144
+ uniqueness: "none",
145
+ },
146
+ {
147
+ name: "givenName",
148
+ type: "string",
149
+ multiValued: false,
150
+ description:
151
+ "The given name of the User, or first name in most Western languages (e.g., 'Barbara' given the full name 'Ms. Barbara J Jensen, III').",
152
+ required: false,
153
+ caseExact: false,
154
+ mutability: "readWrite",
155
+ returned: "default",
156
+ uniqueness: "none",
157
+ },
158
+ ],
159
+ },
160
+ {
161
+ name: "emails",
162
+ type: "complex",
163
+ multiValued: true,
164
+ description:
165
+ "Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g., 'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'. Canonical type values of 'work', 'home', and 'other'.",
166
+ required: false,
167
+ subAttributes: [
168
+ {
169
+ name: "value",
170
+ type: "string",
171
+ multiValued: false,
172
+ description:
173
+ "Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g., 'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'. Canonical type values of 'work', 'home', and 'other'.",
174
+ required: false,
175
+ caseExact: false,
176
+ mutability: "readWrite",
177
+ returned: "default",
178
+ uniqueness: "server",
179
+ },
180
+ {
181
+ name: "primary",
182
+ type: "boolean",
183
+ multiValued: false,
184
+ description:
185
+ "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the preferred mailing address or primary email address. The primary attribute value 'true' MUST appear no more than once.",
186
+ required: false,
187
+ mutability: "readWrite",
188
+ returned: "default",
189
+ },
190
+ ],
191
+ mutability: "readWrite",
192
+ returned: "default",
193
+ uniqueness: "none",
194
+ },
195
+ ],
196
+ meta: {
197
+ resourceType: "Schema",
198
+ location: "/scim/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User",
199
+ },
200
+ };
201
+
202
+ export const SCIMUserResourceType = {
203
+ schemas: ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"],
204
+ id: "User",
205
+ name: "User",
206
+ endpoint: "/Users",
207
+ description: "User Account",
208
+ schema: "urn:ietf:params:scim:schemas:core:2.0:User",
209
+ meta: {
210
+ resourceType: "ResourceType",
211
+ location: "/scim/v2/ResourceTypes/User",
212
+ },
213
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,5 @@
1
+ export const getResourceURL = (path: string, baseURL: string) => {
2
+ const normalizedBaseURL = baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
3
+ const normalizedPath = path.replace(/^\/+/, "");
4
+ return new URL(normalizedPath, normalizedBaseURL).toString();
5
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "references": [
4
+ {
5
+ "path": "../better-auth/tsconfig.json"
6
+ },
7
+ {
8
+ "path": "../core/tsconfig.json"
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "tsdown";
2
+
3
+ export default defineConfig({
4
+ dts: { build: true, incremental: true },
5
+ format: ["esm"],
6
+ entry: ["./src/index.ts", "./src/client.ts"],
7
+ sourcemap: true,
8
+ });
@@ -0,0 +1,3 @@
1
+ import { defineProject } from "vitest/config";
2
+
3
+ export default defineProject({});