webflow-api 0.8.1 → 1.0.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.
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.WebflowRequestError = exports.WebflowClient = void 0;
7
+ var _isomorphicFetch = _interopRequireDefault(require("isomorphic-fetch"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ const DEFAULT_HOST = "webflow.com";
10
+ const USER_AGENT = "Webflow Javascript SDK / 1.0";
11
+ class WebflowRequestError extends Error {
12
+ constructor(error) {
13
+ super(error.err ? error.err : "Unknown error occured");
14
+ Object.assign(this, error);
15
+ }
16
+ }
17
+ exports.WebflowRequestError = WebflowRequestError;
18
+ class WebflowClient {
19
+ constructor({
20
+ host,
21
+ token,
22
+ version,
23
+ headers,
24
+ mode
25
+ } = {}) {
26
+ this.host = host || DEFAULT_HOST;
27
+ this.headers = headers || {};
28
+ this.version = version;
29
+ this.token = token;
30
+ this.mode = mode;
31
+ }
32
+ getUri(path, query = {}) {
33
+ const hasQuery = Object.keys(query).length > 0;
34
+ const queryString = hasQuery ? `?${new URLSearchParams(query)}` : "";
35
+ return `https://api.${this.host}${path}${queryString}`;
36
+ }
37
+ getHeaders() {
38
+ const {
39
+ version,
40
+ token
41
+ } = this;
42
+ const headers = {
43
+ "Content-Type": "application/json",
44
+ Accept: "application/json",
45
+ "User-Agent": USER_AGENT
46
+ };
47
+
48
+ // set authorization header if token is set
49
+ if (token) headers.Authorization = `Bearer ${token}`;
50
+
51
+ // set the API version
52
+ if (version) headers["accept-version"] = version;
53
+
54
+ // merge headers with user headers;
55
+ return {
56
+ ...headers,
57
+ ...this.headers
58
+ };
59
+ }
60
+ async parseBody(res) {
61
+ const body = await res.json();
62
+
63
+ // append ratelimit meta data to response
64
+ if (res.headers) {
65
+ const limit = parseInt(res.headers.get("x-ratelimit-limit"), 10);
66
+ const remaining = parseInt(res.headers.get("x-ratelimit-remaining"), 10);
67
+ body._meta = {
68
+ rateLimit: {
69
+ limit,
70
+ remaining
71
+ }
72
+ };
73
+ }
74
+
75
+ // webflow error
76
+ if (body.err) throw new WebflowRequestError(body);
77
+ return body;
78
+ }
79
+ fetch(method, path, data, query) {
80
+ // build uri
81
+ const uri = this.getUri(path, query);
82
+
83
+ // build request options
84
+ const headers = this.getHeaders();
85
+ const opts = {
86
+ method,
87
+ headers,
88
+ mode: this.mode
89
+ };
90
+ if (data) opts.body = JSON.stringify(data);
91
+
92
+ // call fetch and wrap response
93
+ return (0, _isomorphicFetch.default)(uri, opts).then(this.parseBody.bind(this));
94
+ }
95
+
96
+ // Generic HTTP request handlers
97
+ get(path, query = {}) {
98
+ return this.fetch("GET", path, null, query);
99
+ }
100
+ post(path, data, query = {}) {
101
+ return this.fetch("POST", path, data, query);
102
+ }
103
+ put(path, data, query = {}) {
104
+ return this.fetch("PUT", path, data, query);
105
+ }
106
+ patch(path, data, query = {}) {
107
+ return this.fetch("PATCH", path, data, query);
108
+ }
109
+ delete(path, data, query = {}) {
110
+ return this.fetch("DELETE", path, data, query);
111
+ }
112
+ }
113
+ exports.WebflowClient = WebflowClient;
114
+ var _default = WebflowClient;
115
+ exports.default = _default;
package/dist/index.js CHANGED
@@ -1,4 +1,10 @@
1
1
  "use strict";
2
2
 
3
- module.exports = require("./Webflow")["default"];
4
- module.exports.WebflowError = require("./WebflowError")["default"];
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _Webflow = require("./Webflow");
8
+ var _default = _Webflow.Webflow;
9
+ exports.default = _default;
10
+ module.exports = exports.default;
package/index.d.ts CHANGED
@@ -1,51 +1,77 @@
1
1
  declare class Webflow {
2
- constructor(options: Webflow.WebflowOptions);
2
+ constructor(options: Webflow.Options);
3
+ token: string;
3
4
 
4
5
  get<Result extends any>(
5
6
  path: string,
6
- query?: Webflow.WebflowQueryArg
7
+ query?: Webflow.QueryArg
7
8
  ): Promise<Result>;
8
9
  post<Data extends any, Result extends any>(
9
10
  path: string,
10
11
  data?: Data,
11
- query?: Webflow.WebflowQueryArg
12
+ query?: Webflow.QueryArg
12
13
  ): Promise<Result>;
13
14
  put<Data extends any, Result extends any>(
14
15
  path: string,
15
16
  data?: Data,
16
- query?: Webflow.WebflowQueryArg
17
+ query?: Webflow.QueryArg
17
18
  ): Promise<Result>;
18
19
  patch<Data extends any, Result extends any>(
19
20
  path: string,
20
21
  data?: Data,
21
- query?: Webflow.WebflowQueryArg
22
+ query?: Webflow.QueryArg
22
23
  ): Promise<Result>;
23
24
  delete<Result extends any>(
24
25
  path: string,
25
- query?: Webflow.WebflowQueryArg
26
+ query?: Webflow.QueryArg
26
27
  ): Promise<Result>;
27
28
 
28
- info(query?: Webflow.WebflowQueryArg): Promise<Webflow.WebflowApiModel.Info>;
29
+ // meta
30
+ info(): Promise<Webflow.ApiModel.Info>;
31
+ installer(): Promise<Webflow.ApiModel.Installer>;
32
+
33
+ // oauth
34
+ authorizeUrl(params: {
35
+ client_id: string;
36
+ redirect_uri?: string;
37
+ state?: string;
38
+ scope?: string;
39
+ response_type?: string;
40
+ }): string;
41
+
42
+ accessToken(params: {
43
+ client_id: string;
44
+ client_secret: string;
45
+ redirect_uri?: string;
46
+ code: string;
47
+ grant_type?: string;
48
+ }): Promise<{
49
+ token_type: string;
50
+ access_token: string;
51
+ }>;
52
+
53
+ revokeToken(params: {
54
+ client_id: string;
55
+ client_secret: string;
56
+ access_token: string;
57
+ }): Promise<{ didRevoke: boolean }>;
29
58
 
30
59
  // sites
31
-
32
- sites(
33
- query?: Webflow.WebflowQueryArg
34
- ): Promise<Webflow.WebflowApiModel.Site[]>;
60
+ sites(query?: Webflow.QueryArg): Promise<Webflow.ApiModel.Site[]>;
35
61
 
36
62
  site(
37
63
  params: {
38
64
  siteId: string;
39
65
  },
40
- query?: Webflow.WebflowQueryArg
41
- ): Promise<Webflow.WebflowApiModel.Site>;
66
+ query?: Webflow.QueryArg
67
+ ): Promise<Webflow.ApiModel.Site>;
42
68
 
43
69
  publishSite(
44
70
  data: {
45
71
  siteId: string;
46
72
  domains: string[];
47
73
  },
48
- query?: Webflow.WebflowQueryArg
74
+ query?: Webflow.QueryArg
49
75
  ): Promise<{ queued: boolean }>;
50
76
 
51
77
  // Domains
@@ -54,8 +80,8 @@ declare class Webflow {
54
80
  data: {
55
81
  siteId: string;
56
82
  },
57
- query?: Webflow.WebflowQueryArg
58
- ): Promise<Webflow.WebflowApiModel.Domain[]>;
83
+ query?: Webflow.QueryArg
84
+ ): Promise<Webflow.ApiModel.Domain[]>;
59
85
 
60
86
  // Collections
61
87
 
@@ -63,45 +89,45 @@ declare class Webflow {
63
89
  data: {
64
90
  siteId: string;
65
91
  },
66
- query?: Webflow.WebflowQueryArg
67
- ): Promise<Webflow.WebflowApiModel.Collection[]>;
92
+ query?: Webflow.QueryArg
93
+ ): Promise<Webflow.ApiModel.Collection[]>;
68
94
  collection(
69
95
  data: {
70
96
  collectionId: string;
71
97
  },
72
- query?: Webflow.WebflowQueryArg
73
- ): Promise<Webflow.WebflowApiModel.Collection>;
98
+ query?: Webflow.QueryArg
99
+ ): Promise<Webflow.ApiModel.Collection>;
74
100
 
