diff --git a/examples/javascript/simple-kv/azion.config.cjs b/examples/javascript/simple-kv/azion.config.cjs new file mode 100644 index 0000000..e9cdecb --- /dev/null +++ b/examples/javascript/simple-kv/azion.config.cjs @@ -0,0 +1,102 @@ +/** + * This file was automatically generated based on your preset configuration. + * + * For better type checking and IntelliSense: + * 1. Install azion as dev dependency: + * npm install -D azion + * + * 2. Use defineConfig: + * import { defineConfig } from 'azion' + * + * 3. Replace the configuration with defineConfig: + * export default defineConfig({ + * // Your configuration here + * }) + * + * For more configuration options, visit: + * https://github.com/aziontech/lib/tree/main/packages/config + */ + +module.exports = { + build: { + preset: "javascript", + polyfills: true, + }, + kv: [ + { + name: "$KV_NAME", + }, + ], + functions: [ + { + name: "$FUNCTION_NAME", + path: "./functions/index.js", + }, + ], + applications: [ + { + name: "$APPLICATION_NAME", + rules: { + request: [ + { + name: "Execute Function", + description: "Execute function for all requests", + active: true, + criteria: [ + [ + { + variable: "${uri}", + conditional: "if", + operator: "matches", + argument: "^/", + }, + ], + ], + behaviors: [ + { + type: "run_function", + attributes: { + value: "$FUNCTION_NAME", + }, + }, + ], + }, + ], + }, + functionsInstances: [ + { + name: "$FUNCTION_INSTANCE_NAME", + ref: "$FUNCTION_NAME", + }, + ], + }, + ], + workloads: [ + { + name: "$WORKLOAD_NAME", + active: true, + infrastructure: 1, + protocols: { + http: { + versions: ["http1", "http2"], + httpPorts: [80], + httpsPorts: [443], + quicPorts: null, + }, + }, + deployments: [ + { + name: "$DEPLOYMENT_NAME", + current: true, + active: true, + strategy: { + type: "default", + attributes: { + application: "$APPLICATION_NAME", + }, + }, + }, + ], + }, + ], +}; diff --git a/examples/javascript/simple-kv/index.js b/examples/javascript/simple-kv/index.js new file mode 100644 index 0000000..2972205 --- /dev/null +++ b/examples/javascript/simple-kv/index.js @@ -0,0 +1,27 @@ +export default { + async fetch(request, env, ctx) { + const kv = await Azion.KV.open("my-namespace-kv"); + + if (request.method === "GET") { + const message = await kv.get("message"); + return new Response(JSON.stringify({ message })); + } + + if (request.method === "POST") { + const body = await request.json(); + await kv.put("message", body?.message, { expirationTtl: 60 }); + return new Response(JSON.stringify({ message: "Message saved" }), { + headers: { "Content-Type": "application/json" }, + }); + } + + if (request.method === "DELETE") { + await kv.delete("message"); + return new Response(JSON.stringify({ message: "Message deleted" }), { + headers: { "Content-Type": "application/json" }, + }); + } + + return new Response("Method not allowed", { status: 405 }); + }, +}; diff --git a/examples/typescript/simple-ts-kv/azion.config.ts b/examples/typescript/simple-ts-kv/azion.config.ts new file mode 100644 index 0000000..872df80 --- /dev/null +++ b/examples/typescript/simple-ts-kv/azion.config.ts @@ -0,0 +1,102 @@ +/** + * This file was automatically generated based on your preset configuration. + * + * For better type checking and IntelliSense: + * 1. Install azion as dev dependency: + * npm install -D azion + * + * 2. Use defineConfig: + * import { defineConfig } from 'azion' + * + * 3. Replace the configuration with defineConfig: + * export default defineConfig({ + * // Your configuration here + * }) + * + * For more configuration options, visit: + * https://github.com/aziontech/lib/tree/main/packages/config + */ + +export default { + build: { + preset: "typescript", + polyfills: true, + }, + functions: [ + { + name: "$FUNCTION_NAME", + path: "./functions/index.js", + }, + ], + kv: [ + { + name: "$KV_NAME", + }, + ], + applications: [ + { + name: "$APPLICATION_NAME", + rules: { + request: [ + { + name: "Execute Function", + description: "Execute function for all requests", + active: true, + criteria: [ + [ + { + variable: "${uri}", + conditional: "if", + operator: "matches", + argument: "^/", + }, + ], + ], + behaviors: [ + { + type: "run_function", + attributes: { + value: "$FUNCTION_NAME", + }, + }, + ], + }, + ], + }, + functionsInstances: [ + { + name: "$FUNCTION_INSTANCE_NAME", + ref: "$FUNCTION_NAME", + }, + ], + }, + ], + workloads: [ + { + name: "$WORKLOAD_NAME", + active: true, + infrastructure: 1, + protocols: { + http: { + versions: ["http1", "http2"], + httpPorts: [80], + httpsPorts: [443], + quicPorts: null, + }, + }, + deployments: [ + { + name: "$DEPLOYMENT_NAME", + current: true, + active: true, + strategy: { + type: "default", + attributes: { + application: "$APPLICATION_NAME", + }, + }, + }, + ], + }, + ], +}; diff --git a/examples/typescript/simple-ts-kv/index.ts b/examples/typescript/simple-ts-kv/index.ts new file mode 100644 index 0000000..0720f8b --- /dev/null +++ b/examples/typescript/simple-ts-kv/index.ts @@ -0,0 +1,178 @@ +import * as kv from "azion/kv"; + +const VALID_TYPES = ["json", "text", "arrayBuffer", "stream"] as const; +type ValidType = (typeof VALID_TYPES)[number]; + +interface ErrorResponse { + error: string; + message: string; +} + +interface SuccessResponse { + success: boolean; + data?: any; + message?: string; +} + +function jsonResponse( + data: ErrorResponse | SuccessResponse, + status: number, +): Response { + return new Response(JSON.stringify(data), { + status, + headers: { "Content-Type": "application/json" }, + }); +} + +export default { + async fetch(request: Request, env: any, ctx: any) { + let client: any = null; + + try { + // Initialize the KV client + client = await kv + .createClient({ + namespace: "my-namespace", + }) + .connect(); + + const url = new URL(request.url); + const key = url.searchParams.get("key"); + const type = (url.searchParams.get("type") || "json") as ValidType; + + if (!key) { + return jsonResponse( + { error: "Bad Request", message: "Missing 'key' parameter" }, + 400, + ); + } + + if (!VALID_TYPES.includes(type)) { + return jsonResponse( + { + error: "Bad Request", + message: `Invalid type. Must be one of: ${VALID_TYPES.join(", ")}`, + }, + 400, + ); + } + + switch (request.method) { + case "GET": + return await handleGet(client, key, type); + + case "POST": + case "PUT": + return await handleSet(client, key, request); + + case "DELETE": + return await handleDelete(client, key); + + default: + return jsonResponse( + { + error: "Method Not Allowed", + message: `Method ${request.method} is not supported`, + }, + 405, + ); + } + } catch (error: any) { + console.error("KV Operation Error:", error); + return jsonResponse( + { + error: "Internal Server Error", + message: error.message || "An unexpected error occurred", + }, + 500, + ); + } finally { + if (client) { + try { + await client.disconnect(); + } catch (error) { + console.error("Error disconnecting client:", error); + } + } + } + }, +}; + +async function handleGet( + client: any, + key: string, + type: ValidType, +): Promise { + const value = await client.get(key, { type }); + + if (value === null || value === undefined) { + return jsonResponse( + { error: "Not Found", message: `Key '${key}' not found` }, + 404, + ); + } + + return jsonResponse({ success: true, data: value }, 200); +} + +async function handleSet( + client: any, + key: string, + request: Request, +): Promise { + const contentType = request.headers.get("Content-Type") || ""; + const ttl = parseInt( + new URL(request.url).searchParams.get("ttl") || "30", + 10, + ); + + let value: any; + let options: any = {}; + + if (ttl > 0) { + options.expiration = { + type: "EX", + value: ttl, + }; + } + + if (contentType.includes("application/json")) { + value = await request.json(); + } else if (contentType.includes("text/plain")) { + value = await request.text(); + } else { + return jsonResponse( + { + error: "Bad Request", + message: "Content-Type must be application/json or text/plain", + }, + 400, + ); + } + + await client.set(key, value, options); + + return jsonResponse( + { + success: true, + message: `Key '${key}' set successfully`, + data: { + key, + ttl: + options.expiration?.value > 0 + ? options.expiration.value + : "no expiration", + }, + }, + 200, + ); +} + +async function handleDelete(client: any, key: string): Promise { + await client.delete(key); + + return jsonResponse( + { success: true, message: `Key '${key}' deleted successfully` }, + 200, + ); +} diff --git a/examples/typescript/simple-ts-kv/package.json b/examples/typescript/simple-ts-kv/package.json new file mode 100644 index 0000000..026d597 --- /dev/null +++ b/examples/typescript/simple-ts-kv/package.json @@ -0,0 +1,12 @@ +{ + "name": "simple-ts-kv", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "devDependencies": { + "typescript": "^5.1.6" + }, + "dependencies": { + "azion": "latest" + } +} diff --git a/examples/typescript/simple-ts-kv/tsconfig.json b/examples/typescript/simple-ts-kv/tsconfig.json new file mode 100644 index 0000000..9b229e1 --- /dev/null +++ b/examples/typescript/simple-ts-kv/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + } +}