homey-api 1.5.29 → 1.6.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.
@@ -394,7 +394,33 @@
394
394
  "type": "string",
395
395
  "required": true
396
396
  },
397
- "provider": {
397
+ "paymentProvider": {
398
+ "type": "string",
399
+ "in": "body"
400
+ }
401
+ }
402
+ },
403
+ "createOfferCouponApple": {
404
+ "path": "/offer/coupon_apple",
405
+ "method": "post",
406
+ "parameters": {
407
+ "coupon": {
408
+ "type": "string",
409
+ "in": "body"
410
+ },
411
+ "expiresAt": {
412
+ "type": "string",
413
+ "in": "body"
414
+ },
415
+ "subscriptionType": {
416
+ "type": "string",
417
+ "in": "body"
418
+ },
419
+ "subscriptionQuantity": {
420
+ "type": "number",
421
+ "in": "body"
422
+ },
423
+ "subscriptionDuration": {
398
424
  "type": "string",
399
425
  "in": "body"
400
426
  }
@@ -417,6 +443,10 @@
417
443
  "type": "string",
418
444
  "in": "body"
419
445
  },
446
+ "campaignId": {
447
+ "type": "string",
448
+ "in": "body"
449
+ },
420
450
  "subscriptionType": {
421
451
  "type": "string",
422
452
  "in": "body"
@@ -579,7 +579,7 @@
579
579
 
580
580
  }
581
581
 
582
- export class StorageAdapterNodeJS extends StorageAdapter {
582
+ export class StorageAdapterMemory extends StorageAdapter {
583
583
 
584
584
 
585
585
 
@@ -4738,7 +4738,42 @@
4738
4738
 
4739
4739
 
4740
4740
 
4741
- provider: string,
4741
+ paymentProvider: string,
4742
+
4743
+
4744
+ },
4745
+
4746
+
4747
+
4748
+
4749
+ ):
4750
+ Promise<any>;
4751
+
4752
+ createOfferCouponApple(
4753
+
4754
+
4755
+
4756
+
4757
+ opts: {
4758
+
4759
+
4760
+ coupon: string,
4761
+
4762
+
4763
+
4764
+ expiresAt: string,
4765
+
4766
+
4767
+
4768
+ subscriptionType: string,
4769
+
4770
+
4771
+
4772
+ subscriptionQuantity: number,
4773
+
4774
+
4775
+
4776
+ subscriptionDuration: string,
4742
4777
 
4743
4778
 
4744
4779
  },
@@ -4770,6 +4805,10 @@
4770
4805
 
4771
4806
 
4772
4807
 
4808
+ campaignId: string,
4809
+
4810
+
4811
+
4773
4812
  subscriptionType: string,
4774
4813
 
4775
4814
 
@@ -5598,6 +5637,15 @@
5598
5637
 
5599
5638
 
5600
5639
 
5640
+ ):
5641
+ boolean;
5642
+
5643
+ isReactNative(
5644
+
5645
+
5646
+
5647
+
5648
+
5601
5649
  ):
5602
5650
  boolean;
5603
5651
 
@@ -5805,7 +5853,7 @@
5805
5853
 
5806
5854
  }
5807
5855
 
