@logto/client 1.1.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/errors.cjs ADDED
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const logtoClientErrorCodes = Object.freeze({
4
+ 'sign_in_session.invalid': 'Invalid sign-in session.',
5
+ 'sign_in_session.not_found': 'Sign-in session not found.',
6
+ not_authenticated: 'Not authenticated.',
7
+ fetch_user_info_failed: 'Unable to fetch user info. The access token may be invalid.',
8
+ });
9
+ class LogtoClientError extends Error {
10
+ constructor(code, data) {
11
+ super(logtoClientErrorCodes[code]);
12
+ this.code = code;
13
+ this.data = data;
14
+ }
15
+ }
16
+
17
+ exports.LogtoClientError = LogtoClientError;
package/lib/errors.d.ts CHANGED
@@ -1,13 +1,10 @@
1
- import type { NormalizeKeyPaths } from '@silverhand/essentials';
2
1
  declare const logtoClientErrorCodes: Readonly<{
3
- sign_in_session: {
4
- invalid: string;
5
- not_found: string;
6
- };
2
+ 'sign_in_session.invalid': "Invalid sign-in session.";
3
+ 'sign_in_session.not_found': "Sign-in session not found.";
7
4
  not_authenticated: "Not authenticated.";
8
5
  fetch_user_info_failed: "Unable to fetch user info. The access token may be invalid.";
9
6
  }>;
