@hello.nrfcloud.com/proto-map 14.1.2 → 15.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.
package/api/Context.ts CHANGED
@@ -2,8 +2,10 @@ const baseURL = `https://github.com/hello-nrfcloud/proto-map`
2
2
 
3
3
  export const Context = {
4
4
  device: new URL(`${baseURL}/device`),
5
+ deviceCredentials: new URL(`${baseURL}/device/credentials`),
5
6
  devices: new URL(`${baseURL}/devices`),
6
7
  deviceJWT: new URL(`${baseURL}/device-jwt`),
8
+ userJWT: new URL(`${baseURL}/user-jwt`),
7
9
  shareDevice: {
8
10
  request: new URL(`${baseURL}/share-device-request`),
9
11
  ownershipConfirmed: new URL(`${baseURL}/share-device-ownership-confirmed`),
@@ -0,0 +1,27 @@
1
+ import { Type } from '@sinclair/typebox'
2
+ import { Context } from './Context.js'
3
+ import { DeviceId, PublicDeviceId } from './DeviceId.js'
4
+
5
+ export const DeviceCredentials = Type.Object(
6
+ {
7
+ '@context': Type.Literal(Context.deviceCredentials.toString()),
8
+ id: PublicDeviceId,
9
+ deviceId: DeviceId,
10
+ credentials: Type.Object({
11
+ privateKey: Type.String({
12
+ minLength: 1,
13
+ title: 'Private Key',
14
+ description: 'PEM encoded private key',
15
+ }),
16
+ certificate: Type.String({
17
+ minLength: 1,
18
+ title: 'Certificate',
19
+ description: 'PEM encoded certificate',
20
+ }),
21
+ }),
22
+ },
23
+ {
24
+ title: 'Device credentials',
25
+ description: 'contains credentials for custom devices',
26
+ },
27
+ )
package/api/DeviceJWT.ts CHANGED
@@ -5,6 +5,7 @@ import { Context } from './Context.js'
5
5
 
6
6
  export const DeviceJWTPayload = Type.Object(
7
7
  {
8
+ '@context': Type.Literal(Context.deviceJWT.toString()),
8
9
  id: PublicDeviceId,
9
10
  deviceId: DeviceId,
10
11
  model: Model,
@@ -0,0 +1,29 @@
1
+ import { describe, it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import invalidEmails from './test/invalid-emails.json' assert { type: 'json' }
4
+ import { Email } from './Email.js'
5
+ import { validate } from '../validate.js'
6
+
7
+ const v = validate(Email)
8
+
9
+ void describe('it should validate emails', () => {
10
+ for (const validEmail of ['alex@example.com', 'a@a.no']) {
11
+ void it(`should validate ${validEmail}`, () => {
12
+ assert.equal(
13
+ 'errors' in v(validEmail),
14
+ false,
15
+ `${validEmail} should be valid`,
16
+ )
17
+ })
18
+ }
19
+
20
+ for (const email of invalidEmails) {
21
+ void it(`should not validate ${email}`, () => {
22
+ assert.equal(
23
+ 'errors' in v(email),
24
+ true,
25
+ `The email ${email} should not be valid!`,
26
+ )
27
+ })
28
+ }
29
+ })
package/api/Email.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { Type } from '@sinclair/typebox'
2
+
3
+ const disallowedChars = '@;" '
4
+ const rx = new RegExp(
5
+ `^[^${disallowedChars}]{1,256}@[^${disallowedChars}]{3,253}$`,
6
+ 'i',
7
+ )
8
+ export const Email = Type.RegExp(rx, {
9
+ title: 'Email',
10
+ description:
11
+ 'The email of the owner of the device. They have to confirm the publication of the device every 30 days.',
12
+ })
package/api/UserJWT.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { Type } from '@sinclair/typebox'
2
+ import { Context } from './Context.js'
3
+ import { Email } from './Email.js'
4
+
5
+ export const UserJWTPayload = Type.Object(
6
+ {
7
+ '@context': Type.Literal(Context.userJWT.toString()),
8
+ email: Email,
9
+ },
10
+ {
11
+ title: 'UserJWTPayload',
12
+ description: 'The payload of the JWT for a user identified by their email.',
13
+ },
14
+ )
15
+
16
+ export const UserJWT = Type.Intersect([
17
+ Type.Object(
18
+ {
19
+ '@context': Type.Literal(Context.userJWT.toString()),
20
+ jwt: Type.String({
21
+ title: 'JWT',
22
+ minLength: 5,
23
+ description: 'The JWT for a user.',
24
+ examples: [
25
+ 'eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6ImEyMGM0NzZkLTVlZjUtNDE1NS1iODllLTdkZWRiMzJjODVhNCJ9.eyJpZCI6ImQ0OThkNzZhLWQ0ZjktNGQ4YS1iMTYwLTNlODA5NGMzOGNmYSIsImRldmljZUlkIjoidGFsbXVkaWMtb3ZlcnJhdGUtcGVuc2l2ZWQiLCJtb2RlbCI6InRoaW5neTkxeCIsImlhdCI6MTcyMTI4NjA1NywiZXhwIjoxNzIxMjg5NjU3LCJhdWQiOiJoZWxsby5ucmZjbG91ZC5jb20ifQ.Afn2Vj7V4boatn3Dwf4yZCTh09lTpfAEfsaX2uTZv0z2EvcWVH3CeVVsEmvCtDb8mnpvxJcj88-l9PlJqShKzZF5AShz6Ps0Igkzm0PueGjK-nq12I8DTgraT6fdSB3v5ALzLC9ozwyuPN7kJDLMHMHkO3j24sveBvFLg2BLsharSRBN',
26
+ ],
27
+ }),
28
+ },
29
+ {
30
+ title: 'UserJWT',
31
+ description: 'The JWT for a user.',
32
+ },
33
+ ),
34
+ UserJWTPayload,
35
+ ])
package/api/index.ts CHANGED
@@ -5,4 +5,6 @@ export * from './ShareDeviceOwnershipConfirmed.js'
5
5
  export * from './ShareDeviceRequest.js'
6
6
  export * from './LwM2M.js'
7
7
  export * from './DeviceJWT.js'
8
+ export * from './UserJWT.js'
8
9
  export * from './APIHealth.js'
10
+ export * from './DeviceCredentials.js'
@@ -0,0 +1,7 @@
1
+ [
2
+ "%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ping j9tbwbatz7e2rvipj6r59wf4yv4lsa.example.com -c1').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}",
3
+ "<!DOCTYPE foo [<!ENTITY xxeww2qq SYSTEM \"http://foo.example.com\"> ]>alex@example.com;alex@example.eu<root>&xxeww2qq;</root>",
4
+ "alex@example.com;alex@example.eu",
5
+ "{\"@type\":\"Freddy\"}",
6
+ "{\"@class\":\"\"}"
7
+ ]
@@ -1,8 +1,10 @@
1
1
  var baseURL = "https://github.com/hello-nrfcloud/proto-map";
2
2
  export var Context = {
3
3
  device: new URL("".concat(baseURL, "/device")),
4
+ deviceCredentials: new URL("".concat(baseURL, "/device/credentials")),
4
5
  devices: new URL("".concat(baseURL, "/devices")),
5
6
  deviceJWT: new URL("".concat(baseURL, "/device-jwt")),
7
+ userJWT: new URL("".concat(baseURL, "/user-jwt")),
6
8
  shareDevice: {
7
9
  request: new URL("".concat(baseURL, "/share-device-request")),
8
10
  ownershipConfirmed: new URL("".concat(baseURL, "/share-device-ownership-confirmed"))
@@ -0,0 +1,23 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { Context } from './Context.js';
3
+ import { DeviceId, PublicDeviceId } from './DeviceId.js';
4
+ export var DeviceCredentials = Type.Object({
5
+ '@context': Type.Literal(Context.deviceCredentials.toString()),
6
+ id: PublicDeviceId,
7
+ deviceId: DeviceId,
8
+ credentials: Type.Object({
9
+ privateKey: Type.String({
10
+ minLength: 1,
11
+ title: 'Private Key',
12
+ description: 'PEM encoded private key'
13
+ }),
14
+ certificate: Type.String({
15
+ minLength: 1,
16
+ title: 'Certificate',
17
+ description: 'PEM encoded certificate'
18
+ })
19
+ })
20
+ }, {
21
+ title: 'Device credentials',
22
+ description: 'contains credentials for custom devices'
23
+ });
@@ -3,6 +3,7 @@ import { DeviceId, PublicDeviceId } from './DeviceId.js';
3
3
  import { Model } from './Devices.js';
4
4
  import { Context } from './Context.js';
5
5
  export var DeviceJWTPayload = Type.Object({
6
+ '@context': Type.Literal(Context.deviceJWT.toString()),
6
7
  id: PublicDeviceId,
7
8
  deviceId: DeviceId,
8
9
  model: Model
@@ -0,0 +1,7 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ var disallowedChars = '@;" ';
3
+ var rx = new RegExp("^[^".concat(disallowedChars, "]{1,256}@[^").concat(disallowedChars, "]{3,253}$"), 'i');
4
+ export var Email = Type.RegExp(rx, {
5
+ title: 'Email',
6
+ description: 'The email of the owner of the device. They have to confirm the publication of the device every 30 days.'
7
+ });
@@ -0,0 +1,43 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import invalidEmails from './test/invalid-emails.json' assert {
4
+ type: 'json'
5
+ };
6
+ import { Email } from './Email.js';
7
+ import { validate } from '../validate.js';
8
+ var v = validate(Email);
9
+ void describe('it should validate emails', function() {
10
+ var _loop = function(_i, _iter) {
11
+ var validEmail = _iter[_i];
12
+ void it("should validate ".concat(validEmail), function() {
13
+ assert.equal('errors' in v(validEmail), false, "".concat(validEmail, " should be valid"));
14
+ });
15
+ };
16
+ for(var _i = 0, _iter = [
17
+ 'alex@example.com',
18
+ 'a@a.no'
19
+ ]; _i < _iter.length; _i++)_loop(_i, _iter);
20
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
21
+ try {
22
+ var _loop1 = function() {
23
+ var email = _step.value;
24
+ void it("should not validate ".concat(email), function() {
25
+ assert.equal('errors' in v(email), true, "The email ".concat(email, " should not be valid!"));
26
+ });
27
+ };
28
+ for(var _iterator = invalidEmails[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_loop1();
29
+ } catch (err) {
30
+ _didIteratorError = true;
31
+ _iteratorError = err;
32
+ } finally{
33
+ try {
34
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
35
+ _iterator.return();
36
+ }
37
+ } finally{
38
+ if (_didIteratorError) {
39
+ throw _iteratorError;
40
+ }
41
+ }
42
+ }
43
+ });
@@ -0,0 +1,27 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { Context } from './Context.js';
3
+ import { Email } from './Email.js';
4
+ export var UserJWTPayload = Type.Object({
5
+ '@context': Type.Literal(Context.userJWT.toString()),
6
+ email: Email
7
+ }, {
8
+ title: 'UserJWTPayload',
9
+ description: 'The payload of the JWT for a user identified by their email.'
10
+ });
11
+ export var UserJWT = Type.Intersect([
12
+ Type.Object({
13
+ '@context': Type.Literal(Context.userJWT.toString()),
14
+ jwt: Type.String({
15
+ title: 'JWT',
16
+ minLength: 5,
17
+ description: 'The JWT for a user.',
18
+ examples: [
19
+ 'eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6ImEyMGM0NzZkLTVlZjUtNDE1NS1iODllLTdkZWRiMzJjODVhNCJ9.eyJpZCI6ImQ0OThkNzZhLWQ0ZjktNGQ4YS1iMTYwLTNlODA5NGMzOGNmYSIsImRldmljZUlkIjoidGFsbXVkaWMtb3ZlcnJhdGUtcGVuc2l2ZWQiLCJtb2RlbCI6InRoaW5neTkxeCIsImlhdCI6MTcyMTI4NjA1NywiZXhwIjoxNzIxMjg5NjU3LCJhdWQiOiJoZWxsby5ucmZjbG91ZC5jb20ifQ.Afn2Vj7V4boatn3Dwf4yZCTh09lTpfAEfsaX2uTZv0z2EvcWVH3CeVVsEmvCtDb8mnpvxJcj88-l9PlJqShKzZF5AShz6Ps0Igkzm0PueGjK-nq12I8DTgraT6fdSB3v5ALzLC9ozwyuPN7kJDLMHMHkO3j24sveBvFLg2BLsharSRBN'
20
+ ]
21
+ })
22
+ }, {
23
+ title: 'UserJWT',
24
+ description: 'The JWT for a user.'
25
+ }),
26
+ UserJWTPayload
27
+ ]);
package/dist/api/index.js CHANGED
@@ -5,4 +5,6 @@ export * from './ShareDeviceOwnershipConfirmed.js';
5
5
  export * from './ShareDeviceRequest.js';
6
6
  export * from './LwM2M.js';
7
7
  export * from './DeviceJWT.js';
8
+ export * from './UserJWT.js';
8
9
  export * from './APIHealth.js';
10
+ export * from './DeviceCredentials.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hello.nrfcloud.com/proto-map",
3
- "version": "14.1.2",
3
+ "version": "15.0.0",
4
4
  "description": "Documents the communication protocol between devices, the hello.nrfcloud.com/map backend and web application",
5
5
  "type": "module",
6
6
  "exports": {
@@ -39,18 +39,18 @@
39
39
  "@bifravst/prettier-config": "1.0.4",
40
40
  "@commitlint/config-conventional": "19.2.2",
41
41
  "@swc/cli": "0.4.0",
42
- "@swc/core": "1.7.3",
43
- "@types/node": "20.14.13",
42
+ "@swc/core": "1.7.6",
43
+ "@types/node": "22.1.0",
44
44
  "@types/xml2js": "0.4.14",
45
45
  "chalk": "5.3.0",
46
46
  "globstar": "1.0.0",
47
47
  "husky": "9.1.4",
48
- "lint-staged": "15.2.7",
48
+ "lint-staged": "15.2.8",
49
49
  "prettier-plugin-organize-imports": "4.0.0",
50
50
  "remark": "15.0.1",
51
51
  "remark-frontmatter": "5.0.0",
52
52
  "tsmatchers": "5.0.2",
53
- "tsx": "4.16.2",
53
+ "tsx": "4.16.5",
54
54
  "typescript": "5.5.4",
55
55
  "xml2js": "0.6.2",
56
56
  "yaml": "2.5.0"