@kohost/api-client 1.0.0-alpha.4 → 1.0.0-beta.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.
Files changed (57) hide show
  1. package/commands/CheckInReservationCommand.js +23 -0
  2. package/commands/DiscoverReservationsCommand.js +24 -0
  3. package/commands/DiscoverRoomsCommand.js +21 -0
  4. package/commands/DiscoverUsersCommand.js +2 -2
  5. package/commands/{VerifyDocumentCommand.js → OCRDocumentCommand.js} +4 -8
  6. package/commands/SendEmailCommand.js +24 -0
  7. package/commands/SendSMSCommand.js +21 -0
  8. package/commands/index.js +10 -4
  9. package/defs/http.js +1 -1
  10. package/events/EmailSentEvent.js +17 -0
  11. package/events/Event.js +20 -1
  12. package/events/SMSSentEvent.js +17 -0
  13. package/events/ShortLinkCreatedEvent.js +17 -0
  14. package/events/index.js +7 -0
  15. package/http/handleResponseError.js +9 -29
  16. package/http/index.js +12 -8
  17. package/models/credential.js +29 -0
  18. package/models/gateway.js +0 -8
  19. package/models/identification.js +32 -0
  20. package/models/index.js +9 -9
  21. package/models/kohost.js +4 -3
  22. package/models/product.js +30 -0
  23. package/models/reservation.js +47 -0
  24. package/models/room.js +1 -12
  25. package/models/shortLink.js +29 -0
  26. package/models/space.js +1 -1
  27. package/models/thermostat.js +3 -3
  28. package/models/user.js +0 -2
  29. package/models/windowCovering.js +1 -1
  30. package/package.json +1 -1
  31. package/schemas/admin/property.json +7 -1
  32. package/schemas/camera.json +3 -3
  33. package/schemas/courtesy.json +3 -3
  34. package/schemas/credential.json +28 -0
  35. package/schemas/definitions/common.json +53 -0
  36. package/schemas/definitions/device.json +13 -2
  37. package/schemas/dimmer.json +3 -3
  38. package/schemas/gateway.json +16 -47
  39. package/schemas/identification.json +18 -4
  40. package/schemas/lock.json +6 -3
  41. package/schemas/mediaSource.json +3 -3
  42. package/schemas/motionSensor.json +3 -3
  43. package/schemas/payment.json +3 -1
  44. package/schemas/product.json +36 -0
  45. package/schemas/reservation.json +8 -3
  46. package/schemas/room.json +1 -8
  47. package/schemas/shortLink.json +30 -0
  48. package/schemas/switch.json +3 -3
  49. package/schemas/thermostat.json +11 -10
  50. package/schemas/user.json +57 -5
  51. package/schemas/windowCovering.json +3 -3
  52. package/useCases/http.json +152 -44
  53. package/utils/schema.js +2 -2
  54. package/models/iotGateway.js +0 -29
  55. package/models/sceneController.js +0 -29
  56. package/schemas/iotGateway.json +0 -29
  57. package/schemas/sceneController.json +0 -58