75
101
  // Users
76
102
  users(
77
103
  data: {
78
104
  siteId: string;
79
105
  },
80
- query?: Webflow.WebflowQueryArg
81
- ): Promise<Webflow.WebflowApiModel.User[]>;
106
+ query?: Webflow.QueryArg
107
+ ): Promise<Webflow.ApiModel.User[]>;
82
108
 
83
109
  user(
84
110
  data: {
85
111
  siteId: string;
86
112
  userId: string;
87
113
  },
88
- query?: Webflow.WebflowQueryArg
89
- ): Promise<Webflow.WebflowApiModel.User>;
114
+ query?: Webflow.QueryArg
115
+ ): Promise<Webflow.ApiModel.User>;
90
116
 
91
117
  updateUser(
92
118
  data: { siteId: string; userId: string } & Record<string, any>,
93
- query?: Webflow.WebflowQueryArg
94
- ): Promise<Webflow.WebflowApiModel.User>;
119
+ query?: Webflow.QueryArg
120
+ ): Promise<Webflow.ApiModel.User>;
95
121
 
96
122
  removeUser(
97
123
  data: { siteId: string; userId: string },
98
- query?: Webflow.WebflowQueryArg
124
+ query?: Webflow.QueryArg
99
125
  ): Promise<{ deleted: number }>;
