@kohost/api-client 1.0.0-alpha.1 → 1.0.0-alpha.3

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 (111) hide show
  1. package/.eslintrc.js +10 -0
  2. package/bitbucket-pipelines.yml +39 -0
  3. package/commands/Command.js +38 -0
  4. package/commands/SetAlarmCommand.js +21 -0
  5. package/commands/SetCourtesyCommand.js +21 -0
  6. package/commands/SetDimmerCommand.js +21 -0
  7. package/commands/SetLockCommand.js +21 -0
  8. package/commands/SetSceneControllerCommand.js +21 -0
  9. package/commands/SetSwitchCommand.js +21 -0
  10. package/commands/SetThermostatCommand.js +21 -0
  11. package/commands/SetWindowCoveringCommand.js +21 -0
  12. package/commands/VerifyDocumentCommand.js +24 -0
  13. package/commands/index.js +21 -0
  14. package/defs/deviceTypes.js +15 -0
  15. package/defs/formalDeviceTypes.js +6 -0
  16. package/defs/http.js +7 -0
  17. package/defs/index.js +11 -0
  18. package/errors/AppError.js +8 -0
  19. package/errors/AuthenticationError.js +9 -0
  20. package/errors/AuthorizationError.js +9 -0
  21. package/errors/DeviceCommError.js +9 -0
  22. package/errors/LoginError.js +9 -0
  23. package/errors/NotFoundError.js +9 -0
  24. package/errors/RequestError.js +9 -0
  25. package/errors/SystemCommError.js +9 -0
  26. package/errors/TokenExpiredError.js +9 -0
  27. package/errors/UnprocessableRequestError.js +9 -0
  28. package/errors/ValidationError.js +9 -0
  29. package/errors/index.js +15 -0
  30. package/events/Event.js +33 -0
  31. package/events/SystemCameraUpdatedEvent.js +17 -0
  32. package/events/SystemCourtesyUpdatedEvent.js +17 -0
  33. package/events/SystemDimmerUpdatedEvent.js +17 -0
  34. package/events/SystemLockUpdatedEvent.js +17 -0
  35. package/events/SystemReservationUpdatedEvent.js +17 -0
  36. package/events/SystemSceneControllerUpdatedEvent.js +17 -0
  37. package/events/SystemSourceUpdatedEvent.js +17 -0
  38. package/events/SystemSpaceUpdatedEvent.js +17 -0
  39. package/events/SystemSwitchUpdatedEvent.js +17 -0
  40. package/events/SystemThermostatUpdatedEvent.js +17 -0
  41. package/events/SystemUserUpdatedEvent.js +17 -0
  42. package/events/SystemWindowCoveringUpdatedEvent.js +17 -0
  43. package/events/index.js +28 -0
  44. package/http/handleResponseError.js +53 -0
  45. package/http/handleResponseSuccess.js +15 -0
  46. package/http/index.js +159 -0
  47. package/index.js +21 -71
  48. package/models/acl.js +29 -0
  49. package/models/admin/customer.js +28 -0
  50. package/models/admin/property.js +28 -0
  51. package/models/alarm.js +29 -0
  52. package/models/application.js +28 -0
  53. package/models/camera.js +29 -0
  54. package/models/courtesy.js +33 -0
  55. package/models/dimmer.js +49 -0
  56. package/models/discoveredDevice.js +30 -0
  57. package/models/gateway.js +37 -0
  58. package/models/index.js +56 -0
  59. package/models/integration.js +76 -0
  60. package/models/iotGateway.js +29 -0
  61. package/models/kohost.js +95 -0
  62. package/models/lock.js +33 -0
  63. package/models/mediaSource.js +29 -0
  64. package/models/motionSensor.js +29 -0
  65. package/models/reservation.js +36 -0
  66. package/models/room.js +185 -0
  67. package/models/scene.js +28 -0
  68. package/models/sceneController.js +29 -0
  69. package/models/space.js +99 -0
  70. package/models/switch.js +33 -0
  71. package/models/thermostat.js +80 -0
  72. package/models/ticket.js +91 -0
  73. package/models/user.js +58 -0
  74. package/models/windowCovering.js +49 -0
  75. package/package.json +27 -5
  76. package/prepare.js +4 -0
  77. package/schemas/acl.json +111 -0
  78. package/schemas/admin/customer.json +32 -0
  79. package/schemas/admin/property.json +54 -0
  80. package/schemas/alarm.json +5 -5
  81. package/schemas/application.json +24 -0
  82. package/schemas/camera.json +41 -0
  83. package/schemas/courtesy.json +5 -6
  84. package/schemas/definitions/common.json +21 -0
  85. package/schemas/{device.json → definitions/device.json} +22 -4
  86. package/schemas/dimmer.json +8 -5
  87. package/schemas/discoveredDevice.json +43 -0
  88. package/schemas/gateway.json +45 -13
  89. package/schemas/identification.json +35 -0
  90. package/schemas/integration.json +94 -0
  91. package/schemas/iotGateway.json +29 -0
  92. package/schemas/lock.json +8 -5
  93. package/schemas/mediaSource.json +151 -0
  94. package/schemas/motionSensor.json +26 -0
  95. package/schemas/payment.json +38 -0
  96. package/schemas/reservation.json +66 -0
  97. package/schemas/room.json +138 -0
  98. package/schemas/scene.json +118 -0
  99. package/schemas/sceneController.json +18 -6
  100. package/schemas/space.json +111 -0
  101. package/schemas/switch.json +8 -5
  102. package/schemas/thermostat.json +19 -10
  103. package/schemas/ticket.json +82 -0
  104. package/schemas/user.json +124 -0
  105. package/schemas/windowCovering.json +8 -5
  106. package/tests/unit/models/space.test.js +31 -0
  107. package/tests/unit/models/thermostat.test.js +146 -0
  108. package/useCases/http.json +902 -0
  109. package/utils/getDeviceTypes.js +7 -0
  110. package/utils/getFormalDeviceType.js +5 -0
  111. package/utils/schema.js +28 -0
