@flexbe/sdk 0.1.1 → 0.1.3

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.
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FlexbeAuth = void 0;
4
+ const types_1 = require("../types");
5
+ const token_manager_1 = require("./token-manager");
6
+ class FlexbeAuth {
7
+ constructor(config) {
8
+ this.initialized = false;
9
+ this.initializationPromise = null;
10
+ this.config = config;
11
+ this.tokenManager = token_manager_1.TokenManager.getInstance();
12
+ if (this.config.authType === types_1.FlexbeAuthType.BEARER) {
13
+ // Start initialization but don't wait for it
14
+ this.initializationPromise = this.initialize();
15
+ }
16
+ else {
17
+ this.initialized = true;
18
+ }
19
+ }
20
+ async initialize() {
21
+ try {
22
+ const token = await this.tokenManager.getToken();
23
+ this.initialized = !!token;
24
+ }
25
+ catch (error) {
26
+ console.error('Failed to initialize auth:', error);
27
+ this.initialized = false;
28
+ }
29
+ finally {
30
+ this.initializationPromise = null;
31
+ }
32
+ }
33
+ async ensureInitialized() {
34
+ if (this.config.authType !== types_1.FlexbeAuthType.BEARER || this.initialized) {
35
+ return;
36
+ }
37
+ // If initialization is in progress, wait for it
38
+ if (this.initializationPromise) {
39
+ await this.initializationPromise;
40
+ return;
41
+ }
42
+ // If not initialized and no initialization in progress, start one
43
+ await this.initialize();
44
+ }
45
+ async getAuthHeaders() {
46
+ await this.ensureInitialized();
47
+ const headers = {
48
+ 'Content-Type': 'application/json',
49
+ };
50
+ if (this.config.authType === types_1.FlexbeAuthType.API_KEY) {
51
+ headers['x-api-key'] = this.config.apiKey;
52
+ }
53
+ else if (this.config.authType === types_1.FlexbeAuthType.BEARER) {
54
+ const token = await this.tokenManager.getToken();
55
+ if (!token) {
56
+ throw new Error('No valid bearer token available');
57
+ }
58
+ headers['Authorization'] = `Bearer ${token}`;
59
+ }
60
+ return headers;
61
+ }
62
+ }
63
+ exports.FlexbeAuth = FlexbeAuth;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlexbeClient = void 0;
4
+ const types_1 = require("../types");
4
5
  const pages_1 = require("./pages");
6
+ const api_client_1 = require("./api-client");
5
7
  class FlexbeClient {
6
8
  constructor(config) {
7
9
  const getEnvVar = (key) => {
@@ -15,96 +17,13 @@ class FlexbeClient {
15
17
  timeout: config?.timeout || 30000,
16
18
  apiKey: config?.apiKey || getEnvVar('FLEXBE_API_KEY') || '',
17
19
  siteId: config?.siteId || getEnvVar('FLEXBE_SITE_ID'),
20
+ authType: config?.authType || types_1.FlexbeAuthType.API_KEY,
18
21
  };
19
- if (!this.config.apiKey) {
20
- throw new Error('API key is required. Please provide it either through config or FLEXBE_API_KEY environment variable.');
22
+ if (this.config.authType === 'apiKey' && !this.config.apiKey) {
23
+ throw new Error('API key is required when using apiKey authentication. Please provide it either through config or FLEXBE_API_KEY environment variable.');
21
24
  }
22
- this.pages = new pages_1.Pages(this);
23
- }
24
- buildUrl(path, params) {
25
- const searchParams = new URLSearchParams();
26
- if (params) {
27
- Object.entries(params).forEach(([key, value]) => {
28
- if (value !== undefined && value !== null) {
29
- searchParams.append(key, String(value));
30
- }
31
- });
32
- }
33
- return `${path}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
34
- }
35
- async request(config) {
36
- try {
37
- const controller = new AbortController();
38
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
39
- const url = this.buildUrl(config.url, config.params);
40
- const response = await fetch(this.config.baseUrl + url, {
41
- ...config,
42
- headers: {
43
- 'Authorization': `Bearer ${this.config.apiKey}`,
44
- 'Content-Type': 'application/json',
45
- ...config.headers,
46
- },
47
- signal: controller.signal,
48
- });
49
- clearTimeout(timeoutId);
50
- if (!response.ok) {
51
- const defaultError = { message: response.statusText };
52
- const errorData = await response.json().catch(() => defaultError);
53
- const error = {
54
- message: errorData.message || response.statusText,
55
- code: errorData.code,
56
- status: response.status,
57
- details: errorData.details,
58
- };
59
- throw error;
60
- }
61
- const data = await response.json();
62
- return {
63
- data,
64
- status: response.status,
65
- statusText: response.statusText,
66
- };
67
- }
68
- catch (error) {
69
- if (error instanceof Error && error.name === 'AbortError') {
70
- const timeoutError = {
71
- message: 'Request timeout',
72
- status: 408,
73
- };
74
- throw timeoutError;
75
- }
76
- throw error;
77
- }
78
- }
79
- get(url, config) {
80
- return this.request({ ...config, method: 'GET', url });
81
- }
82
- post(url, data, config) {
83
- return this.request({ ...config, method: 'POST', url, body: JSON.stringify(data) });
84
- }
85
- put(url, data, config) {
86
- return this.request({ ...config, method: 'PUT', url, body: JSON.stringify(data) });
87
- }
88
- delete(url, config) {
89
- return this.request({ ...config, method: 'DELETE', url });
90
- }
91
- getSiteUrl(path) {
92
- if (!this.config.siteId) {
93
- return path;
94
- }
95
- return `/sites/${this.config.siteId}${path}`;
96
- }
97
- sitesGet(path, config) {
98
- return this.get(this.getSiteUrl(path), config);
99
- }
100
- sitesPost(path, data, config) {
101
- return this.post(this.getSiteUrl(path), data, config);
102
- }
103
- sitesPut(path, data, config) {
104
- return this.put(this.getSiteUrl(path), data, config);
105
- }
106
- sitesDelete(path, config) {
107
- return this.delete(this.getSiteUrl(path), config);
25
+ this.api = new api_client_1.ApiClient(this.config);
26
+ this.pages = new pages_1.Pages(this.api);
108
27
  }
109
28
  }
110
29
  exports.FlexbeClient = FlexbeClient;
@@ -2,21 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Pages = void 0;
4
4
  class Pages {
5
- constructor(client) {
6
- this.client = client;
5
+ constructor(api) {
6
+ this.api = api;
7
7
  }
8
8
  /**
9
9
  * Get list of pages for a site
10
10
  */
11
11
  async getPages(params) {
12
- const response = await this.client.sitesGet('/pages', { params });
12
+ const response = await this.api.get('/sites/:siteId:/pages', { params });
13
13
  return response.data;
14
14
  }
15
15
  /**
16
16
  * Get a single page by ID
17
17
  */
18
18
  async getPage(pageId) {
19
- const response = await this.client.sitesGet(`/pages/${pageId}`);
19
+ const response = await this.api.get(`/sites/:siteId:/pages/${pageId}`);
20
20
  return response.data;
21
21
  }
22
22
  }
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenManager = void 0;
4
+ const TOKEN_STORAGE_KEY = 'flexbe_jwt_token';
5
+ const REFRESH_THRESHOLD = 0.8; // Refresh when 80% of token lifetime has passed
6
+ const REFRESH_CHECK_INTERVAL = 30 * 1000; // Check every 30 seconds
7
+ const MAX_REFRESH_DELAY = 10000; // Maximum random delay of 10 seconds
8
+ class TokenManager {
9
+ constructor() {
10
+ this.token = null;
11
+ this.refreshInterval = null;
12
+ this.refreshTimeout = null;
13
+ this.tokenPromise = null;
14
+ this.debug = false;
15
+ this.initializeFromStorage();
16
+ this.setupStorageListener();
17
+ }
18
+ static getInstance() {
19
+ if (!TokenManager.instance) {
20
+ TokenManager.instance = new TokenManager();
21
+ }
22
+ return TokenManager.instance;
23
+ }
24
+ initializeFromStorage() {
25
+ if (typeof window === 'undefined')
26
+ return;
27
+ const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY);
28
+ if (!storedToken)
29
+ return;
30
+ try {
31
+ this.token = JSON.parse(storedToken);
32
+ if (this.token.expiresAt > Date.now()) {
33
+ this.logTokenStatus('Token loaded from storage');
34
+ this.startRefreshInterval();
35
+ }
36
+ else {
37
+ this.clearToken();
38
+ }
39
+ }
40
+ catch (error) {
41
+ console.error('Failed to parse stored token:', error);
42
+ this.clearToken();
43
+ }
44
+ }
45
+ setupStorageListener() {
46
+ if (typeof window === 'undefined')
47
+ return;
48
+ window.addEventListener('storage', (event) => {
49
+ if (event.key !== TOKEN_STORAGE_KEY)
50
+ return;
51
+ if (!event.newValue) {
52
+ this.clearToken();
53
+ void this.retrieveToken();
54
+ return;
55
+ }
56
+ try {
57
+ const newToken = JSON.parse(event.newValue);
58
+ // Skip if the new token is exactly the same as current token
59
+ if (this.token &&
60
+ this.token.accessToken === newToken.accessToken &&
61
+ this.token.expiresAt === newToken.expiresAt) {
62
+ return;
63
+ }
64
+ if (newToken.expiresAt > Date.now()) {
65
+ this.token = newToken;
66
+ this.logTokenStatus('Token updated from storage');
67
+ this.startRefreshInterval();
68
+ }
69
+ else {
70
+ this.clearToken();
71
+ void this.retrieveToken();
72
+ }
73
+ }
74
+ catch (error) {
75
+ console.error('Failed to parse token from storage event:', error);
76
+ this.clearToken();
77
+ void this.retrieveToken();
78
+ }
79
+ });
80
+ }
81
+ getExpirationFromToken(token) {
82
+ try {
83
+ const [, payload] = token.split('.');
84
+ const decodedPayload = JSON.parse(atob(payload));
85
+ return decodedPayload.exp * 1000; // Convert to milliseconds
86
+ }
87
+ catch (error) {
88
+ console.error('Failed to parse token expiration:', error);
89
+ return Date.now() + (4 * 60 * 1000); // Default to 4 minutes if parsing fails
90
+ }
91
+ }
92
+ async getToken() {
93
+ const token = this.token;
94
+ if (token && token.expiresAt && token.expiresAt > Date.now()) {
95
+ return token.accessToken;
96
+ }
97
+ await this.retrieveToken();
98
+ return this.token?.accessToken ?? null;
99
+ }
100
+ async retrieveToken() {
101
+ if (this.tokenPromise) {
102
+ await this.tokenPromise;
103
+ return;
104
+ }
105
+ this.tokenPromise = this.doRetrieveToken();
106
+ try {
107
+ await this.tokenPromise;
108
+ }
109
+ finally {
110
+ this.tokenPromise = null;
111
+ }
112
+ }
113
+ async doRetrieveToken() {
114
+ const controller = new AbortController();
115
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
116
+ try {
117
+ const response = await fetch('/oauth/token', {
118
+ method: 'POST',
119
+ headers: { 'Content-Type': 'application/json' },
120
+ body: JSON.stringify({ grant_type: 'client_credentials' }),
121
+ credentials: 'include',
122
+ signal: controller.signal,
123
+ });
124
+ clearTimeout(timeoutId);
125
+ if (!response.ok) {
126
+ const errorData = await response.json().catch(() => ({ message: response.statusText }));
127
+ throw new Error(errorData.message || response.statusText);
128
+ }
129
+ const data = await response.json();
130
+ this.setToken(data);
131
+ }
132
+ catch (error) {
133
+ console.error('Failed to retrieve token:', error);
134
+ this.clearToken();
135
+ throw error;
136
+ }
137
+ }
138
+ startRefreshInterval() {
139
+ this.clearRefreshTimers();
140
+ if (!this.token)
141
+ return;
142
+ const tokenLifetime = this.token.expiresAt - Date.now();
143
+ const refreshThreshold = Math.round(tokenLifetime * REFRESH_THRESHOLD);
144
+ const timeUntilRefresh = refreshThreshold - (Math.random() * MAX_REFRESH_DELAY);
145
+ this.logTokenStatus('Starting refresh interval', {
146
+ tokenLifetime: `${Math.round(tokenLifetime / 1000)} seconds`,
147
+ refreshThreshold: `${Math.round(refreshThreshold / 1000)} seconds`,
148
+ timeUntilRefresh: `${Math.round(timeUntilRefresh / 1000)} seconds`,
149
+ });
150
+ this.scheduleRefresh(timeUntilRefresh);
151
+ this.refreshInterval = window.setInterval(() => {
152
+ if (!this.token)
153
+ return;
154
+ const timeUntilExpiry = this.token.expiresAt - Date.now();
155
+ if (timeUntilExpiry <= 0) {
156
+ this.logTokenStatus('Token expired');
157
+ this.clearToken();
158
+ void this.retrieveToken();
159
+ return;
160
+ }
161
+ const refreshThreshold = Math.round(timeUntilExpiry * REFRESH_THRESHOLD);
162
+ if (timeUntilExpiry <= refreshThreshold) {
163
+ this.logTokenStatus('Refreshing token', {
164
+ timeUntilExpiry: `${Math.round(timeUntilExpiry / 1000)} seconds`,
165
+ refreshThreshold: `${Math.round(refreshThreshold / 1000)} seconds`,
166
+ });
167
+ this.scheduleRefresh(refreshThreshold - (Math.random() * MAX_REFRESH_DELAY));
168
+ }
169
+ }, REFRESH_CHECK_INTERVAL);
170
+ }
171
+ scheduleRefresh(delay) {
172
+ if (this.refreshTimeout) {
173
+ window.clearTimeout(this.refreshTimeout);
174
+ }
175
+ this.refreshTimeout = window.setTimeout(() => {
176
+ const token = this.token;
177
+ if (token && token.expiresAt - Date.now() <= token.expiresAt * REFRESH_THRESHOLD) {
178
+ void this.retrieveToken();
179
+ }
180
+ }, delay);
181
+ }
182
+ clearRefreshTimers() {
183
+ if (this.refreshInterval) {
184
+ clearInterval(this.refreshInterval);
185
+ this.refreshInterval = null;
186
+ }
187
+ if (this.refreshTimeout) {
188
+ window.clearTimeout(this.refreshTimeout);
189
+ this.refreshTimeout = null;
190
+ }
191
+ }
192
+ logTokenStatus(message, additionalInfo = {}) {
193
+ if (!this.debug)
194
+ return;
195
+ const token = this.token;
196
+ if (!token)
197
+ return;
198
+ console.log(message, {
199
+ expiresIn: `${Math.round((token.expiresAt - Date.now()) / 1000)} seconds`,
200
+ expiresAt: new Date(token.expiresAt).toISOString(),
201
+ ...additionalInfo,
202
+ });
203
+ }
204
+ setToken(tokenResponse) {
205
+ const expiresAt = this.getExpirationFromToken(tokenResponse.accessToken);
206
+ this.token = {
207
+ accessToken: tokenResponse.accessToken,
208
+ expiresAt,
209
+ };
210
+ this.logTokenStatus('Token set', {
211
+ expiresAt: new Date(expiresAt).toISOString(),
212
+ });
213
+ if (typeof window !== 'undefined') {
214
+ localStorage.setItem(TOKEN_STORAGE_KEY, JSON.stringify(this.token));
215
+ }
216
+ this.startRefreshInterval();
217
+ }
218
+ clearToken() {
219
+ this.token = null;
220
+ this.clearRefreshTimers();
221
+ if (typeof window !== 'undefined') {
222
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
223
+ }
224
+ }
225
+ }
226
+ exports.TokenManager = TokenManager;
@@ -1,2 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FlexbeAuthType = void 0;
4
+ var FlexbeAuthType;
5
+ (function (FlexbeAuthType) {
6
+ FlexbeAuthType["API_KEY"] = "apiKey";
7
+ FlexbeAuthType["BEARER"] = "bearer";
8
+ })(FlexbeAuthType || (exports.FlexbeAuthType = FlexbeAuthType = {}));
@@ -0,0 +1,82 @@
1
+ import { FlexbeAuth } from './auth';
2
+ export class ApiClient {
3
+ constructor(config) {
4
+ this.config = config;
5
+ this.auth = new FlexbeAuth(config);
6
+ }
7
+ replaceSiteId(url) {
8
+ if (!this.config.siteId) {
9
+ return url;
10
+ }
11
+ return url.replace(/:siteId:/g, this.config.siteId);
12
+ }
13
+ buildUrl(path, params) {
14
+ const processedPath = this.replaceSiteId(path);
15
+ const searchParams = new URLSearchParams();
16
+ if (params) {
17
+ Object.entries(params).forEach(([key, value]) => {
18
+ if (value !== undefined && value !== null) {
19
+ searchParams.append(key, String(value));
20
+ }
21
+ });
22
+ }
23
+ return `${processedPath}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
24
+ }
25
+ async request(config) {
26
+ try {
27
+ await this.auth.ensureInitialized();
28
+ const controller = new AbortController();
29
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
30
+ const url = this.buildUrl(config.url, config.params);
31
+ const headers = {
32
+ ...(await this.auth.getAuthHeaders()),
33
+ ...config.headers,
34
+ };
35
+ const response = await fetch(this.config.baseUrl + url, {
36
+ ...config,
37
+ headers,
38
+ signal: controller.signal,
39
+ });
40
+ clearTimeout(timeoutId);
41
+ if (!response.ok) {
42
+ const defaultError = { message: response.statusText };
43
+ const errorData = await response.json().catch(() => defaultError);
44
+ const error = {
45
+ message: errorData.message || response.statusText,
46
+ code: errorData.code,
47
+ status: response.status,
48
+ details: errorData.details,
49
+ };
50
+ throw error;
51
+ }
52
+ const data = await response.json();
53
+ return {
54
+ data,
55
+ status: response.status,
56
+ statusText: response.statusText,
57
+ };
58
+ }
59
+ catch (error) {
60
+ if (error instanceof Error && error.name === 'AbortError') {
61
+ const timeoutError = {
62
+ message: 'Request timeout',
63
+ status: 408,
64
+ };
65
+ throw timeoutError;
66
+ }
67
+ throw error;
68
+ }
69
+ }
70
+ get(url, config) {
71
+ return this.request({ ...config, method: 'GET', url });
72
+ }
73
+ post(url, data, config) {
74
+ return this.request({ ...config, method: 'POST', url, body: JSON.stringify(data) });
75
+ }
76
+ put(url, data, config) {
77
+ return this.request({ ...config, method: 'PUT', url, body: JSON.stringify(data) });
78
+ }
79
+ delete(url, config) {
80
+ return this.request({ ...config, method: 'DELETE', url });
81
+ }
82
+ }
@@ -0,0 +1,59 @@
1
+ import { FlexbeAuthType } from '../types';
2
+ import { TokenManager } from './token-manager';
3
+ export class FlexbeAuth {
4
+ constructor(config) {
5
+ this.initialized = false;
6
+ this.initializationPromise = null;
7
+ this.config = config;
8
+ this.tokenManager = TokenManager.getInstance();
9
+ if (this.config.authType === FlexbeAuthType.BEARER) {
10
+ // Start initialization but don't wait for it
11
+ this.initializationPromise = this.initialize();
12
+ }
13
+ else {
14
+ this.initialized = true;
15
+ }
16
+ }
17
+ async initialize() {
18
+ try {
19
+ const token = await this.tokenManager.getToken();
20
+ this.initialized = !!token;
21
+ }
22
+ catch (error) {
23
+ console.error('Failed to initialize auth:', error);
24
+ this.initialized = false;
25
+ }
26
+ finally {
27
+ this.initializationPromise = null;
28
+ }
29
+ }
30
+ async ensureInitialized() {
31
+ if (this.config.authType !== FlexbeAuthType.BEARER || this.initialized) {
32
+ return;
33
+ }
34
+ // If initialization is in progress, wait for it
35
+ if (this.initializationPromise) {
36
+ await this.initializationPromise;
37
+ return;
38
+ }
39
+ // If not initialized and no initialization in progress, start one
40
+ await this.initialize();
41
+ }
42
+ async getAuthHeaders() {
43
+ await this.ensureInitialized();
44
+ const headers = {
45
+ 'Content-Type': 'application/json',
46
+ };
47
+ if (this.config.authType === FlexbeAuthType.API_KEY) {
48
+ headers['x-api-key'] = this.config.apiKey;
49
+ }
50
+ else if (this.config.authType === FlexbeAuthType.BEARER) {
51
+ const token = await this.tokenManager.getToken();
52
+ if (!token) {
53
+ throw new Error('No valid bearer token available');
54
+ }
55
+ headers['Authorization'] = `Bearer ${token}`;
56
+ }
57
+ return headers;
58
+ }
59
+ }
@@ -1,4 +1,6 @@
1
+ import { FlexbeAuthType } from '../types';
1
2
  import { Pages } from './pages';
3
+ import { ApiClient } from './api-client';
2
4
  export class FlexbeClient {
3
5
  constructor(config) {
4
6
  const getEnvVar = (key) => {
@@ -12,95 +14,12 @@ export class FlexbeClient {
12
14
  timeout: config?.timeout || 30000,
13
15
  apiKey: config?.apiKey || getEnvVar('FLEXBE_API_KEY') || '',
14
16
  siteId: config?.siteId || getEnvVar('FLEXBE_SITE_ID'),
17
+ authType: config?.authType || FlexbeAuthType.API_KEY,
15
18
  };
16
- if (!this.config.apiKey) {
17
- throw new Error('API key is required. Please provide it either through config or FLEXBE_API_KEY environment variable.');
19
+ if (this.config.authType === 'apiKey' && !this.config.apiKey) {
20
+ throw new Error('API key is required when using apiKey authentication. Please provide it either through config or FLEXBE_API_KEY environment variable.');
18
21
  }
19
- this.pages = new Pages(this);
20
- }
21
- buildUrl(path, params) {
22
- const searchParams = new URLSearchParams();
23
- if (params) {
24
- Object.entries(params).forEach(([key, value]) => {
25
- if (value !== undefined && value !== null) {
26
- searchParams.append(key, String(value));
27
- }
28
- });
29
- }
30
- return `${path}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
31
- }
32
- async request(config) {
33
- try {
34
- const controller = new AbortController();
35
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
36
- const url = this.buildUrl(config.url, config.params);
37
- const response = await fetch(this.config.baseUrl + url, {
38
- ...config,
39
- headers: {
40
- 'Authorization': `Bearer ${this.config.apiKey}`,
41
- 'Content-Type': 'application/json',
42
- ...config.headers,
43
- },
44
- signal: controller.signal,
45
- });
46
- clearTimeout(timeoutId);
47
- if (!response.ok) {
48
- const defaultError = { message: response.statusText };
49
- const errorData = await response.json().catch(() => defaultError);
50
- const error = {
51
- message: errorData.message || response.statusText,
52
- code: errorData.code,
53
- status: response.status,
54
- details: errorData.details,
55
- };
56
- throw error;
57
- }
58
- const data = await response.json();
59
- return {
60
- data,
61
- status: response.status,
62
- statusText: response.statusText,
63
- };
64
- }
65
- catch (error) {
66
- if (error instanceof Error && error.name === 'AbortError') {
67
- const timeoutError = {
68
- message: 'Request timeout',
69
- status: 408,
70
- };
71
- throw timeoutError;
72
- }
73
- throw error;
74
- }
75
- }
76
- get(url, config) {
77
- return this.request({ ...config, method: 'GET', url });
78
- }
79
- post(url, data, config) {
80
- return this.request({ ...config, method: 'POST', url, body: JSON.stringify(data) });
81
- }
82
- put(url, data, config) {
83
- return this.request({ ...config, method: 'PUT', url, body: JSON.stringify(data) });
84
- }
85
- delete(url, config) {
86
- return this.request({ ...config, method: 'DELETE', url });
87
- }
88
- getSiteUrl(path) {
89
- if (!this.config.siteId) {
90
- return path;
91
- }
92
- return `/sites/${this.config.siteId}${path}`;
93
- }
94
- sitesGet(path, config) {
95
- return this.get(this.getSiteUrl(path), config);
96
- }
97
- sitesPost(path, data, config) {
98
- return this.post(this.getSiteUrl(path), data, config);
99
- }
100
- sitesPut(path, data, config) {
101
- return this.put(this.getSiteUrl(path), data, config);
102
- }
103
- sitesDelete(path, config) {
104
- return this.delete(this.getSiteUrl(path), config);
22
+ this.api = new ApiClient(this.config);
23
+ this.pages = new Pages(this.api);
105
24
  }
106
25
  }