100
126
 
101
127
  inviteUser(
102
128
  data: { siteId: string; email: string },
103
- query?: Webflow.WebflowQueryArg
104
- ): Promise<Webflow.WebflowApiModel.User>;
129
+ query?: Webflow.QueryArg
130
+ ): Promise<Webflow.ApiModel.User>;
105
131
 
106
132
  // Items
107
133
 
@@ -109,61 +135,61 @@ declare class Webflow {
109
135
  data: {
110
136
  collectionId: string;
111
137
  },
112
- query?: Webflow.WebflowQueryArg
113
- ): Promise<Webflow.WebflowApiModel.ItemsResponse>;
138
+ query?: Webflow.QueryArg
139
+ ): Promise<Webflow.ApiModel.ItemsResponse>;
114
140
 
115
141
  item(
116
142
  data: {
117
143
  collectionId: string;
118
144
  itemId: string;
119
145
  },
120
- query?: Webflow.WebflowQueryArg
121
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
146
+ query?: Webflow.QueryArg
147
+ ): Promise<Webflow.ApiModel.CollectionItem>;
122
148
 
123
149
  createItem(
124
150
  // TODO: add a better data type
125
151
  data: { collectionId: string } & Record<string, any>,
126
- query?: Webflow.WebflowQueryArg
127
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
152
+ query?: Webflow.QueryArg
153
+ ): Promise<Webflow.ApiModel.CollectionItem>;
128
154
 
129
155
  updateItem(
130
156
  // TODO: add a better data type
131
157
  data: { collectionId: string; itemId: string } & Record<string, any>,
132
- query?: Webflow.WebflowQueryArg
133
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
158
+ query?: Webflow.QueryArg
159
+ ): Promise<Webflow.ApiModel.CollectionItem>;
134
160
 
135
161
  removeItem(
136
162
  data: { collectionId: string; itemId: string },
137
- query?: Webflow.WebflowQueryArg
163
+ query?: Webflow.QueryArg
138
164
  ): Promise<{ deleted: number }>;
139
165
 
140
166
  patchItem(
141
167
  // TODO: add a better data type
142
168
  data: { collectionId: string; itemId: string } & Record<string, any>,
143
- query?: Webflow.WebflowQueryArg
144
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
169
+ query?: Webflow.QueryArg
170
+ ): Promise<Webflow.ApiModel.CollectionItem>;
145
171
 
146
172
  // Webhooks
147
173
 
148
174
  webhooks(
149
175
  data: { siteId: string },
150
- query?: Webflow.WebflowQueryArg
151
- ): Promise<Webflow.WebflowApiModel.Webhook[]>;
176
+ query?: Webflow.QueryArg
177
+ ): Promise<Webflow.ApiModel.Webhook[]>;
152
178
 
153
179
  webhook(
154
180
  data: { siteId: string; webhookId: string },
155
- query?: Webflow.WebflowQueryArg
156
- ): Promise<Webflow.WebflowApiModel.Webhook>;
181
+ query?: Webflow.QueryArg
182
+ ): Promise<Webflow.ApiModel.Webhook>;
157
183
 
