particle-api-js 10.4.2 → 10.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "particle-api-js",
3
- "version": "10.4.2",
3
+ "version": "10.5.0",
4
4
  "description": "Particle API Client",
5
5
  "main": "src/Particle.js",
6
6
  "scripts": {
package/src/Particle.js CHANGED
@@ -3,17 +3,6 @@ const EventStream = require('./EventStream');
3
3
  const Agent = require('./Agent');
4
4
  const Client = require('./Client');
5
5
 
6
- // Hack to avoid importing the type on every @return statement
7
- /**
8
- * @typedef {import('./Agent').RequestResponse} RequestResponse
9
- */
10
- /**
11
- * @typedef {import('./Agent').RequestError} RequestError
12
- */
13
- /**
14
- * @typedef {import('./Agent').Auth} Auth
15
- */
16
-
17
6
  /**
18
7
  * Particle Cloud API wrapper.
19
8
  *
@@ -22,7 +11,12 @@ const Client = require('./Client');
22
11
  *
23
12
  * Most Particle methods take a single unnamed argument object documented as
24
13
  * `options` with key/value pairs for each option.
14
+ *
15
+ * @typedef {import('./Agent').RequestResponse} RequestResponse
16
+ * @typedef {import('./Agent').RequestError} RequestError
17
+ * @typedef {import('./Agent').Auth} Auth
25
18
  */
19
+ // These typedef avoid importing the type on every @return statement
26
20
  class Particle {
27
21
  /**
28
22
  * Contructor for the Cloud API wrapper.
@@ -243,18 +237,20 @@ class Particle {
243
237
  * @param {String} options.username Email of the new user
244
238
  * @param {String} options.password Password
245
239
  * @param {String} options.accountInfo Object that contains account information fields such as user real name, company name, business account flag etc
240
+ * @param {Object} [options.utm] Object that contains info about the campaign that lead to this user creation
246
241
  * @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
247
242
  * @param {Object} [options.context] Request context
248
243
  * @returns {Promise} A promise
249
244
  */
250
- createUser({ username, password, accountInfo, headers, context }){
245
+ createUser({ username, password, accountInfo, utm, headers, context }){
251
246
  return this.post({
252
247
  uri: '/v1/users',
253
248
  headers,
254
249
  data: {
255
250
  username,
256
251
  password,
257
- account_info : accountInfo
252
+ account_info: accountInfo,
253
+ utm
258
254
  },
259
255
  context
260
256
  });
@@ -667,6 +663,42 @@ class Particle {
667
663
  return this.put({ uri, auth, headers, data, context });
668
664
  }
669
665
 
666
+ /**
667
+ * Disable device protection.
668
+ *
669
+ * @param {Object} options Options for this API call.
670
+ * @param {String} options.deviceId Device ID or name.
671
+ * @param {String} options.action Request action: `prepare` or `confirm`.
672
+ * @param {String} [options.org] Organziation ID or slug.
673
+ * @param {String} [options.product] Product ID or slug.
674
+ * @param {String} [options.serverNonce] Base64-encoded server nonce. Mandatory if `action` is `confirm`,
675
+ * @param {String} [options.deviceNonce] Base64-encoded device nonce. Mandatory if `action` is `confirm`,
676
+ * @param {String} [options.deviceSignature] Base64-encoded device signature. Mandatory if `action` is `confirm`,
677
+ * @param {String} [options.devicePublicKeyFingerprint] Base64-encoded fingerprint of the device public key.
678
+ * Mandatory if `action` is `confirm`,
679
+ * @param {Auth} [options.auth] Access token or basic auth object. Can be ignored if provided in constructor.
680
+ * @param {Object} [options.headers] Key/value pairs to send as headers.
681
+ * @param {Object} [options.context] Request context.
682
+ * @returns {Promise} A promise
683
+ */
684
+ unprotectDevice({ deviceId, org, product, action, serverNonce, deviceNonce, deviceSignature, devicePublicKeyFingerprint, auth, headers, context }) {
685
+ const data = { action };
686
+ if (deviceNonce !== undefined) {
687
+ data.device_nonce = deviceNonce;
688
+ }
689
+ if (serverNonce !== undefined) {
690
+ data.server_nonce = serverNonce;
691
+ }
692
+ if (deviceSignature !== undefined) {
693
+ data.device_signature = deviceSignature;
694
+ }
695
+ if (devicePublicKeyFingerprint !== undefined) {
696
+ data.device_public_key_fingerprint = devicePublicKeyFingerprint;
697
+ }
698
+ const uri = this.deviceUri({ deviceId, product, org }) + '/unprotect';
699
+ return this.put({ uri, data, auth, headers, context });
700
+ }
701
+
670
702
  /**
671
703
  * Provision a new device for products that allow self-provisioning
672
704
  * @param {Object} options Options for this API call
@@ -712,16 +744,6 @@ class Particle {
712
744
  });
713
745
  }
714
746
 
715
- changeProduct({ deviceId, productId, auth, headers, context }){
716
- return this.put({
717
- uri: `/v1/devices/${deviceId}`,
718
- auth,
719
- headers,
720
- data: { product_id: productId },
721
- context
722
- });
723
- }
724
-
725
747
  /**
726
748
  * Get the value of a device variable
727
749
  * @param {Object} options Options for this API call
@@ -2637,11 +2659,18 @@ class Particle {
2637
2659
  * @param {Object} options Options for this API call
2638
2660
  * @param {String} options.deviceId Device ID to access
2639
2661
  * @param {String} [options.product] Device only in this product ID or slug
2662
+ * @param {String} [options.org] Device only in this organization ID or slug
2640
2663
  * @private
2641
2664
  * @returns {string} URI
2642
2665
  */
2643
- deviceUri({ deviceId, product }){
2644
- return product ? `/v1/products/${product}/devices/${deviceId}` : `/v1/devices/${deviceId}`;
2666
+ deviceUri({ deviceId, product, org }){
2667
+ if (org) {
2668
+ return `/v1/orgs/${org}/devices/${deviceId}`;
2669
+ }
2670
+ if (product) {
2671
+ return `/v1/products/${product}/devices/${deviceId}`;
2672
+ }
2673
+ return `/v1/devices/${deviceId}`;
2645
2674
  }
2646
2675
 
2647
2676
  /**
@@ -352,7 +352,28 @@ describe('ParticleAPI', () => {
352
352
  data: {
353
353
  username: props.username,
354
354
  password: props.password,
355
- account_info: props.accountInfo
355
+ account_info: props.accountInfo,
356
+ utm: undefined
357
+ },
358
+ context: {}
359
+ });
360
+ });
361
+ });
362
+ it('allows sending utm parameters', () => {
363
+ props.utm = { utm_source: 'web' };
364
+ return api.createUser(props).then(( results ) => {
365
+ results.should.eql({
366
+ uri: '/v1/users',
367
+ method: 'post',
368
+ auth: undefined,
369
+ headers: props.headers,
370
+ data: {
371
+ username: props.username,
372
+ password: props.password,
373
+ account_info: props.accountInfo,
374
+ utm: {
375
+ utm_source: 'web'
376
+ }
356
377
  },
357
378
  context: {}
358
379
  });
@@ -796,19 +817,6 @@ describe('ParticleAPI', () => {
796
817
  });
797
818
  });
798
819
 
799
- describe('.changeProduct', () => {
800
- it('generates request', () => {
801
- return api.changeProduct(props).then(Common.expectDeviceUrlAndToken);
802
- });
803
-
804
- it('sends proper data', () => {
805
- return api.changeProduct(props).then(({ data }) => {
806
- data.should.be.instanceOf(Object);
807
- data.product_id.should.equal(props.productId);
808
- });
809
- });
810
- });
811
-
812
820
  describe('.getVariable', () => {
813
821
  describe('user scope', () => {
814
822
  it('generates request', () => {
@@ -2880,6 +2888,32 @@ describe('ParticleAPI', () => {
2880
2888
  });
2881
2889
  });
2882
2890
  });
2891
+
2892
+ describe('.unprotectDevice', () => {
2893
+ it('generates request', () => {
2894
+ return api.unprotectDevice(Object.assign({}, propsWithProduct, {
2895
+ action: 'action',
2896
+ deviceNonce: 'device-nonce',
2897
+ serverNonce: 'server-nonce',
2898
+ deviceSignature: 'device-signature',
2899
+ devicePublicKeyFingerprint: 'device-public-key-fingerprint'
2900
+ })).then((results) => {
2901
+ results.should.match({
2902
+ method: 'put',
2903
+ uri: `/v1/products/${product}/devices/${props.deviceId}/unprotect`,
2904
+ auth: props.auth,
2905
+ headers: props.headers,
2906
+ data: {
2907
+ action: 'action',
2908
+ device_nonce: 'device-nonce',
2909
+ server_nonce: 'server-nonce',
2910
+ device_signature: 'device-signature',
2911
+ device_public_key_fingerprint: 'device-public-key-fingerprint'
2912
+ }
2913
+ });
2914
+ });
2915
+ });
2916
+ });
2883
2917
  });
2884
2918
 
2885
2919
  describe('backwards-compatibility function aliases', () => {
@@ -2901,6 +2935,12 @@ describe('ParticleAPI', () => {
2901
2935
  uri.should.equal('/v1/products/xyz/devices/abc');
2902
2936
  });
2903
2937
  });
2938
+ describe('org scope', () => {
2939
+ it('gets the org device uri', () => {
2940
+ const uri = api.deviceUri({ deviceId: 'abc', org: 'xyz' });
2941
+ uri.should.equal('/v1/orgs/xyz/devices/abc');
2942
+ });
2943
+ });
2904
2944
  });
2905
2945
 
2906
2946