@keycloak/keycloak-admin-client 24.0.4 → 25.0.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/README.md CHANGED
@@ -53,7 +53,7 @@ const groups = await kcAdminClient.groups.find();
53
53
 
54
54
  // Set a `realm` property to override the realm for only a single operation.
55
55
  // For example, creating a user in another realm:
56
- await this.kcAdminClient.users.create({
56
+ await kcAdminClient.users.create({
57
57
  realm: 'a-third-realm',
58
58
  username: 'username',
59
59
  email: 'user@example.com',
@@ -107,13 +107,13 @@ setInterval(() => kcAdminClient.auth(credentials), 58 * 1000); // 58 seconds
107
107
  To build the source do a build:
108
108
 
109
109
  ```bash
110
- pnpm run build
110
+ pnpm build
111
111
  ```
112
112
 
113
113
  Start the Keycloak server:
114
114
 
115
115
  ```bash
116
- pnpm run server:start
116
+ pnpm server:start
117
117
  ```
118
118
 
119
119
  If you started your container manually make sure there is an admin user named 'admin' with password 'admin'.
package/lib/client.d.ts CHANGED
@@ -9,6 +9,7 @@ import { Components } from "./resources/components.js";
9
9
  import { Groups } from "./resources/groups.js";
10
10
  import { IdentityProviders } from "./resources/identityProviders.js";
11
11
  import { Realms } from "./resources/realms.js";
12
+ import { Organizations } from "./resources/organizations.js";
12
13
  import { Roles } from "./resources/roles.js";
13
14
  import { ServerInfo } from "./resources/serverInfo.js";
14
15
  import { Users } from "./resources/users.js";
@@ -30,6 +31,7 @@ export declare class KeycloakAdminClient {
30
31
  userStorageProvider: UserStorageProvider;
31
32
  groups: Groups;
32
33
  roles: Roles;
34
+ organizations: Organizations;
33
35
  clients: Clients;
34
36
  realms: Realms;
35
37
  clientScopes: ClientScopes;
package/lib/client.js CHANGED
@@ -8,6 +8,7 @@ import { Components } from "./resources/components.js";
8
8
  import { Groups } from "./resources/groups.js";
9
9
  import { IdentityProviders } from "./resources/identityProviders.js";
10
10
  import { Realms } from "./resources/realms.js";
11
+ import { Organizations } from "./resources/organizations.js";
11
12
  import { Roles } from "./resources/roles.js";
12
13
  import { ServerInfo } from "./resources/serverInfo.js";
13
14
  import { Users } from "./resources/users.js";
@@ -21,6 +22,7 @@ export class KeycloakAdminClient {
21
22
  userStorageProvider;
22
23
  groups;
23
24
  roles;
25
+ organizations;
24
26
  clients;
25
27
  realms;
26
28
  clientScopes;
@@ -51,6 +53,7 @@ export class KeycloakAdminClient {
51
53
  this.userStorageProvider = new UserStorageProvider(this);
52
54
  this.groups = new Groups(this);
53
55
  this.roles = new Roles(this);
56
+ this.organizations = new Organizations(this);
54
57
  this.clients = new Clients(this);
55
58
  this.realms = new Realms(this);
56
59
  this.clientScopes = new ClientScopes(this);
@@ -3,5 +3,6 @@ import type ClientPolicyRepresentation from "./clientPolicyRepresentation.js";
3
3
  * https://www.keycloak.org/docs-api/15.0/rest-api/#_clientpoliciesrepresentation
4
4
  */
5
5
  export default interface ClientPoliciesRepresentation {
6
+ globalPolicies?: ClientPolicyRepresentation[];
6
7
  policies?: ClientPolicyRepresentation[];
7
8
  }
@@ -0,0 +1,4 @@
1
+ export default interface OrganizationDomainRepresentation {
2
+ name?: string;
3
+ verified?: boolean;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type OrganizationDomainRepresentation from "./organizationDomainRepresentation.js";
2
+ export default interface OrganizationRepresentation {
3
+ id?: string;
4
+ name?: string;
5
+ description?: string;
6
+ enabled?: boolean;
7
+ attributes?: Record<string, string[]>;
8
+ domains?: OrganizationDomainRepresentation[];
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -77,6 +77,7 @@ export default interface RealmRepresentation {
77
77
  offlineSessionIdleTimeout?: number;
78
78
  offlineSessionMaxLifespan?: number;
79
79
  offlineSessionMaxLifespanEnabled?: boolean;
80
+ organizationsEnabled?: boolean;
80
81
  otpPolicyAlgorithm?: string;
81
82
  otpPolicyDigits?: number;
82
83
  otpPolicyInitialCounter?: number;
@@ -0,0 +1,4 @@
1
+ import { ConfigPropertyRepresentation } from "./configPropertyRepresentation.js";
2
+ export default interface RequiredActionConfigInfoRepresentation {
3
+ properties?: ConfigPropertyRepresentation[];
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export default interface RequiredActionConfigRepresentation {
2
+ config?: {
3
+ [index: string]: string;
4
+ };
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -6,4 +6,5 @@ export default interface UserSessionRepresentation {
6
6
  start?: number;
7
7
  userId?: string;
8
8
  username?: string;
9
+ transientUser?: boolean;
9
10
  }
@@ -111,7 +111,10 @@ export class Agent {
111
111
  }
112
112
  else {
113
113
  // Otherwise assume it's JSON and stringify it.
114
- requestOptions.body = JSON.stringify(payloadKey ? payload[payloadKey] : payload);
114
+ requestOptions.body =
115
+ payloadKey && typeof payload[payloadKey] === "string"
116
+ ? payload[payloadKey]
117
+ : JSON.stringify(payloadKey ? payload[payloadKey] : payload);
115
118
  }
116
119
  if (!requestHeaders.has("content-type") && !(payload instanceof FormData)) {
117
120
  requestHeaders.set("content-type", "application/json");
@@ -7,6 +7,8 @@ import type AuthenticatorConfigRepresentation from "../defs/authenticatorConfigR
7
7
  import type { AuthenticationProviderRepresentation } from "../defs/authenticatorConfigRepresentation.js";
8
8
  import type AuthenticatorConfigInfoRepresentation from "../defs/authenticatorConfigInfoRepresentation.js";
9
9
  import type RequiredActionProviderSimpleRepresentation from "../defs/requiredActionProviderSimpleRepresentation.js";
10
+ import type RequiredActionConfigInfoRepresentation from "../defs/requiredActionConfigInfoRepresentation.js";
11
+ import type RequiredActionConfigRepresentation from "../defs/requiredActionConfigRepresentation.js";
10
12
  export declare class AuthenticationManagement extends Resource<{
11
13
  realm?: string;
12
14
  }> {
@@ -132,6 +134,26 @@ export declare class AuthenticationManagement extends Resource<{
132
134
  } & {
133
135
  realm?: string | undefined;
134
136
  }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<any>;
137
+ getRequiredActionConfigDescription: (payload?: ({
138
+ alias: string;
139
+ } & {
140
+ realm?: string | undefined;
141
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<RequiredActionConfigInfoRepresentation>;
142
+ getRequiredActionConfig: (payload?: ({
143
+ alias: string;
144
+ } & {
145
+ realm?: string | undefined;
146
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<RequiredActionConfigRepresentation>;
147
+ removeRequiredActionConfig: (payload?: ({
148
+ alias: string;
149
+ } & {
150
+ realm?: string | undefined;
151
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<any>;
152
+ updateRequiredActionConfig: (query: {
153
+ alias: string;
154
+ } & {
155
+ realm?: string | undefined;
156
+ }, payload: RequiredActionConfigRepresentation) => Promise<void>;
135
157
  getConfigDescription: (payload?: ({
136
158
  providerId: string;
137
159
  } & {
@@ -137,6 +137,30 @@ export class AuthenticationManagement extends Resource {
137
137
  path: "/executions/{id}/raise-priority",
138
138
  urlParamKeys: ["id"],
139
139
  });
140
+ // Get required actions provider's configuration description
141
+ getRequiredActionConfigDescription = this.makeRequest({
142
+ method: "GET",
143
+ path: "/required-actions/{alias}/config-description",
144
+ urlParamKeys: ["alias"],
145
+ });
146
+ // Get the configuration of the RequiredAction provider in the current Realm.
147
+ getRequiredActionConfig = this.makeRequest({
148
+ method: "GET",
149
+ path: "/required-actions/{alias}/config",
150
+ urlParamKeys: ["alias"],
151
+ });
152
+ // Remove the configuration from the RequiredAction provider in the current Realm.
153
+ removeRequiredActionConfig = this.makeRequest({
154
+ method: "DELETE",
155
+ path: "/required-actions/{alias}/config",
156
+ urlParamKeys: ["alias"],
157
+ });
158
+ // Update the configuration from the RequiredAction provider in the current Realm.
159
+ updateRequiredActionConfig = this.makeUpdateRequest({
160
+ method: "PUT",
161
+ path: "/required-actions/{alias}/config",
162
+ urlParamKeys: ["alias"],
163
+ });
140
164
  getConfigDescription = this.makeRequest({
141
165
  method: "GET",
142
166
  path: "config-description/{providerId}",
@@ -17,9 +17,11 @@ export declare class ClientPolicies extends Resource<{
17
17
  createProfiles: (payload?: (ClientProfilesRepresentation & {
18
18
  realm?: string | undefined;
19
19
  }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<void>;
20
- listPolicies: (payload?: {
20
+ listPolicies: (payload?: ({
21
+ includeGlobalPolicies?: boolean | undefined;
22
+ } & {
21
23
  realm?: string | undefined;
22
- } | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<ClientPoliciesRepresentation>;
24
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<ClientPoliciesRepresentation>;
23
25
  updatePolicy: (payload?: (ClientPoliciesRepresentation & {
24
26
  realm?: string | undefined;
25
27
  }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<void>;
@@ -29,6 +29,10 @@ export class ClientPolicies extends Resource {
29
29
  listPolicies = this.makeRequest({
30
30
  method: "GET",
31
31
  path: "/policies",
32
+ queryParamKeys: ["include-global-policies"],
33
+ keyTransform: {
34
+ includeGlobalPolicies: "include-global-policies",
35
+ },
32
36
  });
33
37
  updatePolicy = this.makeRequest({
34
38
  method: "PUT",
@@ -27,6 +27,7 @@ export interface ClientQuery extends PaginatedQuery {
27
27
  clientId?: string;
28
28
  viewableOnly?: boolean;
29
29
  search?: boolean;
30
+ q?: string;
30
31
  }
31
32
  export interface ResourceQuery extends PaginatedQuery {
32
33
  id?: string;
@@ -93,7 +94,7 @@ export declare class Clients extends Resource<{
93
94
  roleName: string;
94
95
  } & {
95
96
  realm?: string | undefined;
96
- }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<RoleRepresentation>;
97
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<RoleRepresentation | null>;
97
98
  updateRole: (query: {
98
99
  id: string;
99
100
  roleName: string;
@@ -19,7 +19,7 @@ interface SummarizedQuery {
19
19
  briefRepresentation?: boolean;
20
20
  }
21
21
  export type GroupQuery = Query & PaginatedQuery & SummarizedQuery;
22
- export type SubGroupQuery = PaginatedQuery & SummarizedQuery & {
22
+ export type SubGroupQuery = Query & PaginatedQuery & SummarizedQuery & {
23
23
  parentId: string;
24
24
  };
25
25
  export interface GroupCountQuery {
@@ -97,7 +97,7 @@ export declare class Groups extends Resource<{
97
97
  /**
98
98
  * Finds all subgroups on the specified parent group matching the provided parameters.
99
99
  */
100
- listSubGroups: (payload?: (PaginatedQuery & SummarizedQuery & {
100
+ listSubGroups: (payload?: (Query & PaginatedQuery & SummarizedQuery & {
101
101
  parentId: string;
102
102
  } & {
103
103
  realm?: string | undefined;
@@ -77,7 +77,7 @@ export class Groups extends Resource {
77
77
  method: "GET",
78
78
  path: "/{parentId}/children",
79
79
  urlParamKeys: ["parentId"],
80
- queryParamKeys: ["first", "max", "briefRepresentation"],
80
+ queryParamKeys: ["search", "first", "max", "briefRepresentation"],
81
81
  catchNotFound: true,
82
82
  });
83
83
  /**
@@ -0,0 +1,86 @@
1
+ import type { KeycloakAdminClient } from "../client.js";
2
+ import IdentityProviderRepresentation from "../defs/identityProviderRepresentation.js";
3
+ import type OrganizationRepresentation from "../defs/organizationRepresentation.js";
4
+ import UserRepresentation from "../defs/userRepresentation.js";
5
+ import Resource from "./resource.js";
6
+ interface PaginatedQuery {
7
+ first?: number;
8
+ max?: number;
9
+ search?: string;
10
+ }
11
+ export interface OrganizationQuery extends PaginatedQuery {
12
+ q?: string;
13
+ exact?: boolean;
14
+ }
15
+ interface MemberQuery extends PaginatedQuery {
16
+ orgId: string;
17
+ }
18
+ export declare class Organizations extends Resource<{
19
+ realm?: string;
20
+ }> {
21
+ /**
22
+ * Organizations
23
+ */
24
+ constructor(client: KeycloakAdminClient);
25
+ find: (payload?: (OrganizationQuery & {
26
+ realm?: string | undefined;
27
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<OrganizationRepresentation[]>;
28
+ findOne: (payload?: ({
29
+ id: string;
30
+ } & {
31
+ realm?: string | undefined;
32
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<OrganizationRepresentation>;
33
+ create: (payload?: (OrganizationRepresentation & {
34
+ realm?: string | undefined;
35
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<{
36
+ id: string;
37
+ }>;
38
+ delById: (payload?: ({
39
+ id: string;
40
+ } & {
41
+ realm?: string | undefined;
42
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<void>;
43
+ updateById: (query: {
44
+ id: string;
45
+ } & {
46
+ realm?: string | undefined;
47
+ }, payload: OrganizationRepresentation) => Promise<void>;
48
+ listMembers: (payload?: (MemberQuery & {
49
+ realm?: string | undefined;
50
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<UserRepresentation[]>;
51
+ addMember: (payload?: ({
52
+ orgId: string;
53
+ userId: string;
54
+ } & {
55
+ realm?: string | undefined;
56
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<string>;
57
+ delMember: (payload?: ({
58
+ orgId: string;
59
+ userId: string;
60
+ } & {
61
+ realm?: string | undefined;
62
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<string>;
63
+ invite: (query: {
64
+ orgId: string;
65
+ } & {
66
+ realm?: string | undefined;
67
+ }, payload: FormData) => Promise<any>;
68
+ listIdentityProviders: (payload?: ({
69
+ orgId: string;
70
+ } & {
71
+ realm?: string | undefined;
72
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<IdentityProviderRepresentation[]>;
73
+ linkIdp: (payload?: ({
74
+ orgId: string;
75
+ alias: string;
76
+ } & {
77
+ realm?: string | undefined;
78
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<string>;
79
+ unLinkIdp: (payload?: ({
80
+ orgId: string;
81
+ alias: string;
82
+ } & {
83
+ realm?: string | undefined;
84
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<string>;
85
+ }
86
+ export {};
@@ -0,0 +1,76 @@
1
+ import Resource from "./resource.js";
2
+ export class Organizations extends Resource {
3
+ /**
4
+ * Organizations
5
+ */
6
+ constructor(client) {
7
+ super(client, {
8
+ path: "/admin/realms/{realm}/organizations",
9
+ getUrlParams: () => ({
10
+ realm: client.realmName,
11
+ }),
12
+ getBaseUrl: () => client.baseUrl,
13
+ });
14
+ }
15
+ find = this.makeRequest({
16
+ method: "GET",
17
+ path: "/",
18
+ });
19
+ findOne = this.makeRequest({
20
+ method: "GET",
21
+ path: "/{id}",
22
+ urlParamKeys: ["id"],
23
+ });
24
+ create = this.makeRequest({
25
+ method: "POST",
26
+ path: "/",
27
+ returnResourceIdInLocationHeader: { field: "id" },
28
+ });
29
+ delById = this.makeRequest({
30
+ method: "DELETE",
31
+ path: "/{id}",
32
+ urlParamKeys: ["id"],
33
+ });
34
+ updateById = this.makeUpdateRequest({
35
+ method: "PUT",
36
+ path: "/{id}",
37
+ urlParamKeys: ["id"],
38
+ });
39
+ listMembers = this.makeRequest({
40
+ method: "GET",
41
+ path: "/{orgId}/members",
42
+ urlParamKeys: ["orgId"],
43
+ });
44
+ addMember = this.makeRequest({
45
+ method: "POST",
46
+ path: "/{orgId}/members",
47
+ urlParamKeys: ["orgId"],
48
+ payloadKey: "userId",
49
+ });
50
+ delMember = this.makeRequest({
51
+ method: "DELETE",
52
+ path: "/{orgId}/members/{userId}",
53
+ urlParamKeys: ["orgId", "userId"],
54
+ });
55
+ invite = this.makeUpdateRequest({
56
+ method: "POST",
57
+ path: "/{orgId}/members/invite-user",
58
+ urlParamKeys: ["orgId"],
59
+ });
60
+ listIdentityProviders = this.makeRequest({
61
+ method: "GET",
62
+ path: "/{orgId}/identity-providers",
63
+ urlParamKeys: ["orgId"],
64
+ });
65
+ linkIdp = this.makeRequest({
66
+ method: "POST",
67
+ path: "/{orgId}/identity-providers",
68
+ urlParamKeys: ["orgId"],
69
+ payloadKey: "alias",
70
+ });
71
+ unLinkIdp = this.makeRequest({
72
+ method: "DELETE",
73
+ path: "/{orgId}/identity-providers/{alias}",
74
+ urlParamKeys: ["orgId", "alias"],
75
+ });
76
+ }
@@ -7,6 +7,6 @@ export default class Resource<ParamType = {}> {
7
7
  getUrlParams?: () => Record<string, any>;
8
8
  getBaseUrl?: () => string;
9
9
  });
10
- makeRequest: <PayloadType = any, ResponseType_1 = any>(args: RequestArgs) => (payload?: (PayloadType & ParamType) | undefined, options?: Pick<RequestArgs, "catchNotFound">) => Promise<ResponseType_1>;
11
- makeUpdateRequest: <QueryType = any, PayloadType = any, ResponseType_1 = any>(args: RequestArgs) => (query: QueryType & ParamType, payload: PayloadType) => Promise<ResponseType_1>;
10
+ makeRequest: <PayloadType = any, ResponseType = any>(args: RequestArgs) => ((payload?: PayloadType & ParamType, options?: Pick<RequestArgs, "catchNotFound">) => Promise<ResponseType>);
11
+ makeUpdateRequest: <QueryType = any, PayloadType = any, ResponseType = any>(args: RequestArgs) => ((query: QueryType & ParamType, payload: PayloadType) => Promise<ResponseType>);
12
12
  }
@@ -22,6 +22,7 @@ interface UserBaseQuery {
22
22
  firstName?: string;
23
23
  lastName?: string;
24
24
  username?: string;
25
+ q?: string;
25
26
  }
26
27
  export interface UserQuery extends PaginationQuery, SearchQuery, UserBaseQuery {
27
28
  exact?: boolean;
@@ -324,6 +325,11 @@ export declare class Users extends Resource<{
324
325
  } & {
325
326
  realm?: string | undefined;
326
327
  }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<void>;
328
+ getUnmanagedAttributes: (payload?: ({
329
+ id: string;
330
+ } & {
331
+ realm?: string | undefined;
332
+ }) | undefined, options?: Pick<import("./agent.js").RequestArgs, "catchNotFound"> | undefined) => Promise<Record<string, string[]>>;
327
333
  constructor(client: KeycloakAdminClient);
328
334
  }
329
335
  export {};
@@ -283,6 +283,11 @@ export class Users extends Resource {
283
283
  path: "/{id}/consents/{clientId}",
284
284
  urlParamKeys: ["id", "clientId"],
285
285
  });
286
+ getUnmanagedAttributes = this.makeRequest({
287
+ method: "GET",
288
+ path: "/{id}/unmanagedAttributes",
289
+ urlParamKeys: ["id"],
290
+ });
286
291
  constructor(client) {
287
292
  super(client, {
288
293
  path: "/admin/realms/{realm}/users",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keycloak/keycloak-admin-client",
3
- "version": "24.0.4",
3
+ "version": "25.0.0",
4
4
  "description": "A client to interact with Keycloak's Administration API",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -24,7 +24,7 @@
24
24
  ]
25
25
  },
26
26
  "lint": {
27
- "command": "eslint . --ext js,jsx,mjs,ts,tsx"
27
+ "command": "eslint ."
28
28
  },
29
29
  "test": {
30
30
  "command": "TS_NODE_PROJECT=tsconfig.test.json mocha --recursive \"test/**/*.spec.ts\" --timeout 10000"
@@ -37,13 +37,13 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@faker-js/faker": "^8.4.1",
40
- "@types/chai": "^4.3.12",
40
+ "@types/chai": "^4.3.16",
41
41
  "@types/lodash-es": "^4.17.12",
42
42
  "@types/mocha": "^10.0.6",
43
- "@types/node": "^20.11.24",
44
- "chai": "^5.1.0",
43
+ "@types/node": "^20.14.2",
44
+ "chai": "^5.1.1",
45
45
  "lodash-es": "^4.17.21",
46
- "mocha": "^10.3.0",
46
+ "mocha": "^10.4.0",
47
47
  "ts-node": "^10.9.2"
48
48
  },
49
49
  "author": {
@@ -53,7 +53,8 @@
53
53
  "license": "Apache-2.0",
54
54
  "repository": {
55
55
  "type": "git",
56
- "url": "https://github.com/keycloak/keycloak.git"
56
+ "url": "https://github.com/keycloak/keycloak.git",
57
+ "directory": "js/libs/keycloak-admin-client"
57
58
  },
58
59
  "homepage": "https://www.keycloak.org/",
59
60
  "scripts": {