Change serverless to typescript.

This commit is contained in:
Patrick Fic
2026-01-13 14:45:31 -08:00
parent ea4131102c
commit 319e2e37df
16 changed files with 4660 additions and 162 deletions

View File

@@ -1,16 +1,33 @@
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const s3Client = new S3Client({ region: process.env.AWS_REGION || 'ca-central-1' });
const BUCKET_NAME = process.env.UPLOAD_BUCKET_NAME;
const BUCKET_NAME = process.env.UPLOAD_BUCKET_NAME || '';
interface EmsUploadRequest {
esApiKey: string;
ciecaid: string;
clm_no: string;
ownr_ln: string;
}
interface EmsUploadResponse {
success: boolean;
presignedUrl?: string;
key?: string;
bucket?: string;
expiresIn?: number;
error?: string;
message?: string;
}
/**
* Validates the EMS Upload ID
* @param {string} emsUploadId - The EMS Upload ID to validate
* @param {string} esApiKey - The ES API Key to validate
* @returns {boolean} - Always returns true for now (placeholder)
*/
function validateEmsUploadId(esApiKey) {
function validateEmsUploadId(_esApiKey: string): boolean {
// Placeholder validation - always returns true
// TODO: Implement actual validation logic
return true;
@@ -18,12 +35,12 @@ function validateEmsUploadId(esApiKey) {
/**
* Lambda handler for EMS Upload
* Expects a JSON body with: { emsUploadId: string, fileName?: string }
* Expects a JSON body with: { esApiKey: string, ciecaid: string, clm_no: string, ownr_ln: string }
*/
exports.handler = async (event) => {
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
// Parse the request body
const body = JSON.parse(event.body || '{}');
const body = JSON.parse(event.body || '{}') as EmsUploadRequest;
const { esApiKey, ciecaid, clm_no, ownr_ln } = body;
// Validate required fields
@@ -31,8 +48,8 @@ exports.handler = async (event) => {
return {
statusCode: 400,
body: JSON.stringify({
error: 'Missing required field: esApiKey'
}),
error: 'Missing required field: esApiKey',
} as EmsUploadResponse),
};
}
@@ -42,50 +59,57 @@ exports.handler = async (event) => {
return {
statusCode: 401,
body: JSON.stringify({
error: 'Invalid ES API Key'
})
error: 'Invalid ES API Key',
} as EmsUploadResponse),
};
}
// Generate a unique key for the upload
const key = `${esApiKey}/${ciecaid}-${clm_no}-${ownr_ln}-${new Date().toISOString().replace(/T/, '--').replace(/\..+/, '').replace(/:/g, '-')}.zip`;
const timestamp = new Date()
.toISOString()
.replace(/T/, '--')
.replace(/\..+/, '')
.replace(/:/g, '-');
const key = `${esApiKey}/${ciecaid}-${clm_no}-${ownr_ln}-${timestamp}.zip`;
// Create the presigned URL for upload (valid for 15 minutes)
const command = new PutObjectCommand({
Bucket: BUCKET_NAME,
Key: key,
StorageClass: "INTELLIGENT_TIERING"
StorageClass: 'INTELLIGENT_TIERING',
});
const presignedUrl = await getSignedUrl(s3Client, command, {
expiresIn: 900 // 15 minutes
expiresIn: 900, // 15 minutes
});
console.log('Generated presigned URL for key:', key);
console.log('Presigned URL:', presignedUrl);
// Return success response with presigned URL and key
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
body: JSON.stringify({
success: true,
presignedUrl,
key,
bucket: BUCKET_NAME,
expiresIn: 900
})
expiresIn: 900,
} as EmsUploadResponse),
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.error('Error generating presigned URL:', error);
return {
statusCode: 500,
body: JSON.stringify({
error: 'Internal server error',
message: error.message
})
message: errorMessage,
} as EmsUploadResponse),
};
}
};
};

View File

