@blazeo.com/calendar-client 1.0.27 → 1.0.28

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
@@ -24,23 +24,19 @@ Configure once at app startup, then use models and their methods:
24
24
  ```js
25
25
  import {
26
26
  configure,
27
- setBaseUrl,
28
- setConsumer,
29
- setApiCredentials,
30
- fetchAccessToken,
27
+ setAccessToken,
28
+ setGetAccessToken,
31
29
  CalendarModel,
32
30
  createRootStore,
33
31
  } from '@blazeo.com/calendar-client';
34
32
 
35
- configure({ baseUrl: 'https://your-appointment-api.example.com' });
36
- // or: setBaseUrl('https://localhost:7051');
37
- setConsumer('my-app'); // optional: sent as Consumer header (e.g. for lead source)
38
-
39
- // API JWT (for Authorized routes such as lead export)
40
- setApiCredentials('your-api-key', 'your-api-secret');
41
- await fetchAccessToken();
42
- // Or set a token you obtained elsewhere:
43
- // setAccessToken('eyJ...', '2026-05-19T12:00:00Z');
33
+ configure({
34
+ baseUrl: 'https://your-appointment-api.example.com',
35
+ consumer: 'my-app', // optional Consumer header
36
+ accessToken: yourIdpAccessToken, // JWT from your identity provider
37
+ expiresAtUtc: '2026-05-21T12:00:00Z', // optional used before auto-refresh
38
+ getAccessToken: async () => yourIdp.getAccessToken(), // optional refresh callback
39
+ });
44
40
 
45
41
  // Calendar static methods (no store needed)
46
42
  const timezones = await CalendarModel.getTimeZones();
@@ -52,23 +48,22 @@ const cal = store.addCalendar({ calendarId: 'my-cal', name: 'My Calendar' });
52
48
  await cal.create(); // POST to backend
53
49
  ```
54
50
 
55
- ### API JWT authentication
51
+ ### JWT authentication
56
52
 
57
- The backend issues JWTs via `POST Api/Auth/Token` (`api_key` + `api_secret`). There is no refresh endpoint; when the token expires (~1 hour), call `fetchAccessToken()` again.
53
+ The Appointment API validates Bearer JWTs from your identity provider (`Authentication:Jwt:Authority` on the server). This package does **not** exchange api keys for tokens pass the JWT your app already has.
58
54
 
59
55
  | Function | Purpose |
60
56
  |----------|---------|
61
- | `setApiCredentials(apiKey, apiSecret)` | Store credentials for token exchange |
62
- | `fetchAccessToken()` | Get JWT from API and store on config |
63
- | `setAccessToken(token, expiresAtUtc?)` | Use a token you already have |
64
- | `ensureValidAccessToken()` | Fetch only if missing or near expiry |
65
- | `clearAuth()` | Clear token and credentials |
57
+ | `setAccessToken(token, expiresAtUtc?)` | Store JWT from your IdP |
58
+ | `setGetAccessToken(fn)` | Async callback to refresh when missing/near expiry |
59
+ | `ensureValidAccessToken()` | Resolve token before a request (uses callback if needed) |
60
+ | `clearAuth()` | Clear token and refresh callback |
66
61
 
67
- All `reqGet` / `reqPost` calls automatically attach `Authorization: Bearer …` and re-issue the token before requests when credentials are configured.
62
+ All `reqGet` / `reqPost` calls attach `Authorization: Bearer …` when a token is configured.
68
63
 
69
64
  ```js
70
- configure({ baseUrl: 'https://your-api', apiKey: 'key', apiSecret: 'secret' });
71
- await fetchAccessToken();
65
+ setAccessToken(session.accessToken, session.expiresAt);
66
+ setGetAccessToken(() => authService.acquireTokenSilent());
72
67
  await LeadModel.requestExport('company-key');
73
68
  ```
74
69
 