@@ -0,0 +1,99 @@
1
+ // Create the Space Model
2
+ // A group of rooms -> rooms could become a space later...
3
+ const schemas = require("../utils/schema");
4
+ const schema = require("../schemas/space.json");
5
+ const Kohost = require("./kohost");
6
+ const cloneDeep = require("lodash.clonedeep");
7
+
8
+ const Room = require("./room");
9
+
10
+ schemas.add(schema);
11
+ const validator = schemas.compile(schema);
12
+
13
+ class Space extends Kohost {
14
+ constructor(data) {
15
+ const spaceData = mapSpaceData(data);
16
+ super(spaceData);
17
+ }
18
+
19
+ get floor() {
20
+ const floors = new Set();
21
+
22
+ this.room.forEach((room) => {
23
+ if (room.floor) floors.add(room.floor);
24
+ });
25
+
26
+ return floors.size == 1 ? [...floors][0] : undefined;
27
+ }
28
+
29
+ get hasDimmer() {
30
+ return this.rooms.some((room) => room.hasDimmer);
31
+ }
32
+
33
+ get hasSwitch() {
34
+ return this.rooms.some((room) => room.hasSwitch);
35
+ }
36
+
37
+ get hasWindowCovering() {
38
+ return this.rooms.some((room) => room.hasWindowCovering);
39
+ }
40
+
41
+ get hasThermostat() {
42
+ return this.rooms.some((room) => room.hasThermostat);
43
+ }
44
+
45
+ get hasLock() {
46
+ return this.rooms.some((room) => room.hasLock);
47
+ }
48
+
49
+ get hasCourtesy() {
50
+ return this.rooms.some((room) => room.hasCourtesy);
51
+ }
52
+
53
+ get hasSceneController() {
54
+ return this.rooms.some((room) => room.hasSceneController);
55
+ }
56
+
57
+ get hasCamera() {
58
+ return this.rooms.some((room) => room.hasCamera);
59
+ }
60
+
61
+ get hasAlarm() {
62
+ return this.rooms.some((room) => room.hasAlarm);
63
+ }
64
+
65
+ get hasMedia() {
66
+ return this.rooms.some((room) => room.hasMedia);
67
+ }
68
+ get occupied() {
69
+ return this.rooms.some((room) => room.occupied);
70
+ }
71
+ }
72
+
73
+ Object.defineProperty(Space.prototype, "schema", {
74
+ value: schema,
75
+ });
76
+
77
+ Object.defineProperty(Space.prototype, "validator", {
78
+ get: function () {
79
+ return validator;
80
+ },
81
+ });
82
+
83
+ Object.defineProperty(Space, "validProperties", {
84
+ value: Object.keys(schema.properties),
85
+ });
86
+
87
+ function mapSpaceData(data) {
88
+ const spaceData = cloneDeep(data);
89
+ if (spaceData.rooms?.length) {
90
+ spaceData.rooms.map((room) => {
91
+ if (typeof room === "string") return room;
92
+ if (room instanceof Room) return room;
93
+ return new Room(room);
94
+ });
95
+ }
96
+ return spaceData;
97
+ }
98
+
99
+ module.exports = Space;
@@ -0,0 +1,33 @@
1
+ // create the Switch model
2
+ const schemas = require("../utils/schema");
3
+ const schema = require("../schemas/switch.json");
4
+ const Kohost = require("./kohost");
5
+
6
+ schemas.add(schema);
7
+ const validator = schemas.compile(schema);
8
+
9
+ class Switch extends Kohost {
10
+ constructor(data) {
11
+ super(data);
12
+ }
13
+ }
14
+
15
+ Object.defineProperty(Switch.prototype, "schema", {
16
+ value: schema,
17
+ });
18
+
19
+ Object.defineProperty(Switch.prototype, "validator", {
20
+ get: function () {
21
+ return validator;
22
+ },
23
+ });
24
+
25
+ Object.defineProperty(Switch, "validProperties", {
26
+ value: Object.keys(schema.properties),
27
+ });
28
+
29
+ Object.defineProperty(Switch, "actionProperties", {
30
+ value: ["state"],
31
+ });
32
+
33
+ module.exports = Switch;
@@ -0,0 +1,80 @@
1
+ const schemas = require("../utils/schema");
2
+ const schema = require("../schemas/thermostat.json");
3
+ const Kohost = require("./kohost");
4
+
5
+ schemas.add(schema);
6
+ const validator = schemas.compile(schema);
7
+
8
+ class Thermostat extends Kohost {
9
+ constructor(data) {
10
+ super(data);
11
+ }
12
+
13
+ toCelsius() {
14
+ if (this.temperatureScale === "farenheit")
15
+ this.currentTemperature = ((this.currentTemperature - 32) * 5) / 9;
16
+ this.temperatureScale = "celsius";
17
+ return this.currentTemperature;
18
+ }
19
+
20
+ toFarenheit() {
21
+ if (this.temperatureScale === "celsius")
22
+ this.currentTemperature = (this.currentTemperature * 9) / 5 + 32;
23
+ this.temperatureScale = "farenheit";
24
+ return this.currentTemperature;
25
+ }
26
+
27
+ static getActionDelta(old, _new) {
28
+ const delta = {};
29
+ for (const action in _new) {
30
+ if (this.actionProperties.includes(action)) {
31
+ switch (action) {
32
+ case "hvacMode":
33
+ case "fanMode": {
34
+ if (old[action] !== _new[action]) delta[action] = 1;
35
+ break;
36
+ }
37
+ case "setpoints": {
38
+ const setpoints = _new[action];
39
+ for (const setpoint in setpoints) {
40
+ if (old[action][setpoint].value !== setpoints[setpoint].value) {
41
+ const min =
42
+ setpoints[setpoint].min || old[action][setpoint].min;
43
+ const max =
44
+ setpoints[setpoint].max || old[action][setpoint].max;
45
+ const oldValue = old[action][setpoint].value;
46
+ const value = setpoints[setpoint].value;
47
+ // get percentage change relative to min and max
48
+ const percentChange = (value - oldValue) / (max - min);
49
+ // get the delta
50
+ delta[`setpoints.${setpoint}`] = percentChange;
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ return delta;
59
+ }
60
+ }
61
+
62
+ Object.defineProperty(Thermostat.prototype, "schema", {
63
+ value: schema,
64
+ });
65
+
66
+ Object.defineProperty(Thermostat.prototype, "validator", {
67
+ get: function () {
68
+ return validator;
69
+ },
70
+ });
71
+
72
+ Object.defineProperty(Thermostat, "validProperties", {
73
+ value: Object.keys(schema.properties),
74
+ });
75
+
76
+ Object.defineProperty(Thermostat, "actionProperties", {
77
+ value: ["hvacMode", "fanMode", "setpoints"],
78
+ });
79
+
80
+ module.exports = Thermostat;
@@ -0,0 +1,91 @@
1
+ // Create the User Model
2
+ const schemas = require("../utils/schema");
3
+ const schema = require("../schemas/ticket.json");
4
+ const Kohost = require("./kohost");
5
+
6
+ const sortBy = require("lodash.sortby");
7
+ const findLast = require("lodash.findlast");
8
+
9
+ const { nanoid } = require("nanoid");
10
+
11
+ schemas.add(schema);
12
+ const validator = schemas.compile(schema);
13
+
14
+ class Ticket extends Kohost {
15
+ constructor(data) {
16
+ super(data);
17
+ }
18
+
19
+ static generateMessageId(len = 16) {
20
+ return nanoid(len);
21
+ }
22
+ }
23
+
24
+ Object.defineProperty(Ticket.prototype, "schema", {
25
+ value: schema,
26
+ });
27
+
28
+ Object.defineProperty(Ticket.prototype, "validator", {
29
+ get: function () {
30
+ return validator;
31
+ },
32
+ });
33
+
34
+ Object.defineProperty(Ticket, "validProperties", {
35
+ value: Object.keys(schema.properties),
36
+ });
37
+
38
+ Object.defineProperty(Ticket.prototype, "responseTime", {
39
+ get: function () {
40
+ const conversation = this.conversation;
41
+ const requester = this.requester;
42
+
43
+ if (conversation.length === 0) return 0;
44
+ const mapped = conversation.map((msg) => {
45
+ if (typeof msg.timestamp === "string")
46
+ msg.timestamp = new Date(msg.timestamp);
47
+ return msg;
48
+ });
49
+ const sorted = sortBy(mapped, ["timestamp"]);
50
+ const firstMsg = sorted.find((entry) => entry.user === requester);
51
+ const firstResponse = sorted.find((entry) => entry.user !== requester);
52
+
53
+ if (firstMsg && firstResponse) {
54
+ const firstMsgTime = firstMsg.timestamp.getTime() / 1000;
55
+ const firstResponseTime = firstResponse.timestamp.getTime() / 1000;
56
+ return firstResponseTime - firstMsgTime;
57
+ }
58
+
59
+ return 0;
60
+ },
61
+ });
62
+
63
+ Object.defineProperty(Ticket.prototype, "resolutionTime", {
64
+ get: function () {
65
+ if (this.status !== "closed") return 0;
66
+ const createdAt = this.createdAt.getTime() / 1000;
67
+ const solvedAt = this.solvedAt
68
+ ? this.solvedAt.getTime() / 1000
69
+ : this.updatedAt.getTime() / 1000;
70
+
71
+ return Math.abs(solvedAt - createdAt);
72
+ },
73
+ });
74
+
75
+ Object.defineProperty(Ticket.prototype, "lastResponder", {
76
+ get: function () {
77
+ const conversation = this.conversation;
78
+ const requester = this.requester;
79
+
80
+ const sorted = sortBy(conversation, ["timestamp"]);
81
+
82
+ const lastFromNonRequester = findLast(sorted, function (c) {
83
+ return c.user !== requester;
84
+ });
85
+
86
+ if (!lastFromNonRequester) return null;
87
+ else return lastFromNonRequester.user;
88
+ },
89
+ });
90
+
91
+ module.exports = Ticket;
package/models/user.js ADDED
@@ -0,0 +1,58 @@
1
+ // Create the User Model
2
+ const schemas = require("../utils/schema");
3
+ const schema = require("../schemas/user.json");
4
+ const idSchema = require("../schemas/identification.json");
5
+ const paymentSchema = require("../schemas/payment.json");
6
+ const Kohost = require("./kohost");
7
+
8
+ const { nanoid } = require("nanoid/async");
9
+
10
+ schemas.add(idSchema);
11
+ schemas.add(paymentSchema);
12
+ schemas.add(schema);
13
+
14
+ const validator = schemas.compile(schema);
15
+
16
+ class User extends Kohost {
17
+ constructor(data) {
18
+ super(data);
19
+ }
20
+
21
+ static validatePhone(phoneNumber) {
22
+ const regex = /^\+?[1-9]\d{1,14}$/;
23
+ return regex.test(phoneNumber);
24
+ }
25
+
26
+ static validateEmail(email) {
27
+ //eslint-disable-next-line no-useless-escape
28
+ const regex =
29
+ /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
30
+ return regex.test(email);
31
+ }
32
+
33
+ static async generatePassword(len = 16) {
34
+ return await nanoid(len);
35
+ }
36
+ }
37
+
38
+ Object.defineProperty(User.prototype, "schema", {
39
+ value: schema,
40
+ });
41
+
42
+ Object.defineProperty(User.prototype, "validator", {
43
+ get: function () {
44
+ return validator;
45
+ },
46
+ });
47
+
48
+ Object.defineProperty(User, "validProperties", {
49
+ value: Object.keys(schema.properties),
50
+ });
51
+
52
+ Object.defineProperty(User.prototype, "fullName", {
53
+ get: function () {
54
+ return `${this.firstName} ${this.lastName}`;
55
+ },
56
+ });
57
+
58
+ module.exports = User;
@@ -0,0 +1,49 @@
1
+ // Create the WindowCovering Model
2
+ const schemas = require("../utils/schema");
3
+ const schema = require("../schemas/windowCovering.json");
4
+ const Kohost = require("./kohost");
5
+
6
+ schemas.add(schema);
7
+ const validator = schemas.compile(schema);
8
+
9
+ class WindowCovering extends Kohost {
10
+ constructor(data) {
11
+ super(data);
12
+ }
13
+
14
+ static getActionDelta(old, _new) {
15
+ const delta = {};
16
+ for (const action in _new) {
17
+ if (this.actionProperties?.includes(action)) {
18
+ if (action === "position") {
19
+ const oldPos = old[action];
20
+ const newPos = _new[action];
21
+ delta[action] = newPos - oldPos / 100;
22
+ } else if (old[action] !== _new[action]) {
23
+ delta[action] = 1;
24
+ }
25
+ }
26
+ }
27
+ return delta;
28
+ }
29
+ }
30
+
31
+ Object.defineProperty(WindowCovering.prototype, "schema", {
32
+ value: schema,
33
+ });
34
+
35
+ Object.defineProperty(WindowCovering.prototype, "validator", {
36
+ get: function () {
37
+ return validator;
38
+ },
39
+ });
40
+
41
+ Object.defineProperty(WindowCovering, "validProperties", {
42
+ value: Object.keys(schema.properties),
43
+ });
44
+
45
+ Object.defineProperty(WindowCovering, "actionProperties", {
46
+ value: ["position"],
47
+ });
48
+
49
+ module.exports = WindowCovering;
package/package.json CHANGED
@@ -1,15 +1,37 @@
1
1
  {
2
2
  "dependencies": {
3
- "ajv": "^8.11.0"
3
+ "ajv": "^8.11.0",
4
+ "ajv-formats": "^2.1.1",
5
+ "axios": "^1.0.0",
6
+ "lodash.clonedeep": "^4.5.0",
7
+ "lodash.findlast": "^4.6.0",
8
+ "lodash.sortby": "^4.7.0",
9
+ "nanoid": "^3.3.4"
4
10
  },
5
11
  "name": "@kohost/api-client",
6
- "version": "1.0.0-alpha.1",
12
+ "version": "1.0.0-alpha.3",
7
13
  "description": "API client for Kohost utils",
8
14
  "main": "index.js",
9
- "devDependencies": {},
10
15
  "scripts": {
11
- "test": "echo \"Error: no test specified\" && exit 1"
16
+ "test": "jest",
17
+ "test:watch": "jest --watchAll",
18
+ "lint": "eslint ./",
19
+ "lint:fix": "eslint --fix ./",
20
+ "prepare": "node prepare.js"
12
21
  },
13
22
  "author": "Ian Rogers",
14
- "license": "ISC"
23
+ "license": "ISC",
24
+ "devDependencies": {
25
+ "@kohost/eslint-config": "^1.0.0",
26
+ "eslint": "^8.6.0",
27
+ "eslint-plugin-jest": "^27.1.3",
28
+ "husky": "^8.0.1",
29
+ "jest": "^29.2.2",
30
+ "lint-staged": "^13.0.3",
31
+ "prettier": "^2.5.1"
32
+ },
33
+ "lint-staged": {
34
+ "*.js": "eslint --cache --fix",
35
+ "*.{js,css,md,json}": "prettier --write"
36
+ }
15
37
  }
package/prepare.js ADDED
@@ -0,0 +1,4 @@
1
+ const isCi = process.env.CI !== undefined;
2
+ if (!isCi) {
3
+ require("husky").install();
4
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "https://api.kohost.app/schemas/v3/acl.json",
4
+ "title": "Access Control List Schema",
5
+ "type": "object",
6
+ "required": ["id", "name", "resource", "resourceFilter", "permissions"],
7
+ "properties": {
8
+ "id": {
9
+ "type": "string"
10
+ },
11
+ "name": {
12
+ "type": "string"
13
+ },
14
+ "resourceType": {
15
+ "type": "string",
16
+ "enum": [
17
+ "*",
18
+ "Guest",
19
+ "Reservation",
20
+ "User",
21
+ "Manager",
22
+ "Admin",
23
+ "SuperAdmin",
24
+ "Ticket",
25
+ "Group",
26
+ "HotelRoom",
27
+ "Room",
28
+ "Notification",
29
+ "Image",
30
+ "EnergyReport",
31
+ "RoomType",
32
+ "SceneTemplate",
33
+ "Setting",
34
+ "Subscription",
35
+ "Integration",
36
+ "PMS",
37
+ "Source",
38
+ "ACL"
39
+ ]
40
+ },
41
+ "resource": {
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string"
45
+ }
46
+ },
47
+ "resourceFilter": {
48
+ "type": "array",
49
+ "items": {
50
+ "type": "object",
51
+ "properties": {
52
+ "resourceType": {
53
+ "type": "string",
54
+ "enum": ["SubSystem"]
55
+ },
56
+ "resource": {
57
+ "type": "array",
58
+ "items": {
59
+ "type": "string"
60
+ }
61
+ },
62
+ "permissions": {
63
+ "type": "array",
64
+ "uniqueItems": true,
65
+ "items": {
66
+ "type": "string",
67
+ "enum": [
68
+ "*",
69
+ "read",
70
+ "write",
71
+ "delete",
72
+ "create",
73
+ "update",
74
+ "list",
75
+ "execute"
76
+ ]
77
+ }
78
+ }
79
+ }
80
+ }
81
+ },
82
+ "permissions": {
83
+ "type": "array",
84
+ "uniqueItems": true,
85
+ "items": {
86
+ "type": "string",
87
+ "enum": [
88
+ "*",
89
+ "read",
90
+ "write",
91
+ "delete",
92
+ "create",
93
+ "update",
94
+ "list",
95
+ "execute"
96
+ ]
97
+ }
98
+ },
99
+ "begins": {
100
+ "type": ["object", "null"]
101
+ },
102
+ "expires": {
103
+ "type": ["object", "null"]
104
+ },
105
+ "global": {
106
+ "type": "boolean",
107
+ "default": false
108
+ }
109
+ },
110
+ "definitions": {}
111
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "https://api.kohost.app/schemas/v3/admin/customer.json",
4
+ "title": "Customer",
5
+ "type": "object",
6
+ "description": "A Kohost customer",
7
+ "required": ["accountNumber", "name"],
8
+ "properties": {
9
+ "id": {
10
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/common.json#/definitions/id"
11
+ },
12
+ "accountNumber": {
13
+ "type": "number",
14
+ "minimum": 10000
15
+ },
16
+ "name": {
17
+ "type": "string"
18
+ },
19
+ "properties": {
20
+ "type": "array",
21
+ "items": {
22
+ "type": "string"
23
+ }
24
+ },
25
+ "createdAt": {
26
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/common.json#/definitions/createdAt"
27
+ },
28
+ "updatedAt": {
29
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/common.json#/definitions/updatedAt"
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "https://api.kohost.app/schemas/v3/admin/property.json",
4
+ "title": "Property",
5
+ "type": "object",
6
+ "description": "A property is a physical asset or building",
7
+ "required": ["id", "name", "type"],
8
+ "properties": {
9
+ "id": {
10
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/common.json#/definitions/id"
11
+ },
12
+ "name": {
13
+ "type": "string"
14
+ },
15
+ "type": {
16
+ "type": "string",
17
+ "enum": ["hospitality", "education", "commercial"]
18
+ },
19
+ "timezone": {
20
+ "type": "string"
21
+ },
22
+ "address": {
23
+ "type": "object",
24
+ "properties": {
25
+ "street": {
26
+ "type": "string"
27
+ },
28
+ "city": {
29
+ "type": "string"
30
+ },
31
+ "state": {
32
+ "type": "string"
33
+ },
34
+ "zip": {
35
+ "type": "string"
36
+ },
37
+ "country": {
38
+ "type": "string"
39
+ }
40
+ }
41
+ },
42
+ "latitude": {
43
+ "type": "number"
44
+ },
45
+ "longitude": {
46
+ "type": "number"
47
+ },
48
+ "credentials": {
49
+ "type": "object",
50
+ "additionalProperties": true
51
+ },
52
+ "additionalProperties": false
53
+ }
54
+ }
@@ -6,19 +6,19 @@
6
6
  "type": "object",
7
7
  "properties": {
8
8
  "id": {
9
- "$ref": "https://api.kohost.app/schemas/v3/device.json#/definitions/id"
9
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/device.json#/definitions/id"
10
10
  },
11
11
  "type": {
12
- "$ref": "https://api.kohost.app/schemas/v3/device.json#/definitions/type"
12
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/device.json#/definitions/type"
13
13
  },
14
14
  "systemData": {
15
- "$ref": "https://api.kohost.app/schemas/v3/device.json#/definitions/systemData"
15
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/device.json#/definitions/systemData"
16
16
  },
17
17
  "supportedNotifications": {
18
- "$ref": "https://api.kohost.app/schemas/v3/device.json#/definitions/supportedNotifications"
18
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/device.json#/definitions/supportedNotifications"
19
19
  },
20
20
  "notification": {
21
- "$ref": "https://api.kohost.app/schemas/v3/device.json#/definitions/notification"
21
+ "$ref": "https://api.kohost.app/schemas/v3/definitions/device.json#/definitions/notification"
22
22
  },
23
23
  "areas": {
24
24
  "type": "array",