@@ -1,63 +0,0 @@
const axios = require('axios');
const FormData = require('form-data');
const ES_USER = process.env.ES_USER;
const ES_PASSWORD = process.env.ES_PASSWORD;
const ES_ENDPOINT = process.env.ES_ENDPOINT;
const getVehicleType = require("../lib/vehicleTypes/vehicleType").getVehicleType;
exports.handler = async (event) => {
// Path parameters are automatically parsed for you
//Take the estimate details, add them to the database, scrub it, and then retrun the result and add the scrubbed results to database.
try {
const { esApiKey, estimate } = event.body ? JSON.parse(event.body) : {};
//TODO: Replace the previous vehicle logic with just getting it here.
estimate.v_type = getVehicleType(estimate.v_model).type;
estimate.sendingEntityId = "87330f61-412b-4251-baaa-d026565b23c5";
const fileName = `${esApiKey}-${estimate.clm_no}-${Date.now()}`;
const formData = new FormData();
const jsonString = JSON.stringify(estimate);
formData.append(
"file",
Buffer.from(jsonString),
{
filename: `${fileName}.json`,
contentType: 'application/json'
}
);
const result = await axios.post(
`${ES_ENDPOINT}/api/sendems`,
formData,
{
auth: {
username: ES_USER,
password: ES_PASSWORD,
},
headers: {
APIkey: esApiKey,
},
},
);
const resultPDFUrl = result?.data?.report_link;
const reportIssueUrl = `https://insurtechtoolkit.com/pcontactUs.aspx?apiKey=${esApiKey}&file=${fileName}.json`;
return {
statusCode: 200,
body: JSON.stringify({
resultPDFUrl, reportIssueUrl, identified_item: result.data?.identified_item
}),
}
}
catch (error) {
return {
statusCode: 400,
body: JSON.stringify({
message: `Error scrubbing estimate.`,
error: error.response.data || error.message || 'Unknown error',
})
};
}
};

View File

@@ -0,0 +1,78 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import axios, { AxiosError } from 'axios';
import FormData from 'form-data';
import { getVehicleType } from '../lib/vehicleTypes/vehicleType';
const ES_USER = process.env.ES_USER || '';
const ES_PASSWORD = process.env.ES_PASSWORD || '';
const ES_ENDPOINT = process.env.ES_ENDPOINT || '';
interface Estimate {
v_type?: string;
v_model: string;
clm_no: string;
sendingEntityId?: string;
[key: string]: unknown;
}
interface ScrubRequest {
esApiKey: string;
estimate: Estimate;
}
interface ScrubResponse {
report_link?: string;
identified_item?: unknown;
}
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const { esApiKey, estimate } = JSON.parse(event.body || '{}') as ScrubRequest;
// Set vehicle type and sending entity ID
estimate.v_type = getVehicleType(estimate.v_model).type;
estimate.sendingEntityId = '87330f61-412b-4251-baaa-d026565b23c5';
const fileName = `${esApiKey}-${estimate.clm_no}-${Date.now()}`;
const formData = new FormData();
const jsonString = JSON.stringify(estimate);
formData.append('file', Buffer.from(jsonString), {
filename: `${fileName}.json`,
contentType: 'application/json',
});
const result = await axios.post<ScrubResponse>(`${ES_ENDPOINT}/api/sendems`, formData, {
auth: {
username: ES_USER,
password: ES_PASSWORD,
},
headers: {
APIkey: esApiKey,
},
});
const resultPDFUrl = result?.data?.report_link;
const reportIssueUrl = `https://insurtechtoolkit.com/pcontactUs.aspx?apiKey=${esApiKey}&file=${fileName}.json`;
return {
statusCode: 200,
body: JSON.stringify({
resultPDFUrl,
reportIssueUrl,
identified_item: result.data?.identified_item,
}),
};
} catch (error) {
const axiosError = error as AxiosError;
const errorMessage = axiosError.response?.data || axiosError.message || 'Unknown error';
return {
statusCode: 400,
body: JSON.stringify({
message: 'Error scrubbing estimate.',
error: errorMessage,
}),
};
}
};

View File

