@better-auth/scim 1.5.7-beta.1 → 1.6.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/dist/client.d.mts +2 -2
- package/dist/client.mjs +2 -2
- package/dist/index.d.mts +2367 -2300
- package/dist/index.mjs +46 -25
- package/dist/version-Cf5gNNxE.mjs +5 -0
- package/package.json +9 -8
- package/dist/client.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as PACKAGE_VERSION } from "./version-Cf5gNNxE.mjs";
|
|
1
2
|
import { base64Url } from "@better-auth/utils/base64";
|
|
2
3
|
import { APIError, createAuthEndpoint, createAuthMiddleware, sessionMiddleware } from "better-auth/api";
|
|
3
4
|
import { APIError as APIError$1, HIDE_METADATA } from "better-auth";
|
|
@@ -613,7 +614,21 @@ const generateSCIMTokenBodySchema = z.object({
|
|
|
613
614
|
});
|
|
614
615
|
const getSCIMProviderConnectionQuerySchema = z.object({ providerId: z.string() });
|
|
615
616
|
const deleteSCIMProviderConnectionBodySchema = z.object({ providerId: z.string() });
|
|
616
|
-
|
|
617
|
+
function parseMemberRoles(role) {
|
|
618
|
+
return role.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
619
|
+
}
|
|
620
|
+
function hasRequiredRole(memberRole, requiredRole) {
|
|
621
|
+
return !requiredRole.length || parseMemberRoles(memberRole).some((role) => requiredRole.includes(role));
|
|
622
|
+
}
|
|
623
|
+
function resolveRequiredRoles(ctx, opts) {
|
|
624
|
+
if (opts.requiredRole) return opts.requiredRole;
|
|
625
|
+
const creatorRole = ctx.context.getPlugin("organization")?.options?.creatorRole;
|
|
626
|
+
return Array.from(new Set(["admin", creatorRole ?? "owner"]));
|
|
627
|
+
}
|
|
628
|
+
function isProviderOwnershipEnabled(opts) {
|
|
629
|
+
return opts.providerOwnership?.enabled ?? false;
|
|
630
|
+
}
|
|
631
|
+
async function getSCIMUserOrgMemberships(ctx, userId) {
|
|
617
632
|
const members = await ctx.context.adapter.findMany({
|
|
618
633
|
model: "member",
|
|
619
634
|
where: [{
|
|
@@ -621,7 +636,7 @@ async function getSCIMUserOrgIds(ctx, userId) {
|
|
|
621
636
|
value: userId
|
|
622
637
|
}]
|
|
623
638
|
});
|
|
624
|
-
return new
|
|
639
|
+
return new Map(members.map((member) => [member.organizationId, parseMemberRoles(member.role)]));
|
|
625
640
|
}
|
|
626
641
|
function normalizeSCIMProvider(provider) {
|
|
627
642
|
return {
|
|
@@ -642,13 +657,15 @@ async function findOrganizationMember(ctx, userId, organizationId) {
|
|
|
642
657
|
}]
|
|
643
658
|
});
|
|
644
659
|
}
|
|
645
|
-
async function assertSCIMProviderAccess(ctx, userId, provider) {
|
|
660
|
+
async function assertSCIMProviderAccess(ctx, userId, provider, requiredRole) {
|
|
646
661
|
if (provider.organizationId) {
|
|
647
662
|
if (!ctx.context.hasPlugin("organization")) throw new APIError("FORBIDDEN", { message: "Organization plugin is required to access this SCIM provider" });
|
|
648
|
-
|
|
663
|
+
const member = await findOrganizationMember(ctx, userId, provider.organizationId);
|
|
664
|
+
if (!member) throw new APIError("FORBIDDEN", { message: "You must be a member of the organization to access this provider" });
|
|
665
|
+
if (!hasRequiredRole(member.role, requiredRole)) throw new APIError("FORBIDDEN", { message: "Insufficient role for this operation" });
|
|
649
666
|
} else if (provider.userId && provider.userId !== userId) throw new APIError("FORBIDDEN", { message: "You must be the owner to access this provider" });
|
|
650
667
|
}
|
|
651
|
-
async function checkSCIMProviderAccess(ctx, userId, providerId) {
|
|
668
|
+
async function checkSCIMProviderAccess(ctx, userId, providerId, requiredRole) {
|
|
652
669
|
const provider = await ctx.context.adapter.findOne({
|
|
653
670
|
model: "scimProvider",
|
|
654
671
|
where: [{
|
|
@@ -657,7 +674,7 @@ async function checkSCIMProviderAccess(ctx, userId, providerId) {
|
|
|
657
674
|
}]
|
|
658
675
|
});
|
|
659
676
|
if (!provider) throw new APIError("NOT_FOUND", { message: "SCIM provider not found" });
|
|
660
|
-
await assertSCIMProviderAccess(ctx, userId, provider);
|
|
677
|
+
await assertSCIMProviderAccess(ctx, userId, provider, requiredRole);
|
|
661
678
|
return provider;
|
|
662
679
|
}
|
|
663
680
|
const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
|
|
@@ -681,12 +698,14 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
|
|
|
681
698
|
}, async (ctx) => {
|
|
682
699
|
const { providerId, organizationId } = ctx.body;
|
|
683
700
|
const user = ctx.context.session.user;
|
|
701
|
+
const requiredRole = resolveRequiredRoles(ctx, opts);
|
|
684
702
|
if (providerId.includes(":")) throw new APIError("BAD_REQUEST", { message: "Provider id contains forbidden characters" });
|
|
685
703
|
if (organizationId && !ctx.context.hasPlugin("organization")) throw new APIError("BAD_REQUEST", { message: "Restricting a token to an organization requires the organization plugin" });
|
|
686
704
|
let member = null;
|
|
687
705
|
if (organizationId) {
|
|
688
706
|
member = await findOrganizationMember(ctx, user.id, organizationId);
|
|
689
707
|
if (!member) throw new APIError("FORBIDDEN", { message: "You are not a member of the organization" });
|
|
708
|
+
if (!hasRequiredRole(member.role, requiredRole)) throw new APIError("FORBIDDEN", { message: "Insufficient role for this operation" });
|
|
690
709
|
}
|
|
691
710
|
const scimProvider = await ctx.context.adapter.findOne({
|
|
692
711
|
model: "scimProvider",
|
|
@@ -699,7 +718,7 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
|
|
|
699
718
|
}] : []]
|
|
700
719
|
});
|
|
701
720
|
if (scimProvider) {
|
|
702
|
-
await assertSCIMProviderAccess(ctx, user.id, scimProvider);
|
|
721
|
+
await assertSCIMProviderAccess(ctx, user.id, scimProvider, requiredRole);
|
|
703
722
|
await ctx.context.adapter.delete({
|
|
704
723
|
model: "scimProvider",
|
|
705
724
|
where: [{
|
|
@@ -721,7 +740,7 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
|
|
|
721
740
|
providerId,
|
|
722
741
|
organizationId,
|
|
723
742
|
scimToken: await storeSCIMToken(ctx, opts, baseToken),
|
|
724
|
-
...opts
|
|
743
|
+
...isProviderOwnershipEnabled(opts) ? { userId: user.id } : {}
|
|
725
744
|
}
|
|
726
745
|
});
|
|
727
746
|
if (opts.afterSCIMTokenGenerated) await opts.afterSCIMTokenGenerated({
|
|
@@ -733,13 +752,13 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
|
|
|
733
752
|
ctx.setStatus(201);
|
|
734
753
|
return ctx.json({ scimToken });
|
|
735
754
|
});
|
|
736
|
-
const listSCIMProviderConnections = () => createAuthEndpoint("/scim/list-provider-connections", {
|
|
755
|
+
const listSCIMProviderConnections = (opts) => createAuthEndpoint("/scim/list-provider-connections", {
|
|
737
756
|
method: "GET",
|
|
738
757
|
use: [sessionMiddleware],
|
|
739
758
|
metadata: { openapi: {
|
|
740
759
|
operationId: "listSCIMProviderConnections",
|
|
741
760
|
summary: "List SCIM providers",
|
|
742
|
-
description: "Returns SCIM providers
|
|
761
|
+
description: "Returns SCIM providers the user owns or has the required org role for.",
|
|
743
762
|
responses: { "200": {
|
|
744
763
|
description: "List of SCIM providers",
|
|
745
764
|
content: { "application/json": { schema: {
|
|
@@ -763,15 +782,18 @@ const listSCIMProviderConnections = () => createAuthEndpoint("/scim/list-provide
|
|
|
763
782
|
} }
|
|
764
783
|
}, async (ctx) => {
|
|
765
784
|
const userId = ctx.context.session.user.id;
|
|
766
|
-
const
|
|
785
|
+
const requiredRole = resolveRequiredRoles(ctx, opts);
|
|
786
|
+
const orgMemberships = ctx.context.hasPlugin("organization") ? await getSCIMUserOrgMemberships(ctx, userId) : /* @__PURE__ */ new Map();
|
|
767
787
|
const providers = (await ctx.context.adapter.findMany({ model: "scimProvider" })).filter((p) => {
|
|
768
|
-
if (p.organizationId)
|
|
769
|
-
|
|
770
|
-
|
|
788
|
+
if (p.organizationId) {
|
|
789
|
+
const roles = orgMemberships.get(p.organizationId);
|
|
790
|
+
return roles ? !requiredRole.length || roles.some((role) => requiredRole.includes(role)) : false;
|
|
791
|
+
}
|
|
792
|
+
return p.userId === userId || !p.userId;
|
|
771
793
|
}).map((p) => normalizeSCIMProvider(p));
|
|
772
794
|
return ctx.json({ providers });
|
|
773
795
|
});
|
|
774
|
-
const getSCIMProviderConnection = () => createAuthEndpoint("/scim/get-provider-connection", {
|
|
796
|
+
const getSCIMProviderConnection = (opts) => createAuthEndpoint("/scim/get-provider-connection", {
|
|
775
797
|
method: "GET",
|
|
776
798
|
use: [sessionMiddleware],
|
|
777
799
|
query: getSCIMProviderConnectionQuerySchema,
|
|
@@ -801,10 +823,10 @@ const getSCIMProviderConnection = () => createAuthEndpoint("/scim/get-provider-c
|
|
|
801
823
|
}, async (ctx) => {
|
|
802
824
|
const { providerId } = ctx.query;
|
|
803
825
|
const userId = ctx.context.session.user.id;
|
|
804
|
-
const provider = await checkSCIMProviderAccess(ctx, userId, providerId);
|
|
826
|
+
const provider = await checkSCIMProviderAccess(ctx, userId, providerId, resolveRequiredRoles(ctx, opts));
|
|
805
827
|
return ctx.json(normalizeSCIMProvider(provider));
|
|
806
828
|
});
|
|
807
|
-
const deleteSCIMProviderConnection = () => createAuthEndpoint("/scim/delete-provider-connection", {
|
|
829
|
+
const deleteSCIMProviderConnection = (opts) => createAuthEndpoint("/scim/delete-provider-connection", {
|
|
808
830
|
method: "POST",
|
|
809
831
|
use: [sessionMiddleware],
|
|
810
832
|
body: deleteSCIMProviderConnectionBodySchema,
|
|
@@ -827,7 +849,7 @@ const deleteSCIMProviderConnection = () => createAuthEndpoint("/scim/delete-prov
|
|
|
827
849
|
}, async (ctx) => {
|
|
828
850
|
const { providerId } = ctx.body;
|
|
829
851
|
const userId = ctx.context.session.user.id;
|
|
830
|
-
await checkSCIMProviderAccess(ctx, userId, providerId);
|
|
852
|
+
await checkSCIMProviderAccess(ctx, userId, providerId, resolveRequiredRoles(ctx, opts));
|
|
831
853
|
await ctx.context.adapter.delete({
|
|
832
854
|
model: "scimProvider",
|
|
833
855
|
where: [{
|
|
@@ -1416,17 +1438,18 @@ const parseSCIMAPIUserFilter = (filter) => {
|
|
|
1416
1438
|
const scim = (options) => {
|
|
1417
1439
|
const opts = {
|
|
1418
1440
|
storeSCIMToken: "plain",
|
|
1419
|
-
providerOwnership: { enabled: false },
|
|
1420
1441
|
...options
|
|
1421
1442
|
};
|
|
1443
|
+
const providerOwnershipEnabled = options?.providerOwnership?.enabled ?? false;
|
|
1422
1444
|
const authMiddleware = authMiddlewareFactory(opts);
|
|
1423
1445
|
return {
|
|
1424
1446
|
id: "scim",
|
|
1447
|
+
version: PACKAGE_VERSION,
|
|
1425
1448
|
endpoints: {
|
|
1426
1449
|
generateSCIMToken: generateSCIMToken(opts),
|
|
1427
|
-
listSCIMProviderConnections: listSCIMProviderConnections(),
|
|
1428
|
-
getSCIMProviderConnection: getSCIMProviderConnection(),
|
|
1429
|
-
deleteSCIMProviderConnection: deleteSCIMProviderConnection(),
|
|
1450
|
+
listSCIMProviderConnections: listSCIMProviderConnections(opts),
|
|
1451
|
+
getSCIMProviderConnection: getSCIMProviderConnection(opts),
|
|
1452
|
+
deleteSCIMProviderConnection: deleteSCIMProviderConnection(opts),
|
|
1430
1453
|
getSCIMUser: getSCIMUser(authMiddleware),
|
|
1431
1454
|
createSCIMUser: createSCIMUser(authMiddleware),
|
|
1432
1455
|
patchSCIMUser: patchSCIMUser(authMiddleware),
|
|
@@ -1454,7 +1477,7 @@ const scim = (options) => {
|
|
|
1454
1477
|
type: "string",
|
|
1455
1478
|
required: false
|
|
1456
1479
|
},
|
|
1457
|
-
...
|
|
1480
|
+
...providerOwnershipEnabled ? { userId: {
|
|
1458
1481
|
type: "string",
|
|
1459
1482
|
required: false
|
|
1460
1483
|
} } : {}
|
|
@@ -1464,5 +1487,3 @@ const scim = (options) => {
|
|
|
1464
1487
|
};
|
|
1465
1488
|
//#endregion
|
|
1466
1489
|
export { scim };
|
|
1467
|
-
|
|
1468
|
-
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/scim",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "SCIM plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
|
+
"sideEffects": false,
|
|
23
24
|
"files": [
|
|
24
25
|
"dist"
|
|
25
26
|
],
|
|
@@ -49,23 +50,23 @@
|
|
|
49
50
|
}
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
52
|
-
"@better-auth/utils": "0.3.1",
|
|
53
|
-
"better-call": "2.0.2",
|
|
54
53
|
"zod": "^4.3.6"
|
|
55
54
|
},
|
|
56
55
|
"devDependencies": {
|
|
57
56
|
"tsdown": "0.21.1",
|
|
58
|
-
"@better-auth/core": "1.
|
|
59
|
-
"@better-auth/sso": "1.
|
|
57
|
+
"@better-auth/core": "1.6.0",
|
|
58
|
+
"@better-auth/sso": "1.6.0"
|
|
60
59
|
},
|
|
61
60
|
"peerDependencies": {
|
|
62
|
-
"@better-auth/
|
|
63
|
-
"better-
|
|
61
|
+
"@better-auth/utils": "0.4.0",
|
|
62
|
+
"better-call": "1.3.5",
|
|
63
|
+
"@better-auth/core": "^1.6.0",
|
|
64
|
+
"better-auth": "^1.6.0"
|
|
64
65
|
},
|
|
65
66
|
"scripts": {
|
|
66
67
|
"build": "tsdown",
|
|
67
68
|
"dev": "tsdown --watch",
|
|
68
|
-
"lint:package": "publint run --strict",
|
|
69
|
+
"lint:package": "publint run --strict --pack false",
|
|
69
70
|
"lint:types": "attw --profile esm-only --pack .",
|
|
70
71
|
"typecheck": "tsc --project tsconfig.json",
|
|
71
72
|
"test": "vitest",
|
package/dist/client.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type { BetterAuthClientPlugin } from \"better-auth/client\";\nimport type { scim } from \"./index\";\n\nexport const scimClient = () => {\n\treturn {\n\t\tid: \"scim-client\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof scim>,\n\t} satisfies BetterAuthClientPlugin;\n};\n"],"mappings":";AAGA,MAAa,mBAAmB;AAC/B,QAAO;EACN,IAAI;EACJ,oBAAoB,EAAE;EACtB"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["APIError"],"sources":["../src/scim-error.ts","../src/scim-tokens.ts","../src/middlewares.ts","../src/mappings.ts","../src/patch-operations.ts","../src/user-schemas.ts","../src/scim-filters.ts","../src/scim-metadata.ts","../src/utils.ts","../src/scim-resources.ts","../src/routes.ts","../src/index.ts"],"sourcesContent":["import type { Status } from \"better-auth\";\nimport { APIError } from \"better-auth\";\nimport { statusCodes } from \"better-call\";\n\n/**\n * SCIM compliant error\n * See: https://datatracker.ietf.org/doc/html/rfc7644#section-3.12\n */\nexport class SCIMAPIError extends APIError {\n\tconstructor(\n\t\tstatus: keyof typeof statusCodes | Status = \"INTERNAL_SERVER_ERROR\",\n\t\toverrides: any = {},\n\t) {\n\t\tconst body = {\n\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:Error\"],\n\t\t\tstatus: (typeof status === \"number\"\n\t\t\t\t? status\n\t\t\t\t: statusCodes[status]\n\t\t\t).toString(),\n\t\t\tdetail: overrides.detail,\n\t\t\t...overrides,\n\t\t};\n\t\tsuper(status, body);\n\t\tthis.message = body.detail ?? body.message;\n\t}\n}\n\nconst SCIMErrorOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tstatus: {\n\t\t\ttype: \"string\",\n\t\t},\n\t\tdetail: {\n\t\t\ttype: \"string\",\n\t\t},\n\t\tscimType: {\n\t\t\ttype: \"string\",\n\t\t},\n\t},\n} as const;\n\nexport const SCIMErrorOpenAPISchemas = {\n\t\"400\": {\n\t\tdescription:\n\t\t\t\"Bad Request. Usually due to missing parameters, or invalid parameters\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"401\": {\n\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"403\": {\n\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"404\": {\n\t\tdescription: \"Not Found. The requested resource was not found.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"429\": {\n\t\tdescription:\n\t\t\t\"Too Many Requests. You have exceeded the rate limit. Try again later.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"500\": {\n\t\tdescription:\n\t\t\t\"Internal Server Error. This is a problem with the server that you cannot fix.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n};\n","import { base64Url } from \"@better-auth/utils/base64\";\nimport { createHash } from \"@better-auth/utils/hash\";\nimport type { GenericEndpointContext } from \"better-auth\";\nimport { symmetricDecrypt, symmetricEncrypt } from \"better-auth/crypto\";\nimport type { SCIMOptions } from \"./types\";\n\nconst defaultKeyHasher = async (token: string) => {\n\tconst hash = await createHash(\"SHA-256\").digest(\n\t\tnew TextEncoder().encode(token),\n\t);\n\treturn base64Url.encode(new Uint8Array(hash), { padding: false });\n};\n\nexport async function storeSCIMToken(\n\tctx: GenericEndpointContext,\n\topts: SCIMOptions,\n\tscimToken: string,\n) {\n\tif (opts.storeSCIMToken === \"encrypted\") {\n\t\treturn await symmetricEncrypt({\n\t\t\tkey: ctx.context.secretConfig,\n\t\t\tdata: scimToken,\n\t\t});\n\t}\n\tif (opts.storeSCIMToken === \"hashed\") {\n\t\treturn await defaultKeyHasher(scimToken);\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"hash\" in opts.storeSCIMToken\n\t) {\n\t\treturn await opts.storeSCIMToken.hash(scimToken);\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"encrypt\" in opts.storeSCIMToken\n\t) {\n\t\treturn await opts.storeSCIMToken.encrypt(scimToken);\n\t}\n\n\treturn scimToken;\n}\n\nexport async function verifySCIMToken(\n\tctx: GenericEndpointContext,\n\topts: SCIMOptions,\n\tstoredSCIMToken: string,\n\tscimToken: string,\n): Promise<boolean> {\n\tif (opts.storeSCIMToken === \"encrypted\") {\n\t\treturn (\n\t\t\t(await symmetricDecrypt({\n\t\t\t\tkey: ctx.context.secretConfig,\n\t\t\t\tdata: storedSCIMToken,\n\t\t\t})) === scimToken\n\t\t);\n\t}\n\tif (opts.storeSCIMToken === \"hashed\") {\n\t\tconst hashedSCIMToken = await defaultKeyHasher(scimToken);\n\t\treturn hashedSCIMToken === storedSCIMToken;\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"hash\" in opts.storeSCIMToken\n\t) {\n\t\tconst hashedSCIMToken = await opts.storeSCIMToken.hash(scimToken);\n\t\treturn hashedSCIMToken === storedSCIMToken;\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"decrypt\" in opts.storeSCIMToken\n\t) {\n\t\tconst decryptedSCIMToken =\n\t\t\tawait opts.storeSCIMToken.decrypt(storedSCIMToken);\n\t\treturn decryptedSCIMToken === scimToken;\n\t}\n\n\treturn scimToken === storedSCIMToken;\n}\n","import { base64Url } from \"@better-auth/utils/base64\";\nimport { createAuthMiddleware } from \"better-auth/api\";\nimport { SCIMAPIError } from \"./scim-error\";\nimport { verifySCIMToken } from \"./scim-tokens\";\nimport type { SCIMOptions, SCIMProvider } from \"./types\";\n\nexport type AuthMiddleware = ReturnType<typeof authMiddlewareFactory>;\n\n/**\n * The middleware forces the endpoint to have a valid token\n */\nexport const authMiddlewareFactory = (opts: SCIMOptions) =>\n\tcreateAuthMiddleware(async (ctx) => {\n\t\tconst authHeader = ctx.headers?.get(\"Authorization\");\n\t\tconst authSCIMToken = authHeader?.replace(/^Bearer\\s+/i, \"\");\n\n\t\tif (!authSCIMToken) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"SCIM token is required\",\n\t\t\t});\n\t\t}\n\n\t\tconst baseScimTokenParts = new TextDecoder()\n\t\t\t.decode(base64Url.decode(authSCIMToken))\n\t\t\t.split(\":\");\n\n\t\tconst [scimToken, providerId] = baseScimTokenParts;\n\t\tconst organizationId = baseScimTokenParts.slice(2).join(\":\");\n\n\t\tif (!scimToken || !providerId) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t});\n\t\t}\n\n\t\tlet scimProvider: Omit<SCIMProvider, \"id\"> | null =\n\t\t\topts.defaultSCIM?.find((p) => {\n\t\t\t\tif (p.providerId === providerId && !organizationId) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn !!(\n\t\t\t\t\tp.providerId === providerId &&\n\t\t\t\t\torganizationId &&\n\t\t\t\t\tp.organizationId === organizationId\n\t\t\t\t);\n\t\t\t}) ?? null;\n\n\t\tif (scimProvider) {\n\t\t\tif (scimProvider.scimToken === scimToken) {\n\t\t\t\treturn { authSCIMToken: scimProvider.scimToken, scimProvider };\n\t\t\t} else {\n\t\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tscimProvider = await ctx.context.adapter.findOne<SCIMProvider>({\n\t\t\tmodel: \"scimProvider\",\n\t\t\twhere: [\n\t\t\t\t{ field: \"providerId\", value: providerId },\n\t\t\t\t...(organizationId\n\t\t\t\t\t? [{ field: \"organizationId\", value: organizationId }]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t});\n\n\t\tif (!scimProvider) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t});\n\t\t}\n\n\t\tconst isValidToken = await verifySCIMToken(\n\t\t\tctx,\n\t\t\topts,\n\t\t\tscimProvider.scimToken,\n\t\t\tscimToken,\n\t\t);\n\n\t\tif (!isValidToken) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t});\n\t\t}\n\n\t\treturn { authSCIMToken: scimToken, scimProvider };\n\t});\n","import type { SCIMEmail, SCIMName } from \"./types\";\n\nexport const getAccountId = (userName: string, externalId?: string) => {\n\treturn externalId ?? userName;\n};\n\nconst getFormattedName = (name: SCIMName) => {\n\tif (name.givenName && name.familyName) {\n\t\treturn `${name.givenName} ${name.familyName}`;\n\t}\n\n\tif (name.givenName) {\n\t\treturn name.givenName;\n\t}\n\n\treturn name.familyName ?? \"\";\n};\n\nexport const getUserFullName = (email: string, name?: SCIMName) => {\n\tif (name) {\n\t\tconst formatted = name.formatted?.trim() ?? \"\";\n\t\tif (formatted.length > 0) {\n\t\t\treturn formatted;\n\t\t}\n\n\t\treturn getFormattedName(name) || email;\n\t}\n\n\treturn email;\n};\n\nexport const getUserPrimaryEmail = (userName: string, emails?: SCIMEmail[]) => {\n\treturn (\n\t\temails?.find((email) => email.primary)?.value ??\n\t\temails?.[0]?.value ??\n\t\tuserName\n\t);\n};\n","import type { User } from \"better-auth\";\nimport { getUserFullName } from \"./mappings\";\n\ntype Operation = {\n\top: \"add\" | \"remove\" | \"replace\";\n\tvalue: any;\n\tpath?: string;\n};\n\ntype Mapping = {\n\ttarget: string;\n\tresource: \"user\" | \"account\";\n\tmap: (user: User, op: Operation, resources: Resources) => any;\n};\n\ntype Resources = {\n\tuser: Record<string, any>;\n\taccount: Record<string, any>;\n};\n\nconst identity = (user: User, op: Operation, resources: Resources) => {\n\treturn op.value;\n};\n\nconst lowerCase = (user: User, op: Operation, resources: Resources) => {\n\treturn op.value.toLowerCase();\n};\n\nconst givenName = (user: User, op: Operation, resources: Resources) => {\n\tconst currentName = (resources.user.name as string) ?? user.name;\n\tconst familyName = currentName.split(\" \").slice(1).join(\" \").trim();\n\tconst givenName = op.value;\n\n\treturn getUserFullName(user.email, {\n\t\tgivenName,\n\t\tfamilyName,\n\t});\n};\n\nconst familyName = (user: User, op: Operation, resources: Resources) => {\n\tconst currentName = (resources.user.name as string) ?? user.name;\n\tconst givenName = (\n\t\tcurrentName.split(\" \").slice(0, -1).join(\" \") || currentName\n\t).trim();\n\tconst familyName = op.value;\n\treturn getUserFullName(user.email, {\n\t\tgivenName,\n\t\tfamilyName,\n\t});\n};\n\nconst userPatchMappings: Record<string, Mapping> = {\n\t\"/name/formatted\": { resource: \"user\", target: \"name\", map: identity },\n\t\"/name/givenName\": { resource: \"user\", target: \"name\", map: givenName },\n\t\"/name/familyName\": {\n\t\tresource: \"user\",\n\t\ttarget: \"name\",\n\t\tmap: familyName,\n\t},\n\t\"/externalId\": {\n\t\tresource: \"account\",\n\t\ttarget: \"accountId\",\n\t\tmap: identity,\n\t},\n\t\"/userName\": { resource: \"user\", target: \"email\", map: lowerCase },\n};\n\nconst normalizePath = (path: string): string => {\n\tconst withoutLeadingSlash = path.startsWith(\"/\") ? path.slice(1) : path;\n\treturn `/${withoutLeadingSlash.replaceAll(\".\", \"/\")}`;\n};\n\nconst isNestedObject = (value: unknown): value is Record<string, unknown> => {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst applyMapping = (\n\tuser: User,\n\tresources: Resources,\n\tpath: string,\n\tvalue: unknown,\n\top: \"add\" | \"replace\",\n) => {\n\tconst normalizedPath = normalizePath(path);\n\tconst mapping = userPatchMappings[normalizedPath];\n\n\tif (!mapping) {\n\t\treturn;\n\t}\n\n\tconst newValue = mapping.map(\n\t\tuser,\n\t\t{\n\t\t\top,\n\t\t\tvalue,\n\t\t\tpath: normalizedPath,\n\t\t},\n\t\tresources,\n\t);\n\n\tif (op === \"add\" && mapping.resource === \"user\") {\n\t\tconst currentValue = (user as Record<string, unknown>)[mapping.target];\n\t\tif (currentValue === newValue) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tresources[mapping.resource][mapping.target] = newValue;\n};\n\nconst applyPatchValue = (\n\tuser: User,\n\tresources: Resources,\n\tvalue: unknown,\n\top: \"add\" | \"replace\",\n\tpath?: string | undefined,\n) => {\n\tif (isNestedObject(value)) {\n\t\tfor (const [key, nestedValue] of Object.entries(value)) {\n\t\t\tconst nestedPath = path ? `${path}.${key}` : key;\n\t\t\tapplyPatchValue(user, resources, nestedValue, op, nestedPath);\n\t\t}\n\t} else if (path) {\n\t\tapplyMapping(user, resources, path, value, op);\n\t}\n};\n\nexport const buildUserPatch = (user: User, operations: Operation[]) => {\n\tconst userPatch: Record<string, any> = {};\n\tconst accountPatch: Record<string, any> = {};\n\tconst resources: Resources = { user: userPatch, account: accountPatch };\n\n\tfor (const operation of operations) {\n\t\tif (operation.op !== \"add\" && operation.op !== \"replace\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tapplyPatchValue(\n\t\t\tuser,\n\t\t\tresources,\n\t\t\toperation.value,\n\t\t\toperation.op,\n\t\t\toperation.path,\n\t\t);\n\t}\n\n\treturn resources;\n};\n","import * as z from \"zod\";\n\nexport const APIUserSchema = z.object({\n\tuserName: z.string().lowercase(),\n\texternalId: z.string().optional(),\n\tname: z\n\t\t.object({\n\t\t\tformatted: z.string().optional(),\n\t\t\tgivenName: z.string().optional(),\n\t\t\tfamilyName: z.string().optional(),\n\t\t})\n\t\t.optional(),\n\temails: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tvalue: z.email(),\n\t\t\t\tprimary: z.boolean().optional(),\n\t\t\t}),\n\t\t)\n\t\t.optional(),\n});\n\nexport const OpenAPIUserResourceSchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tid: { type: \"string\" },\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: { type: \"string\" },\n\t\t\t\tcreated: { type: \"string\", format: \"date-time\" },\n\t\t\t\tlastModified: { type: \"string\", format: \"date-time\" },\n\t\t\t\tlocation: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tuserName: { type: \"string\" },\n\t\tname: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tformatted: { type: \"string\" },\n\t\t\t\tgivenName: { type: \"string\" },\n\t\t\t\tfamilyName: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tdisplayName: { type: \"string\" },\n\t\tactive: { type: \"boolean\" },\n\t\temails: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tvalue: { type: \"string\" },\n\t\t\t\t\tprimary: { type: \"boolean\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t},\n} as const;\n\nexport const SCIMUserResourceSchema = {\n\tid: \"urn:ietf:params:scim:schemas:core:2.0:User\",\n\tschemas: [\"urn:ietf:params:scim:schemas:core:2.0:Schema\"],\n\tname: \"User\",\n\tdescription: \"User Account\",\n\tattributes: [\n\t\t{\n\t\t\tname: \"id\",\n\t\t\ttype: \"string\",\n\t\t\tmultiValued: false,\n\t\t\tdescription: \"Unique opaque identifier for the User\",\n\t\t\trequired: false,\n\t\t\tcaseExact: true,\n\t\t\tmutability: \"readOnly\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"server\",\n\t\t},\n\t\t{\n\t\t\tname: \"userName\",\n\t\t\ttype: \"string\",\n\t\t\tmultiValued: false,\n\t\t\tdescription:\n\t\t\t\t\"Unique identifier for the User, typically used by the user to directly authenticate to the service provider\",\n\t\t\trequired: true,\n\t\t\tcaseExact: false,\n\t\t\tmutability: \"readWrite\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"server\",\n\t\t},\n\t\t{\n\t\t\tname: \"displayName\",\n\t\t\ttype: \"string\",\n\t\t\tmultiValued: false,\n\t\t\tdescription:\n\t\t\t\t\"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.\",\n\t\t\trequired: false,\n\t\t\tcaseExact: true,\n\t\t\tmutability: \"readOnly\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"none\",\n\t\t},\n\t\t{\n\t\t\tname: \"active\",\n\t\t\ttype: \"boolean\",\n\t\t\tmultiValued: false,\n\t\t\tdescription:\n\t\t\t\t\"A Boolean value indicating the User's administrative status.\",\n\t\t\trequired: false,\n\t\t\tmutability: \"readOnly\",\n\t\t\treturned: \"default\",\n\t\t},\n\t\t{\n\t\t\tname: \"name\",\n\t\t\ttype: \"complex\",\n\t\t\tmultiValued: false,\n\t\t\tdescription: \"The components of the user's real name.\",\n\t\t\trequired: false,\n\t\t\tsubAttributes: [\n\t\t\t\t{\n\t\t\t\t\tname: \"formatted\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The full name, including all middlenames, titles, and suffixes as appropriate, formatted for display(e.g., 'Ms. Barbara J Jensen, III').\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"none\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"familyName\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The family name of the User, or last name in most Western languages (e.g., 'Jensen' given the fullname 'Ms. Barbara J Jensen, III').\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"none\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"givenName\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"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').\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"none\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tname: \"emails\",\n\t\t\ttype: \"complex\",\n\t\t\tmultiValued: true,\n\t\t\tdescription:\n\t\t\t\t\"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'.\",\n\t\t\trequired: false,\n\t\t\tsubAttributes: [\n\t\t\t\t{\n\t\t\t\t\tname: \"value\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"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'.\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"server\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"primary\",\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"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.\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tmutability: \"readWrite\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"none\",\n\t\t},\n\t],\n\tmeta: {\n\t\tresourceType: \"Schema\",\n\t\tlocation: \"/scim/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User\",\n\t},\n};\n\nexport const SCIMUserResourceType = {\n\tschemas: [\"urn:ietf:params:scim:schemas:core:2.0:ResourceType\"],\n\tid: \"User\",\n\tname: \"User\",\n\tendpoint: \"/Users\",\n\tdescription: \"User Account\",\n\tschema: \"urn:ietf:params:scim:schemas:core:2.0:User\",\n\tmeta: {\n\t\tresourceType: \"ResourceType\",\n\t\tlocation: \"/scim/v2/ResourceTypes/User\",\n\t},\n};\n","import { SCIMUserResourceSchema } from \"./user-schemas\";\n\nexport type DBFilter = {\n\tfield: string;\n\tvalue: string | string[];\n\toperator?: any;\n};\n\nconst SCIMOperators: Record<string, string | undefined> = {\n\teq: \"eq\",\n};\n\nconst SCIMUserAttributes: Record<string, string | undefined> = {\n\tuserName: \"email\",\n};\n\nexport class SCIMParseError extends Error {}\n\nconst SCIMFilterRegex =\n\t/^\\s*(?<attribute>[^\\s]+)\\s+(?<op>eq|ne|co|sw|ew|pr)\\s*(?:(?<value>\"[^\"]*\"|[^\\s]+))?\\s*$/i;\n\nconst parseSCIMFilter = (filter: string) => {\n\tconst match = filter.match(SCIMFilterRegex);\n\tif (!match) {\n\t\tthrow new SCIMParseError(\"Invalid filter expression\");\n\t}\n\n\tconst attribute = match.groups?.attribute;\n\tconst op = match.groups?.op?.toLowerCase();\n\tconst value = match.groups?.value;\n\n\tif (!attribute || !op || !value) {\n\t\tthrow new SCIMParseError(\"Invalid filter expression\");\n\t}\n\n\tconst operator = SCIMOperators[op];\n\tif (!operator) {\n\t\tthrow new SCIMParseError(`The operator \"${op}\" is not supported`);\n\t}\n\n\treturn { attribute, operator, value };\n};\n\nexport const parseSCIMUserFilter = (filter: string) => {\n\tconst { attribute, operator, value } = parseSCIMFilter(filter);\n\n\tconst filters: DBFilter[] = [];\n\tconst targetAttribute = SCIMUserAttributes[attribute];\n\tconst resourceAttribute = SCIMUserResourceSchema.attributes.find(\n\t\t(attr) => attr.name === attribute,\n\t);\n\n\tif (!targetAttribute || !resourceAttribute) {\n\t\tthrow new SCIMParseError(`The attribute \"${attribute}\" is not supported`);\n\t}\n\n\tlet finalValue = value.replaceAll('\"', \"\");\n\tif (!resourceAttribute.caseExact) {\n\t\tfinalValue = finalValue.toLowerCase();\n\t}\n\n\tfilters.push({\n\t\tfield: targetAttribute,\n\t\tvalue: finalValue,\n\t\toperator,\n\t});\n\n\treturn filters;\n};\n","const MetadataFieldSupportOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tsupported: {\n\t\t\ttype: \"boolean\",\n\t\t},\n\t},\n};\n\nexport const ServiceProviderOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tpatch: MetadataFieldSupportOpenAPISchema,\n\t\tbulk: MetadataFieldSupportOpenAPISchema,\n\t\tfilter: MetadataFieldSupportOpenAPISchema,\n\t\tchangePassword: MetadataFieldSupportOpenAPISchema,\n\t\tsort: MetadataFieldSupportOpenAPISchema,\n\t\tetag: MetadataFieldSupportOpenAPISchema,\n\t\tauthenticationSchemes: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tname: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\tdescription: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\tspecUri: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\ttype: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\tprimary: {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"string\",\n\t\t\t},\n\t\t},\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n} as const;\n\nexport const ResourceTypeOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tid: { type: \"string\" },\n\t\tname: { type: \"string\" },\n\t\tendpoint: { type: \"string\" },\n\t\tdescription: { type: \"string\" },\n\t\tschema: { type: \"string\" },\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: { type: \"string\" },\n\t\t\t\tlocation: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t},\n} as const;\n\nconst SCIMSchemaAttributesOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tname: { type: \"string\" },\n\t\ttype: { type: \"string\" },\n\t\tmultiValued: { type: \"boolean\" },\n\t\tdescription: { type: \"string\" },\n\t\trequired: { type: \"boolean\" },\n\t\tcaseExact: { type: \"boolean\" },\n\t\tmutability: { type: \"string\" },\n\t\treturned: { type: \"string\" },\n\t\tuniqueness: { type: \"string\" },\n\t},\n} as const;\n\nexport const SCIMSchemaOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tid: { type: \"string\" },\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tname: { type: \"string\" },\n\t\tdescription: { type: \"string\" },\n\t\tattributes: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\t...SCIMSchemaAttributesOpenAPISchema,\n\t\t\t\tproperties: {\n\t\t\t\t\t...SCIMSchemaAttributesOpenAPISchema.properties,\n\t\t\t\t\tsubAttributes: {\n\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\titems: SCIMSchemaAttributesOpenAPISchema,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: { type: \"string\" },\n\t\t\t\tlocation: { type: \"string\" },\n\t\t\t},\n\t\t\trequired: [\"resourceType\", \"location\"],\n\t\t},\n\t},\n} as const;\n","export const getResourceURL = (path: string, baseURL: string) => {\n\tconst normalizedBaseURL = baseURL.endsWith(\"/\") ? baseURL : `${baseURL}/`;\n\tconst normalizedPath = path.replace(/^\\/+/, \"\");\n\treturn new URL(normalizedPath, normalizedBaseURL).toString();\n};\n","import type { Account, User } from \"better-auth\";\nimport { SCIMUserResourceSchema } from \"./user-schemas\";\nimport { getResourceURL } from \"./utils\";\n\nexport const createUserResource = (\n\tbaseURL: string,\n\tuser: User,\n\taccount?: Account | null,\n) => {\n\treturn {\n\t\t// Common attributes\n\t\t// See https://datatracker.ietf.org/doc/html/rfc7643#section-3.1\n\n\t\tid: user.id,\n\t\texternalId: account?.accountId,\n\t\tmeta: {\n\t\t\tresourceType: \"User\",\n\t\t\tcreated: user.createdAt,\n\t\t\tlastModified: user.updatedAt,\n\t\t\tlocation: getResourceURL(`/scim/v2/Users/${user.id}`, baseURL),\n\t\t},\n\n\t\t// SCIM user resource\n\t\t// See https://datatracker.ietf.org/doc/html/rfc7643#section-4.1\n\n\t\tuserName: user.email,\n\t\tname: {\n\t\t\tformatted: user.name,\n\t\t},\n\t\tdisplayName: user.name,\n\t\tactive: true,\n\t\temails: [{ primary: true, value: user.email }],\n\t\tschemas: [SCIMUserResourceSchema.id],\n\t};\n};\n","import { base64Url } from \"@better-auth/utils/base64\";\nimport type {\n\tAccount,\n\tDBAdapter,\n\tGenericEndpointContext,\n\tUser,\n} from \"better-auth\";\nimport { HIDE_METADATA } from \"better-auth\";\nimport {\n\tAPIError,\n\tcreateAuthEndpoint,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport type { Member } from \"better-auth/plugins\";\nimport * as z from \"zod\";\nimport { getAccountId, getUserFullName, getUserPrimaryEmail } from \"./mappings\";\nimport type { AuthMiddleware } from \"./middlewares\";\nimport { buildUserPatch } from \"./patch-operations\";\nimport { SCIMAPIError, SCIMErrorOpenAPISchemas } from \"./scim-error\";\nimport type { DBFilter } from \"./scim-filters\";\nimport { parseSCIMUserFilter, SCIMParseError } from \"./scim-filters\";\nimport {\n\tResourceTypeOpenAPISchema,\n\tSCIMSchemaOpenAPISchema,\n\tServiceProviderOpenAPISchema,\n} from \"./scim-metadata\";\nimport { createUserResource } from \"./scim-resources\";\nimport { storeSCIMToken } from \"./scim-tokens\";\nimport type { SCIMOptions, SCIMProvider } from \"./types\";\nimport {\n\tAPIUserSchema,\n\tOpenAPIUserResourceSchema,\n\tSCIMUserResourceSchema,\n\tSCIMUserResourceType,\n} from \"./user-schemas\";\nimport { getResourceURL } from \"./utils\";\n\nconst supportedSCIMSchemas = [SCIMUserResourceSchema];\nconst supportedSCIMResourceTypes = [SCIMUserResourceType];\nconst supportedMediaTypes = [\"application/json\", \"application/scim+json\"];\n\nconst generateSCIMTokenBodySchema = z.object({\n\tproviderId: z.string().meta({ description: \"Unique provider identifier\" }),\n\torganizationId: z\n\t\t.string()\n\t\t.optional()\n\t\t.meta({ description: \"Optional organization id\" }),\n});\n\nconst getSCIMProviderConnectionQuerySchema = z.object({\n\tproviderId: z.string(),\n});\n\nconst deleteSCIMProviderConnectionBodySchema = z.object({\n\tproviderId: z.string(),\n});\n\nasync function getSCIMUserOrgIds(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n): Promise<Set<string>> {\n\tconst members = await ctx.context.adapter.findMany<Member>({\n\t\tmodel: \"member\",\n\t\twhere: [{ field: \"userId\", value: userId }],\n\t});\n\treturn new Set(members.map((m) => m.organizationId));\n}\n\nfunction normalizeSCIMProvider(provider: SCIMProvider) {\n\treturn {\n\t\tid: provider.id,\n\t\tproviderId: provider.providerId,\n\t\torganizationId: provider.organizationId ?? null,\n\t};\n}\n\nasync function findOrganizationMember(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n\torganizationId: string,\n): Promise<Member | null> {\n\treturn ctx.context.adapter.findOne<Member>({\n\t\tmodel: \"member\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"userId\",\n\t\t\t\tvalue: userId,\n\t\t\t},\n\t\t\t{\n\t\t\t\tfield: \"organizationId\",\n\t\t\t\tvalue: organizationId,\n\t\t\t},\n\t\t],\n\t});\n}\n\nasync function assertSCIMProviderAccess(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n\tprovider: SCIMProvider,\n): Promise<void> {\n\tif (provider.organizationId) {\n\t\tif (!ctx.context.hasPlugin(\"organization\")) {\n\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\tmessage: \"Organization plugin is required to access this SCIM provider\",\n\t\t\t});\n\t\t}\n\n\t\tconst member = await findOrganizationMember(\n\t\t\tctx,\n\t\t\tuserId,\n\t\t\tprovider.organizationId,\n\t\t);\n\n\t\tif (!member) {\n\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\tmessage:\n\t\t\t\t\t\"You must be a member of the organization to access this provider\",\n\t\t\t});\n\t\t}\n\t} else if (provider.userId && provider.userId !== userId) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: \"You must be the owner to access this provider\",\n\t\t});\n\t}\n}\n\nasync function checkSCIMProviderAccess(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n\tproviderId: string,\n): Promise<SCIMProvider> {\n\tconst provider = await ctx.context.adapter.findOne<SCIMProvider>({\n\t\tmodel: \"scimProvider\",\n\t\twhere: [{ field: \"providerId\", value: providerId }],\n\t});\n\n\tif (!provider) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\tmessage: \"SCIM provider not found\",\n\t\t});\n\t}\n\n\tawait assertSCIMProviderAccess(ctx, userId, provider);\n\n\treturn provider;\n}\n\nexport const generateSCIMToken = (opts: SCIMOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/generate-token\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: generateSCIMTokenBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Generates a new SCIM token for the given provider\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Generates a new SCIM token to be used for SCIM operations\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"201\": {\n\t\t\t\t\t\t\tdescription: \"SCIM token response\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tscimToken: {\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"SCIM token\",\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { providerId, organizationId } = ctx.body;\n\t\t\tconst user = ctx.context.session.user;\n\n\t\t\tif (providerId.includes(\":\")) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Provider id contains forbidden characters\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (organizationId && !ctx.context.hasPlugin(\"organization\")) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"Restricting a token to an organization requires the organization plugin\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet member: Member | null = null;\n\t\t\tif (organizationId) {\n\t\t\t\tmember = await findOrganizationMember(ctx, user.id, organizationId);\n\n\t\t\t\tif (!member) {\n\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\tmessage: \"You are not a member of the organization\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst scimProvider = await ctx.context.adapter.findOne<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\twhere: [\n\t\t\t\t\t{ field: \"providerId\", value: providerId },\n\t\t\t\t\t...(organizationId\n\t\t\t\t\t\t? [{ field: \"organizationId\", value: organizationId }]\n\t\t\t\t\t\t: []),\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tif (scimProvider) {\n\t\t\t\tawait assertSCIMProviderAccess(ctx, user.id, scimProvider);\n\t\t\t\tawait ctx.context.adapter.delete<SCIMProvider>({\n\t\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\t\twhere: [{ field: \"id\", value: scimProvider.id }],\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst baseToken = generateRandomString(24);\n\t\t\tconst scimToken = base64Url.encode(\n\t\t\t\t`${baseToken}:${providerId}${organizationId ? `:${organizationId}` : \"\"}`,\n\t\t\t);\n\n\t\t\tif (opts.beforeSCIMTokenGenerated) {\n\t\t\t\tawait opts.beforeSCIMTokenGenerated({\n\t\t\t\t\tuser,\n\t\t\t\t\tmember,\n\t\t\t\t\tscimToken,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst newSCIMProvider = await ctx.context.adapter.create<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\tdata: {\n\t\t\t\t\tproviderId: providerId,\n\t\t\t\t\torganizationId: organizationId,\n\t\t\t\t\tscimToken: await storeSCIMToken(ctx, opts, baseToken),\n\t\t\t\t\t...(opts.providerOwnership?.enabled ? { userId: user.id } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (opts.afterSCIMTokenGenerated) {\n\t\t\t\tawait opts.afterSCIMTokenGenerated({\n\t\t\t\t\tuser,\n\t\t\t\t\tmember,\n\t\t\t\t\tscimToken,\n\t\t\t\t\tscimProvider: newSCIMProvider,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tctx.setStatus(201);\n\n\t\t\treturn ctx.json({\n\t\t\t\tscimToken,\n\t\t\t});\n\t\t},\n\t);\n\nexport const listSCIMProviderConnections = () =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/list-provider-connections\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"listSCIMProviderConnections\",\n\t\t\t\t\tsummary: \"List SCIM providers\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Returns SCIM providers for organizations the user is a member of.\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"List of SCIM providers\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tproviders: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tproviderId: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\torganizationId: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.context.session.user.id;\n\t\t\tconst userOrgIds: Set<string> = ctx.context.hasPlugin(\"organization\")\n\t\t\t\t? await getSCIMUserOrgIds(ctx, userId)\n\t\t\t\t: new Set();\n\n\t\t\tconst allProviders = await ctx.context.adapter.findMany<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t});\n\n\t\t\tconst accessibleProviders = allProviders.filter((p) => {\n\t\t\t\tif (p.organizationId) return userOrgIds.has(p.organizationId); // org level access\n\t\t\t\tif (p.userId === userId) return true; // owner access\n\t\t\t\treturn !p.userId; // no org and no owner\n\t\t\t});\n\n\t\t\tconst providers = accessibleProviders.map((p) =>\n\t\t\t\tnormalizeSCIMProvider(p),\n\t\t\t);\n\n\t\t\treturn ctx.json({ providers });\n\t\t},\n\t);\n\nexport const getSCIMProviderConnection = () =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/get-provider-connection\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tquery: getSCIMProviderConnectionQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getSCIMProviderConnection\",\n\t\t\t\t\tsummary: \"Get SCIM provider details\",\n\t\t\t\t\tdescription: \"Returns details for a specific SCIM provider\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM provider details\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tid: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\tproviderId: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\torganizationId: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"404\": {\n\t\t\t\t\t\t\tdescription: \"Provider not found\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"403\": {\n\t\t\t\t\t\t\tdescription: \"Access denied\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { providerId } = ctx.query;\n\t\t\tconst userId = ctx.context.session.user.id;\n\n\t\t\tconst provider = await checkSCIMProviderAccess(ctx, userId, providerId);\n\n\t\t\treturn ctx.json(normalizeSCIMProvider(provider));\n\t\t},\n\t);\n\nexport const deleteSCIMProviderConnection = () =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/delete-provider-connection\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: deleteSCIMProviderConnectionBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"deleteSCIMProviderConnection\",\n\t\t\t\t\tsummary: \"Delete SCIM provider\",\n\t\t\t\t\tdescription: \"Deletes a SCIM provider and invalidates its token\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM provider deleted successfully\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: { type: \"boolean\" },\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"404\": {\n\t\t\t\t\t\t\tdescription: \"Provider not found\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"403\": {\n\t\t\t\t\t\t\tdescription: \"Access denied\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { providerId } = ctx.body;\n\t\t\tconst userId = ctx.context.session.user.id;\n\n\t\t\tawait checkSCIMProviderAccess(ctx, userId, providerId);\n\n\t\t\tawait ctx.context.adapter.delete<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\twhere: [{ field: \"providerId\", value: providerId }],\n\t\t\t});\n\n\t\t\treturn ctx.json({ success: true });\n\t\t},\n\t);\n\nexport const createSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: APIUserSchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Create SCIM user.\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Provision a new user into the linked organization via SCIM. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.3\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"201\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user resource\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst body = ctx.body;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst accountId = getAccountId(body.userName, body.externalId);\n\n\t\t\tconst existingAccount = await ctx.context.adapter.findOne<Account>({\n\t\t\t\tmodel: \"account\",\n\t\t\t\twhere: [\n\t\t\t\t\t{ field: \"accountId\", value: accountId },\n\t\t\t\t\t{ field: \"providerId\", value: providerId },\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tif (existingAccount) {\n\t\t\t\tthrow new SCIMAPIError(\"CONFLICT\", {\n\t\t\t\t\tdetail: \"User already exists\",\n\t\t\t\t\tscimType: \"uniqueness\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst email = getUserPrimaryEmail(body.userName, body.emails);\n\t\t\tconst name = getUserFullName(email, body.name);\n\n\t\t\tconst existingUser = await ctx.context.adapter.findOne<User>({\n\t\t\t\tmodel: \"user\",\n\t\t\t\twhere: [{ field: \"email\", value: email }],\n\t\t\t});\n\n\t\t\tconst createAccount = (userId: string) =>\n\t\t\t\tctx.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: userId,\n\t\t\t\t\tproviderId: providerId,\n\t\t\t\t\taccountId: accountId,\n\t\t\t\t\taccessToken: \"\",\n\t\t\t\t\trefreshToken: \"\",\n\t\t\t\t});\n\n\t\t\tconst createUser = () =>\n\t\t\t\tctx.context.internalAdapter.createUser({\n\t\t\t\t\temail,\n\t\t\t\t\tname,\n\t\t\t\t});\n\n\t\t\tconst createOrgMembership = async (userId: string) => {\n\t\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\n\t\t\t\tif (organizationId) {\n\t\t\t\t\tconst isOrgMember = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"organizationId\", value: organizationId },\n\t\t\t\t\t\t\t{ field: \"userId\", value: userId },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!isOrgMember) {\n\t\t\t\t\t\treturn await ctx.context.adapter.create<Member>({\n\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: userId,\n\t\t\t\t\t\t\t\trole: \"member\",\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\torganizationId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tlet user: User;\n\t\t\tlet account: Account;\n\n\t\t\tif (existingUser) {\n\t\t\t\tuser = existingUser;\n\t\t\t\taccount = await ctx.context.adapter.transaction<Account>(async () => {\n\t\t\t\t\tconst account = await createAccount(user.id);\n\t\t\t\t\tawait createOrgMembership(user.id);\n\t\t\t\t\treturn account;\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t[user, account] = await ctx.context.adapter.transaction<\n\t\t\t\t\t[User, Account]\n\t\t\t\t>(async () => {\n\t\t\t\t\tconst user = await createUser();\n\t\t\t\t\tconst account = await createAccount(user.id);\n\t\t\t\t\tawait createOrgMembership(user.id);\n\t\t\t\t\treturn [user, account];\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst userResource = createUserResource(\n\t\t\t\tctx.context.baseURL,\n\t\t\t\tuser,\n\t\t\t\taccount,\n\t\t\t);\n\n\t\t\tctx.setStatus(201);\n\t\t\tctx.setHeader(\"location\", userResource.meta.location);\n\t\t\treturn ctx.json(userResource);\n\t\t},\n\t);\n\nexport const updateSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: APIUserSchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Update SCIM user.\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Updates an existing user into the linked organization via SCIM. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.3\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user resource\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst body = ctx.body;\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst { organizationId, providerId } = ctx.context.scimProvider;\n\t\t\tconst accountId = getAccountId(body.userName, body.externalId);\n\n\t\t\tconst { user, account } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst [updatedUser, updatedAccount] =\n\t\t\t\tawait ctx.context.adapter.transaction<[User | null, Account | null]>(\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tconst email = getUserPrimaryEmail(body.userName, body.emails);\n\t\t\t\t\t\tconst name = getUserFullName(email, body.name);\n\n\t\t\t\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUser(\n\t\t\t\t\t\t\tuserId,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst updatedAccount =\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.updateAccount(account.id, {\n\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn [updatedUser, updatedAccount];\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\tconst userResource = createUserResource(\n\t\t\t\tctx.context.baseURL,\n\t\t\t\tupdatedUser!,\n\t\t\t\tupdatedAccount,\n\t\t\t);\n\n\t\t\treturn ctx.json(userResource);\n\t\t},\n\t);\n\nconst listSCIMUsersQuerySchema = z\n\t.object({\n\t\tfilter: z.string().optional(),\n\t})\n\t.optional();\n\nexport const listSCIMUsers = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: listSCIMUsersQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"List SCIM users\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Returns all users provisioned via SCIM for the linked organization. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user list\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttotalResults: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\t\titemsPerPage: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\t\tstartIndex: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\t\tResources: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst emptyListResponse = {\n\t\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\t\ttotalResults: 0,\n\t\t\t\tstartIndex: 1,\n\t\t\t\titemsPerPage: 0,\n\t\t\t\tResources: [],\n\t\t\t} as const;\n\n\t\t\tconst apiFilters: DBFilter[] = parseSCIMAPIUserFilter(ctx.query?.filter);\n\n\t\t\tctx.context.logger.info(\"Querying result with filters: \", apiFilters);\n\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst accounts = await ctx.context.adapter.findMany<Account>({\n\t\t\t\tmodel: \"account\",\n\t\t\t\twhere: [{ field: \"providerId\", value: providerId }],\n\t\t\t});\n\n\t\t\tconst accountUserIds = accounts.map((account) => account.userId);\n\n\t\t\t// No accounts exist for this provider\n\n\t\t\tif (accountUserIds.length === 0) {\n\t\t\t\treturn ctx.json(emptyListResponse);\n\t\t\t}\n\n\t\t\tlet userFilters: DBFilter[] = [\n\t\t\t\t{ field: \"id\", value: accountUserIds, operator: \"in\" },\n\t\t\t];\n\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\t\t\tif (organizationId) {\n\t\t\t\tconst members = await ctx.context.adapter.findMany<Member>({\n\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{ field: \"organizationId\", value: organizationId },\n\t\t\t\t\t\t{ field: \"userId\", value: accountUserIds, operator: \"in\" },\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tconst memberUserIds = members.map((member) => member.userId);\n\n\t\t\t\t// No members exist for this organization\n\n\t\t\t\tif (memberUserIds.length === 0) {\n\t\t\t\t\treturn ctx.json(emptyListResponse);\n\t\t\t\t}\n\n\t\t\t\tuserFilters = [{ field: \"id\", value: memberUserIds, operator: \"in\" }];\n\t\t\t}\n\n\t\t\tconst users = await ctx.context.adapter.findMany<User>({\n\t\t\t\tmodel: \"user\",\n\t\t\t\twhere: [...userFilters, ...apiFilters],\n\t\t\t});\n\n\t\t\treturn ctx.json({\n\t\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\t\ttotalResults: users.length,\n\t\t\t\tstartIndex: 1,\n\t\t\t\titemsPerPage: users.length,\n\t\t\t\tResources: users.map((user) => {\n\t\t\t\t\tconst account = accounts.find((a) => a.userId === user.id);\n\t\t\t\t\treturn createUserResource(ctx.context.baseURL, user, account);\n\t\t\t\t}),\n\t\t\t});\n\t\t},\n\t);\n\nexport const getSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Get SCIM user details\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Returns the provisioned SCIM user details. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.1\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user resource\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\n\t\t\tconst { user, account } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn ctx.json(createUserResource(ctx.context.baseURL, user, account));\n\t\t},\n\t);\n\nconst patchSCIMUserBodySchema = z.object({\n\tschemas: z\n\t\t.array(z.string())\n\t\t.refine(\n\t\t\t(s) => s.includes(\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"),\n\t\t\t{\n\t\t\t\tmessage: \"Invalid schemas for PatchOp\",\n\t\t\t},\n\t\t),\n\tOperations: z.array(\n\t\tz.object({\n\t\t\top: z\n\t\t\t\t.string()\n\t\t\t\t.toLowerCase()\n\t\t\t\t.default(\"replace\")\n\t\t\t\t.pipe(z.enum([\"replace\", \"add\", \"remove\"])),\n\t\t\tpath: z.string().optional(),\n\t\t\tvalue: z.any(),\n\t\t}),\n\t),\n});\n\nexport const patchSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody: patchSCIMUserBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Patch SCIM user\",\n\t\t\t\t\tdescription: \"Updates fields on a SCIM user record\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"204\": {\n\t\t\t\t\t\t\tdescription: \"Patch update applied correctly\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\n\t\t\tconst { user, account } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { user: userPatch, account: accountPatch } = buildUserPatch(\n\t\t\t\tuser,\n\t\t\t\tctx.body.Operations,\n\t\t\t);\n\n\t\t\tif (\n\t\t\t\tObject.keys(userPatch).length === 0 &&\n\t\t\t\tObject.keys(accountPatch).length === 0\n\t\t\t) {\n\t\t\t\tthrow new SCIMAPIError(\"BAD_REQUEST\", {\n\t\t\t\t\tdetail: \"No valid fields to update\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait Promise.all([\n\t\t\t\tObject.keys(userPatch).length > 0\n\t\t\t\t\t? ctx.context.internalAdapter.updateUser(userId, {\n\t\t\t\t\t\t\t...userPatch,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t})\n\t\t\t\t\t: Promise.resolve(),\n\t\t\t\tObject.keys(accountPatch).length > 0\n\t\t\t\t\t? ctx.context.internalAdapter.updateAccount(account.id, {\n\t\t\t\t\t\t\t...accountPatch,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t})\n\t\t\t\t\t: Promise.resolve(),\n\t\t\t]);\n\n\t\t\tctx.setStatus(204);\n\t\t\treturn;\n\t\t},\n\t);\n\nexport const deleteSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"DELETE\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: [...supportedMediaTypes, \"\"],\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Delete SCIM user\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Deletes (or deactivates) a user within the linked organization.\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"204\": {\n\t\t\t\t\t\t\tdescription: \"Delete applied successfully\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\n\t\t\tconst { user } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait ctx.context.internalAdapter.deleteUser(userId);\n\n\t\t\tctx.setStatus(204);\n\t\t\treturn;\n\t\t},\n\t);\n\nexport const getSCIMServiceProviderConfig = createAuthEndpoint(\n\t\"/scim/v2/ServiceProviderConfig\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Configuration\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: ServiceProviderOpenAPISchema,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\tpatch: { supported: true },\n\t\t\tbulk: { supported: false },\n\t\t\tfilter: { supported: true },\n\t\t\tchangePassword: { supported: false },\n\t\t\tsort: { supported: false },\n\t\t\tetag: { supported: false },\n\t\t\tauthenticationSchemes: [\n\t\t\t\t{\n\t\t\t\t\tname: \"OAuth Bearer Token\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Authentication scheme using the Authorization header with a bearer token tied to an organization.\",\n\t\t\t\t\tspecUri: \"http://www.rfc-editor.org/info/rfc6750\",\n\t\t\t\t\ttype: \"oauthbearertoken\",\n\t\t\t\t\tprimary: true,\n\t\t\t\t},\n\t\t\t],\n\t\t\tschemas: [\"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig\"],\n\t\t\tmeta: {\n\t\t\t\tresourceType: \"ServiceProviderConfig\",\n\t\t\t},\n\t\t});\n\t},\n);\n\nexport const getSCIMSchemas = createAuthEndpoint(\n\t\"/scim/v2/Schemas\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Configuration Schemas\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to acquire information about supported schemas. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\titems: SCIMSchemaOpenAPISchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\ttotalResults: supportedSCIMSchemas.length,\n\t\t\titemsPerPage: supportedSCIMSchemas.length,\n\t\t\tstartIndex: 1,\n\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\tResources: supportedSCIMSchemas.map((s) => {\n\t\t\t\treturn {\n\t\t\t\t\t...s,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\t...s.meta,\n\t\t\t\t\t\tlocation: getResourceURL(s.meta.location, ctx.context.baseURL),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}),\n\t\t});\n\t},\n);\n\nexport const getSCIMSchema = createAuthEndpoint(\n\t\"/scim/v2/Schemas/:schemaId\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM a Service Provider Configuration Schema\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to acquire information about a given schema. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: SCIMSchemaOpenAPISchema,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst schema = supportedSCIMSchemas.find(\n\t\t\t(s) => s.id === ctx.params.schemaId,\n\t\t);\n\n\t\tif (!schema) {\n\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\tdetail: \"Schema not found\",\n\t\t\t});\n\t\t}\n\n\t\treturn ctx.json({\n\t\t\t...schema,\n\t\t\tmeta: {\n\t\t\t\t...schema.meta,\n\t\t\t\tlocation: getResourceURL(schema.meta.location, ctx.context.baseURL),\n\t\t\t},\n\t\t});\n\t},\n);\n\nexport const getSCIMResourceTypes = createAuthEndpoint(\n\t\"/scim/v2/ResourceTypes\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Supported Resource Types\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to get a list of server supported types. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttotalResults: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\titemsPerPage: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\tstartIndex: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\tResources: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\titems: ResourceTypeOpenAPISchema,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\ttotalResults: supportedSCIMResourceTypes.length,\n\t\t\titemsPerPage: supportedSCIMResourceTypes.length,\n\t\t\tstartIndex: 1,\n\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\tResources: supportedSCIMResourceTypes.map((s) => {\n\t\t\t\treturn {\n\t\t\t\t\t...s,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\t...s.meta,\n\t\t\t\t\t\tlocation: getResourceURL(s.meta.location, ctx.context.baseURL),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}),\n\t\t});\n\t},\n);\n\nexport const getSCIMResourceType = createAuthEndpoint(\n\t\"/scim/v2/ResourceTypes/:resourceTypeId\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Supported Resource Type\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to get a server supported type. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: ResourceTypeOpenAPISchema,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst resourceType = supportedSCIMResourceTypes.find(\n\t\t\t(s) => s.id === ctx.params.resourceTypeId,\n\t\t);\n\n\t\tif (!resourceType) {\n\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\tdetail: \"Resource type not found\",\n\t\t\t});\n\t\t}\n\n\t\treturn ctx.json({\n\t\t\t...resourceType,\n\t\t\tmeta: {\n\t\t\t\t...resourceType.meta,\n\t\t\t\tlocation: getResourceURL(\n\t\t\t\t\tresourceType.meta.location,\n\t\t\t\t\tctx.context.baseURL,\n\t\t\t\t),\n\t\t\t},\n\t\t});\n\t},\n);\n\nconst findUserById = async (\n\tadapter: DBAdapter,\n\t{\n\t\tuserId,\n\t\tproviderId,\n\t\torganizationId,\n\t}: { userId: string; providerId: string; organizationId?: string },\n) => {\n\tconst account = await adapter.findOne<Account>({\n\t\tmodel: \"account\",\n\t\twhere: [\n\t\t\t{ field: \"userId\", value: userId },\n\t\t\t{ field: \"providerId\", value: providerId },\n\t\t],\n\t});\n\n\t// Disallows access to the resource\n\t// Account is not associated to the provider\n\n\tif (!account) {\n\t\treturn { user: null, account: null };\n\t}\n\n\tlet member: Member | null = null;\n\tif (organizationId) {\n\t\tmember = await adapter.findOne<Member>({\n\t\t\tmodel: \"member\",\n\t\t\twhere: [\n\t\t\t\t{ field: \"organizationId\", value: organizationId },\n\t\t\t\t{ field: \"userId\", value: userId },\n\t\t\t],\n\t\t});\n\t}\n\n\t// Disallows access to the resource\n\t// Token is restricted to an org and the member is not part of it\n\n\tif (organizationId && !member) {\n\t\treturn { user: null, account: null };\n\t}\n\n\tconst user = await adapter.findOne<User>({\n\t\tmodel: \"user\",\n\t\twhere: [{ field: \"id\", value: userId }],\n\t});\n\n\tif (!user) {\n\t\treturn { user: null, account: null };\n\t}\n\n\treturn { user, account };\n};\n\nconst parseSCIMAPIUserFilter = (filter?: string) => {\n\tlet filters: DBFilter[] = [];\n\n\ttry {\n\t\tfilters = filter ? parseSCIMUserFilter(filter) : [];\n\t} catch (error) {\n\t\tthrow new SCIMAPIError(\"BAD_REQUEST\", {\n\t\t\tdetail:\n\t\t\t\terror instanceof SCIMParseError ? error.message : \"Invalid SCIM filter\",\n\t\t\tscimType: \"invalidFilter\",\n\t\t});\n\t}\n\n\treturn filters;\n};\n","import type { BetterAuthPlugin } from \"better-auth\";\nimport { authMiddlewareFactory } from \"./middlewares\";\nimport {\n\tcreateSCIMUser,\n\tdeleteSCIMProviderConnection,\n\tdeleteSCIMUser,\n\tgenerateSCIMToken,\n\tgetSCIMProviderConnection,\n\tgetSCIMResourceType,\n\tgetSCIMResourceTypes,\n\tgetSCIMSchema,\n\tgetSCIMSchemas,\n\tgetSCIMServiceProviderConfig,\n\tgetSCIMUser,\n\tlistSCIMProviderConnections,\n\tlistSCIMUsers,\n\tpatchSCIMUser,\n\tupdateSCIMUser,\n} from \"./routes\";\nimport type { SCIMOptions } from \"./types\";\n\ndeclare module \"@better-auth/core\" {\n\tinterface BetterAuthPluginRegistry<AuthOptions, Options> {\n\t\tscim: {\n\t\t\tcreator: typeof scim;\n\t\t};\n\t}\n}\n\nexport const scim = (options?: SCIMOptions) => {\n\tconst opts = {\n\t\tstoreSCIMToken: \"plain\",\n\t\tproviderOwnership: { enabled: false },\n\t\t...options,\n\t} satisfies SCIMOptions;\n\n\tconst authMiddleware = authMiddlewareFactory(opts);\n\n\treturn {\n\t\tid: \"scim\",\n\t\tendpoints: {\n\t\t\tgenerateSCIMToken: generateSCIMToken(opts),\n\t\t\tlistSCIMProviderConnections: listSCIMProviderConnections(),\n\t\t\tgetSCIMProviderConnection: getSCIMProviderConnection(),\n\t\t\tdeleteSCIMProviderConnection: deleteSCIMProviderConnection(),\n\t\t\tgetSCIMUser: getSCIMUser(authMiddleware),\n\t\t\tcreateSCIMUser: createSCIMUser(authMiddleware),\n\t\t\tpatchSCIMUser: patchSCIMUser(authMiddleware),\n\t\t\tdeleteSCIMUser: deleteSCIMUser(authMiddleware),\n\t\t\tupdateSCIMUser: updateSCIMUser(authMiddleware),\n\t\t\tlistSCIMUsers: listSCIMUsers(authMiddleware),\n\t\t\tgetSCIMServiceProviderConfig,\n\t\t\tgetSCIMSchemas,\n\t\t\tgetSCIMSchema,\n\t\t\tgetSCIMResourceTypes,\n\t\t\tgetSCIMResourceType,\n\t\t},\n\t\tschema: {\n\t\t\tscimProvider: {\n\t\t\t\tfields: {\n\t\t\t\t\tproviderId: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tunique: true,\n\t\t\t\t\t},\n\t\t\t\t\tscimToken: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tunique: true,\n\t\t\t\t\t},\n\t\t\t\t\torganizationId: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\trequired: false,\n\t\t\t\t\t},\n\t\t\t\t\t...(opts.providerOwnership?.enabled\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tuserId: {\n\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\toptions,\n\t} satisfies BetterAuthPlugin;\n};\n\nexport * from \"./types\";\n"],"mappings":"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ACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,YAAY;GACZ;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,YAAY;GACZ;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,YAAY;GACZ,UAAU;GACV;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aAAa;GACb,UAAU;GACV,eAAe;IACd;KACC,MAAM;KACN,MAAM;KACN,aAAa;KACb,aACC;KACD,UAAU;KACV,WAAW;KACX,YAAY;KACZ,UAAU;KACV,YAAY;KACZ;IACD;KACC,MAAM;KACN,MAAM;KACN,aAAa;KACb,aACC;KACD,UAAU;KACV,WAAW;KACX,YAAY;KACZ,UAAU;KACV,YAAY;KACZ;IACD;KACC,MAAM;KACN,MAAM;KACN,aAAa;KACb,aACC;KACD,UAAU;KACV,WAAW;KACX,YAAY;KACZ,UAAU;KACV,YAAY;KACZ;IACD;GACD;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,eAAe,CACd;IACC,MAAM;IACN,MAAM;IACN,aAAa;IACb,aACC;IACD,UAAU;IACV,WAAW;IACX,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,EACD;IACC,MAAM;IACN,MAAM;IACN,aAAa;IACb,aACC;IACD,UAAU;IACV,YAAY;IACZ,UAAU;IACV,CACD;GACD,YAAY;GACZ,UAAU;GACV,YAAY;GACZ;EACD;CACD,MAAM;EACL,cAAc;EACd,UAAU;EACV;CACD;AAED,MAAa,uBAAuB;CACnC,SAAS,CAAC,qDAAqD;CAC/D,IAAI;CACJ,MAAM;CACN,UAAU;CACV,aAAa;CACb,QAAQ;CACR,MAAM;EACL,cAAc;EACd,UAAU;EACV;CACD;;;AC5MD,MAAM,gBAAoD,EACzD,IAAI,MACJ;AAED,MAAM,qBAAyD,EAC9D,UAAU,SACV;AAED,IAAa,iBAAb,cAAoC,MAAM;AAE1C,MAAM,kBACL;AAED,MAAM,mBAAmB,WAAmB;CAC3C,MAAM,QAAQ,OAAO,MAAM,gBAAgB;AAC3C,KAAI,CAAC,MACJ,OAAM,IAAI,eAAe,4BAA4B;CAGtD,MAAM,YAAY,MAAM,QAAQ;CAChC,MAAM,KAAK,MAAM,QAAQ,IAAI,aAAa;CAC1C,MAAM,QAAQ,MAAM,QAAQ;AAE5B,KAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MACzB,OAAM,IAAI,eAAe,4BAA4B;CAGtD,MAAM,WAAW,cAAc;AAC/B,KAAI,CAAC,SACJ,OAAM,IAAI,eAAe,iBAAiB,GAAG,oBAAoB;AAGlE,QAAO;EAAE;EAAW;EAAU;EAAO;;AAGtC,MAAa,uBAAuB,WAAmB;CACtD,MAAM,EAAE,WAAW,UAAU,UAAU,gBAAgB,OAAO;CAE9D,MAAM,UAAsB,EAAE;CAC9B,MAAM,kBAAkB,mBAAmB;CAC3C,MAAM,oBAAoB,uBAAuB,WAAW,MAC1D,SAAS,KAAK,SAAS,UACxB;AAED,KAAI,CAAC,mBAAmB,CAAC,kBACxB,OAAM,IAAI,eAAe,kBAAkB,UAAU,oBAAoB;CAG1E,IAAI,aAAa,MAAM,WAAW,MAAK,GAAG;AAC1C,KAAI,CAAC,kBAAkB,UACtB,cAAa,WAAW,aAAa;AAGtC,SAAQ,KAAK;EACZ,OAAO;EACP,OAAO;EACP;EACA,CAAC;AAEF,QAAO;;;;ACnER,MAAM,oCAAoC;CACzC,MAAM;CACN,YAAY,EACX,WAAW,EACV,MAAM,WACN,EACD;CACD;AAED,MAAa,+BAA+B;CAC3C,MAAM;CACN,YAAY;EACX,OAAO;EACP,MAAM;EACN,QAAQ;EACR,gBAAgB;EAChB,MAAM;EACN,MAAM;EACN,uBAAuB;GACtB,MAAM;GACN,OAAO;IACN,MAAM;IACN,YAAY;KACX,MAAM,EACL,MAAM,UACN;KACD,aAAa,EACZ,MAAM,UACN;KACD,SAAS,EACR,MAAM,UACN;KACD,MAAM,EACL,MAAM,UACN;KACD,SAAS,EACR,MAAM,WACN;KACD;IACD;GACD;EACD,SAAS;GACR,MAAM;GACN,OAAO,EACN,MAAM,UACN;GACD;EACD,MAAM;GACL,MAAM;GACN,YAAY,EACX,cAAc,EACb,MAAM,UACN,EACD;GACD;EACD;CACD;AAED,MAAa,4BAA4B;CACxC,MAAM;CACN,YAAY;EACX,SAAS;GACR,MAAM;GACN,OAAO,EAAE,MAAM,UAAU;GACzB;EACD,IAAI,EAAE,MAAM,UAAU;EACtB,MAAM,EAAE,MAAM,UAAU;EACxB,UAAU,EAAE,MAAM,UAAU;EAC5B,aAAa,EAAE,MAAM,UAAU;EAC/B,QAAQ,EAAE,MAAM,UAAU;EAC1B,MAAM;GACL,MAAM;GACN,YAAY;IACX,cAAc,EAAE,MAAM,UAAU;IAChC,UAAU,EAAE,MAAM,UAAU;IAC5B;GACD;EACD;CACD;AAED,MAAM,oCAAoC;CACzC,MAAM;CACN,YAAY;EACX,MAAM,EAAE,MAAM,UAAU;EACxB,MAAM,EAAE,MAAM,UAAU;EACxB,aAAa,EAAE,MAAM,WAAW;EAChC,aAAa,EAAE,MAAM,UAAU;EAC/B,UAAU,EAAE,MAAM,WAAW;EAC7B,WAAW,EAAE,MAAM,WAAW;EAC9B,YAAY,EAAE,MAAM,UAAU;EAC9B,UAAU,EAAE,MAAM,UAAU;EAC5B,YAAY,EAAE,MAAM,UAAU;EAC9B;CACD;AAED,MAAa,0BAA0B;CACtC,MAAM;CACN,YAAY;EACX,IAAI,EAAE,MAAM,UAAU;EACtB,SAAS;GACR,MAAM;GACN,OAAO,EAAE,MAAM,UAAU;GACzB;EACD,MAAM,EAAE,MAAM,UAAU;EACxB,aAAa,EAAE,MAAM,UAAU;EAC/B,YAAY;GACX,MAAM;GACN,OAAO;IACN,GAAG;IACH,YAAY;KACX,GAAG,kCAAkC;KACrC,eAAe;MACd,MAAM;MACN,OAAO;MACP;KACD;IACD;GACD;EACD,MAAM;GACL,MAAM;GACN,YAAY;IACX,cAAc,EAAE,MAAM,UAAU;IAChC,UAAU,EAAE,MAAM,UAAU;IAC5B;GACD,UAAU,CAAC,gBAAgB,WAAW;GACtC;EACD;CACD;;;AC/HD,MAAa,kBAAkB,MAAc,YAAoB;CAChE,MAAM,oBAAoB,QAAQ,SAAS,IAAI,GAAG,UAAU,GAAG,QAAQ;CACvE,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,GAAG;AAC/C,QAAO,IAAI,IAAI,gBAAgB,kBAAkB,CAAC,UAAU;;;;ACC7D,MAAa,sBACZ,SACA,MACA,YACI;AACJ,QAAO;EAIN,IAAI,KAAK;EACT,YAAY,SAAS;EACrB,MAAM;GACL,cAAc;GACd,SAAS,KAAK;GACd,cAAc,KAAK;GACnB,UAAU,eAAe,kBAAkB,KAAK,MAAM,QAAQ;GAC9D;EAKD,UAAU,KAAK;EACf,MAAM,EACL,WAAW,KAAK,MAChB;EACD,aAAa,KAAK;EAClB,QAAQ;EACR,QAAQ,CAAC;GAAE,SAAS;GAAM,OAAO,KAAK;GAAO,CAAC;EAC9C,SAAS,CAAC,uBAAuB,GAAG;EACpC;;;;ACKF,MAAM,uBAAuB,CAAC,uBAAuB;AACrD,MAAM,6BAA6B,CAAC,qBAAqB;AACzD,MAAM,sBAAsB,CAAC,oBAAoB,wBAAwB;AAEzE,MAAM,8BAA8B,EAAE,OAAO;CAC5C,YAAY,EAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,8BAA8B,CAAC;CAC1E,gBAAgB,EACd,QAAQ,CACR,UAAU,CACV,KAAK,EAAE,aAAa,4BAA4B,CAAC;CACnD,CAAC;AAEF,MAAM,uCAAuC,EAAE,OAAO,EACrD,YAAY,EAAE,QAAQ,EACtB,CAAC;AAEF,MAAM,yCAAyC,EAAE,OAAO,EACvD,YAAY,EAAE,QAAQ,EACtB,CAAC;AAEF,eAAe,kBACd,KACA,QACuB;CACvB,MAAM,UAAU,MAAM,IAAI,QAAQ,QAAQ,SAAiB;EAC1D,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAU,OAAO;GAAQ,CAAC;EAC3C,CAAC;AACF,QAAO,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,eAAe,CAAC;;AAGrD,SAAS,sBAAsB,UAAwB;AACtD,QAAO;EACN,IAAI,SAAS;EACb,YAAY,SAAS;EACrB,gBAAgB,SAAS,kBAAkB;EAC3C;;AAGF,eAAe,uBACd,KACA,QACA,gBACyB;AACzB,QAAO,IAAI,QAAQ,QAAQ,QAAgB;EAC1C,OAAO;EACP,OAAO,CACN;GACC,OAAO;GACP,OAAO;GACP,EACD;GACC,OAAO;GACP,OAAO;GACP,CACD;EACD,CAAC;;AAGH,eAAe,yBACd,KACA,QACA,UACgB;AAChB,KAAI,SAAS,gBAAgB;AAC5B,MAAI,CAAC,IAAI,QAAQ,UAAU,eAAe,CACzC,OAAM,IAAI,SAAS,aAAa,EAC/B,SAAS,gEACT,CAAC;AASH,MAAI,CANW,MAAM,uBACpB,KACA,QACA,SAAS,eACT,CAGA,OAAM,IAAI,SAAS,aAAa,EAC/B,SACC,oEACD,CAAC;YAEO,SAAS,UAAU,SAAS,WAAW,OACjD,OAAM,IAAI,SAAS,aAAa,EAC/B,SAAS,iDACT,CAAC;;AAIJ,eAAe,wBACd,KACA,QACA,YACwB;CACxB,MAAM,WAAW,MAAM,IAAI,QAAQ,QAAQ,QAAsB;EAChE,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAc,OAAO;GAAY,CAAC;EACnD,CAAC;AAEF,KAAI,CAAC,SACJ,OAAM,IAAI,SAAS,aAAa,EAC/B,SAAS,2BACT,CAAC;AAGH,OAAM,yBAAyB,KAAK,QAAQ,SAAS;AAErD,QAAO;;AAGR,MAAa,qBAAqB,SACjC,mBACC,wBACA;CACC,QAAQ;CACR,MAAM;CACN,UAAU,EACT,SAAS;EACR,SAAS;EACT,aACC;EACD,WAAW,EACV,OAAO;GACN,aAAa;GACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,WAAW;KACV,aAAa;KACb,MAAM;KACN,EACD;IACD,EACD,EACD;GACD,EACD;EACD,EACD;CACD,KAAK,CAAC,kBAAkB;CACxB,EACD,OAAO,QAAQ;CACd,MAAM,EAAE,YAAY,mBAAmB,IAAI;CAC3C,MAAM,OAAO,IAAI,QAAQ,QAAQ;AAEjC,KAAI,WAAW,SAAS,IAAI,CAC3B,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,6CACT,CAAC;AAGH,KAAI,kBAAkB,CAAC,IAAI,QAAQ,UAAU,eAAe,CAC3D,OAAM,IAAI,SAAS,eAAe,EACjC,SACC,2EACD,CAAC;CAGH,IAAI,SAAwB;AAC5B,KAAI,gBAAgB;AACnB,WAAS,MAAM,uBAAuB,KAAK,KAAK,IAAI,eAAe;AAEnE,MAAI,CAAC,OACJ,OAAM,IAAI,SAAS,aAAa,EAC/B,SAAS,4CACT,CAAC;;CAIJ,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,QAAsB;EACpE,OAAO;EACP,OAAO,CACN;GAAE,OAAO;GAAc,OAAO;GAAY,EAC1C,GAAI,iBACD,CAAC;GAAE,OAAO;GAAkB,OAAO;GAAgB,CAAC,GACpD,EAAE,CACL;EACD,CAAC;AAEF,KAAI,cAAc;AACjB,QAAM,yBAAyB,KAAK,KAAK,IAAI,aAAa;AAC1D,QAAM,IAAI,QAAQ,QAAQ,OAAqB;GAC9C,OAAO;GACP,OAAO,CAAC;IAAE,OAAO;IAAM,OAAO,aAAa;IAAI,CAAC;GAChD,CAAC;;CAGH,MAAM,YAAY,qBAAqB,GAAG;CAC1C,MAAM,YAAY,UAAU,OAC3B,GAAG,UAAU,GAAG,aAAa,iBAAiB,IAAI,mBAAmB,KACrE;AAED,KAAI,KAAK,yBACR,OAAM,KAAK,yBAAyB;EACnC;EACA;EACA;EACA,CAAC;CAGH,MAAM,kBAAkB,MAAM,IAAI,QAAQ,QAAQ,OAAqB;EACtE,OAAO;EACP,MAAM;GACO;GACI;GAChB,WAAW,MAAM,eAAe,KAAK,MAAM,UAAU;GACrD,GAAI,KAAK,mBAAmB,UAAU,EAAE,QAAQ,KAAK,IAAI,GAAG,EAAE;GAC9D;EACD,CAAC;AAEF,KAAI,KAAK,wBACR,OAAM,KAAK,wBAAwB;EAClC;EACA;EACA;EACA,cAAc;EACd,CAAC;AAGH,KAAI,UAAU,IAAI;AAElB,QAAO,IAAI,KAAK,EACf,WACA,CAAC;EAEH;AAEF,MAAa,oCACZ,mBACC,mCACA;CACC,QAAQ;CACR,KAAK,CAAC,kBAAkB;CACxB,UAAU,EACT,SAAS;EACR,aAAa;EACb,SAAS;EACT,aACC;EACD,WAAW,EACV,OAAO;GACN,aAAa;GACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,WAAW;KACV,MAAM;KACN,OAAO;MACN,MAAM;MACN,YAAY;OACX,IAAI,EAAE,MAAM,UAAU;OACtB,YAAY,EAAE,MAAM,UAAU;OAC9B,gBAAgB;QACf,MAAM;QACN,UAAU;QACV;OACD;MACD;KACD,EACD;IACD,EACD,EACD;GACD,EACD;EACD,EACD;CACD,EACD,OAAO,QAAQ;CACd,MAAM,SAAS,IAAI,QAAQ,QAAQ,KAAK;CACxC,MAAM,aAA0B,IAAI,QAAQ,UAAU,eAAe,GAClE,MAAM,kBAAkB,KAAK,OAAO,mBACpC,IAAI,KAAK;CAYZ,MAAM,aAVe,MAAM,IAAI,QAAQ,QAAQ,SAAuB,EACrE,OAAO,gBACP,CAAC,EAEuC,QAAQ,MAAM;AACtD,MAAI,EAAE,eAAgB,QAAO,WAAW,IAAI,EAAE,eAAe;AAC7D,MAAI,EAAE,WAAW,OAAQ,QAAO;AAChC,SAAO,CAAC,EAAE;GACT,CAEoC,KAAK,MAC1C,sBAAsB,EAAE,CACxB;AAED,QAAO,IAAI,KAAK,EAAE,WAAW,CAAC;EAE/B;AAEF,MAAa,kCACZ,mBACC,iCACA;CACC,QAAQ;CACR,KAAK,CAAC,kBAAkB;CACxB,OAAO;CACP,UAAU,EACT,SAAS;EACR,aAAa;EACb,SAAS;EACT,aAAa;EACb,WAAW;GACV,OAAO;IACN,aAAa;IACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;KACP,MAAM;KACN,YAAY;MACX,IAAI,EAAE,MAAM,UAAU;MACtB,YAAY,EAAE,MAAM,UAAU;MAC9B,gBAAgB;OACf,MAAM;OACN,UAAU;OACV;MACD;KACD,EACD,EACD;IACD;GACD,OAAO,EACN,aAAa,sBACb;GACD,OAAO,EACN,aAAa,iBACb;GACD;EACD,EACD;CACD,EACD,OAAO,QAAQ;CACd,MAAM,EAAE,eAAe,IAAI;CAC3B,MAAM,SAAS,IAAI,QAAQ,QAAQ,KAAK;CAExC,MAAM,WAAW,MAAM,wBAAwB,KAAK,QAAQ,WAAW;AAEvE,QAAO,IAAI,KAAK,sBAAsB,SAAS,CAAC;EAEjD;AAEF,MAAa,qCACZ,mBACC,oCACA;CACC,QAAQ;CACR,KAAK,CAAC,kBAAkB;CACxB,MAAM;CACN,UAAU,EACT,SAAS;EACR,aAAa;EACb,SAAS;EACT,aAAa;EACb,WAAW;GACV,OAAO;IACN,aAAa;IACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;KACP,MAAM;KACN,YAAY,EACX,SAAS,EAAE,MAAM,WAAW,EAC5B;KACD,EACD,EACD;IACD;GACD,OAAO,EACN,aAAa,sBACb;GACD,OAAO,EACN,aAAa,iBACb;GACD;EACD,EACD;CACD,EACD,OAAO,QAAQ;CACd,MAAM,EAAE,eAAe,IAAI;CAC3B,MAAM,SAAS,IAAI,QAAQ,QAAQ,KAAK;AAExC,OAAM,wBAAwB,KAAK,QAAQ,WAAW;AAEtD,OAAM,IAAI,QAAQ,QAAQ,OAAqB;EAC9C,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAc,OAAO;GAAY,CAAC;EACnD,CAAC;AAEF,QAAO,IAAI,KAAK,EAAE,SAAS,MAAM,CAAC;EAEnC;AAEF,MAAa,kBAAkB,mBAC9B,mBACC,kBACA;CACC,QAAQ;CACR,MAAM;CACN,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ,2BACR,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,KAAK,CAAC,eAAe;CACrB,EACD,OAAO,QAAQ;CACd,MAAM,OAAO,IAAI;CACjB,MAAM,aAAa,IAAI,QAAQ,aAAa;CAC5C,MAAM,YAAY,aAAa,KAAK,UAAU,KAAK,WAAW;AAU9D,KARwB,MAAM,IAAI,QAAQ,QAAQ,QAAiB;EAClE,OAAO;EACP,OAAO,CACN;GAAE,OAAO;GAAa,OAAO;GAAW,EACxC;GAAE,OAAO;GAAc,OAAO;GAAY,CAC1C;EACD,CAAC,CAGD,OAAM,IAAI,aAAa,YAAY;EAClC,QAAQ;EACR,UAAU;EACV,CAAC;CAGH,MAAM,QAAQ,oBAAoB,KAAK,UAAU,KAAK,OAAO;CAC7D,MAAM,OAAO,gBAAgB,OAAO,KAAK,KAAK;CAE9C,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,QAAc;EAC5D,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAS,OAAO;GAAO,CAAC;EACzC,CAAC;CAEF,MAAM,iBAAiB,WACtB,IAAI,QAAQ,gBAAgB,cAAc;EACjC;EACI;EACD;EACX,aAAa;EACb,cAAc;EACd,CAAC;CAEH,MAAM,mBACL,IAAI,QAAQ,gBAAgB,WAAW;EACtC;EACA;EACA,CAAC;CAEH,MAAM,sBAAsB,OAAO,WAAmB;EACrD,MAAM,iBAAiB,IAAI,QAAQ,aAAa;AAEhD,MAAI;OASC,CARgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACrD,OAAO;IACP,OAAO,CACN;KAAE,OAAO;KAAkB,OAAO;KAAgB,EAClD;KAAE,OAAO;KAAU,OAAO;KAAQ,CAClC;IACD,CAAC,CAGD,QAAO,MAAM,IAAI,QAAQ,QAAQ,OAAe;IAC/C,OAAO;IACP,MAAM;KACG;KACR,MAAM;KACN,2BAAW,IAAI,MAAM;KACrB;KACA;IACD,CAAC;;;CAKL,IAAI;CACJ,IAAI;AAEJ,KAAI,cAAc;AACjB,SAAO;AACP,YAAU,MAAM,IAAI,QAAQ,QAAQ,YAAqB,YAAY;GACpE,MAAM,UAAU,MAAM,cAAc,KAAK,GAAG;AAC5C,SAAM,oBAAoB,KAAK,GAAG;AAClC,UAAO;IACN;OAEF,EAAC,MAAM,WAAW,MAAM,IAAI,QAAQ,QAAQ,YAE1C,YAAY;EACb,MAAM,OAAO,MAAM,YAAY;EAC/B,MAAM,UAAU,MAAM,cAAc,KAAK,GAAG;AAC5C,QAAM,oBAAoB,KAAK,GAAG;AAClC,SAAO,CAAC,MAAM,QAAQ;GACrB;CAGH,MAAM,eAAe,mBACpB,IAAI,QAAQ,SACZ,MACA,QACA;AAED,KAAI,UAAU,IAAI;AAClB,KAAI,UAAU,YAAY,aAAa,KAAK,SAAS;AACrD,QAAO,IAAI,KAAK,aAAa;EAE9B;AAEF,MAAa,kBAAkB,mBAC9B,mBACC,0BACA;CACC,QAAQ;CACR,MAAM;CACN,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ,2BACR,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,KAAK,CAAC,eAAe;CACrB,EACD,OAAO,QAAQ;CACd,MAAM,OAAO,IAAI;CACjB,MAAM,SAAS,IAAI,OAAO;CAC1B,MAAM,EAAE,gBAAgB,eAAe,IAAI,QAAQ;CACnD,MAAM,YAAY,aAAa,KAAK,UAAU,KAAK,WAAW;CAE9D,MAAM,EAAE,MAAM,YAAY,MAAM,aAAa,IAAI,QAAQ,SAAS;EACjE;EACA;EACA;EACA,CAAC;AAEF,KAAI,CAAC,KACJ,OAAM,IAAI,aAAa,aAAa,EACnC,QAAQ,kBACR,CAAC;CAGH,MAAM,CAAC,aAAa,kBACnB,MAAM,IAAI,QAAQ,QAAQ,YACzB,YAAY;EACX,MAAM,QAAQ,oBAAoB,KAAK,UAAU,KAAK,OAAO;EAC7D,MAAM,OAAO,gBAAgB,OAAO,KAAK,KAAK;AAiB9C,SAAO,CAfa,MAAM,IAAI,QAAQ,gBAAgB,WACrD,QACA;GACC;GACA;GACA,2BAAW,IAAI,MAAM;GACrB,CACD,EAGA,MAAM,IAAI,QAAQ,gBAAgB,cAAc,QAAQ,IAAI;GAC3D;GACA,2BAAW,IAAI,MAAM;GACrB,CAAC,CAEiC;GAErC;CAEF,MAAM,eAAe,mBACpB,IAAI,QAAQ,SACZ,aACA,eACA;AAED,QAAO,IAAI,KAAK,aAAa;EAE9B;AAEF,MAAM,2BAA2B,EAC/B,OAAO,EACP,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAC7B,CAAC,CACD,UAAU;AAEZ,MAAa,iBAAiB,mBAC7B,mBACC,kBACA;CACC,QAAQ;CACR,OAAO;CACP,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;MACP,MAAM;MACN,YAAY;OACX,cAAc,EAAE,MAAM,UAAU;OAChC,cAAc,EAAE,MAAM,UAAU;OAChC,YAAY,EAAE,MAAM,UAAU;OAC9B,WAAW;QACV,MAAM;QACN,OAAO;QACP;OACD;MACD,EACD,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,KAAK,CAAC,eAAe;CACrB,EACD,OAAO,QAAQ;CACd,MAAM,oBAAoB;EACzB,SAAS,CAAC,qDAAqD;EAC/D,cAAc;EACd,YAAY;EACZ,cAAc;EACd,WAAW,EAAE;EACb;CAED,MAAM,aAAyB,uBAAuB,IAAI,OAAO,OAAO;AAExE,KAAI,QAAQ,OAAO,KAAK,kCAAkC,WAAW;CAErE,MAAM,aAAa,IAAI,QAAQ,aAAa;CAC5C,MAAM,WAAW,MAAM,IAAI,QAAQ,QAAQ,SAAkB;EAC5D,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAc,OAAO;GAAY,CAAC;EACnD,CAAC;CAEF,MAAM,iBAAiB,SAAS,KAAK,YAAY,QAAQ,OAAO;AAIhE,KAAI,eAAe,WAAW,EAC7B,QAAO,IAAI,KAAK,kBAAkB;CAGnC,IAAI,cAA0B,CAC7B;EAAE,OAAO;EAAM,OAAO;EAAgB,UAAU;EAAM,CACtD;CAED,MAAM,iBAAiB,IAAI,QAAQ,aAAa;AAChD,KAAI,gBAAgB;EASnB,MAAM,iBARU,MAAM,IAAI,QAAQ,QAAQ,SAAiB;GAC1D,OAAO;GACP,OAAO,CACN;IAAE,OAAO;IAAkB,OAAO;IAAgB,EAClD;IAAE,OAAO;IAAU,OAAO;IAAgB,UAAU;IAAM,CAC1D;GACD,CAAC,EAE4B,KAAK,WAAW,OAAO,OAAO;AAI5D,MAAI,cAAc,WAAW,EAC5B,QAAO,IAAI,KAAK,kBAAkB;AAGnC,gBAAc,CAAC;GAAE,OAAO;GAAM,OAAO;GAAe,UAAU;GAAM,CAAC;;CAGtE,MAAM,QAAQ,MAAM,IAAI,QAAQ,QAAQ,SAAe;EACtD,OAAO;EACP,OAAO,CAAC,GAAG,aAAa,GAAG,WAAW;EACtC,CAAC;AAEF,QAAO,IAAI,KAAK;EACf,SAAS,CAAC,qDAAqD;EAC/D,cAAc,MAAM;EACpB,YAAY;EACZ,cAAc,MAAM;EACpB,WAAW,MAAM,KAAK,SAAS;GAC9B,MAAM,UAAU,SAAS,MAAM,MAAM,EAAE,WAAW,KAAK,GAAG;AAC1D,UAAO,mBAAmB,IAAI,QAAQ,SAAS,MAAM,QAAQ;IAC5D;EACF,CAAC;EAEH;AAEF,MAAa,eAAe,mBAC3B,mBACC,0BACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ,2BACR,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,KAAK,CAAC,eAAe;CACrB,EACD,OAAO,QAAQ;CACd,MAAM,SAAS,IAAI,OAAO;CAC1B,MAAM,aAAa,IAAI,QAAQ,aAAa;CAC5C,MAAM,iBAAiB,IAAI,QAAQ,aAAa;CAEhD,MAAM,EAAE,MAAM,YAAY,MAAM,aAAa,IAAI,QAAQ,SAAS;EACjE;EACA;EACA;EACA,CAAC;AAEF,KAAI,CAAC,KACJ,OAAM,IAAI,aAAa,aAAa,EACnC,QAAQ,kBACR,CAAC;AAGH,QAAO,IAAI,KAAK,mBAAmB,IAAI,QAAQ,SAAS,MAAM,QAAQ,CAAC;EAExE;AAEF,MAAM,0BAA0B,EAAE,OAAO;CACxC,SAAS,EACP,MAAM,EAAE,QAAQ,CAAC,CACjB,QACC,MAAM,EAAE,SAAS,gDAAgD,EAClE,EACC,SAAS,+BACT,CACD;CACF,YAAY,EAAE,MACb,EAAE,OAAO;EACR,IAAI,EACF,QAAQ,CACR,aAAa,CACb,QAAQ,UAAU,CAClB,KAAK,EAAE,KAAK;GAAC;GAAW;GAAO;GAAS,CAAC,CAAC;EAC5C,MAAM,EAAE,QAAQ,CAAC,UAAU;EAC3B,OAAO,EAAE,KAAK;EACd,CAAC,CACF;CACD,CAAC;AAEF,MAAa,iBAAiB,mBAC7B,mBACC,0BACA;CACC,QAAQ;CACR,MAAM;CACN,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aAAa;GACb,WAAW;IACV,OAAO,EACN,aAAa,kCACb;IACD,GAAG;IACH;GACD;EACD;CACD,KAAK,CAAC,eAAe;CACrB,EACD,OAAO,QAAQ;CACd,MAAM,SAAS,IAAI,OAAO;CAC1B,MAAM,iBAAiB,IAAI,QAAQ,aAAa;CAChD,MAAM,aAAa,IAAI,QAAQ,aAAa;CAE5C,MAAM,EAAE,MAAM,YAAY,MAAM,aAAa,IAAI,QAAQ,SAAS;EACjE;EACA;EACA;EACA,CAAC;AAEF,KAAI,CAAC,KACJ,OAAM,IAAI,aAAa,aAAa,EACnC,QAAQ,kBACR,CAAC;CAGH,MAAM,EAAE,MAAM,WAAW,SAAS,iBAAiB,eAClD,MACA,IAAI,KAAK,WACT;AAED,KACC,OAAO,KAAK,UAAU,CAAC,WAAW,KAClC,OAAO,KAAK,aAAa,CAAC,WAAW,EAErC,OAAM,IAAI,aAAa,eAAe,EACrC,QAAQ,6BACR,CAAC;AAGH,OAAM,QAAQ,IAAI,CACjB,OAAO,KAAK,UAAU,CAAC,SAAS,IAC7B,IAAI,QAAQ,gBAAgB,WAAW,QAAQ;EAC/C,GAAG;EACH,2BAAW,IAAI,MAAM;EACrB,CAAC,GACD,QAAQ,SAAS,EACpB,OAAO,KAAK,aAAa,CAAC,SAAS,IAChC,IAAI,QAAQ,gBAAgB,cAAc,QAAQ,IAAI;EACtD,GAAG;EACH,2BAAW,IAAI,MAAM;EACrB,CAAC,GACD,QAAQ,SAAS,CACpB,CAAC;AAEF,KAAI,UAAU,IAAI;EAGnB;AAEF,MAAa,kBAAkB,mBAC9B,mBACC,0BACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB,CAAC,GAAG,qBAAqB,GAAG;EAC/C,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO,EACN,aAAa,+BACb;IACD,GAAG;IACH;GACD;EACD;CACD,KAAK,CAAC,eAAe;CACrB,EACD,OAAO,QAAQ;CACd,MAAM,SAAS,IAAI,OAAO;CAC1B,MAAM,aAAa,IAAI,QAAQ,aAAa;CAC5C,MAAM,iBAAiB,IAAI,QAAQ,aAAa;CAEhD,MAAM,EAAE,SAAS,MAAM,aAAa,IAAI,QAAQ,SAAS;EACxD;EACA;EACA;EACA,CAAC;AAEF,KAAI,CAAC,KACJ,OAAM,IAAI,aAAa,aAAa,EACnC,QAAQ,kBACR,CAAC;AAGH,OAAM,IAAI,QAAQ,gBAAgB,WAAW,OAAO;AAEpD,KAAI,UAAU,IAAI;EAGnB;AAEF,MAAa,+BAA+B,mBAC3C,kCACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ,8BACR,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,EACD,OAAO,QAAQ;AACd,QAAO,IAAI,KAAK;EACf,OAAO,EAAE,WAAW,MAAM;EAC1B,MAAM,EAAE,WAAW,OAAO;EAC1B,QAAQ,EAAE,WAAW,MAAM;EAC3B,gBAAgB,EAAE,WAAW,OAAO;EACpC,MAAM,EAAE,WAAW,OAAO;EAC1B,MAAM,EAAE,WAAW,OAAO;EAC1B,uBAAuB,CACtB;GACC,MAAM;GACN,aACC;GACD,SAAS;GACT,MAAM;GACN,SAAS;GACT,CACD;EACD,SAAS,CAAC,8DAA8D;EACxE,MAAM,EACL,cAAc,yBACd;EACD,CAAC;EAEH;AAED,MAAa,iBAAiB,mBAC7B,oBACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;MACP,MAAM;MACN,OAAO;MACP,EACD,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,EACD,OAAO,QAAQ;AACd,QAAO,IAAI,KAAK;EACf,cAAc,qBAAqB;EACnC,cAAc,qBAAqB;EACnC,YAAY;EACZ,SAAS,CAAC,qDAAqD;EAC/D,WAAW,qBAAqB,KAAK,MAAM;AAC1C,UAAO;IACN,GAAG;IACH,MAAM;KACL,GAAG,EAAE;KACL,UAAU,eAAe,EAAE,KAAK,UAAU,IAAI,QAAQ,QAAQ;KAC9D;IACD;IACA;EACF,CAAC;EAEH;AAED,MAAa,gBAAgB,mBAC5B,8BACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ,yBACR,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,EACD,OAAO,QAAQ;CACd,MAAM,SAAS,qBAAqB,MAClC,MAAM,EAAE,OAAO,IAAI,OAAO,SAC3B;AAED,KAAI,CAAC,OACJ,OAAM,IAAI,aAAa,aAAa,EACnC,QAAQ,oBACR,CAAC;AAGH,QAAO,IAAI,KAAK;EACf,GAAG;EACH,MAAM;GACL,GAAG,OAAO;GACV,UAAU,eAAe,OAAO,KAAK,UAAU,IAAI,QAAQ,QAAQ;GACnE;EACD,CAAC;EAEH;AAED,MAAa,uBAAuB,mBACnC,0BACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;MACP,MAAM;MACN,YAAY;OACX,cAAc,EAAE,MAAM,UAAU;OAChC,cAAc,EAAE,MAAM,UAAU;OAChC,YAAY,EAAE,MAAM,UAAU;OAC9B,WAAW;QACV,MAAM;QACN,OAAO;QACP;OACD;MACD,EACD,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,EACD,OAAO,QAAQ;AACd,QAAO,IAAI,KAAK;EACf,cAAc,2BAA2B;EACzC,cAAc,2BAA2B;EACzC,YAAY;EACZ,SAAS,CAAC,qDAAqD;EAC/D,WAAW,2BAA2B,KAAK,MAAM;AAChD,UAAO;IACN,GAAG;IACH,MAAM;KACL,GAAG,EAAE;KACL,UAAU,eAAe,EAAE,KAAK,UAAU,IAAI,QAAQ,QAAQ;KAC9D;IACD;IACA;EACF,CAAC;EAEH;AAED,MAAa,sBAAsB,mBAClC,0CACA;CACC,QAAQ;CACR,UAAU;EACT,GAAG;EACH,mBAAmB;EACnB,SAAS;GACR,SAAS;GACT,aACC;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ,2BACR,EACD;KACD;IACD,GAAG;IACH;GACD;EACD;CACD,EACD,OAAO,QAAQ;CACd,MAAM,eAAe,2BAA2B,MAC9C,MAAM,EAAE,OAAO,IAAI,OAAO,eAC3B;AAED,KAAI,CAAC,aACJ,OAAM,IAAI,aAAa,aAAa,EACnC,QAAQ,2BACR,CAAC;AAGH,QAAO,IAAI,KAAK;EACf,GAAG;EACH,MAAM;GACL,GAAG,aAAa;GAChB,UAAU,eACT,aAAa,KAAK,UAClB,IAAI,QAAQ,QACZ;GACD;EACD,CAAC;EAEH;AAED,MAAM,eAAe,OACpB,SACA,EACC,QACA,YACA,qBAEG;CACJ,MAAM,UAAU,MAAM,QAAQ,QAAiB;EAC9C,OAAO;EACP,OAAO,CACN;GAAE,OAAO;GAAU,OAAO;GAAQ,EAClC;GAAE,OAAO;GAAc,OAAO;GAAY,CAC1C;EACD,CAAC;AAKF,KAAI,CAAC,QACJ,QAAO;EAAE,MAAM;EAAM,SAAS;EAAM;CAGrC,IAAI,SAAwB;AAC5B,KAAI,eACH,UAAS,MAAM,QAAQ,QAAgB;EACtC,OAAO;EACP,OAAO,CACN;GAAE,OAAO;GAAkB,OAAO;GAAgB,EAClD;GAAE,OAAO;GAAU,OAAO;GAAQ,CAClC;EACD,CAAC;AAMH,KAAI,kBAAkB,CAAC,OACtB,QAAO;EAAE,MAAM;EAAM,SAAS;EAAM;CAGrC,MAAM,OAAO,MAAM,QAAQ,QAAc;EACxC,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAM,OAAO;GAAQ,CAAC;EACvC,CAAC;AAEF,KAAI,CAAC,KACJ,QAAO;EAAE,MAAM;EAAM,SAAS;EAAM;AAGrC,QAAO;EAAE;EAAM;EAAS;;AAGzB,MAAM,0BAA0B,WAAoB;CACnD,IAAI,UAAsB,EAAE;AAE5B,KAAI;AACH,YAAU,SAAS,oBAAoB,OAAO,GAAG,EAAE;UAC3C,OAAO;AACf,QAAM,IAAI,aAAa,eAAe;GACrC,QACC,iBAAiB,iBAAiB,MAAM,UAAU;GACnD,UAAU;GACV,CAAC;;AAGH,QAAO;;;;ACrtCR,MAAa,QAAQ,YAA0B;CAC9C,MAAM,OAAO;EACZ,gBAAgB;EAChB,mBAAmB,EAAE,SAAS,OAAO;EACrC,GAAG;EACH;CAED,MAAM,iBAAiB,sBAAsB,KAAK;AAElD,QAAO;EACN,IAAI;EACJ,WAAW;GACV,mBAAmB,kBAAkB,KAAK;GAC1C,6BAA6B,6BAA6B;GAC1D,2BAA2B,2BAA2B;GACtD,8BAA8B,8BAA8B;GAC5D,aAAa,YAAY,eAAe;GACxC,gBAAgB,eAAe,eAAe;GAC9C,eAAe,cAAc,eAAe;GAC5C,gBAAgB,eAAe,eAAe;GAC9C,gBAAgB,eAAe,eAAe;GAC9C,eAAe,cAAc,eAAe;GAC5C;GACA;GACA;GACA;GACA;GACA;EACD,QAAQ,EACP,cAAc,EACb,QAAQ;GACP,YAAY;IACX,MAAM;IACN,UAAU;IACV,QAAQ;IACR;GACD,WAAW;IACV,MAAM;IACN,UAAU;IACV,QAAQ;IACR;GACD,gBAAgB;IACf,MAAM;IACN,UAAU;IACV;GACD,GAAI,KAAK,mBAAmB,UACzB,EACA,QAAQ;IACP,MAAM;IACN,UAAU;IACV,EACD,GACA,EAAE;GACL,EACD,EACD;EACD;EACA"}
|