@@ -0,0 +1,23 @@
1
+ const Command = require("./Command");
2
+ const RequestError = require("../errors/RequestError");
3
+
4
+ class CheckInReservationCommand extends Command {
5
+ constructor({ id }) {
6
+ if (!id) throw new RequestError("document type is required");
7
+ super({ id });
8
+ }
9
+
10
+ get name() {
11
+ return "CheckInReservation";
12
+ }
13
+
14
+ get routingKey() {
15
+ return `reservation.${this.data.id}.checkin`;
16
+ }
17
+
18
+ get replyTo() {
19
+ return "system.response.reservations";
20
+ }
21
+ }
22
+
23
+ module.exports = CheckInReservationCommand;
@@ -0,0 +1,24 @@
1
+ const { RequestError } = require("../errors");
2
+ const Command = require("./Command");
3
+
4
+ class DiscoverReservationsCommand extends Command {
5
+ constructor(options) {
6
+ if (!options) throw new RequestError("options are required");
7
+ const { id, startDate, endDate, status } = options;
8
+ super({ id, startDate, endDate, status });
9
+ }
10
+
11
+ get name() {
12
+ return "DiscoverReservations";
13
+ }
14
+
15
+ get routingKey() {
16
+ return "reservation.discover";
17
+ }
18
+
19
+ get replyTo() {
20
+ return "system.response.reservations";
21
+ }
22
+ }
23
+
24
+ module.exports = DiscoverReservationsCommand;
@@ -0,0 +1,21 @@
1
+ const Command = require("./Command");
2
+
3
+ class DiscoverRoomsCommand extends Command {
4
+ constructor({ id }) {
5
+ super({ id });
6
+ }
7
+
8
+ get name() {
9
+ return "DiscoverRooms";
10
+ }
11
+
12
+ get routingKey() {
13
+ return `rooms.${this.data.id}.get`;
14
+ }
15
+
16
+ get replyTo() {
17
+ return "system.response.users";
18
+ }
19
+ }
20
+
21
+ module.exports = DiscoverRoomsCommand;
@@ -1,6 +1,6 @@
1
1
  const Command = require("./Command");
2
2
 
