diff --git a/package.json b/package.json index a1ede84..1c92d78 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@fastify/cors": "^9.0.1", "fastify": "^4.28.1", "nodemailer": "^6.10.1", + "mssql": "^11.0.1", "pg": "^8.12.0" } } diff --git a/src/routes/integrations.js b/src/routes/integrations.js index e9e5605..b4db783 100644 --- a/src/routes/integrations.js +++ b/src/routes/integrations.js @@ -141,25 +141,28 @@ export async function integrationRoutes(app) { } else if (req.params.slug === 'sambapos') { const errors = [] - // SQL test + // SQL test — SambaPOS uses MSSQL; host may be "server\INSTANCE" try { if (!creds.sql_host || !creds.sql_database || !creds.sql_username || !creds.sql_password) throw new Error('SQL host, database, username and password are required') - const { default: pg } = await import('pg') - const sqlPool = new pg.Pool({ - host: creds.sql_host, port: parseInt(creds.sql_port || '5432'), - database: creds.sql_database, user: creds.sql_username, password: creds.sql_password, - connectionTimeoutMillis: 8000, max: 1, - }) - await sqlPool.query('SELECT 1') - await sqlPool.end() + const { default: sql } = await import('mssql') + const [sqlServer, sqlInstance] = creds.sql_host.split('\\') + const cfg = { + server: sqlServer, + database: creds.sql_database, + authentication: { type: 'default', options: { userName: creds.sql_username, password: creds.sql_password } }, + options: { trustServerCertificate: true, connectTimeout: 8000, ...(sqlInstance ? { instanceName: sqlInstance } : { port: parseInt(creds.sql_port || '1433') }) }, + } + const pool = await sql.connect(cfg) + await pool.request().query('SELECT 1') + await pool.close() } catch (e) { errors.push(`SQL: ${e.message}`) } - // GraphQL test — obtain token via password grant then run a minimal query + // GraphQL test — token endpoint lives at origin, not inside /api path try { if (!creds.graphql_endpoint || !creds.graphql_username || !creds.graphql_password || !creds.graphql_client_id) throw new Error('GraphQL endpoint, username, password and client ID are required') - const base = creds.graphql_endpoint.replace(/\/$/, '') - const tokenRes = await fetch(`${base}/connect/token`, { + const origin = new URL(creds.graphql_endpoint).origin + const tokenRes = await fetch(`${origin}/connect/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ @@ -174,7 +177,7 @@ export async function integrationRoutes(app) { if (!tokenRes.ok) throw new Error(`Token request failed (${tokenRes.status})`) const { access_token } = await tokenRes.json() if (!access_token) throw new Error('No access token returned') - const gqlRes = await fetch(`${base}/api`, { + const gqlRes = await fetch(creds.graphql_endpoint.replace(/\/$/, ''), { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${access_token}` }, body: JSON.stringify({ query: '{ __typename }' }),