feat: Upgrade to Astro with full PDPA compliance

PDPA Features:
 Cookie consent banner
 Consent logging API
 Admin dashboard
 Privacy Policy
 Terms & Conditions

Technical:
 Astro 5.x + Tailwind v4
 Docker on port 80
 SQLite database
 15 pages built

Ready for Easypanel deployment.
This commit is contained in:
Kunthawat
2026-03-12 10:01:04 +07:00
parent 668f69048f
commit 77ac4d2d05
13719 changed files with 307487 additions and 25765 deletions

13
node_modules/astro-consent/dist/config/defaults.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import type { CookieBannerConfig } from "../types/config.js";
/**
* DEFAULT_CONFIG
* ---------------------------------------------------------
* Fallback values ONLY.
*
* These are used:
* - when the user omits a value
* - during internal normalisation
*
* User-provided config ALWAYS takes priority.
*/
export declare const DEFAULT_CONFIG: CookieBannerConfig;

40
node_modules/astro-consent/dist/config/defaults.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
/**
* DEFAULT_CONFIG
* ---------------------------------------------------------
* Fallback values ONLY.
*
* These are used:
* - when the user omits a value
* - during internal normalisation
*
* User-provided config ALWAYS takes priority.
*/
export const DEFAULT_CONFIG = {
siteName: "This website",
policyUrl: "/privacy",
consent: {
enabled: true,
// Number of days consent remains valid
days: 30,
// Must match runtime + frontend API
storageKey: "astro-consent"
},
categories: {
essential: {
label: "Essential",
description: "Required for the website to function correctly",
enabled: true,
readonly: true
},
analytics: {
label: "Analytics",
description: "Helps us understand how visitors use the site",
enabled: false
},
marketing: {
label: "Marketing",
description: "Used to deliver personalised ads",
enabled: false
}
}
};

View File

@@ -0,0 +1,7 @@
import type { CookieBannerConfig } from "../types/config.js";
/**
* Safely loads the user config file and merges it with defaults.
* User values always override defaults.
* Cache-busted to ensure updates are picked up during dev.
*/
export declare function loadUserConfig(projectRoot: string): Promise<CookieBannerConfig>;

65
node_modules/astro-consent/dist/config/loadConfig.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
import * as fs from "node:fs";
import * as path from "node:path";
import { pathToFileURL } from "node:url";
import { DEFAULT_CONFIG } from "./defaults.js";
/**
* Safely loads the user config file and merges it with defaults.
* User values always override defaults.
* Cache-busted to ensure updates are picked up during dev.
*/
export async function loadUserConfig(projectRoot) {
const configPath = path.join(projectRoot, "src", "astro-consent", "config.ts");
let userConfig = {};
try {
const stat = fs.statSync(configPath);
const cacheBuster = `?v=${stat.mtimeMs}`;
const imported = await import(
/* @vite-ignore */
pathToFileURL(configPath).href + cacheBuster);
userConfig = imported?.default ?? {};
}
catch (err) {
console.warn("[astro-consent] Failed to load user config, falling back to defaults");
}
return {
siteName: userConfig.siteName ?? DEFAULT_CONFIG.siteName,
policyUrl: userConfig.policyUrl ?? DEFAULT_CONFIG.policyUrl,
consent: {
enabled: userConfig.consent?.enabled ??
DEFAULT_CONFIG.consent.enabled,
days: userConfig.consent?.days ??
DEFAULT_CONFIG.consent.days,
storageKey: userConfig.consent?.storageKey ??
DEFAULT_CONFIG.consent.storageKey
},
categories: mergeCategories(userConfig.categories, DEFAULT_CONFIG.categories)
};
}
/**
* Merge category config safely.
* - Defaults are preserved
* - User overrides win
* - Custom categories are supported
*/
function mergeCategories(userCategories, defaultCategories) {
const merged = {};
// Start with defaults
for (const key of Object.keys(defaultCategories)) {
merged[key] = {
...defaultCategories[key],
...(userCategories?.[key] ?? {})
};
}
// Add user-defined custom categories safely
if (userCategories) {
for (const key of Object.keys(userCategories)) {
if (!merged[key]) {
merged[key] = {
...userCategories[key],
enabled: userCategories[key].enabled ?? false
};
}
}
}
return merged;
}