@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 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.2" : "0.0.0";
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:
@@ -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" : "0.0.0";
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":"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","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lagunacreek/hogan-pms-client",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Shared client for the Hogan PMS API: connection logic and typed data-access methods.",
5
5
  "license": "MIT",
6
6
  "type": "module",