@hello.nrfcloud.com/nrfcloud-api-helpers 3.0.74 → 4.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.
- package/dist/api/getAccountInfo.d.ts +3 -1
- package/dist/api/getAccountInfo.js +1 -1
- package/dist/api/getAccountInfo.spec.js +1 -1
- package/dist/api/getLocationHistory.d.ts +46 -0
- package/dist/api/getLocationHistory.js +97 -0
- package/dist/api/getLocationHistory.spec.d.ts +1 -0
- package/dist/api/getLocationHistory.spec.js +35 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/test-data/location.json +26 -0
- package/dist/api/validatedFetch.d.ts +3 -1
- package/dist/api/validatedFetch.js +2 -2
- package/package.json +4 -4
|
@@ -13,7 +13,7 @@ void describe('getAccountInfo()', () => {
|
|
|
13
13
|
json: async () => Promise.resolve(APIresponse),
|
|
14
14
|
}));
|
|
15
15
|
assert.equal('error' in res, false);
|
|
16
|
-
check(res).is(objectMatching({
|
|
16
|
+
check('result' in res && res.result).is(objectMatching({
|
|
17
17
|
mqttEndpoint: 'mqtt.nrfcloud.com',
|
|
18
18
|
mqttTopicPrefix: 'prod/b8b26bc5-2814-4063-b4fa-83ecddb2fec7/',
|
|
19
19
|
team: {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Static } from '@sinclair/typebox';
|
|
2
|
+
import type { ValidationError } from 'ajv';
|
|
3
|
+
export declare enum LocationHistoryServiceType {
|
|
4
|
+
ANCHOR = "ANCHOR",
|
|
5
|
+
GNSS = "GNSS",
|
|
6
|
+
GPS = "GPS",
|
|
7
|
+
MCELL = "MCELL",
|
|
8
|
+
MCELL_EVAL = "MCELL_EVAL",
|
|
9
|
+
SCELL = "SCELL",
|
|
10
|
+
SCELL_EVAL = "SCELL_EVAL",
|
|
11
|
+
WIFI = "WIFI",
|
|
12
|
+
WIFI_EVAL = "WIFI_EVAL"
|
|
13
|
+
}
|
|
14
|
+
declare const LocationHistoryType: import("@sinclair/typebox").TObject<{
|
|
15
|
+
items: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
16
|
+
id: import("@sinclair/typebox").TString;
|
|
17
|
+
deviceId: import("@sinclair/typebox").TString;
|
|
18
|
+
serviceType: import("@sinclair/typebox").TEnum<typeof LocationHistoryServiceType>;
|
|
19
|
+
insertedAt: import("@sinclair/typebox").TString;
|
|
20
|
+
lat: import("@sinclair/typebox").TString;
|
|
21
|
+
lon: import("@sinclair/typebox").TString;
|
|
22
|
+
meta: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TAny>;
|
|
23
|
+
uncertainty: import("@sinclair/typebox").TRegExp;
|
|
24
|
+
anchors: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
25
|
+
macAddress: import("@sinclair/typebox").TRegExp;
|
|
26
|
+
name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRegExp>;
|
|
27
|
+
}>>>;
|
|
28
|
+
}>>;
|
|
29
|
+
total: import("@sinclair/typebox").TNumber;
|
|
30
|
+
pageNextToken: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
31
|
+
}>;
|
|
32
|
+
export type LocationHistory = Static<typeof LocationHistoryType>;
|
|
33
|
+
export declare const getLocationHistory: ({ apiKey, endpoint, }: {
|
|
34
|
+
apiKey: string;
|
|
35
|
+
endpoint: URL;
|
|
36
|
+
}, fetchImplementation?: typeof fetch) => ({ deviceId, pageNextToken, start, end, }: {
|
|
37
|
+
deviceId: string;
|
|
38
|
+
pageNextToken?: string;
|
|
39
|
+
start?: Date;
|
|
40
|
+
end?: Date;
|
|
41
|
+
}) => Promise<{
|
|
42
|
+
error: Error | ValidationError;
|
|
43
|
+
} | {
|
|
44
|
+
result: Static<typeof LocationHistoryType>;
|
|
45
|
+
}>;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Type } from '@sinclair/typebox';
|
|
2
|
+
import { validatedFetch } from './validatedFetch.js';
|
|
3
|
+
export var LocationHistoryServiceType;
|
|
4
|
+
(function (LocationHistoryServiceType) {
|
|
5
|
+
LocationHistoryServiceType["ANCHOR"] = "ANCHOR";
|
|
6
|
+
LocationHistoryServiceType["GNSS"] = "GNSS";
|
|
7
|
+
LocationHistoryServiceType["GPS"] = "GPS";
|
|
8
|
+
LocationHistoryServiceType["MCELL"] = "MCELL";
|
|
9
|
+
LocationHistoryServiceType["MCELL_EVAL"] = "MCELL_EVAL";
|
|
10
|
+
LocationHistoryServiceType["SCELL"] = "SCELL";
|
|
11
|
+
LocationHistoryServiceType["SCELL_EVAL"] = "SCELL_EVAL";
|
|
12
|
+
LocationHistoryServiceType["WIFI"] = "WIFI";
|
|
13
|
+
LocationHistoryServiceType["WIFI_EVAL"] = "WIFI_EVAL";
|
|
14
|
+
})(LocationHistoryServiceType || (LocationHistoryServiceType = {}));
|
|
15
|
+
const LocationHistoryType = Type.Object({
|
|
16
|
+
items: Type.Array(Type.Object({
|
|
17
|
+
id: Type.String({
|
|
18
|
+
minLength: 1,
|
|
19
|
+
title: 'ID',
|
|
20
|
+
description: 'Universally unique identifier',
|
|
21
|
+
examples: ['bc631093-7f7c-4c1b-aa63-a68c759bcd5c'],
|
|
22
|
+
}),
|
|
23
|
+
deviceId: Type.String({
|
|
24
|
+
minLength: 1,
|
|
25
|
+
title: 'This is the canonical device id used in the device certificate, and as the MQTT client id.',
|
|
26
|
+
examples: ['nrf-1234567890123456789000'],
|
|
27
|
+
}),
|
|
28
|
+
serviceType: Type.Enum(LocationHistoryServiceType, {
|
|
29
|
+
title: 'Tracker Service Type',
|
|
30
|
+
description: 'This is the service used to obtain the location of a device. The "_EVAL" suffix means the location was obtained using an evaluation token. GNSS location is derived on the device and reported back to the cloud. "GPS" type has been deprecated, but will still return for older records.',
|
|
31
|
+
examples: ['location'],
|
|
32
|
+
}),
|
|
33
|
+
insertedAt: Type.String({
|
|
34
|
+
title: 'Insertion Time',
|
|
35
|
+
description: 'HTML-encoded ISO-8601 date-time string denoting the start or end of a date range. If the string includes only a date, the time is the beginning of the day (00:00:00).',
|
|
36
|
+
examples: ['2021-08-31T20:00:00Z'],
|
|
37
|
+
}),
|
|
38
|
+
lat: Type.String({
|
|
39
|
+
minLength: 1,
|
|
40
|
+
examples: ['63.41999531'],
|
|
41
|
+
description: 'Latitude in degrees',
|
|
42
|
+
}),
|
|
43
|
+
lon: Type.String({
|
|
44
|
+
minLength: 1,
|
|
45
|
+
examples: ['-122.688408'],
|
|
46
|
+
description: 'Longitude in degrees',
|
|
47
|
+
}),
|
|
48
|
+
meta: Type.Record(Type.String({ minLength: 1 }), Type.Any(), {
|
|
49
|
+
title: 'GNSS metatdata',
|
|
50
|
+
description: 'Metadata sent from device when reporting GNSS location in PVT format. Can include other non-gnss related key/value pairs for easy retrieval later. Only populated for GNSS PVT formatted fixes, empty object otherwise.',
|
|
51
|
+
}),
|
|
52
|
+
uncertainty: Type.RegExp(/^[0-9.]+$/, {
|
|
53
|
+
title: 'Uncertainty',
|
|
54
|
+
description: 'Radius of the uncertainty circle around the location in meters. Also known as Horizontal Positioning Error (HPE).',
|
|
55
|
+
examples: ['2420', '13.012'],
|
|
56
|
+
}),
|
|
57
|
+
anchors: Type.Optional(Type.Array(Type.Object({
|
|
58
|
+
macAddress: Type.RegExp(/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i, {
|
|
59
|
+
title: 'Mac Address',
|
|
60
|
+
description: 'String comprised of 6 hexadecimal pairs, separated by colons or dashes. When used in a positioning request, it must be universally assigned. See this help page for details.',
|
|
61
|
+
examples: ['FE:1E:41:2D:9E:53'],
|
|
62
|
+
}),
|
|
63
|
+
name: Type.Optional(Type.RegExp(/^[a-z0-9_ -]{1,32}$/i, {
|
|
64
|
+
title: 'Name',
|
|
65
|
+
description: 'Limit 32 characters. Only numbers, letters, underscores, dashes, and spaces allowed. All other characters will be removed.',
|
|
66
|
+
examples: ['anchor-1'],
|
|
67
|
+
})),
|
|
68
|
+
}))),
|
|
69
|
+
})),
|
|
70
|
+
total: Type.Number({ minimum: 0 }),
|
|
71
|
+
pageNextToken: Type.Optional(Type.String({ minLength: 1 })),
|
|
72
|
+
}, {
|
|
73
|
+
title: 'Location History',
|
|
74
|
+
description: 'See https://api.nrfcloud.com/v1#tag/Location-History/operation/GetLocationHistory',
|
|
75
|
+
});
|
|
76
|
+
export const getLocationHistory = ({ apiKey, endpoint, }, fetchImplementation) => async ({ deviceId, pageNextToken, start, end, }) => {
|
|
77
|
+
const query = new URLSearchParams({
|
|
78
|
+
pageLimit: '100',
|
|
79
|
+
deviceId,
|
|
80
|
+
});
|
|
81
|
+
if (start !== undefined)
|
|
82
|
+
query.set('start', start.toISOString());
|
|
83
|
+
if (end !== undefined)
|
|
84
|
+
query.set('end', end.toISOString());
|
|
85
|
+
if (pageNextToken !== undefined)
|
|
86
|
+
query.set('pageNextToken', pageNextToken);
|
|
87
|
+
const maybeHistory = await validatedFetch({
|
|
88
|
+
endpoint,
|
|
89
|
+
apiKey,
|
|
90
|
+
}, fetchImplementation)({
|
|
91
|
+
resource: 'location/history',
|
|
92
|
+
query,
|
|
93
|
+
}, LocationHistoryType);
|
|
94
|
+
if ('error' in maybeHistory)
|
|
95
|
+
return maybeHistory;
|
|
96
|
+
return maybeHistory;
|
|
97
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { getLocationHistory } from './getLocationHistory.js';
|
|
4
|
+
import APIresponse from './test-data/location.json';
|
|
5
|
+
import { aString, arrayMatching, check, objectMatching } from 'tsmatchers';
|
|
6
|
+
await describe('getLocationHistory()', async () => {
|
|
7
|
+
await it('return the location history', async () => {
|
|
8
|
+
const res = await getLocationHistory({
|
|
9
|
+
endpoint: new URL('https://example.com/'),
|
|
10
|
+
apiKey: 'some-key',
|
|
11
|
+
}, () => Promise.resolve({
|
|
12
|
+
ok: true,
|
|
13
|
+
json: async () => Promise.resolve(APIresponse),
|
|
14
|
+
}))({
|
|
15
|
+
deviceId: 'oob-355025930003742',
|
|
16
|
+
});
|
|
17
|
+
assert.equal('error' in res, false);
|
|
18
|
+
check('result' in res && res.result).is(objectMatching({
|
|
19
|
+
items: arrayMatching([
|
|
20
|
+
objectMatching({
|
|
21
|
+
id: '3b45f2db-3b0c-4be8-be9a-273f12697fc4',
|
|
22
|
+
deviceId: 'oob-355025930003742',
|
|
23
|
+
serviceType: 'MCELL',
|
|
24
|
+
insertedAt: '2024-06-04T09:54:52.651Z',
|
|
25
|
+
uncertainty: '301',
|
|
26
|
+
lat: '59.92335269',
|
|
27
|
+
lon: '10.68829941',
|
|
28
|
+
meta: {},
|
|
29
|
+
}),
|
|
30
|
+
]),
|
|
31
|
+
total: 100,
|
|
32
|
+
pageNextToken: aString,
|
|
33
|
+
}));
|
|
34
|
+
});
|
|
35
|
+
});
|
package/dist/api/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './getCurrentMonthlyCosts.js';
|
|
|
4
4
|
export * from './createAccountDevice.js';
|
|
5
5
|
export * from './slashless.js';
|
|
6
6
|
export * from './getAccountInfo.js';
|
|
7
|
+
export * from './getLocationHistory.js';
|
|
7
8
|
export * from './deleteAccountDevice.js';
|
|
8
9
|
export * from './getDeviceShadow.js';
|
|
9
10
|
export * from './DeviceShadow.js';
|
package/dist/api/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './getCurrentMonthlyCosts.js';
|
|
|
4
4
|
export * from './createAccountDevice.js';
|
|
5
5
|
export * from './slashless.js';
|
|
6
6
|
export * from './getAccountInfo.js';
|
|
7
|
+
export * from './getLocationHistory.js';
|
|
7
8
|
export * from './deleteAccountDevice.js';
|
|
8
9
|
export * from './getDeviceShadow.js';
|
|
9
10
|
export * from './DeviceShadow.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"items": [
|
|
3
|
+
{
|
|
4
|
+
"id": "3b45f2db-3b0c-4be8-be9a-273f12697fc4",
|
|
5
|
+
"deviceId": "oob-355025930003742",
|
|
6
|
+
"serviceType": "MCELL",
|
|
7
|
+
"insertedAt": "2024-06-04T09:54:52.651Z",
|
|
8
|
+
"uncertainty": "301",
|
|
9
|
+
"lat": "59.92335269",
|
|
10
|
+
"lon": "10.68829941",
|
|
11
|
+
"meta": {}
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "1d2d7188-ef48-427f-9e7d-55caf47958ac",
|
|
15
|
+
"deviceId": "oob-355025930003742",
|
|
16
|
+
"serviceType": "WIFI",
|
|
17
|
+
"insertedAt": "2024-06-04T09:54:47.014Z",
|
|
18
|
+
"uncertainty": "15.066",
|
|
19
|
+
"lat": "59.9212502",
|
|
20
|
+
"lon": "10.6885059",
|
|
21
|
+
"meta": {}
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"total": 100,
|
|
25
|
+
"pageNextToken": "G6QAUI3UVncWwk%2Bps9f3dKLy3I6kBRhUXs5fmFKo3JJn4JADhwMGFhAH3BIINuA4xsDGDT8Ev7rn%2FV45Dd2vBBCx6wxjnHJOFJ6JQyLRS0Kmudiqz%2FMEsmojHdxaYxOCA06orvL7gm7dxH2o06ADouim%2BstZ2lqDqFDECoX6Rh%2FJGB5dsxTPDQM%3D"
|
|
26
|
+
}
|
|
@@ -8,7 +8,7 @@ export declare class ValidationError extends Error {
|
|
|
8
8
|
export declare const validatedFetch: ({ endpoint, apiKey }: {
|
|
9
9
|
apiKey: string;
|
|
10
10
|
endpoint: URL;
|
|
11
|
-
}, fetchImplementation?: typeof fetch) => <Schema extends TObject<import("@sinclair/typebox").TProperties>>(params: {
|
|
11
|
+
}, fetchImplementation?: typeof fetch) => <Schema extends TObject<import("@sinclair/typebox").TProperties>>(params: ({
|
|
12
12
|
resource: string;
|
|
13
13
|
} | {
|
|
14
14
|
resource: string;
|
|
@@ -16,6 +16,8 @@ export declare const validatedFetch: ({ endpoint, apiKey }: {
|
|
|
16
16
|
} | {
|
|
17
17
|
resource: string;
|
|
18
18
|
method: string;
|
|
19
|
+
}) & {
|
|
20
|
+
query?: URLSearchParams;
|
|
19
21
|
}, schema: Schema) => Promise<{
|
|
20
22
|
error: Error | ValidationError;
|
|
21
23
|
} | {
|
|
@@ -25,7 +25,7 @@ const fetchData = (fetchImplementation) => async (...args) => {
|
|
|
25
25
|
return response.json();
|
|
26
26
|
};
|
|
27
27
|
export const validatedFetch = ({ endpoint, apiKey }, fetchImplementation) => async (params, schema) => {
|
|
28
|
-
const { resource } = params;
|
|
28
|
+
const { resource, query } = params;
|
|
29
29
|
const args = {
|
|
30
30
|
headers: headers(apiKey),
|
|
31
31
|
};
|
|
@@ -38,7 +38,7 @@ export const validatedFetch = ({ endpoint, apiKey }, fetchImplementation) => asy
|
|
|
38
38
|
else if ('method' in params) {
|
|
39
39
|
args.method = params.method;
|
|
40
40
|
}
|
|
41
|
-
return fetchData(fetchImplementation)(`${slashless(endpoint)}/v1/${resource}`, args)
|
|
41
|
+
return fetchData(fetchImplementation)(`${slashless(endpoint)}/v1/${resource}${query !== undefined ? `?${query.toString()}` : ''}`, args)
|
|
42
42
|
.then((res) => ({ result: validate(schema, res) }))
|
|
43
43
|
.catch((error) => ({
|
|
44
44
|
error,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hello.nrfcloud.com/nrfcloud-api-helpers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Helper functions for integrating nRF Cloud APIs in AWS lambdas written in TypeScript.",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./*": {
|
|
@@ -82,9 +82,9 @@
|
|
|
82
82
|
],
|
|
83
83
|
"prettier": "@bifravst/prettier-config",
|
|
84
84
|
"peerDependencies": {
|
|
85
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
86
|
-
"@aws-sdk/client-ssm": "^3.
|
|
87
|
-
"@aws-sdk/util-dynamodb": "^3.
|
|
85
|
+
"@aws-sdk/client-dynamodb": "^3.590.0",
|
|
86
|
+
"@aws-sdk/client-ssm": "^3.590.0",
|
|
87
|
+
"@aws-sdk/util-dynamodb": "^3.590.0",
|
|
88
88
|
"@bifravst/aws-ssm-settings-helpers": "^1.1.26",
|
|
89
89
|
"@hello.nrfcloud.com/proto": "^13.0.8",
|
|
90
90
|
"@sinclair/typebox": "^0.32.31"
|