diff --git a/server.ts b/server.ts index bfe9f5f..4bb64f3 100644 --- a/server.ts +++ b/server.ts @@ -3,12 +3,16 @@ import { Hono } from 'hono'; import { serveStatic } from 'hono/bun'; import { cors } from 'hono/cors'; import PocketBase from 'pocketbase'; -import { ConfidentialClientApplication } from '@azure/msal-node'; // --------------------------------------------------------------------------- // Config // --------------------------------------------------------------------------- -config({ path: '/home/admin/secrets/.env' }); +const PRIMARY_ENV_PATH = 'C:\\Users\\AlfonsoEwing\\OneDrive - Cardoza Construction\\Apps\\Secrets\\.env'; +const FALLBACK_ENV_PATH = 'D:\\.env'; +const primaryEnv = config({ path: PRIMARY_ENV_PATH }); +if (primaryEnv.error) { + config({ path: FALLBACK_ENV_PATH }); +} // Known OneNote target // Section/page IDs must come from the OneNote Graph API (sites/{siteId}/onenote/sections), @@ -365,19 +369,39 @@ function findRecordFieldName(record: Record, patterns: RegExp[] // --------------------------------------------------------------------------- // MSAL app-only (Graph status check) // --------------------------------------------------------------------------- -const cca = new ConfidentialClientApplication({ - auth: { - clientId: process.env.CLIENT_ID || '', - authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`, - clientSecret: process.env.CLIENT_SECRET || '', - }, -}); +type ClientCredentialResult = { + accessToken?: string; + expiresOn?: Date | string | null; +} | null; + +type ClientCredentialApp = { + acquireTokenByClientCredential: (request: { scopes: string[] }) => Promise; +}; + +let ccaPromise: Promise | null = null; + +async function getConfidentialClientApp(): Promise { + if (!ccaPromise) { + ccaPromise = (async () => { + const msal = await import('@azure/msal-node'); + return new msal.ConfidentialClientApplication({ + auth: { + clientId: process.env.CLIENT_ID || '', + authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`, + clientSecret: process.env.CLIENT_SECRET || '', + }, + }); + })(); + } + return ccaPromise; +} let graphTokenCache: { token: string; expiresOn: number } | null = null; async function getGraphToken() { const now = Date.now(); if (graphTokenCache && graphTokenCache.expiresOn - 60_000 > now) return graphTokenCache; + const cca = await getConfidentialClientApp(); const result = await cca.acquireTokenByClientCredential({ scopes: ['https://graph.microsoft.com/.default'] }); if (!result?.accessToken) throw new Error('Failed to acquire Graph token'); graphTokenCache = {