UNPKG

@letsparky/api-v2-client

Version:

TypeScript client for the LetsParky API V2

397 lines (396 loc) 16.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LetsParkyClient = exports.testUtils = exports.logger = exports.LogLevel = exports.Logger = exports.ErrorCodes = exports.createStandardError = exports.ConfigurationError = exports.RateLimitError = exports.TokenExpiredError = exports.ValidationError = exports.AuthenticationError = exports.NetworkError = exports.ApiError = exports.PaymentStatus = exports.PaymentType = exports.EntityStatus = exports.UserStatus = exports.UserRole = exports.UserGender = exports.ParkingAreaType = exports.ParkingStatus = exports.Environment = void 0; const client_1 = require("./client"); const auth_1 = require("./auth"); const devices_1 = require("./devices"); const device_logs_1 = require("./device_logs"); const memberships_1 = require("./memberships"); const parkings_1 = require("./parkings"); const parking_areas_1 = require("./parking_areas"); const payments_1 = require("./payments"); const users_1 = require("./users"); const tenants_1 = require("./tenants"); const system_1 = require("./system"); const types_1 = require("./types"); const logger_1 = require("./logger"); Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } }); const errors_1 = require("./errors"); const testUtils = __importStar(require("./test-utils")); exports.testUtils = testUtils; // Export types explicitly var types_2 = require("./types"); Object.defineProperty(exports, "Environment", { enumerable: true, get: function () { return types_2.Environment; } }); Object.defineProperty(exports, "ParkingStatus", { enumerable: true, get: function () { return types_2.ParkingStatus; } }); Object.defineProperty(exports, "ParkingAreaType", { enumerable: true, get: function () { return types_2.ParkingAreaType; } }); Object.defineProperty(exports, "UserGender", { enumerable: true, get: function () { return types_2.UserGender; } }); Object.defineProperty(exports, "UserRole", { enumerable: true, get: function () { return types_2.UserRole; } }); Object.defineProperty(exports, "UserStatus", { enumerable: true, get: function () { return types_2.UserStatus; } }); Object.defineProperty(exports, "EntityStatus", { enumerable: true, get: function () { return types_2.EntityStatus; } }); Object.defineProperty(exports, "PaymentType", { enumerable: true, get: function () { return types_2.PaymentType; } }); Object.defineProperty(exports, "PaymentStatus", { enumerable: true, get: function () { return types_2.PaymentStatus; } }); // Export errors explicitly var errors_2 = require("./errors"); Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return errors_2.ApiError; } }); Object.defineProperty(exports, "NetworkError", { enumerable: true, get: function () { return errors_2.NetworkError; } }); Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_2.AuthenticationError; } }); Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_2.ValidationError; } }); Object.defineProperty(exports, "TokenExpiredError", { enumerable: true, get: function () { return errors_2.TokenExpiredError; } }); Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_2.RateLimitError; } }); Object.defineProperty(exports, "ConfigurationError", { enumerable: true, get: function () { return errors_2.ConfigurationError; } }); Object.defineProperty(exports, "createStandardError", { enumerable: true, get: function () { return errors_2.createStandardError; } }); Object.defineProperty(exports, "ErrorCodes", { enumerable: true, get: function () { return errors_2.ErrorCodes; } }); var logger_2 = require("./logger"); Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_2.Logger; } }); Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_2.LogLevel; } }); /** * Main client class for the LetsParky API v2. * * This is the primary entry point for interacting with the LetsParky API. * It provides a unified interface that combines all API functionality including * device management, parking operations, user management, tenant operations, * and authentication. * * The client automatically handles: * - Authentication and token management * - Rate limiting and retries * - Error handling and logging * - Environment-specific configuration * * @example * ```typescript * // Basic usage with API key * const client = new LetsParkyClient({ * apiKey: 'your-api-key', * environment: Environment.PRODUCTION * }); * * // Usage with email/password * const client = new LetsParkyClient({ * email: 'your-email', * password: 'your-password', * environment: Environment.STAGING * }); * * // Access specific functionality * const devices = await client.listDevices(); * const parkings = await client.listParkings(); * const profile = await client.getProfile(); * * // Or use the specialized clients directly * const newDevice = await client.devices.create({ * name: 'Sensor 1', * type: 'ultrasonic' * }); * ``` * * @since 1.0.0 */ class LetsParkyClient { /** * Creates a new LetsParkyClient instance. * * @param config - Configuration options for the client * @param config.apiKey - API key for authentication (alternative to email/password) * @param config.baseUrl - Custom base URL for the API (overrides environment-based URL) * @param config.timeout - Request timeout in milliseconds (default: 30000) * @param config.email - Email for authentication (requires password) * @param config.password - Password for authentication (requires email) * @param config.environment - Target environment (default: PRODUCTION) * @param config.logLevel - Logging level (default: INFO) * @param config.silentLogs - Disable all logging (default: false) * @param config.useHttps - Force HTTPS usage (default: false, auto-enabled for production) * @param config.acceptSelfSigned - Accept self-signed certificates in development (default: false) * @param config.rateLimitRetryCount - Number of retries when rate limited (default: 3) * @param config.rateLimitRetryDelay - Base delay between retries in milliseconds (default: 1000) * * @example * ```typescript * // Production client with API key * const client = new LetsParkyClient({ * apiKey: 'pk_live_...', * environment: Environment.PRODUCTION, * logLevel: LogLevel.WARN * }); * * // Development client with credentials * const devClient = new LetsParkyClient({ * email: 'dev-user', * password: 'dev-password', * environment: Environment.DEVELOPMENT, * useHttps: false, * acceptSelfSigned: true, * logLevel: LogLevel.DEBUG * }); * ``` * * @throws {ConfigurationError} When invalid configuration is provided * @throws {AuthenticationError} When automatic authentication fails (if email/password provided) * * @since 1.0.0 */ constructor(config = {}) { this.client = new client_1.ApiClient(config); this.auth = new auth_1.Auth(this.client); this.devices = new devices_1.Devices(this.client); this.deviceLogs = new device_logs_1.DeviceLogs(this.client); this.memberships = new memberships_1.Memberships(this.client); this.parkings = new parkings_1.Parkings(this.client); this.parkingAreas = new parking_areas_1.ParkingAreas(this.client); this.payments = new payments_1.Payments(this.client); this.users = new users_1.Users(this.client); this.tenants = new tenants_1.Tenants(this.client); this.system = new system_1.System(this.client); } /** * Sets the target environment for the client. * * This method changes the environment and automatically updates the base URL * to match the selected environment. It also propagates the environment * setting to validators and other components. * * @param environment - The target environment * * @example * ```typescript * const client = new LetsParkyClient(); * * // Switch to development for testing * client.setEnvironment(Environment.DEVELOPMENT); * * // Switch to production * client.setEnvironment(Environment.PRODUCTION); * ``` * * @since 1.0.0 */ setEnvironment(environment) { this.client.setEnvironment(environment); } /** * Sets the logging level for the client. * * This controls the verbosity of log output from the client and all * its components. Higher levels include all lower levels. * * @param level - The logging level to set * * @example * ```typescript * const client = new LetsParkyClient(); * * // Enable debug logging for development * client.setLogLevel(LogLevel.DEBUG); * * // Only show errors in production * client.setLogLevel(LogLevel.ERROR); * ``` * * @since 1.0.0 */ setLogLevel(level) { this.client.setLogLevel(level); } /** * Authenticates the client using configured email and password. * * This is a convenience method that delegates to the underlying client's * authenticate method. The client must have been configured with email * and password for this to work. * * @returns Promise that resolves when authentication is successful * * @throws {AuthenticationError} When email/password are missing or authentication fails * @throws {NetworkError} When the request fails due to network issues * * @example * ```typescript * const client = new LetsParkyClient({ * email: 'your-email', * password: 'your-password' * }); * * try { * await client.authenticate(); * console.log('Successfully authenticated'); * } catch (error) { * console.error('Authentication failed:', error.message); * } * ``` * * @since 1.0.0 */ async authenticate() { return this.client.authenticate(); } /** * Retrieves a list of all devices. * * This is a convenience method that delegates to the devices client. * For more advanced device operations, use the `devices` property directly. * * @returns Promise resolving to an array of devices * * @throws {AuthenticationError} When authentication is required or fails * @throws {ApiError} When the API returns an error response * @throws {NetworkError} When the request fails due to network issues * * @example * ```typescript * const client = new LetsParkyClient({ apiKey: 'your-api-key' }); * * const devices = await client.listDevices(); * console.log(`Found ${devices.length} devices`); * * devices.forEach(device => { * console.log(`- ${device.name} (${device.type})`); * }); * ``` * * @since 1.0.0 */ async listDevices() { const devices = await this.devices.list(); return devices; } /** * Get current rate limit information */ getRateLimitInfo() { return this.client.getRateLimitInfo(); } /** * List all devices with pagination * @param page Page number (starting from 1) * @param limit Items per page * @param filters Optional filters */ async listDevicesPaginated(page = 1, limit = 10, filters) { const response = await this.devices.listPaginated({ page, limit }, filters); return response.data; } /** * List all parkings * @param filters Optional filter parameters for parkings */ async listParkings(filters) { const parkings = await this.parkings.list(filters); return parkings; } /** * Get user profile * Convenience method that delegates to auth.getProfile() */ async getProfile() { const response = await this.auth.getProfile(); return response.data; } /** * List all tenants (SYSTEM only) * @param filters Optional filter parameters for tenants * Convenience method that delegates to tenants.list() */ async listTenants(filters) { const response = await this.tenants.list(filters); return response.data; } /** * Check if the API endpoint is responding * Useful for verifying connectivity before running tests * @returns Promise that resolves to true if the API is online, false otherwise */ async isApiOnline() { try { // Try to access the base URL await this.client.get('/'); return true; } catch (error) { if (error instanceof errors_1.ApiError && error.status === 404) { // 404 means the API is responding but the specific endpoint doesn't exist return true; } return false; } } /** * Get device logs with optional filtering * Convenience method that delegates to deviceLogs.list() * @param filters Optional filter parameters for device logs */ async getDeviceLogs(filters) { const response = await this.deviceLogs.list(filters); return response.data; } /** * Get analytics for a specific device * Convenience method that delegates to deviceLogs.getAnalytics() * @param deviceId The device ID to get analytics for * @param params Optional time range parameters */ async getDeviceAnalytics(deviceId, params) { const response = await this.deviceLogs.getAnalytics(deviceId, params); return response.data; } /** * Get the latest log for a specific device * Convenience method that delegates to deviceLogs.getLatest() * @param deviceId The device ID to get the latest log for */ async getLatestDeviceLog(deviceId) { const response = await this.deviceLogs.getLatest(deviceId); return response.data; } /** * Download device logs as an Excel file. * In browser contexts this will prompt the user with a file download dialog. * In Node.js it resolves with a Buffer containing the file contents. * * @param filters Optional filter parameters (same as getDeviceLogs) */ async downloadDeviceLogs(filters) { return this.deviceLogs.download(filters); } /** * Initialize client with test/mock data * Use this for testing when the actual API might not be available * @param options Configuration for mock data */ setupTestEnvironment(options = {}) { // Set up mock data as needed if (options.authToken) { this.client.setToken(options.authToken); } // Set environment to development this.setEnvironment(types_1.Environment.DEVELOPMENT); // Set log level to debug for testing this.setLogLevel(types_1.LogLevel.DEBUG); logger_1.logger.warn('Client initialized in TEST environment with mock data'); } } exports.LetsParkyClient = LetsParkyClient; // Export LetsParkyClient as default exports.default = LetsParkyClient;