ZenBackendsanitizer.ts8 matches
7*/
89export function sanitizeSQLString(input: string): string {
10if (typeof input !== 'string') {
11throw new Error("Input must be a string");
32* Validate that a string matches expected format patterns
33*/
34export function validateFormat(input: string, pattern: RegExp): boolean {
35return pattern.test(input);
36}
39* Sanitize general input to prevent XSS and other attacks
40*/
41export function sanitizeInput(input: string, maxLength: number = 1000): string {
42if (typeof input !== 'string') {
43return '';
64* Validate booking ID format
65*/
66export function isValidBookingId(bookingId: string): boolean {
67return /^booking_[a-zA-Z0-9]{6,12}$/.test(bookingId);
68}
71* Validate nonce format
72*/
73export function isValidNonce(nonce: string): boolean {
74return /^[a-f0-9]{64}$/.test(nonce);
75}
78* Validate UUID format
79*/
80export function isValidUUID(uuid: string): boolean {
81return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(uuid);
82}
85* Validate decimal amount format
86*/
87export function isValidAmount(amount: string): boolean {
88return /^\d+(\.\d{2})?$/.test(amount);
89}
92* Validate timestamp format (ISO without timezone)
93*/
94export function isValidTimestamp(timestamp: string): boolean {
95return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(timestamp);
96}
ZenBackendpaymentService.ts1 match
129static generateMerchantUniquePaymentId(): string {
130// Generate a UUID v4
131return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
132const r = Math.random() * 16 | 0;
133const v = c === 'x' ? r : (r & 0x3 | 0x8);
ZenBackendsecurity.ts1 match
2import { environment } from "../config/environment.ts";
34export async function securityMiddleware(request: Request): Promise<Response | null> {
5const url = new URL(request.url);
6const ip = request.headers.get("cf-connecting-ip") ||
ZenBackendrateLimit.ts2 matches
31const rateLimitCache = new Map<string, { count: number; resetTime: number }>();
3233export async function rateLimitMiddleware(request: Request): Promise<Response | null> {
34const url = new URL(request.url);
35const endpoint = url.pathname;
100}
101102function cleanupRateLimitCache(): void {
103const now = Date.now();
104const cutoff = now - (60 * 60 * 1000); // 1 hour ago
ZenBackendcors.ts2 matches
6const ALLOWED_HEADERS = ["Content-Type", "X-Payment-Nonce", "Authorization"];
78export async function corsMiddleware(request: Request): Promise<Response | null> {
9const origin = request.headers.get("origin");
10const method = request.method;
49}
5051export function addCorsHeaders(response: Response, origin?: string): Response {
52const headers = new Headers(response.headers);
53
ZenBackendapiGateway.ts5 matches
293<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.11.0/swagger-ui-standalone-preset.js"></script>
294<script>
295window.onload = function() {
296const ui = SwaggerUIBundle({
297url: '/openapi.yaml',
307layout: "StandaloneLayout",
308tryItOutEnabled: true,
309requestInterceptor: function(request) {
310request.headers['X-Requested-With'] = 'SwaggerUI';
311return request;
312},
313responseInterceptor: function(response) {
314console.log('API Response:', response);
315return response;
326});
327
328setTimeout(function() {
329document.querySelectorAll('.opblock-summary-description').forEach(function(elem) {
330const text = elem.textContent;
331if (text && text.includes('nonce')) {
ZenBackendtest-frontend-client.tsx10 matches
3// This file currently runs on https://val.town infrastructure which has limitations.
45export default async function(_req: Request) {
6return new Response(
7`
110const randomName = randomNames[Math.floor(Math.random() * randomNames.length)];
111112function generateGUID() {
113return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
114const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
115return v.toString(16);
117}
118119function getTimestamp() {
120return new Date().toISOString().slice(0, 19);
121}
211};
212213function RenderZenPayResult({ zpResult }) {
214if (!zpResult) return null;
215try {
242243// Modern iframe modal component
244function PaymentIframeModal({ url, onClose }) {
245const [isLoading, setIsLoading] = useState(true);
246290}
291292function useScriptOrdered(scripts) {
293const [ready, setReady] = useState(false);
294useEffect(() => {
297for (let i = 0; i < scripts.length; ++i) {
298const { src, globalCheck } = scripts[i];
299if (typeof globalCheck === 'function' && globalCheck()) continue;
300if (typeof globalCheck === 'string' && window[globalCheck]) continue;
301await new Promise((resolve, reject) => {
316}
317318function useCSS(href) {
319useEffect(() => {
320if (!document.querySelector(\`link[href='\${href}']\`)) {
327}
328329function TravelCheckoutFlow() {
330// === Payment Variables ===
331// Enhanced security: Use demo booking for testing
ZenBackendREADME.md1 match
40- **Security Model**: Multi-layered protection mechanisms
41- **API Reference**: Complete endpoint documentation with examples
42- **Frontend Integration**: Required client-side functions and flow examples
43- **File Structure**: Purpose of each component in the system
44
ZenBackendDOCUMENTATION.md5 matches
352## Frontend Integration Requirements
353354### Required Client-Side Functions
355356```javascript
357// 1. UUID Generation for Payment IDs
358function generateUUID() {
359return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
360var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
361return v.toString(16);
364365// 2. Timestamp Generation (ISO format without timezone)
366function getCurrentTimestamp() {
367return new Date().toISOString().slice(0, 19); // "2025-07-04T05:15:00"
368}
369370// 3. Error Handling for Payment Failures
371function handlePaymentError() {
372// Must refresh page or call refresh endpoint
373// Cannot reuse burned nonces
50// --- HTML & FRONTEND ---
5152function generateHtml(sourceUrl: string) {
53return `<!DOCTYPE html>
54<html lang="en">
86/* Animations */
87@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } }
88.pulse { animation-name: pulse; animation-timing-function: ease-in-out; animation-iteration-count: infinite; }
89@keyframes shake { 0%, 100% { transform: translateX(0); } 10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); } 20%, 40%, 60%, 80% { transform: translateX(10px); } }
90.shake { animation-name: shake; animation-timing-function: ease-in-out; }
91@keyframes swoop-in { from { opacity: 0; transform: translateY(50px) scale(0.5); } to { opacity: 1; transform: translateY(0) scale(1); } }
92.swoop-in { animation-name: swoop-in; animation-timing-function: ease-out; }
93@keyframes glow { 0%, 100% { text-shadow: 0 0 20px #ffc400; } 50% { text-shadow: 0 0 35px #fff, 0 0 50px #f09; } }
94.glow { animation-name: glow; animation-timing-function: ease-in-out; animation-iteration-count: infinite; }
95
96/* Control Panel */
141142<script>
143(function() {
144const API_ENDPOINT = '${sourceUrl}api';
145const form = document.getElementById('ai-form');
193});
194195function applyUpdates(data) {
196if (!data.updates || !Array.isArray(data.updates)) {
197reasoningEl.textContent = 'AI returned an invalid response structure.';