webflow-api 1.2.2 → 1.3.1
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 +50 -1
- package/dist/api/collection.d.ts +1 -1
- package/dist/api/item.d.ts +4 -4
- package/dist/api/item.js +1 -1
- package/dist/api/meta.d.ts +2 -2
- package/dist/api/oauth.d.ts +3 -1
- package/dist/api/oauth.js +6 -1
- package/dist/core/error.js +1 -1
- package/dist/core/webflow.d.ts +7 -3
- package/dist/core/webflow.js +78 -5
- package/package.json +2 -1
- package/src/api/collection.ts +1 -1
- package/src/api/item.ts +4 -4
- package/src/api/meta.ts +2 -2
- package/src/api/oauth.ts +8 -2
- package/src/core/error.ts +1 -1
- package/src/core/webflow.ts +111 -4
- package/yarn.lock +2281 -2271
package/README.md
CHANGED
|
@@ -38,6 +38,41 @@ const webflow = new Webflow({
|
|
|
38
38
|
});
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## Transitioning to API v2
|
|
42
|
+
|
|
43
|
+
We're actively working on a new version of the SDK that will fully support API v2. In the meantime, to make use of API v2 with our SDK, there are some important changes you need to be aware of:
|
|
44
|
+
|
|
45
|
+
### Setting Up For API v2
|
|
46
|
+
|
|
47
|
+
When initializing your client, it's crucial to set the `beta` flag to true in the client options. This ensures you're targeting the API v2 endpoints.
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
const webflow = new Webflow({ beta: true, ...otherOptions });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Please note, when the beta flag is set, several built-in methods will not be available. These methods include, but are not limited to, info, authenticatedUser, sites, site, etc. Attempting to use these will throw an error.
|
|
54
|
+
|
|
55
|
+
### Calling API v2 Endpoints
|
|
56
|
+
|
|
57
|
+
To interact with API v2, you'll need to move away from using built-in methods, and instead use the provided HTTP methods directly.
|
|
58
|
+
|
|
59
|
+
For instance, where you previously used `sites()`:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
// get the first site
|
|
63
|
+
const [site] = await webflow.sites();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For API v2, you will need to use direct HTTP methods:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
// get the first site
|
|
70
|
+
const sites = await webflow.get("/sites");
|
|
71
|
+
const site = sites[0];
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
We understand that this is a shift in how you interact with the SDK, but rest assured, our upcoming SDK version will streamline this process and offer a more integrated experience with API v2.
|
|
75
|
+
|
|
41
76
|
## Basic Usage
|
|
42
77
|
|
|
43
78
|
### Chaining Calls
|
|
@@ -131,6 +166,20 @@ const url = webflow.authorizeUrl({
|
|
|
131
166
|
res.redirect(url);
|
|
132
167
|
```
|
|
133
168
|
|
|
169
|
+
### Using the scopes Parameter with v2 API
|
|
170
|
+
|
|
171
|
+
The v2 API introduces the concept of 'scopes', providing more control over app permissions. Instead of using the scope parameter as a single string, you can define multiple permissions using the scopes array:
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const url = webflow.authorizeUrl({
|
|
175
|
+
client_id: "[CLIENT ID]",
|
|
176
|
+
redirect_uri: "https://my.server.com/oauth/callback",
|
|
177
|
+
scopes: ["read:sites", "write:items", "read:users"],
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
For more information and a detailed list of available scopes, refer to our Scopes Guide.
|
|
182
|
+
|
|
134
183
|
### Access Token
|
|
135
184
|
|
|
136
185
|
Once a user has authorized their Webflow resource(s), Webflow will redirect back to your server with a `code`. Use this to get an access token.
|
|
@@ -176,7 +225,7 @@ Get all sites available or lookup by site id.
|
|
|
176
225
|
const sites = await webflow.sites();
|
|
177
226
|
|
|
178
227
|
// Get a single site
|
|
179
|
-
const site = await webflow.
|
|
228
|
+
const site = await webflow.site({ siteId: "[SITE ID]" });
|
|
180
229
|
```
|
|
181
230
|
|
|
182
231
|
### Collections
|
package/dist/api/collection.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare type CollectionField = {
|
|
|
12
12
|
name: string;
|
|
13
13
|
required: boolean;
|
|
14
14
|
editable: boolean;
|
|
15
|
-
validations?: Record<string,
|
|
15
|
+
validations?: Record<string, any>;
|
|
16
16
|
};
|
|
17
17
|
/**************************************************************
|
|
18
18
|
* Interfaces
|
package/dist/api/item.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface IDeletedItems {
|
|
|
31
31
|
/**************************************************************
|
|
32
32
|
* Types
|
|
33
33
|
**************************************************************/
|
|
34
|
-
export declare type
|
|
34
|
+
export declare type PaginatedItems = PaginatedData & {
|
|
35
35
|
items: IItem[];
|
|
36
36
|
};
|
|
37
37
|
/**************************************************************
|
|
@@ -64,7 +64,7 @@ export declare class Item extends WebflowRecord<IItem> implements IItem {
|
|
|
64
64
|
static getOne({ collectionId, itemId }: {
|
|
65
65
|
collectionId: string;
|
|
66
66
|
itemId: string;
|
|
67
|
-
}, client: AxiosInstance): Promise<import("axios").AxiosResponse<
|
|
67
|
+
}, client: AxiosInstance): Promise<import("axios").AxiosResponse<PaginatedItems, any>>;
|
|
68
68
|
/**
|
|
69
69
|
* Get a list of Items
|
|
70
70
|
* @param params The params for the request
|
|
@@ -78,7 +78,7 @@ export declare class Item extends WebflowRecord<IItem> implements IItem {
|
|
|
78
78
|
collectionId: string;
|
|
79
79
|
limit?: number;
|
|
80
80
|
offset?: number;
|
|
81
|
-
}, client: AxiosInstance): Promise<import("axios").AxiosResponse<
|
|
81
|
+
}, client: AxiosInstance): Promise<import("axios").AxiosResponse<PaginatedItems, any>>;
|
|
82
82
|
/**
|
|
83
83
|
* Create a new Item
|
|
84
84
|
* @param params The params for the request
|
|
@@ -132,7 +132,7 @@ export declare class Item extends WebflowRecord<IItem> implements IItem {
|
|
|
132
132
|
collectionId: string;
|
|
133
133
|
}, client: AxiosInstance): Promise<import("axios").AxiosResponse<IItemDelete, any>>;
|
|
134
134
|
/**
|
|
135
|
-
*
|
|
135
|
+
* Unpublish a list of Items
|
|
136
136
|
* @param params The params for the request
|
|
137
137
|
* @param params.collectionId The Collection ID
|
|
138
138
|
* @param params.live Unpublish from the live site
|
package/dist/api/item.js
CHANGED
|
@@ -93,7 +93,7 @@ class Item extends core_1.WebflowRecord {
|
|
|
93
93
|
return client.delete(path);
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
96
|
+
* Unpublish a list of Items
|
|
97
97
|
* @param params The params for the request
|
|
98
98
|
* @param params.collectionId The Collection ID
|
|
99
99
|
* @param params.live Unpublish from the live site
|
package/dist/api/meta.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface IAuthenticatedUser {
|
|
|
21
21
|
_id: string;
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
export interface
|
|
24
|
+
export interface IAuthenticationInfo {
|
|
25
25
|
application: InfoApplication;
|
|
26
26
|
workspaces: string[];
|
|
27
27
|
rateLimit: number;
|
|
@@ -43,7 +43,7 @@ export declare class Meta {
|
|
|
43
43
|
* @param client The Axios client instance
|
|
44
44
|
* @returns The authentication info
|
|
45
45
|
*/
|
|
46
|
-
static info(client: AxiosInstance): Promise<import("axios").AxiosResponse<
|
|
46
|
+
static info(client: AxiosInstance): Promise<import("axios").AxiosResponse<IAuthenticationInfo, any>>;
|
|
47
47
|
/**
|
|
48
48
|
* Get the authenticated user
|
|
49
49
|
* @param client The Axios client instance
|
package/dist/api/oauth.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { AxiosInstance } from "axios";
|
|
2
|
+
import { SupportedScope } from "../core";
|
|
2
3
|
/**************************************************************
|
|
3
4
|
* Interfaces
|
|
4
5
|
**************************************************************/
|
|
5
6
|
export interface IAuthorizeUrlParams {
|
|
6
7
|
state?: string;
|
|
7
8
|
scope?: string;
|
|
9
|
+
scopes?: SupportedScope[];
|
|
8
10
|
client_id: string;
|
|
9
11
|
redirect_uri?: string;
|
|
10
12
|
response_type?: string;
|
|
@@ -43,7 +45,7 @@ export declare class OAuth {
|
|
|
43
45
|
* @param client The Axios client instance
|
|
44
46
|
* @returns The URL to authorize a user
|
|
45
47
|
*/
|
|
46
|
-
static authorizeUrl({ response_type, redirect_uri, client_id, state, scope }: IAuthorizeUrlParams, client: AxiosInstance): string;
|
|
48
|
+
static authorizeUrl({ response_type, redirect_uri, client_id, state, scope, scopes }: IAuthorizeUrlParams, client: AxiosInstance): string;
|
|
47
49
|
/**
|
|
48
50
|
* Get an access token
|
|
49
51
|
* @param params The params for the request
|
package/dist/api/oauth.js
CHANGED
|
@@ -17,8 +17,11 @@ class OAuth {
|
|
|
17
17
|
* @param client The Axios client instance
|
|
18
18
|
* @returns The URL to authorize a user
|
|
19
19
|
*/
|
|
20
|
-
static authorizeUrl({ response_type = "code", redirect_uri, client_id, state, scope }, client) {
|
|
20
|
+
static authorizeUrl({ response_type = "code", redirect_uri, client_id, state, scope, scopes }, client) {
|
|
21
21
|
(0, core_1.requireArgs)({ client_id });
|
|
22
|
+
if (scope && scopes) {
|
|
23
|
+
throw new Error("Please provide either 'scope' or 'scopes', but not both.");
|
|
24
|
+
}
|
|
22
25
|
const params = { response_type, client_id };
|
|
23
26
|
if (redirect_uri)
|
|
24
27
|
params["redirect_uri"] = redirect_uri;
|
|
@@ -26,6 +29,8 @@ class OAuth {
|
|
|
26
29
|
params["state"] = state;
|
|
27
30
|
if (scope)
|
|
28
31
|
params["scope"] = scope;
|
|
32
|
+
if (scopes && scopes.length > 0)
|
|
33
|
+
params["scope"] = scopes.join("+");
|
|
29
34
|
const url = "/oauth/authorize";
|
|
30
35
|
const baseURL = client.defaults.baseURL.replace("api.", "");
|
|
31
36
|
return client.getUri({ baseURL, url, method: "GET", params });
|
package/dist/core/error.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ErrorInterceptor = exports.requireArgs = exports.ArgumentError = exports.RequestError = void 0;
|
|
4
4
|
class RequestError extends Error {
|
|
5
5
|
constructor(error) {
|
|
6
|
-
super(error.err ? error.err : "Unknown error
|
|
6
|
+
super(error.err ? error.err : "Unknown error occurred");
|
|
7
7
|
Object.assign(this, error);
|
|
8
8
|
}
|
|
9
9
|
}
|
package/dist/core/webflow.d.ts
CHANGED
|
@@ -8,7 +8,10 @@ export interface Options {
|
|
|
8
8
|
token?: string;
|
|
9
9
|
version?: string;
|
|
10
10
|
headers?: Record<string, string>;
|
|
11
|
+
beta?: boolean;
|
|
11
12
|
}
|
|
13
|
+
export declare const SCOPES_ARRAY: readonly ["assets:read", "assets:write", "authorized_user:read", "cms:read", "cms:write", "custom_code:read", "custom_code:write", "forms:read", "forms:write", "pages:read", "pages:write", "sites:read", "sites:write", "users:read", "users:write", "ecommerce:read", "ecommerce:write"];
|
|
14
|
+
export declare type SupportedScope = typeof SCOPES_ARRAY[number];
|
|
12
15
|
/**************************************************************
|
|
13
16
|
* Class
|
|
14
17
|
**************************************************************/
|
|
@@ -16,6 +19,7 @@ export declare class Webflow {
|
|
|
16
19
|
options: Options;
|
|
17
20
|
private client;
|
|
18
21
|
constructor(options?: Options);
|
|
22
|
+
private removeNonBetaMethods;
|
|
19
23
|
set token(value: string);
|
|
20
24
|
clearToken(): void;
|
|
21
25
|
get config(): AxiosRequestConfig<any>;
|
|
@@ -101,7 +105,7 @@ export declare class Webflow {
|
|
|
101
105
|
* Get the current authorization information
|
|
102
106
|
* @returns The authorization information
|
|
103
107
|
*/
|
|
104
|
-
info(): Promise<import("../api").
|
|
108
|
+
info(): Promise<import("../api").IAuthenticationInfo>;
|
|
105
109
|
/**
|
|
106
110
|
* Get the current authenticated user
|
|
107
111
|
* @returns The current authenticated user
|
|
@@ -236,7 +240,7 @@ export declare class Webflow {
|
|
|
236
240
|
collectionId: string;
|
|
237
241
|
}): Promise<import("../api").IItemDelete>;
|
|
238
242
|
/**
|
|
239
|
-
*
|
|
243
|
+
* Unpublish a Collection Item
|
|
240
244
|
* @param params The Item information
|
|
241
245
|
* @param params.collectionId The Collection ID
|
|
242
246
|
* @param params.itemId The Item ID
|
|
@@ -374,7 +378,7 @@ export declare class Webflow {
|
|
|
374
378
|
* @param params.siteId The Site Id
|
|
375
379
|
* @param params.url The Url the Webhook should call on events
|
|
376
380
|
* @param params.triggerType The type of event that should trigger the Webhook
|
|
377
|
-
* @param params.filter The filter to apply to the Webhook (
|
|
381
|
+
* @param params.filter The filter to apply to the Webhook (form_submission only)
|
|
378
382
|
* @returns The created webhook
|
|
379
383
|
*/
|
|
380
384
|
createWebhook({ url, siteId, triggerType, filter, }: {
|
package/dist/core/webflow.js
CHANGED
|
@@ -3,12 +3,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Webflow = exports.USER_AGENT = exports.DEFAULT_HOST = void 0;
|
|
6
|
+
exports.Webflow = exports.SCOPES_ARRAY = exports.USER_AGENT = exports.DEFAULT_HOST = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const core_1 = require("../core");
|
|
9
9
|
const api_1 = require("../api");
|
|
10
10
|
exports.DEFAULT_HOST = "webflow.com";
|
|
11
11
|
exports.USER_AGENT = "Webflow Javascript SDK / 1.0";
|
|
12
|
+
exports.SCOPES_ARRAY = [
|
|
13
|
+
"assets:read",
|
|
14
|
+
"assets:write",
|
|
15
|
+
"authorized_user:read",
|
|
16
|
+
"cms:read",
|
|
17
|
+
"cms:write",
|
|
18
|
+
"custom_code:read",
|
|
19
|
+
"custom_code:write",
|
|
20
|
+
"forms:read",
|
|
21
|
+
"forms:write",
|
|
22
|
+
"pages:read",
|
|
23
|
+
"pages:write",
|
|
24
|
+
"sites:read",
|
|
25
|
+
"sites:write",
|
|
26
|
+
"users:read",
|
|
27
|
+
"users:write",
|
|
28
|
+
"ecommerce:read",
|
|
29
|
+
"ecommerce:write",
|
|
30
|
+
];
|
|
12
31
|
/**************************************************************
|
|
13
32
|
* Class
|
|
14
33
|
**************************************************************/
|
|
@@ -17,6 +36,38 @@ class Webflow {
|
|
|
17
36
|
this.options = options;
|
|
18
37
|
this.client = axios_1.default.create(this.config);
|
|
19
38
|
this.client.interceptors.response.use(core_1.ErrorInterceptor);
|
|
39
|
+
if (this.options.beta) {
|
|
40
|
+
this.removeNonBetaMethods();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
removeNonBetaMethods() {
|
|
44
|
+
const methodsToRemove = [
|
|
45
|
+
"info",
|
|
46
|
+
"authenticatedUser",
|
|
47
|
+
"sites",
|
|
48
|
+
"site",
|
|
49
|
+
"publishSite",
|
|
50
|
+
"domains",
|
|
51
|
+
"collections",
|
|
52
|
+
"collection",
|
|
53
|
+
"items",
|
|
54
|
+
"item",
|
|
55
|
+
"createItem",
|
|
56
|
+
"updateItem",
|
|
57
|
+
"patchItem",
|
|
58
|
+
"removeItem",
|
|
59
|
+
"deleteItems",
|
|
60
|
+
"publishItems",
|
|
61
|
+
];
|
|
62
|
+
methodsToRemove.forEach((method) => {
|
|
63
|
+
Object.defineProperty(this, method, {
|
|
64
|
+
value: function () {
|
|
65
|
+
throw new Error(`The method '${method}()' is not available in beta mode. Please disable the beta option to use this method.`);
|
|
66
|
+
},
|
|
67
|
+
enumerable: false,
|
|
68
|
+
configurable: true,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
20
71
|
}
|
|
21
72
|
// Set the Authentication token
|
|
22
73
|
set token(value) {
|
|
@@ -28,9 +79,10 @@ class Webflow {
|
|
|
28
79
|
}
|
|
29
80
|
// The Axios configuration
|
|
30
81
|
get config() {
|
|
31
|
-
const { host = exports.DEFAULT_HOST, token, version, headers } = this.options;
|
|
82
|
+
const { host = exports.DEFAULT_HOST, token, version, headers, beta = false } = this.options;
|
|
83
|
+
const effectiveHost = beta ? "webflow.com/beta" : host;
|
|
32
84
|
const config = {
|
|
33
|
-
baseURL: `https://api.${
|
|
85
|
+
baseURL: `https://api.${effectiveHost}/`,
|
|
34
86
|
headers: {
|
|
35
87
|
"Content-Type": "application/json",
|
|
36
88
|
"User-Agent": exports.USER_AGENT,
|
|
@@ -43,6 +95,27 @@ class Webflow {
|
|
|
43
95
|
// Add the Authorization header if a token is set
|
|
44
96
|
if (token)
|
|
45
97
|
config.headers.Authorization = `Bearer ${token}`;
|
|
98
|
+
config.paramsSerializer = {
|
|
99
|
+
serialize: (params) => {
|
|
100
|
+
if (typeof params !== "object" || params === null) {
|
|
101
|
+
return "";
|
|
102
|
+
}
|
|
103
|
+
const parts = [];
|
|
104
|
+
for (const key in params) {
|
|
105
|
+
const value = params[key];
|
|
106
|
+
if (value === undefined)
|
|
107
|
+
continue;
|
|
108
|
+
const safeValue = typeof value === "string" || typeof value === "number" ? value : String(value);
|
|
109
|
+
if (key === "scope") {
|
|
110
|
+
parts.push(`${key}=${safeValue}`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
parts.push(`${key}=${encodeURIComponent(safeValue)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return parts.join("&");
|
|
117
|
+
},
|
|
118
|
+
};
|
|
46
119
|
return config;
|
|
47
120
|
}
|
|
48
121
|
/**************************************************************
|
|
@@ -296,7 +369,7 @@ class Webflow {
|
|
|
296
369
|
return res.data;
|
|
297
370
|
}
|
|
298
371
|
/**
|
|
299
|
-
*
|
|
372
|
+
* Unpublish a Collection Item
|
|
300
373
|
* @param params The Item information
|
|
301
374
|
* @param params.collectionId The Collection ID
|
|
302
375
|
* @param params.itemId The Item ID
|
|
@@ -433,7 +506,7 @@ class Webflow {
|
|
|
433
506
|
* @param params.siteId The Site Id
|
|
434
507
|
* @param params.url The Url the Webhook should call on events
|
|
435
508
|
* @param params.triggerType The type of event that should trigger the Webhook
|
|
436
|
-
* @param params.filter The filter to apply to the Webhook (
|
|
509
|
+
* @param params.filter The filter to apply to the Webhook (form_submission only)
|
|
437
510
|
* @returns The created webhook
|
|
438
511
|
*/
|
|
439
512
|
async createWebhook({ url, siteId, triggerType, filter, }) {
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webflow-api",
|
|
3
3
|
"description": "Webflow's official Node.js SDK for Data APIs",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.1",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"contributors": [
|
|
8
|
+
"Rodney Urquhart (https://github.com/rodneyu215)",
|
|
8
9
|
"John Agan (https://github.com/johnagan)"
|
|
9
10
|
],
|
|
10
11
|
"repository": {
|
package/src/api/collection.ts
CHANGED
|
@@ -32,7 +32,7 @@ export type CollectionField = {
|
|
|
32
32
|
required: boolean;
|
|
33
33
|
editable: boolean;
|
|
34
34
|
// TODO: add a better type
|
|
35
|
-
validations?: Record<string,
|
|
35
|
+
validations?: Record<string, any>;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/**************************************************************
|
package/src/api/item.ts
CHANGED
|
@@ -36,7 +36,7 @@ export interface IDeletedItems {
|
|
|
36
36
|
/**************************************************************
|
|
37
37
|
* Types
|
|
38
38
|
**************************************************************/
|
|
39
|
-
export type
|
|
39
|
+
export type PaginatedItems = PaginatedData & {
|
|
40
40
|
items: IItem[];
|
|
41
41
|
};
|
|
42
42
|
|
|
@@ -77,7 +77,7 @@ export class Item extends WebflowRecord<IItem> implements IItem {
|
|
|
77
77
|
requireArgs({ collectionId, itemId });
|
|
78
78
|
const path = `/collections/${collectionId}/items/${itemId}`;
|
|
79
79
|
// The API returns a paginated list with one record :(
|
|
80
|
-
return client.get<
|
|
80
|
+
return client.get<PaginatedItems>(path);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
@@ -96,7 +96,7 @@ export class Item extends WebflowRecord<IItem> implements IItem {
|
|
|
96
96
|
requireArgs({ collectionId });
|
|
97
97
|
const params = { limit, offset };
|
|
98
98
|
const path = `/collections/${collectionId}/items`;
|
|
99
|
-
return client.get<
|
|
99
|
+
return client.get<PaginatedItems>(path, { params });
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
@@ -192,7 +192,7 @@ export class Item extends WebflowRecord<IItem> implements IItem {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
/**
|
|
195
|
-
*
|
|
195
|
+
* Unpublish a list of Items
|
|
196
196
|
* @param params The params for the request
|
|
197
197
|
* @param params.collectionId The Collection ID
|
|
198
198
|
* @param params.live Unpublish from the live site
|
package/src/api/meta.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface IAuthenticatedUser {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export interface
|
|
27
|
+
export interface IAuthenticationInfo {
|
|
28
28
|
application: InfoApplication;
|
|
29
29
|
workspaces: string[];
|
|
30
30
|
rateLimit: number;
|
|
@@ -48,7 +48,7 @@ export class Meta {
|
|
|
48
48
|
* @returns The authentication info
|
|
49
49
|
*/
|
|
50
50
|
static info(client: AxiosInstance) {
|
|
51
|
-
return client.get<
|
|
51
|
+
return client.get<IAuthenticationInfo>("/info");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/**
|
package/src/api/oauth.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AxiosInstance } from "axios";
|
|
2
|
-
import { requireArgs } from "../core";
|
|
2
|
+
import { requireArgs, SupportedScope } from "../core";
|
|
3
3
|
|
|
4
4
|
/**************************************************************
|
|
5
5
|
* Interfaces
|
|
@@ -7,6 +7,7 @@ import { requireArgs } from "../core";
|
|
|
7
7
|
export interface IAuthorizeUrlParams {
|
|
8
8
|
state?: string;
|
|
9
9
|
scope?: string;
|
|
10
|
+
scopes?: SupportedScope[];
|
|
10
11
|
client_id: string;
|
|
11
12
|
redirect_uri?: string;
|
|
12
13
|
response_type?: string;
|
|
@@ -52,15 +53,20 @@ export class OAuth {
|
|
|
52
53
|
* @returns The URL to authorize a user
|
|
53
54
|
*/
|
|
54
55
|
static authorizeUrl(
|
|
55
|
-
{ response_type = "code", redirect_uri, client_id, state, scope }: IAuthorizeUrlParams,
|
|
56
|
+
{ response_type = "code", redirect_uri, client_id, state, scope, scopes }: IAuthorizeUrlParams,
|
|
56
57
|
client: AxiosInstance,
|
|
57
58
|
) {
|
|
58
59
|
requireArgs({ client_id });
|
|
59
60
|
|
|
61
|
+
if (scope && scopes) {
|
|
62
|
+
throw new Error("Please provide either 'scope' or 'scopes', but not both.");
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
const params = { response_type, client_id };
|
|
61
66
|
if (redirect_uri) params["redirect_uri"] = redirect_uri;
|
|
62
67
|
if (state) params["state"] = state;
|
|
63
68
|
if (scope) params["scope"] = scope;
|
|
69
|
+
if (scopes && scopes.length > 0) params["scope"] = scopes.join("+");
|
|
64
70
|
|
|
65
71
|
const url = "/oauth/authorize";
|
|
66
72
|
const baseURL = client.defaults.baseURL.replace("api.", "");
|
package/src/core/error.ts
CHANGED
|
@@ -16,7 +16,7 @@ export class RequestError extends Error implements IRequestError {
|
|
|
16
16
|
err: string;
|
|
17
17
|
|
|
18
18
|
constructor(error: IRequestError) {
|
|
19
|
-
super(error.err ? error.err : "Unknown error
|
|
19
|
+
super(error.err ? error.err : "Unknown error occurred");
|
|
20
20
|
Object.assign(this, error);
|
|
21
21
|
}
|
|
22
22
|
}
|
package/src/core/webflow.ts
CHANGED
|
@@ -22,8 +22,51 @@ export interface Options {
|
|
|
22
22
|
token?: string;
|
|
23
23
|
version?: string;
|
|
24
24
|
headers?: Record<string, string>;
|
|
25
|
+
beta?: boolean;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
type MethodNames =
|
|
29
|
+
| "info"
|
|
30
|
+
| "authenticatedUser"
|
|
31
|
+
| "sites"
|
|
32
|
+
| "site"
|
|
33
|
+
| "publishSite"
|
|
34
|
+
| "domains"
|
|
35
|
+
| "collections"
|
|
36
|
+
| "collection"
|
|
37
|
+
| "items"
|
|
38
|
+
| "item"
|
|
39
|
+
| "createItem"
|
|
40
|
+
| "updateItem"
|
|
41
|
+
| "patchItem"
|
|
42
|
+
| "removeItem"
|
|
43
|
+
| "deleteItems"
|
|
44
|
+
| "publishItems";
|
|
45
|
+
|
|
46
|
+
export const SCOPES_ARRAY = [
|
|
47
|
+
"assets:read",
|
|
48
|
+
"assets:write",
|
|
49
|
+
"authorized_user:read",
|
|
50
|
+
"cms:read",
|
|
51
|
+
"cms:write",
|
|
52
|
+
"custom_code:read",
|
|
53
|
+
"custom_code:write",
|
|
54
|
+
"forms:read",
|
|
55
|
+
"forms:write",
|
|
56
|
+
"pages:read",
|
|
57
|
+
"pages:write",
|
|
58
|
+
"sites:read",
|
|
59
|
+
"sites:write",
|
|
60
|
+
"users:read",
|
|
61
|
+
"users:write",
|
|
62
|
+
"ecommerce:read",
|
|
63
|
+
"ecommerce:write",
|
|
64
|
+
] as const;
|
|
65
|
+
|
|
66
|
+
export type SupportedScope = typeof SCOPES_ARRAY[number];
|
|
67
|
+
|
|
68
|
+
type ParamValueType = string | number | boolean | null | undefined;
|
|
69
|
+
|
|
27
70
|
/**************************************************************
|
|
28
71
|
* Class
|
|
29
72
|
**************************************************************/
|
|
@@ -32,6 +75,43 @@ export class Webflow {
|
|
|
32
75
|
constructor(public options: Options = {}) {
|
|
33
76
|
this.client = axios.create(this.config);
|
|
34
77
|
this.client.interceptors.response.use(ErrorInterceptor);
|
|
78
|
+
|
|
79
|
+
if (this.options.beta) {
|
|
80
|
+
this.removeNonBetaMethods();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private removeNonBetaMethods() {
|
|
85
|
+
const methodsToRemove: MethodNames[] = [
|
|
86
|
+
"info",
|
|
87
|
+
"authenticatedUser",
|
|
88
|
+
"sites",
|
|
89
|
+
"site",
|
|
90
|
+
"publishSite",
|
|
91
|
+
"domains",
|
|
92
|
+
"collections",
|
|
93
|
+
"collection",
|
|
94
|
+
"items",
|
|
95
|
+
"item",
|
|
96
|
+
"createItem",
|
|
97
|
+
"updateItem",
|
|
98
|
+
"patchItem",
|
|
99
|
+
"removeItem",
|
|
100
|
+
"deleteItems",
|
|
101
|
+
"publishItems",
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
methodsToRemove.forEach((method) => {
|
|
105
|
+
Object.defineProperty(this, method, {
|
|
106
|
+
value: function (): never {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`The method '${method}()' is not available in beta mode. Please disable the beta option to use this method.`,
|
|
109
|
+
);
|
|
110
|
+
},
|
|
111
|
+
enumerable: false,
|
|
112
|
+
configurable: true,
|
|
113
|
+
});
|
|
114
|
+
});
|
|
35
115
|
}
|
|
36
116
|
|
|
37
117
|
// Set the Authentication token
|
|
@@ -46,10 +126,11 @@ export class Webflow {
|
|
|
46
126
|
|
|
47
127
|
// The Axios configuration
|
|
48
128
|
get config() {
|
|
49
|
-
const { host = DEFAULT_HOST, token, version, headers } = this.options;
|
|
129
|
+
const { host = DEFAULT_HOST, token, version, headers, beta = false } = this.options;
|
|
130
|
+
const effectiveHost = beta ? "webflow.com/beta" : host;
|
|
50
131
|
|
|
51
132
|
const config: AxiosRequestConfig = {
|
|
52
|
-
baseURL: `https://api.${
|
|
133
|
+
baseURL: `https://api.${effectiveHost}/`,
|
|
53
134
|
headers: {
|
|
54
135
|
"Content-Type": "application/json",
|
|
55
136
|
"User-Agent": USER_AGENT,
|
|
@@ -63,6 +144,32 @@ export class Webflow {
|
|
|
63
144
|
// Add the Authorization header if a token is set
|
|
64
145
|
if (token) config.headers.Authorization = `Bearer ${token}`;
|
|
65
146
|
|
|
147
|
+
config.paramsSerializer = {
|
|
148
|
+
serialize: (params: Record<string, ParamValueType>): string => {
|
|
149
|
+
if (typeof params !== "object" || params === null) {
|
|
150
|
+
return "";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const parts: string[] = [];
|
|
154
|
+
|
|
155
|
+
for (const key in params) {
|
|
156
|
+
const value = params[key];
|
|
157
|
+
if (value === undefined) continue;
|
|
158
|
+
|
|
159
|
+
const safeValue =
|
|
160
|
+
typeof value === "string" || typeof value === "number" ? value : String(value);
|
|
161
|
+
|
|
162
|
+
if (key === "scope") {
|
|
163
|
+
parts.push(`${key}=${safeValue}`);
|
|
164
|
+
} else {
|
|
165
|
+
parts.push(`${key}=${encodeURIComponent(safeValue)}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return parts.join("&");
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
66
173
|
return config;
|
|
67
174
|
}
|
|
68
175
|
|
|
@@ -328,7 +435,7 @@ export class Webflow {
|
|
|
328
435
|
return res.data;
|
|
329
436
|
}
|
|
330
437
|
/**
|
|
331
|
-
*
|
|
438
|
+
* Unpublish a Collection Item
|
|
332
439
|
* @param params The Item information
|
|
333
440
|
* @param params.collectionId The Collection ID
|
|
334
441
|
* @param params.itemId The Item ID
|
|
@@ -503,7 +610,7 @@ export class Webflow {
|
|
|
503
610
|
* @param params.siteId The Site Id
|
|
504
611
|
* @param params.url The Url the Webhook should call on events
|
|
505
612
|
* @param params.triggerType The type of event that should trigger the Webhook
|
|
506
|
-
* @param params.filter The filter to apply to the Webhook (
|
|
613
|
+
* @param params.filter The filter to apply to the Webhook (form_submission only)
|
|
507
614
|
* @returns The created webhook
|
|
508
615
|
*/
|
|
509
616
|
async createWebhook({
|