@hello.nrfcloud.com/nrfcloud-api-helpers 6.0.466 → 6.0.468

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.
Files changed (63) hide show
  1. package/npm/api/DeviceShadow.js +32 -0
  2. package/npm/api/FetchError.js +9 -0
  3. package/npm/{src/api → api}/bulkOps.d.ts +5 -3
  4. package/npm/api/bulkOps.js +22 -0
  5. package/npm/{src/api → api}/cancelFOTAJob.d.ts +1 -1
  6. package/npm/api/cancelFOTAJob.js +15 -0
  7. package/npm/api/createAccountDevice.d.ts +7 -0
  8. package/npm/api/createAccountDevice.js +25 -0
  9. package/npm/{src/api → api}/createFOTAJob.d.ts +4 -3
  10. package/npm/api/createFOTAJob.js +32 -0
  11. package/npm/api/deleteAccountDevice.js +9 -0
  12. package/npm/api/devices.d.ts +98 -0
  13. package/npm/api/devices.js +98 -0
  14. package/npm/api/export.js +18 -0
  15. package/npm/{src/api → api}/getAccountInfo.d.ts +9 -2
  16. package/npm/api/getAccountInfo.js +20 -0
  17. package/npm/{src/api → api}/getCurrentMonthlyCosts.d.ts +1 -1
  18. package/npm/api/getCurrentMonthlyCosts.js +22 -0
  19. package/npm/api/getDeviceShadow.d.ts +28 -0
  20. package/npm/api/getDeviceShadow.js +42 -0
  21. package/npm/{src/api → api}/getFOTABundles.d.ts +11 -3
  22. package/npm/api/getFOTABundles.js +101 -0
  23. package/npm/{src/api → api}/getFOTAJob.d.ts +23 -3
  24. package/npm/api/getFOTAJob.js +114 -0
  25. package/npm/{src/api → api}/getLocationHistory.d.ts +24 -5
  26. package/npm/api/getLocationHistory.js +118 -0
  27. package/npm/{src/api → api}/groundFix.d.ts +8 -4
  28. package/npm/api/groundFix.js +38 -0
  29. package/npm/{src/api → api}/serviceToken.d.ts +2 -2
  30. package/npm/api/serviceToken.js +20 -0
  31. package/npm/api/slashless.js +1 -0
  32. package/npm/{src/api → api}/validatedFetch.d.ts +6 -4
  33. package/npm/api/validatedFetch.js +58 -0
  34. package/npm/settings/export.js +5 -0
  35. package/npm/settings/getAllAccounts.js +9 -0
  36. package/npm/settings/getAllAccountsSettings.js +13 -0
  37. package/npm/settings/groupByAccount.js +16 -0
  38. package/npm/settings/scope.js +6 -0
  39. package/npm/{src/settings → settings}/settings.d.ts +7 -13
  40. package/npm/settings/settings.js +83 -0
  41. package/package.json +2 -2
  42. package/npm/src/api/createAccountDevice.d.ts +0 -13
  43. package/npm/src/api/devices.d.ts +0 -78
  44. package/npm/src/api/getDeviceShadow.d.ts +0 -25
  45. /package/npm/{src/api → api}/DeviceShadow.d.ts +0 -0
  46. /package/npm/{src/api → api}/DeviceShadow.spec.d.ts +0 -0
  47. /package/npm/{src/api → api}/FetchError.d.ts +0 -0
  48. /package/npm/{src/api → api}/deleteAccountDevice.d.ts +0 -0
  49. /package/npm/{src/api → api}/export.d.ts +0 -0
  50. /package/npm/{src/api → api}/getAccountInfo.spec.d.ts +0 -0
  51. /package/npm/{src/api → api}/getCurrentMonthlyCosts.spec.d.ts +0 -0
  52. /package/npm/{src/api → api}/getDeviceShadow.spec.d.ts +0 -0
  53. /package/npm/{src/api → api}/getFOTABundle.spec.d.ts +0 -0
  54. /package/npm/{src/api → api}/getLocationHistory.spec.d.ts +0 -0
  55. /package/npm/{src/api → api}/slashless.d.ts +0 -0
  56. /package/npm/{src/api → api}/slashless.spec.d.ts +0 -0
  57. /package/npm/{src/api → api}/validatedFetch.spec.d.ts +0 -0
  58. /package/npm/{src/settings → settings}/export.d.ts +0 -0
  59. /package/npm/{src/settings → settings}/getAllAccounts.d.ts +0 -0
  60. /package/npm/{src/settings → settings}/getAllAccountsSettings.d.ts +0 -0
  61. /package/npm/{src/settings → settings}/groupByAccount.d.ts +0 -0
  62. /package/npm/{src/settings → settings}/groupByAccount.spec.d.ts +0 -0
  63. /package/npm/{src/settings → settings}/scope.d.ts +0 -0