@@ -1,55 +0,0 @@
// You can require shared code from the lib folder
// const { dbConnect } = require('../lib/db');
const TrucksList = require("../lib/vehicleTypes/trucks.json");
const CargoVanList = require("../lib/vehicleTypes/cargovans.json");
const PassengerVanList = require("../lib/vehicleTypes/passengervans.json");
const SuvList = require("../lib/vehicleTypes/suvs.json");
exports.handler = async (event) => {
try {
const { model } = JSON.parse(event.body || '{}');
if (!model || model.trim() === "") {
return {
statusCode: 400,
body: JSON.stringify({
success: false,
error: "Please provide a model"
})
}
} else {
vehicle
const type = getVehicleType(model.trim())
return {
statusCode: 200,
body: JSON.stringify({
success: true, ...type
})
}
}
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify({
success: false,
error: error.message,
})
};
};
}
function getVehicleType(model) {
const inTrucks = TrucksList.includes(model.toUpperCase());
const inPV = PassengerVanList.includes(model.toUpperCase());
const inSuv = SuvList.includes(model.toUpperCase());
const inCv = CargoVanList.includes(model.toUpperCase());
if (inTrucks) return { type: "TK", match: true };
else if (inPV) return { type: "PC", match: true };
else if (inSuv) return { type: "SUV", match: true };
else if (inCv) return { type: "VN", match: true };
else return { type: "PC", match: false };
}

View File

@@ -0,0 +1,62 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import TrucksList from '../lib/vehicleTypes/trucks.json';
import CargoVanList from '../lib/vehicleTypes/cargovans.json';
import PassengerVanList from '../lib/vehicleTypes/passengervans.json';
import SuvList from '../lib/vehicleTypes/suvs.json';
interface VehicleTypeRequest {
model?: string;
}
interface VehicleTypeResult {
type: string;
match: boolean;
}
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const { model } = JSON.parse(event.body || '{}') as VehicleTypeRequest;
if (!model || model.trim() === '') {
return {
statusCode: 400,
body: JSON.stringify({
success: false,
error: 'Please provide a model',
}),
};
}
const type = getVehicleType(model.trim());
return {
statusCode: 200,
body: JSON.stringify({
success: true,
...type,
}),
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
statusCode: 500,
body: JSON.stringify({
success: false,
error: errorMessage,
}),
};
}
};
function getVehicleType(model: string): VehicleTypeResult {
const upperModel = model.toUpperCase();
const inTrucks = TrucksList.includes(upperModel);
const inPV = PassengerVanList.includes(upperModel);
const inSuv = SuvList.includes(upperModel);
const inCv = CargoVanList.includes(upperModel);
if (inTrucks) return { type: 'TK', match: true };
else if (inPV) return { type: 'PC', match: true };
else if (inSuv) return { type: 'SUV', match: true };
else if (inCv) return { type: 'VN', match: true };
else return { type: 'PC', match: false };
}

2
serverless/src/lib/db.ts Normal file
View File

@@ -0,0 +1,2 @@
// Placeholder for database utilities
// Export database connection and helper functions here

View File

@@ -1,18 +0,0 @@
const TrucksList = require("./trucks.json");
const CargoVanList = require("./cargovans.json");
const PassengerVanList = require("./passengervans.json");
const SuvList = require("./suvs.json");
function getVehicleType(model) {
const inTrucks = TrucksList.includes(model.toUpperCase());
const inPV = PassengerVanList.includes(model.toUpperCase());
const inSuv = SuvList.includes(model.toUpperCase());
const inCv = CargoVanList.includes(model.toUpperCase());
if (inTrucks) return { type: "TK", match: true };
else if (inPV) return { type: "PC", match: true };
else if (inSuv) return { type: "SUV", match: true };
else if (inCv) return { type: "VN", match: true };
else return { type: "PC", match: false };
}
exports.getVehicleType = getVehicleType;

View File

@@ -0,0 +1,23 @@
import TrucksList from './trucks.json';
import CargoVanList from './cargovans.json';
import PassengerVanList from './passengervans.json';
import SuvList from './suvs.json';
interface VehicleTypeResult {
type: string;
match: boolean;
}
export function getVehicleType(model: string): VehicleTypeResult {
const upperModel = model.toUpperCase();
const inTrucks = TrucksList.includes(upperModel);
const inPV = PassengerVanList.includes(upperModel);
const inSuv = SuvList.includes(upperModel);
const inCv = CargoVanList.includes(upperModel);
if (inTrucks) return { type: 'TK', match: true };
else if (inPV) return { type: 'PC', match: true };
else if (inSuv) return { type: 'SUV', match: true };
else if (inCv) return { type: 'VN', match: true };
else return { type: 'PC', match: false };
}