10
- export type LogtoClientErrorCode = NormalizeKeyPaths<typeof logtoClientErrorCodes>;
7
+ export type LogtoClientErrorCode = keyof typeof logtoClientErrorCodes;
11
8
  export declare class LogtoClientError extends Error {
12
9
  code: LogtoClientErrorCode;
13
10
  data: unknown;
package/lib/errors.js CHANGED
@@ -1,33 +1,15 @@
1
- 'use strict';
2
-
3
- var get = require('lodash.get');
4
-
5
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
-
7
- var get__default = /*#__PURE__*/_interopDefault(get);
8
-
9
1
  const logtoClientErrorCodes = Object.freeze({
10
- sign_in_session: {
11
- invalid: 'Invalid sign-in session.',
12
- not_found: 'Sign-in session not found.',
13
- },
2
+ 'sign_in_session.invalid': 'Invalid sign-in session.',
3
+ 'sign_in_session.not_found': 'Sign-in session not found.',
14
4
  not_authenticated: 'Not authenticated.',
15
5
  fetch_user_info_failed: 'Unable to fetch user info. The access token may be invalid.',
16
6
  });
17
- const getMessageByErrorCode = (errorCode) => {
18
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
19
- const message = get__default.default(logtoClientErrorCodes, errorCode);
20
- if (typeof message === 'string') {
21
- return message;
22
- }
23
- return errorCode;
24
- };
25
7
  class LogtoClientError extends Error {
26
8
  constructor(code, data) {
27
- super(getMessageByErrorCode(code));
9
+ super(logtoClientErrorCodes[code]);
28
10
  this.code = code;
29
11
  this.data = data;
30
12
  }
31
13
  }
32
14
 
33
- exports.LogtoClientError = LogtoClientError;
15
+ export { LogtoClientError };
@@ -1,21 +1,24 @@
1
- import { Prompt, withDefaultScopes, decodeIdToken, fetchUserInfo, generateSignInUri, verifyAndParseCodeFromCallbackUri, fetchTokenByAuthorizationCode, revoke, generateSignOutUri, fetchTokenByRefreshToken, fetchOidcConfig, verifyIdToken } from '@logto/js';
2
- export { LogtoError, LogtoRequestError, OidcError, Prompt, ReservedScope, UserScope } from '@logto/js';
3
- import { createRemoteJWKSet } from 'jose';
4
- import once from 'lodash.once';
5
- import { LogtoClientError } from './errors.mjs';
6
- import { isLogtoSignInSessionItem, isLogtoAccessTokenMap } from './types/index.mjs';
7
- import { buildAccessTokenKey, getDiscoveryEndpoint } from './utils/index.mjs';
8
- export { createRequester } from './utils/requester.mjs';
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var js = require('@logto/js');
6
+ var jose = require('jose');
7
+ var errors = require('./errors.cjs');
8
+ var index = require('./types/index.cjs');
9
+ var index$1 = require('./utils/index.cjs');
10
+ var once = require('./utils/once.cjs');
11
+ var requester = require('./utils/requester.cjs');
9
12
 
10
13
  class LogtoClient {
11
14
  constructor(logtoConfig, adapter) {
12
- this.getOidcConfig = once(this._getOidcConfig);
13
- this.getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);
15
+ this.getOidcConfig = once.once(this._getOidcConfig);
16
+ this.getJwtVerifyGetKey = once.once(this._getJwtVerifyGetKey);
14
17
  this.accessTokenMap = new Map();
15
18
  this.logtoConfig = {
16
19
  ...logtoConfig,
17
- prompt: logtoConfig.prompt ?? Prompt.Consent,
18
- scopes: withDefaultScopes(logtoConfig.scopes).split(' '),
20
+ prompt: logtoConfig.prompt ?? js.Prompt.Consent,
21
+ scopes: js.withDefaultScopes(logtoConfig.scopes).split(' '),
19
22
  };
20
23
  this.adapter = adapter;
21
24
  void this.loadAccessTokenMap();
@@ -31,9 +34,9 @@ class LogtoClient {
31
34
  }
32
35
  async getAccessToken(resource) {
33
36
  if (!(await this.getIdToken())) {
34
- throw new LogtoClientError('not_authenticated');
37
+ throw new errors.LogtoClientError('not_authenticated');
35
38
  }
36
- const accessTokenKey = buildAccessTokenKey(resource);
39
+ const accessTokenKey = index$1.buildAccessTokenKey(resource);
37
40
  const accessToken = this.accessTokenMap.get(accessTokenKey);
38
41
  if (accessToken && accessToken.expiresAt > Date.now() / 1000) {
39
42
  return accessToken.token;
@@ -50,17 +53,21 @@ class LogtoClient {
50
53
  async getIdTokenClaims() {
51
54
  const idToken = await this.getIdToken();
52
55
  if (!idToken) {
53
- throw new LogtoClientError('not_authenticated');
56
+ throw new errors.LogtoClientError('not_authenticated');
54
57
  }
55
- return decodeIdToken(idToken);
58
+ return js.decodeIdToken(idToken);
59
+ }
60
+ async getAccessTokenClaims(resource) {
61
+ const accessToken = await this.getAccessToken(resource);
62
+ return js.decodeAccessToken(accessToken);
56
63
  }
57
64
  async fetchUserInfo() {
58
65
  const { userinfoEndpoint } = await this.getOidcConfig();
59
66
  const accessToken = await this.getAccessToken();
60
67
  if (!accessToken) {
61
- throw new LogtoClientError('fetch_user_info_failed');
68
+ throw new errors.LogtoClientError('fetch_user_info_failed');
62
69
  }
63
- return fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
70
+ return js.fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
64
71
  }
65
72
  async signIn(redirectUri, interactionMode) {
66
73
  const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;
@@ -68,7 +75,7 @@ class LogtoClient {
68
75
  const codeVerifier = this.adapter.generateCodeVerifier();
69
76
  const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);
70
77
  const state = this.adapter.generateState();
71
- const signInUri = generateSignInUri({
78
+ const signInUri = js.generateSignInUri({
72
79
  authorizationEndpoint,
73
80
  clientId,
74
81
  redirectUri,
@@ -98,13 +105,13 @@ class LogtoClient {
98
105
  const { requester } = adapter;
99
106
  const signInSession = await this.getSignInSession();
100
107
  if (!signInSession) {
101
- throw new LogtoClientError('sign_in_session.not_found');
108
+ throw new errors.LogtoClientError('sign_in_session.not_found');
102
109
  }
103
110
  const { redirectUri, state, codeVerifier } = signInSession;
104
- const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
111
+ const code = js.verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
105
112
  const { appId: clientId } = logtoConfig;
106
113
  const { tokenEndpoint } = await this.getOidcConfig();
107
- const codeTokenResponse = await fetchTokenByAuthorizationCode({
114
+ const codeTokenResponse = await js.fetchTokenByAuthorizationCode({
108
115
  clientId,
109
116
  tokenEndpoint,
110
117
  redirectUri,
@@ -121,13 +128,13 @@ class LogtoClient {
121
128
  const refreshToken = await this.getRefreshToken();
122
129
  if (refreshToken) {
123
130
  try {
124
- await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
131
+ await js.revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
125
132
  }
126
133
  catch {
127
134
  // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed
128
135
  }
129
136
  }
130
- const url = generateSignOutUri({
137
+ const url = js.generateSignOutUri({
131
138
  endSessionEndpoint,
132
139
  postLogoutRedirectUri,
133
140
  clientId,
@@ -144,8 +151,8 @@ class LogtoClient {
144
151
  return null;
145
152
  }
146
153
  const item = JSON.parse(jsonItem);
147
- if (!isLogtoSignInSessionItem(item)) {
148
- throw new LogtoClientError('sign_in_session.invalid');
154
+ if (!index.isLogtoSignInSessionItem(item)) {
155
+ throw new errors.LogtoClientError('sign_in_session.invalid');
149
156
  }
150
157
  return item;
151
158
  }
@@ -174,12 +181,12 @@ class LogtoClient {
174
181
  async getAccessTokenByRefreshToken(resource) {
175
182
  const currentRefreshToken = await this.getRefreshToken();
176
183
  if (!currentRefreshToken) {
177
- throw new LogtoClientError('not_authenticated');
184
+ throw new errors.LogtoClientError('not_authenticated');
178
185
  }
179
- const accessTokenKey = buildAccessTokenKey(resource);
186
+ const accessTokenKey = index$1.buildAccessTokenKey(resource);
180
187
  const { appId: clientId } = this.logtoConfig;
181
188
  const { tokenEndpoint } = await this.getOidcConfig();
182
- const { accessToken, refreshToken, idToken, scope, expiresIn } = await fetchTokenByRefreshToken({
189
+ const { accessToken, refreshToken, idToken, scope, expiresIn } = await js.fetchTokenByRefreshToken({
183
190
  clientId,
184
191
  tokenEndpoint,
185
192
  refreshToken: currentRefreshToken,
@@ -200,24 +207,24 @@ class LogtoClient {
200
207
  }
201
208
  async _getOidcConfig() {
202
209
  const { endpoint } = this.logtoConfig;
203
- const discoveryEndpoint = getDiscoveryEndpoint(endpoint);
204
- return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
210
+ const discoveryEndpoint = index$1.getDiscoveryEndpoint(endpoint);
211
+ return js.fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
205
212
  }
206
213
  async _getJwtVerifyGetKey() {
207
214
  const { jwksUri } = await this.getOidcConfig();
208
- return createRemoteJWKSet(new URL(jwksUri));
215
+ return jose.createRemoteJWKSet(new URL(jwksUri));
209
216
  }
210
217
  async verifyIdToken(idToken) {
211
218
  const { appId } = this.logtoConfig;
212
219
  const { issuer } = await this.getOidcConfig();
213
220
  const jwtVerifyGetKey = await this.getJwtVerifyGetKey();
214
- await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
221
+ await js.verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
215
222
  }
216
223
  async saveCodeToken({ refreshToken, idToken, scope, accessToken, expiresIn, }) {
217
224
  await this.setRefreshToken(refreshToken ?? null);
218
225
  await this.setIdToken(idToken);
219
226
  // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)
220
- const accessTokenKey = buildAccessTokenKey();
227
+ const accessTokenKey = index$1.buildAccessTokenKey();
221
228
  const expiresAt = Date.now() / 1000 + expiresIn;
222
229
  this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });
223
230
  await this.saveAccessTokenMap();
@@ -237,7 +244,7 @@ class LogtoClient {
237
244
  }
238
245
  try {
239
246
  const json = JSON.parse(raw);
240
- if (!isLogtoAccessTokenMap(json)) {
247
+ if (!index.isLogtoAccessTokenMap(json)) {
241
248
  return;
242
249
  }
243
250
  this.accessTokenMap.clear();
@@ -251,4 +258,32 @@ class LogtoClient {
251
258
  }
252
259
  }
253
260
 
254
- export { LogtoClientError, LogtoClient as default, isLogtoAccessTokenMap, isLogtoSignInSessionItem };
261
+ Object.defineProperty(exports, 'LogtoError', {
262
+ enumerable: true,
263
+ get: function () { return js.LogtoError; }
264
+ });
265
+ Object.defineProperty(exports, 'LogtoRequestError', {
266
+ enumerable: true,
267
+ get: function () { return js.LogtoRequestError; }
268
+ });
269
+ Object.defineProperty(exports, 'OidcError', {
270
+ enumerable: true,
271
+ get: function () { return js.OidcError; }
272
+ });
273
+ Object.defineProperty(exports, 'Prompt', {
274
+ enumerable: true,
275
+ get: function () { return js.Prompt; }
276
+ });
277
+ Object.defineProperty(exports, 'ReservedScope', {
278
+ enumerable: true,
279
+ get: function () { return js.ReservedScope; }
280
+ });
281
+ Object.defineProperty(exports, 'UserScope', {
282
+ enumerable: true,
283
+ get: function () { return js.UserScope; }
284
+ });
285
+ exports.LogtoClientError = errors.LogtoClientError;
286
+ exports.isLogtoAccessTokenMap = index.isLogtoAccessTokenMap;
287
+ exports.isLogtoSignInSessionItem = index.isLogtoSignInSessionItem;
288
+ exports.createRequester = requester.createRequester;
289
+ exports.default = LogtoClient;
package/lib/index.d.ts CHANGED
@@ -1,25 +1,17 @@
1
- import type { IdTokenClaims, UserInfoResponse, InteractionMode } from '@logto/js';
1
+ import { type IdTokenClaims, type UserInfoResponse, type InteractionMode, type AccessTokenClaims } from '@logto/js';
2
2
  import type { Nullable } from '@silverhand/essentials';
3
- import type { ClientAdapter } from './adapter';
4
- import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from './types';
3
+ import type { ClientAdapter } from './adapter.js';
4
+ import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from './types/index.js';
5
5
  export type { IdTokenClaims, LogtoErrorCode, UserInfoResponse, InteractionMode } from '@logto/js';
6
6
  export { LogtoError, OidcError, Prompt, LogtoRequestError, ReservedScope, UserScope, } from '@logto/js';
7
- export * from './errors';
8
- export type { Storage, StorageKey, ClientAdapter } from './adapter';
9
- export { createRequester } from './utils';
10
- export * from './types';
7
+ export * from './errors.js';
8
+ export type { Storage, StorageKey, ClientAdapter } from './adapter.js';
9
+ export { createRequester } from './utils/index.js';
10
+ export * from './types/index.js';
11
11
  export default class LogtoClient {
12
12
  protected readonly logtoConfig: LogtoConfig;
13
- protected readonly getOidcConfig: () => Promise<import("@silverhand/essentials").KeysToCamelCase<{
14
- authorization_endpoint: string;
15
- token_endpoint: string;
16
- userinfo_endpoint: string;
17
- end_session_endpoint: string;
18
- revocation_endpoint: string;
19
- jwks_uri: string;
20
- issuer: string;
21
- }>>;
22
- protected readonly getJwtVerifyGetKey: () => Promise<(protectedHeader?: import("jose").JWSHeaderParameters | undefined, token?: import("jose").FlattenedJWSInput | undefined) => Promise<import("jose").KeyLike>>;
13
+ protected readonly getOidcConfig: typeof this._getOidcConfig;
14
+ protected readonly getJwtVerifyGetKey: (...args: unknown[]) => Promise<(protectedHeader?: import("jose").JWSHeaderParameters | undefined, token?: import("jose").FlattenedJWSInput | undefined) => Promise<import("jose").KeyLike>>;
23
15
  protected readonly adapter: ClientAdapter;
24
16
  protected readonly accessTokenMap: Map<string, AccessToken>;
25
17
  constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter);
@@ -28,6 +20,7 @@ export default class LogtoClient {
28
20
  getIdToken(): Promise<Nullable<string>>;
29
21
  getAccessToken(resource?: string): Promise<string>;
30
22
  getIdTokenClaims(): Promise<IdTokenClaims>;
23
+ getAccessTokenClaims(resource?: string): Promise<AccessTokenClaims>;
31
24
  fetchUserInfo(): Promise<UserInfoResponse>;
32
25
  signIn(redirectUri: string, interactionMode?: InteractionMode): Promise<void>;
33
26
  isSignInRedirected(url: string): Promise<boolean>;
package/lib/index.js CHANGED
@@ -1,28 +1,21 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var js = require('@logto/js');
6
- var jose = require('jose');
7
- var once = require('lodash.once');
8
- var errors = require('./errors.js');
9
- var index = require('./types/index.js');
10
- var index$1 = require('./utils/index.js');
11
- var requester = require('./utils/requester.js');
12
-
13
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
-
15
- var once__default = /*#__PURE__*/_interopDefault(once);
1
+ import { Prompt, withDefaultScopes, decodeIdToken, decodeAccessToken, fetchUserInfo, generateSignInUri, verifyAndParseCodeFromCallbackUri, fetchTokenByAuthorizationCode, revoke, generateSignOutUri, fetchTokenByRefreshToken, fetchOidcConfig, verifyIdToken } from '@logto/js';
2
+ export { LogtoError, LogtoRequestError, OidcError, Prompt, ReservedScope, UserScope } from '@logto/js';
3
+ import { createRemoteJWKSet } from 'jose';
4
+ import { LogtoClientError } from './errors.js';
5
+ import { isLogtoSignInSessionItem, isLogtoAccessTokenMap } from './types/index.js';
6
+ import { buildAccessTokenKey, getDiscoveryEndpoint } from './utils/index.js';
7
+ import { once } from './utils/once.js';
8
+ export { createRequester } from './utils/requester.js';
16
9
 
17
10
  class LogtoClient {
18
11
  constructor(logtoConfig, adapter) {
19
- this.getOidcConfig = once__default.default(this._getOidcConfig);
20
- this.getJwtVerifyGetKey = once__default.default(this._getJwtVerifyGetKey);
12
+ this.getOidcConfig = once(this._getOidcConfig);
13
+ this.getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);
21
14
  this.accessTokenMap = new Map();
22
15
  this.logtoConfig = {
23
16
  ...logtoConfig,
24
- prompt: logtoConfig.prompt ?? js.Prompt.Consent,
25
- scopes: js.withDefaultScopes(logtoConfig.scopes).split(' '),
17
+ prompt: logtoConfig.prompt ?? Prompt.Consent,
18
+ scopes: withDefaultScopes(logtoConfig.scopes).split(' '),
26
19
  };
27
20
  this.adapter = adapter;
28
21
  void this.loadAccessTokenMap();
@@ -38,9 +31,9 @@ class LogtoClient {
38
31
  }
39
32
  async getAccessToken(resource) {
40
33
  if (!(await this.getIdToken())) {
41
- throw new errors.LogtoClientError('not_authenticated');
34
+ throw new LogtoClientError('not_authenticated');
42
35
  }
43
- const accessTokenKey = index$1.buildAccessTokenKey(resource);
36
+ const accessTokenKey = buildAccessTokenKey(resource);
44
37
  const accessToken = this.accessTokenMap.get(accessTokenKey);
45
38
  if (accessToken && accessToken.expiresAt > Date.now() / 1000) {
46
39
  return accessToken.token;
@@ -57,17 +50,21 @@ class LogtoClient {
57
50
  async getIdTokenClaims() {
58
51
  const idToken = await this.getIdToken();
59
52
  if (!idToken) {
60
- throw new errors.LogtoClientError('not_authenticated');
53
+ throw new LogtoClientError('not_authenticated');
61
54
  }
62
- return js.decodeIdToken(idToken);
55
+ return decodeIdToken(idToken);
56
+ }
57
+ async getAccessTokenClaims(resource) {
58
+ const accessToken = await this.getAccessToken(resource);
59
+ return decodeAccessToken(accessToken);
63
60
  }
64
61
  async fetchUserInfo() {
65
62
  const { userinfoEndpoint } = await this.getOidcConfig();
66
63
  const accessToken = await this.getAccessToken();
67
64
  if (!accessToken) {
68
- throw new errors.LogtoClientError('fetch_user_info_failed');
65
+ throw new LogtoClientError('fetch_user_info_failed');
69
66
  }
70
- return js.fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
67
+ return fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
71
68
  }
72
69
  async signIn(redirectUri, interactionMode) {
73
70
  const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;
@@ -75,7 +72,7 @@ class LogtoClient {
75
72
  const codeVerifier = this.adapter.generateCodeVerifier();
76
73
  const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);
77
74
  const state = this.adapter.generateState();
78
- const signInUri = js.generateSignInUri({
75
+ const signInUri = generateSignInUri({
79
76
  authorizationEndpoint,
80
77
  clientId,
81
78
  redirectUri,
@@ -105,13 +102,13 @@ class LogtoClient {
105
102
  const { requester } = adapter;
106
103
  const signInSession = await this.getSignInSession();
107
104
  if (!signInSession) {
108
- throw new errors.LogtoClientError('sign_in_session.not_found');
105
+ throw new LogtoClientError('sign_in_session.not_found');
109
106
  }
110
107
  const { redirectUri, state, codeVerifier } = signInSession;
111
- const code = js.verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
108
+ const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
112
109
  const { appId: clientId } = logtoConfig;
113
110
  const { tokenEndpoint } = await this.getOidcConfig();
114
- const codeTokenResponse = await js.fetchTokenByAuthorizationCode({
111
+ const codeTokenResponse = await fetchTokenByAuthorizationCode({
115
112
  clientId,
116
113
  tokenEndpoint,
117
114
  redirectUri,
@@ -128,13 +125,13 @@ class LogtoClient {
128
125
  const refreshToken = await this.getRefreshToken();
129
126
  if (refreshToken) {
130
127
  try {
131
- await js.revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
128
+ await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
132
129
  }
133
130
  catch {
134
131
  // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed
135
132
  }
136
133
  }
137
- const url = js.generateSignOutUri({
134
+ const url = generateSignOutUri({
138
135
  endSessionEndpoint,
139
136
  postLogoutRedirectUri,
140
137
  clientId,
@@ -151,8 +148,8 @@ class LogtoClient {
151
148
  return null;
152
149
  }
153
150
  const item = JSON.parse(jsonItem);
154
- if (!index.isLogtoSignInSessionItem(item)) {
155
- throw new errors.LogtoClientError('sign_in_session.invalid');
151
+ if (!isLogtoSignInSessionItem(item)) {
152
+ throw new LogtoClientError('sign_in_session.invalid');
156
153
  }
157
154
  return item;
158
155
  }
@@ -181,12 +178,12 @@ class LogtoClient {
181
178
  async getAccessTokenByRefreshToken(resource) {
182
179
  const currentRefreshToken = await this.getRefreshToken();
183
180
  if (!currentRefreshToken) {
184
- throw new errors.LogtoClientError('not_authenticated');
181
+ throw new LogtoClientError('not_authenticated');
185
182
  }
186
- const accessTokenKey = index$1.buildAccessTokenKey(resource);
183
+ const accessTokenKey = buildAccessTokenKey(resource);
187
184
  const { appId: clientId } = this.logtoConfig;
188
185
  const { tokenEndpoint } = await this.getOidcConfig();
189
- const { accessToken, refreshToken, idToken, scope, expiresIn } = await js.fetchTokenByRefreshToken({
186
+ const { accessToken, refreshToken, idToken, scope, expiresIn } = await fetchTokenByRefreshToken({
190
187
  clientId,
191
188
  tokenEndpoint,
192
189
  refreshToken: currentRefreshToken,
@@ -207,24 +204,24 @@ class LogtoClient {
207
204
  }
208
205
  async _getOidcConfig() {
209
206
  const { endpoint } = this.logtoConfig;
210
- const discoveryEndpoint = index$1.getDiscoveryEndpoint(endpoint);
211
- return js.fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
207
+ const discoveryEndpoint = getDiscoveryEndpoint(endpoint);
208
+ return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
212
209
  }
213
210
  async _getJwtVerifyGetKey() {
214
211
  const { jwksUri } = await this.getOidcConfig();
215
- return jose.createRemoteJWKSet(new URL(jwksUri));
212
+ return createRemoteJWKSet(new URL(jwksUri));
216
213
  }
217
214
  async verifyIdToken(idToken) {
218
215
  const { appId } = this.logtoConfig;
219
216
  const { issuer } = await this.getOidcConfig();
220
217
  const jwtVerifyGetKey = await this.getJwtVerifyGetKey();
221
- await js.verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
218
+ await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
222
219
  }
223
220
  async saveCodeToken({ refreshToken, idToken, scope, accessToken, expiresIn, }) {
224
221
  await this.setRefreshToken(refreshToken ?? null);
225
222
  await this.setIdToken(idToken);
226
223
  // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)
227
- const accessTokenKey = index$1.buildAccessTokenKey();
224
+ const accessTokenKey = buildAccessTokenKey();
228
225
  const expiresAt = Date.now() / 1000 + expiresIn;
229
226
  this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });
230
227
  await this.saveAccessTokenMap();
@@ -244,7 +241,7 @@ class LogtoClient {
244
241
  }
245
242
  try {
246
243
  const json = JSON.parse(raw);
247
- if (!index.isLogtoAccessTokenMap(json)) {
244
+ if (!isLogtoAccessTokenMap(json)) {
248
245
  return;
249
246
  }
250
247
  this.accessTokenMap.clear();
@@ -258,32 +255,4 @@ class LogtoClient {
258
255
  }
259
256
  }
260
257
 
261
- Object.defineProperty(exports, 'LogtoError', {
262
- enumerable: true,
263
- get: function () { return js.LogtoError; }
264
- });
265
- Object.defineProperty(exports, 'LogtoRequestError', {
266
- enumerable: true,
267
- get: function () { return js.LogtoRequestError; }
268
- });
269
- Object.defineProperty(exports, 'OidcError', {
270
- enumerable: true,
271
- get: function () { return js.OidcError; }
272
- });
273
- Object.defineProperty(exports, 'Prompt', {
274
- enumerable: true,
275
- get: function () { return js.Prompt; }
276
- });
277
- Object.defineProperty(exports, 'ReservedScope', {
278
- enumerable: true,
279
- get: function () { return js.ReservedScope; }
280
- });
281
- Object.defineProperty(exports, 'UserScope', {
282
- enumerable: true,
283
- get: function () { return js.UserScope; }
284
- });
285
- exports.LogtoClientError = errors.LogtoClientError;
286
- exports.isLogtoAccessTokenMap = index.isLogtoAccessTokenMap;
287
- exports.isLogtoSignInSessionItem = index.isLogtoSignInSessionItem;
288
- exports.createRequester = requester.createRequester;
289
- exports.default = LogtoClient;
258
+ export { LogtoClientError, LogtoClient as default, isLogtoAccessTokenMap, isLogtoSignInSessionItem };
package/lib/mock.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /// <reference types="jest" />
2
2
  import { Prompt } from '@logto/js';
3
3
  import type { Nullable } from '@silverhand/essentials';
4
- import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from '.';
5
- import LogtoClient from '.';
6
- import type { Storage } from './adapter';
4
+ import type { Storage } from './adapter.js';
5
+ import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from './index.js';
6
+ import LogtoClient from './index.js';
7
7
  export declare const appId = "app_id_value";
8
8
  export declare const endpoint = "https://logto.dev";
9
9
  export declare class MockedStorage implements Storage {
@@ -1,17 +1,19 @@
1
- import { isArbitraryObject } from '@logto/js';
1
+ 'use strict';
2
+
3
+ var js = require('@logto/js');
2
4
 
3
5
  const isLogtoSignInSessionItem = (data) => {
4
- if (!isArbitraryObject(data)) {
6
+ if (!js.isArbitraryObject(data)) {
5
7
  return false;
6
8
  }
7
9
  return ['redirectUri', 'codeVerifier', 'state'].every((key) => typeof data[key] === 'string');
8
10
  };
9
11
  const isLogtoAccessTokenMap = (data) => {
10
- if (!isArbitraryObject(data)) {
12
+ if (!js.isArbitraryObject(data)) {
11
13
  return false;
12
14
  }
13
15
  return Object.values(data).every((value) => {
14
- if (!isArbitraryObject(value)) {
16
+ if (!js.isArbitraryObject(value)) {
15
17
  return false;
16
18
  }
17
19
  return (typeof value.token === 'string' &&
@@ -20,4 +22,5 @@ const isLogtoAccessTokenMap = (data) => {
20
22
  });
21
23
  };
22
24
 
23
- export { isLogtoAccessTokenMap, isLogtoSignInSessionItem };
25
+ exports.isLogtoAccessTokenMap = isLogtoAccessTokenMap;
26
+ exports.isLogtoSignInSessionItem = isLogtoSignInSessionItem;
@@ -1,19 +1,17 @@
1
- 'use strict';
2
-
3
- var js = require('@logto/js');
1
+ import { isArbitraryObject } from '@logto/js';
4
2
 
5
3
  const isLogtoSignInSessionItem = (data) => {
6
- if (!js.isArbitraryObject(data)) {
4
+ if (!isArbitraryObject(data)) {
7
5
  return false;
8
6
  }
9
7
  return ['redirectUri', 'codeVerifier', 'state'].every((key) => typeof data[key] === 'string');
10
8
  };
11
9
  const isLogtoAccessTokenMap = (data) => {
12
- if (!js.isArbitraryObject(data)) {
10
+ if (!isArbitraryObject(data)) {
13
11
  return false;
14
12
  }
15
13
  return Object.values(data).every((value) => {
16
- if (!js.isArbitraryObject(value)) {
14
+ if (!isArbitraryObject(value)) {
17
15
  return false;
18
16
  }
19
17
  return (typeof value.token === 'string' &&
@@ -22,5 +20,4 @@ const isLogtoAccessTokenMap = (data) => {
22
20
  });
23
21
  };
24
22
 
25
- exports.isLogtoAccessTokenMap = isLogtoAccessTokenMap;
26
- exports.isLogtoSignInSessionItem = isLogtoSignInSessionItem;
23
+ export { isLogtoAccessTokenMap, isLogtoSignInSessionItem };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var js = require('@logto/js');
4
+
5
+ const buildAccessTokenKey = (resource = '', scopes = []) => `${scopes.slice().sort().join(' ')}@${resource}`;
6
+ const getDiscoveryEndpoint = (endpoint) => new URL(js.discoveryPath, endpoint).toString();
7
+
8
+ exports.buildAccessTokenKey = buildAccessTokenKey;
9
+ exports.getDiscoveryEndpoint = getDiscoveryEndpoint;
@@ -1,3 +1,3 @@
1
- export * from './requester';
1
+ export * from './requester.js';
2
2
  export declare const buildAccessTokenKey: (resource?: string, scopes?: string[]) => string;
3
3
  export declare const getDiscoveryEndpoint: (endpoint: string) => string;
@@ -1,9 +1,6 @@
1
- 'use strict';
2
-
3
- var js = require('@logto/js');
1
+ import { discoveryPath } from '@logto/js';
4
2
 
5
3
  const buildAccessTokenKey = (resource = '', scopes = []) => `${scopes.slice().sort().join(' ')}@${resource}`;
6
- const getDiscoveryEndpoint = (endpoint) => new URL(js.discoveryPath, endpoint).toString();
4
+ const getDiscoveryEndpoint = (endpoint) => new URL(discoveryPath, endpoint).toString();
7
5
 
8
- exports.buildAccessTokenKey = buildAccessTokenKey;
9
- exports.getDiscoveryEndpoint = getDiscoveryEndpoint;
6
+ export { buildAccessTokenKey, getDiscoveryEndpoint };
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ // TODO @sijie move to essentials
4
+ /* eslint-disable @silverhand/fp/no-let */
5
+ /* eslint-disable @silverhand/fp/no-mutation */
6
+ function once(function_) {
7
+ let called = false;
8
+ let result;
9
+ return function (...args) {
10
+ if (!called) {
11
+ called = true;
12
+ result = function_.apply(this, args);
13
+ }
14
+ return result;
15
+ };
16
+ }
17
+ /* eslint-enable @silverhand/fp/no-mutation */
18
+ /* eslint-enable @silverhand/fp/no-let */
19
+
20
+ exports.once = once;
@@ -0,0 +1,3 @@
1
+ type Procedure<T> = (...args: unknown[]) => T;
2
+ export declare function once<T>(function_: Procedure<T>): Procedure<T>;
3
+ export {};
@@ -0,0 +1,18 @@
1
+ // TODO @sijie move to essentials
2
+ /* eslint-disable @silverhand/fp/no-let */
3
+ /* eslint-disable @silverhand/fp/no-mutation */
4
+ function once(function_) {
5
+ let called = false;
6
+ let result;
7
+ return function (...args) {
8
+ if (!called) {
9
+ called = true;
10
+ result = function_.apply(this, args);
11
+ }
12
+ return result;
13
+ };
14
+ }
15
+ /* eslint-enable @silverhand/fp/no-mutation */
16
+ /* eslint-enable @silverhand/fp/no-let */
17
+
18
+ export { once };
@@ -1,19 +1,21 @@
1
- import { isLogtoRequestError, LogtoError, LogtoRequestError } from '@logto/js';
1
+ 'use strict';
2
+
3
+ var js = require('@logto/js');
2
4
 
3
5
  const createRequester = (fetchFunction) => {
4
6
  return async (...args) => {
5
7
  const response = await fetchFunction(...args);
6
8
  if (!response.ok) {
7
9
  const responseJson = await response.json();
8
- if (!isLogtoRequestError(responseJson)) {
9
- throw new LogtoError('unexpected_response_error', responseJson);
10
+ if (!js.isLogtoRequestError(responseJson)) {
11
+ throw new js.LogtoError('unexpected_response_error', responseJson);
10
12
  }
11
13
  // Expected request error from server
12
14
  const { code, message } = responseJson;
13
- throw new LogtoRequestError(code, message);
15
+ throw new js.LogtoRequestError(code, message);
14
16
  }
15
17
  return response.json();
16
18
  };
17
19
  };
18
20
 
19
- export { createRequester };
21
+ exports.createRequester = createRequester;
@@ -1,21 +1,19 @@
1
- 'use strict';
2
-
3
- var js = require('@logto/js');
1
+ import { isLogtoRequestError, LogtoError, LogtoRequestError } from '@logto/js';
4
2
 
5
3
  const createRequester = (fetchFunction) => {
6
4
  return async (...args) => {
7
5
  const response = await fetchFunction(...args);
8
6
  if (!response.ok) {
9
7
  const responseJson = await response.json();
10
- if (!js.isLogtoRequestError(responseJson)) {
11
- throw new js.LogtoError('unexpected_response_error', responseJson);
8
+ if (!isLogtoRequestError(responseJson)) {
9
+ throw new LogtoError('unexpected_response_error', responseJson);
12
10
  }
13
11
  // Expected request error from server
14
12
  const { code, message } = responseJson;
15
- throw new js.LogtoRequestError(code, message);
13
+ throw new LogtoRequestError(code, message);
16
14
  }
17
15
  return response.json();
18
16
  };
19
17
  };
20
18
 
21
- exports.createRequester = createRequester;
19
+ export { createRequester };
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@logto/client",
3
- "version": "1.1.2",
4
- "source": "./src/index.ts",
5
- "main": "./lib/index.js",
3
+ "version": "2.1.0",
4
+ "type": "module",
5
+ "main": "./lib/index.cjs",
6
+ "module": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
6
8
  "exports": {
7
- "require": "./lib/index.js",
8
- "import": "./lib/index.mjs"
9
+ "types": "./lib/index.d.ts",
10
+ "require": "./lib/index.cjs",
11
+ "import": "./lib/index.js",
12
+ "default": "./lib/index.js"
9
13
  },
10
- "module": "./lib/index.mjs",
11
- "types": "./lib/index.d.ts",
12
14
  "files": [
13
15
  "lib"
14
16
  ],
@@ -18,33 +20,18 @@
18
20
  "url": "https://github.com/logto-io/js.git",
19
21
  "directory": "packages/client"
20
22
  },
21
- "scripts": {
22
- "dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
23
- "precommit": "lint-staged",
24
- "check": "tsc --noEmit",
25
- "build": "rm -rf lib/ && tsc -p tsconfig.build.json --noEmit && rollup -c",
26
- "lint": "eslint --ext .ts src",
27
- "test": "jest",
28
- "test:coverage": "jest --silent --env=jsdom && jest --silent --coverage",
29
- "prepack": "pnpm test"
30
- },
31
23
  "dependencies": {
32
- "@logto/js": "^1.1.2",
33
- "@silverhand/essentials": "^2.6.1",
24
+ "@logto/js": "^2.1.0",
25
+ "@silverhand/essentials": "^2.6.2",
34
26
  "camelcase-keys": "^7.0.1",
35
- "jose": "^4.13.2",
36
- "lodash.get": "^4.4.2",
37
- "lodash.once": "^4.1.1"
27
+ "jose": "^4.13.2"
38
28
  },
39
29
  "devDependencies": {
40
- "@jest/types": "^29.5.0",
41
- "@silverhand/eslint-config": "^2.0.0",
42
- "@silverhand/ts-config": "^1.0.0",
30
+ "@silverhand/eslint-config": "^3.0.1",
31
+ "@silverhand/ts-config": "^3.0.0",
43
32
  "@swc/core": "^1.3.50",
44
33
  "@swc/jest": "^0.2.24",
45
34
  "@types/jest": "^29.5.0",
46
- "@types/lodash.get": "^4.4.6",
47
- "@types/lodash.once": "^4.1.7",
48
35
  "@types/node": "^18.0.0",
49
36
  "eslint": "^8.38.0",
50
37
  "jest": "^29.5.0",
@@ -63,5 +50,13 @@
63
50
  "publishConfig": {
64
51
  "access": "public"
65
52
  },
66
- "gitHead": "9e9a8b0887ef67baa7c3c564590bb06e7801d03e"
67
- }
53
+ "scripts": {
54
+ "dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
55
+ "precommit": "lint-staged",
56
+ "check": "tsc --noEmit",
57
+ "build": "rm -rf lib/ && tsc -p tsconfig.build.json --noEmit && rollup -c",
58
+ "lint": "eslint --ext .ts src",
59
+ "test": "jest",
60
+ "test:coverage": "jest --silent --env=jsdom && jest --silent --coverage"
61
+ }
62
+ }
package/lib/errors.mjs DELETED
@@ -1,27 +0,0 @@
1
- import get from 'lodash.get';
2
-
3
- const logtoClientErrorCodes = Object.freeze({
4
- sign_in_session: {
5
- invalid: 'Invalid sign-in session.',
6
- not_found: 'Sign-in session not found.',
7
- },
8
- not_authenticated: 'Not authenticated.',
9
- fetch_user_info_failed: 'Unable to fetch user info. The access token may be invalid.',
10
- });
11
- const getMessageByErrorCode = (errorCode) => {
12
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
13
- const message = get(logtoClientErrorCodes, errorCode);
14
- if (typeof message === 'string') {
15
- return message;
16
- }
17
- return errorCode;
18
- };
19
- class LogtoClientError extends Error {
20
- constructor(code, data) {
21
- super(getMessageByErrorCode(code));
22
- this.code = code;
23
- this.data = data;
24
- }
25
- }
26
-
27
- export { LogtoClientError };
@@ -1,6 +0,0 @@
1
- import { discoveryPath } from '@logto/js';
2
-
3
- const buildAccessTokenKey = (resource = '', scopes = []) => `${scopes.slice().sort().join(' ')}@${resource}`;
4
- const getDiscoveryEndpoint = (endpoint) => new URL(discoveryPath, endpoint).toString();
5
-
6
- export { buildAccessTokenKey, getDiscoveryEndpoint };