#!/usr/bin/env node /** Scaffolds communication app routes + locked feature pages */ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); const APP = path.join(ROOT, "app", "communication"); const FEATURES = path.join(ROOT, "modules", "communication", "features"); const lockKeyMap = { email: "email", whatsapp: "whatsapp", telegram: "telegram", rubika: "rubika", push: "push", voice: "voice", video: "video", liveChat: "live_chat", omnichannelInbox: "omnichannel_inbox", marketingAutomation: "marketing_automation", automationTriggers: "automation_triggers", journeyBuilder: "journey_builder", aiCampaigns: "ai_campaigns", webhookCenter: "webhook_center", connectors: "connectors", conversations: "conversations", campaignOrchestrator: "campaign_orchestrator", notificationCenter: "notification_center", templateCategories: "template_categories", roles: "roles", audit: "audit", apiKeys: "api_keys", integrationsHub: "integrations_hub", }; const PAGES = [ ["", "ExecutiveDashboard", "executiveDashboard"], ["dashboard", "CommunicationDashboard", "dashboard"], ["providers/dashboard", "ProviderDashboard", "providerDashboard"], ["sms", "SmsDashboard", "smsDashboard"], ["sms/providers", "ProvidersPage", "providers"], ["sms/templates", "TemplatesPage", "templates"], ["sms/template-categories", "TemplateCategoriesPage", "templateCategories"], ["sms/senders", "SendersPage", "senders"], ["sms/campaigns", "CampaignsPage", "campaigns"], ["sms/send", "SendMessagePage", "sendMessage"], ["sms/queue", "QueuePage", "queue"], ["sms/delivery-reports", "DeliveryReportsPage", "deliveryReports"], ["sms/messages", "MessagesPage", "messages"], ["contacts/recipients", "RecipientsPage", "recipients"], ["contacts/sources", "ContactSourcesPage", "contactSources"], ["contacts/address-books", "AddressBooksPage", "recipients"], ["email", "EmailPage", "email"], ["whatsapp", "WhatsappPage", "whatsapp"], ["telegram", "TelegramPage", "telegram"], ["rubika", "RubikaPage", "rubika"], ["push", "PushPage", "push"], ["voice", "VoicePage", "voice"], ["video", "VideoPage", "video"], ["live-chat", "LiveChatPage", "liveChat"], ["inbox", "OmnichannelInboxPage", "omnichannelInbox"], ["automation", "MarketingAutomationPage", "marketingAutomation"], ["automation/triggers", "AutomationTriggersPage", "automationTriggers"], ["journey-builder", "JourneyBuilderPage", "journeyBuilder"], ["ai-campaigns", "AiCampaignsPage", "aiCampaigns"], ["webhooks", "WebhookCenterPage", "webhookCenter"], ["connectors", "ConnectorsPage", "connectors"], ["conversations", "ConversationsPage", "conversations"], ["campaign-orchestrator", "CampaignOrchestratorPage", "campaignOrchestrator"], ["notifications", "NotificationCenterPage", "notificationCenter"], ["monitoring", "MonitoringPage", "monitoring"], ["analytics", "AnalyticsPage", "monitoring"], ["reports", "ReportsPage", "monitoring"], ["health", "HealthPage", "health"], ["capabilities", "CapabilitiesPage", "capabilities"], ["settings", "SettingsPage", "settings"], ["permissions", "PermissionsPage", "permissions"], ["roles", "RolesPage", "roles"], ["audit", "AuditPage", "audit"], ["api-keys", "ApiKeysPage", "apiKeys"], ["integrations", "IntegrationsHubPage", "integrationsHub"], ["otp", "OtpPage", "otp"], ]; function ensureDir(d) { fs.mkdirSync(d, { recursive: true }); } function writeLockedFeature(featureFile, lockKey, exportName) { const file = path.join(FEATURES, `${featureFile}.tsx`); if (fs.existsSync(file)) return; fs.writeFileSync( file, `import { createCommunicationLockedPage } from "@/modules/communication/components/CommunicationFeatureLock"; import { FUTURE_MODULE_REGISTRY } from "@/modules/communication/constants/featureRegistry"; const config = FUTURE_MODULE_REGISTRY.${lockKey}!; export const ${exportName} = createCommunicationLockedPage(config); export default ${exportName}; ` ); } function writeRoute(routePath, exportName, featureFile) { const dir = path.join(APP, routePath); ensureDir(dir); fs.writeFileSync( path.join(dir, "page.tsx"), `"use client"; export { ${exportName} as default } from "@/modules/communication/features/${featureFile}"; ` ); fs.writeFileSync( path.join(dir, "loading.tsx"), `import { LoadingState } from "@/components/ds"; export default function Loading() { return ; } ` ); fs.writeFileSync( path.join(dir, "error.tsx"), `"use client"; import { ErrorState } from "@/components/ds"; export default function Error({ error, reset }: { error: Error; reset: () => void }) { return ; } ` ); } ensureDir(APP); fs.writeFileSync( path.join(APP, "layout.tsx"), `"use client"; import { CommunicationRootLayout } from "@/modules/communication/components/createPortalLayout"; export default CommunicationRootLayout; ` ); fs.writeFileSync( path.join(APP, "not-found.tsx"), `import Link from "next/link"; import { EmptyState, Button } from "@/components/ds"; export default function NotFound() { return ( } /> ); } ` ); for (const [file, key] of Object.entries(lockKeyMap)) { const exportName = file.charAt(0).toUpperCase() + file.slice(1) + "Page"; writeLockedFeature(file, key, exportName); } for (const [route, exportName, featureFile] of PAGES) { writeRoute(route, exportName, featureFile); } console.log(`Scaffolded ${PAGES.length} communication routes`);