webflow-api 0.8.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,76 @@
1
1
  declare class Webflow {
2
- constructor(options: Webflow.WebflowOptions);
2
+ constructor(options: Webflow.Options);
3
3
 
4
4
  get<Result extends any>(
5
5
  path: string,
6
- query?: Webflow.WebflowQueryArg
6
+ query?: Webflow.QueryArg
7
7
  ): Promise<Result>;
8
8
  post<Data extends any, Result extends any>(
9
9
  path: string,
10
10
  data?: Data,
11
- query?: Webflow.WebflowQueryArg
11
+ query?: Webflow.QueryArg
12
12
  ): Promise<Result>;
13
13
  put<Data extends any, Result extends any>(
14
14
  path: string,
15
15
  data?: Data,
16
- query?: Webflow.WebflowQueryArg
16
+ query?: Webflow.QueryArg
17
17
  ): Promise<Result>;
18
18
  patch<Data extends any, Result extends any>(
19
19
  path: string,
20
20
  data?: Data,
21
- query?: Webflow.WebflowQueryArg
21
+ query?: Webflow.QueryArg
22
22
  ): Promise<Result>;
23
23
  delete<Result extends any>(
24
24
  path: string,
25
- query?: Webflow.WebflowQueryArg
25
+ query?: Webflow.QueryArg
26
26
  ): Promise<Result>;
27
27
 
28
- info(query?: Webflow.WebflowQueryArg): Promise<Webflow.WebflowApiModel.Info>;
28
+ // meta
29
+ info(): Promise<Webflow.ApiModel.Info>;
30
+ installer(): Promise<Webflow.ApiModel.Installer>;
31
+
32
+ // oauth
33
+ authorizeUrl(params: {
34
+ client_id: string;
35
+ redirect_uri?: string;
36
+ state?: string;
37
+ scope?: string;
38
+ response_type?: string;
39
+ }): string;
40
+
41
+ accessToken(params: {
42
+ client_id: string;
43
+ client_secret: string;
44
+ redirect_uri?: string;
45
+ code: string;
46
+ grant_type?: string;
47
+ }): Promise<{
48
+ token_type: string;
49
+ access_token: string;
50
+ }>;
51
+
52
+ revokeToken(params: {
53
+ client_id: string;
54
+ client_secret: string;
55
+ access_token: string;
56
+ }): Promise<{ didRevoke: boolean }>;
29
57
 
30
58
  // sites
31
-
32
- sites(
33
- query?: Webflow.WebflowQueryArg
34
- ): Promise<Webflow.WebflowApiModel.Site[]>;
59
+ sites(query?: Webflow.QueryArg): Promise<Webflow.ApiModel.Site[]>;
35
60
 
36
61
  site(
37
62
  params: {
38
63
  siteId: string;
39
64
  },
40
- query?: Webflow.WebflowQueryArg
41
- ): Promise<Webflow.WebflowApiModel.Site>;
65
+ query?: Webflow.QueryArg
66
+ ): Promise<Webflow.ApiModel.Site>;
42
67
 
43
68
  publishSite(
44
69
  data: {
45
70
  siteId: string;
46
71
  domains: string[];
47
72
  },
48
- query?: Webflow.WebflowQueryArg
73
+ query?: Webflow.QueryArg
49
74
  ): Promise<{ queued: boolean }>;
50
75
 
51
76
  // Domains
@@ -54,8 +79,8 @@ declare class Webflow {
54
79
  data: {
55
80
  siteId: string;
56
81
  },
57
- query?: Webflow.WebflowQueryArg
58
- ): Promise<Webflow.WebflowApiModel.Domain[]>;
82
+ query?: Webflow.QueryArg
83
+ ): Promise<Webflow.ApiModel.Domain[]>;
59
84
 
60
85
  // Collections
61
86
 
@@ -63,45 +88,45 @@ declare class Webflow {
63
88
  data: {
64
89
  siteId: string;
65
90
  },
66
- query?: Webflow.WebflowQueryArg
67
- ): Promise<Webflow.WebflowApiModel.Collection[]>;
91
+ query?: Webflow.QueryArg
92
+ ): Promise<Webflow.ApiModel.Collection[]>;
68
93
  collection(
69
94
  data: {
70
95
  collectionId: string;
71
96
  },
72
- query?: Webflow.WebflowQueryArg
73
- ): Promise<Webflow.WebflowApiModel.Collection>;
97
+ query?: Webflow.QueryArg
98
+ ): Promise<Webflow.ApiModel.Collection>;
74
99
 
75
100
  // Users
76
101
  users(
77
102
  data: {
78
103
  siteId: string;
79
104
  },
80
- query?: Webflow.WebflowQueryArg
81
- ): Promise<Webflow.WebflowApiModel.User[]>;
105
+ query?: Webflow.QueryArg
106
+ ): Promise<Webflow.ApiModel.User[]>;
82
107
 
83
108
  user(
84
109
  data: {
85
110
  siteId: string;
86
111
  userId: string;
87
112
  },
88
- query?: Webflow.WebflowQueryArg
89
- ): Promise<Webflow.WebflowApiModel.User>;
113
+ query?: Webflow.QueryArg
114
+ ): Promise<Webflow.ApiModel.User>;
90
115
 