158
184
  createWebhook(
159
185
  // TODO: add a better data type
160
186
  data: { siteId: string } & Record<string, any>,
161
- query?: Webflow.WebflowQueryArg
162
- ): Promise<Webflow.WebflowApiModel.Webhook>;
187
+ query?: Webflow.QueryArg
188
+ ): Promise<Webflow.ApiModel.Webhook>;
163
189
 
164
190
  removeWebhook(
165
191
  data: { siteId: string; webhookId: string },
166
- query?: Webflow.WebflowQueryArg
192
+ query?: Webflow.QueryArg
167
193
  ): Promise<{ deleted: number }>;
168
194
  }
169
195
 
@@ -172,15 +198,26 @@ declare namespace Webflow {
172
198
  class WebflowError extends Error {}
173
199
 
174
200
  // helper types / namespaces
175
- type WebflowQueryArg = Record<string, any>;
201
+ type QueryArg = Record<string, any>;
176
202
 
177
- interface WebflowOptions {
203
+ interface Options {
178
204
  token: string;
179
205
  endpoint?: string;
180
206
  version?: string;
207
+ mode?: string;
208
+ headers?: { [key: string]: string };
181
209
  }
182
210
 
183
- namespace WebflowApiModel {
211
+ namespace ApiModel {
212
+ interface Installer {
213
+ user: {
214
+ _id: string;
215
+ email: string;
216
+ firstName: string;
217
+ lastName: string;
218
+ };
219
+ }
220
+
184
221
  interface InfoApplication {
185
222
  _id: string;
186
223
  description: string;
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "webflow-api",
3
- "version": "0.8.1",
4
- "description": "SDK for the Webflow CMS API",
3
+ "description": "Webflow's official Node.js SDK for Data APIs",
4
+ "version": "1.0.1",
5
+ "types": "index.d.ts",
5
6
  "main": "dist/index.js",
6
- "jsnext:main": "src/index.js",
7
+ "contributors": [
8
+ "John Agan (https://github.com/johnagan)"
9
+ ],
7
10
  "repository": {
8
11
  "url": "https://github.com/webflow/js-webflow-api.git",
9
12
  "type": "git"
10
13
  },
11
14
  "license": "MIT",
12
- "types": "index.d.ts",
13
15
  "files": [
14
16
  "dist",
15
17
  "src",
@@ -18,35 +20,31 @@
18
20
  "index.d.ts"
19
21
  ],
20
22
  "scripts": {
21
- "build": "BABEL_ENV=production babel --out-dir dist src/",
22
- "lint": "eslint src",
23
- "prepublish": "npm run build",
24
- "report": "nyc report --reporter=html",
25
- "test": "nyc ava",
26
- "watch": "npm run build -- --watch",
27
- "watch:test": "npm run test -- --watch"
23
+ "compile": "BABEL_ENV=production babel --out-dir dist src/",
24
+ "build": " yarn clean && yarn compile",
25
+ "watch": "yarn build --watch",
26
+ "prepublish": "yarn build",
27
+ "clean": "rm -rf dist",
28
+ "lint": "eslint",
29
+ "test": "jest"
28
30
  },
29
31
  "devDependencies": {
30
- "@babel/cli": "^7.17.6",
31
- "@babel/core": "^7.17.8",
32
- "@babel/preset-env": "^7.16.11",
33
- "@babel/register": "^7.17.7",
34
- "ava": "^4.1.0",
32
+ "@babel/cli": "^7.19.3",
33
+ "@babel/core": "^7.19.6",
34
+ "@babel/preset-env": "^7.19.4",
35
+ "@babel/register": "^7.18.9",
36
+ "@jest/globals": "^29.2.2",
37
+ "babel-jest": "^29.2.2",
38
+ "babel-plugin-add-module-exports": "^1.0.4",
35
39
  "eslint": "^8.12.0",
36
40
  "eslint-config-airbnb-base": "^15.0.0",
37
41
  "eslint-config-prettier": "^8.5.0",
38
- "eslint-plugin-import": "^2.25.2",
39
- "nock": "^13.0.7",
40
- "nyc": "^15.1.0"
42
+ "eslint-plugin-import": "^2.26.0",
43
+ "eslint-plugin-prettier": "^4.2.1",
44
+ "jest": "^29.2.2",
45
+ "nock": "^13.0.7"
41
46
  },
42
47
  "dependencies": {
43
- "es6-error": "^4.0.0",
44
- "isomorphic-fetch": "^3.0.0",
45
- "qs": "^6.3.0"
46
- },
47
- "ava": {
48
- "require": [
49
- "@babel/register"
50
- ]
48
+ "isomorphic-fetch": "^3.0.0"
51
49
  }
52
50
  }
@@ -10,16 +10,16 @@ export default class ResponseWrapper {
10
10
  collections: this.api.collections.bind(this.api, { siteId: site._id }),
11
11
  webhooks: this.api.webhooks.bind(this.api, { siteId: site._id }),
12
12
  domains: this.api.domains.bind(this.api, { siteId: site._id }),
13
- webhook(first, ...rest) {
13
+ webhook: (first, ...rest) => {
14
14
  return this.api.webhook({ ...first, siteId: site._id }, ...rest);
15
15
  },
16
- createWebhook(first, ...rest) {
16
+ createWebhook: (first, ...rest) => {
17
17
  return this.api.createWebhook({ ...first, siteId: site._id }, ...rest);
18
18
  },
19
- removeWebhook(first, ...rest) {
19
+ removeWebhook: (first, ...rest) => {
20
20
  return this.api.removeWebhook({ ...first, siteId: site._id }, ...rest);
21
21
  },
22
- publishSite(domains) {
22
+ publishSite: (domains) => {
23
23
  return this.api.publishSite({ siteId: site._id, domains });
24
24
  },
25
25
  };
@@ -36,25 +36,25 @@ export default class ResponseWrapper {
36
36
  ...collection,
37
37
 
38
38
  items: this.api.items.bind(this.api, { collectionId: collection._id }),
39
- item(first, ...rest) {
39
+ item: (first, ...rest) => {
40
40
  return this.api.item(
41
41
  { ...first, collectionId: collection._id },
42
42
  ...rest
43
43
  );
44
44
  },
45
- createItem(first, ...rest) {
45
+ createItem: (first, ...rest) => {
46
46
  return this.api.createItem(
47
47
  { ...first, collectionId: collection._id },
48
48
  ...rest
49
49
  );
50
50
  },
51
- updateItem(first, ...rest) {
51
+ updateItem: (first, ...rest) => {
52
52
  return this.api.updateItem(
53
53
  { ...first, collectionId: collection._id },
54
54
  ...rest
55
55
  );
56
56
  },
57
- removeItem(first, ...rest) {
57
+ removeItem: (first, ...rest) => {
58
58
  return this.api.removeItem(
59
59
  { ...first, collectionId: collection._id },
60
60
  ...rest
@@ -64,43 +64,40 @@ export default class ResponseWrapper {
64
64
  }
65
65
 
66
66
  item(item, collectionId) {
67
+ const itemId = item._id;
68
+ const ids = { itemId, collectionId };
67
69
  return {
68
70
  ...item,
69
71
 
70
- update(first, ...rest) {
71
- return this.api.updateItem(
72
- { ...first, collectionId, itemId: item._id },
73
- ...rest
74
- );
72
+ update: (itemData, query) => {
73
+ return this.api.updateItem({ ...itemData, ...ids }, query);
74
+ },
75
+ remove: (query) => {
76
+ return this.api.removeItem(ids, query);
75
77
  },
76
- remove: this.api.updateItem.bind(this.api, {
77
- collectionId,
78
- itemId: item._id,
79
- }),
80
78
  };
81
79
  }
82
80
 
83
81
  user(user, siteId) {
82
+ const userId = user._id;
83
+ const ids = { userId, siteId };
84
+
84
85
  return {
85
86
  ...user,
86
-
87
- update(first, ...rest) {
88
- return this.api.updateUser({ ...first, siteId }, ...rest);
89
- },
90
- remove(first, ...rest) {
91
- return this.api.removeUser({ ...first, siteId }, ...rest);
87
+ update: (userData) => {
88
+ return this.api.updateUser({ ...ids, ...userData });
92
89
  },
90
+ remove: this.api.removeUser.bind(this.api, ids),
93
91
  };
94
92
  }
95
93
 
96
94
  webhook(webhook, siteId) {
95
+ const webhookId = webhook._id;
96
+ const ids = { webhookId, siteId };
97
+
97
98
  return {
98
99
  ...webhook,
99
-
100
- remove: this.api.removeWebhook.bind(this.api, {
101
- siteId,
102
- webhookId: webhook._id,
103
- }),
100
+ remove: this.api.removeWebhook.bind(this.api, ids),
104
101
  };
105
102
  }
106
103
  }