package/dist/index.d.ts CHANGED
@@ -1,19 +1,8 @@
1
1
  /** @blazeo.com/calendar-client - type declarations */
2
2
 
3
- export type AccessTokenResult = {
4
- status: string;
5
- message?: string;
6
- accessToken?: string;
7
- expiresAtUtc?: string | null;
8
- tokenType?: string;
9
- };
10
-
11
3
  export type AuthState = {
12
4
  accessToken?: string;
13
5
  tokenExpiresAt?: string;
14
- apiKey?: string;
15
- apiSecret?: string;
16
- hasApiCredentials: boolean;
17
6
  };
18
7
 
19
8
  export function configure(env: {
@@ -25,10 +14,8 @@ export function configure(env: {
25
14
  expiresAtUtc?: string;
26
15
  tokenExpiresAt?: string;
27
16
  expires_at_utc?: string;
28
- apiKey?: string;
29
- api_key?: string;
30
- apiSecret?: string;
31
- api_secret?: string;
17
+ /** Called when the stored JWT is missing or near expiry; return a fresh token from your IdP. */
18
+ getAccessToken?: () => Promise<string | undefined>;
32
19
  }): void;
33
20
 
34
21
  export function getConfig(): {
@@ -38,23 +25,18 @@ export function getConfig(): {
38
25
  getDefaultOffset?: () => number;
39
26
  accessToken?: string;
40
27
  tokenExpiresAt?: string;
41
- hasApiCredentials?: boolean;
42
28
  } | null;
43
29
 
44
30
  export function setBaseUrl(baseUrl: string): void;
45
31
  export function setConsumer(consumer: string): void;
46
32
  export function setAccessToken(accessToken: string, expiresAtUtc?: string): void;
47
33
  export function clearAccessToken(): void;
48
- export function setApiCredentials(apiKey: string, apiSecret: string): void;
49
- export function clearApiCredentials(): void;
34
+ export function setGetAccessToken(fn: () => Promise<string | undefined>): void;
50
35
  export function clearAuth(): void;
51
36
  export function getAuth(): AuthState;
52
- export function fetchAccessToken(apiKey?: string, apiSecret?: string): Promise<AccessTokenResult>;
53
37
  export function ensureValidAccessToken(): Promise<string | undefined>;
54
- export function requestAccessToken(apiKey: string, apiSecret: string, opts?: { baseUrl?: string; fetch?: typeof fetch }): Promise<AccessTokenResult>;
55
38
  export function isAccessTokenExpired(expiresAtUtc?: string | number | Date | null, skewMs?: number): boolean;
56
39
  export function buildAuthHeaders(extra?: Record<string, string>): Record<string, string>;
57
- export const TOKEN_PATH: '/Api/Auth/Token';
58
40
  export const DEFAULT_TOKEN_REFRESH_SKEW_MS: number;
59
41
  export function getConfigStore(): unknown;
60
42
 
package/dist/index.js CHANGED
@@ -49,27 +49,23 @@ __export(index_exports, {
49
49
  RecurringFrequency: () => RecurringFrequency,
50
50
  RootStore: () => RootStore,
51
51
  SettingModel: () => Setting_default,
52
- TOKEN_PATH: () => TOKEN_PATH,
53
52
  TimeFrameModel: () => TimeFrame_default,
54
53
  TimeSlotModel: () => TimeSlot_default,
55
54
  Unit: () => Unit,
56
55
  buildAuthHeaders: () => buildAuthHeaders,
57
56
  clearAccessToken: () => clearAccessToken,
58
- clearApiCredentials: () => clearApiCredentials,
59
57
  clearAuth: () => clearAuth,
60
58
  configure: () => configure,
61
59
  createRootStore: () => createRootStore,
62
60
  ensureValidAccessToken: () => ensureValidAccessToken,
63
- fetchAccessToken: () => fetchAccessToken2,
64
61
  getAuth: () => getAuth,
65
62
  getConfig: () => getConfig,
66
63
  getConfigStore: () => getConfigStore,
67
64
  isAccessTokenExpired: () => isAccessTokenExpired,
68
- requestAccessToken: () => requestAccessToken,
69
65
  setAccessToken: () => setAccessToken,
70
- setApiCredentials: () => setApiCredentials,
71
66
  setBaseUrl: () => setBaseUrl,
72
- setConsumer: () => setConsumer
67
+ setConsumer: () => setConsumer,
68
+ setGetAccessToken: () => setGetAccessToken
73
69
  });
74
70
  module.exports = __toCommonJS(index_exports);
75
71
 
@@ -85,8 +81,8 @@ var ConfigModel = import_mobx_state_tree.types.model("Config", {
85
81
  fetch: void 0,
86
82
  accessToken: void 0,
87
83
  tokenExpiresAt: void 0,
88
- apiKey: void 0,
89
- apiSecret: void 0,
84
+ /** Host app supplies a fresh JWT (e.g. from your IdP) when the stored token is missing/expired. */
85
+ getAccessToken: void 0,
90
86
  getDefaultOffset: () => -(/* @__PURE__ */ new Date()).getTimezoneOffset()
91
87
  })).actions((self) => ({
92
88
  setBaseUrl(url) {
@@ -101,6 +97,9 @@ var ConfigModel = import_mobx_state_tree.types.model("Config", {
101
97
  setGetDefaultOffset(fn) {
102
98
  self.getDefaultOffset = fn;
103
99
  },
100
+ setGetAccessToken(fn) {
101
+ self.getAccessToken = fn;
102
+ },
104
103
  setAccessToken(token, expiresAtUtc = void 0) {
105
104
  self.accessToken = token ? String(token) : void 0;
106
105
  self.tokenExpiresAt = expiresAtUtc != null && expiresAtUtc !== "" ? String(expiresAtUtc) : void 0;
@@ -109,40 +108,24 @@ var ConfigModel = import_mobx_state_tree.types.model("Config", {
109
108
  self.accessToken = void 0;
110
109
  self.tokenExpiresAt = void 0;
111
110
  },
112
- setApiCredentials(apiKey, apiSecret) {
113
- self.apiKey = apiKey != null ? String(apiKey) : void 0;
114
- self.apiSecret = apiSecret != null ? String(apiSecret) : void 0;
115
- },
116
- clearApiCredentials() {
117
- self.apiKey = void 0;
118
- self.apiSecret = void 0;
119
- },
120
111
  clearAuth() {
121
112
  self.clearAccessToken();
122
- self.clearApiCredentials();
113
+ self.getAccessToken = void 0;
123
114
  },
124
115
  configure(env) {
125
116
  if (env.baseUrl != null) self.baseUrl = env.baseUrl;
126
117
  if (env.consumer != null) self.consumer = env.consumer;
127
118
  if (env.fetch != null) self.fetch = env.fetch;
128
119
  if (env.getDefaultOffset != null) self.getDefaultOffset = env.getDefaultOffset;
120
+ if (env.getAccessToken != null) self.getAccessToken = env.getAccessToken;
129
121
  if (env.accessToken != null) {
130
122
  self.setAccessToken(
131
123
  env.accessToken,
132
124
  env.expiresAtUtc ?? env.tokenExpiresAt ?? env.expires_at_utc
133
125
  );
134
126
  }
135
- if (env.apiKey != null || env.api_key != null) {
136
- self.apiKey = String(env.apiKey ?? env.api_key);
137
- }
138
- if (env.apiSecret != null || env.api_secret != null) {
139
- self.apiSecret = String(env.apiSecret ?? env.api_secret);
140
- }
141
127
  }
142
128
  })).views((self) => ({
143
- get hasApiCredentials() {
144
- return Boolean(self.apiKey && self.apiSecret);
145
- },
146
129
  getEnv() {
147
130
  return {
148
131
  baseUrl: self.baseUrl || void 0,
@@ -150,8 +133,7 @@ var ConfigModel = import_mobx_state_tree.types.model("Config", {
150
133
  fetch: self.fetch,
151
134
  getDefaultOffset: self.getDefaultOffset,
152
135
  accessToken: self.accessToken,
153
- tokenExpiresAt: self.tokenExpiresAt,
154
- hasApiCredentials: self.hasApiCredentials
136
+ tokenExpiresAt: self.tokenExpiresAt
155
137
  };
156
138
  }
157
139
  }));
@@ -163,26 +145,7 @@ function getConfigStore() {
163
145
  var ConfigModel_default = ConfigModel;
164
146
 
165
147
  // src/apiAuth.js
166
- var TOKEN_PATH = "/Api/Auth/Token";
167
148
  var DEFAULT_TOKEN_REFRESH_SKEW_MS = 6e4;
168
- function defaultFetch() {
169
- if (typeof fetch === "undefined") {
170
- throw new Error("fetch not available");
171
- }
172
- return fetch;
173
- }
174
- function pickTokenPayload(data) {
175
- if (!data || typeof data !== "object") return null;
176
- const nested = data.data && typeof data.data === "object" ? data.data : data;
177
- const accessToken = nested.access_token ?? nested.accessToken ?? nested.AccessToken ?? null;
178
- if (!accessToken) return null;
179
- const expiresAtUtc = nested.expires_at_utc ?? nested.expiresAtUtc ?? nested.ExpiresAtUtc ?? null;
180
- return {
181
- accessToken: String(accessToken),
182
- expiresAtUtc: expiresAtUtc != null ? String(expiresAtUtc) : null,
183
- tokenType: nested.token_type ?? nested.tokenType ?? "Bearer"
184
- };
185
- }
186
149
  function isAccessTokenExpired(expiresAtUtc, skewMs = DEFAULT_TOKEN_REFRESH_SKEW_MS) {
187
150
  if (expiresAtUtc == null || expiresAtUtc === "") return false;
188
151
  const expMs = new Date(expiresAtUtc).getTime();
@@ -193,77 +156,22 @@ function getAuthState() {
193
156
  const store = getConfigStore();
194
157
  return {
195
158
  accessToken: store.accessToken ?? void 0,
196
- tokenExpiresAt: store.tokenExpiresAt ?? void 0,
197
- apiKey: store.apiKey ?? void 0,
198
- apiSecret: store.apiSecret ?? void 0,
199
- hasApiCredentials: Boolean(store.apiKey && store.apiSecret)
200
- };
201
- }
202
- async function requestAccessToken(apiKey, apiSecret, opts = {}) {
203
- const store = getConfigStore();
204
- const baseUrl = opts.baseUrl ?? store.baseUrl;
205
- if (!baseUrl) {
206
- return { status: "failure", message: "baseUrl required. Call configure({ baseUrl }) first." };
207
- }
208
- const key = apiKey != null ? String(apiKey).trim() : "";
209
- const secret = apiSecret != null ? String(apiSecret).trim() : "";
210
- if (!key || !secret) {
211
- return { status: "failure", message: "api_key and api_secret are required" };
212
- }
213
- const fetchFn = opts.fetch ?? store.fetch ?? defaultFetch();
214
- const url = `${String(baseUrl).replace(/\/+$/, "")}${TOKEN_PATH}`;
215
- const httpRes = await fetchFn(url, {
216
- method: "POST",
217
- headers: { "Content-Type": "application/json" },
218
- body: JSON.stringify({ api_key: key, api_secret: secret })
219
- });
220
- const text = await httpRes.text();
221
- let body;
222
- try {
223
- body = JSON.parse(text);
224
- } catch {
225
- body = { status: "failure", message: text || httpRes.statusText };
226
- }
227
- if (!httpRes.ok && body.status !== "failure") {
228
- body.status = "failure";
229
- body.message = body.message ?? `HTTP ${httpRes.status}`;
230
- }
231
- if (body.status !== "success") {
232
- return {
233
- status: "failure",
234
- message: body.message ?? "Failed to obtain access token"
235
- };
236
- }
237
- const parsed = pickTokenPayload(body);
238
- if (!parsed) {
239
- return { status: "failure", message: "Token response missing access_token" };
240
- }
241
- return {
242
- status: "success",
243
- accessToken: parsed.accessToken,
244
- expiresAtUtc: parsed.expiresAtUtc,
245
- tokenType: parsed.tokenType
159
+ tokenExpiresAt: store.tokenExpiresAt ?? void 0
246
160
  };
247
161
  }
248
- async function fetchAccessToken(apiKey, apiSecret) {
249
- const store = getConfigStore();
250
- const key = apiKey ?? store.apiKey;
251
- const secret = apiSecret ?? store.apiSecret;
252
- const result = await requestAccessToken(key, secret);
253
- if (result.status === "success") {
254
- store.setAccessToken(result.accessToken, result.expiresAtUtc);
255
- }
256
- return result;
257
- }
258
162
  async function ensureAccessToken() {
259
163
  const store = getConfigStore();
260
- const { accessToken, tokenExpiresAt, apiKey, apiSecret } = getAuthState();
164
+ const { accessToken, tokenExpiresAt } = getAuthState();
261
165
  if (accessToken && !isAccessTokenExpired(tokenExpiresAt)) {
262
166
  return accessToken;
263
167
  }
264
- if (apiKey && apiSecret) {
265
- const result = await fetchAccessToken(apiKey, apiSecret);
266
- if (result.status === "success") return result.accessToken;
168
+ const refresh = store.getAccessToken;
169
+ if (typeof refresh === "function") {
170
+ const next = await refresh();
171
+ if (next) {
172
+ store.setAccessToken(next);
173
+ return next;
174
+ }
267
175
  }
268
176
  return accessToken;
269
177
  }
@@ -300,11 +208,8 @@ function setAccessToken(accessToken, expiresAtUtc) {
300
208
  function clearAccessToken() {
301
209
  getConfigStore().clearAccessToken();
302
210
  }
303
- function setApiCredentials(apiKey, apiSecret) {
304
- getConfigStore().setApiCredentials(apiKey, apiSecret);
305
- }
306
- function clearApiCredentials() {
307
- getConfigStore().clearApiCredentials();
211
+ function setGetAccessToken(fn) {
212
+ getConfigStore().setGetAccessToken(fn);
308
213
  }
309
214
  function clearAuth() {
310
215
  getConfigStore().clearAuth();
@@ -312,9 +217,6 @@ function clearAuth() {
312
217
  function getAuth() {
313
218
  return getAuthState();
314
219
  }
315
- function fetchAccessToken2(apiKey, apiSecret) {
316
- return fetchAccessToken(apiKey, apiSecret);
317
- }
318
220
  function ensureValidAccessToken() {
319
221
  return ensureAccessToken();
320
222
  }
@@ -3035,25 +2937,21 @@ function createRootStore(initialState = {}) {
3035
2937
  RecurringFrequency,
3036
2938
  RootStore,
3037
2939
  SettingModel,
3038
- TOKEN_PATH,
3039
2940
  TimeFrameModel,
3040
2941
  TimeSlotModel,
3041
2942
  Unit,
3042
2943
  buildAuthHeaders,
3043
2944
  clearAccessToken,
3044
- clearApiCredentials,
3045
2945
  clearAuth,
3046
2946
  configure,
3047
2947
  createRootStore,
3048
2948
  ensureValidAccessToken,
3049
- fetchAccessToken,
3050
2949
  getAuth,
3051
2950
  getConfig,
3052
2951
  getConfigStore,
3053
2952
  isAccessTokenExpired,
3054
- requestAccessToken,
3055
2953
  setAccessToken,
3056
- setApiCredentials,
3057
2954
  setBaseUrl,
3058
- setConsumer
2955
+ setConsumer,
2956
+ setGetAccessToken
3059
2957
  });
package/dist/index.mjs CHANGED
@@ -10,8 +10,8 @@ var ConfigModel = types.model("Config", {
10
10
  fetch: void 0,
11
11
  accessToken: void 0,
12
12
  tokenExpiresAt: void 0,
13
- apiKey: void 0,
14
- apiSecret: void 0,
13
+ /** Host app supplies a fresh JWT (e.g. from your IdP) when the stored token is missing/expired. */
14
+ getAccessToken: void 0,
15
15
  getDefaultOffset: () => -(/* @__PURE__ */ new Date()).getTimezoneOffset()
16
16
  })).actions((self) => ({
17
17
  setBaseUrl(url) {
@@ -26,6 +26,9 @@ var ConfigModel = types.model("Config", {
26
26
  setGetDefaultOffset(fn) {
27
27
  self.getDefaultOffset = fn;
28
28
  },
29
+ setGetAccessToken(fn) {
30
+ self.getAccessToken = fn;
31
+ },
29
32
  setAccessToken(token, expiresAtUtc = void 0) {
30
33
  self.accessToken = token ? String(token) : void 0;
31
34
  self.tokenExpiresAt = expiresAtUtc != null && expiresAtUtc !== "" ? String(expiresAtUtc) : void 0;
@@ -34,40 +37,24 @@ var ConfigModel = types.model("Config", {
34
37
  self.accessToken = void 0;
35
38
  self.tokenExpiresAt = void 0;
36
39
  },
37
- setApiCredentials(apiKey, apiSecret) {
38
- self.apiKey = apiKey != null ? String(apiKey) : void 0;
39
- self.apiSecret = apiSecret != null ? String(apiSecret) : void 0;
40
- },
41
- clearApiCredentials() {
42
- self.apiKey = void 0;
43
- self.apiSecret = void 0;
44
- },
45
40
  clearAuth() {
46
41
  self.clearAccessToken();
47
- self.clearApiCredentials();
42
+ self.getAccessToken = void 0;
48
43
  },
49
44
  configure(env) {
50
45
  if (env.baseUrl != null) self.baseUrl = env.baseUrl;
51
46
  if (env.consumer != null) self.consumer = env.consumer;
52
47
  if (env.fetch != null) self.fetch = env.fetch;
53
48
  if (env.getDefaultOffset != null) self.getDefaultOffset = env.getDefaultOffset;
49
+ if (env.getAccessToken != null) self.getAccessToken = env.getAccessToken;
54
50
  if (env.accessToken != null) {
55
51
  self.setAccessToken(
56
52
  env.accessToken,
57
53
  env.expiresAtUtc ?? env.tokenExpiresAt ?? env.expires_at_utc
58
54
  );
59
55
  }
60
- if (env.apiKey != null || env.api_key != null) {
61
- self.apiKey = String(env.apiKey ?? env.api_key);
62
- }
63
- if (env.apiSecret != null || env.api_secret != null) {
64
- self.apiSecret = String(env.apiSecret ?? env.api_secret);
65
- }
66
56
  }
67
57
  })).views((self) => ({
68
- get hasApiCredentials() {
69
- return Boolean(self.apiKey && self.apiSecret);
70
- },
71
58
  getEnv() {
72
59
  return {
73
60
  baseUrl: self.baseUrl || void 0,
@@ -75,8 +62,7 @@ var ConfigModel = types.model("Config", {
75
62
  fetch: self.fetch,
76
63
  getDefaultOffset: self.getDefaultOffset,
77
64
  accessToken: self.accessToken,
78
- tokenExpiresAt: self.tokenExpiresAt,
79
- hasApiCredentials: self.hasApiCredentials
65
+ tokenExpiresAt: self.tokenExpiresAt
80
66
  };
81
67
  }
82
68
  }));
@@ -88,26 +74,7 @@ function getConfigStore() {
88
74
  var ConfigModel_default = ConfigModel;
89
75
 
90
76
  // src/apiAuth.js
91
- var TOKEN_PATH = "/Api/Auth/Token";
92
77
  var DEFAULT_TOKEN_REFRESH_SKEW_MS = 6e4;
93
- function defaultFetch() {
94
- if (typeof fetch === "undefined") {
95
- throw new Error("fetch not available");
96
- }
97
- return fetch;
98
- }
99
- function pickTokenPayload(data) {
100
- if (!data || typeof data !== "object") return null;
101
- const nested = data.data && typeof data.data === "object" ? data.data : data;
102
- const accessToken = nested.access_token ?? nested.accessToken ?? nested.AccessToken ?? null;
103
- if (!accessToken) return null;
104
- const expiresAtUtc = nested.expires_at_utc ?? nested.expiresAtUtc ?? nested.ExpiresAtUtc ?? null;
105
- return {
106
- accessToken: String(accessToken),
107
- expiresAtUtc: expiresAtUtc != null ? String(expiresAtUtc) : null,
108
- tokenType: nested.token_type ?? nested.tokenType ?? "Bearer"
109
- };
110
- }
111
78
  function isAccessTokenExpired(expiresAtUtc, skewMs = DEFAULT_TOKEN_REFRESH_SKEW_MS) {
112
79
  if (expiresAtUtc == null || expiresAtUtc === "") return false;
113
80
  const expMs = new Date(expiresAtUtc).getTime();
@@ -118,77 +85,22 @@ function getAuthState() {
118
85
  const store = getConfigStore();
119
86
  return {
120
87
  accessToken: store.accessToken ?? void 0,
121
- tokenExpiresAt: store.tokenExpiresAt ?? void 0,
122
- apiKey: store.apiKey ?? void 0,
123
- apiSecret: store.apiSecret ?? void 0,
124
- hasApiCredentials: Boolean(store.apiKey && store.apiSecret)
125
- };
126
- }
127
- async function requestAccessToken(apiKey, apiSecret, opts = {}) {
128
- const store = getConfigStore();
129
- const baseUrl = opts.baseUrl ?? store.baseUrl;
130
- if (!baseUrl) {
131
- return { status: "failure", message: "baseUrl required. Call configure({ baseUrl }) first." };
132
- }
133
- const key = apiKey != null ? String(apiKey).trim() : "";
134
- const secret = apiSecret != null ? String(apiSecret).trim() : "";
135
- if (!key || !secret) {
136
- return { status: "failure", message: "api_key and api_secret are required" };
137
- }
138
- const fetchFn = opts.fetch ?? store.fetch ?? defaultFetch();
139
- const url = `${String(baseUrl).replace(/\/+$/, "")}${TOKEN_PATH}`;
140
- const httpRes = await fetchFn(url, {
141
- method: "POST",
142
- headers: { "Content-Type": "application/json" },
143
- body: JSON.stringify({ api_key: key, api_secret: secret })
144
- });
145
- const text = await httpRes.text();
146
- let body;
147
- try {
148
- body = JSON.parse(text);
149
- } catch {
150
- body = { status: "failure", message: text || httpRes.statusText };
151
- }
152
- if (!httpRes.ok && body.status !== "failure") {
153
- body.status = "failure";
154
- body.message = body.message ?? `HTTP ${httpRes.status}`;
155
- }
156
- if (body.status !== "success") {
157
- return {
158
- status: "failure",
159
- message: body.message ?? "Failed to obtain access token"
160
- };
161
- }
162
- const parsed = pickTokenPayload(body);
163
- if (!parsed) {
164
- return { status: "failure", message: "Token response missing access_token" };
165
- }
166
- return {
167
- status: "success",
168
- accessToken: parsed.accessToken,
169
- expiresAtUtc: parsed.expiresAtUtc,
170
- tokenType: parsed.tokenType
88
+ tokenExpiresAt: store.tokenExpiresAt ?? void 0
171
89
  };
172
90
  }
173
- async function fetchAccessToken(apiKey, apiSecret) {
174
- const store = getConfigStore();
175
- const key = apiKey ?? store.apiKey;
176
- const secret = apiSecret ?? store.apiSecret;
177
- const result = await requestAccessToken(key, secret);
178
- if (result.status === "success") {
179
- store.setAccessToken(result.accessToken, result.expiresAtUtc);
180
- }
181
- return result;
182
- }
183
91
  async function ensureAccessToken() {
184
92
  const store = getConfigStore();
185
- const { accessToken, tokenExpiresAt, apiKey, apiSecret } = getAuthState();
93
+ const { accessToken, tokenExpiresAt } = getAuthState();
186
94
  if (accessToken && !isAccessTokenExpired(tokenExpiresAt)) {
187
95
  return accessToken;
188
96
  }
189
- if (apiKey && apiSecret) {
190
- const result = await fetchAccessToken(apiKey, apiSecret);
191
- if (result.status === "success") return result.accessToken;
97
+ const refresh = store.getAccessToken;
98
+ if (typeof refresh === "function") {
99
+ const next = await refresh();
100
+ if (next) {
101
+ store.setAccessToken(next);
102
+ return next;
103
+ }
192
104
  }
193
105
  return accessToken;
194
106
  }
@@ -225,11 +137,8 @@ function setAccessToken(accessToken, expiresAtUtc) {
225
137
  function clearAccessToken() {
226
138
  getConfigStore().clearAccessToken();
227
139
  }
228
- function setApiCredentials(apiKey, apiSecret) {
229
- getConfigStore().setApiCredentials(apiKey, apiSecret);
230
- }
231
- function clearApiCredentials() {
232
- getConfigStore().clearApiCredentials();
140
+ function setGetAccessToken(fn) {
141
+ getConfigStore().setGetAccessToken(fn);
233
142
  }
234
143
  function clearAuth() {
235
144
  getConfigStore().clearAuth();
@@ -237,9 +146,6 @@ function clearAuth() {
237
146
  function getAuth() {
238
147
  return getAuthState();
239
148
  }
240
- function fetchAccessToken2(apiKey, apiSecret) {
241
- return fetchAccessToken(apiKey, apiSecret);
242
- }
243
149
  function ensureValidAccessToken() {
244
150
  return ensureAccessToken();
245
151
  }
@@ -2959,25 +2865,21 @@ export {
2959
2865
  RecurringFrequency,
2960
2866
  RootStore,
2961
2867
  Setting_default as SettingModel,
2962
- TOKEN_PATH,
2963
2868
  TimeFrame_default as TimeFrameModel,
2964
2869
  TimeSlot_default as TimeSlotModel,
2965
2870
  Unit,
2966
2871
  buildAuthHeaders,
2967
2872
  clearAccessToken,
2968
- clearApiCredentials,
2969
2873
  clearAuth,
2970
2874
  configure,
2971
2875
  createRootStore,
2972
2876
  ensureValidAccessToken,
2973
- fetchAccessToken2 as fetchAccessToken,
2974
2877
  getAuth,
2975
2878
  getConfig,
2976
2879
  getConfigStore,
2977
2880
  isAccessTokenExpired,
2978
- requestAccessToken,
2979
2881
  setAccessToken,
2980
- setApiCredentials,
2981
2882
  setBaseUrl,
2982
- setConsumer
2883
+ setConsumer,
2884
+ setGetAccessToken
2983
2885
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blazeo.com/calendar-client",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "description": "Blazeo Calendar / Appointment API client with MobX State Tree models",
5
5
  "exports": {
6
6
  ".": {