91
116
  updateUser(
92
117
  data: { siteId: string; userId: string } & Record<string, any>,
93
- query?: Webflow.WebflowQueryArg
94
- ): Promise<Webflow.WebflowApiModel.User>;
118
+ query?: Webflow.QueryArg
119
+ ): Promise<Webflow.ApiModel.User>;
95
120
 
96
121
  removeUser(
97
122
  data: { siteId: string; userId: string },
98
- query?: Webflow.WebflowQueryArg
123
+ query?: Webflow.QueryArg
99
124
  ): Promise<{ deleted: number }>;
100
125
 
101
126
  inviteUser(
102
127
  data: { siteId: string; email: string },
103
- query?: Webflow.WebflowQueryArg
104
- ): Promise<Webflow.WebflowApiModel.User>;
128
+ query?: Webflow.QueryArg
129
+ ): Promise<Webflow.ApiModel.User>;
105
130
 
106
131
  // Items
107
132
 
@@ -109,61 +134,61 @@ declare class Webflow {
109
134
  data: {
110
135
  collectionId: string;
111
136
  },
112
- query?: Webflow.WebflowQueryArg
113
- ): Promise<Webflow.WebflowApiModel.ItemsResponse>;
137
+ query?: Webflow.QueryArg
138
+ ): Promise<Webflow.ApiModel.ItemsResponse>;
114
139
 
115
140
  item(
116
141
  data: {
117
142
  collectionId: string;
118
143
  itemId: string;
119
144
  },
120
- query?: Webflow.WebflowQueryArg
121
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
145
+ query?: Webflow.QueryArg
146
+ ): Promise<Webflow.ApiModel.CollectionItem>;
122
147
 
123
148
  createItem(
124
149
  // TODO: add a better data type
125
150
  data: { collectionId: string } & Record<string, any>,
126
- query?: Webflow.WebflowQueryArg
127
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
151
+ query?: Webflow.QueryArg
152
+ ): Promise<Webflow.ApiModel.CollectionItem>;
128
153
 
129
154
  updateItem(
130
155
  // TODO: add a better data type
131
156
  data: { collectionId: string; itemId: string } & Record<string, any>,
132
- query?: Webflow.WebflowQueryArg
133
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
157
+ query?: Webflow.QueryArg
158
+ ): Promise<Webflow.ApiModel.CollectionItem>;
134
159
 
135
160
  removeItem(
136
161
  data: { collectionId: string; itemId: string },
137
- query?: Webflow.WebflowQueryArg
162
+ query?: Webflow.QueryArg
138
163
  ): Promise<{ deleted: number }>;
139
164
 
140
165
  patchItem(
141
166
  // TODO: add a better data type
142
167
  data: { collectionId: string; itemId: string } & Record<string, any>,
143
- query?: Webflow.WebflowQueryArg
144
- ): Promise<Webflow.WebflowApiModel.CollectionItem>;
168
+ query?: Webflow.QueryArg
169
+ ): Promise<Webflow.ApiModel.CollectionItem>;
145
170
 
146
171
  // Webhooks
147
172
 
148
173
  webhooks(
149
174
  data: { siteId: string },
150
- query?: Webflow.WebflowQueryArg
151
- ): Promise<Webflow.WebflowApiModel.Webhook[]>;
175
+ query?: Webflow.QueryArg
176
+ ): Promise<Webflow.ApiModel.Webhook[]>;
152
177
 
153
178
  webhook(
154
179
  data: { siteId: string; webhookId: string },
155
- query?: Webflow.WebflowQueryArg
156
- ): Promise<Webflow.WebflowApiModel.Webhook>;
180
+ query?: Webflow.QueryArg
181
+ ): Promise<Webflow.ApiModel.Webhook>;
157
182
 
158
183
  createWebhook(
159
184
  // TODO: add a better data type
160
185
  data: { siteId: string } & Record<string, any>,
161
- query?: Webflow.WebflowQueryArg
162
- ): Promise<Webflow.WebflowApiModel.Webhook>;
186
+ query?: Webflow.QueryArg
187
+ ): Promise<Webflow.ApiModel.Webhook>;
163
188
 
164
189
  removeWebhook(
165
190
  data: { siteId: string; webhookId: string },
166
- query?: Webflow.WebflowQueryArg
191
+ query?: Webflow.QueryArg
167
192
  ): Promise<{ deleted: number }>;
168
193
  }
169
194
 
@@ -172,15 +197,26 @@ declare namespace Webflow {
172
197
  class WebflowError extends Error {}
173
198
 
174
199
  // helper types / namespaces
175
- type WebflowQueryArg = Record<string, any>;
200
+ type QueryArg = Record<string, any>;
176
201
 
177
- interface WebflowOptions {
202
+ interface Options {
178
203
  token: string;
179
204
  endpoint?: string;
180
205
  version?: string;
206
+ mode?: string;
207
+ headers?: { [key: string]: string };
181
208
  }
182
209
 
183
- namespace WebflowApiModel {
210
+ namespace ApiModel {
211
+ interface Installer {
212
+ user: {
213
+ _id: string;
214
+ email: string;
215
+ firstName: string;
216
+ lastName: string;
217
+ };
218
+ }
219
+
184
220
  interface InfoApplication {
185
221
  _id: string;
186
222
  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.0",
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
  }