@lagunacreek/hogan-pms-client 0.1.2 → 0.1.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.
- package/README.md +5 -0
- package/dist/index.cjs +12 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -1
- package/dist/index.d.ts +70 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,11 @@ console.log(version()); // -> "0.1.0"
|
|
|
17
17
|
console.log(VERSION); // -> "0.1.0"
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
## Import Types
|
|
21
|
+
```ts
|
|
22
|
+
import type { WhoAmIType } from "@lagunacreek/hogan-pms-client";
|
|
23
|
+
```
|
|
24
|
+
|
|
20
25
|
Call an OTA endpoint with the internal client (constructor args: `apiKey`, `env`,
|
|
21
26
|
`version`; `env` is one of `LOCAL` | `DEV` | `TEST` | `PROD`):
|
|
22
27
|
|
package/dist/index.cjs
CHANGED
|
@@ -29,7 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
module.exports = __toCommonJS(index_exports);
|
|
30
30
|
|
|
31
31
|
// src/version.ts
|
|
32
|
-
var VERSION = true ? "0.1.
|
|
32
|
+
var VERSION = true ? "0.1.3" : "0.0.0";
|
|
33
33
|
function version() {
|
|
34
34
|
return VERSION;
|
|
35
35
|
}
|
|
@@ -222,6 +222,17 @@ var internalOta = class {
|
|
|
222
222
|
async postReservation(payload) {
|
|
223
223
|
return postRequest(`${this.baseUrl}/postReservation`, this.apiKey, payload);
|
|
224
224
|
}
|
|
225
|
+
// Replicant feed: one page of the cross-tenant property list an OTA partner
|
|
226
|
+
// caches to resell our clients' inventory. Page size is fixed server-side;
|
|
227
|
+
// walk pages by following `next_page` / `next_link` until next_page is false.
|
|
228
|
+
async getReplicant(params = {}) {
|
|
229
|
+
const query = new URLSearchParams();
|
|
230
|
+
if (params.page !== void 0) {
|
|
231
|
+
query.set("page", String(params.page));
|
|
232
|
+
}
|
|
233
|
+
const qs = query.toString();
|
|
234
|
+
return getRequest(`${this.baseUrl}/getReplicant${qs ? `?${qs}` : ""}`, this.apiKey);
|
|
235
|
+
}
|
|
225
236
|
};
|
|
226
237
|
var internal_ota_default = internalOta;
|
|
227
238
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/errors.ts","../src/resources/requests.ts","../src/internal-ota.ts"],"sourcesContent":["// Barrel export for @lagunacreek/hogan-pms-client.\n//\n// As resources, the HoganClient, auth providers and error types are added,\n// re-export them from here so consumers have a single import surface.\nexport { version, VERSION } from \"./version.js\";\nexport { default as HoganInternalOTAClient } from \"./internal-ota.js\";\nexport * from \"./types/internal-ota/whoami.js\";\nexport * from \"./types/internal-ota/org.js\";\nexport * from \"./types/internal-ota/property.js\";\nexport * from \"./types/internal-ota/property-detail.js\";\nexport * from \"./types/internal-ota/availability.js\";\nexport * from \"./types/internal-ota/amenity.js\";\nexport * from \"./types/internal-ota/room-type.js\";\nexport * from \"./types/internal-ota/room-availability.js\";\nexport * from \"./types/internal-ota/calculate-stay.js\";\nexport * from \"./types/internal-ota/reservation.js\";\nexport * from \"./types/internal-ota/make-reservation.js\";\nexport * from \"./errors.js\";","// `__PACKAGE_VERSION__` is replaced at build time by tsup's `define` (see\n// tsup.config.ts) and by vitest's `define` during tests, both sourced from\n// package.json. The fallback keeps the value sane if the package is consumed\n// in an unexpected way where the replacement did not happen.\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * The version of this package, as declared in its package.json.\n */\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ === \"string\" ? __PACKAGE_VERSION__ : \"0.0.0\";\n\n/**\n * Returns the version of the hogan-pms-client package.\n */\nexport function version(): string {\n return VERSION;\n}\n","// Error types thrown by the Hogan client. Consumers can branch on these\n// with `instanceof` instead of inspecting raw responses.\n\n/**\n * Thrown when the Hogan API responds with a non-2xx status. Carries the\n * status code and the parsed body (when available) for inspection.\n */\nexport class HoganApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly method: string;\n readonly url: string;\n /** Parsed response body, or the raw text if it was not JSON. */\n readonly body: unknown;\n\n constructor(args: {\n status: number;\n statusText: string;\n method: string;\n url: string;\n body: unknown;\n }) {\n super(\n `Hogan API ${args.method} ${args.url} failed: ${args.status} ${args.statusText}`,\n );\n this.name = \"HoganApiError\";\n this.status = args.status;\n this.statusText = args.statusText;\n this.method = args.method;\n this.url = args.url;\n this.body = args.body;\n }\n}\n\n/**\n * Thrown when the request never produced an HTTP response at all — a network\n * failure, DNS error, timeout/abort, etc.\n */\nexport class HoganNetworkError extends Error {\n readonly method: string;\n readonly url: string;\n\n constructor(args: { method: string; url: string; cause: unknown }) {\n super(`Hogan API request to ${args.method} ${args.url} failed to send`, {\n cause: args.cause,\n });\n this.name = \"HoganNetworkError\";\n this.method = args.method;\n this.url = args.url;\n }\n}\n","/**\n * @description Utility functions for making API requests to the Hogan PMS API.\n * Each verb (GET, POST, PUT, DELETE) delegates to a single `request` helper that\n * sets the auth header, reads the response body exactly once, and converts\n * failures into typed errors:\n * - non-2xx responses throw `HoganApiError` (with status + parsed body)\n * - transport failures (DNS, offline, abort/timeout) throw `HoganNetworkError`\n */\n\nimport { HoganApiError, HoganNetworkError } from \"../errors.js\";\n\n/**\n * @description Build the headers sent on every request. Auth is the OTA\n * `x-api-key` header (the API does not use a bearer token).\n * @param apiKey string\n */\nexport const requestHeaders = (apiKey: string): Record<string, string> => ({\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"x-api-key\": `${apiKey}`,\n});\n\n/**\n * @description Core request configuration for the `request` helper.\n * @param method string - HTTP verb (GET, POST, etc.)\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @body JSON-serialisable request body, body Omitted for GET/DELETE.\n */\ninterface RequestConfig {\n method: string;\n url: string;\n apiKey: string;\n body?: object;\n}\n\n/**\n * @description Read a fetch Response body a single time. Returns parsed JSON when\n * the body is JSON, the raw text when it is not, and `undefined` for empty/no\n * content (e.g. 204). Never throws on parse failure.\n */\nconst parseBody = async (response: Response): Promise<unknown> => {\n if (response.status === 204 || response.status === 205) {\n return undefined;\n }\n const text = await response.text();\n if (text === \"\") {\n return undefined;\n }\n try {\n return JSON.parse(text);\n } catch {\n // Error pages are sometimes plain text or HTML; hand back the raw text.\n return text;\n }\n};\n\n/**\n * @description Core request helper shared by every verb.\n * @returns Promise<T> - the parsed response body.\n * @throws HoganApiError when the server responds with a non-2xx status.\n * @throws HoganNetworkError when the request never reaches the server.\n */\nconst request = async <T>({\n method,\n url,\n apiKey,\n body,\n}: RequestConfig): Promise<T> => {\n const headers = requestHeaders(apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n } catch (cause) {\n throw new HoganNetworkError({ method, url, cause });\n }\n\n const parsed = await parseBody(response);\n\n if (!response.ok) {\n throw new HoganApiError({\n status: response.status,\n statusText: response.statusText,\n method,\n url,\n body: parsed,\n });\n }\n\n return parsed as T;\n};\n\n/**\n * @description Make a GET request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const getRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"GET\", url, apiKey });\n\n/**\n * @description Make a POST request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const postRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"POST\", url, apiKey, body });\n\n/**\n * @description Make a PUT request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const putRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"PUT\", url, apiKey, body });\n\n/**\n * @description Make a DELETE request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const deleteRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"DELETE\", url, apiKey });\n","\n\nimport type { WhoAmIType } from \"./types/internal-ota/whoami\";\nimport type { orgType } from \"./types/internal-ota/org\";\nimport type { propertyDetailType } from \"./types/internal-ota/property-detail\";\nimport type { availabilityType, availabilityQueryType } from \"./types/internal-ota/availability\";\nimport type { propertyAmenityType } from \"./types/internal-ota/amenity\";\nimport type { roomTypeType } from \"./types/internal-ota/room-type\";\nimport type { roomAvailabilityType, roomAvailabilityQueryType } from \"./types/internal-ota/room-availability\";\nimport type { paymentCalculationType, calculateStayQueryType } from \"./types/internal-ota/calculate-stay\";\nimport type { ReservationDetailOutput } from \"./types/internal-ota/reservation\";\nimport type { MakeReservationPayloadOTA, MakeReservationResponse } from \"./types/internal-ota/make-reservation\";\nimport { getRequest, postRequest } from \"./resources/requests\";\n\n\nconst internalOta = class {\n\n apiKey: string;\n env: string;\n version: string;\n baseUrl: string;\n\n getBaseUrl() :string {\n this.env = this.env.toUpperCase();\n switch ( this.env ) {\n case \"PROD\":\n case \"PRODUCTION\":\n return `https://production-api.lagunacreek.cloud/ota/${this.version}`;\n case \"TEST\":\n case \"TESTING\":\n return `https://testing-api.lagunacreek.net/ota/${this.version}`;\n case \"DEV\":\n case \"DEVELOPMENT\":\n return `https://development-api.lagunacreek.net/ota/${this.version}`;\n case \"LOCAL\":\n default:\n return `http://localhost:50000/ota/${this.version}`;\n }\n }\n\n\n constructor( apiKey=\"\", env=\"LOCAL\", version=\"v1\" ) {\n this.apiKey = apiKey;\n this.env = env;\n this.version = version;\n this.baseUrl = this.getBaseUrl();\n }\n\n overrideBaseUrl( baseUrl: string ) {\n this.baseUrl = baseUrl;\n }\n\n setAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\", value:string ) {\n this[`${key}`] = value;\n }\n\n getAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\" ) :string {\n return this[key];\n }\n\n\n async whoami(): Promise<WhoAmIType> {\n return getRequest<WhoAmIType>( `${this.baseUrl}/getWhoami`, this.apiKey );\n }\n\n\n async getOrg(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getOrg`, this.apiKey );\n }\n\n\n async getProperties(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getProperties`, this.apiKey );\n }\n\n\n async getPropertyDetail( id: number | string ): Promise<propertyDetailType> {\n return getRequest<propertyDetailType>( `${this.baseUrl}/getPropertyDetail/${id}`, this.apiKey );\n }\n\n\n async getAvailability( params: availabilityQueryType ): Promise<availabilityType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n number_of_guests: String( params.number_of_guests ),\n property_id: String( params.property_id ),\n });\n return getRequest<availabilityType>( `${this.baseUrl}/getAvailability?${query}`, this.apiKey );\n }\n\n\n async getPropertyAmenities( property_id: number | string ): Promise<propertyAmenityType[]> {\n return getRequest<propertyAmenityType[]>( `${this.baseUrl}/getPropertyAmenities/${property_id}`, this.apiKey );\n }\n\n\n async getRoomTypes( property_id: number | string ): Promise<roomTypeType[]> {\n const query = new URLSearchParams({ property_id: String( property_id ) });\n return getRequest<roomTypeType[]>( `${this.baseUrl}/getRoomTypes?${query}`, this.apiKey );\n }\n\n\n async getRoomAvailability( params: roomAvailabilityQueryType ): Promise<roomAvailabilityType[]> {\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n });\n // room_type_ids is a repeated query param (?room_type_ids=1&room_type_ids=2).\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<roomAvailabilityType[]>( `${this.baseUrl}/getRoomAvailability?${query}`, this.apiKey );\n }\n\n\n async getCalculateStay( params: calculateStayQueryType ): Promise<paymentCalculationType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n check_in: params.check_in,\n check_out: params.check_out,\n no_of_rooms: String( params.no_of_rooms ),\n });\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<paymentCalculationType>( `${this.baseUrl}/getCalculateStay?${query}`, this.apiKey );\n }\n\n\n // Property maps are returned as plain-text SVG markup (media_type text/plain).\n // getMaps concatenates every property's SVG; getMap returns one property's SVG,\n // or undefined when the property has no map (the server replies 204).\n async getPropertyMaps(): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMaps`, this.apiKey );\n }\n\n\n async getPropertyMap( property_id: number | string ): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMap/${property_id}`, this.apiKey );\n }\n\n\n async getReservation( reservation_id: number ): Promise<ReservationDetailOutput> {\n const query = new URLSearchParams({ reservation_id: String( reservation_id ) });\n return getRequest<ReservationDetailOutput>( `${this.baseUrl}/getReservation?${query}`, this.apiKey );\n }\n\n\n async postReservation( payload: MakeReservationPayloadOTA ): Promise<MakeReservationResponse> {\n return postRequest<MakeReservationResponse>( `${this.baseUrl}/postReservation`, this.apiKey, payload );\n }\n\n\n};\n\nexport default internalOta;"],"mappings":"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","names":["version"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/errors.ts","../src/resources/requests.ts","../src/internal-ota.ts"],"sourcesContent":["// Barrel export for @lagunacreek/hogan-pms-client.\n//\n// As resources, the HoganClient, auth providers and error types are added,\n// re-export them from here so consumers have a single import surface.\nexport { version, VERSION } from \"./version.js\";\nexport { default as HoganInternalOTAClient } from \"./internal-ota.js\";\nexport * from \"./types/internal-ota/whoami.js\";\nexport * from \"./types/internal-ota/org.js\";\nexport * from \"./types/internal-ota/property.js\";\nexport * from \"./types/internal-ota/property-detail.js\";\nexport * from \"./types/internal-ota/availability.js\";\nexport * from \"./types/internal-ota/amenity.js\";\nexport * from \"./types/internal-ota/room-type.js\";\nexport * from \"./types/internal-ota/room-availability.js\";\nexport * from \"./types/internal-ota/calculate-stay.js\";\nexport * from \"./types/internal-ota/reservation.js\";\nexport * from \"./types/internal-ota/make-reservation.js\";\nexport * from \"./types/internal-ota/replicant.js\";\nexport * from \"./errors.js\";","// `__PACKAGE_VERSION__` is replaced at build time by tsup's `define` (see\n// tsup.config.ts) and by vitest's `define` during tests, both sourced from\n// package.json. The fallback keeps the value sane if the package is consumed\n// in an unexpected way where the replacement did not happen.\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * The version of this package, as declared in its package.json.\n */\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ === \"string\" ? __PACKAGE_VERSION__ : \"0.0.0\";\n\n/**\n * Returns the version of the hogan-pms-client package.\n */\nexport function version(): string {\n return VERSION;\n}\n","// Error types thrown by the Hogan client. Consumers can branch on these\n// with `instanceof` instead of inspecting raw responses.\n\n/**\n * Thrown when the Hogan API responds with a non-2xx status. Carries the\n * status code and the parsed body (when available) for inspection.\n */\nexport class HoganApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly method: string;\n readonly url: string;\n /** Parsed response body, or the raw text if it was not JSON. */\n readonly body: unknown;\n\n constructor(args: {\n status: number;\n statusText: string;\n method: string;\n url: string;\n body: unknown;\n }) {\n super(\n `Hogan API ${args.method} ${args.url} failed: ${args.status} ${args.statusText}`,\n );\n this.name = \"HoganApiError\";\n this.status = args.status;\n this.statusText = args.statusText;\n this.method = args.method;\n this.url = args.url;\n this.body = args.body;\n }\n}\n\n/**\n * Thrown when the request never produced an HTTP response at all — a network\n * failure, DNS error, timeout/abort, etc.\n */\nexport class HoganNetworkError extends Error {\n readonly method: string;\n readonly url: string;\n\n constructor(args: { method: string; url: string; cause: unknown }) {\n super(`Hogan API request to ${args.method} ${args.url} failed to send`, {\n cause: args.cause,\n });\n this.name = \"HoganNetworkError\";\n this.method = args.method;\n this.url = args.url;\n }\n}\n","/**\n * @description Utility functions for making API requests to the Hogan PMS API.\n * Each verb (GET, POST, PUT, DELETE) delegates to a single `request` helper that\n * sets the auth header, reads the response body exactly once, and converts\n * failures into typed errors:\n * - non-2xx responses throw `HoganApiError` (with status + parsed body)\n * - transport failures (DNS, offline, abort/timeout) throw `HoganNetworkError`\n */\n\nimport { HoganApiError, HoganNetworkError } from \"../errors.js\";\n\n/**\n * @description Build the headers sent on every request. Auth is the OTA\n * `x-api-key` header (the API does not use a bearer token).\n * @param apiKey string\n */\nexport const requestHeaders = (apiKey: string): Record<string, string> => ({\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"x-api-key\": `${apiKey}`,\n});\n\n/**\n * @description Core request configuration for the `request` helper.\n * @param method string - HTTP verb (GET, POST, etc.)\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @body JSON-serialisable request body, body Omitted for GET/DELETE.\n */\ninterface RequestConfig {\n method: string;\n url: string;\n apiKey: string;\n body?: object;\n}\n\n/**\n * @description Read a fetch Response body a single time. Returns parsed JSON when\n * the body is JSON, the raw text when it is not, and `undefined` for empty/no\n * content (e.g. 204). Never throws on parse failure.\n */\nconst parseBody = async (response: Response): Promise<unknown> => {\n if (response.status === 204 || response.status === 205) {\n return undefined;\n }\n const text = await response.text();\n if (text === \"\") {\n return undefined;\n }\n try {\n return JSON.parse(text);\n } catch {\n // Error pages are sometimes plain text or HTML; hand back the raw text.\n return text;\n }\n};\n\n/**\n * @description Core request helper shared by every verb.\n * @returns Promise<T> - the parsed response body.\n * @throws HoganApiError when the server responds with a non-2xx status.\n * @throws HoganNetworkError when the request never reaches the server.\n */\nconst request = async <T>({\n method,\n url,\n apiKey,\n body,\n}: RequestConfig): Promise<T> => {\n const headers = requestHeaders(apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n } catch (cause) {\n throw new HoganNetworkError({ method, url, cause });\n }\n\n const parsed = await parseBody(response);\n\n if (!response.ok) {\n throw new HoganApiError({\n status: response.status,\n statusText: response.statusText,\n method,\n url,\n body: parsed,\n });\n }\n\n return parsed as T;\n};\n\n/**\n * @description Make a GET request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const getRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"GET\", url, apiKey });\n\n/**\n * @description Make a POST request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const postRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"POST\", url, apiKey, body });\n\n/**\n * @description Make a PUT request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const putRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"PUT\", url, apiKey, body });\n\n/**\n * @description Make a DELETE request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const deleteRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"DELETE\", url, apiKey });\n","\n\nimport type { WhoAmIType } from \"./types/internal-ota/whoami\";\nimport type { orgType } from \"./types/internal-ota/org\";\nimport type { propertyDetailType } from \"./types/internal-ota/property-detail\";\nimport type { availabilityType, availabilityQueryType } from \"./types/internal-ota/availability\";\nimport type { propertyAmenityType } from \"./types/internal-ota/amenity\";\nimport type { roomTypeType } from \"./types/internal-ota/room-type\";\nimport type { roomAvailabilityType, roomAvailabilityQueryType } from \"./types/internal-ota/room-availability\";\nimport type { paymentCalculationType, calculateStayQueryType } from \"./types/internal-ota/calculate-stay\";\nimport type { ReservationDetailOutput } from \"./types/internal-ota/reservation\";\nimport type { MakeReservationPayloadOTA, MakeReservationResponse } from \"./types/internal-ota/make-reservation\";\nimport type { replicantType, replicantQueryType } from \"./types/internal-ota/replicant\";\nimport { getRequest, postRequest } from \"./resources/requests\";\n\n\nconst internalOta = class {\n\n apiKey: string;\n env: string;\n version: string;\n baseUrl: string;\n\n getBaseUrl() :string {\n this.env = this.env.toUpperCase();\n switch ( this.env ) {\n case \"PROD\":\n case \"PRODUCTION\":\n return `https://production-api.lagunacreek.cloud/ota/${this.version}`;\n case \"TEST\":\n case \"TESTING\":\n return `https://testing-api.lagunacreek.net/ota/${this.version}`;\n case \"DEV\":\n case \"DEVELOPMENT\":\n return `https://development-api.lagunacreek.net/ota/${this.version}`;\n case \"LOCAL\":\n default:\n return `http://localhost:50000/ota/${this.version}`;\n }\n }\n\n\n constructor( apiKey=\"\", env=\"LOCAL\", version=\"v1\" ) {\n this.apiKey = apiKey;\n this.env = env;\n this.version = version;\n this.baseUrl = this.getBaseUrl();\n }\n\n overrideBaseUrl( baseUrl: string ) {\n this.baseUrl = baseUrl;\n }\n\n setAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\", value:string ) {\n this[`${key}`] = value;\n }\n\n getAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\" ) :string {\n return this[key];\n }\n\n\n async whoami(): Promise<WhoAmIType> {\n return getRequest<WhoAmIType>( `${this.baseUrl}/getWhoami`, this.apiKey );\n }\n\n\n async getOrg(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getOrg`, this.apiKey );\n }\n\n\n async getProperties(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getProperties`, this.apiKey );\n }\n\n\n async getPropertyDetail( id: number | string ): Promise<propertyDetailType> {\n return getRequest<propertyDetailType>( `${this.baseUrl}/getPropertyDetail/${id}`, this.apiKey );\n }\n\n\n async getAvailability( params: availabilityQueryType ): Promise<availabilityType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n number_of_guests: String( params.number_of_guests ),\n property_id: String( params.property_id ),\n });\n return getRequest<availabilityType>( `${this.baseUrl}/getAvailability?${query}`, this.apiKey );\n }\n\n\n async getPropertyAmenities( property_id: number | string ): Promise<propertyAmenityType[]> {\n return getRequest<propertyAmenityType[]>( `${this.baseUrl}/getPropertyAmenities/${property_id}`, this.apiKey );\n }\n\n\n async getRoomTypes( property_id: number | string ): Promise<roomTypeType[]> {\n const query = new URLSearchParams({ property_id: String( property_id ) });\n return getRequest<roomTypeType[]>( `${this.baseUrl}/getRoomTypes?${query}`, this.apiKey );\n }\n\n\n async getRoomAvailability( params: roomAvailabilityQueryType ): Promise<roomAvailabilityType[]> {\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n });\n // room_type_ids is a repeated query param (?room_type_ids=1&room_type_ids=2).\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<roomAvailabilityType[]>( `${this.baseUrl}/getRoomAvailability?${query}`, this.apiKey );\n }\n\n\n async getCalculateStay( params: calculateStayQueryType ): Promise<paymentCalculationType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n check_in: params.check_in,\n check_out: params.check_out,\n no_of_rooms: String( params.no_of_rooms ),\n });\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<paymentCalculationType>( `${this.baseUrl}/getCalculateStay?${query}`, this.apiKey );\n }\n\n\n // Property maps are returned as plain-text SVG markup (media_type text/plain).\n // getMaps concatenates every property's SVG; getMap returns one property's SVG,\n // or undefined when the property has no map (the server replies 204).\n async getPropertyMaps(): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMaps`, this.apiKey );\n }\n\n\n async getPropertyMap( property_id: number | string ): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMap/${property_id}`, this.apiKey );\n }\n\n\n async getReservation( reservation_id: number ): Promise<ReservationDetailOutput> {\n const query = new URLSearchParams({ reservation_id: String( reservation_id ) });\n return getRequest<ReservationDetailOutput>( `${this.baseUrl}/getReservation?${query}`, this.apiKey );\n }\n\n\n async postReservation( payload: MakeReservationPayloadOTA ): Promise<MakeReservationResponse> {\n return postRequest<MakeReservationResponse>( `${this.baseUrl}/postReservation`, this.apiKey, payload );\n }\n\n\n // Replicant feed: one page of the cross-tenant property list an OTA partner\n // caches to resell our clients' inventory. Page size is fixed server-side;\n // walk pages by following `next_page` / `next_link` until next_page is false.\n async getReplicant( params: replicantQueryType = {} ): Promise<replicantType> {\n const query = new URLSearchParams();\n if ( params.page !== undefined ) {\n query.set( \"page\", String( params.page ) );\n }\n const qs = query.toString();\n return getRequest<replicantType>( `${this.baseUrl}/getReplicant${qs ? `?${qs}` : \"\"}`, this.apiKey );\n }\n\n\n};\n\nexport default internalOta;"],"mappings":"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","names":["version"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -903,6 +903,74 @@ interface MakeReservationResponse {
|
|
|
903
903
|
payment_intent: PaymentIntent | null;
|
|
904
904
|
}
|
|
905
905
|
|
|
906
|
+
/**
|
|
907
|
+
* Types for GET /ota/v1/getReplicant.
|
|
908
|
+
*
|
|
909
|
+
* The replicant feed copies every tenant's properties into a paginated,
|
|
910
|
+
* cross-tenant list that an OTA partner caches to display our clients' sales
|
|
911
|
+
* on their own platform.
|
|
912
|
+
*
|
|
913
|
+
* Backend source of truth:
|
|
914
|
+
* pms-backend app/routes/ota/end_points.py (get_replicant)
|
|
915
|
+
* pms-backend app/controllers/ota/controller.py
|
|
916
|
+
* (get_replicant_page, _tenant_properties, _highlighted_amenities, _property_images)
|
|
917
|
+
* app/routes/properties/schemas/property.py (PropertyListSchema)
|
|
918
|
+
*
|
|
919
|
+
* Note: the endpoint response differs from the controller's raw page dict — it
|
|
920
|
+
* exposes `next_page` (boolean) and `next_link` instead of the controller's
|
|
921
|
+
* `pages` count.
|
|
922
|
+
*/
|
|
923
|
+
|
|
924
|
+
/** Query parameters accepted by getReplicant. */
|
|
925
|
+
type replicantQueryType = {
|
|
926
|
+
/** 1-based page number. Server defaults to 1; page_size is server-fixed. */
|
|
927
|
+
page?: number;
|
|
928
|
+
};
|
|
929
|
+
/**
|
|
930
|
+
* A base amenity flagged as featured for resale display
|
|
931
|
+
* (controller `_highlighted_amenities`). Note this is a flattened projection,
|
|
932
|
+
* not the full RoomAmenitySchema used elsewhere.
|
|
933
|
+
*/
|
|
934
|
+
type replicantHighlightedAmenityType = {
|
|
935
|
+
name: string;
|
|
936
|
+
description: string | null;
|
|
937
|
+
icon_path: string | null;
|
|
938
|
+
additional_charge: boolean;
|
|
939
|
+
/** Amenity category name, or null when the amenity has no category. */
|
|
940
|
+
category: string | null;
|
|
941
|
+
};
|
|
942
|
+
/** A capped active image media entry for the property (controller `_property_images`). */
|
|
943
|
+
type replicantImageType = {
|
|
944
|
+
path: string;
|
|
945
|
+
alt: string | null;
|
|
946
|
+
caption: string | null;
|
|
947
|
+
category: string | null;
|
|
948
|
+
};
|
|
949
|
+
/**
|
|
950
|
+
* One property in the replicant feed: the PropertyListSchema fields (shared with
|
|
951
|
+
* proptryType) plus the cross-tenant resale extras the controller appends.
|
|
952
|
+
*/
|
|
953
|
+
type replicantPropertyType = proptryType & {
|
|
954
|
+
/** Schema name of the tenant this property belongs to, e.g. "pms_demo". */
|
|
955
|
+
tenant: string;
|
|
956
|
+
highlighted_amenities: replicantHighlightedAmenityType[];
|
|
957
|
+
images: replicantImageType[];
|
|
958
|
+
};
|
|
959
|
+
/** Full response from getReplicant. */
|
|
960
|
+
type replicantType = {
|
|
961
|
+
results: replicantPropertyType[];
|
|
962
|
+
/** The page that was returned (echoes the requested page). */
|
|
963
|
+
page: number;
|
|
964
|
+
/** Server-fixed page size. */
|
|
965
|
+
page_size: number;
|
|
966
|
+
/** Total properties across every tenant. */
|
|
967
|
+
total: number;
|
|
968
|
+
/** True when a further page exists. */
|
|
969
|
+
next_page: boolean;
|
|
970
|
+
/** Relative path to the next page, or null when on the last page. */
|
|
971
|
+
next_link: string | null;
|
|
972
|
+
};
|
|
973
|
+
|
|
906
974
|
declare const internalOta: {
|
|
907
975
|
new (apiKey?: string, env?: string, version?: string): {
|
|
908
976
|
apiKey: string;
|
|
@@ -926,6 +994,7 @@ declare const internalOta: {
|
|
|
926
994
|
getPropertyMap(property_id: number | string): Promise<string | undefined>;
|
|
927
995
|
getReservation(reservation_id: number): Promise<ReservationDetailOutput>;
|
|
928
996
|
postReservation(payload: MakeReservationPayloadOTA): Promise<MakeReservationResponse>;
|
|
997
|
+
getReplicant(params?: replicantQueryType): Promise<replicantType>;
|
|
929
998
|
};
|
|
930
999
|
};
|
|
931
1000
|
|
|
@@ -962,4 +1031,4 @@ declare class HoganNetworkError extends Error {
|
|
|
962
1031
|
});
|
|
963
1032
|
}
|
|
964
1033
|
|
|
965
|
-
export { type ChargeOutput, type CreateGuestInput, type CustomField, type FolioOutput, type Group, type GuestBaseSchema, HoganApiError, internalOta as HoganInternalOTAClient, HoganNetworkError, type MakeReservationPayloadOTA, type MakeReservationResponse, type MakeReservationResult, type PaymentIntent, type PaymentMethodOutput, type PaymentOutput, type PaymentRoutingReadSchema, type PostingCodeDepartmentOutputPostingCode, type PostingCodeDepartmentOutputTaxes, type PostingCodeOutput, type PostingCodeWithDepartmentOutput, type PostingDepartmentReadSchema, type PropertyListSchema, type RateCodeRead, type RatePlanRead, type RatePlanRuleRead, type RefundOutput, type ReservationCommentResponse, type ReservationDetailOutput, type ReservationOutput, type ReservationStayDetail, type ReservationStayGuestOTA, type ReservationsBelongingToGroup, type RoomInfo, type RoomSchemaRead, type RoomStatusList, type RoomTypeReservation, type StayOTA, type TargetDepartmentGroup, type TargetDepartmentGroupOutput, type TaxExemptionReadSchema, type UserBaseSchema, type UserDepartmentList, type UserRoleSchema, type UserSchema, VERSION, type WhoAmIType, type amenityCategoryType, type availabilityQueryType, type availabilityType, type calculateStayQueryType, type orgType, type paymentCalculationType, type propertyAmenityType, type propertyDetailType, type proptryType, type rateCodeDetailType, type roomAmenityType, type roomAvailabilityQueryType, type roomAvailabilityType, type roomTypeAvailabilityType, type roomTypeOutputType, type roomTypeType, type roomWisePriceType, type taxDetailType, type taxRateType, version };
|
|
1034
|
+
export { type ChargeOutput, type CreateGuestInput, type CustomField, type FolioOutput, type Group, type GuestBaseSchema, HoganApiError, internalOta as HoganInternalOTAClient, HoganNetworkError, type MakeReservationPayloadOTA, type MakeReservationResponse, type MakeReservationResult, type PaymentIntent, type PaymentMethodOutput, type PaymentOutput, type PaymentRoutingReadSchema, type PostingCodeDepartmentOutputPostingCode, type PostingCodeDepartmentOutputTaxes, type PostingCodeOutput, type PostingCodeWithDepartmentOutput, type PostingDepartmentReadSchema, type PropertyListSchema, type RateCodeRead, type RatePlanRead, type RatePlanRuleRead, type RefundOutput, type ReservationCommentResponse, type ReservationDetailOutput, type ReservationOutput, type ReservationStayDetail, type ReservationStayGuestOTA, type ReservationsBelongingToGroup, type RoomInfo, type RoomSchemaRead, type RoomStatusList, type RoomTypeReservation, type StayOTA, type TargetDepartmentGroup, type TargetDepartmentGroupOutput, type TaxExemptionReadSchema, type UserBaseSchema, type UserDepartmentList, type UserRoleSchema, type UserSchema, VERSION, type WhoAmIType, type amenityCategoryType, type availabilityQueryType, type availabilityType, type calculateStayQueryType, type orgType, type paymentCalculationType, type propertyAmenityType, type propertyDetailType, type proptryType, type rateCodeDetailType, type replicantHighlightedAmenityType, type replicantImageType, type replicantPropertyType, type replicantQueryType, type replicantType, type roomAmenityType, type roomAvailabilityQueryType, type roomAvailabilityType, type roomTypeAvailabilityType, type roomTypeOutputType, type roomTypeType, type roomWisePriceType, type taxDetailType, type taxRateType, version };
|
package/dist/index.d.ts
CHANGED
|
@@ -903,6 +903,74 @@ interface MakeReservationResponse {
|
|
|
903
903
|
payment_intent: PaymentIntent | null;
|
|
904
904
|
}
|
|
905
905
|
|
|
906
|
+
/**
|
|
907
|
+
* Types for GET /ota/v1/getReplicant.
|
|
908
|
+
*
|
|
909
|
+
* The replicant feed copies every tenant's properties into a paginated,
|
|
910
|
+
* cross-tenant list that an OTA partner caches to display our clients' sales
|
|
911
|
+
* on their own platform.
|
|
912
|
+
*
|
|
913
|
+
* Backend source of truth:
|
|
914
|
+
* pms-backend app/routes/ota/end_points.py (get_replicant)
|
|
915
|
+
* pms-backend app/controllers/ota/controller.py
|
|
916
|
+
* (get_replicant_page, _tenant_properties, _highlighted_amenities, _property_images)
|
|
917
|
+
* app/routes/properties/schemas/property.py (PropertyListSchema)
|
|
918
|
+
*
|
|
919
|
+
* Note: the endpoint response differs from the controller's raw page dict — it
|
|
920
|
+
* exposes `next_page` (boolean) and `next_link` instead of the controller's
|
|
921
|
+
* `pages` count.
|
|
922
|
+
*/
|
|
923
|
+
|
|
924
|
+
/** Query parameters accepted by getReplicant. */
|
|
925
|
+
type replicantQueryType = {
|
|
926
|
+
/** 1-based page number. Server defaults to 1; page_size is server-fixed. */
|
|
927
|
+
page?: number;
|
|
928
|
+
};
|
|
929
|
+
/**
|
|
930
|
+
* A base amenity flagged as featured for resale display
|
|
931
|
+
* (controller `_highlighted_amenities`). Note this is a flattened projection,
|
|
932
|
+
* not the full RoomAmenitySchema used elsewhere.
|
|
933
|
+
*/
|
|
934
|
+
type replicantHighlightedAmenityType = {
|
|
935
|
+
name: string;
|
|
936
|
+
description: string | null;
|
|
937
|
+
icon_path: string | null;
|
|
938
|
+
additional_charge: boolean;
|
|
939
|
+
/** Amenity category name, or null when the amenity has no category. */
|
|
940
|
+
category: string | null;
|
|
941
|
+
};
|
|
942
|
+
/** A capped active image media entry for the property (controller `_property_images`). */
|
|
943
|
+
type replicantImageType = {
|
|
944
|
+
path: string;
|
|
945
|
+
alt: string | null;
|
|
946
|
+
caption: string | null;
|
|
947
|
+
category: string | null;
|
|
948
|
+
};
|
|
949
|
+
/**
|
|
950
|
+
* One property in the replicant feed: the PropertyListSchema fields (shared with
|
|
951
|
+
* proptryType) plus the cross-tenant resale extras the controller appends.
|
|
952
|
+
*/
|
|
953
|
+
type replicantPropertyType = proptryType & {
|
|
954
|
+
/** Schema name of the tenant this property belongs to, e.g. "pms_demo". */
|
|
955
|
+
tenant: string;
|
|
956
|
+
highlighted_amenities: replicantHighlightedAmenityType[];
|
|
957
|
+
images: replicantImageType[];
|
|
958
|
+
};
|
|
959
|
+
/** Full response from getReplicant. */
|
|
960
|
+
type replicantType = {
|
|
961
|
+
results: replicantPropertyType[];
|
|
962
|
+
/** The page that was returned (echoes the requested page). */
|
|
963
|
+
page: number;
|
|
964
|
+
/** Server-fixed page size. */
|
|
965
|
+
page_size: number;
|
|
966
|
+
/** Total properties across every tenant. */
|
|
967
|
+
total: number;
|
|
968
|
+
/** True when a further page exists. */
|
|
969
|
+
next_page: boolean;
|
|
970
|
+
/** Relative path to the next page, or null when on the last page. */
|
|
971
|
+
next_link: string | null;
|
|
972
|
+
};
|
|
973
|
+
|
|
906
974
|
declare const internalOta: {
|
|
907
975
|
new (apiKey?: string, env?: string, version?: string): {
|
|
908
976
|
apiKey: string;
|
|
@@ -926,6 +994,7 @@ declare const internalOta: {
|
|
|
926
994
|
getPropertyMap(property_id: number | string): Promise<string | undefined>;
|
|
927
995
|
getReservation(reservation_id: number): Promise<ReservationDetailOutput>;
|
|
928
996
|
postReservation(payload: MakeReservationPayloadOTA): Promise<MakeReservationResponse>;
|
|
997
|
+
getReplicant(params?: replicantQueryType): Promise<replicantType>;
|
|
929
998
|
};
|
|
930
999
|
};
|
|
931
1000
|
|
|
@@ -962,4 +1031,4 @@ declare class HoganNetworkError extends Error {
|
|
|
962
1031
|
});
|
|
963
1032
|
}
|
|
964
1033
|
|
|
965
|
-
export { type ChargeOutput, type CreateGuestInput, type CustomField, type FolioOutput, type Group, type GuestBaseSchema, HoganApiError, internalOta as HoganInternalOTAClient, HoganNetworkError, type MakeReservationPayloadOTA, type MakeReservationResponse, type MakeReservationResult, type PaymentIntent, type PaymentMethodOutput, type PaymentOutput, type PaymentRoutingReadSchema, type PostingCodeDepartmentOutputPostingCode, type PostingCodeDepartmentOutputTaxes, type PostingCodeOutput, type PostingCodeWithDepartmentOutput, type PostingDepartmentReadSchema, type PropertyListSchema, type RateCodeRead, type RatePlanRead, type RatePlanRuleRead, type RefundOutput, type ReservationCommentResponse, type ReservationDetailOutput, type ReservationOutput, type ReservationStayDetail, type ReservationStayGuestOTA, type ReservationsBelongingToGroup, type RoomInfo, type RoomSchemaRead, type RoomStatusList, type RoomTypeReservation, type StayOTA, type TargetDepartmentGroup, type TargetDepartmentGroupOutput, type TaxExemptionReadSchema, type UserBaseSchema, type UserDepartmentList, type UserRoleSchema, type UserSchema, VERSION, type WhoAmIType, type amenityCategoryType, type availabilityQueryType, type availabilityType, type calculateStayQueryType, type orgType, type paymentCalculationType, type propertyAmenityType, type propertyDetailType, type proptryType, type rateCodeDetailType, type roomAmenityType, type roomAvailabilityQueryType, type roomAvailabilityType, type roomTypeAvailabilityType, type roomTypeOutputType, type roomTypeType, type roomWisePriceType, type taxDetailType, type taxRateType, version };
|
|
1034
|
+
export { type ChargeOutput, type CreateGuestInput, type CustomField, type FolioOutput, type Group, type GuestBaseSchema, HoganApiError, internalOta as HoganInternalOTAClient, HoganNetworkError, type MakeReservationPayloadOTA, type MakeReservationResponse, type MakeReservationResult, type PaymentIntent, type PaymentMethodOutput, type PaymentOutput, type PaymentRoutingReadSchema, type PostingCodeDepartmentOutputPostingCode, type PostingCodeDepartmentOutputTaxes, type PostingCodeOutput, type PostingCodeWithDepartmentOutput, type PostingDepartmentReadSchema, type PropertyListSchema, type RateCodeRead, type RatePlanRead, type RatePlanRuleRead, type RefundOutput, type ReservationCommentResponse, type ReservationDetailOutput, type ReservationOutput, type ReservationStayDetail, type ReservationStayGuestOTA, type ReservationsBelongingToGroup, type RoomInfo, type RoomSchemaRead, type RoomStatusList, type RoomTypeReservation, type StayOTA, type TargetDepartmentGroup, type TargetDepartmentGroupOutput, type TaxExemptionReadSchema, type UserBaseSchema, type UserDepartmentList, type UserRoleSchema, type UserSchema, VERSION, type WhoAmIType, type amenityCategoryType, type availabilityQueryType, type availabilityType, type calculateStayQueryType, type orgType, type paymentCalculationType, type propertyAmenityType, type propertyDetailType, type proptryType, type rateCodeDetailType, type replicantHighlightedAmenityType, type replicantImageType, type replicantPropertyType, type replicantQueryType, type replicantType, type roomAmenityType, type roomAvailabilityQueryType, type roomAvailabilityType, type roomTypeAvailabilityType, type roomTypeOutputType, type roomTypeType, type roomWisePriceType, type taxDetailType, type taxRateType, version };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = true ? "0.1.
|
|
2
|
+
var VERSION = true ? "0.1.3" : "0.0.0";
|
|
3
3
|
function version() {
|
|
4
4
|
return VERSION;
|
|
5
5
|
}
|
|
@@ -192,6 +192,17 @@ var internalOta = class {
|
|
|
192
192
|
async postReservation(payload) {
|
|
193
193
|
return postRequest(`${this.baseUrl}/postReservation`, this.apiKey, payload);
|
|
194
194
|
}
|
|
195
|
+
// Replicant feed: one page of the cross-tenant property list an OTA partner
|
|
196
|
+
// caches to resell our clients' inventory. Page size is fixed server-side;
|
|
197
|
+
// walk pages by following `next_page` / `next_link` until next_page is false.
|
|
198
|
+
async getReplicant(params = {}) {
|
|
199
|
+
const query = new URLSearchParams();
|
|
200
|
+
if (params.page !== void 0) {
|
|
201
|
+
query.set("page", String(params.page));
|
|
202
|
+
}
|
|
203
|
+
const qs = query.toString();
|
|
204
|
+
return getRequest(`${this.baseUrl}/getReplicant${qs ? `?${qs}` : ""}`, this.apiKey);
|
|
205
|
+
}
|
|
195
206
|
};
|
|
196
207
|
var internal_ota_default = internalOta;
|
|
197
208
|
export {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts","../src/errors.ts","../src/resources/requests.ts","../src/internal-ota.ts"],"sourcesContent":["// `__PACKAGE_VERSION__` is replaced at build time by tsup's `define` (see\n// tsup.config.ts) and by vitest's `define` during tests, both sourced from\n// package.json. The fallback keeps the value sane if the package is consumed\n// in an unexpected way where the replacement did not happen.\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * The version of this package, as declared in its package.json.\n */\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ === \"string\" ? __PACKAGE_VERSION__ : \"0.0.0\";\n\n/**\n * Returns the version of the hogan-pms-client package.\n */\nexport function version(): string {\n return VERSION;\n}\n","// Error types thrown by the Hogan client. Consumers can branch on these\n// with `instanceof` instead of inspecting raw responses.\n\n/**\n * Thrown when the Hogan API responds with a non-2xx status. Carries the\n * status code and the parsed body (when available) for inspection.\n */\nexport class HoganApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly method: string;\n readonly url: string;\n /** Parsed response body, or the raw text if it was not JSON. */\n readonly body: unknown;\n\n constructor(args: {\n status: number;\n statusText: string;\n method: string;\n url: string;\n body: unknown;\n }) {\n super(\n `Hogan API ${args.method} ${args.url} failed: ${args.status} ${args.statusText}`,\n );\n this.name = \"HoganApiError\";\n this.status = args.status;\n this.statusText = args.statusText;\n this.method = args.method;\n this.url = args.url;\n this.body = args.body;\n }\n}\n\n/**\n * Thrown when the request never produced an HTTP response at all — a network\n * failure, DNS error, timeout/abort, etc.\n */\nexport class HoganNetworkError extends Error {\n readonly method: string;\n readonly url: string;\n\n constructor(args: { method: string; url: string; cause: unknown }) {\n super(`Hogan API request to ${args.method} ${args.url} failed to send`, {\n cause: args.cause,\n });\n this.name = \"HoganNetworkError\";\n this.method = args.method;\n this.url = args.url;\n }\n}\n","/**\n * @description Utility functions for making API requests to the Hogan PMS API.\n * Each verb (GET, POST, PUT, DELETE) delegates to a single `request` helper that\n * sets the auth header, reads the response body exactly once, and converts\n * failures into typed errors:\n * - non-2xx responses throw `HoganApiError` (with status + parsed body)\n * - transport failures (DNS, offline, abort/timeout) throw `HoganNetworkError`\n */\n\nimport { HoganApiError, HoganNetworkError } from \"../errors.js\";\n\n/**\n * @description Build the headers sent on every request. Auth is the OTA\n * `x-api-key` header (the API does not use a bearer token).\n * @param apiKey string\n */\nexport const requestHeaders = (apiKey: string): Record<string, string> => ({\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"x-api-key\": `${apiKey}`,\n});\n\n/**\n * @description Core request configuration for the `request` helper.\n * @param method string - HTTP verb (GET, POST, etc.)\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @body JSON-serialisable request body, body Omitted for GET/DELETE.\n */\ninterface RequestConfig {\n method: string;\n url: string;\n apiKey: string;\n body?: object;\n}\n\n/**\n * @description Read a fetch Response body a single time. Returns parsed JSON when\n * the body is JSON, the raw text when it is not, and `undefined` for empty/no\n * content (e.g. 204). Never throws on parse failure.\n */\nconst parseBody = async (response: Response): Promise<unknown> => {\n if (response.status === 204 || response.status === 205) {\n return undefined;\n }\n const text = await response.text();\n if (text === \"\") {\n return undefined;\n }\n try {\n return JSON.parse(text);\n } catch {\n // Error pages are sometimes plain text or HTML; hand back the raw text.\n return text;\n }\n};\n\n/**\n * @description Core request helper shared by every verb.\n * @returns Promise<T> - the parsed response body.\n * @throws HoganApiError when the server responds with a non-2xx status.\n * @throws HoganNetworkError when the request never reaches the server.\n */\nconst request = async <T>({\n method,\n url,\n apiKey,\n body,\n}: RequestConfig): Promise<T> => {\n const headers = requestHeaders(apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n } catch (cause) {\n throw new HoganNetworkError({ method, url, cause });\n }\n\n const parsed = await parseBody(response);\n\n if (!response.ok) {\n throw new HoganApiError({\n status: response.status,\n statusText: response.statusText,\n method,\n url,\n body: parsed,\n });\n }\n\n return parsed as T;\n};\n\n/**\n * @description Make a GET request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const getRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"GET\", url, apiKey });\n\n/**\n * @description Make a POST request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const postRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"POST\", url, apiKey, body });\n\n/**\n * @description Make a PUT request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const putRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"PUT\", url, apiKey, body });\n\n/**\n * @description Make a DELETE request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const deleteRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"DELETE\", url, apiKey });\n","\n\nimport type { WhoAmIType } from \"./types/internal-ota/whoami\";\nimport type { orgType } from \"./types/internal-ota/org\";\nimport type { propertyDetailType } from \"./types/internal-ota/property-detail\";\nimport type { availabilityType, availabilityQueryType } from \"./types/internal-ota/availability\";\nimport type { propertyAmenityType } from \"./types/internal-ota/amenity\";\nimport type { roomTypeType } from \"./types/internal-ota/room-type\";\nimport type { roomAvailabilityType, roomAvailabilityQueryType } from \"./types/internal-ota/room-availability\";\nimport type { paymentCalculationType, calculateStayQueryType } from \"./types/internal-ota/calculate-stay\";\nimport type { ReservationDetailOutput } from \"./types/internal-ota/reservation\";\nimport type { MakeReservationPayloadOTA, MakeReservationResponse } from \"./types/internal-ota/make-reservation\";\nimport { getRequest, postRequest } from \"./resources/requests\";\n\n\nconst internalOta = class {\n\n apiKey: string;\n env: string;\n version: string;\n baseUrl: string;\n\n getBaseUrl() :string {\n this.env = this.env.toUpperCase();\n switch ( this.env ) {\n case \"PROD\":\n case \"PRODUCTION\":\n return `https://production-api.lagunacreek.cloud/ota/${this.version}`;\n case \"TEST\":\n case \"TESTING\":\n return `https://testing-api.lagunacreek.net/ota/${this.version}`;\n case \"DEV\":\n case \"DEVELOPMENT\":\n return `https://development-api.lagunacreek.net/ota/${this.version}`;\n case \"LOCAL\":\n default:\n return `http://localhost:50000/ota/${this.version}`;\n }\n }\n\n\n constructor( apiKey=\"\", env=\"LOCAL\", version=\"v1\" ) {\n this.apiKey = apiKey;\n this.env = env;\n this.version = version;\n this.baseUrl = this.getBaseUrl();\n }\n\n overrideBaseUrl( baseUrl: string ) {\n this.baseUrl = baseUrl;\n }\n\n setAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\", value:string ) {\n this[`${key}`] = value;\n }\n\n getAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\" ) :string {\n return this[key];\n }\n\n\n async whoami(): Promise<WhoAmIType> {\n return getRequest<WhoAmIType>( `${this.baseUrl}/getWhoami`, this.apiKey );\n }\n\n\n async getOrg(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getOrg`, this.apiKey );\n }\n\n\n async getProperties(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getProperties`, this.apiKey );\n }\n\n\n async getPropertyDetail( id: number | string ): Promise<propertyDetailType> {\n return getRequest<propertyDetailType>( `${this.baseUrl}/getPropertyDetail/${id}`, this.apiKey );\n }\n\n\n async getAvailability( params: availabilityQueryType ): Promise<availabilityType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n number_of_guests: String( params.number_of_guests ),\n property_id: String( params.property_id ),\n });\n return getRequest<availabilityType>( `${this.baseUrl}/getAvailability?${query}`, this.apiKey );\n }\n\n\n async getPropertyAmenities( property_id: number | string ): Promise<propertyAmenityType[]> {\n return getRequest<propertyAmenityType[]>( `${this.baseUrl}/getPropertyAmenities/${property_id}`, this.apiKey );\n }\n\n\n async getRoomTypes( property_id: number | string ): Promise<roomTypeType[]> {\n const query = new URLSearchParams({ property_id: String( property_id ) });\n return getRequest<roomTypeType[]>( `${this.baseUrl}/getRoomTypes?${query}`, this.apiKey );\n }\n\n\n async getRoomAvailability( params: roomAvailabilityQueryType ): Promise<roomAvailabilityType[]> {\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n });\n // room_type_ids is a repeated query param (?room_type_ids=1&room_type_ids=2).\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<roomAvailabilityType[]>( `${this.baseUrl}/getRoomAvailability?${query}`, this.apiKey );\n }\n\n\n async getCalculateStay( params: calculateStayQueryType ): Promise<paymentCalculationType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n check_in: params.check_in,\n check_out: params.check_out,\n no_of_rooms: String( params.no_of_rooms ),\n });\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<paymentCalculationType>( `${this.baseUrl}/getCalculateStay?${query}`, this.apiKey );\n }\n\n\n // Property maps are returned as plain-text SVG markup (media_type text/plain).\n // getMaps concatenates every property's SVG; getMap returns one property's SVG,\n // or undefined when the property has no map (the server replies 204).\n async getPropertyMaps(): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMaps`, this.apiKey );\n }\n\n\n async getPropertyMap( property_id: number | string ): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMap/${property_id}`, this.apiKey );\n }\n\n\n async getReservation( reservation_id: number ): Promise<ReservationDetailOutput> {\n const query = new URLSearchParams({ reservation_id: String( reservation_id ) });\n return getRequest<ReservationDetailOutput>( `${this.baseUrl}/getReservation?${query}`, this.apiKey );\n }\n\n\n async postReservation( payload: MakeReservationPayloadOTA ): Promise<MakeReservationResponse> {\n return postRequest<MakeReservationResponse>( `${this.baseUrl}/postReservation`, this.apiKey, payload );\n }\n\n\n};\n\nexport default internalOta;"],"mappings":";AASO,IAAM,UACX,OAA0C,UAAsB;AAK3D,SAAS,UAAkB;AAChC,SAAO;AACT;;;ACVO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,MAMT;AACD;AAAA,MACE,aAAa,KAAK,MAAM,IAAI,KAAK,GAAG,YAAY,KAAK,MAAM,IAAI,KAAK,UAAU;AAAA,IAChF;AACA,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,aAAa,KAAK;AACvB,SAAK,SAAS,KAAK;AACnB,SAAK,MAAM,KAAK;AAChB,SAAK,OAAO,KAAK;AAAA,EACnB;AACF;AAMO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAClC;AAAA,EACA;AAAA,EAET,YAAY,MAAuD;AACjE,UAAM,wBAAwB,KAAK,MAAM,IAAI,KAAK,GAAG,mBAAmB;AAAA,MACtE,OAAO,KAAK;AAAA,IACd,CAAC;AACD,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,MAAM,KAAK;AAAA,EAClB;AACF;;;AClCO,IAAM,iBAAiB,CAAC,YAA4C;AAAA,EACzE,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,aAAa,GAAG,MAAM;AACxB;AAqBA,IAAM,YAAY,OAAO,aAAyC;AAChE,MAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,SAAS,IAAI;AACf,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAQA,IAAM,UAAU,OAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAiC;AAC/B,QAAM,UAAU,eAAe,MAAM;AAErC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,GAAI,SAAS,SAAY,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,kBAAkB,EAAE,QAAQ,KAAK,MAAM,CAAC;AAAA,EACpD;AAEA,QAAM,SAAS,MAAM,UAAU,QAAQ;AAEvC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,cAAc;AAAA,MACtB,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS;AAAA,MACrB;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAOO,IAAM,aAAa,CACxB,KACA,WACe,QAAW,EAAE,QAAQ,OAAO,KAAK,OAAO,CAAC;AAQnD,IAAM,cAAc,CACzB,KACA,QACA,SACe,QAAW,EAAE,QAAQ,QAAQ,KAAK,QAAQ,KAAK,CAAC;;;ACtGjE,IAAM,cAAc,MAAM;AAAA,EAEtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,aAAqB;AACjB,SAAK,MAAM,KAAK,IAAI,YAAY;AAChC,YAAS,KAAK,KAAM;AAAA,MAChB,KAAK;AAAA,MACL,KAAK;AACD,eAAO,gDAAgD,KAAK,OAAO;AAAA,MACvE,KAAK;AAAA,MACL,KAAK;AACD,eAAO,2CAA2C,KAAK,OAAO;AAAA,MAClE,KAAK;AAAA,MACL,KAAK;AACD,eAAO,+CAA+C,KAAK,OAAO;AAAA,MACtE,KAAK;AAAA,MACL;AACI,eAAO,8BAA8B,KAAK,OAAO;AAAA,IACzD;AAAA,EACJ;AAAA,EAGA,YAAa,SAAO,IAAI,MAAI,SAASA,WAAQ,MAAQ;AACjD,SAAK,SAAS;AACd,SAAK,MAAM;AACX,SAAK,UAAUA;AACf,SAAK,UAAU,KAAK,WAAW;AAAA,EACnC;AAAA,EAEA,gBAAiB,SAAkB;AAC/B,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,aAAc,KAA8C,OAAe;AACvE,SAAK,GAAG,GAAG,EAAE,IAAI;AAAA,EACrB;AAAA,EAEA,aAAc,KAAuD;AACjE,WAAO,KAAK,GAAG;AAAA,EACnB;AAAA,EAGA,MAAM,SAA8B;AAChC,WAAO,WAAwB,GAAG,KAAK,OAAO,cAAc,KAAK,MAAO;AAAA,EAC5E;AAAA,EAGA,MAAM,SAA2B;AAC7B,WAAO,WAAqB,GAAG,KAAK,OAAO,WAAW,KAAK,MAAO;AAAA,EACtE;AAAA,EAGA,MAAM,gBAAkC;AACpC,WAAO,WAAqB,GAAG,KAAK,OAAO,kBAAkB,KAAK,MAAO;AAAA,EAC7E;AAAA,EAGA,MAAM,kBAAmB,IAAmD;AACxE,WAAO,WAAgC,GAAG,KAAK,OAAO,sBAAsB,EAAE,IAAI,KAAK,MAAO;AAAA,EAClG;AAAA,EAGA,MAAM,gBAAiB,QAA2D;AAE9E,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAC9B,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,kBAAkB,OAAQ,OAAO,gBAAiB;AAAA,MAClD,aAAa,OAAQ,OAAO,WAAY;AAAA,IAC5C,CAAC;AACD,WAAO,WAA8B,GAAG,KAAK,OAAO,oBAAoB,KAAK,IAAI,KAAK,MAAO;AAAA,EACjG;AAAA,EAGA,MAAM,qBAAsB,aAA+D;AACvF,WAAO,WAAmC,GAAG,KAAK,OAAO,yBAAyB,WAAW,IAAI,KAAK,MAAO;AAAA,EACjH;AAAA,EAGA,MAAM,aAAc,aAAwD;AACxE,UAAM,QAAQ,IAAI,gBAAgB,EAAE,aAAa,OAAQ,WAAY,EAAE,CAAC;AACxE,WAAO,WAA4B,GAAG,KAAK,OAAO,iBAAiB,KAAK,IAAI,KAAK,MAAO;AAAA,EAC5F;AAAA,EAGA,MAAM,oBAAqB,QAAqE;AAC5F,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAC9B,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,IACrB,CAAC;AAED,eAAY,MAAM,OAAO,eAAgB;AACrC,YAAM,OAAQ,iBAAiB,OAAQ,EAAG,CAAE;AAAA,IAChD;AACA,WAAO,WAAoC,GAAG,KAAK,OAAO,wBAAwB,KAAK,IAAI,KAAK,MAAO;AAAA,EAC3G;AAAA,EAGA,MAAM,iBAAkB,QAAkE;AAEtF,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAC9B,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,aAAa,OAAQ,OAAO,WAAY;AAAA,IAC5C,CAAC;AACD,eAAY,MAAM,OAAO,eAAgB;AACrC,YAAM,OAAQ,iBAAiB,OAAQ,EAAG,CAAE;AAAA,IAChD;AACA,WAAO,WAAoC,GAAG,KAAK,OAAO,qBAAqB,KAAK,IAAI,KAAK,MAAO;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAA+C;AACjD,WAAO,WAAgC,GAAG,KAAK,OAAO,uBAAuB,KAAK,MAAO;AAAA,EAC7F;AAAA,EAGA,MAAM,eAAgB,aAA4D;AAC9E,WAAO,WAAgC,GAAG,KAAK,OAAO,sBAAsB,WAAW,IAAI,KAAK,MAAO;AAAA,EAC3G;AAAA,EAGA,MAAM,eAAgB,gBAA2D;AAC7E,UAAM,QAAQ,IAAI,gBAAgB,EAAE,gBAAgB,OAAQ,cAAe,EAAE,CAAC;AAC9E,WAAO,WAAqC,GAAG,KAAK,OAAO,mBAAmB,KAAK,IAAI,KAAK,MAAO;AAAA,EACvG;AAAA,EAGA,MAAM,gBAAiB,SAAuE;AAC1F,WAAO,YAAsC,GAAG,KAAK,OAAO,oBAAoB,KAAK,QAAQ,OAAQ;AAAA,EACzG;AAGJ;AAEA,IAAO,uBAAQ;","names":["version"]}
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/errors.ts","../src/resources/requests.ts","../src/internal-ota.ts"],"sourcesContent":["// `__PACKAGE_VERSION__` is replaced at build time by tsup's `define` (see\n// tsup.config.ts) and by vitest's `define` during tests, both sourced from\n// package.json. The fallback keeps the value sane if the package is consumed\n// in an unexpected way where the replacement did not happen.\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * The version of this package, as declared in its package.json.\n */\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ === \"string\" ? __PACKAGE_VERSION__ : \"0.0.0\";\n\n/**\n * Returns the version of the hogan-pms-client package.\n */\nexport function version(): string {\n return VERSION;\n}\n","// Error types thrown by the Hogan client. Consumers can branch on these\n// with `instanceof` instead of inspecting raw responses.\n\n/**\n * Thrown when the Hogan API responds with a non-2xx status. Carries the\n * status code and the parsed body (when available) for inspection.\n */\nexport class HoganApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly method: string;\n readonly url: string;\n /** Parsed response body, or the raw text if it was not JSON. */\n readonly body: unknown;\n\n constructor(args: {\n status: number;\n statusText: string;\n method: string;\n url: string;\n body: unknown;\n }) {\n super(\n `Hogan API ${args.method} ${args.url} failed: ${args.status} ${args.statusText}`,\n );\n this.name = \"HoganApiError\";\n this.status = args.status;\n this.statusText = args.statusText;\n this.method = args.method;\n this.url = args.url;\n this.body = args.body;\n }\n}\n\n/**\n * Thrown when the request never produced an HTTP response at all — a network\n * failure, DNS error, timeout/abort, etc.\n */\nexport class HoganNetworkError extends Error {\n readonly method: string;\n readonly url: string;\n\n constructor(args: { method: string; url: string; cause: unknown }) {\n super(`Hogan API request to ${args.method} ${args.url} failed to send`, {\n cause: args.cause,\n });\n this.name = \"HoganNetworkError\";\n this.method = args.method;\n this.url = args.url;\n }\n}\n","/**\n * @description Utility functions for making API requests to the Hogan PMS API.\n * Each verb (GET, POST, PUT, DELETE) delegates to a single `request` helper that\n * sets the auth header, reads the response body exactly once, and converts\n * failures into typed errors:\n * - non-2xx responses throw `HoganApiError` (with status + parsed body)\n * - transport failures (DNS, offline, abort/timeout) throw `HoganNetworkError`\n */\n\nimport { HoganApiError, HoganNetworkError } from \"../errors.js\";\n\n/**\n * @description Build the headers sent on every request. Auth is the OTA\n * `x-api-key` header (the API does not use a bearer token).\n * @param apiKey string\n */\nexport const requestHeaders = (apiKey: string): Record<string, string> => ({\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"x-api-key\": `${apiKey}`,\n});\n\n/**\n * @description Core request configuration for the `request` helper.\n * @param method string - HTTP verb (GET, POST, etc.)\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @body JSON-serialisable request body, body Omitted for GET/DELETE.\n */\ninterface RequestConfig {\n method: string;\n url: string;\n apiKey: string;\n body?: object;\n}\n\n/**\n * @description Read a fetch Response body a single time. Returns parsed JSON when\n * the body is JSON, the raw text when it is not, and `undefined` for empty/no\n * content (e.g. 204). Never throws on parse failure.\n */\nconst parseBody = async (response: Response): Promise<unknown> => {\n if (response.status === 204 || response.status === 205) {\n return undefined;\n }\n const text = await response.text();\n if (text === \"\") {\n return undefined;\n }\n try {\n return JSON.parse(text);\n } catch {\n // Error pages are sometimes plain text or HTML; hand back the raw text.\n return text;\n }\n};\n\n/**\n * @description Core request helper shared by every verb.\n * @returns Promise<T> - the parsed response body.\n * @throws HoganApiError when the server responds with a non-2xx status.\n * @throws HoganNetworkError when the request never reaches the server.\n */\nconst request = async <T>({\n method,\n url,\n apiKey,\n body,\n}: RequestConfig): Promise<T> => {\n const headers = requestHeaders(apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n } catch (cause) {\n throw new HoganNetworkError({ method, url, cause });\n }\n\n const parsed = await parseBody(response);\n\n if (!response.ok) {\n throw new HoganApiError({\n status: response.status,\n statusText: response.statusText,\n method,\n url,\n body: parsed,\n });\n }\n\n return parsed as T;\n};\n\n/**\n * @description Make a GET request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const getRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"GET\", url, apiKey });\n\n/**\n * @description Make a POST request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const postRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"POST\", url, apiKey, body });\n\n/**\n * @description Make a PUT request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n * @param body object - The data to send in the request body.\n */\nexport const putRequest = <T = unknown>(\n url: string,\n apiKey: string,\n body: object,\n): Promise<T> => request<T>({ method: \"PUT\", url, apiKey, body });\n\n/**\n * @description Make a DELETE request to the Hogan PMS API.\n * @param url string - The URL to send the request to.\n * @param apiKey string - The API key for authentication.\n */\nexport const deleteRequest = <T = unknown>(\n url: string,\n apiKey: string,\n): Promise<T> => request<T>({ method: \"DELETE\", url, apiKey });\n","\n\nimport type { WhoAmIType } from \"./types/internal-ota/whoami\";\nimport type { orgType } from \"./types/internal-ota/org\";\nimport type { propertyDetailType } from \"./types/internal-ota/property-detail\";\nimport type { availabilityType, availabilityQueryType } from \"./types/internal-ota/availability\";\nimport type { propertyAmenityType } from \"./types/internal-ota/amenity\";\nimport type { roomTypeType } from \"./types/internal-ota/room-type\";\nimport type { roomAvailabilityType, roomAvailabilityQueryType } from \"./types/internal-ota/room-availability\";\nimport type { paymentCalculationType, calculateStayQueryType } from \"./types/internal-ota/calculate-stay\";\nimport type { ReservationDetailOutput } from \"./types/internal-ota/reservation\";\nimport type { MakeReservationPayloadOTA, MakeReservationResponse } from \"./types/internal-ota/make-reservation\";\nimport type { replicantType, replicantQueryType } from \"./types/internal-ota/replicant\";\nimport { getRequest, postRequest } from \"./resources/requests\";\n\n\nconst internalOta = class {\n\n apiKey: string;\n env: string;\n version: string;\n baseUrl: string;\n\n getBaseUrl() :string {\n this.env = this.env.toUpperCase();\n switch ( this.env ) {\n case \"PROD\":\n case \"PRODUCTION\":\n return `https://production-api.lagunacreek.cloud/ota/${this.version}`;\n case \"TEST\":\n case \"TESTING\":\n return `https://testing-api.lagunacreek.net/ota/${this.version}`;\n case \"DEV\":\n case \"DEVELOPMENT\":\n return `https://development-api.lagunacreek.net/ota/${this.version}`;\n case \"LOCAL\":\n default:\n return `http://localhost:50000/ota/${this.version}`;\n }\n }\n\n\n constructor( apiKey=\"\", env=\"LOCAL\", version=\"v1\" ) {\n this.apiKey = apiKey;\n this.env = env;\n this.version = version;\n this.baseUrl = this.getBaseUrl();\n }\n\n overrideBaseUrl( baseUrl: string ) {\n this.baseUrl = baseUrl;\n }\n\n setAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\", value:string ) {\n this[`${key}`] = value;\n }\n\n getAttribute( key:\"apiKey\" | \"env\" | \"version\" | \"baseUrl\" ) :string {\n return this[key];\n }\n\n\n async whoami(): Promise<WhoAmIType> {\n return getRequest<WhoAmIType>( `${this.baseUrl}/getWhoami`, this.apiKey );\n }\n\n\n async getOrg(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getOrg`, this.apiKey );\n }\n\n\n async getProperties(): Promise<orgType> {\n return getRequest<orgType>( `${this.baseUrl}/getProperties`, this.apiKey );\n }\n\n\n async getPropertyDetail( id: number | string ): Promise<propertyDetailType> {\n return getRequest<propertyDetailType>( `${this.baseUrl}/getPropertyDetail/${id}`, this.apiKey );\n }\n\n\n async getAvailability( params: availabilityQueryType ): Promise<availabilityType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n number_of_guests: String( params.number_of_guests ),\n property_id: String( params.property_id ),\n });\n return getRequest<availabilityType>( `${this.baseUrl}/getAvailability?${query}`, this.apiKey );\n }\n\n\n async getPropertyAmenities( property_id: number | string ): Promise<propertyAmenityType[]> {\n return getRequest<propertyAmenityType[]>( `${this.baseUrl}/getPropertyAmenities/${property_id}`, this.apiKey );\n }\n\n\n async getRoomTypes( property_id: number | string ): Promise<roomTypeType[]> {\n const query = new URLSearchParams({ property_id: String( property_id ) });\n return getRequest<roomTypeType[]>( `${this.baseUrl}/getRoomTypes?${query}`, this.apiKey );\n }\n\n\n async getRoomAvailability( params: roomAvailabilityQueryType ): Promise<roomAvailabilityType[]> {\n const query = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n });\n // room_type_ids is a repeated query param (?room_type_ids=1&room_type_ids=2).\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<roomAvailabilityType[]>( `${this.baseUrl}/getRoomAvailability?${query}`, this.apiKey );\n }\n\n\n async getCalculateStay( params: calculateStayQueryType ): Promise<paymentCalculationType> {\n // rate_code is resolved server-side from the API key, so it is not sent here.\n const query = new URLSearchParams({\n check_in: params.check_in,\n check_out: params.check_out,\n no_of_rooms: String( params.no_of_rooms ),\n });\n for ( const id of params.room_type_ids ) {\n query.append( \"room_type_ids\", String( id ) );\n }\n return getRequest<paymentCalculationType>( `${this.baseUrl}/getCalculateStay?${query}`, this.apiKey );\n }\n\n\n // Property maps are returned as plain-text SVG markup (media_type text/plain).\n // getMaps concatenates every property's SVG; getMap returns one property's SVG,\n // or undefined when the property has no map (the server replies 204).\n async getPropertyMaps(): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMaps`, this.apiKey );\n }\n\n\n async getPropertyMap( property_id: number | string ): Promise<string | undefined> {\n return getRequest<string | undefined>( `${this.baseUrl}/properties/getMap/${property_id}`, this.apiKey );\n }\n\n\n async getReservation( reservation_id: number ): Promise<ReservationDetailOutput> {\n const query = new URLSearchParams({ reservation_id: String( reservation_id ) });\n return getRequest<ReservationDetailOutput>( `${this.baseUrl}/getReservation?${query}`, this.apiKey );\n }\n\n\n async postReservation( payload: MakeReservationPayloadOTA ): Promise<MakeReservationResponse> {\n return postRequest<MakeReservationResponse>( `${this.baseUrl}/postReservation`, this.apiKey, payload );\n }\n\n\n // Replicant feed: one page of the cross-tenant property list an OTA partner\n // caches to resell our clients' inventory. Page size is fixed server-side;\n // walk pages by following `next_page` / `next_link` until next_page is false.\n async getReplicant( params: replicantQueryType = {} ): Promise<replicantType> {\n const query = new URLSearchParams();\n if ( params.page !== undefined ) {\n query.set( \"page\", String( params.page ) );\n }\n const qs = query.toString();\n return getRequest<replicantType>( `${this.baseUrl}/getReplicant${qs ? `?${qs}` : \"\"}`, this.apiKey );\n }\n\n\n};\n\nexport default internalOta;"],"mappings":";AASO,IAAM,UACX,OAA0C,UAAsB;AAK3D,SAAS,UAAkB;AAChC,SAAO;AACT;;;ACVO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,MAMT;AACD;AAAA,MACE,aAAa,KAAK,MAAM,IAAI,KAAK,GAAG,YAAY,KAAK,MAAM,IAAI,KAAK,UAAU;AAAA,IAChF;AACA,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,aAAa,KAAK;AACvB,SAAK,SAAS,KAAK;AACnB,SAAK,MAAM,KAAK;AAChB,SAAK,OAAO,KAAK;AAAA,EACnB;AACF;AAMO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAClC;AAAA,EACA;AAAA,EAET,YAAY,MAAuD;AACjE,UAAM,wBAAwB,KAAK,MAAM,IAAI,KAAK,GAAG,mBAAmB;AAAA,MACtE,OAAO,KAAK;AAAA,IACd,CAAC;AACD,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,MAAM,KAAK;AAAA,EAClB;AACF;;;AClCO,IAAM,iBAAiB,CAAC,YAA4C;AAAA,EACzE,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,aAAa,GAAG,MAAM;AACxB;AAqBA,IAAM,YAAY,OAAO,aAAyC;AAChE,MAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,SAAS,IAAI;AACf,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAQA,IAAM,UAAU,OAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAiC;AAC/B,QAAM,UAAU,eAAe,MAAM;AAErC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,GAAI,SAAS,SAAY,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,kBAAkB,EAAE,QAAQ,KAAK,MAAM,CAAC;AAAA,EACpD;AAEA,QAAM,SAAS,MAAM,UAAU,QAAQ;AAEvC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,cAAc;AAAA,MACtB,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS;AAAA,MACrB;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAOO,IAAM,aAAa,CACxB,KACA,WACe,QAAW,EAAE,QAAQ,OAAO,KAAK,OAAO,CAAC;AAQnD,IAAM,cAAc,CACzB,KACA,QACA,SACe,QAAW,EAAE,QAAQ,QAAQ,KAAK,QAAQ,KAAK,CAAC;;;ACrGjE,IAAM,cAAc,MAAM;AAAA,EAEtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,aAAqB;AACjB,SAAK,MAAM,KAAK,IAAI,YAAY;AAChC,YAAS,KAAK,KAAM;AAAA,MAChB,KAAK;AAAA,MACL,KAAK;AACD,eAAO,gDAAgD,KAAK,OAAO;AAAA,MACvE,KAAK;AAAA,MACL,KAAK;AACD,eAAO,2CAA2C,KAAK,OAAO;AAAA,MAClE,KAAK;AAAA,MACL,KAAK;AACD,eAAO,+CAA+C,KAAK,OAAO;AAAA,MACtE,KAAK;AAAA,MACL;AACI,eAAO,8BAA8B,KAAK,OAAO;AAAA,IACzD;AAAA,EACJ;AAAA,EAGA,YAAa,SAAO,IAAI,MAAI,SAASA,WAAQ,MAAQ;AACjD,SAAK,SAAS;AACd,SAAK,MAAM;AACX,SAAK,UAAUA;AACf,SAAK,UAAU,KAAK,WAAW;AAAA,EACnC;AAAA,EAEA,gBAAiB,SAAkB;AAC/B,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,aAAc,KAA8C,OAAe;AACvE,SAAK,GAAG,GAAG,EAAE,IAAI;AAAA,EACrB;AAAA,EAEA,aAAc,KAAuD;AACjE,WAAO,KAAK,GAAG;AAAA,EACnB;AAAA,EAGA,MAAM,SAA8B;AAChC,WAAO,WAAwB,GAAG,KAAK,OAAO,cAAc,KAAK,MAAO;AAAA,EAC5E;AAAA,EAGA,MAAM,SAA2B;AAC7B,WAAO,WAAqB,GAAG,KAAK,OAAO,WAAW,KAAK,MAAO;AAAA,EACtE;AAAA,EAGA,MAAM,gBAAkC;AACpC,WAAO,WAAqB,GAAG,KAAK,OAAO,kBAAkB,KAAK,MAAO;AAAA,EAC7E;AAAA,EAGA,MAAM,kBAAmB,IAAmD;AACxE,WAAO,WAAgC,GAAG,KAAK,OAAO,sBAAsB,EAAE,IAAI,KAAK,MAAO;AAAA,EAClG;AAAA,EAGA,MAAM,gBAAiB,QAA2D;AAE9E,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAC9B,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,kBAAkB,OAAQ,OAAO,gBAAiB;AAAA,MAClD,aAAa,OAAQ,OAAO,WAAY;AAAA,IAC5C,CAAC;AACD,WAAO,WAA8B,GAAG,KAAK,OAAO,oBAAoB,KAAK,IAAI,KAAK,MAAO;AAAA,EACjG;AAAA,EAGA,MAAM,qBAAsB,aAA+D;AACvF,WAAO,WAAmC,GAAG,KAAK,OAAO,yBAAyB,WAAW,IAAI,KAAK,MAAO;AAAA,EACjH;AAAA,EAGA,MAAM,aAAc,aAAwD;AACxE,UAAM,QAAQ,IAAI,gBAAgB,EAAE,aAAa,OAAQ,WAAY,EAAE,CAAC;AACxE,WAAO,WAA4B,GAAG,KAAK,OAAO,iBAAiB,KAAK,IAAI,KAAK,MAAO;AAAA,EAC5F;AAAA,EAGA,MAAM,oBAAqB,QAAqE;AAC5F,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAC9B,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,IACrB,CAAC;AAED,eAAY,MAAM,OAAO,eAAgB;AACrC,YAAM,OAAQ,iBAAiB,OAAQ,EAAG,CAAE;AAAA,IAChD;AACA,WAAO,WAAoC,GAAG,KAAK,OAAO,wBAAwB,KAAK,IAAI,KAAK,MAAO;AAAA,EAC3G;AAAA,EAGA,MAAM,iBAAkB,QAAkE;AAEtF,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAC9B,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,aAAa,OAAQ,OAAO,WAAY;AAAA,IAC5C,CAAC;AACD,eAAY,MAAM,OAAO,eAAgB;AACrC,YAAM,OAAQ,iBAAiB,OAAQ,EAAG,CAAE;AAAA,IAChD;AACA,WAAO,WAAoC,GAAG,KAAK,OAAO,qBAAqB,KAAK,IAAI,KAAK,MAAO;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAA+C;AACjD,WAAO,WAAgC,GAAG,KAAK,OAAO,uBAAuB,KAAK,MAAO;AAAA,EAC7F;AAAA,EAGA,MAAM,eAAgB,aAA4D;AAC9E,WAAO,WAAgC,GAAG,KAAK,OAAO,sBAAsB,WAAW,IAAI,KAAK,MAAO;AAAA,EAC3G;AAAA,EAGA,MAAM,eAAgB,gBAA2D;AAC7E,UAAM,QAAQ,IAAI,gBAAgB,EAAE,gBAAgB,OAAQ,cAAe,EAAE,CAAC;AAC9E,WAAO,WAAqC,GAAG,KAAK,OAAO,mBAAmB,KAAK,IAAI,KAAK,MAAO;AAAA,EACvG;AAAA,EAGA,MAAM,gBAAiB,SAAuE;AAC1F,WAAO,YAAsC,GAAG,KAAK,OAAO,oBAAoB,KAAK,QAAQ,OAAQ;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAc,SAA6B,CAAC,GAA4B;AAC1E,UAAM,QAAQ,IAAI,gBAAgB;AAClC,QAAK,OAAO,SAAS,QAAY;AAC7B,YAAM,IAAK,QAAQ,OAAQ,OAAO,IAAK,CAAE;AAAA,IAC7C;AACA,UAAM,KAAK,MAAM,SAAS;AAC1B,WAAO,WAA2B,GAAG,KAAK,OAAO,gBAAgB,KAAK,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,MAAO;AAAA,EACvG;AAGJ;AAEA,IAAO,uBAAQ;","names":["version"]}
|