3
- class SetAlarmCommand extends Command {
3
+ class DiscoverUsersCommand extends Command {
4
4
  constructor({ id }) {
5
5
  super({ id });
6
6
  }
@@ -18,4 +18,4 @@ class SetAlarmCommand extends Command {
18
18
  }
19
19
  }
20
20
 
21
- module.exports = SetAlarmCommand;
21
+ module.exports = DiscoverUsersCommand;
@@ -1,7 +1,7 @@
1
1
  const Command = require("./Command");
2
2
  const RequestError = require("../errors/RequestError");
3
3
 
4
- class VerifyDocumentCommand extends Command {
4
+ class OCRDocumentCommand extends Command {
5
5
  constructor({ type, image }) {
6
6
  if (!type) throw new RequestError("document type is required");
7
7
  if (!image) throw new RequestError("document image is required");
@@ -9,16 +9,12 @@ class VerifyDocumentCommand extends Command {
9
9
  }
10
10
 
11
11
  get name() {
12
- return "VerifyDocument";
12
+ return "OCRDocument";
13
13
  }
14
14
 
15
15
  get routingKey() {
16
- return `document.${this.data.type}.verify`;
17
- }
18
-
19
- get replyTo() {
20
- return "system.response.documents";
16
+ return `document.${this.data.type}.ocr`;
21
17
  }
22
18
  }
23
19
 
24
- module.exports = VerifyDocumentCommand;
20
+ module.exports = OCRDocumentCommand;
@@ -0,0 +1,24 @@
1
+ const Command = require("./Command");
2
+ const RequestError = require("../errors/RequestError");
3
+
4
+ class SendEmailCommand extends Command {
5
+ constructor({ text, html, to, from, subject, eventData }) {
6
+ if (!to) throw new RequestError("email to is required");
7
+ if (!from) throw new RequestError("email from is required");
8
+ if (!subject) throw new RequestError("email subject is required");
9
+ if (!text && !html)
10
+ throw new RequestError("email text or html is required");
11
+
12
+ super({ text, html, to, from, subject, eventData });
13
+ }
14
+
15
+ get name() {
16
+ return "SendEmail";
17
+ }
18
+
19
+ get routingKey() {
20
+ return "comm.email.send";
21
+ }
22
+ }
23
+
24
+ module.exports = SendEmailCommand;
@@ -0,0 +1,21 @@
1
+ const Command = require("./Command");
2
+ const RequestError = require("../errors/RequestError");
3
+
4
+ class SendSMSCommand extends Command {
5
+ constructor({ body, to, from, metaData }) {
6
+ if (!body) throw new RequestError("sms body is required");
7
+ if (!to) throw new RequestError("sms to is required");
8
+ if (!from) throw new RequestError("sms from is required");
9
+ super({ body, to, from, metaData });
10
+ }
11
+
12
+ get name() {
13
+ return "SendSMS";
14
+ }
15
+
16
+ get routingKey() {
17
+ return "comm.sms.send";
18
+ }
19
+ }
20
+
21
+ module.exports = SendSMSCommand;
package/commands/index.js CHANGED
@@ -6,10 +6,12 @@ const SetLockCommand = require("./SetLockCommand");
6
6
  const SetSceneControllerCommand = require("./SetSceneControllerCommand");
7
7
  const SetWindowCoveringCommand = require("./SetWindowCoveringCommand");
8
8
  const SetCourtesyCommand = require("./SetCourtesyCommand");
9
-
10
9
  const DiscoverUsersCommand = require("./DiscoverUsersCommand");
11
-
12
- const VerifyDocumentCommand = require("./VerifyDocumentCommand");
10
+ const OCRDocumentCommand = require("./OCRDocumentCommand");
11
+ const CheckInReservationCommand = require("./CheckInReservationCommand");
12
+ const SendSMSCommand = require("./SendSMSCommand");
13
+ const DiscoverReservationsCommand = require("./DiscoverReservationsCommand");
14
+ const DiscoverRoomsCommand = require("./DiscoverRoomsCommand");
13
15
 
14
16
  module.exports = {
15
17
  SetAlarmCommand,
@@ -20,6 +22,10 @@ module.exports = {
20
22
  SetSceneControllerCommand,
21
23
  SetWindowCoveringCommand,
22
24
  SetCourtesyCommand,
23
- VerifyDocumentCommand,
25
+ OCRDocumentCommand,
24
26
  DiscoverUsersCommand,
27
+ CheckInReservationCommand,
28
+ SendSMSCommand,
29
+ DiscoverReservationsCommand,
30
+ DiscoverRoomsCommand,
25
31
  };
package/defs/http.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const http = {
2
2
  authTokenHeader: "X-Auth-Token",
3
3
  refreshTokenHeader: "X-Refresh-Token",
4
- tenantHeader: "X-Tenant-Id",
4
+ propertyHeader: "X-Property-Id",
5
5
  };
6
6
 
7
7
  module.exports = http;
@@ -0,0 +1,17 @@
1
+ const Event = require("./Event");
2
+
3
+ class EmailSentEvent extends Event {
4
+ constructor(email, context) {
5
+ super(email, context);
6
+ }
7
+
8
+ get name() {
9
+ return "EmailSent";
10
+ }
11
+
12
+ get routingKey() {
13
+ return "comm.email.sent";
14
+ }
15
+ }
16
+
17
+ module.exports = EmailSentEvent;
package/events/Event.js CHANGED
@@ -1,13 +1,32 @@
1
1
  class Event {
2
- constructor(data) {
2
+ constructor(data, context) {
3
3
  this.data = {};
4
+ this.context = {};
4
5
  if (!data) throw new Error("Event data is required");
5
6
  if (typeof data !== "object")
6
7
  throw new Error("Event data must be an object");
7
8
 
9
+ if (!data.name) this.data.name = this.name;
10
+ if (!data.type) this.data.type = this.type;
11
+
8
12
  for (const key in data) {
9
13
  this.data[key] = data[key];
10
14
  }
15
+
16
+ if (data.eventData) {
17
+ for (const key in data.eventData) {
18
+ this.data[key] = data.eventData[key];
19
+ }
20
+ delete this.data.eventData;
21
+ }
22
+
23
+ if (context) {
24
+ for (const key in context) {
25
+ this.context[key] = context[key];
26
+ }
27
+ }
28
+
29
+ if (!this.data.timestamp) this.data.timestamp = new Date();
11
30
  }
12
31
  get name() {
13
32
  throw new Error("Event name is required");
@@ -0,0 +1,17 @@
1
+ const Event = require("./Event");
2
+
3
+ class SMSSentEvent extends Event {
4
+ constructor(email, context) {
5
+ super(email, context);
6
+ }
7
+
8
+ get name() {
9
+ return "SMSSent";
10
+ }
11
+
12
+ get routingKey() {
13
+ return "comm.sms.sent";
14
+ }
15
+ }
16
+
17
+ module.exports = SMSSentEvent;
@@ -0,0 +1,17 @@
1
+ const Event = require("./Event");
2
+
3
+ class ShortLinkCreatedEvent extends Event {
4
+ constructor(shortLink, context) {
5
+ super(shortLink, context);
6
+ }
7
+
8
+ get name() {
9
+ return "ShortLinkCreated";
10
+ }
11
+
12
+ get routingKey() {
13
+ return `shortlink.${this.data.id}.created`;
14
+ }
15
+ }
16
+
17
+ module.exports = ShortLinkCreatedEvent;
package/events/index.js CHANGED
@@ -12,6 +12,10 @@ const SystemUserUpdatedEvent = require("./SystemUserUpdatedEvent");
12
12
  const SystemSpaceUpdatedEvent = require("./SystemSpaceUpdatedEvent");
13
13
  const SystemReservationUpdatedEvent = require("./SystemReservationUpdatedEvent");
14
14
 
15
+ const SMSSentEvent = require("./SMSSentEvent");
16
+ const EmailSentEvent = require("./EmailSentEvent");
17
+ const ShortLinkCreatedEvent = require("./ShortLinkCreatedEvent");
18
+
15
19
  module.exports = {
16
20
  SystemThermostatUpdatedEvent,
17
21
  SystemDimmerUpdatedEvent,
@@ -25,4 +29,7 @@ module.exports = {
25
29
  SystemUserUpdatedEvent,
26
30
  SystemSpaceUpdatedEvent,
27
31
  SystemReservationUpdatedEvent,
32
+ SMSSentEvent,
33
+ EmailSentEvent,
34
+ ShortLinkCreatedEvent,
28
35
  };
@@ -1,48 +1,28 @@
1
- const defs = require("../defs").http;
2
-
3
1
  module.exports = function handleResponseError(error) {
4
2
  const { config: originalReq } = error;
5
3
  if (!error.response) return Promise.reject(error);
6
4
  const { status, data } = error.response;
7
- const errorCode = data && data.error && data.error.code;
8
- const errorMessage = data && data.error && data.error.message;
5
+ const errorType = data?.error?.type;
6
+ const errorMessage = data?.error?.message;
9
7
 
10
8
  try {
11
9
  const expectedError = status >= 400 && status < 500;
10
+ const newTokensNeeded = expectedError && errorType === "TokenExpiredError";
12
11
 
13
- if (errorMessage && errorMessage === "Login Required") {
12
+ if (expectedError && errorMessage === "Login Required") {
14
13
  this.onLoginRequired();
15
14
  return Promise.reject(error);
16
15
  }
17
16
 
18
- // prettier-ignore
19
- const newTokensNeeded = expectedError && errorCode === 1004 && status === 401;
20
-
21
- if (status === 401 && !newTokensNeeded) {
22
- return Promise.reject(error);
23
- }
24
- if (status === 400 && errorCode === 1010) {
17
+ if (expectedError && errorMessage === "No token provided") {
25
18
  this.onLoginRequired();
26
19
  return Promise.reject(error);
27
20
  }
28
21
 
29
- if (newTokensNeeded) {
30
- return this.RefreshToken({
31
- headers: {
32
- [defs.refreshTokenHeader]: this.refreshToken,
33
- },
34
- }).then((response) => {
35
- // update headers with the new tokens
36
- if (
37
- response &&
38
- response.headers &&
39
- response.headers[this.authTokenHeaderKey]
40
- ) {
41
- const newToken = response.headers[this.authTokenHeaderKey];
42
- originalReq.headers[defs.authTokenHeader] = newToken;
43
- this.authToken = newToken;
44
- return this.http(originalReq);
45
- }
22
+ if (expectedError && newTokensNeeded) {
23
+ return this.RefreshToken().then(() => {
24
+ // retry the original request with the new token
25
+ return this.http(originalReq);
46
26
  });
47
27
  }
48
28
  } catch (error) {
package/http/index.js CHANGED
@@ -43,14 +43,14 @@ function useCaseMethodFactory(Client) {
43
43
  // get parameters from path
44
44
  const pathParams = path.match(/:[a-zA-Z0-9]+/g);
45
45
 
46
- const { data, params, query, headers } = requestData;
46
+ const { data, query, headers } = requestData;
47
47
 
48
48
  // replace path parameters with values from params
49
49
  let url = path;
50
- if (pathParams && params) {
50
+ if (pathParams && data) {
51
51
  for (const param of pathParams) {
52
52
  const paramName = param.replace(":", "");
53
- url = url.replace(param, params[paramName]);
53
+ url = url.replace(param, data[paramName]);
54
54
  }
55
55
  }
56
56
 
@@ -85,7 +85,7 @@ function useCaseMethodFactory(Client) {
85
85
  class KohostApiClient extends EventEmitter {
86
86
  /*
87
87
  @param {Object} options - The options to create the client
88
- @param {String} options.tenantId - The tenant ID
88
+ @param {String} options.propertyId - The property ID
89
89
  @param {String} options.url - The base URL for the API endpint
90
90
  @param {Object} options.headers - Additional headers to send with each request
91
91
 
@@ -93,13 +93,13 @@ class KohostApiClient extends EventEmitter {
93
93
  constructor(
94
94
  options = {
95
95
  url: "",
96
- tenantId: "",
96
+ propertyId: "",
97
97
  headers: {},
98
98
  }
99
99
  ) {
100
100
  super();
101
101
  if (!options.url) throw new Error("options.url is required");
102
- if (!options.tenantId) throw new Error("options.tenant is required");
102
+ if (!options.propertyId) throw new Error("options.property is required");
103
103
  this.options = options;
104
104
  // eslint-disable-next-line no-undef
105
105
  this.isBrowser = typeof window !== "undefined";
@@ -114,7 +114,7 @@ class KohostApiClient extends EventEmitter {
114
114
  headers: {
115
115
  "Content-Type": "application/json",
116
116
  Accept: "application/json",
117
- [defs.tenantHeader]: options.tenantId,
117
+ [defs.propertyHeader]: options.propertyId,
118
118
  ...options.headers,
119
119
  },
120
120
  });
@@ -143,7 +143,7 @@ class KohostApiClient extends EventEmitter {
143
143
  }
144
144
 
145
145
  get lsTokenKey() {
146
- return `${this.options.tenantId}_${defs.authTokenHeader}`;
146
+ return `${this.options.propertyId}_${defs.authTokenHeader}`;
147
147
  }
148
148
 
149
149
  get authToken() {
@@ -158,6 +158,10 @@ class KohostApiClient extends EventEmitter {
158
158
  set authToken(token) {
159
159
  this._authToken = token;
160
160
  }
161
+
162
+ onLoginRequired() {
163
+ this.emit("LoginRequired");
164
+ }
161
165
  }
162
166
 
163
167
  useCaseMethodFactory(KohostApiClient);
@@ -0,0 +1,29 @@
1
+ // create the Credential Model
2
+ const schemas = require("../utils/schema");
3
+ const schema = require("../schemas/credential.json");
4
+ const Kohost = require("./kohost");
5
+
6
+ schemas.add(schema);
7
+ const validator = schemas.compile(schema);
8
+
9
+ class Credential extends Kohost {
10
+ constructor(data) {
11
+ super(data);
12
+ }
13
+ }
14
+
15
+ Object.defineProperty(Credential.prototype, "schema", {
16
+ value: schema,
17
+ });
18
+
19
+ Object.defineProperty(Credential.prototype, "validator", {
20
+ get: function () {
21
+ return validator;
22
+ },
23
+ });
24
+
25
+ Object.defineProperty(Credential, "validProperties", {
26
+ value: Object.keys(schema.properties),
27
+ });
28
+
29
+ module.exports = Credential;
package/models/gateway.js CHANGED
@@ -6,18 +6,10 @@ const Kohost = require("./kohost");
6
6
  schemas.add(schema);
7
7
  const validator = schemas.compile(schema);
8
8
 
9
- const { customAlphabet } = require("nanoid/async");
10
- const characters =
11
- "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
12
-
13
9
  class Gateway extends Kohost {
14
10
  constructor(data) {
15
11
  super(data);
16
12
  }
17
-
18
- static async generateAuthKey(length = 64) {
19
- return await customAlphabet(characters, length)();
20
- }
21
13
  }
22
14
 
23
15
  Object.defineProperty(Gateway.prototype, "schema", {
@@ -0,0 +1,32 @@
1
+ const schemas = require("../utils/schema");
2
+ const schema = require("../schemas/identification.json");
3
+ const Kohost = require("./kohost");
4
+
5
+ schemas.add(schema);
6
+ const validator = schemas.compile(schema);
7
+
8
+ class Identification extends Kohost {
9
+ constructor(data) {
10
+ super(data);
11
+ }
12
+
13
+ get isExpired() {
14
+ return new Date(this.expirationDate) < new Date();
15
+ }
16
+ }
17
+
18
+ Object.defineProperty(Identification.prototype, "schema", {
19
+ value: schema,
20
+ });
21
+
22
+ Object.defineProperty(Identification.prototype, "validator", {
23
+ get: function () {
24
+ return validator;
25
+ },
26
+ });
27
+
28
+ Object.defineProperty(Identification, "validProperties", {
29
+ value: Object.keys(schema.properties),
30
+ });
31
+
32
+ module.exports = Identification;
package/models/index.js CHANGED
@@ -1,13 +1,11 @@
1
- const IotGateway = require("./iotGateway");
2
1
  const Switch = require("./switch");
3
2
  const Alarm = require("./alarm");
4
3
  const Dimmer = require("./dimmer");
5
4
  const Lock = require("./lock");
6
- const SceneController = require("./sceneController");
7
5
  const Thermostat = require("./thermostat");
8
6
  const WindowCovering = require("./windowCovering");
7
+ const Identification = require("./identification");
9
8
  const User = require("./user");
10
- const ACL = require("./acl");
11
9
  const Courtesy = require("./courtesy");
12
10
  const Camera = require("./camera");
13
11
  const MotionSensor = require("./motionSensor");
@@ -18,9 +16,11 @@ const Application = require("./application");
18
16
  const Space = require("./space");
19
17
  const Ticket = require("./ticket");
20
18
  const Scene = require("./scene");
21
- const Integration = require("./integration");
22
19
  const Gateway = require("./gateway");
20
+ const Product = require("./product");
23
21
  const DiscoveredDevice = require("./discoveredDevice");
22
+ const Credential = require("./credential");
23
+ const ShortLink = require("./shortLink");
24
24
 
25
25
  const AdminCustomer = require("./admin/customer");
26
26
  const AdminProperty = require("./admin/property");
@@ -31,26 +31,26 @@ module.exports = {
31
31
  Property: AdminProperty,
32
32
  },
33
33
  Gateway,
34
- IotGateway,
35
34
  Switch,
36
35
  Alarm,
37
36
  Dimmer,
38
37
  Lock,
39
38
  Courtesy,
40
39
  Camera,
41
- SceneController,
42
40
  MotionSensor,
43
41
  Thermostat,
44
42
  WindowCovering,
45
43
  MediaSource,
44
+ Identification,
45
+ Product,
46
46
  User,
47
- ACL,
48
47
  Room,
49
- Application,
48
+ Application,
50
49
  Space,
51
50
  Ticket,
52
51
  Scene,
53
- Integration,
54
52
  DiscoveredDevice,
55
53
  Reservation,
54
+ Credential,
55
+ ShortLink,
56
56
  };
package/models/kohost.js CHANGED
@@ -54,10 +54,11 @@ class Kohost {
54
54
 
55
55
  _validate(data) {
56
56
  const valid = this.validator(data);
57
- if (!valid)
57
+ if (!valid) {
58
58
  throw new ValidationError(`Invalid ${this.constructor.name}`, {
59
- cause: this.validator.errors,
60
- });
59
+ cause: this.validator.errors,
60
+ }); }
61
+
61
62
  }
62
63
 
63
64
  static generateId() {
@@ -0,0 +1,30 @@
1
+ // Create the Product Model
2
+ const schemas = require("../utils/schema");
3
+ const schema = require("../schemas/product.json");
4
+ const Kohost = require("./kohost");
5
+
6
+ schemas.add(schema);
7
+ const validator = schemas.compile(schema);
8
+
9
+ class Product extends Kohost {
10
+ constructor(data) {
11
+ super(data);
12
+ }
13
+ }
14
+
15
+ Object.defineProperty(Product.prototype, "schema", {
16
+ value: schema,
17
+ });
18
+
19
+ Object.defineProperty(Product.prototype, "validator", {
20
+ get: function () {
21
+ return validator;
22
+ },
23
+ });
24
+
25
+ Object.defineProperty(Product, "validProperties", {
26
+ value: Object.keys(schema.properties),
27
+ });
28
+
29
+
30
+ module.exports = Product;
@@ -17,6 +17,53 @@ class Reservation extends Kohost {
17
17
  get hasPayment() {
18
18
  return this.paymentId?.length > 0;
19
19
  }
20
+
21
+ range(tz) {
22
+ const start = new Date(this.checkInDateTime);
23
+ const end = new Date(this.checkOutDateTime);
24
+
25
+ // output Dec 19-23 if same month and year
26
+ if (
27
+ start.getMonth() === end.getMonth() &&
28
+ start.getFullYear() === end.getFullYear()
29
+ ) {
30
+ return `${start.toLocaleString("default", {
31
+ month: "short",
32
+ timeZone: tz,
33
+ })} ${start.toLocaleString("default", {
34
+ timeZone: tz,
35
+ day: "numeric",
36
+ })}-${end.toLocaleString("default", {
37
+ timeZone: tz,
38
+ day: "numeric",
39
+ })}`;
40
+ }
41
+
42
+ // output Dec 19 - Jan 2 if different month and year
43
+ return `${start.toLocaleString("default", {
44
+ month: "short",
45
+ timeZone: tz,
46
+ })} ${start.getDate()} - ${end.toLocaleString("default", {
47
+ month: "short",
48
+ timeZone: tz,
49
+ })} ${end.getDate()}`;
50
+ }
51
+
52
+ checkInTime(tz) {
53
+ return new Date(this.checkInDateTime).toLocaleString("default", {
54
+ hour: "numeric",
55
+ minute: "numeric",
56
+ timeZone: tz,
57
+ });
58
+ }
59
+
60
+ checkOutTime(tz) {
61
+ return new Date(this.checkOutDateTime).toLocaleString("default", {
62
+ hour: "numeric",
63
+ minute: "numeric",
64
+ timeZone: tz,
65
+ });
66
+ }
20
67
  }
21
68
 
22
69
  Object.defineProperty(Reservation.prototype, "schema", {