5808
- export class StorageAdapterNodeJS extends StorageAdapter {
5856
+ export class StorageAdapterMemory extends StorageAdapter {
5809
5857
 
5810
5858
 
5811
5859
 
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * Abstract storage adapter. To be extended by your own, or {@link AthomCloudAPI.StorageAdapterBrowser} or {@link AthomCloudAPI.StorageAdapterNodeJS}.
4
+ * Abstract storage adapter. To be extended by your own, or {@link AthomCloudAPI.StorageAdapterBrowser} or {@link AthomCloudAPI.StorageAdapterMemory}.
5
5
  * @class
6
6
  * @memberof AthomCloudAPI
7
7
  */
@@ -3,12 +3,12 @@
3
3
  const StorageAdapter = require('./StorageAdapter');
4
4
 
5
5
  /**
6
- * In-memory storage adapter for Node.js.
6
+ * In-memory storage adapter for Node.js or React Native.
7
7
  * @class
8
8
  * @extends StorageAdapter
9
9
  * @memberof AthomCloudAPI
10
10
  */
11
- class StorageAdapterNodeJS extends StorageAdapter {
11
+ class StorageAdapterMemory extends StorageAdapter {
12
12
 
13
13
  constructor() {
14
14
  super();
@@ -34,4 +34,4 @@ class StorageAdapterNodeJS extends StorageAdapter {
34
34
 
35
35
  }
36
36
 
37
- module.exports = StorageAdapterNodeJS;
37
+ module.exports = StorageAdapterMemory;
@@ -9,7 +9,7 @@ const Homey = require('./AthomCloudAPI/Homey');
9
9
  const Token = require('./AthomCloudAPI/Token');
10
10
  const StorageAdapter = require('./AthomCloudAPI/StorageAdapter');
11
11
  const StorageAdapterBrowser = require('./AthomCloudAPI/StorageAdapterBrowser');
12
- const StorageAdapterNodeJS = require('./AthomCloudAPI/StorageAdapterNodeJS');
12
+ const StorageAdapterMemory = require('./AthomCloudAPI/StorageAdapterMemory');
13
13
 
14
14
  class AthomCloudAPI extends API {
15
15
 
@@ -18,7 +18,7 @@ class AthomCloudAPI extends API {
18
18
  static Token = Token;
19
19
  static StorageAdapter = StorageAdapter;
20
20
  static StorageAdapterBrowser = StorageAdapterBrowser;
21
- static StorageAdapterNodeJS = StorageAdapterNodeJS;
21
+ static StorageAdapterMemory = StorageAdapterMemory;
22
22
 
23
23
  static SPECIFICATION = require('../assets/specifications/AthomCloudAPI.json');
24
24
  static SPECIFICATION_URL = 'https://api.athom.com/specification.json';
@@ -75,7 +75,7 @@ for(const device of Object.values(devices)) {
75
75
  @param {string} opts.redirectUrl
76
76
  @param {boolean} [opts.autoRefreshTokens=true]
77
77
  @param {AthomCloudAPI.Token} [opts.token=null]
78
- @param {AthomCloudAPI.StorageAdapter} [opts.store={@link AthomCloudAPI.StorageAdapterBrowser} or {@link AthomCloudAPI.StorageAdapterNodeJS}]`;
78
+ @param {AthomCloudAPI.StorageAdapter} [opts.store={@link AthomCloudAPI.StorageAdapterBrowser} or {@link AthomCloudAPI.StorageAdapterMemory}]`;
79
79
 
80
80
  constructor({
81
81
  clientId,
@@ -85,7 +85,7 @@ for(const device of Object.values(devices)) {
85
85
  token = null,
86
86
  store = Util.isBrowser()
87
87
  ? new StorageAdapterBrowser()
88
- : new StorageAdapterNodeJS(),
88
+ : new StorageAdapterMemory(),
89
89
  ...args
90
90
  } = {}) {
91
91
  super({ ...args });
@@ -304,10 +304,11 @@ for(const device of Object.values(devices)) {
304
304
  body.append('grant_type', 'client_credentials');
305
305
 
306
306
  const response = await Util.fetch(`${this.baseUrl}/oauth2/token`, {
307
- body,
307
+ body: body.toString(),
308
308
  method: 'post',
309
309
  headers: {
310
- Authorization: `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
310
+ 'Authorization': `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
311
+ 'Content-Type': 'application/x-www-form-urlencoded',
311
312
  },
312
313
  });
313
314
 
@@ -358,10 +359,11 @@ for(const device of Object.values(devices)) {
358
359
  body.append('code', code);
359
360
 
360
361
  const response = await Util.fetch(`${this.baseUrl}/oauth2/token`, {
361
- body,
362
+ body: body.toString(),
362
363
  method: 'post',
363
364
  headers: {
364
- Authorization: `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
365
+ 'Authorization': `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
366
+ 'Content-Type': 'application/x-www-form-urlencoded',
365
367
  },
366
368
  });
367
369
 
@@ -418,10 +420,11 @@ for(const device of Object.values(devices)) {
418
420
  body.append('password', password);
419
421
 
420
422
  const response = await Util.fetch(`${this.baseUrl}/oauth2/token`, {
421
- body,
423
+ body: body.toString(),
422
424
  method: 'post',
423
425
  headers: {
424
- Authorization: `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
426
+ 'Authorization': `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
427
+ 'Content-Type': 'application/x-www-form-urlencoded',
425
428
  },
426
429
  });
427
430
 
@@ -462,10 +465,11 @@ for(const device of Object.values(devices)) {
462
465
  body.append('refresh_token', this.__token.refresh_token);
463
466
 
464
467
  const response = await Util.fetch(`${this.baseUrl}/oauth2/token`, {
465
- body,
468
+ body: body.toString(),
466
469
  method: 'post',
467
470
  headers: {
468
- Authorization: `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
471
+ 'Authorization': `Basic ${Util.base64(`${this.__clientId}:${this.__clientSecret}`)}`,
472
+ 'Content-Type': 'application/x-www-form-urlencoded',
469
473
  },
470
474
  });
471
475
 
@@ -1,9 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const fetch = require('node-fetch');
4
-
5
3
  const API = require('./API');
6
4
  const APIError = require('./APIError');
5
+ const Util = require('./Util');
7
6
 
8
7
  class HomeyCloudAPI extends API {
9
8
 
@@ -26,7 +25,7 @@ class HomeyCloudAPI extends API {
26
25
  * @returns {string} result.region - e.g. `eu-central-1`
27
26
  */
28
27
  static async getClosestRegion() {
29
- const res = await fetch(`https://${HomeyCloudAPI.SPECIFICATION.host}`);
28
+ const res = await Util.fetch(`https://${HomeyCloudAPI.SPECIFICATION.host}`);
30
29
  if (!res.ok) {
31
30
  throw new Error(res.statusText || 'Unknown Error');
32
31
  }
@@ -56,7 +55,7 @@ class HomeyCloudAPI extends API {
56
55
  * @returns {Promise<object>} result
57
56
  */
58
57
  async getSystemStatus({ secret }) {
59
- const res = await fetch(`${this.baseUrl}/api/system/status`, {
58
+ const res = await Util.fetch(`${this.baseUrl}/api/system/status`, {
60
59
  headers: {
61
60
  'X-Homey-Secret': secret,
62
61
  },
package/lib/Util.js CHANGED
@@ -18,13 +18,22 @@ class Util {
18
18
  * @returns {Promise}
19
19
  */
20
20
  static async fetch(...args) {
21
- // If in a browser
21
+ if (this.isReactNative()) {
22
+ return fetch(...args);
23
+ }
24
+
22
25
  if (this.isBrowser()) {
23
26
  return window.fetch(...args);
24
27
  }
25
28
 
26
- const fetch = require('node-fetch');
27
- return fetch(...args);
29
+ if (this.isNodeJS()) {
30
+ const fetch = require('node-fetch');
31
+ return fetch(...args);
32
+ }
33
+
34
+ if (typeof fetch !== 'undefined') {
35
+ return fetch(...args);
36
+ }
28
37
  }
29
38
 
30
39
  /**
@@ -81,17 +90,26 @@ class Util {
81
90
  return window.location.protocol === 'http:';
82
91
  }
83
92
 
93
+ /**
94
+ * @returns {boolean}
95
+ */
96
+ static isReactNative() {
97
+ return (typeof navigator !== 'undefined' && navigator.product === 'ReactNative');
98
+ }
99
+
84
100
  /**
85
101
  * @returns {boolean}
86
102
  */
87
103
  static isBrowser() {
88
- return (typeof window !== 'undefined');
104
+ if (this.isReactNative()) return false;
105
+ return (typeof document !== 'undefined' && typeof document.window !== 'undefined');
89
106
  }
90
107
 
91
108
  /**
92
109
  * @returns {boolean}
93
110
  */
94
111
  static isNodeJS() {
112
+ if (this.isReactNative()) return false;
95
113
  return (typeof process !== 'undefined');
96
114
  }
97
115
 
@@ -119,19 +137,58 @@ class Util {
119
137
  }
120
138
 
121
139
  /**
140
+ * This method encodes a string into a base64 string.
141
+ * It's provided as Util because Node.js uses `Buffer`,
142
+ * browsers use `btoa` and React Native doesn't provide anything.
122
143
  * @param {string} input - Input
123
144
  * @returns {string} - Base64 encoded output
124
145
  */
125
- static base64(str) {
126
- if (typeof btoa === 'function') {
127
- return btoa(str);
146
+ static base64(s) {
147
+ function btoaLookup(index) {
148
+ if (index >= 0 && index < 64) {
149
+ const keystr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
150
+ return keystr[index];
151
+ }
152
+
153
+ // Throw INVALID_CHARACTER_ERR exception here -- won't be hit in the tests.
154
+ return undefined;
128
155
  }
129
156
 
130
- if (typeof Buffer !== 'undefined') {
131
- return Buffer.from(str).toString('base64');
157
+ if (typeof s !== 'string') {
158
+ throw new Error('Invalid Input');
132
159
  }
133
160
 
134
- throw new Error('No Base64 Methods Available');
161
+ let i;
162
+
163
+ // "The btoa() method must throw an "InvalidCharacterError" DOMException if
164
+ // data contains any character whose code point is greater than U+00FF."
165
+ for (i = 0; i < s.length; i++) {
166
+ if (s.charCodeAt(i) > 255) {
167
+ return null;
168
+ }
169
+ }
170
+ let out = '';
171
+ for (i = 0; i < s.length; i += 3) {
172
+ const groupsOfSix = [undefined, undefined, undefined, undefined];
173
+ groupsOfSix[0] = s.charCodeAt(i) >> 2;
174
+ groupsOfSix[1] = (s.charCodeAt(i) & 0x03) << 4;
175
+ if (s.length > i + 1) {
176
+ groupsOfSix[1] |= s.charCodeAt(i + 1) >> 4;
177
+ groupsOfSix[2] = (s.charCodeAt(i + 1) & 0x0f) << 2;
178
+ }
179
+ if (s.length > i + 2) {
180
+ groupsOfSix[2] |= s.charCodeAt(i + 2) >> 6;
181
+ groupsOfSix[3] = s.charCodeAt(i + 2) & 0x3f;
182
+ }
183
+ for (let j = 0; j < groupsOfSix.length; j++) {
184
+ if (typeof groupsOfSix[j] === 'undefined') {
185
+ out += '=';
186
+ } else {
187
+ out += btoaLookup(groupsOfSix[j]);
188
+ }
189
+ }
190
+ }
191
+ return out;
135
192
  }
136
193
 
137
194
  /**
@@ -161,6 +218,10 @@ class Util {
161
218
  return process.env[key] || null;
162
219
  }
163
220
 
221
+ if (this.isReactNative()) {
222
+ return null;
223
+ }
224
+
164
225
  return null;
165
226
  }
166
227
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homey-api",
3
- "version": "1.5.29",
3
+ "version": "1.6.1",
4
4
  "description": "Homey API",
5
5
  "main": "index.js",
6
6
  "types": "assets/types/homey-api.d.ts",