Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bbde7e5
Editor
KyleParato May 1, 2025
c1d690e
Readded auth, attempting to add editor
KyleParato May 1, 2025
4a943b0
Update Auth
KyleParato May 1, 2025
e0bd67b
Create New Document
KyleParato May 1, 2025
9c6920c
Add npm i to .yml
KyleParato May 1, 2025
e6d25bc
Resolved bug, fixed path
KyleParato May 1, 2025
121d79b
Fetch
KyleParato May 2, 2025
32ecf7e
Test Lambda
KyleParato May 2, 2025
fcaa3ed
Document seperation
KyleParato May 2, 2025
f644a20
Bug fix, doc seperation build
KyleParato May 2, 2025
3a44077
Please
KyleParato May 2, 2025
7dc4101
Readded default bug
KyleParato May 2, 2025
b766bad
Bug: new shared docs are constantly added when navigating
KyleParato May 2, 2025
a43f64d
Changed frontend build command
KyleParato May 2, 2025
6029a89
Changed editor export
KyleParato May 3, 2025
4881ae3
Default docId
KyleParato May 3, 2025
ed089fa
Wrapped Url Param
KyleParato May 3, 2025
1eaccc0
Enable SSR build and add Lambda API call to editor page
KyleParato May 3, 2025
e6b45dc
Removed API call
KyleParato May 3, 2025
d3626bf
test collab
KyleParato May 3, 2025
969ac26
Delete Function testing
KyleParato May 3, 2025
cf9d246
Added api key authmode
KyleParato May 3, 2025
6edbb4c
Revert "Added api key authmode"
KyleParato May 3, 2025
08d4146
Add Lambda functions
MichaelR13 May 7, 2025
4057e21
Updated Lambda functions with DynamoDB integration
MichaelR13 May 7, 2025
89192f0
Updated to correct DynamoDB in AWS
MichaelR13 May 7, 2025
5dd0029
Updated to US-WEST-1 DynamoDB in AWS
MichaelR13 May 7, 2025
14310e6
Importing createDocument Lambda Function
MichaelR13 May 7, 2025
8c2e4f1
API Gateway integration for Lambda
MichaelR13 May 8, 2025
d9c03ed
Updated env variable for API and Lambda
MichaelR13 May 8, 2025
94a264b
v2 for Front end, API and Lambda work
MichaelR13 May 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions amplify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ backend:
commands:
- npm ci --cache .npm --prefer-offline
- npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
- npm i
frontend:
phases:
build:
Expand Down
16 changes: 12 additions & 4 deletions amplify/backend.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource.js';
import { data } from './data/resource.js';
import { defineBackend } from "@aws-amplify/backend";
import { auth } from "./auth/resource";
import { data } from "./data/resource";
import { deleteDocument } from "./functions/deleteDocument/resource";
import { downloadDocument } from "./functions/downloadDocument/resource";
import { fetchDocuments } from "./functions/fetchDocuments/resource";
import { createDocument } from "./functions/createDocument/resource";

defineBackend({
auth,
data,
});
deleteDocument,
downloadDocument,
fetchDocuments,
createDocument
});
2 changes: 1 addition & 1 deletion amplify/data/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const schema = a.schema({
content: a.string(),
})
.authorization((allow) => [allow.authenticated()]), // or add allow.apiKey() here if needed
});
});

export const data = defineData({
schema, // ✅ This now has a value
Expand Down
97 changes: 97 additions & 0 deletions amplify/functions/createDocument/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";
import { randomUUID } from 'crypto';

const client = new DynamoDBClient({ region: "us-west-1" });
const docClient = DynamoDBDocumentClient.from(client);

// Get the DynamoDB table name from environment variables
const tableName = process.env.DOCUMENT_TABLE_NAME || "Document-vnyciacn2nca3b6znjb4pulud4-NONE";

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
console.log("Event received:", JSON.stringify(event, null, 2));

try {
// Parse document data from request body
if (!event.body) {
return {
statusCode: 400,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "POST"
},
body: JSON.stringify({ error: "Request body is required" })
};
}

const requestBody = JSON.parse(event.body);

// Validate required fields
if (!requestBody.title) {
return {
statusCode: 400,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "POST"
},
body: JSON.stringify({ error: "Document title is required" })
};
}

// Create document with required fields and timestamps
const now = new Date().toISOString();
const documentId = requestBody.id || randomUUID();

const document = {
__typename: "Document",
id: documentId,
title: requestBody.title,
content: requestBody.content || "",
createdAt: now,
updatedAt: now
};

// Put the document in DynamoDB
const putParams = {
TableName: tableName,
Item: document
};

await docClient.send(new PutCommand(putParams));

return {
statusCode: 201,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "POST"
},
body: JSON.stringify({
message: "Document created successfully",
document
})
};
} catch (error: unknown) {
console.error("Error creating document:", error);

return {
statusCode: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "POST"
},
body: JSON.stringify({
error: "Failed to create document",
details: error instanceof Error ? error.message : 'Unknown error'
})
};
}
};
6 changes: 6 additions & 0 deletions amplify/functions/createDocument/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineFunction } from "@aws-amplify/backend";