@@ -0,0 +1,32 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ /**
3
+ * @link https://api.nrfcloud.com/v1/#tag/All-Devices/operation/ListDevices
4
+ */ export const DeviceShadow = Type.Object({
5
+ id: Type.String(),
6
+ $meta: Type.Object({
7
+ createdAt: Type.String({
8
+ minLength: 1,
9
+ examples: [
10
+ '2019-08-24T14:15:22Z'
11
+ ]
12
+ }),
13
+ updatedAt: Type.Optional(Type.String({
14
+ minLength: 1,
15
+ examples: [
16
+ '2019-08-24T14:15:22Z'
17
+ ]
18
+ }))
19
+ }),
20
+ state: Type.Optional(Type.Object({
21
+ reported: Type.Optional(Type.Record(Type.String({
22
+ minLength: 1
23
+ }), Type.Any())),
24
+ desired: Type.Optional(Type.Record(Type.String({
25
+ minLength: 1
26
+ }), Type.Any())),
27
+ version: Type.Number(),
28
+ metadata: Type.Record(Type.String({
29
+ minLength: 1
30
+ }), Type.Any())
31
+ }))
32
+ });
@@ -0,0 +1,9 @@
1
+ export class FetchError extends Error {
2
+ statusCode;
3
+ constructor(statusCode, message){
4
+ super(message);
5
+ this.statusCode = statusCode;
6
+ this.name = 'FetchError';
7
+ }
8
+ }
9
+ export const toFetchError = async (response)=>new FetchError(response.status, parseInt(response.headers.get('content-length') ?? '0', 10) > 0 ? await response.text() : 'No content returned from server');
@@ -1,4 +1,3 @@
1
- import { type Static } from '@sinclair/typebox';
2
1
  import type { FetchError } from './FetchError.ts';
3
2
  import { type ValidationError } from './validatedFetch.ts';
