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

67
node_modules/unstorage/drivers/netlify-blobs.mjs generated vendored Normal file
View File

@@ -0,0 +1,67 @@
import { createError, createRequiredError, defineDriver } from "./utils/index.mjs";
import { getStore, getDeployStore } from "@netlify/blobs";
import { fetch } from "ofetch";
const DRIVER_NAME = "netlify-blobs";
export default defineDriver((options) => {
const { deployScoped, name, ...opts } = options;
let store;
const getClient = () => {
if (!store) {
if (deployScoped) {
if (name) {
throw createError(
DRIVER_NAME,
"deploy-scoped stores cannot have a name"
);
}
store = getDeployStore({ fetch, ...options });
} else {
if (!name) {
throw createRequiredError(DRIVER_NAME, "name");
}
store = getStore({ name: encodeURIComponent(name), fetch, ...opts });
}
}
return store;
};
return {
name: DRIVER_NAME,
options,
getInstance: getClient,
async hasItem(key) {
return getClient().getMetadata(key).then(Boolean);
},
getItem: (key, tops) => {
return getClient().get(key, tops);
},
getMeta(key) {
return getClient().getMetadata(key);
},
getItemRaw(key, topts) {
return getClient().get(key, { type: topts?.type ?? "arrayBuffer" });
},
async setItem(key, value, topts) {
await getClient().set(key, value, topts);
},
async setItemRaw(key, value, topts) {
await getClient().set(key, value, topts);
},
removeItem(key) {
return getClient().delete(key);
},
async getKeys(base, tops) {
return (await getClient().list({ ...tops, prefix: base })).blobs.map(
(item) => item.key
);
},
async clear(base) {
const client = getClient();
return Promise.allSettled(
(await client.list({ prefix: base })).blobs.map(
(item) => client.delete(item.key)
)
).then(() => {
});
}
};
});