2 * API Request Routing Logic
4 * Determines the correct API endpoint based on:
5 * - Request type (openapi, gnap, elink)
6 * - Current store context
9 * Store URLs are built dynamically from environment variable:
10 * NEXT_PUBLIC_FIELDPINE_STORE_DOMAIN (default: cwanz.online)
11 * Format: https://{store-id}.{domain}
12 * Examples: https://cowra.cwanz.online, https://iig.cwanz.online
15import { Store } from './stores';
17export type RequestType = 'openapi' | 'gnap' | 'elink';
19export interface RoutingContext {
21 requestType: RequestType;
25 * Get the appropriate endpoint URL based on request type and store
28 * - OpenAPI: Routes to store URL (e.g., cowra.cwanz.online/openapi)
29 * Only available for store types, NOT for management portal
31 * - GNAP: Always routes to IIG management portal (iig.cwanz.online/GNAP/j)
32 * Used for central reporting and cross-store operations
34 * - ELINK: Routes to store URL (e.g., cowra.cwanz.online/GNAP/j)
35 * Used for store-specific configuration
37export function getEndpointUrl(
38 requestType: RequestType,
41 switch (requestType) {
43 if (store.type === 'management') {
45 'OpenAPI endpoints are not available when logged into the management portal. ' +
46 'Please log into a specific store to access POS functions.'
49 return `${store.url}/openapi`;
52 // GNAP requests always go to IIG management portal for central operations
53 return 'https://iig.cwanz.online/GNAP/j';
56 // ELINK requests go to the current store for store-specific config
57 return `${store.url}/GNAP/j`;
60 throw new Error(`Unknown request type: ${requestType}`);
65 * Validate that a request is allowed for the current store context
68 * - Retail stores: Can ONLY access ELINK endpoints
69 * - Management portal: Can access OpenAPI, GNAP, and ELINK
70 * - OpenAPI: Management portal ONLY (for centralized POS operations)
71 * - GNAP: Management portal ONLY (for reporting and analytics)
72 * - ELINK: Both retail stores and management portal (store-specific operations)
74export function validateRequest(
75 requestType: RequestType,
77): { valid: boolean; error?: string } {
78 // Management portal has full access
79 if (store.type === 'management') {
80 return { valid: true };
83 // Retail stores can ONLY use ELINK
84 if (store.type === 'store') {
85 if (requestType === 'openapi') {
88 error: 'Security: Retail stores cannot access OpenAPI. Use ELINK endpoints for store operations.'
92 if (requestType === 'gnap') {
95 error: 'Security: Retail stores cannot access GNAP. This is restricted to management portal.'
99 if (requestType === 'elink') {
100 return { valid: true };
106 error: 'Invalid request type or store type'
111 * Get the appropriate request type for common operations
113export function getRequestTypeForOperation(operation: string): RequestType {
114 // POS Operations - OpenAPI
115 if (operation.match(/^(products|sales|customers|inventory|stock)/i)) {
119 // Reporting and cross-store - GNAP
120 if (operation.match(/^(report|analytics|cross-store)/i)) {
124 // Store configuration - ELINK
125 if (operation.match(/^(config|settings|store-setup)/i)) {
129 // Default to GNAP for unknown operations
134 * Build full API URL with query parameters
136export function buildApiUrl(
139 params?: Record<string, string>
141 const url = new URL(path, baseUrl);
144 Object.entries(params).forEach(([key, value]) => {
145 url.searchParams.append(key, value);
149 return url.toString();