4
3
  /**
@@ -11,8 +10,11 @@ export declare const BulkOpsRequestType: import("@sinclair/typebox").TObject<{
11
10
  export declare const bulkOpsRequests: ({ apiKey, endpoint, }: {
12
11
  apiKey: string;
13
12
  endpoint: URL;
14
- }, fetchImplementation?: typeof fetch) => (bulkOpsId: string) => Promise<{
13
+ }, fetchImplementation?: typeof fetch | undefined) => (bulkOpsId: string) => Promise<{
15
14
  error: FetchError | ValidationError;
16
15
  } | {
17
- result: Static<typeof BulkOpsRequestType>;
16
+ result: {
17
+ bulkOpsRequestId: string;
18
+ status: "FAILED" | "IN_PROGRESS" | "PENDING" | "SUCCEEDED";
19
+ };
18
20
  }>;
@@ -0,0 +1,22 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { validatedFetch } from './validatedFetch.js';
3
+ /**
4
+ * @link https://api.nrfcloud.com/v1/#tag/Bulk-Ops-Requests/operation/FetchBulkOpsRequest
5
+ */ export const BulkOpsRequestType = Type.Object({
6
+ bulkOpsRequestId: Type.String(),
7
+ status: Type.Union([
8
+ Type.Literal('PENDING'),
9
+ Type.Literal('IN_PROGRESS'),
10
+ Type.Literal('FAILED'),
11
+ Type.Literal('SUCCEEDED')
12
+ ])
13
+ });
14
+ export const bulkOpsRequests = ({ apiKey, endpoint }, fetchImplementation)=>async (bulkOpsId)=>{
15
+ const vf = validatedFetch({
16
+ endpoint,
17
+ apiKey
18
+ }, fetchImplementation);
19
+ return vf({
20
+ resource: `bulk-ops-requests/${encodeURIComponent(bulkOpsId)}`
21
+ }, BulkOpsRequestType);
22
+ };
@@ -3,7 +3,7 @@ import type { ValidationError } from './validatedFetch.ts';
3
3
  export declare const cancelFOTAJob: ({ apiKey, endpoint, }: {
4
4
  apiKey: string;
5
5
  endpoint: URL;
6
- }, fetchImplementation?: typeof fetch) => (jobId: string) => Promise<{
6
+ }, fetchImplementation?: typeof fetch | undefined) => (jobId: string) => Promise<{
7
7
  error: FetchError | ValidationError;
8
8
  } | {
9
9
  success: true;
@@ -0,0 +1,15 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { validatedFetch } from './validatedFetch.js';
3
+ export const cancelFOTAJob = ({ apiKey, endpoint }, fetchImplementation)=>async (jobId)=>{
4
+ const maybeSuccess = await validatedFetch({
5
+ endpoint,
6
+ apiKey
7
+ }, fetchImplementation)({
8
+ resource: `fota-jobs/${jobId}/cancel`,
9
+ method: 'PUT'
10
+ }, Type.Any());
11
+ if ('error' in maybeSuccess) return maybeSuccess;
12
+ return {
13
+ success: true
14
+ };
15
+ };
@@ -0,0 +1,7 @@
1
+ export declare const createAccountDevice: ({ apiKey, endpoint, }: {
2
+ apiKey: string;
3
+ endpoint: URL;
4
+ }) => Promise<{
5
+ clientCert: string;
6
+ privateKey: string;
7
+ }>;
@@ -0,0 +1,25 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { validatedFetch } from './validatedFetch.js';
3
+ /**
4
+ * @link https://api.nrfcloud.com/v1/#tag/Account-Devices/operation/CreateAccountDevice
5
+ */ const CertificateCredentials = Type.Object({
6
+ clientCert: Type.String(),
7
+ privateKey: Type.String()
8
+ });
9
+ export const createAccountDevice = async ({ apiKey, endpoint })=>{
10
+ const vf = validatedFetch({
11
+ endpoint,
12
+ apiKey
13
+ });
14
+ const maybeResult = await vf({
15
+ resource: 'devices/account',
16
+ method: 'POST'
17
+ }, CertificateCredentials);
18
+ if ('error' in maybeResult) {
19
+ throw maybeResult.error;
20
+ }
21
+ return {
22
+ clientCert: maybeResult.result.clientCert,
23
+ privateKey: maybeResult.result.privateKey
24
+ };
25
+ };
@@ -1,4 +1,3 @@
1
- import { type Static } from '@sinclair/typebox';
2
1
  import type { FetchError } from './FetchError.ts';
3
2
  import type { ValidationError } from './validatedFetch.ts';
4
3
  export declare const CreateFOTAJobType: import("@sinclair/typebox").TObject<{
@@ -7,11 +6,13 @@ export declare const CreateFOTAJobType: import("@sinclair/typebox").TObject<{
7
6
  export declare const createFOTAJob: ({ apiKey, endpoint, }: {
8
7
  apiKey: string;
9
8
  endpoint: URL;
10
- }, fetchImplementation?: typeof fetch) => ({ deviceId, bundleId, }: {
9
+ }, fetchImplementation?: typeof fetch | undefined) => ({ deviceId, bundleId, }: {
11
10
  deviceId: string;
12
11
  bundleId: string;
13
12
  }) => Promise<{
14
13
  error: FetchError | ValidationError;
15
14
  } | {
16
- result: Static<typeof CreateFOTAJobType>;
15
+ result: {
16
+ jobId: string;
17
+ };
17
18
  }>;
@@ -0,0 +1,32 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { JSONPayload, validatedFetch } from './validatedFetch.js';
3
+ export const CreateFOTAJobType = Type.Object({
4
+ jobId: Type.String({
5
+ minLength: 1,
6
+ title: 'ID',
7
+ description: 'Universally unique identifier',
8
+ examples: [
9
+ 'bc631093-7f7c-4c1b-aa63-a68c759bcd5c'
10
+ ]
11
+ })
12
+ }, {
13
+ title: 'FOTA Job',
14
+ description: 'See https://api.nrfcloud.com/#tag/FOTA-Jobs/operation/CreateFOTAJob'
15
+ });
16
+ export const createFOTAJob = ({ apiKey, endpoint }, fetchImplementation)=>async ({ deviceId, bundleId })=>{
17
+ const maybeJob = await validatedFetch({
18
+ endpoint,
19
+ apiKey
20
+ }, fetchImplementation)({
21
+ resource: 'fota-jobs',
22
+ payload: JSONPayload({
23
+ bundleId,
24
+ autoApply: true,
25
+ deviceIdentifiers: [
26
+ deviceId
27
+ ]
28
+ })
29
+ }, CreateFOTAJobType);
30
+ if ('error' in maybeJob) return maybeJob;
31
+ return maybeJob;
32
+ };
@@ -0,0 +1,9 @@
1
+ import { slashless } from './slashless.js';
2
+ export const deleteAccountDevice = async ({ apiKey, endpoint })=>{
3
+ await fetch(`${slashless(endpoint)}/v1/devices/account`, {
4
+ method: 'DELETE',
5
+ headers: {
6
+ Authorization: `Bearer ${apiKey}`
7
+ }
8
+ });
9
+ };
@@ -0,0 +1,98 @@
1
+ import type { FetchError } from './FetchError.ts';
2
+ import { type ValidationError } from './validatedFetch.ts';
3
+ /**
4
+ * firmware types supported by a device for FOTA
5
+ */
6
+ export declare enum FwType {
7
+ APP = "APP",
8
+ MODEM = "MODEM",
9
+ BOOT = "BOOT",
10
+ SOFTDEVICE = "SOFTDEVICE",
11
+ BOOTLOADER = "BOOTLOADER",
12
+ MDM_FULL = "MDM_FULL"
13
+ }
14
+ export declare const devices: ({ endpoint, apiKey, }: {
15
+ endpoint: URL;
16
+ apiKey: string;
17
+ }, fetchImplementation?: typeof fetch | undefined) => {
18
+ list: () => Promise<{
19
+ error: FetchError | ValidationError;
20
+ } | {
21
+ result: {
22
+ total: number;
23
+ items: {
24
+ id: string;
25
+ $meta: {
26
+ createdAt: string;
27
+ updatedAt?: string | undefined;
28
+ };
29
+ state?: {
30
+ reported?: {
31
+ [x: string]: any;
32
+ } | undefined;
33
+ desired?: {
34
+ [x: string]: any;
35
+ } | undefined;
36
+ version: number;
37
+ metadata: {
38
+ [x: string]: any;
39
+ };
40
+ } | undefined;
41
+ }[];
42
+ };
43
+ }>;
44
+ get: (id: string) => Promise<{
45
+ error: FetchError | ValidationError;
46
+ } | {
47
+ result: {
48
+ id: string;
49
+ $meta: {
50
+ createdAt: string;
51
+ updatedAt?: string | undefined;
52
+ };
53
+ state?: {
54
+ reported?: {
55
+ [x: string]: any;
56
+ } | undefined;
57
+ desired?: {
58
+ [x: string]: any;
59
+ } | undefined;
60
+ version: number;
61
+ metadata: {
62
+ [x: string]: any;
63
+ };
64
+ } | undefined;
65
+ };
66
+ }>;
67
+ updateState: (id: string, state: {
68
+ desired?: Record<string, any> | undefined;
69
+ reported?: Record<string, any> | undefined;
70
+ }) => Promise<{
71
+ error: FetchError | ValidationError;
72
+ } | {
73
+ success: boolean;
74
+ }>;
75
+ register: (devices: {
76
+ deviceId: string;
77
+ certPem: string;
78
+ subType?: string | undefined;
79
+ tags?: string[] | undefined;
80
+ /**
81
+ * A list of pipe-delimited firmware types that each device supports for FOTA (e.g., APP|MODEM)
82
+ *
83
+ * Defaults to all supported (APP|MODEM|BOOT|SOFTDEVICE|BOOTLOADER|MDM_FULL)
84
+ *
85
+ * @default 'APP|MODEM|BOOT|SOFTDEVICE|BOOTLOADER|MDM_FULL'
86
+ */
87
+ fwTypes?: FwType[] | undefined;
88
+ }[]) => Promise<{
89
+ error: FetchError | ValidationError;
90
+ } | {
91
+ bulkOpsRequestId: string;
92
+ }>;
93
+ remove: (deviceId: string) => Promise<{
94
+ error: FetchError | ValidationError;
95
+ } | {
96
+ success: boolean;
97
+ }>;
98
+ };
@@ -0,0 +1,98 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { DeviceShadow } from './DeviceShadow.js';
3
+ import { toFetchError } from './FetchError.js';
4
+ import { slashless } from './slashless.js';
5
+ import { validatedFetch } from './validatedFetch.js';
6
+ const Page = (Item)=>Type.Object({
7
+ total: Type.Integer(),
8
+ items: Type.Array(Item)
9
+ });
10
+ const Devices = Page(DeviceShadow);
11
+ /**
12
+ * @link https://api.nrfcloud.com/v1/#tag/IP-Devices/operation/ProvisionDevices
13
+ */ const ProvisionDevice = Type.Object({
14
+ bulkOpsRequestId: Type.String()
15
+ });
16
+ /**
17
+ * firmware types supported by a device for FOTA
18
+ */ export var FwType = /*#__PURE__*/ function(FwType) {
19
+ FwType["APP"] = "APP";
20
+ FwType["MODEM"] = "MODEM";
21
+ FwType["BOOT"] = "BOOT";
22
+ FwType["SOFTDEVICE"] = "SOFTDEVICE";
23
+ FwType["BOOTLOADER"] = "BOOTLOADER";
24
+ FwType["MDM_FULL"] = "MDM_FULL";
25
+ return FwType;
26
+ }({});
27
+ export const devices = ({ endpoint, apiKey }, fetchImplementation)=>{
28
+ const headers = {
29
+ Authorization: `Bearer ${apiKey}`,
30
+ Accept: 'application/json; charset=utf-8'
31
+ };
32
+ const vf = validatedFetch({
33
+ endpoint,
34
+ apiKey
35
+ }, fetchImplementation);
36
+ return {
37
+ // FIXME: implement pagination
38
+ list: async ()=>vf({
39
+ resource: `devices?${new URLSearchParams({
40
+ pageLimit: '100',
41
+ deviceNameFuzzy: 'oob-'
42
+ }).toString()}`
43
+ }, Devices),
44
+ get: async (id)=>vf({
45
+ resource: `devices/${encodeURIComponent(id)}`
46
+ }, DeviceShadow),
47
+ updateState: async (id, state)=>fetch(`${slashless(endpoint)}/v1/devices/${encodeURIComponent(id)}/state`, {
48
+ headers: {
49
+ ...headers,
50
+ 'Content-Type': 'application/json'
51
+ },
52
+ method: 'PATCH',
53
+ body: JSON.stringify(state)
54
+ }).then(async (res)=>{
55
+ if (res.status >= 400) return {
56
+ error: await toFetchError(res)
57
+ };
58
+ return {
59
+ success: true
60
+ };
61
+ }),
62
+ register: async (devices)=>{
63
+ const bulkRegistrationPayload = devices.map(({ deviceId, subType, tags, fwTypes, certPem })=>{
64
+ const deviceFwTypes = fwTypes ?? Object.values(FwType);
65
+ return [
66
+ [
67
+ deviceId,
68
+ subType ?? '',
69
+ (tags ?? []).join('|'),
70
+ deviceFwTypes.join('|'),
71
+ `"${certPem}"`
72
+ ]
73
+ ];
74
+ }).map((cols)=>cols.join(',')).join('\n');
75
+ const maybeResult = await vf({
76
+ resource: 'devices',
77
+ payload: {
78
+ body: bulkRegistrationPayload,
79
+ type: 'application/octet-stream'
80
+ }
81
+ }, ProvisionDevice);
82
+ if ('error' in maybeResult) return maybeResult;
83
+ return {
84
+ bulkOpsRequestId: maybeResult.result.bulkOpsRequestId
85
+ };
86
+ },
87
+ remove: async (deviceId)=>{
88
+ const maybeResult = await vf({
89
+ method: 'DELETE',
90
+ resource: `devices/${deviceId}`
91
+ }, Type.Any());
92
+ if ('error' in maybeResult) return maybeResult;
93
+ return {
94
+ success: true
95
+ };
96
+ }
97
+ };
98
+ };
@@ -0,0 +1,18 @@
1
+ export * from './bulkOps.js';
2
+ export * from './cancelFOTAJob.js';
3
+ export * from './createAccountDevice.js';
4
+ export * from './createFOTAJob.js';
5
+ export * from './deleteAccountDevice.js';
6
+ export * from './devices.js';
7
+ export * from './DeviceShadow.js';
8
+ export * from './FetchError.js';
9
+ export * from './getAccountInfo.js';
10
+ export * from './getCurrentMonthlyCosts.js';
11
+ export * from './getDeviceShadow.js';
12
+ export * from './getFOTABundles.js';
13
+ export * from './getFOTAJob.js';
14
+ export * from './getLocationHistory.js';
15
+ export * from './groundFix.js';
16
+ export * from './serviceToken.js';
17
+ export * from './slashless.js';
18
+ export * from './validatedFetch.js';
@@ -13,9 +13,16 @@ export type AccountInfo = Static<typeof AccountInfoType>;
13
13
  export declare const getAccountInfo: ({ apiKey, endpoint, }: {
14
14
  apiKey: string;
15
15
  endpoint: URL;
16
- }, fetchImplementation?: typeof fetch) => Promise<{
16
+ }, fetchImplementation?: typeof fetch | undefined) => Promise<{
17
17
  error: FetchError | ValidationError;
18
18
  } | {
19
- result: AccountInfo;
19
+ result: {
20
+ mqttEndpoint: string;
21
+ mqttTopicPrefix: string;
22
+ team: {
23
+ tenantId: string;
24
+ name: string;
25
+ };
26
+ };
20
27
  }>;
21
28
  export {};
@@ -0,0 +1,20 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { validatedFetch } from './validatedFetch.js';
3
+ const AccountInfoType = Type.Object({
4
+ mqttEndpoint: Type.String(),
5
+ mqttTopicPrefix: Type.String(),
6
+ team: Type.Object({
7
+ tenantId: Type.String(),
8
+ name: Type.String()
9
+ })
10
+ });
11
+ export const getAccountInfo = async ({ apiKey, endpoint }, fetchImplementation)=>{
12
+ const maybeAccount = await validatedFetch({
13
+ endpoint,
14
+ apiKey
15
+ }, fetchImplementation)({
16
+ resource: 'account'
17
+ }, AccountInfoType);
18
+ if ('error' in maybeAccount) return maybeAccount;
19
+ return maybeAccount;
20
+ };
@@ -3,7 +3,7 @@ import type { ValidationError } from './validatedFetch.ts';
3
3
  export declare const getCurrentMonthlyCosts: ({ apiKey, endpoint, }: {
4
4
  apiKey: string;
5
5
  endpoint: URL;
6
- }, fetchImplementation?: typeof fetch) => () => Promise<{
6
+ }, fetchImplementation?: typeof fetch | undefined) => () => Promise<{
7
7
  error: FetchError | ValidationError;
8
8
  } | {
9
9
  currentMonthTotalCost: number;
@@ -0,0 +1,22 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { validatedFetch } from './validatedFetch.js';
3
+ export const getCurrentMonthlyCosts = ({ apiKey, endpoint }, fetchImplementation)=>async ()=>{
4
+ const vf = validatedFetch({
5
+ endpoint,
6
+ apiKey
7
+ }, fetchImplementation);
8
+ const maybeResult = await vf({
9
+ resource: 'account'
10
+ }, Type.Object({
11
+ plan: Type.Object({
12
+ currentMonthTotalCost: Type.Number()
13
+ })
14
+ }));
15
+ if ('error' in maybeResult) {
16
+ return maybeResult;
17
+ }
18
+ const currentMonthTotalCost = maybeResult.result.plan.currentMonthTotalCost;
19
+ return {
20
+ currentMonthTotalCost
21
+ };
22
+ };
@@ -0,0 +1,28 @@
1
+ import type { FetchError } from './FetchError.ts';
2
+ import type { ValidationError } from './validatedFetch.ts';
3
+ export declare const getDeviceShadow: ({ endpoint, apiKey, }: {
4
+ endpoint: URL;
5
+ apiKey: string;
6
+ }, fetchImplementation?: typeof fetch | undefined) => (devices: string[]) => Promise<{
7
+ shadows: {
8
+ id: string;
9
+ $meta: {
10
+ createdAt: string;
11
+ updatedAt?: string | undefined;
12
+ };
13
+ state?: {
14
+ reported?: {
15
+ [x: string]: any;
16
+ } | undefined;
17
+ desired?: {
18
+ [x: string]: any;
19
+ } | undefined;
20
+ version: number;
21
+ metadata: {
22
+ [x: string]: any;
23
+ };
24
+ } | undefined;
25
+ }[];
26
+ } | {
27
+ error: FetchError | ValidationError;
28
+ }>;
@@ -0,0 +1,42 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { DeviceShadow } from './DeviceShadow.js';
3
+ import { validatedFetch } from './validatedFetch.js';
4
+ const DeviceShadows = Type.Array(DeviceShadow);
5
+ /**
6
+ * @see https://api.nrfcloud.com/v1#tag/All-Devices/operation/ListDevices
7
+ */ const ListDevices = Type.Object({
8
+ items: DeviceShadows,
9
+ total: Type.Optional(Type.Number({
10
+ minimum: 0
11
+ })),
12
+ pageNextToken: Type.Optional(Type.String({
13
+ minLength: 1
14
+ }))
15
+ });
16
+ export const getDeviceShadow = ({ endpoint, apiKey }, fetchImplementation)=>{
17
+ const vf = validatedFetch({
18
+ endpoint,
19
+ apiKey
20
+ }, fetchImplementation);
21
+ return async (devices)=>{
22
+ const params = {
23
+ includeState: true,
24
+ includeStateMeta: true,
25
+ pageLimit: 100,
26
+ deviceIds: devices.join(',')
27
+ };
28
+ const queryString = Object.entries(params).sort((a, b)=>a[0].localeCompare(b[0])).map((kv)=>kv.map(encodeURIComponent).join('=')).join('&');
29
+ const url = `devices?${queryString}`;
30
+ const maybeResult = await vf({
31
+ resource: url
32
+ }, ListDevices);
33
+ if ('error' in maybeResult) {
34
+ return {
35
+ error: maybeResult.error
36
+ };
37
+ }
38
+ return {
39
+ shadows: maybeResult.result.items
40
+ };
41
+ };
42
+ };
@@ -1,4 +1,3 @@
1
- import { type Static } from '@sinclair/typebox';
2
1
  import { FwType } from './devices.ts';
3
2
  import type { FetchError } from './FetchError.ts';
4
3
  import type { ValidationError } from './validatedFetch.ts';
@@ -15,8 +14,17 @@ export declare const FOTABundle: import("@sinclair/typebox").TObject<{
15
14
  export declare const getFOTABundles: ({ apiKey, endpoint, }: {
16
15
  apiKey: string;
17
16
  endpoint: URL;
18
- }, fetchImplementation?: typeof fetch) => () => Promise<{
17
+ }, fetchImplementation?: typeof fetch | undefined) => () => Promise<{
19
18
  error: FetchError | ValidationError;
20
19
  } | {
21
- bundles: Array<Static<typeof FOTABundle>>;
20
+ bundles: {
21
+ bundleId: string;
22
+ lastModified?: string | undefined;
23
+ size: number;
24
+ version: string;
25
+ type: FwType;
26
+ filenames: string[];
27
+ name?: string | undefined;
28
+ description?: string | undefined;
29
+ }[];
22
30
  }>;