Update project configuration and enhance API functionality
- Updated package.json to use npx for deploying and developing, and upgraded several dependencies including vitest and wrangler. - Renamed the project in wrangler.jsonc to include the year 2026 and added new routes and triggers for scheduled tasks. - Enhanced the API by adding new reload endpoints for pages, blogs, projects, and experiences, with appropriate CORS handling. - Implemented checks in import functions for files, images, and videos to skip updates if no changes are detected. - Improved error handling and logging across various routes and utilities. - Refactored global headers to dynamically resolve CORS origins based on incoming requests.
This commit is contained in:
parent
6d5265dfe0
commit
db60e43d73
18
package.json
18
package.json
@ -3,25 +3,23 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"deploy": "wrangler deploy --env production",
|
"deploy": "npx wrangler deploy --env production",
|
||||||
"dev": "wrangler dev --test-scheduled --host 0.0.0.0",
|
"dev": "npx wrangler dev --test-scheduled --host 0.0.0.0"
|
||||||
"test": "vitest"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/vitest-pool-workers": "^0.6.4",
|
"@cloudflare/vitest-pool-workers": "^0.10.5",
|
||||||
"vitest": "~2.1.9",
|
"wrangler": "^4.46.0"
|
||||||
"wrangler": "^4.38.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@napi-rs/canvas": "^0.1.80",
|
"@napi-rs/canvas": "^0.1.81",
|
||||||
"@notionhq/client": "^5.1.0",
|
"@notionhq/client": "^5.3.0",
|
||||||
"blurhash": "^2.0.5",
|
"blurhash": "^2.0.5",
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.19",
|
||||||
"jpeg-js": "^0.4.4",
|
"jpeg-js": "^0.4.4",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"microdiff": "^1.5.0",
|
"microdiff": "^1.5.0",
|
||||||
"remove-svg-properties": "^0.3.4",
|
"remove-svg-properties": "^0.3.4",
|
||||||
"sharp": "^0.34.3",
|
"sharp": "^0.34.5",
|
||||||
"svgson": "^5.3.1",
|
"svgson": "^5.3.1",
|
||||||
"upng-js": "^2.1.0"
|
"upng-js": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/index.js
109
src/index.js
@ -2,6 +2,16 @@ import { handleContactRequest } from "./routes/contact.js";
|
|||||||
import { handleContentRequest } from "./routes/content.js";
|
import { handleContentRequest } from "./routes/content.js";
|
||||||
import { handleNotionHook } from "./routes/hooks.js";
|
import { handleNotionHook } from "./routes/hooks.js";
|
||||||
import { globalHeaders } from "./utils/api.js";
|
import { globalHeaders } from "./utils/api.js";
|
||||||
|
import {
|
||||||
|
handleReloadPage,
|
||||||
|
handleReloadBlog,
|
||||||
|
handleReloadProject,
|
||||||
|
handleReloadExperience,
|
||||||
|
} from "./routes/reload.js";
|
||||||
|
import { handleBlurHashUpdate } from "./utils/imageCache.js";
|
||||||
|
import { importFiles } from "./objects/files.js";
|
||||||
|
import { importVideos } from "./objects/videos.js";
|
||||||
|
import { importImages } from "./objects/images.js";
|
||||||
|
|
||||||
async function handleRequest(request, env) {
|
async function handleRequest(request, env) {
|
||||||
if (
|
if (
|
||||||
@ -12,7 +22,7 @@ async function handleRequest(request, env) {
|
|||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 204, // No Content
|
status: 204, // No Content
|
||||||
headers: {
|
headers: {
|
||||||
"Access-Control-Allow-Origin": env.CORS_ORIGIN,
|
...globalHeaders(request),
|
||||||
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
||||||
"Access-Control-Allow-Headers": "Content-Type",
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
},
|
},
|
||||||
@ -39,18 +49,105 @@ async function handleRequest(request, env) {
|
|||||||
return await handleNotionHook(request, env);
|
return await handleNotionHook(request, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
request.method === "OPTIONS" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadPage")
|
||||||
|
) {
|
||||||
|
console.log("Handling reloadPage OPTIONS request...");
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204, // No Content
|
||||||
|
headers: {
|
||||||
|
...globalHeaders(request),
|
||||||
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
||||||
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
request.method === "POST" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadPage")
|
||||||
|
) {
|
||||||
|
return await handleReloadPage(request, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
request.method === "OPTIONS" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadBlog")
|
||||||
|
) {
|
||||||
|
console.log("Handling reloadBlog OPTIONS request...");
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204, // No Content
|
||||||
|
headers: {
|
||||||
|
...globalHeaders(request),
|
||||||
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
||||||
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
request.method === "POST" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadBlog")
|
||||||
|
) {
|
||||||
|
return await handleReloadBlog(request, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
request.method === "OPTIONS" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadProject")
|
||||||
|
) {
|
||||||
|
console.log("Handling reloadProject OPTIONS request...");
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204, // No Content
|
||||||
|
headers: {
|
||||||
|
...globalHeaders(request),
|
||||||
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
||||||
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
request.method === "POST" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadProject")
|
||||||
|
) {
|
||||||
|
return await handleReloadProject(request, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
request.method === "OPTIONS" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadExperience")
|
||||||
|
) {
|
||||||
|
console.log("Handling reloadExperience OPTIONS request...");
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204, // No Content
|
||||||
|
headers: {
|
||||||
|
...globalHeaders(request),
|
||||||
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
||||||
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
request.method === "POST" &&
|
||||||
|
request.url.split("?")[0].endsWith("/reloadExperience")
|
||||||
|
) {
|
||||||
|
return await handleReloadExperience(request, env);
|
||||||
|
}
|
||||||
|
|
||||||
// Return 404 if the route is not found
|
// Return 404 if the route is not found
|
||||||
return new Response("Not Found", { status: 404, headers: globalHeaders });
|
return new Response("Not Found", {
|
||||||
|
status: 404,
|
||||||
|
headers: globalHeaders(request),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleScheduledEvent(event, env) {
|
async function handleScheduledEvent(event, env) {
|
||||||
console.log("Scheduled event:", event.cron);
|
console.log("Scheduled event:", event.cron);
|
||||||
switch (event.cron) {
|
switch (event.cron) {
|
||||||
case "*/5 * * * *":
|
case "*/5 * * * *":
|
||||||
await updateAllSmoobuData(env);
|
await importFiles(env);
|
||||||
break;
|
await importVideos(env);
|
||||||
case "* * * * *":
|
await importImages(env);
|
||||||
await refreshBookingCache(env);
|
await handleBlurHashUpdate(env);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -2,7 +2,12 @@ import { getPages } from "../utils/pages.js";
|
|||||||
import { getBlogs } from "../utils/blogs.js";
|
import { getBlogs } from "../utils/blogs.js";
|
||||||
import { getProjects } from "../utils/projects.js";
|
import { getProjects } from "../utils/projects.js";
|
||||||
import { getCompanies } from "../utils/companies.js";
|
import { getCompanies } from "../utils/companies.js";
|
||||||
import { collectFileUrls, updateFiles } from "../utils/fileCache.js";
|
import {
|
||||||
|
collectFileUrls,
|
||||||
|
updateFiles,
|
||||||
|
getFiles,
|
||||||
|
getFileIdFromUrl,
|
||||||
|
} from "../utils/fileCache.js";
|
||||||
import { getCvs } from "../utils/cv.js";
|
import { getCvs } from "../utils/cv.js";
|
||||||
|
|
||||||
export async function importFiles(env) {
|
export async function importFiles(env) {
|
||||||
@ -21,6 +26,22 @@ export async function importFiles(env) {
|
|||||||
...cvs,
|
...cvs,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Check if files have changed before updating
|
||||||
|
const existingFiles = (await getFiles(env)) || [];
|
||||||
|
const existingFileIds = new Set(existingFiles.map((file) => file.id));
|
||||||
|
const currentFileIds = new Set(fileUrls.map((url) => getFileIdFromUrl(url)));
|
||||||
|
|
||||||
|
// Check if there are any differences
|
||||||
|
const hasChanges =
|
||||||
|
existingFileIds.size !== currentFileIds.size ||
|
||||||
|
[...currentFileIds].some((id) => !existingFileIds.has(id)) ||
|
||||||
|
[...existingFileIds].some((id) => !currentFileIds.has(id));
|
||||||
|
|
||||||
|
if (!hasChanges) {
|
||||||
|
console.log("No file changes detected. Skipping file update.");
|
||||||
|
return existingFiles;
|
||||||
|
}
|
||||||
|
|
||||||
const updatedFiles = await updateFiles(env, fileUrls);
|
const updatedFiles = await updateFiles(env, fileUrls);
|
||||||
console.log("Imported files from Notion.");
|
console.log("Imported files from Notion.");
|
||||||
return updatedFiles;
|
return updatedFiles;
|
||||||
|
|||||||
@ -2,7 +2,12 @@ import { getPages } from "../utils/pages.js";
|
|||||||
import { getBlogs } from "../utils/blogs.js";
|
import { getBlogs } from "../utils/blogs.js";
|
||||||
import { getProjects } from "../utils/projects.js";
|
import { getProjects } from "../utils/projects.js";
|
||||||
import { getCompanies } from "../utils/companies.js";
|
import { getCompanies } from "../utils/companies.js";
|
||||||
import { collectImageUrls, updateImages } from "../utils/imageCache.js";
|
import {
|
||||||
|
collectImageUrls,
|
||||||
|
updateImages,
|
||||||
|
getImages,
|
||||||
|
getImageIdFromUrl,
|
||||||
|
} from "../utils/imageCache.js";
|
||||||
|
|
||||||
export async function importImages(env) {
|
export async function importImages(env) {
|
||||||
// Fetch caches
|
// Fetch caches
|
||||||
@ -20,6 +25,24 @@ export async function importImages(env) {
|
|||||||
...companies,
|
...companies,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Check if images have changed before updating
|
||||||
|
const existingImages = (await getImages(env)) || [];
|
||||||
|
const existingImageIds = new Set(existingImages.map((image) => image.id));
|
||||||
|
const currentImageIds = new Set(
|
||||||
|
imageUrls.map((url) => getImageIdFromUrl(url))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if there are any differences
|
||||||
|
const hasChanges =
|
||||||
|
existingImageIds.size !== currentImageIds.size ||
|
||||||
|
[...currentImageIds].some((id) => !existingImageIds.has(id)) ||
|
||||||
|
[...existingImageIds].some((id) => !currentImageIds.has(id));
|
||||||
|
|
||||||
|
if (!hasChanges) {
|
||||||
|
console.log("No image changes detected. Skipping image update.");
|
||||||
|
return existingImages;
|
||||||
|
}
|
||||||
|
|
||||||
const updatedImages = await updateImages(env, imageUrls);
|
const updatedImages = await updateImages(env, imageUrls);
|
||||||
console.log("Imported images from Notion.");
|
console.log("Imported images from Notion.");
|
||||||
return updatedImages;
|
return updatedImages;
|
||||||
|
|||||||
@ -29,12 +29,25 @@ export async function importNotionProjects(env, notionId = null) {
|
|||||||
transformNotionProject(env, project, settingsData)
|
transformNotionProject(env, project, settingsData)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).filter(Boolean);
|
)
|
||||||
|
.filter(Boolean)
|
||||||
|
.sort((a, b) => {
|
||||||
|
const dateA = a.date ? new Date(a.date) : new Date(0);
|
||||||
|
const dateB = b.date ? new Date(b.date) : new Date(0);
|
||||||
|
return dateB - dateA;
|
||||||
|
});
|
||||||
|
|
||||||
// If notionId is not null, use lodash unionBy to replace existing Projects
|
// If notionId is not null, use lodash unionBy to replace existing Projects
|
||||||
if (notionId !== null) {
|
if (notionId !== null) {
|
||||||
const cachedProjects = await getProjects(env);
|
const cachedProjects = await getProjects(env);
|
||||||
const mergedProjects = unionBy(Projects, cachedProjects, "notionId");
|
const mergedProjects = unionBy(Projects, cachedProjects, "notionId").sort(
|
||||||
|
(a, b) => {
|
||||||
|
const dateA = a.date ? new Date(a.date) : new Date(0);
|
||||||
|
const dateB = b.date ? new Date(b.date) : new Date(0);
|
||||||
|
return dateB - dateA;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await storeProjects(env, mergedProjects);
|
await storeProjects(env, mergedProjects);
|
||||||
console.log("Imported Projects from Notion and merged with cache.");
|
console.log("Imported Projects from Notion and merged with cache.");
|
||||||
return mergedProjects;
|
return mergedProjects;
|
||||||
|
|||||||
@ -2,7 +2,12 @@ import { getPages } from "../utils/pages.js";
|
|||||||
import { getBlogs } from "../utils/blogs.js";
|
import { getBlogs } from "../utils/blogs.js";
|
||||||
import { getProjects } from "../utils/projects.js";
|
import { getProjects } from "../utils/projects.js";
|
||||||
import { getCompanies } from "../utils/companies.js";
|
import { getCompanies } from "../utils/companies.js";
|
||||||
import { collectVideoUrls, updateVideos } from "../utils/videoCache.js";
|
import {
|
||||||
|
collectVideoUrls,
|
||||||
|
updateVideos,
|
||||||
|
getVideos,
|
||||||
|
getVideoIdFromUrl,
|
||||||
|
} from "../utils/videoCache.js";
|
||||||
|
|
||||||
export async function importVideos(env) {
|
export async function importVideos(env) {
|
||||||
console.log("Importing videos from Notion...");
|
console.log("Importing videos from Notion...");
|
||||||
@ -18,6 +23,24 @@ export async function importVideos(env) {
|
|||||||
...companies,
|
...companies,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Check if videos have changed before updating
|
||||||
|
const existingVideos = (await getVideos(env)) || [];
|
||||||
|
const existingVideoIds = new Set(existingVideos.map((video) => video.id));
|
||||||
|
const currentVideoIds = new Set(
|
||||||
|
videoUrls.map((url) => getVideoIdFromUrl(url))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if there are any differences
|
||||||
|
const hasChanges =
|
||||||
|
existingVideoIds.size !== currentVideoIds.size ||
|
||||||
|
[...currentVideoIds].some((id) => !existingVideoIds.has(id)) ||
|
||||||
|
[...existingVideoIds].some((id) => !currentVideoIds.has(id));
|
||||||
|
|
||||||
|
if (!hasChanges) {
|
||||||
|
console.log("No video changes detected. Skipping video update.");
|
||||||
|
return existingVideos;
|
||||||
|
}
|
||||||
|
|
||||||
const updatedVideos = await updateVideos(env, videoUrls);
|
const updatedVideos = await updateVideos(env, videoUrls);
|
||||||
console.log("Imported videos from Notion.");
|
console.log("Imported videos from Notion.");
|
||||||
return updatedVideos;
|
return updatedVideos;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export async function handleProcessBlurhash(env) {
|
export async function handleProcessBlurhash(env, request) {
|
||||||
try {
|
try {
|
||||||
const imagesData = await getImages(env);
|
const imagesData = await getImages(env);
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ export async function handleProcessBlurhash(env) {
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
status: 500,
|
status: 500,
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,8 +14,8 @@ export async function handleContactRequest(request, env) {
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
status: 400,
|
status: 400,
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,12 +28,12 @@ export async function handleContactRequest(request, env) {
|
|||||||
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
secret: env.TURNSTILE_AUTH,
|
secret: env.TURNSTILE_AUTH,
|
||||||
response: token,
|
response: token,
|
||||||
}),
|
}),
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const verificationData = await verificationResponse.json();
|
const verificationData = await verificationResponse.json();
|
||||||
@ -47,8 +47,8 @@ export async function handleContactRequest(request, env) {
|
|||||||
JSON.stringify({ message: errorMessage, code: `captcha-${code}` }),
|
JSON.stringify({ message: errorMessage, code: `captcha-${code}` }),
|
||||||
{
|
{
|
||||||
status: 400,
|
status: 400,
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ export async function handleContactRequest(request, env) {
|
|||||||
Message: message,
|
Message: message,
|
||||||
["IP Address"]: ip,
|
["IP Address"]: ip,
|
||||||
},
|
},
|
||||||
env.MESSAGES_DB,
|
env.MESSAGES_DB
|
||||||
);
|
);
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@ -70,16 +70,16 @@ export async function handleContactRequest(request, env) {
|
|||||||
message: "Email processed and added to Notion",
|
message: "Email processed and added to Notion",
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ message: "Error storing data.", code: "storage-error" }),
|
JSON.stringify({ message: "Error storing data.", code: "storage-error" }),
|
||||||
{
|
{
|
||||||
status: 500,
|
status: 500,
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,24 +9,35 @@ import { importNotionCompanies } from "../objects/companies.js";
|
|||||||
import { importImages } from "../objects/images.js";
|
import { importImages } from "../objects/images.js";
|
||||||
import { importNotionCvs } from "../objects/cv.js";
|
import { importNotionCvs } from "../objects/cv.js";
|
||||||
import { importFiles } from "../objects/files.js";
|
import { importFiles } from "../objects/files.js";
|
||||||
|
import { importNotionProjects } from "../objects/projects.js";
|
||||||
import { importVideos } from "../objects/videos.js";
|
import { importVideos } from "../objects/videos.js";
|
||||||
|
|
||||||
// Fetch or return cached content
|
// Fetch or return cached content
|
||||||
export async function getCachedContent(env) {
|
export async function getCachedContent(env, request) {
|
||||||
// Try to get combined cached content
|
// Try to get combined cached content
|
||||||
var cachedContent = await getCombinedCachedContent(env);
|
var cachedContent = await getCombinedCachedContent(env);
|
||||||
|
|
||||||
const noBlogs = cachedContent.blogs?.length === 0;
|
const noBlogs =
|
||||||
const noPages = cachedContent.pages?.length === 0;
|
cachedContent.blogs?.length === 0 || cachedContent.blogs == null;
|
||||||
const noSettings = cachedContent.settings == {};
|
const noPages =
|
||||||
const noCompanies = cachedContent.companies?.length === 0;
|
cachedContent.pages?.length === 0 || cachedContent.pages == null;
|
||||||
const noCvs = cachedContent.cvs?.length === 0;
|
const noSettings =
|
||||||
const noPositions = cachedContent.positions?.length === 0;
|
Object.keys(cachedContent.settings).length === 0 ||
|
||||||
|
cachedContent.settings == null;
|
||||||
|
const noCompanies =
|
||||||
|
cachedContent.companies?.length === 0 || cachedContent.companies == null;
|
||||||
|
const noCvs = cachedContent.cvs?.length === 0 || cachedContent.cvs == null;
|
||||||
|
const noProjects =
|
||||||
|
cachedContent.projects?.length === 0 || cachedContent.projects == null;
|
||||||
|
|
||||||
if (noBlogs || noPages || noSettings || noCompanies || noCvs || noPositions) {
|
if (noBlogs || noPages || noSettings || noCompanies || noCvs || noProjects) {
|
||||||
await importNotionNavigation(env);
|
await importNotionNavigation(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (noSettings) {
|
||||||
|
cachedContent.settings = await importNotionSettings(env);
|
||||||
|
}
|
||||||
|
|
||||||
if (noBlogs) {
|
if (noBlogs) {
|
||||||
cachedContent.blogs = await importNotionBlogs(env);
|
cachedContent.blogs = await importNotionBlogs(env);
|
||||||
cachedContent.images = await importImages(env);
|
cachedContent.images = await importImages(env);
|
||||||
@ -41,10 +52,6 @@ export async function getCachedContent(env) {
|
|||||||
cachedContent.videos = await importVideos(env);
|
cachedContent.videos = await importVideos(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noSettings) {
|
|
||||||
cachedContent.settings = await importNotionSettings(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noCvs) {
|
if (noCvs) {
|
||||||
cachedContent.cvs = await importNotionCvs(env);
|
cachedContent.cvs = await importNotionCvs(env);
|
||||||
cachedContent.files = await importFiles(env);
|
cachedContent.files = await importFiles(env);
|
||||||
@ -58,6 +65,13 @@ export async function getCachedContent(env) {
|
|||||||
cachedContent.videos = await importVideos(env);
|
cachedContent.videos = await importVideos(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (noProjects) {
|
||||||
|
cachedContent.projects = await importNotionProjects(env);
|
||||||
|
cachedContent.images = await importImages(env);
|
||||||
|
cachedContent.files = await importFiles(env);
|
||||||
|
cachedContent.videos = await importVideos(env);
|
||||||
|
}
|
||||||
|
|
||||||
if (cachedContent) {
|
if (cachedContent) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@ -65,17 +79,17 @@ export async function getCachedContent(env) {
|
|||||||
blogs: cachedContent.blogs.filter((blog) => blog.published == true),
|
blogs: cachedContent.blogs.filter((blog) => blog.published == true),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(JSON.stringify({}), { headers: globalHeaders });
|
return new Response(JSON.stringify({}), { headers: globalHeaders(request) });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleContentRequest(request, env) {
|
export async function handleContentRequest(request, env) {
|
||||||
try {
|
try {
|
||||||
return await getCachedContent(env);
|
return await getCachedContent(env, request);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error handling content request:", error);
|
console.error("Error handling content request:", error);
|
||||||
return new Response(
|
return new Response(
|
||||||
@ -85,7 +99,7 @@ export async function handleContentRequest(request, env) {
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
status: 500,
|
status: 500,
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { globalHeaders } from "../utils/api";
|
|||||||
import { importImages } from "../objects/images";
|
import { importImages } from "../objects/images";
|
||||||
import { importFiles } from "../objects/files";
|
import { importFiles } from "../objects/files";
|
||||||
import { importVideos } from "../objects/videos";
|
import { importVideos } from "../objects/videos";
|
||||||
import { handleBlurhashUpdate } from "../utils/imageCache";
|
|
||||||
import { importNotionProjects } from "../objects/projects";
|
import { importNotionProjects } from "../objects/projects";
|
||||||
import { importNotionCompanies } from "../objects/companies";
|
import { importNotionCompanies } from "../objects/companies";
|
||||||
import { importNotionPositions } from "../objects/positions";
|
import { importNotionPositions } from "../objects/positions";
|
||||||
@ -33,7 +32,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: "gotVerificationToken",
|
status: "gotVerificationToken",
|
||||||
}),
|
}),
|
||||||
{ headers: globalHeaders }
|
{ headers: globalHeaders(request) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
console.log("Notion hook received:", body.type);
|
console.log("Notion hook received:", body.type);
|
||||||
@ -51,14 +50,13 @@ export async function handleNotionHook(request, env) {
|
|||||||
await importNotionNavigation(env);
|
await importNotionNavigation(env);
|
||||||
const pages = await importNotionPages(env, entityId);
|
const pages = await importNotionPages(env, entityId);
|
||||||
const images = await importImages(env);
|
const images = await importImages(env);
|
||||||
await handleBlurhashUpdate(request, env);
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: "OK",
|
status: "OK",
|
||||||
content: { pages, images },
|
content: { pages, images },
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -68,14 +66,13 @@ export async function handleNotionHook(request, env) {
|
|||||||
const images = await importImages(env);
|
const images = await importImages(env);
|
||||||
const files = await importFiles(env);
|
const files = await importFiles(env);
|
||||||
const videos = await importVideos(env);
|
const videos = await importVideos(env);
|
||||||
await handleBlurhashUpdate(request, env);
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: "OK",
|
status: "OK",
|
||||||
content: { blogs, images, files, videos },
|
content: { blogs, images, files, videos },
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -85,14 +82,13 @@ export async function handleNotionHook(request, env) {
|
|||||||
const images = await importImages(env);
|
const images = await importImages(env);
|
||||||
const files = await importFiles(env);
|
const files = await importFiles(env);
|
||||||
const videos = await importVideos(env);
|
const videos = await importVideos(env);
|
||||||
await handleBlurhashUpdate(request, env);
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: "OK",
|
status: "OK",
|
||||||
content: { projects, images, files, videos },
|
content: { projects, images, files, videos },
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -102,14 +98,13 @@ export async function handleNotionHook(request, env) {
|
|||||||
const images = await importImages(env);
|
const images = await importImages(env);
|
||||||
const files = await importFiles(env);
|
const files = await importFiles(env);
|
||||||
const videos = await importVideos(env);
|
const videos = await importVideos(env);
|
||||||
await handleBlurhashUpdate(request, env);
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: "OK",
|
status: "OK",
|
||||||
content: { companies, images, positions, files, videos },
|
content: { companies, images, positions, files, videos },
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -117,7 +112,6 @@ export async function handleNotionHook(request, env) {
|
|||||||
const positions = await importNotionPositions(env, entityId);
|
const positions = await importNotionPositions(env, entityId);
|
||||||
const companies = await importNotionCompanies(env);
|
const companies = await importNotionCompanies(env);
|
||||||
const images = await importImages(env);
|
const images = await importImages(env);
|
||||||
await handleBlurhashUpdate(request, env);
|
|
||||||
const files = await importFiles(env);
|
const files = await importFiles(env);
|
||||||
const videos = await importVideos(env);
|
const videos = await importVideos(env);
|
||||||
return new Response(
|
return new Response(
|
||||||
@ -126,7 +120,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
content: { positions, companies, images, files, videos },
|
content: { positions, companies, images, files, videos },
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -136,7 +130,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { cvs, files } }),
|
JSON.stringify({ status: "OK", content: { cvs, files } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -145,7 +139,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { settings } }),
|
JSON.stringify({ status: "OK", content: { settings } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -154,7 +148,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { redirects } }),
|
JSON.stringify({ status: "OK", content: { redirects } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -163,16 +157,13 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { branding } }),
|
JSON.stringify({ status: "OK", content: { branding } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
console.log("Page Blogs with data source:", dataSourceId);
|
console.log("Page Blogs with data source:", dataSourceId);
|
||||||
}
|
}
|
||||||
if (
|
if (body.type == "page.deleted" && body.data?.parent?.data_source_id) {
|
||||||
body.type == "page.properties_updated" ||
|
|
||||||
(body.type == "page.deleted" && body.data?.parent?.data_source_id)
|
|
||||||
) {
|
|
||||||
const dataSourceId = body.data.parent.data_source_id;
|
const dataSourceId = body.data.parent.data_source_id;
|
||||||
const entityId = body?.entity?.id || null;
|
const entityId = body?.entity?.id || null;
|
||||||
console.log("Data source ID:", dataSourceId);
|
console.log("Data source ID:", dataSourceId);
|
||||||
@ -185,7 +176,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { pages } }),
|
JSON.stringify({ status: "OK", content: { pages } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.BLOGS_DB:
|
case env.BLOGS_DB:
|
||||||
@ -194,7 +185,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { blogs } }),
|
JSON.stringify({ status: "OK", content: { blogs } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.COMPANIES_DB:
|
case env.COMPANIES_DB:
|
||||||
@ -202,7 +193,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { companies } }),
|
JSON.stringify({ status: "OK", content: { companies } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.POSITIONS_DB:
|
case env.POSITIONS_DB:
|
||||||
@ -211,7 +202,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { positions } }),
|
JSON.stringify({ status: "OK", content: { positions } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.PROJECTS_DB:
|
case env.PROJECTS_DB:
|
||||||
@ -219,7 +210,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { projects } }),
|
JSON.stringify({ status: "OK", content: { projects } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.CV_DB:
|
case env.CV_DB:
|
||||||
@ -227,7 +218,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { cvs } }),
|
JSON.stringify({ status: "OK", content: { cvs } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.THEMES_DB:
|
case env.THEMES_DB:
|
||||||
@ -235,7 +226,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { settings } }),
|
JSON.stringify({ status: "OK", content: { settings } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.REDIRECTS_DB:
|
case env.REDIRECTS_DB:
|
||||||
@ -243,7 +234,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { redirects } }),
|
JSON.stringify({ status: "OK", content: { redirects } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
case env.BRANDING_DB:
|
case env.BRANDING_DB:
|
||||||
@ -251,7 +242,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "OK", content: { branding } }),
|
JSON.stringify({ status: "OK", content: { branding } }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -263,7 +254,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ status: "Unknown hook", type: body.type }),
|
JSON.stringify({ status: "Unknown hook", type: body.type }),
|
||||||
{
|
{
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -271,7 +262,7 @@ export async function handleNotionHook(request, env) {
|
|||||||
console.log("No body to parse. Calling both fetch requests...");
|
console.log("No body to parse. Calling both fetch requests...");
|
||||||
const content = await updateAllNotionData(env);
|
const content = await updateAllNotionData(env);
|
||||||
return new Response(JSON.stringify({ status: "OK", content }), {
|
return new Response(JSON.stringify({ status: "OK", content }), {
|
||||||
headers: globalHeaders,
|
headers: globalHeaders(request),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
156
src/routes/reload.js
Normal file
156
src/routes/reload.js
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { globalHeaders } from "../utils/api.js";
|
||||||
|
import { importNotionNavigation } from "../objects/navigation.js";
|
||||||
|
import { importNotionPages } from "../objects/pages.js";
|
||||||
|
import { importNotionBlogs } from "../objects/blogs.js";
|
||||||
|
import { importNotionProjects } from "../objects/projects.js";
|
||||||
|
import { importNotionPositions } from "../objects/positions.js";
|
||||||
|
import { importNotionCompanies } from "../objects/companies.js";
|
||||||
|
import { importImages } from "../objects/images.js";
|
||||||
|
import { importFiles } from "../objects/files.js";
|
||||||
|
import { importVideos } from "../objects/videos.js";
|
||||||
|
import { handleBlurHashUpdate } from "../utils/imageCache.js";
|
||||||
|
|
||||||
|
class ReloadRequestError extends Error {
|
||||||
|
constructor(message, status = 400) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function parseReloadRequest(request) {
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
||||||
|
throw new ReloadRequestError("Request body must be a JSON object");
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof ReloadRequestError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new ReloadRequestError("Invalid JSON body");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createErrorResponse(error, request) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
status: "error",
|
||||||
|
message: error.message,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
status: error.status ?? 500,
|
||||||
|
headers: globalHeaders(request),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handleReloadPage(request, env) {
|
||||||
|
let body;
|
||||||
|
try {
|
||||||
|
body = await parseReloadRequest(request);
|
||||||
|
} catch (error) {
|
||||||
|
return createErrorResponse(error, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const notionId = body?.notionId ?? null;
|
||||||
|
|
||||||
|
await importNotionNavigation(env);
|
||||||
|
const pages = await importNotionPages(env, notionId);
|
||||||
|
const images = await importImages(env);
|
||||||
|
await handleBlurHashUpdate(env);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
status: "OK",
|
||||||
|
content: { pages, images },
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: globalHeaders(request),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handleReloadBlog(request, env) {
|
||||||
|
let body;
|
||||||
|
try {
|
||||||
|
body = await parseReloadRequest(request);
|
||||||
|
} catch (error) {
|
||||||
|
return createErrorResponse(error, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const notionId = body?.notionId ?? null;
|
||||||
|
|
||||||
|
await importNotionNavigation(env);
|
||||||
|
const blogs = await importNotionBlogs(env, notionId);
|
||||||
|
const images = await importImages(env);
|
||||||
|
const files = await importFiles(env);
|
||||||
|
const videos = await importVideos(env);
|
||||||
|
await handleBlurHashUpdate(env);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
status: "OK",
|
||||||
|
content: { blogs, images, files, videos },
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: globalHeaders(request),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handleReloadProject(request, env) {
|
||||||
|
let body;
|
||||||
|
try {
|
||||||
|
body = await parseReloadRequest(request);
|
||||||
|
} catch (error) {
|
||||||
|
return createErrorResponse(error, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const notionId = body?.notionId ?? null;
|
||||||
|
|
||||||
|
await importNotionNavigation(env);
|
||||||
|
const projects = await importNotionProjects(env, notionId);
|
||||||
|
const images = await importImages(env);
|
||||||
|
const files = await importFiles(env);
|
||||||
|
const videos = await importVideos(env);
|
||||||
|
await handleBlurHashUpdate(env);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
status: "OK",
|
||||||
|
content: { projects, images, files, videos },
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: globalHeaders(request),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handleReloadExperience(request, env) {
|
||||||
|
let body;
|
||||||
|
try {
|
||||||
|
body = await parseReloadRequest(request);
|
||||||
|
} catch (error) {
|
||||||
|
return createErrorResponse(error, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const notionId = body?.notionId ?? null;
|
||||||
|
|
||||||
|
const positions = await importNotionPositions(env);
|
||||||
|
const companies = await importNotionCompanies(env, notionId);
|
||||||
|
const images = await importImages(env);
|
||||||
|
await handleBlurHashUpdate(env);
|
||||||
|
const files = await importFiles(env);
|
||||||
|
const videos = await importVideos(env);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
status: "OK",
|
||||||
|
content: { positions, companies, images, files, videos },
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: globalHeaders(request),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,6 +1,32 @@
|
|||||||
import { env } from "cloudflare:workers";
|
import { env } from "cloudflare:workers";
|
||||||
|
|
||||||
export const globalHeaders = {
|
const allowedOrigins = Array.isArray(env.CORS_ORIGIN)
|
||||||
"Content-Type": "application/json",
|
? env.CORS_ORIGIN
|
||||||
"Access-Control-Allow-Origin": env.CORS_ORIGIN,
|
: env.CORS_ORIGIN.split(",");
|
||||||
|
|
||||||
|
const resolveOrigin = (request) => {
|
||||||
|
const requestOrigin = request.headers.get("Origin") || "dev.tombutcher.work";
|
||||||
|
|
||||||
|
if (allowedOrigins.length === 0 || allowedOrigins.includes("*")) {
|
||||||
|
return "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestOriginWithProtocol = requestOrigin.startsWith("https://")
|
||||||
|
? requestOrigin
|
||||||
|
: "https://" + requestOrigin;
|
||||||
|
|
||||||
|
if (
|
||||||
|
requestOriginWithProtocol &&
|
||||||
|
allowedOrigins.includes(requestOriginWithProtocol)
|
||||||
|
) {
|
||||||
|
return requestOriginWithProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
return allowedOrigins[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const globalHeaders = (request) => ({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Access-Control-Allow-Credentials": "true",
|
||||||
|
"Access-Control-Allow-Origin": resolveOrigin(request),
|
||||||
|
});
|
||||||
|
|||||||
@ -169,10 +169,7 @@ export async function transformNotionBlog(env, notionBlog) {
|
|||||||
|
|
||||||
const published = properties["Published"].checkbox || false;
|
const published = properties["Published"].checkbox || false;
|
||||||
|
|
||||||
const dateRaw = properties["Date"].date;
|
const date = properties["Date"]?.date?.start || null;
|
||||||
const date = dateRaw?.start
|
|
||||||
? dayjs(dateRaw.start).format("DD/MM/YY h:mma")
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Extract image URLs (handle both external and file images)
|
// Extract image URLs (handle both external and file images)
|
||||||
const images = (properties["Images"]?.files || [])
|
const images = (properties["Images"]?.files || [])
|
||||||
|
|||||||
@ -302,7 +302,7 @@ export function collectImageUrls(contentObjects) {
|
|||||||
return imageUrls;
|
return imageUrls;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleBlurhashUpdate(request, env) {
|
export async function handleBlurHashUpdate(env) {
|
||||||
// Read the image cache
|
// Read the image cache
|
||||||
const cachedImages = await env.CONTENT_KV.get(env.IMAGES_KEY, {
|
const cachedImages = await env.CONTENT_KV.get(env.IMAGES_KEY, {
|
||||||
type: "json",
|
type: "json",
|
||||||
|
|||||||
@ -89,6 +89,10 @@ export async function storePages(env, pages) {
|
|||||||
|
|
||||||
export async function transformPageData(env, notionPage, settingsData) {
|
export async function transformPageData(env, notionPage, settingsData) {
|
||||||
const navigationItems = await getNavigation(env);
|
const navigationItems = await getNavigation(env);
|
||||||
|
console.log(
|
||||||
|
"Navigation items:",
|
||||||
|
navigationItems.map((item) => item.notionId)
|
||||||
|
);
|
||||||
|
|
||||||
const icon = getItemByNotionId(navigationItems, notionPage.id).icon;
|
const icon = getItemByNotionId(navigationItems, notionPage.id).icon;
|
||||||
|
|
||||||
|
|||||||
@ -140,7 +140,7 @@ export async function transformNotionPosition(env, notionPosition) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract duration
|
// Extract duration
|
||||||
const duration = properties["Duration"].date;
|
const duration = properties["Duration"]?.date || null;
|
||||||
|
|
||||||
// Extract name from title
|
// Extract name from title
|
||||||
const name = properties.Name?.title?.[0]?.plain_text || "Untitled";
|
const name = properties.Name?.title?.[0]?.plain_text || "Untitled";
|
||||||
|
|||||||
@ -166,8 +166,7 @@ export async function transformNotionProject(env, notionProject, settingsData) {
|
|||||||
|
|
||||||
const status = toCamelCase(properties["Status"]?.status?.name || null);
|
const status = toCamelCase(properties["Status"]?.status?.name || null);
|
||||||
|
|
||||||
const dateRaw = properties["Date"]?.date;
|
const date = properties["Date"]?.date?.start || null;
|
||||||
const date = dateRaw?.start ? dayjs(dateRaw.start).format("DD/MM/YY") : null;
|
|
||||||
|
|
||||||
// Extract image URL (handle both external and file images)
|
// Extract image URL (handle both external and file images)
|
||||||
const imageFile = notionProject?.cover;
|
const imageFile = notionProject?.cover;
|
||||||
|
|||||||
@ -4,13 +4,19 @@
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
"$schema": "node_modules/wrangler/config-schema.json",
|
"$schema": "node_modules/wrangler/config-schema.json",
|
||||||
"name": "tombutcher-api",
|
"name": "tombutcher-api-2026",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"compatibility_date": "2025-02-24",
|
"compatibility_date": "2025-02-24",
|
||||||
"observability": {
|
"observability": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"head_sampling_rate": 1
|
"head_sampling_rate": 1
|
||||||
},
|
},
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"pattern": "api2026.tombutcher.work",
|
||||||
|
"custom_domain": true
|
||||||
|
}
|
||||||
|
],
|
||||||
/**
|
/**
|
||||||
* Smart Placement
|
* Smart Placement
|
||||||
* Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
|
* Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
|
||||||
@ -24,6 +30,9 @@
|
|||||||
* https://developers.cloudflare.com/workers/runtime-apis/bindings/
|
* https://developers.cloudflare.com/workers/runtime-apis/bindings/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
"triggers": {
|
||||||
|
"crons": ["*/5 * * * *"]
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Environment Variables
|
* Environment Variables
|
||||||
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
|
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
|
||||||
@ -38,30 +47,35 @@
|
|||||||
"PROJECTS_DB": "297dd26d-60b6-8031-9de2-000bb1de652b",
|
"PROJECTS_DB": "297dd26d-60b6-8031-9de2-000bb1de652b",
|
||||||
"COMPANIES_DB": "29fdd26d-60b6-80e8-8b70-000b0c24c7b7",
|
"COMPANIES_DB": "29fdd26d-60b6-80e8-8b70-000b0c24c7b7",
|
||||||
"POSITIONS_DB": "29fdd26d-60b6-8018-9fd5-000bdce63f48",
|
"POSITIONS_DB": "29fdd26d-60b6-8018-9fd5-000bdce63f48",
|
||||||
|
"DEVELOPERS_DB": "2a6dd26d-60b6-8041-9dc3-000bf09477ed",
|
||||||
"CV_DB": "2a3dd26d-60b6-8098-85c0-000b12e171c4",
|
"CV_DB": "2a3dd26d-60b6-8098-85c0-000b12e171c4",
|
||||||
"BLOGS_KEY": "th-blogs-cache",
|
"BLOGS_KEY": "tb-blogs-cache",
|
||||||
"COMPANIES_KEY": "th-companies-cache",
|
"COMPANIES_KEY": "tb-companies-cache",
|
||||||
"POSITIONS_KEY": "th-positions-cache",
|
"POSITIONS_KEY": "tb-positions-cache",
|
||||||
"NAVIGATION_KEY": "th-navigation-cache",
|
"NAVIGATION_KEY": "tb-navigation-cache",
|
||||||
"PAGES_KEY": "th-pages-cache",
|
"PAGES_KEY": "tb-pages-cache",
|
||||||
"IMAGES_KEY": "th-images-cache",
|
"IMAGES_KEY": "tb-images-cache",
|
||||||
"BOOKINGS_KEY": "th-bookings-cache",
|
"BOOKINGS_KEY": "tb-bookings-cache",
|
||||||
"PROJECTS_KEY": "th-projects-cache",
|
"PROJECTS_KEY": "tb-projects-cache",
|
||||||
"VIDEOS_KEY": "th-videos-cache",
|
"VIDEOS_KEY": "tb-videos-cache",
|
||||||
"FILES_KEY": "th-files-cache",
|
"FILES_KEY": "tb-files-cache",
|
||||||
"PROPERTIES_KEY": "th-properties-cache",
|
"PROPERTIES_KEY": "tb-properties-cache",
|
||||||
"SETTINGS_KEY": "th-settings-cache",
|
"SETTINGS_KEY": "tb-settings-cache",
|
||||||
"CV_KEY": "th-cv-cache",
|
"CV_KEY": "tb-cv-cache",
|
||||||
"CACHE_URL": "https://api.tombutcherltd.com/cache",
|
"CACHE_URL": "https://api.tombutcherltd.com/cache",
|
||||||
"R2_PUBLIC_URL": "https://cdn2026.tombutcher.work",
|
"R2_PUBLIC_URL": "https://cdn2026.tombutcher.work",
|
||||||
"BLUR_HASH": "true",
|
"BLUR_HASH": "false",
|
||||||
"CORS_ORIGIN": "https://tombutcher.work"
|
"CORS_ORIGIN": [
|
||||||
|
"https://tombutcher.work",
|
||||||
|
"https://2026.tombutcher.work",
|
||||||
|
"https://api2026.tombutcher.work"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
"kv_namespaces": [
|
"kv_namespaces": [
|
||||||
{
|
{
|
||||||
"binding": "CONTENT_KV", // the variable you’ll use in the Worker
|
"binding": "CONTENT_KV", // the variable you’ll use in the Worker
|
||||||
"id": "05c5283d5b74488da7f90297ea350f9c" // ID from Cloudflare dashboard
|
"id": "1cffbf98b6e24fd3a58d5f484ecb12ef" // ID from Cloudflare dashboard
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"r2_buckets": [
|
"r2_buckets": [
|
||||||
@ -79,7 +93,7 @@
|
|||||||
"kv_namespaces": [
|
"kv_namespaces": [
|
||||||
{
|
{
|
||||||
"binding": "CONTENT_KV", // the variable you’ll use in the Worker
|
"binding": "CONTENT_KV", // the variable you’ll use in the Worker
|
||||||
"id": "05c5283d5b74488da7f90297ea350f9c" // ID from Cloudflare dashboard
|
"id": "1cffbf98b6e24fd3a58d5f484ecb12ef" // ID from Cloudflare dashboard
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"r2_buckets": [
|
"r2_buckets": [
|
||||||
@ -92,26 +106,38 @@
|
|||||||
"binding": "IMAGES" // i.e. available in your Worker on env.IMAGES
|
"binding": "IMAGES" // i.e. available in your Worker on env.IMAGES
|
||||||
},
|
},
|
||||||
"vars": {
|
"vars": {
|
||||||
"THEMES_DB": "26d4d3a4-6a6f-8052-966a-000bc1c836c1",
|
"THEMES_DB": "289dd26d-60b6-8195-843b-000b65b97c0a",
|
||||||
"GLOBAL_THEMES_DB": "26d4d3a4-6a6f-80a8-b5f8-000b1b040695",
|
"GLOBAL_THEMES_DB": "289dd26d-60b6-81d8-8823-000b24e2a783",
|
||||||
"PAGES_DB": "26d4d3a4-6a6f-80f1-a0fc-000b3c4c5013",
|
"PAGES_DB": "289dd26d-60b6-81d0-b598-000becb15373",
|
||||||
"PROPERTIES_DB": "26e4d3a4-6a6f-80b8-ac80-000b7b236ebc",
|
"BLOGS_DB": "289dd26d-60b6-811d-9bdb-000bc5557136",
|
||||||
"BOOKINGS_DB": "26e4d3a4-6a6f-80fe-960a-000be56680fd",
|
"MESSAGES_DB": "289dd26d-60b6-818e-9f49-000b5fb2ba34",
|
||||||
"GUESTS_DB": "2764d3a4-6a6f-808b-af87-000b072894d7",
|
"REDIRECTS_DB": "289dd26d-60b6-817c-9f97-000ba041fcfb",
|
||||||
"MESSAGES_DB": "2754d3a4-6a6f-80b5-8f8e-000b2ab6ae7a",
|
"PROJECTS_DB": "297dd26d-60b6-8031-9de2-000bb1de652b",
|
||||||
"REDIRECTS_DB": "2754d3a4-6a6f-80ca-b30f-000b828310d2",
|
"COMPANIES_DB": "29fdd26d-60b6-80e8-8b70-000b0c24c7b7",
|
||||||
"BRANDING_DB": "2764d3a4-6a6f-80f6-8354-000bf2304e00",
|
"POSITIONS_DB": "29fdd26d-60b6-8018-9fd5-000bdce63f48",
|
||||||
"NAVIGATION_KEY": "th-navigation-cache",
|
"DEVELOPERS_DB": "2a6dd26d-60b6-8041-9dc3-000bf09477ed",
|
||||||
"PAGES_KEY": "th-pages-cache",
|
"CV_DB": "2a3dd26d-60b6-8098-85c0-000b12e171c4",
|
||||||
"IMAGES_KEY": "th-images-cache",
|
"BLOGS_KEY": "tb-blogs-cache",
|
||||||
"BOOKINGS_KEY": "th-bookings-cache",
|
"COMPANIES_KEY": "tb-companies-cache",
|
||||||
"GUESTS_KEY": "th-guests-cache",
|
"POSITIONS_KEY": "tb-positions-cache",
|
||||||
"PROPERTIES_KEY": "th-properties-cache",
|
"NAVIGATION_KEY": "tb-navigation-cache",
|
||||||
"SETTINGS_KEY": "th-settings-cache",
|
"PAGES_KEY": "tb-pages-cache",
|
||||||
"CACHE_URL": "https://api.tombutcherltd.com/cache",
|
"IMAGES_KEY": "tb-images-cache",
|
||||||
|
"BOOKINGS_KEY": "tb-bookings-cache",
|
||||||
|
"PROJECTS_KEY": "tb-projects-cache",
|
||||||
|
"VIDEOS_KEY": "tb-videos-cache",
|
||||||
|
"FILES_KEY": "tb-files-cache",
|
||||||
|
"PROPERTIES_KEY": "tb-properties-cache",
|
||||||
|
"SETTINGS_KEY": "tb-settings-cache",
|
||||||
|
"CV_KEY": "tb-cv-cache",
|
||||||
|
"CACHE_URL": "https://api2026.tombutcher.work/cache",
|
||||||
"R2_PUBLIC_URL": "https://cdn2026.tombutcher.work",
|
"R2_PUBLIC_URL": "https://cdn2026.tombutcher.work",
|
||||||
"BLUR_HASH": "true",
|
"BLUR_HASH": "true",
|
||||||
"CORS_ORIGIN": "https://tombutcher.work"
|
"CORS_ORIGIN": [
|
||||||
|
"https://tombutcher.work",
|
||||||
|
"https://2026.tombutcher.work",
|
||||||
|
"https://api2026.tombutcher.work"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user