export const createDocument = defineFunction({
name: "createDocument",
entry: "./handler.ts"
});
87 changes: 87 additions & 0 deletions amplify/functions/deleteDocument/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, DeleteCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

// Get the DynamoDB table name from environment variables
const tableName = process.env.DOCUMENT_TABLE_NAME || "Document-vnyciacn2nca3b6znjb4pulud4-NONE";

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
console.log("Event received:", JSON.stringify(event, null, 2));

try {
// Extract document ID from event
const documentId = event.pathParameters?.id ||
JSON.parse(event.body || '{}').id ||
event.queryStringParameters?.id;

if (!documentId) {
return {
statusCode: 400,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "DELETE"
},
body: JSON.stringify({ error: "Document ID is required" })
};
}

// Delete the document from DynamoDB
const deleteParams = {
TableName: tableName,
Key: {
id: documentId
},
ReturnValues: "ALL_OLD" as const // Return the deleted item
};

const { Attributes } = await docClient.send(new DeleteCommand(deleteParams));

if (!Attributes) {
return {
statusCode: 404,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "DELETE"
},
body: JSON.stringify({ error: "Document not found or already deleted" })
};
}

return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "DELETE"
},
body: JSON.stringify({
message: "Document deleted successfully",
deletedDocument: Attributes
})
};
} catch (error: unknown) {
console.error("Error deleting document:", error);

return {
statusCode: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "DELETE"
},
body: JSON.stringify({
error: "Failed to delete document",
details: error instanceof Error ? error.message : 'Unknown error'
})
};
}
};
Empty file.
6 changes: 6 additions & 0 deletions amplify/functions/deleteDocument/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineFunction } from "@aws-amplify/backend";

export const deleteDocument = defineFunction({
name: "deleteDocument",
entry: "./handler.ts"
});
89 changes: 89 additions & 0 deletions amplify/functions/downloadDocument/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

// Get the DynamoDB table name from environment variables
const tableName = process.env.DOCUMENT_TABLE_NAME || "Document-vnyciacn2nca3b6znjb4pulud4-NONE";

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
console.log("Event received:", JSON.stringify(event, null, 2));

try {
// Extract document ID from the event
const documentId = event.pathParameters?.id ||
event.queryStringParameters?.id ||
JSON.parse(event.body || '{}').id;

if (!documentId) {
return {
statusCode: 400,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "GET"
},
body: JSON.stringify({ error: "Document ID is required" })
};
}

// Get the document from DynamoDB
const getParams = {
TableName: tableName,
Key: {
id: documentId
}
};

const { Item } = await docClient.send(new GetCommand(getParams));

if (!Item) {
return {
statusCode: 404,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "GET"
},
body: JSON.stringify({ error: "Document not found" })
};
}

// Return the document content
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "GET",
"Content-Disposition": `attachment; filename="${Item.title || 'document'}.txt"`
},
body: JSON.stringify({
document: Item,
content: Item.content || "",
title: Item.title || "document"
})
};
} catch (error: unknown) {
console.error("Error downloading document:", error);

return {
statusCode: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "GET"
},
body: JSON.stringify({
error: "Failed to download document",
details: error instanceof Error ? error.message : 'Unknown error'
})
};
}
};
Empty file.
6 changes: 6 additions & 0 deletions amplify/functions/downloadDocument/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineFunction } from "@aws-amplify/backend";

export const downloadDocument = defineFunction({
name: "downloadDocument",
entry: "./handler.ts"
});
52 changes: 52 additions & 0 deletions amplify/functions/fetchDocuments/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, ScanCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

// Get the DynamoDB table name from environment variables
const tableName = process.env.DOCUMENT_TABLE_NAME || "Document-vnyciacn2nca3b6znjb4pulud4-NONE";

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
console.log("Event received:", JSON.stringify(event, null, 2));

try {
// Scan the DynamoDB table to get all documents
const scanParams = {
TableName: tableName,
};

const scanResponse = await docClient.send(new ScanCommand(scanParams));

// Return the results
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*", // For CORS support
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "GET"
},
body: JSON.stringify({
documents: scanResponse.Items || [],
count: scanResponse.Count || 0
})
};
} catch (error: unknown) {
console.error("Error fetching documents:", error);
return {
statusCode: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "GET"
},
body: JSON.stringify({
error: "Failed to fetch documents",
details: error instanceof Error ? error.message : 'Unknown error'
})
};
}
};
Loading