diff --git a/Mode2Test/tokens.json b/Mode2Test/tokens.json
index 0b48ccf..73c1cc1 100644
--- a/Mode2Test/tokens.json
+++ b/Mode2Test/tokens.json
@@ -1,7 +1,7 @@
{
- "pbToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2xsZWN0aW9uSWQiOiJfcGJfdXNlcnNfYXV0aF8iLCJleHAiOjE4MDAyMTY5MjgsImlkIjoiMWhiaWY5ZGJxbmc4Nmg5IiwicmVmcmVzaGFibGUiOnRydWUsInR5cGUiOiJhdXRoIn0.PCwm9Ac67h_n-lLv1BdzrqXDCsjfkEcWqTcgnwT5cGQ",
- "pbTokenExpiry": 1769285728680,
+ "pbToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2xsZWN0aW9uSWQiOiJfcGJfdXNlcnNfYXV0aF8iLCJleHAiOjE4MDAyMjIzMjgsImlkIjoiMWhiaWY5ZGJxbmc4Nmg5IiwicmVmcmVzaGFibGUiOnRydWUsInR5cGUiOiJhdXRoIn0.lkHN__Eh6ECrVtlQmCjl7sVZ1B2KMg75FnRjUNzsUtU",
+ "pbTokenExpiry": 1769291128701,
"graphToken": "eyJ0eXAiOiJKV1QiLCJub25jZSI6InRSOVQyM1h4RXhKRHN1YXJuSkdmcmYzd2FDS094TF9xWUkwd2dLUjhMVTQiLCJhbGciOiJSUzI1NiIsIng1dCI6IlBjWDk4R1g0MjBUMVg2c0JEa3poUW1xZ3dNVSIsImtpZCI6IlBjWDk4R1g0MjBUMVg2c0JEa3poUW1xZ3dNVSJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC8zZmQ5N2VhNy1iMTI0LTQxZjEtODU1Zi01MmQ4YWMzYjE2YzcvIiwiaWF0IjoxNzY4Njc4Mjk1LCJuYmYiOjE3Njg2NzgyOTUsImV4cCI6MTc2ODY4MjIxMSwiYWNjdCI6MCwiYWNyIjoiMSIsImFjcnMiOlsicDEiXSwiYWlvIjoiQWRRQUsvOGJBQUFBMW1BM04rN1pMMFU5OURDcUtsZ2JiOE1pSlhYRXZOT0dMQ2FjVllmdWZMTVM3b2N1emlvdkVmd1dZQnRBV2VyK0U5bGZxUU9FZ1lVZnBOODAxK2srMXBqOW5NRHlqdHhuRWVkaWI5Q1hZbThTMmFLeVNmZWFaQTFFZVdOa2VqWkduN2ZRQSsxLzE5ckVKcWlqMlRRRWZBMm9RTTlDamwxSE5QbGpGQ05iTHZwcmtETFIrT29CVlM4VlBXZi8zTU00Q1pzQ2ZiZnNRb3FuSGpzUHBUTzdFMzk1Qk5UQVhveXoxL1lRTkFucVhmNHRGajVaMUZVWW9jY1hES0NubEc0NXBmTVMxSHMreE1ZWVdnT3h0MkhJeVE9PSIsImFtciI6WyJyc2EiLCJtZmEiXSwiYXBwX2Rpc3BsYXluYW1lIjoiSm9iX0luZm9fU3luYyIsImFwcGlkIjoiM2M4NDZlNzEtOTYwOS00MGUxLWI0NTgtMGViODA1ZTIxYjlmIiwiYXBwaWRhY3IiOiIxIiwiZGV2aWNlaWQiOiJkZjdmZmUyOC04NDQ2LTQ5NjUtOWNlMC1jNDJiNjIxZmFiYjciLCJmYW1pbHlfbmFtZSI6IkV3aW5nIiwiZ2l2ZW5fbmFtZSI6IkFsZm9uc28iLCJpZHR5cCI6InVzZXIiLCJpcGFkZHIiOiIxNDMuMTA1LjI0Ny4xNDYiLCJuYW1lIjoiQWxmb25zbyBFd2luZyIsIm9pZCI6IjFhNmU5ZDEwLTEzOGEtNDNlNC1hMDllLTFmNTA0NjMxNDhjOSIsInBsYXRmIjoiMyIsInB1aWQiOiIxMDAzMjAwNTFGRUI4QUMwIiwicmgiOiIxLkFUVUFwMzdaUHlTeDhVR0ZYMUxZckRzV3h3TUFBQUFBQUFBQXdBQUFBQUFBQUFCbEFVazFBQS4iLCJzY3AiOiJDaGFubmVsLlJlYWRCYXNpYy5BbGwgQ2hhbm5lbE1lbWJlci5SZWFkLkFsbCBDaGFubmVsTWVtYmVyLlJlYWRXcml0ZS5BbGwgQ2hhbm5lbE1lc3NhZ2UuRWRpdCBDaGFubmVsTWVzc2FnZS5SZWFkLkFsbCBDaGFubmVsTWVzc2FnZS5SZWFkV3JpdGUgQ2hhbm5lbE1lc3NhZ2UuU2VuZCBDaGFubmVsU2V0dGluZ3MuUmVhZC5BbGwgQ2hhbm5lbFNldHRpbmdzLlJlYWRXcml0ZS5BbGwgQ2hhdE1lc3NhZ2UuUmVhZCBDaGF0TWVzc2FnZS5TZW5kIERpcmVjdG9yeS5BY2Nlc3NBc1VzZXIuQWxsIERpcmVjdG9yeS5SZWFkLkFsbCBEaXJlY3RvcnkuUmVhZFdyaXRlLkFsbCBlbWFpbCBGaWxlcy5SZWFkV3JpdGUuQWxsIEdyb3VwLlJlYWQuQWxsIEdyb3VwLlJlYWRXcml0ZS5BbGwgR3JvdXAtQ29udmVyc2F0aW9uLlJlYWQuQWxsIEdyb3VwLUNvbnZlcnNhdGlvbi5SZWFkV3JpdGUuQWxsIEdyb3VwTWVtYmVyLlJlYWQuQWxsIEdyb3VwTWVtYmVyLlJlYWRXcml0ZS5BbGwgR3JvdXBTZXR0aW5ncy5SZWFkLkFsbCBHcm91cFNldHRpbmdzLlJlYWRXcml0ZS5BbGwgcHJvZmlsZSBTaXRlcy5SZWFkV3JpdGUuQWxsIFRhc2tzLlJlYWQgVGFza3MuUmVhZC5TaGFyZWQgVGFza3MuUmVhZFdyaXRlIFRhc2tzLlJlYWRXcml0ZS5TaGFyZWQgVGVhbXNBY3Rpdml0eS5SZWFkIFRlYW1TZXR0aW5ncy5SZWFkLkFsbCBUZWFtU2V0dGluZ3MuUmVhZFdyaXRlLkFsbCBUZWFtc1BvbGljeVVzZXJBc3NpZ24uUmVhZFdyaXRlLkFsbCBVc2VyLlJlYWQgb3BlbmlkIiwic2lkIjoiMDA4ZDJjYjktODU5MS1jMDdkLTVhMjQtYzk2MjhkYzc1ZDIzIiwic2lnbmluX3N0YXRlIjpbImttc2kiXSwic3ViIjoiQXNWc0d6U3NUTmFWblJiTWxDWnlWeWtZMlh6NEhyS0RpRWx1eUVaWXZTdyIsInRlbmFudF9yZWdpb25fc2NvcGUiOiJOQSIsInRpZCI6IjNmZDk3ZWE3LWIxMjQtNDFmMS04NTVmLTUyZDhhYzNiMTZjNyIsInVuaXF1ZV9uYW1lIjoiYWV3aW5nQGNhcmRvemEuY29uc3RydWN0aW9uIiwidXBuIjoiYWV3aW5nQGNhcmRvemEuY29uc3RydWN0aW9uIiwidXRpIjoiVDljb0FWV3ZXVTJTbTBGLUFqS3lBQSIsInZlciI6IjEuMCIsIndpZHMiOlsiZmU5MzBiZTctNWU2Mi00N2RiLTkxYWYtOThjM2E0OWEzOGIxIiwiNjJlOTAzOTQtNjlmNS00MjM3LTkxOTAtMDEyMTc3MTQ1ZTEwIiwiMjkyMzJjZGYtOTMyMy00MmZkLWFkZTItMWQwOTdhZjNlNGRlIiwiNjkwOTEyNDYtMjBlOC00YTU2LWFhNGQtMDY2MDc1YjJhN2E4IiwiYjc5ZmJmNGQtM2VmOS00Njg5LTgxNDMtNzZiMTk0ZTg1NTA5Il0sInhtc19hY2QiOjE3NjM0MDU4NjQsInhtc19hY3RfZmN0IjoiOSAzIiwieG1zX2Z0ZCI6IkYyUXJpNWN3ZEhLQzVuZzFrYjdsU1huX3BlWXFaR3JUT21KeDYyN21LZUVCZFhOM1pYTjBNeTFrYzIxeiIsInhtc19pZHJlbCI6IjggMSIsInhtc19zdCI6eyJzdWIiOiJBSGY2UURxRXRkdkR5em1aMHlMMnRmZEktSW1ZUnFGVElRYUxzN2JKdlBjIn0sInhtc19zdWJfZmN0IjoiMyA2IiwieG1zX3RjZHQiOjE1NTg1NDYwMDcsInhtc190bnRfZmN0IjoiNiAzIn0.UqBTFe_GkrUqp9oHgjO93KtXckuDH91RQ03fV8ZzgUit4Vre1EXctVC-Zm5j5kfSM_6pb99VKasBPAolbIa4U-_J1yGidc81sghJj3Haz048v9_074Ky4Qzl0czNQ7OYTn2N1xKuYeBEzXCMt6Cc8gpGJv372seP0CVTs6ZxFTAfRXw2PvHsrJdiEJQMpMoSLBRC_bF9s223o6PiN3v1XgGbAqwP3WI-0GhtyK5Tnul0WJIH5i9G2sA3DlDAmxFm51RwxZtaeqhYPGNEkHrUQqBkNHeAiZ_VqvmGHyuj-D7E-XHOGkF8bQPCHWVXeLdZJNkOxxBEgqYNBpp2QWBWVg",
- "graphTokenExpiry": 1768684528680,
- "lastRefresh": 1768680928680
+ "graphTokenExpiry": 1768689928701,
+ "lastRefresh": 1768686328701
}
\ No newline at end of file
diff --git a/Mode3Test.backup/auth/README.md b/Mode3Test.backup/auth/README.md
new file mode 100644
index 0000000..fc28b12
--- /dev/null
+++ b/Mode3Test.backup/auth/README.md
@@ -0,0 +1,75 @@
+# Universal Auth Module
+
+## Overview
+This module provides a standardized, immutable authentication and token management system for any web project using PocketBase and Microsoft Graph. It supports user and agent tokens, delegated and app-only flows, and a consistent popup UI for login prompts.
+
+## Features
+- Pattern-based: Choose 'pb-user', 'pb-agent', 'graph-user', 'graph-agent', or any combination (e.g., 'pb-user+graph-agent') for your project needs
+- Supports both user and agent tokens for PocketBase and Microsoft Graph
+- Special handling for Valkey/Redis agent login and token storage (for backend/automation flows)
+- Single source of truth for token storage, retrieval, and refresh
+- Consistent, hidden popup for all user login prompts
+- Extracts user info (display name, email) from PocketBase
+- Works in any frontend project with PocketBase
+
+## Usage
+
+### 1. Include in your project
+```html
+
+
+```
+
+### 2. Initialize the pattern
+```js
+// Choose your pattern:
+// 'pb-user' - PocketBase user login
+// 'pb-agent' - PocketBase agent/service login
+// 'graph-user' - Microsoft Graph delegated (user) login
+// 'graph-agent' - Microsoft Graph agent/app-only (client credentials)
+// Combine as needed: 'pb-user+graph-agent', 'pb-agent+graph-user', etc.
+Auth.use('pb-user+graph-agent');
+```
+
+### 3. Get and use tokens
+```js
+const pbToken = await Auth.ensureToken('pb');
+const graphToken = await Auth.ensureToken('graph');
+const userInfo = Auth.getUserInfo();
+```
+
+### 4. Handle reauthentication
+- If a token is missing or expired, Auth will automatically show a popup for login.
+- The popup is hidden at all other times.
+
+### 5. Clear tokens (for testing or logout)
+```js
+Auth.clearToken('pb');
+Auth.clearToken('graph');
+```
+
+## Secrets and Environment
+- For frontend, all secrets are handled by PocketBase OAuth (no client secrets exposed).
+- For backend/agent flows, use environment variables and server-side code to store secrets securely.
+- The module does not expose or require secrets in the frontend.
+
+## Example Test Page
+See `auth-test.html` for a safe way to test all flows without affecting your main app.
+
+## Rules for Copilot Instructions
+- Always use Auth.use() to set the pattern before requesting tokens. Supported types: 'pb-user', 'pb-agent', 'graph-user', 'graph-agent', or any combination.
+- Always use Auth.ensureToken(type) to get a valid token; it will handle refresh and prompt if needed.
+- Never store secrets in frontend code; use PocketBase OAuth for user login.
+- All login prompts must use the provided popup, never custom dialogs.
+- Token keys are immutable: 'pbUserToken', 'pbAgentToken', 'graphUserToken', 'graphAgentToken'.
+- User info extraction must use Auth.getUserInfo().
+- For agent/app-only tokens, use backend code, environment variables, and optionally Valkey/Redis for secure storage and retrieval.
+
+## FAQ
+- **Can I use this in any project?** Yes, as long as you include PocketBase and this module.
+- **Does it work for both user and agent tokens?** Yes, with the correct pattern and backend support for agent tokens (including Valkey/Redis for automation).
+- **Is the popup customizable?** The style can be changed, but the flow must remain consistent for all projects.
+- **How are secrets handled?** Only via backend environment variables for agent tokens; never exposed in frontend.
+
+---
+For further integration, see the comments in `auth-universal.js` and the example test page.
\ No newline at end of file
diff --git a/Mode3Test.backup/auth/auth-test.html b/Mode3Test.backup/auth/auth-test.html
new file mode 100644
index 0000000..f2c195c
--- /dev/null
+++ b/Mode3Test.backup/auth/auth-test.html
@@ -0,0 +1,85 @@
+
+
+
+
+ Universal Auth Test
+
+
+
+
+
+
+
Choose Auth Pattern
+
+
+ Clear All Tokens
+
+
+
+
Test Actions
+
Test PB User
+
Test PB Agent
+
Test Graph User
+
Test Graph Agent
+
Show User Info
+
+
+
+
+
diff --git a/Mode3Test.backup/auth/auth-universal.js b/Mode3Test.backup/auth/auth-universal.js
new file mode 100644
index 0000000..47e3c02
--- /dev/null
+++ b/Mode3Test.backup/auth/auth-universal.js
@@ -0,0 +1,220 @@
+// Universal Auth Module: Immutable, Pattern-Based, Project-Agnostic
+// Usage: import and call Auth.use('pb-graph') or Auth.use('pb') or Auth.use('graph')
+// Provides: getToken(type), ensureToken(type), refreshToken(type), getUserInfo(), promptReauth()
+// Token types: 'pb' (PocketBase user/agent), 'graph' (Graph delegated), 'graphAgent' (Graph app-only)
+// All storage, retrieval, refresh, and UI are standardized and immutable
+
+const TOKEN_KEYS = {
+ 'pb-user': 'pbUserToken',
+ 'pb-agent': 'pbAgentToken',
+ 'graph-user': 'graphUserToken',
+ 'graph-agent': 'graphAgentToken'
+};
+
+function parsePattern(pattern) {
+ return pattern.split('+').map(s => s.trim()).filter(Boolean);
+}
+
+window.Auth = (() => {
+ let pattern = 'pb-user'; // default
+ let enabledTypes = ['pb-user'];
+ let pb = null;
+ let popup = null;
+ let agentCreds = { email: '', password: '' };
+ let superuserCreds = { email: '', password: '' };
+
+ // --- Setup ---
+ function use(type) {
+ pattern = type;
+ enabledTypes = parsePattern(type);
+ if (enabledTypes.some(t => t.startsWith('pb'))) {
+ pb = window.PocketBase ? new PocketBase('https://pocketbase.ccllc.pro') : null;
+ }
+ // Only one-time setup
+ if (!document.getElementById('authPopup')) {
+ createPopup();
+ }
+ }
+
+ // --- Token Storage ---
+ function getToken(type) {
+ return localStorage.getItem(TOKEN_KEYS[type]) || '';
+ }
+ function setToken(type, value) {
+ if (value) localStorage.setItem(TOKEN_KEYS[type], value);
+ }
+ function clearToken(type) {
+ localStorage.removeItem(TOKEN_KEYS[type]);
+ }
+
+ // --- Info Extraction ---
+ function getUserInfo() {
+ if (pb && pb.authStore.model) {
+ return {
+ displayName: pb.authStore.model.display_name || pb.authStore.model.name || pb.authStore.model.email || pb.authStore.model.username || 'Unknown',
+ email: pb.authStore.model.email || pb.authStore.model.username || null
+ };
+ }
+ return { displayName: '', email: '' };
+ }
+
+ // --- Token Ensure/Refresh ---
+ async function ensureToken(type) {
+ let token = getToken(type);
+ if (token) return token;
+ if (type === 'pb-user' && pb) {
+ if (pb.authStore.isValid) {
+ setToken('pb-user', pb.authStore.token);
+ return pb.authStore.token;
+ }
+ // Choose login method: email/password or OAuth
+ if (pattern.includes('pb-user-oauth')) {
+ return await promptReauth('pb-user-oauth');
+ } else {
+ return await promptReauth('pb-user');
+ }
+ }
+ if (type === 'pb-superuser' && pb) {
+ // Prompt for superuser credentials
+ await promptReauth('pb-superuser');
+ // Use superuser credentials to login
+ const authData = await pb.collection('_superuser').authWithPassword(superuserCreds.email, superuserCreds.password);
+ setToken('pb-superuser', pb.authStore.token);
+ return pb.authStore.token;
+ }
+ if (type === 'pb-agent' && pb) {
+ // Prompt for agent credentials if not set
+ if (!agentCreds.email || !agentCreds.password) {
+ await promptReauth('pb-agent');
+ }
+ // Use agent credentials to login
+ const authData = await pb.collection('users').authWithPassword(agentCreds.email, agentCreds.password);
+ setToken('pb-agent', pb.authStore.token);
+ return pb.authStore.token;
+ }
+ if (type === 'graph-user' && pb) {
+ // OAuth only
+ return await promptReauth('graph-user');
+ }
+ if (type === 'graph-agent') {
+ // Prompt for agent credentials if not set
+ if (!agentCreds.email || !agentCreds.password) {
+ await promptReauth('graph-agent');
+ }
+ // Use agent credentials to get token (simulate, real flow is backend)
+ setToken('graph-agent', 'AGENT_TOKEN_' + agentCreds.email);
+ return getToken('graph-agent');
+ }
+ throw new Error('Unknown token type');
+ }
+
+ async function refreshToken(type) {
+ if (type === 'graph-user' && pb) {
+ try {
+ const authData = await pb.collection('users').authRefresh();
+ const meta = authData?.meta || pb?.authStore?.model?.meta || {};
+ const token = meta.graphAccessToken || meta.graph_token || meta.graphToken || meta.accessToken || meta.access_token || meta.token || meta.rawToken || meta?.authData?.access_token || '';
+ setToken('graph-user', token);
+ return token || '';
+ } catch (err) {
+ return '';
+ }
+ }
+ // Add refresh logic for other types as needed
+ return '';
+ }
+
+ // --- Reauth Popup ---
+ function createPopup() {
+ popup = document.createElement('div');
+ popup.id = 'authPopup';
+ popup.style = 'display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.4);z-index:9999;align-items:center;justify-content:center;';
+ popup.innerHTML = `
+
+
Sign In Required
+
+
+
+ `;
+ document.body.appendChild(popup);
+ }
+
+ function showForm(type) {
+ const forms = {
+ 'pb-user': ` `,
+ 'pb-user-oauth': ``,
+ 'pb-superuser': ` `,
+ 'pb-agent': ` `,
+ 'graph-user': ``,
+ 'graph-agent': ` `
+ };
+ document.getElementById('authPopupForms').innerHTML = forms[type] || '';
+ }
+
+ async function promptReauth(type) {
+ showForm(type);
+ popup.style.display = 'flex';
+ return new Promise((resolve, reject) => {
+ document.getElementById('authPopupBtn').onclick = async () => {
+ try {
+ if (type === 'pb-user') {
+ const email = document.getElementById('pbUserEmail').value;
+ const password = document.getElementById('pbUserPassword').value;
+ const authData = await pb.collection('users').authWithPassword(email, password);
+ setToken('pb-user', pb.authStore.token);
+ popup.style.display = 'none';
+ resolve(pb.authStore.token);
+ } else if (type === 'pb-user-oauth') {
+ const authData = await pb.collection('users').authWithOAuth2({ provider: 'microsoft' });
+ setToken('pb-user', authData?.meta?.graphAccessToken || '');
+ popup.style.display = 'none';
+ resolve(authData?.meta?.graphAccessToken || '');
+ } else if (type === 'pb-superuser') {
+ superuserCreds.email = document.getElementById('pbSuperuserEmail').value;
+ superuserCreds.password = document.getElementById('pbSuperuserPassword').value;
+ popup.style.display = 'none';
+ resolve();
+ } else if (type === 'pb-agent') {
+ agentCreds.email = document.getElementById('pbAgentEmail').value;
+ agentCreds.password = document.getElementById('pbAgentPassword').value;
+ popup.style.display = 'none';
+ resolve();
+ } else if (type === 'graph-user') {
+ const authData = await pb.collection('users').authWithOAuth2({ provider: 'microsoft' });
+ setToken('graph-user', authData?.meta?.graphAccessToken || '');
+ popup.style.display = 'none';
+ resolve(authData?.meta?.graphAccessToken || '');
+ } else if (type === 'graph-agent') {
+ agentCreds.email = document.getElementById('graphAgentEmail').value;
+ agentCreds.password = document.getElementById('graphAgentPassword').value;
+ popup.style.display = 'none';
+ resolve();
+ }
+ } catch (err) {
+ document.getElementById('authPopupError').textContent = err.message || 'Authentication failed.';
+ document.getElementById('authPopupError').style.display = '';
+ }
+ };
+ });
+ }
+
+ // --- API ---
+ return {
+ use,
+ getToken,
+ setToken,
+ clearToken,
+ getUserInfo,
+ ensureToken,
+ refreshToken,
+ promptReauth
+ };
+})();
+
+window.Auth = Auth;
+
+// Example usage:
+// Auth.use('pb-graph');
+// const token = await Auth.ensureToken('graph');
+// const user = Auth.getUserInfo();
+// All login prompts are handled via the popup, which is hidden unless needed.
diff --git a/Mode3Test.backup/backend/cache-api-keys.cjs b/Mode3Test.backup/backend/cache-api-keys.cjs
new file mode 100644
index 0000000..640f3b5
--- /dev/null
+++ b/Mode3Test.backup/backend/cache-api-keys.cjs
@@ -0,0 +1,37 @@
+// Express API for Redis/Valkey: keys list and single key fetch (for fast UI)
+const express = require('express');
+const Redis = require('ioredis');
+const app = express();
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+// List all keys (no values)
+app.get('/api/cache/keys', async (req, res) => {
+ try {
+ const keys = await redis.keys('*');
+ // Optionally, add summary/metadata here
+ res.json(keys.map(key => ({ key })));
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+// Fetch value for a single key
+app.get('/api/cache/:key', async (req, res) => {
+ try {
+ const key = req.params.key;
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ res.json({ key, value });
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+const port = process.env.CACHE_API_PORT || 3006;
+app.listen(port, () => {
+ console.log(`Cache API (keys+single) running on http://localhost:${port}/api/cache/keys`);
+});
diff --git a/Mode3Test.backup/backend/cache-api.cjs b/Mode3Test.backup/backend/cache-api.cjs
new file mode 100644
index 0000000..f1e55eb
--- /dev/null
+++ b/Mode3Test.backup/backend/cache-api.cjs
@@ -0,0 +1,29 @@
+// Simple Express API to serve all Redis/Valkey cache keys and values as JSON (CommonJS)
+const express = require('express');
+const Redis = require('ioredis');
+const app = express();
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+app.get('/api/cache', async (req, res) => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ res.json(result);
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+const port = process.env.CACHE_API_PORT || 3006;
+app.listen(port, () => {
+ console.log(`Cache API running on http://localhost:${port}/api/cache`);
+});
diff --git a/Mode3Test.backup/backend/cache-api.js b/Mode3Test.backup/backend/cache-api.js
new file mode 100644
index 0000000..4a33eec
--- /dev/null
+++ b/Mode3Test.backup/backend/cache-api.js
@@ -0,0 +1,29 @@
+// Simple Express API to serve all Redis/Valkey cache keys and values as JSON
+const express = require('express');
+const Redis = require('ioredis');
+const app = express();
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+app.get('/api/cache', async (req, res) => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ res.json(result);
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+const port = process.env.CACHE_API_PORT || 3030;
+app.listen(port, () => {
+ console.log(`Cache API running on http://localhost:${port}/api/cache`);
+});
diff --git a/Mode3Test.backup/backend/list-redis-keys.cjs b/Mode3Test.backup/backend/list-redis-keys.cjs
new file mode 100644
index 0000000..d8d3f89
--- /dev/null
+++ b/Mode3Test.backup/backend/list-redis-keys.cjs
@@ -0,0 +1,25 @@
+// Script to list all Redis/Valkey keys and their values for visualization (CommonJS)
+const Redis = require('ioredis');
+
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+(async () => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ console.log(JSON.stringify(result, null, 2));
+ process.exit(0);
+ } catch (err) {
+ console.error('Error listing Redis keys:', err);
+ process.exit(1);
+ }
+})();
diff --git a/Mode3Test.backup/backend/list-redis-keys.js b/Mode3Test.backup/backend/list-redis-keys.js
new file mode 100644
index 0000000..d309b49
--- /dev/null
+++ b/Mode3Test.backup/backend/list-redis-keys.js
@@ -0,0 +1,25 @@
+// Script to list all Redis/Valkey keys and their values for visualization
+const Redis = require('ioredis');
+
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+(async () => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ console.log(JSON.stringify(result, null, 2));
+ process.exit(0);
+ } catch (err) {
+ console.error('Error listing Redis keys:', err);
+ process.exit(1);
+ }
+})();
diff --git a/Mode3Test.backup/backend/redis-cache.ts b/Mode3Test.backup/backend/redis-cache.ts
new file mode 100644
index 0000000..f6463a2
--- /dev/null
+++ b/Mode3Test.backup/backend/redis-cache.ts
@@ -0,0 +1,101 @@
+import Redis from 'ioredis';
+
+// Create Redis client
+const redis = new Redis({
+ host: process.env.REDIS_HOST || 'localhost',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+ retryStrategy(times) {
+ const delay = Math.min(times * 50, 2000);
+ return delay;
+ },
+ maxRetriesPerRequest: 3,
+ lazyConnect: true,
+});
+
+// Handle connection events
+redis.on('connect', () => {
+ console.log('✓ Redis connected');
+});
+
+redis.on('error', (err) => {
+ console.error('Redis error:', err.message);
+});
+
+redis.on('close', () => {
+ console.log('Redis connection closed');
+});
+
+// Connect to Redis
+(async () => {
+ try {
+ await redis.connect();
+ } catch (err) {
+ console.error('Failed to connect to Redis:', err);
+ }
+})();
+
+/**
+ * Get a value from cache
+ */
+export async function getCache(key: string): Promise {
+ try {
+ const value = await redis.get(key);
+ if (!value) return null;
+ return JSON.parse(value);
+ } catch (err) {
+ console.error(`Cache get error for key "${key}":`, err);
+ return null;
+ }
+}
+
+/**
+ * Set a value in cache with TTL in seconds
+ */
+export async function setCache(key: string, value: any, ttl: number = 300): Promise {
+ try {
+ const serialized = JSON.stringify(value);
+ await redis.setex(key, ttl, serialized);
+ return true;
+ } catch (err) {
+ console.error(`Cache set error for key "${key}":`, err);
+ return false;
+ }
+}
+
+/**
+ * Delete a key from cache
+ */
+export async function deleteCache(key: string): Promise {
+ try {
+ await redis.del(key);
+ return true;
+ } catch (err) {
+ console.error(`Cache delete error for key "${key}":`, err);
+ return false;
+ }
+}
+
+/**
+ * Clear all cache keys matching a pattern
+ */
+export async function clearCachePattern(pattern: string): Promise {
+ try {
+ const keys = await redis.keys(pattern);
+ if (keys.length === 0) return 0;
+ await redis.del(...keys);
+ return keys.length;
+ } catch (err) {
+ console.error(`Cache clear error for pattern "${pattern}":`, err);
+ return 0;
+ }
+}
+
+/**
+ * Check if Redis is connected
+ */
+export function isRedisConnected(): boolean {
+ return redis.status === 'ready';
+}
+
+export default redis;
diff --git a/Mode3Test.backup/backend/server.ts b/Mode3Test.backup/backend/server.ts
new file mode 100644
index 0000000..fb31b94
--- /dev/null
+++ b/Mode3Test.backup/backend/server.ts
@@ -0,0 +1,513 @@
+import { Hono } from 'hono';
+import { serveStatic } from 'hono/bun';
+import fs from 'fs';
+// @ts-ignore Bun project may not have dotenv types configured
+import { config } from 'dotenv';
+import { getCache, setCache, isRedisConnected } from './redis-cache';
+
+config();
+
+const app = new Hono();
+
+// Minimal log helpers
+const logLine = (path: string, line: string) => {
+ try {
+ fs.appendFileSync(path, `${new Date().toISOString()} ${line}\n`);
+ } catch (err) {
+ console.error('Failed to write log:', err);
+ }
+};
+
+// Version endpoint sourced from package.json
+app.get('/version', (c) => {
+ try {
+ const pkgRaw = fs.readFileSync('./package.json', 'utf-8');
+ const pkg = JSON.parse(pkgRaw);
+ return c.json({ version: pkg.version || '0.0.0' });
+ } catch (err) {
+ logLine('logs/error.log', `version endpoint error: ${(err as Error)?.message || String(err)}`);
+ return c.json({ version: '0.0.0' }, 200);
+ }
+});
+
+// Jobs endpoint with Redis caching
+app.get('/api/jobs', async (c) => {
+ const page = parseInt(c.req.query('page') || '1');
+ const perPage = parseInt(c.req.query('perPage') || '50');
+ const sort = c.req.query('sort') || '-Job_Number';
+
+ const cacheKey = `jobs:page:${page}:perPage:${perPage}:sort:${sort}`;
+ const ttl = 300; // 5 minutes cache
+
+ try {
+ // Try to get from cache first
+ if (isRedisConnected()) {
+ const cached = await getCache(cacheKey);
+ if (cached) {
+ logLine('logs/server.log', `Cache HIT for ${cacheKey}`);
+ return c.json(cached);
+ }
+ logLine('logs/server.log', `Cache MISS for ${cacheKey}`);
+ }
+
+ // Fetch from PocketBase
+ const pbUrl = `https://pocketbase.ccllc.pro/api/collections/pbc_1407612689/records?page=${page}&perPage=${perPage}&sort=${sort}`;
+ const authHeader = c.req.header('Authorization') || '';
+
+ const response = await fetch(pbUrl, {
+ headers: authHeader ? { Authorization: authHeader } : {}
+ });
+
+ if (!response.ok) {
+ throw new Error(`PocketBase returned ${response.status}`);
+ }
+
+ const data = await response.json();
+
+ // Cache the result
+ if (isRedisConnected()) {
+ await setCache(cacheKey, data, ttl);
+ logLine('logs/server.log', `Cached ${cacheKey} for ${ttl}s`);
+ }
+
+ return c.json(data);
+
+ } catch (err) {
+ logLine('logs/error.log', `jobs endpoint error: ${(err as Error)?.message || String(err)}`);
+ return c.json({ error: 'Failed to fetch jobs' }, 500);
+ }
+});
+
+// Fast endpoint: returns all jobs in a single cached request
+app.get('/api/jobs-all', async (c) => {
+ const cacheKey = 'jobs:all';
+ const ttl = 1800; // 30 minutes cache
+ try {
+ // Try cache first for instant response
+ if (isRedisConnected()) {
+ const cached = await getCache(cacheKey);
+ if (cached) {
+ logLine('logs/server.log', `Cache HIT for ${cacheKey} (${cached.items?.length || 0} jobs)`);
+ // Return cached data immediately
+ setImmediate(async () => {
+ try {
+ await refreshJobsCache(cacheKey, ttl, c.req.header('Authorization') || '');
+ } catch (err) {}
+ });
+ // Return all cached jobs in a single response
+ return c.json({ ...cached, partial: false });
+ } else {
+ // No cache: return empty array instantly, trigger background fetch
+ setImmediate(async () => {
+ try {
+ const result = await fetchAllJobsFromPocketBase(c.req.header('Authorization') || '');
+ if (isRedisConnected()) {
+ await setCache(cacheKey, result, ttl);
+ logLine('logs/server.log', `Cached ${cacheKey} with ${result.items.length} jobs for ${ttl}s`);
+ }
+ } catch (err) {
+ logLine('logs/error.log', `jobs-all background fetch error: ${(err as Error)?.message || String(err)}`);
+ }
+ });
+ return c.json({ items: [], partial: true });
+ }
+ }
+ // Redis not connected: fallback to direct fetch (blocking)
+ const result = await fetchAllJobsFromPocketBase(c.req.header('Authorization') || '');
+ return c.json(result);
+ } catch (err) {
+ logLine('logs/error.log', `jobs-all endpoint error: ${(err as Error)?.message || String(err)}`);
+ return c.json({ error: 'Failed to fetch jobs' }, 500);
+ }
+});
+
+// Helper function to fetch all jobs from PocketBase
+async function fetchAllJobsFromPocketBase(authHeader: string): Promise {
+ const allItems: any[] = [];
+ let page = 1;
+ const perPage = 500;
+
+ while (true) {
+ const pbUrl = `https://pocketbase.ccllc.pro/api/collections/pbc_1407612689/records?page=${page}&perPage=${perPage}&sort=-Job_Number`;
+ const response = await fetch(pbUrl, {
+ headers: authHeader ? { Authorization: authHeader } : {}
+ });
+
+ if (!response.ok) {
+ throw new Error(`PocketBase returned ${response.status}`);
+ }
+
+ const data = await response.json();
+ const items = data.items || [];
+
+ if (items.length === 0) break;
+ allItems.push(...items);
+
+ if (allItems.length >= (data.totalItems || 0)) break;
+ page++;
+ }
+
+ return {
+ page: 1,
+ perPage: allItems.length,
+ totalItems: allItems.length,
+ totalPages: 1,
+ items: allItems
+ };
+}
+
+// Helper function to refresh jobs cache in background
+async function refreshJobsCache(cacheKey: string, ttl: number, authHeader: string): Promise {
+ try {
+ const result = await fetchAllJobsFromPocketBase(authHeader);
+ await setCache(cacheKey, result, ttl);
+ logLine('logs/server.log', `Background refresh: cached ${cacheKey} with ${result.items.length} jobs`);
+ } catch (err) {
+ logLine('logs/error.log', `Background refresh error: ${(err as Error)?.message || String(err)}`);
+ }
+}
+
+
+// --- Microsoft Graph helpers ---
+const getGraphToken = (c?: any) => {
+ const headerToken = c?.req?.header ? c.req.header('x-graph-token') : '';
+ const envToken = process.env.GRAPH_TOKEN || process.env.MS_GRAPH_TOKEN || '';
+ const token = headerToken || envToken;
+ console.log('[getGraphToken] Header token:', headerToken ? headerToken.substring(0, 20) + '...' : 'NONE');
+ console.log('[getGraphToken] Env token:', envToken ? 'SET' : 'NOT SET');
+ console.log('[getGraphToken] Using:', token ? token.substring(0, 20) + '...' : 'NONE');
+ return token;
+};
+
+const b64Url = (input: string) =>
+ Buffer.from(input).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
+
+type DriveItem = {
+ id: string;
+ name: string;
+ webUrl?: string;
+ size?: number;
+ lastModifiedDateTime?: string;
+ file?: { mimeType?: string };
+ folder?: { childCount?: number };
+ parentReference?: { path?: string; driveId?: string };
+};
+
+const fetchJson = async (url: string, token: string) => {
+ const res = await fetch(url, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ Accept: 'application/json',
+ },
+ });
+ if (!res.ok) {
+ const text = await res.text();
+ const err: any = new Error(`Graph ${res.status}: ${text}`);
+ err.status = res.status;
+ throw err;
+ }
+ return res.json();
+};
+
+const resolveShareLink = async (link: string, token: string) => {
+ // Decode the link in case it comes pre-encoded from the database
+ const decodedLink = decodeURIComponent(link);
+ console.log('[resolveShareLink] Decoded link:', decodedLink);
+
+ // Check if this is a short sharing link (/:f:/ or /:b:/) or a direct document library URL
+ if (decodedLink.includes('/:f:/') || decodedLink.includes('/:b:/')) {
+ // Short sharing link - use shares API
+ const encoded = `u!${b64Url(decodedLink)}`;
+ console.log('[resolveShareLink] Using shares API, encoded:', encoded);
+ const data = await fetchJson(`https://graph.microsoft.com/v1.0/shares/${encoded}/driveItem`, token);
+ return { driveId: data.parentReference?.driveId as string, itemId: data.id as string };
+ } else {
+ // Direct document library URL - parse it and use drive API
+ // Example: https://czflex.sharepoint.com/sites/Team/Shared Documents/Forms/AllItems.aspx?RootFolder=/sites/Team/Shared Documents/General/...
+ const url = new URL(decodedLink);
+ const pathMatch = url.hostname.match(/^([^.]+)\.sharepoint\.com$/);
+ if (!pathMatch) throw new Error('Invalid SharePoint URL');
+
+ const hostname = pathMatch[1]; // e.g., 'czflex'
+ const sitePath = url.pathname.split('/Shared')[0]; // e.g., /sites/Team
+ const rootFolderParam = url.searchParams.get('RootFolder');
+ if (!rootFolderParam) throw new Error('RootFolder parameter missing');
+
+ // Extract the folder path relative to the document library
+ // RootFolder format: /sites/Team/Shared Documents/General/Operations [Server]/...
+ // We need: General/Operations [Server]/...
+ const folderPath = rootFolderParam.split('/Shared Documents/')[1];
+ if (!folderPath) throw new Error('Could not parse folder path');
+
+ console.log('[resolveShareLink] Hostname:', hostname);
+ console.log('[resolveShareLink] Site path:', sitePath);
+ console.log('[resolveShareLink] Folder path:', folderPath);
+
+ // Get the site ID first using hostname:sitePath format
+ const siteData = await fetchJson(`https://graph.microsoft.com/v1.0/sites/${hostname}.sharepoint.com:${sitePath}`, token);
+ const siteId = siteData.id;
+
+ // Get the default document library drive
+ const driveData = await fetchJson(`https://graph.microsoft.com/v1.0/sites/${siteId}/drive`, token);
+ const driveId = driveData.id;
+
+ // Get the folder item by path
+ const itemData = await fetchJson(
+ `https://graph.microsoft.com/v1.0/drives/${driveId}/root:/${folderPath}`,
+ token
+ );
+
+ console.log('[resolveShareLink] Resolved to driveId:', driveId, 'itemId:', itemData.id);
+ return { driveId, itemId: itemData.id };
+ }
+};
+
+const listChildrenRecursive = async (
+ driveId: string,
+ itemId: string,
+ depth = 0,
+ maxDepth = 5,
+ token: string,
+): Promise => {
+ const out: DriveItem[] = [];
+ const data = await fetchJson(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/children`, token);
+ for (const child of data.value || []) {
+ out.push(child as DriveItem);
+ if (child.folder && depth < maxDepth) {
+ const nested = await listChildrenRecursive(driveId, child.id, depth + 1, maxDepth, token);
+ out.push(...nested);
+ }
+ }
+ return out;
+};
+
+const searchWithinFolder = async (driveId: string, itemId: string, query: string, token: string): Promise => {
+ const data = await fetchJson(
+ `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/search(q='${encodeURIComponent(query)}')`,
+ token,
+ );
+ return (data.value || []) as DriveItem[];
+};
+
+const filterByCategory = (items: DriveItem[], category?: string, pdfOnly: boolean = true) => {
+ // First filter: show PDF files and Word documents (which will be converted to PDF)
+ let filtered = items;
+ if (pdfOnly) {
+ filtered = items.filter((i) => {
+ if (i.folder) return false;
+ const name = i.name.toLowerCase();
+ const mimeType = i.file?.mimeType?.toLowerCase() || '';
+ // Include PDFs, Word documents, and images
+ return name.endsWith('.pdf') || mimeType.includes('pdf') ||
+ name.endsWith('.doc') || name.endsWith('.docx') || mimeType.includes('word') ||
+ name.endsWith('.jpg') || name.endsWith('.jpeg') || name.endsWith('.png') ||
+ name.endsWith('.gif') || name.endsWith('.bmp') || name.endsWith('.tiff') ||
+ name.endsWith('.webp') || mimeType.includes('image');
+ });
+ }
+
+ // Second filter: category filtering (if specified)
+ if (!category) return filtered;
+ const nameHas = (name: string, words: string[]) => words.some((w) => name.includes(w));
+ const lc = (s: string) => (s || '').toLowerCase();
+ const contractWords = ['contract', 'estimate', 'proposal', 'bid', 'award', 'agreement', 'sow'];
+ const planWords = ['plan', 'drawing', 'dwg', 'pdf', 'sheet', 'layout'];
+ return filtered.filter((i) => {
+ const n = lc(i.name);
+ if (category === 'contracts') return nameHas(n, contractWords);
+ if (category === 'plans') return nameHas(n, planWords);
+ return true;
+ });
+};
+
+// List/search job files via Graph using a shared folder link
+app.get('/api/job-files', async (c) => {
+ try {
+ console.log('[job-files] Request received');
+ const token = getGraphToken(c);
+ if (!token) {
+ console.log('[job-files] No token found');
+ return c.json({ error: 'GRAPH_TOKEN missing' }, 500);
+ }
+ console.log('[job-files] Token found:', token.substring(0, 20) + '...');
+ const link = c.req.query('link');
+ const q = c.req.query('q') || '';
+ const category = c.req.query('category') || '';
+ if (!link) return c.json({ error: 'link required' }, 400);
+ console.log('[job-files] Link:', link);
+
+ const { driveId, itemId } = await resolveShareLink(link, token);
+
+ let items: DriveItem[] = [];
+ if (q) {
+ items = await searchWithinFolder(driveId, itemId, q, token);
+ } else {
+ // Walk subfolders up to depth 5
+ items = await listChildrenRecursive(driveId, itemId, 0, 5, token);
+ }
+
+ // Filter to show only PDFs by default (can be disabled with pdfOnly=false query param)
+ const pdfOnly = c.req.query('pdfOnly') !== 'false';
+ const filtered = filterByCategory(items, category, pdfOnly);
+ console.log(`[job-files] Found ${items.length} total items, ${filtered.length} after filtering`);
+
+ const mapped = filtered.map((i) => ({
+ id: i.id,
+ name: i.name,
+ url: i.webUrl,
+ driveId: i.parentReference?.driveId || driveId,
+ size: i.size,
+ modified: i.lastModifiedDateTime,
+ contentType: i.file?.mimeType,
+ isFolder: Boolean(i.folder),
+ path: i.parentReference?.path || '',
+ }));
+
+ return c.json({ items: mapped, total: mapped.length, source: q ? 'search' : 'walk', driveId });
+ } catch (err) {
+ const message = (err as Error)?.message || String(err);
+ const status = (err as any)?.status || 500;
+ console.error('[job-files] ERROR:', message);
+ logLine('logs/error.log', `/api/job-files error: ${message}`);
+ return c.json({ error: message }, status);
+ }
+});
+
+// Stream file content via Graph to avoid CSP issues for inline preview
+app.get('/api/job-file-content', async (c) => {
+ try {
+ const token = getGraphToken(c);
+ if (!token) return c.json({ error: 'GRAPH_TOKEN missing' }, 500);
+ const driveId = c.req.query('driveId');
+ const itemId = c.req.query('itemId');
+ if (!driveId || !itemId) return c.json({ error: 'driveId and itemId required' }, 400);
+
+ const res = await fetch(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/content`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+ if (!res.ok) {
+ const text = await res.text();
+ logLine('logs/error.log', `/api/job-file-content failed: ${res.status} - ${text}`);
+ return c.json({ error: `Graph ${res.status}: ${text}` }, 502);
+ }
+ const headers: Record = {};
+ const ct = res.headers.get('content-type');
+ const cd = res.headers.get('content-disposition');
+ if (ct) headers['Content-Type'] = ct;
+ if (cd) headers['Content-Disposition'] = cd;
+ return new Response(res.body, { status: 200, headers });
+ } catch (err) {
+ const message = (err as Error)?.message || String(err);
+ const status = (err as any)?.status || 500;
+ logLine('logs/error.log', `/api/job-file-content error: ${message}`);
+ return c.json({ error: message }, status);
+ }
+});
+
+// Convert Word documents to PDF for display
+app.get('/api/job-file-pdf', async (c) => {
+ try {
+ const token = getGraphToken(c);
+ if (!token) return c.json({ error: 'GRAPH_TOKEN missing' }, 500);
+ const driveId = c.req.query('driveId');
+ const itemId = c.req.query('itemId');
+ if (!driveId || !itemId) return c.json({ error: 'driveId and itemId required' }, 400);
+
+ // Use Graph API to convert to PDF format
+ const res = await fetch(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/content?format=pdf`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+ if (!res.ok) {
+ const text = await res.text();
+ logLine('logs/error.log', `/api/job-file-pdf conversion failed: ${res.status} - ${text}`);
+ return c.json({ error: `PDF conversion failed: ${res.status}` }, 502);
+ }
+ const headers: Record = {
+ 'Content-Type': 'application/pdf',
+ };
+ const cd = res.headers.get('content-disposition');
+ if (cd) {
+ // Replace .docx/.doc extension with .pdf in filename
+ headers['Content-Disposition'] = cd.replace(/\.(docx?)/gi, '.pdf');
+ }
+ logLine('logs/server.log', `Successfully converted document to PDF: driveId=${driveId}, itemId=${itemId}`);
+ return new Response(res.body, { status: 200, headers });
+ } catch (err) {
+ const message = (err as Error)?.message || String(err);
+ const status = (err as any)?.status || 500;
+ logLine('logs/error.log', `/api/job-file-pdf error: ${message}`);
+ return c.json({ error: message }, status);
+ }
+});
+
+// Mutation logging endpoint
+app.post('/log-change', async (c) => {
+ try {
+ const body = await c.req.json();
+ const { action = 'unknown', user = 'unknown', target = '', detail = '' } = body || {};
+ const payload = JSON.stringify({ action, user, target, detail });
+ logLine('logs/changes.log', payload);
+ return c.json({ status: 'ok' });
+ } catch (err) {
+ logLine('logs/error.log', `log-change error: ${(err as Error)?.message || String(err)}`);
+ return c.text('Bad Request', 400);
+ }
+});
+
+// Serve static files from the frontend directory (must come after API routes)
+// Add cache headers for static assets
+app.use('/assets/*', async (c, next) => {
+ await next();
+ // Cache assets for 1 year
+ c.header('Cache-Control', 'public, max-age=31536000, immutable');
+});
+app.use('/*', serveStatic({ root: './frontend' }));
+
+// Error handler
+app.onError((err, c) => {
+ logLine('logs/error.log', `Unhandled error: ${err?.message || err}`);
+ return c.text('Internal Server Error', 500);
+});
+
+// Default to 3005 for test instance; can be overridden by Environment=PORT
+const PORT = Number(process.env.PORT || 3005);
+
+logLine('logs/server.log', `Starting frontend server (Redis version) on port ${PORT}`);
+
+// Warm up cache on startup
+(async () => {
+ try {
+ if (isRedisConnected()) {
+ logLine('logs/server.log', 'Warming up jobs cache...');
+ const result = await fetchAllJobsFromPocketBase('');
+ await setCache('jobs:all', result, 1800);
+ logLine('logs/server.log', `✓ Cache warmed with ${result.items.length} jobs`);
+ }
+ } catch (err) {
+ logLine('logs/error.log', `Cache warmup failed: ${(err as Error)?.message || String(err)}`);
+ }
+})();
+
+// Background refresh every 5 minutes to keep cache hot
+setInterval(async () => {
+ try {
+ if (isRedisConnected()) {
+ await refreshJobsCache('jobs:all', 1800, '');
+ }
+ } catch (err) {
+ logLine('logs/error.log', `Periodic refresh error: ${(err as Error)?.message || String(err)}`);
+ }
+}, 5 * 60 * 1000); // Every 5 minutes
+
+// Graceful shutdown logging
+const shutdown = (signal: string) => {
+ logLine('logs/server.log', `Shutting down due to ${signal}`);
+ process.exit(0);
+};
+process.on('SIGINT', () => shutdown('SIGINT'));
+process.on('SIGTERM', () => shutdown('SIGTERM'));
+
+export default {
+ port: PORT,
+ fetch: app.fetch,
+};
diff --git a/Mode3Test.backup/bun.lock b/Mode3Test.backup/bun.lock
new file mode 100644
index 0000000..5ff3b9e
--- /dev/null
+++ b/Mode3Test.backup/bun.lock
@@ -0,0 +1,600 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 0,
+ "workspaces": {
+ "": {
+ "name": "job-info",
+ "dependencies": {
+ "dotenv": "^17.2.3",
+ "hono": "^4.10.8",
+ "ioredis": "^5.8.2",
+ "pocketbase": "^0.26.5",
+ "tailwind": "^4.0.0",
+ },
+ "devDependencies": {
+ "@types/bun": "latest",
+ "autoprefixer": "^10.4.23",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18",
+ },
+ "peerDependencies": {
+ "typescript": "^5",
+ },
+ },
+ },
+ "packages": {
+ "@babel/runtime": ["@babel/runtime@7.3.4", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g=="],
+
+ "@ioredis/commands": ["@ioredis/commands@1.4.0", "", {}, "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ=="],
+
+ "@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="],
+
+ "@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
+
+ "@types/react": ["@types/react@19.2.4", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-tBFxBp9Nfyy5rsmefN+WXc1JeW/j2BpBHFdLZbEVfs9wn3E3NRFxwV0pJg8M1qQAexFpvz73hJXFofV0ZAu92A=="],
+
+ "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
+
+ "ajv": ["ajv@6.10.0", "", { "dependencies": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg=="],
+
+ "amqplib": ["amqplib@0.5.2", "", { "dependencies": { "bitsyntax": "~0.0.4", "bluebird": "^3.4.6", "buffer-more-ints": "0.0.2", "readable-stream": "1.x >=1.1.9", "safe-buffer": "^5.0.1" } }, "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA=="],
+
+ "ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
+
+ "app-root-path": ["app-root-path@2.1.0", "", {}, "sha512-z5BqVjscbjmJBybKlICogJR2jCr2q/Ixu7Pvui5D4y97i7FLsJlvEG9XOR/KJRlkxxZz7UaaS2TMwQh1dRJ2dA=="],
+
+ "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
+
+ "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="],
+
+ "array.prototype.reduce": ["array.prototype.reduce@1.0.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-array-method-boxes-properly": "^1.0.0", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "is-string": "^1.1.1" } }, "sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw=="],
+
+ "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
+
+ "asn1": ["asn1@0.2.3", "", {}, "sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w=="],
+
+ "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
+
+ "async-limiter": ["async-limiter@1.0.1", "", {}, "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="],
+
+ "async-retry": ["async-retry@1.2.3", "", { "dependencies": { "retry": "0.12.0" } }, "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q=="],
+
+ "autoprefixer": ["autoprefixer@10.4.23", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001760", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA=="],
+
+ "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
+
+ "babel-runtime": ["babel-runtime@6.26.0", "", { "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" } }, "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g=="],
+
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.9.8", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Y1fOuNDowLfgKOypdc9SPABfoWXuZHBOyCS4cD52IeZBhr4Md6CLLs6atcxVrzRmQ06E7hSlm5bHHApPKR/byA=="],
+
+ "basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="],
+
+ "bitsyntax": ["bitsyntax@0.0.4", "", { "dependencies": { "buffer-more-ints": "0.0.2" } }, "sha512-Pav3HSZXD2NLQOWfJldY3bpJLt8+HS2nUo5Z1bLLmHg2vCE/cM1qfEvNjlYo7GgYQPneNr715Bh42i01ZHZPvw=="],
+
+ "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
+
+ "body-parser": ["body-parser@1.18.3", "", { "dependencies": { "bytes": "3.0.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "~1.6.3", "iconv-lite": "0.4.23", "on-finished": "~2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", "type-is": "~1.6.16" } }, "sha512-YQyoqQG3sO8iCmf8+hyVpgHHOv0/hCEFiS4zTGUwTA1HjAFX66wRcNQrVCeJq9pgESMRvUAOvSil5MJlmccuKQ=="],
+
+ "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
+
+ "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
+
+ "buffer-more-ints": ["buffer-more-ints@0.0.2", "", {}, "sha512-PDgX2QJgUc5+Jb2xAoBFP5MxhtVUmZHR33ak+m/SDxRdCrbnX1BggRIaxiW7ImwfmO4iJeCQKN18ToSXWGjYkA=="],
+
+ "bun-types": ["bun-types@1.3.2", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg=="],
+
+ "bytes": ["bytes@3.0.0", "", {}, "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw=="],
+
+ "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
+
+ "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
+
+ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="],
+
+ "chalk": ["chalk@2.4.1", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ=="],
+
+ "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
+
+ "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
+
+ "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
+
+ "commands-events": ["commands-events@1.0.4", "", { "dependencies": { "@babel/runtime": "7.2.0", "formats": "1.0.0", "uuidv4": "2.0.0" } }, "sha512-HdP/+1Anoc7z+6L2h7nd4Imz54+LW+BjMGt30riBZrZ3ZeP/8el93wD8Jj8ltAaqVslqNgjX6qlhSBJwuDSmpg=="],
+
+ "comparejs": ["comparejs@1.0.0", "", {}, "sha512-Ue/Zd9aOucHzHXwaCe4yeHR7jypp7TKrIBZ5yls35nPNiVXlW14npmNVKM1ZaLlQTKZ6/4ewA//gYKHHIwCpOw=="],
+
+ "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="],
+
+ "compression": ["compression@1.7.3", "", { "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", "compressible": "~2.0.14", "debug": "2.6.9", "on-headers": "~1.0.1", "safe-buffer": "5.1.2", "vary": "~1.1.2" } }, "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg=="],
+
+ "content-disposition": ["content-disposition@0.5.2", "", {}, "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA=="],
+
+ "content-type": ["content-type@1.0.4", "", {}, "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="],
+
+ "cookie": ["cookie@0.3.1", "", {}, "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw=="],
+
+ "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="],
+
+ "core-js": ["core-js@2.6.12", "", {}, "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="],
+
+ "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
+
+ "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="],
+
+ "crypto2": ["crypto2@2.0.0", "", { "dependencies": { "babel-runtime": "6.26.0", "node-rsa": "0.4.2", "util.promisify": "1.0.0" } }, "sha512-jdXdAgdILldLOF53md25FiQ6ybj2kUFTiRjs7msKTUoZrzgT/M1FPX5dYGJjbbwFls+RJIiZxNTC02DE/8y0ZQ=="],
+
+ "csstype": ["csstype@3.2.0", "", {}, "sha512-si++xzRAY9iPp60roQiFta7OFbhrgvcthrhlNAGeQptSY25uJjkfUV8OArC3KLocB8JT8ohz+qgxWCmz8RhjIg=="],
+
+ "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
+
+ "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
+
+ "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
+
+ "datasette": ["datasette@1.0.1", "", { "dependencies": { "comparejs": "1.0.0", "eventemitter2": "5.0.1", "lodash": "4.17.5" } }, "sha512-aJdlCBToEJUP4M57r67r4V6tltwGKa3qetnjpBtXYIlqbX9tM9jsoDMxb4xd9AGjpp3282oHRmqI5Z8TVAU0Mg=="],
+
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
+ "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
+
+ "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
+
+ "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
+
+ "depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="],
+
+ "destroy": ["destroy@1.0.4", "", {}, "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg=="],
+
+ "dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
+
+ "draht": ["draht@1.0.1", "", { "dependencies": { "eventemitter2": "5.0.1" } }, "sha512-yNNHL864dniNmIE9ZKD++mKypiAUAvVZtyV0QrbXH/ak3ebzFqo5xsmRBRqV8pZVhImOSBiyq500Wcmrf44zAg=="],
+
+ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
+
+ "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
+
+ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="],
+
+ "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
+
+ "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="],
+
+ "es-array-method-boxes-properly": ["es-array-method-boxes-properly@1.0.0", "", {}, "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="],
+
+ "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
+
+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+ "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
+
+ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
+
+ "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
+
+ "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
+
+ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
+
+ "eventemitter2": ["eventemitter2@5.0.1", "", {}, "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg=="],
+
+ "express": ["express@4.16.4", "", { "dependencies": { "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.3", "content-disposition": "0.5.2", "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.4", "qs": "6.5.2", "range-parser": "~1.2.0", "safe-buffer": "5.1.2", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", "statuses": "~1.4.0", "type-is": "~1.6.16", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg=="],
+
+ "fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="],
+
+ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
+
+ "finalhandler": ["finalhandler@1.1.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "statuses": "~1.4.0", "unpipe": "~1.0.0" } }, "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg=="],
+
+ "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
+
+ "flaschenpost": ["flaschenpost@1.1.3", "", { "dependencies": { "@babel/runtime": "7.2.0", "app-root-path": "2.1.0", "babel-runtime": "6.26.0", "chalk": "2.4.1", "find-root": "1.1.0", "lodash": "4.17.11", "moment": "2.22.2", "processenv": "1.1.0", "split2": "3.0.0", "stack-trace": "0.0.10", "stringify-object": "3.3.0", "untildify": "3.0.3", "util.promisify": "1.0.0", "varname": "2.0.3" }, "bin": { "flaschenpost-uncork": "dist/bin/flaschenpost-uncork.js", "flaschenpost-normalize": "dist/bin/flaschenpost-normalize.js" } }, "sha512-1VAYPvDsVBGFJyUrOa/6clnJwZYC3qVq9nJLcypy6lvaaNbo1wOQiH8HQ+4Fw/k51pVG7JHzSf5epb8lmIW86g=="],
+
+ "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
+
+ "formats": ["formats@1.0.0", "", {}, "sha512-For0Y8egwEK96JgJo4NONErPhtl7H2QzeB2NYGmzeGeJ8a1JZqPgLYOtM3oJRCYhmgsdDFd6KGRYyfe37XY4Yg=="],
+
+ "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
+
+ "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
+
+ "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="],
+
+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+ "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
+
+ "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
+
+ "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
+
+ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
+
+ "get-own-enumerable-property-symbols": ["get-own-enumerable-property-symbols@3.0.2", "", {}, "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g=="],
+
+ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+
+ "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
+
+ "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
+
+ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
+
+ "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
+
+ "has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
+
+ "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
+
+ "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
+
+ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
+
+ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
+
+ "hase": ["hase@2.0.0", "", { "dependencies": { "@babel/runtime": "7.1.2", "amqplib": "0.5.2" } }, "sha512-L83pBR/oZvQQNjv4kw9aUpTqBxERPiY7B42jsmkt1VDeUaRVhYkEIKzkCqrppjtxHe2EZqzZJzuhMXsWsxYIsw=="],
+
+ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
+
+ "hono": ["hono@4.10.8", "", {}, "sha512-DDT0A0r6wzhe8zCGoYOmMeuGu3dyTAE40HHjwUsWFTEy5WxK1x2WDSsBPlEXgPbRIFY6miDualuUDbasPogIww=="],
+
+ "http-errors": ["http-errors@1.6.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" } }, "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A=="],
+
+ "iconv-lite": ["iconv-lite@0.4.23", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA=="],
+
+ "inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="],
+
+ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
+
+ "ioredis": ["ioredis@5.8.2", "", { "dependencies": { "@ioredis/commands": "1.4.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q=="],
+
+ "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
+
+ "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
+
+ "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
+
+ "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
+
+ "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
+
+ "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
+
+ "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
+
+ "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
+
+ "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
+
+ "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
+
+ "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
+
+ "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
+
+ "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
+
+ "is-obj": ["is-obj@1.0.1", "", {}, "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="],
+
+ "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
+
+ "is-regexp": ["is-regexp@1.0.0", "", {}, "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA=="],
+
+ "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
+
+ "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
+
+ "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
+
+ "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
+
+ "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
+
+ "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
+
+ "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
+
+ "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
+
+ "isarray": ["isarray@0.0.1", "", {}, "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="],
+
+ "json-lines": ["json-lines@1.0.0", "", { "dependencies": { "timer2": "1.0.0" } }, "sha512-ytuLZb4RBQb3bTRsG/QBenyIo5oHLpjeCVph3s2NnoAsZE9K6h+uR+OWpEOWV1UeHdX63tYctGppBpGAc+JNMA=="],
+
+ "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
+
+ "jsonwebtoken": ["jsonwebtoken@8.5.0", "", { "dependencies": { "jws": "^3.2.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^5.6.0" } }, "sha512-IqEycp0znWHNA11TpYi77bVgyBO/pGESDh7Ajhas+u0ttkGkKYIIAjniL4Bw5+oVejVF+SYkaI7XKfwCCyeTuA=="],
+
+ "jwa": ["jwa@1.4.2", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw=="],
+
+ "jws": ["jws@3.2.3", "", { "dependencies": { "jwa": "^1.4.2", "safe-buffer": "^5.0.1" } }, "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g=="],
+
+ "limes": ["limes@2.0.0", "", { "dependencies": { "@babel/runtime": "7.3.4", "jsonwebtoken": "8.5.0" } }, "sha512-evWD0pnTgPX7QueaSoJl5JBUL30T1ZVzo34ke97tIKmeagqhBTYK/JkKL0vtG3MpNApw8ZY9TlbybfwEz9knBA=="],
+
+ "lodash": ["lodash@4.17.11", "", {}, "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="],
+
+ "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="],
+
+ "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="],
+
+ "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="],
+
+ "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="],
+
+ "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="],
+
+ "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="],
+
+ "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
+
+ "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="],
+
+ "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
+
+ "lusca": ["lusca@1.6.1", "", { "dependencies": { "tsscmp": "^1.0.5" } }, "sha512-+JzvUMH/rsE/4XfHdDOl70bip0beRcHSviYATQM0vtls59uVtdn1JMu4iD7ZShBpAmFG8EnaA+PrYG9sECMIOQ=="],
+
+ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+
+ "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="],
+
+ "merge-descriptors": ["merge-descriptors@1.0.1", "", {}, "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="],
+
+ "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="],
+
+ "mime": ["mime@1.4.1", "", { "bin": { "mime": "cli.js" } }, "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="],
+
+ "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
+
+ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
+ "moment": ["moment@2.22.2", "", {}, "sha512-LRvkBHaJGnrcWvqsElsOhHCzj8mU39wLx5pQ0pc6s153GynCTsPdGdqsVNKAQD9sKnWj11iF7TZx9fpLwdD3fw=="],
+
+ "morgan": ["morgan@1.9.1", "", { "dependencies": { "basic-auth": "~2.0.0", "debug": "2.6.9", "depd": "~1.1.2", "on-finished": "~2.3.0", "on-headers": "~1.0.1" } }, "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+ "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
+
+ "nocache": ["nocache@2.0.0", "", {}, "sha512-YdKcy2x0dDwOh+8BEuHvA+mnOKAhmMQDgKBOCUGaLpewdmsRYguYZSom3yA+/OrE61O/q+NMQANnun65xpI1Hw=="],
+
+ "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
+
+ "node-rsa": ["node-rsa@0.4.2", "", { "dependencies": { "asn1": "0.2.3" } }, "sha512-Bvso6Zi9LY4otIZefYrscsUpo2mUpiAVIEmSZV2q41sP8tHZoert3Yu6zv4f/RXJqMNZQKCtnhDugIuCma23YA=="],
+
+ "node-statsd": ["node-statsd@0.1.1", "", {}, "sha512-QDf6R8VXF56QVe1boek8an/Rb3rSNaxoFWb7Elpsv2m1+Noua1yy0F1FpKpK5VluF8oymWM4w764A4KsYL4pDg=="],
+
+ "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
+
+ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
+
+ "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
+
+ "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
+
+ "object.getownpropertydescriptors": ["object.getownpropertydescriptors@2.1.9", "", { "dependencies": { "array.prototype.reduce": "^1.0.8", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "gopd": "^1.2.0", "safe-array-concat": "^1.1.3" } }, "sha512-mt8YM6XwsTTovI+kdZdHSxoyF2DI59up034orlC9NfweclcWOt7CVascNNLp6U+bjFVCVCIh9PwS76tDM/rH8g=="],
+
+ "on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
+
+ "on-headers": ["on-headers@1.0.2", "", {}, "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="],
+
+ "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
+
+ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
+
+ "partof": ["partof@1.0.0", "", {}, "sha512-+TXdhKCySpJDynCxgAPoGVyAkiK3QPusQ63/BdU5t68QcYzyU6zkP/T7F3gkMQBVUYqdWEADKa6Kx5zg8QIKrg=="],
+
+ "path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "pocketbase": ["pocketbase@0.26.5", "", {}, "sha512-SXcq+sRvVpNxfLxPB1C+8eRatL7ZY4o3EVl/0OdE3MeR9fhPyZt0nmmxLqYmkLvXCN9qp3lXWV/0EUYb3MmMXQ=="],
+
+ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
+
+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
+ "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
+
+ "processenv": ["processenv@1.1.0", "", { "dependencies": { "babel-runtime": "6.26.0" } }, "sha512-SymqIsn8GjEUy8nG7HiyEjgbfk1xFosRIakUX1NHLpriq3vVpKniGrr9RdMWCaGYWByIovbRt2f/WvmP/IOApQ=="],
+
+ "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
+
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+
+ "qs": ["qs@6.5.2", "", {}, "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="],
+
+ "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
+
+ "raw-body": ["raw-body@2.3.3", "", { "dependencies": { "bytes": "3.0.0", "http-errors": "1.6.3", "iconv-lite": "0.4.23", "unpipe": "1.0.0" } }, "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw=="],
+
+ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
+
+ "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="],
+
+ "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="],
+
+ "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
+
+ "regenerator-runtime": ["regenerator-runtime@0.12.1", "", {}, "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="],
+
+ "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
+
+ "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
+
+ "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
+
+ "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
+
+ "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
+
+ "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
+
+ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
+
+ "semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
+
+ "send": ["send@0.16.2", "", { "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", "on-finished": "~2.3.0", "range-parser": "~1.2.0", "statuses": "~1.4.0" } }, "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw=="],
+
+ "serve-static": ["serve-static@1.13.2", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.2", "send": "0.16.2" } }, "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw=="],
+
+ "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
+
+ "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
+
+ "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
+
+ "setprototypeof": ["setprototypeof@1.1.0", "", {}, "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="],
+
+ "sha-1": ["sha-1@0.1.1", "", {}, "sha512-dexizf3hB7d4Jq6Cd0d/NYQiqgEqIfZIpuMfwPfvSb6h06DZKmHyUe55jYwpHC12R42wpqXO6ouhiBpRzIcD/g=="],
+
+ "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
+
+ "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
+
+ "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
+
+ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "split2": ["split2@3.0.0", "", { "dependencies": { "readable-stream": "^3.0.0" } }, "sha512-Cp7G+nUfKJyHCrAI8kze3Q00PFGEG1pMgrAlTFlDbn+GW24evSZHJuMl+iUJx1w/NTRDeBiTgvwnf6YOt94FMw=="],
+
+ "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="],
+
+ "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
+
+ "statuses": ["statuses@1.4.0", "", {}, "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="],
+
+ "stethoskop": ["stethoskop@1.0.0", "", { "dependencies": { "node-statsd": "0.1.1" } }, "sha512-4JnZ+UmTs9SFfDjSHFlD/EoXcb1bfwntkt4h1ipNGrpxtRzmHTxOmdquCJvIrVu608Um7a09cGX0ZSOSllWJNQ=="],
+
+ "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
+
+ "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
+
+ "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
+
+ "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
+
+ "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
+
+ "stringify-object": ["stringify-object@3.3.0", "", { "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" } }, "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw=="],
+
+ "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
+
+ "tailwind": ["tailwind@4.0.0", "", { "dependencies": { "@babel/runtime": "7.3.4", "ajv": "6.10.0", "app-root-path": "2.1.0", "async-retry": "1.2.3", "body-parser": "1.18.3", "commands-events": "1.0.4", "compression": "1.7.3", "content-type": "1.0.4", "cors": "2.8.5", "crypto2": "2.0.0", "datasette": "1.0.1", "draht": "1.0.1", "express": "4.16.4 ", "flaschenpost": "1.1.3", "hase": "2.0.0", "json-lines": "1.0.0", "limes": "2.0.0", "lodash": "4.17.11", "lusca": "1.6.1", "morgan": "1.9.1", "nocache": "2.0.0", "partof": "1.0.0", "processenv": "1.1.0", "stethoskop": "1.0.0", "timer2": "1.0.0", "uuidv4": "3.0.1", "ws": "6.2.0" } }, "sha512-LlUNoD/5maFG1h5kQ6/hXfFPdcnYw+1Z7z+kUD/W/E71CUMwcnrskxiBM8c3G8wmPsD1VvCuqGYMHviI8+yrmg=="],
+
+ "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
+
+ "timer2": ["timer2@1.0.0", "", {}, "sha512-UOZql+P2ET0da+B7V3/RImN3IhC5ghb+9cpecfUhmYGIm0z73dDr3A781nBLnFYmRzeT1AmoT4w9Lgr8n7n7xg=="],
+
+ "tsscmp": ["tsscmp@1.0.6", "", {}, "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="],
+
+ "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="],
+
+ "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
+
+ "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
+
+ "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
+
+ "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
+
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+
+ "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
+
+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
+
+ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
+
+ "untildify": ["untildify@3.0.3", "", {}, "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+
+ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
+
+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
+
+ "util.promisify": ["util.promisify@1.0.0", "", { "dependencies": { "define-properties": "^1.1.2", "object.getownpropertydescriptors": "^2.0.3" } }, "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA=="],
+
+ "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
+
+ "uuid": ["uuid@3.3.2", "", { "bin": { "uuid": "./bin/uuid" } }, "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="],
+
+ "uuidv4": ["uuidv4@3.0.1", "", { "dependencies": { "uuid": "3.3.2" } }, "sha512-PPzksdWRl2a5C9hrs3OOYrArTeyoR0ftJ3jtOy+BnVHkT2UlrrzPNt9nTdiGuxmQItHM/AcTXahwZZC57Njojg=="],
+
+ "varname": ["varname@2.0.3", "", {}, "sha512-+DofT9mJAUALhnr9ipZ5Z2icwaEZ7DAajOZT4ffXy3MQqnXtG3b7atItLQEJCkfcJTOf9WcsywneOEibD4eqJg=="],
+
+ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
+
+ "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
+
+ "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
+
+ "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
+
+ "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="],
+
+ "ws": ["ws@6.2.0", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w=="],
+
+ "amqplib/readable-stream": ["readable-stream@1.1.14", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ=="],
+
+ "babel-runtime/regenerator-runtime": ["regenerator-runtime@0.11.1", "", {}, "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="],
+
+ "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "commands-events/@babel/runtime": ["@babel/runtime@7.2.0", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg=="],
+
+ "commands-events/uuidv4": ["uuidv4@2.0.0", "", { "dependencies": { "sha-1": "0.1.1", "uuid": "3.3.2" } }, "sha512-sAUlwUVepcVk6bwnaW/oi6LCwMdueako5QQzRr90ioAVVcms6p1mV0PaSxK8gyAC4CRvKddsk217uUpZUbKd2Q=="],
+
+ "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "datasette/lodash": ["lodash@4.17.5", "", {}, "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="],
+
+ "ecdsa-sig-formatter/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+ "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "flaschenpost/@babel/runtime": ["@babel/runtime@7.2.0", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg=="],
+
+ "hase/@babel/runtime": ["@babel/runtime@7.1.2", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg=="],
+
+ "mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+ "morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "safe-array-concat/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "send/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+ "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "amqplib/readable-stream/string_decoder": ["string_decoder@0.10.31", "", {}, "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="],
+
+ "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "morgan/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+ }
+}
diff --git a/Mode3Test.backup/frontend/assets/CCwhiteApp.png b/Mode3Test.backup/frontend/assets/CCwhiteApp.png
new file mode 100644
index 0000000..e4ef4f1
Binary files /dev/null and b/Mode3Test.backup/frontend/assets/CCwhiteApp.png differ
diff --git a/Mode3Test.backup/frontend/assets/DailyCheck.png b/Mode3Test.backup/frontend/assets/DailyCheck.png
new file mode 100644
index 0000000..200eba4
Binary files /dev/null and b/Mode3Test.backup/frontend/assets/DailyCheck.png differ
diff --git a/Mode3Test.backup/frontend/assets/PalmIsland.png b/Mode3Test.backup/frontend/assets/PalmIsland.png
new file mode 100644
index 0000000..e31ab51
Binary files /dev/null and b/Mode3Test.backup/frontend/assets/PalmIsland.png differ
diff --git a/Mode3Test.backup/frontend/assets/lightbulb.jpg b/Mode3Test.backup/frontend/assets/lightbulb.jpg
new file mode 100644
index 0000000..f75425e
Binary files /dev/null and b/Mode3Test.backup/frontend/assets/lightbulb.jpg differ
diff --git a/Mode3Test.backup/frontend/auth.js b/Mode3Test.backup/frontend/auth.js
new file mode 100644
index 0000000..323c570
--- /dev/null
+++ b/Mode3Test.backup/frontend/auth.js
@@ -0,0 +1,39 @@
+// PocketBase auth bootstrap shared by pages
+(function (global) {
+ const pb = new PocketBase('https://pocketbase.ccllc.pro');
+
+ function authHeaders() {
+ if (pb.authStore.isValid && pb.authStore.token) {
+ return { Authorization: `Bearer ${pb.authStore.token}` };
+ }
+ return {};
+ }
+
+ function getDisplayName() {
+ const model = pb.authStore.model || {};
+ return (
+ model.display_name ||
+ model.name ||
+ model.email ||
+ model.username ||
+ 'Unknown'
+ );
+ }
+
+ function getEmail() {
+ const model = pb.authStore.model || {};
+ // Prefer email, but fall back to username if email missing
+ return model.email || model.username || null;
+ }
+
+ async function ensureAuth() {
+ if (pb.authStore.isValid) return true;
+ const path = new URL(window.location.href).pathname;
+ if (!path.endsWith('signin.html')) {
+ window.location.href = 'signin.html';
+ }
+ return false;
+ }
+
+ global.Auth = { pb, authHeaders, ensureAuth, getDisplayName, getEmail };
+})(window);
diff --git a/Mode3Test.backup/frontend/index.html b/Mode3Test.backup/frontend/index.html
new file mode 100644
index 0000000..0d0333b
--- /dev/null
+++ b/Mode3Test.backup/frontend/index.html
@@ -0,0 +1,3039 @@
+
+
+
+
+
+Job Info — Vanilla JS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Job Info
+
+
+
+
+
+
Show Filters
+
+
+
+
+
+
+
+ Sign out
+
+ v1.0.0-beta2
+
+
+
+
+
+
+
+
+
+
INFO
+
+
+
No Folder Available
+
+
+
+
+
+
NOTES
+
+
+
+
+ B
+ I
+ U
+ A
+ A
+ A
+ Reset
+
+
+
+
+
+ Submit
+ Clear
+ Close
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Back
+
+
INFO
+
NOTES
+
MANAGER INFO
+
+
+
+
+
+
+
+
+
+
+
+
+ −
+ 45%
+ +
+ 45%
+
+
+ ◀
+ ▶
+ Page 1 / 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mode3Test.backup/frontend/output.css b/Mode3Test.backup/frontend/output.css
new file mode 100644
index 0000000..971f4ad
--- /dev/null
+++ b/Mode3Test.backup/frontend/output.css
@@ -0,0 +1,5 @@
+/* Generated Tailwind CSS - Basic version */
+/* This will be updated by tailwind CLI on dev */
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/Mode3Test.backup/frontend/signin.html b/Mode3Test.backup/frontend/signin.html
new file mode 100644
index 0000000..a0c3792
--- /dev/null
+++ b/Mode3Test.backup/frontend/signin.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+ Sign In
+
+
+
+
+
+
+
Welcome
+
Sign in with your Microsoft account
+
+
Sign in with Microsoft
+
+
+
+
+
Signed in
+
Name:
+
Email:
+
+
Continue to Job Info
+
Sign out
+
+
+
+
+
+
diff --git a/Mode3Test.backup/input.css b/Mode3Test.backup/input.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/Mode3Test.backup/input.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/Mode3Test.backup/package.json b/Mode3Test.backup/package.json
new file mode 100644
index 0000000..8c75fc8
--- /dev/null
+++ b/Mode3Test.backup/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "job-info-pb",
+ "version": "1.0.0-beta3",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "dev": "bun --watch backend/server.ts",
+ "start": "bun run backend/server.ts",
+ "build:css": "tailwindcss -i input.css -o frontend/output.css --watch"
+ },
+ "devDependencies": {
+ "@types/bun": "latest",
+ "autoprefixer": "^10.4.23",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "dependencies": {
+ "dotenv": "^17.2.3",
+ "hono": "^4.10.8",
+ "pocketbase": "^0.26.5",
+ "tailwind": "^4.0.0"
+ }
+}
diff --git a/Mode3Test.backup/postcss.config.js b/Mode3Test.backup/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/Mode3Test.backup/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/Mode3Test.backup/tailwind.config.js b/Mode3Test.backup/tailwind.config.js
new file mode 100644
index 0000000..f4decb5
--- /dev/null
+++ b/Mode3Test.backup/tailwind.config.js
@@ -0,0 +1,10 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ './frontend/**/*.{html,js}',
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
diff --git a/Mode3Test/auth/README.md b/Mode3Test/auth/README.md
new file mode 100644
index 0000000..fc28b12
--- /dev/null
+++ b/Mode3Test/auth/README.md
@@ -0,0 +1,75 @@
+# Universal Auth Module
+
+## Overview
+This module provides a standardized, immutable authentication and token management system for any web project using PocketBase and Microsoft Graph. It supports user and agent tokens, delegated and app-only flows, and a consistent popup UI for login prompts.
+
+## Features
+- Pattern-based: Choose 'pb-user', 'pb-agent', 'graph-user', 'graph-agent', or any combination (e.g., 'pb-user+graph-agent') for your project needs
+- Supports both user and agent tokens for PocketBase and Microsoft Graph
+- Special handling for Valkey/Redis agent login and token storage (for backend/automation flows)
+- Single source of truth for token storage, retrieval, and refresh
+- Consistent, hidden popup for all user login prompts
+- Extracts user info (display name, email) from PocketBase
+- Works in any frontend project with PocketBase
+
+## Usage
+
+### 1. Include in your project
+```html
+
+
+```
+
+### 2. Initialize the pattern
+```js
+// Choose your pattern:
+// 'pb-user' - PocketBase user login
+// 'pb-agent' - PocketBase agent/service login
+// 'graph-user' - Microsoft Graph delegated (user) login
+// 'graph-agent' - Microsoft Graph agent/app-only (client credentials)
+// Combine as needed: 'pb-user+graph-agent', 'pb-agent+graph-user', etc.
+Auth.use('pb-user+graph-agent');
+```
+
+### 3. Get and use tokens
+```js
+const pbToken = await Auth.ensureToken('pb');
+const graphToken = await Auth.ensureToken('graph');
+const userInfo = Auth.getUserInfo();
+```
+
+### 4. Handle reauthentication
+- If a token is missing or expired, Auth will automatically show a popup for login.
+- The popup is hidden at all other times.
+
+### 5. Clear tokens (for testing or logout)
+```js
+Auth.clearToken('pb');
+Auth.clearToken('graph');
+```
+
+## Secrets and Environment
+- For frontend, all secrets are handled by PocketBase OAuth (no client secrets exposed).
+- For backend/agent flows, use environment variables and server-side code to store secrets securely.
+- The module does not expose or require secrets in the frontend.
+
+## Example Test Page
+See `auth-test.html` for a safe way to test all flows without affecting your main app.
+
+## Rules for Copilot Instructions
+- Always use Auth.use() to set the pattern before requesting tokens. Supported types: 'pb-user', 'pb-agent', 'graph-user', 'graph-agent', or any combination.
+- Always use Auth.ensureToken(type) to get a valid token; it will handle refresh and prompt if needed.
+- Never store secrets in frontend code; use PocketBase OAuth for user login.
+- All login prompts must use the provided popup, never custom dialogs.
+- Token keys are immutable: 'pbUserToken', 'pbAgentToken', 'graphUserToken', 'graphAgentToken'.
+- User info extraction must use Auth.getUserInfo().
+- For agent/app-only tokens, use backend code, environment variables, and optionally Valkey/Redis for secure storage and retrieval.
+
+## FAQ
+- **Can I use this in any project?** Yes, as long as you include PocketBase and this module.
+- **Does it work for both user and agent tokens?** Yes, with the correct pattern and backend support for agent tokens (including Valkey/Redis for automation).
+- **Is the popup customizable?** The style can be changed, but the flow must remain consistent for all projects.
+- **How are secrets handled?** Only via backend environment variables for agent tokens; never exposed in frontend.
+
+---
+For further integration, see the comments in `auth-universal.js` and the example test page.
\ No newline at end of file
diff --git a/Mode3Test/auth/auth-test.html b/Mode3Test/auth/auth-test.html
new file mode 100644
index 0000000..f2c195c
--- /dev/null
+++ b/Mode3Test/auth/auth-test.html
@@ -0,0 +1,85 @@
+
+
+
+
+ Universal Auth Test
+
+
+
+
+
+
+
Choose Auth Pattern
+
+
+ Clear All Tokens
+
+
+
+
Test Actions
+
Test PB User
+
Test PB Agent
+
Test Graph User
+
Test Graph Agent
+
Show User Info
+
+
+
+
+
diff --git a/Mode3Test/auth/auth-universal.js b/Mode3Test/auth/auth-universal.js
new file mode 100644
index 0000000..47e3c02
--- /dev/null
+++ b/Mode3Test/auth/auth-universal.js
@@ -0,0 +1,220 @@
+// Universal Auth Module: Immutable, Pattern-Based, Project-Agnostic
+// Usage: import and call Auth.use('pb-graph') or Auth.use('pb') or Auth.use('graph')
+// Provides: getToken(type), ensureToken(type), refreshToken(type), getUserInfo(), promptReauth()
+// Token types: 'pb' (PocketBase user/agent), 'graph' (Graph delegated), 'graphAgent' (Graph app-only)
+// All storage, retrieval, refresh, and UI are standardized and immutable
+
+const TOKEN_KEYS = {
+ 'pb-user': 'pbUserToken',
+ 'pb-agent': 'pbAgentToken',
+ 'graph-user': 'graphUserToken',
+ 'graph-agent': 'graphAgentToken'
+};
+
+function parsePattern(pattern) {
+ return pattern.split('+').map(s => s.trim()).filter(Boolean);
+}
+
+window.Auth = (() => {
+ let pattern = 'pb-user'; // default
+ let enabledTypes = ['pb-user'];
+ let pb = null;
+ let popup = null;
+ let agentCreds = { email: '', password: '' };
+ let superuserCreds = { email: '', password: '' };
+
+ // --- Setup ---
+ function use(type) {
+ pattern = type;
+ enabledTypes = parsePattern(type);
+ if (enabledTypes.some(t => t.startsWith('pb'))) {
+ pb = window.PocketBase ? new PocketBase('https://pocketbase.ccllc.pro') : null;
+ }
+ // Only one-time setup
+ if (!document.getElementById('authPopup')) {
+ createPopup();
+ }
+ }
+
+ // --- Token Storage ---
+ function getToken(type) {
+ return localStorage.getItem(TOKEN_KEYS[type]) || '';
+ }
+ function setToken(type, value) {
+ if (value) localStorage.setItem(TOKEN_KEYS[type], value);
+ }
+ function clearToken(type) {
+ localStorage.removeItem(TOKEN_KEYS[type]);
+ }
+
+ // --- Info Extraction ---
+ function getUserInfo() {
+ if (pb && pb.authStore.model) {
+ return {
+ displayName: pb.authStore.model.display_name || pb.authStore.model.name || pb.authStore.model.email || pb.authStore.model.username || 'Unknown',
+ email: pb.authStore.model.email || pb.authStore.model.username || null
+ };
+ }
+ return { displayName: '', email: '' };
+ }
+
+ // --- Token Ensure/Refresh ---
+ async function ensureToken(type) {
+ let token = getToken(type);
+ if (token) return token;
+ if (type === 'pb-user' && pb) {
+ if (pb.authStore.isValid) {
+ setToken('pb-user', pb.authStore.token);
+ return pb.authStore.token;
+ }
+ // Choose login method: email/password or OAuth
+ if (pattern.includes('pb-user-oauth')) {
+ return await promptReauth('pb-user-oauth');
+ } else {
+ return await promptReauth('pb-user');
+ }
+ }
+ if (type === 'pb-superuser' && pb) {
+ // Prompt for superuser credentials
+ await promptReauth('pb-superuser');
+ // Use superuser credentials to login
+ const authData = await pb.collection('_superuser').authWithPassword(superuserCreds.email, superuserCreds.password);
+ setToken('pb-superuser', pb.authStore.token);
+ return pb.authStore.token;
+ }
+ if (type === 'pb-agent' && pb) {
+ // Prompt for agent credentials if not set
+ if (!agentCreds.email || !agentCreds.password) {
+ await promptReauth('pb-agent');
+ }
+ // Use agent credentials to login
+ const authData = await pb.collection('users').authWithPassword(agentCreds.email, agentCreds.password);
+ setToken('pb-agent', pb.authStore.token);
+ return pb.authStore.token;
+ }
+ if (type === 'graph-user' && pb) {
+ // OAuth only
+ return await promptReauth('graph-user');
+ }
+ if (type === 'graph-agent') {
+ // Prompt for agent credentials if not set
+ if (!agentCreds.email || !agentCreds.password) {
+ await promptReauth('graph-agent');
+ }
+ // Use agent credentials to get token (simulate, real flow is backend)
+ setToken('graph-agent', 'AGENT_TOKEN_' + agentCreds.email);
+ return getToken('graph-agent');
+ }
+ throw new Error('Unknown token type');
+ }
+
+ async function refreshToken(type) {
+ if (type === 'graph-user' && pb) {
+ try {
+ const authData = await pb.collection('users').authRefresh();
+ const meta = authData?.meta || pb?.authStore?.model?.meta || {};
+ const token = meta.graphAccessToken || meta.graph_token || meta.graphToken || meta.accessToken || meta.access_token || meta.token || meta.rawToken || meta?.authData?.access_token || '';
+ setToken('graph-user', token);
+ return token || '';
+ } catch (err) {
+ return '';
+ }
+ }
+ // Add refresh logic for other types as needed
+ return '';
+ }
+
+ // --- Reauth Popup ---
+ function createPopup() {
+ popup = document.createElement('div');
+ popup.id = 'authPopup';
+ popup.style = 'display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.4);z-index:9999;align-items:center;justify-content:center;';
+ popup.innerHTML = `
+
+
Sign In Required
+
+
+
+ `;
+ document.body.appendChild(popup);
+ }
+
+ function showForm(type) {
+ const forms = {
+ 'pb-user': ` `,
+ 'pb-user-oauth': ``,
+ 'pb-superuser': ` `,
+ 'pb-agent': ` `,
+ 'graph-user': ``,
+ 'graph-agent': ` `
+ };
+ document.getElementById('authPopupForms').innerHTML = forms[type] || '';
+ }
+
+ async function promptReauth(type) {
+ showForm(type);
+ popup.style.display = 'flex';
+ return new Promise((resolve, reject) => {
+ document.getElementById('authPopupBtn').onclick = async () => {
+ try {
+ if (type === 'pb-user') {
+ const email = document.getElementById('pbUserEmail').value;
+ const password = document.getElementById('pbUserPassword').value;
+ const authData = await pb.collection('users').authWithPassword(email, password);
+ setToken('pb-user', pb.authStore.token);
+ popup.style.display = 'none';
+ resolve(pb.authStore.token);
+ } else if (type === 'pb-user-oauth') {
+ const authData = await pb.collection('users').authWithOAuth2({ provider: 'microsoft' });
+ setToken('pb-user', authData?.meta?.graphAccessToken || '');
+ popup.style.display = 'none';
+ resolve(authData?.meta?.graphAccessToken || '');
+ } else if (type === 'pb-superuser') {
+ superuserCreds.email = document.getElementById('pbSuperuserEmail').value;
+ superuserCreds.password = document.getElementById('pbSuperuserPassword').value;
+ popup.style.display = 'none';
+ resolve();
+ } else if (type === 'pb-agent') {
+ agentCreds.email = document.getElementById('pbAgentEmail').value;
+ agentCreds.password = document.getElementById('pbAgentPassword').value;
+ popup.style.display = 'none';
+ resolve();
+ } else if (type === 'graph-user') {
+ const authData = await pb.collection('users').authWithOAuth2({ provider: 'microsoft' });
+ setToken('graph-user', authData?.meta?.graphAccessToken || '');
+ popup.style.display = 'none';
+ resolve(authData?.meta?.graphAccessToken || '');
+ } else if (type === 'graph-agent') {
+ agentCreds.email = document.getElementById('graphAgentEmail').value;
+ agentCreds.password = document.getElementById('graphAgentPassword').value;
+ popup.style.display = 'none';
+ resolve();
+ }
+ } catch (err) {
+ document.getElementById('authPopupError').textContent = err.message || 'Authentication failed.';
+ document.getElementById('authPopupError').style.display = '';
+ }
+ };
+ });
+ }
+
+ // --- API ---
+ return {
+ use,
+ getToken,
+ setToken,
+ clearToken,
+ getUserInfo,
+ ensureToken,
+ refreshToken,
+ promptReauth
+ };
+})();
+
+window.Auth = Auth;
+
+// Example usage:
+// Auth.use('pb-graph');
+// const token = await Auth.ensureToken('graph');
+// const user = Auth.getUserInfo();
+// All login prompts are handled via the popup, which is hidden unless needed.
diff --git a/Mode3Test/backend/cache-api-keys.cjs b/Mode3Test/backend/cache-api-keys.cjs
new file mode 100644
index 0000000..640f3b5
--- /dev/null
+++ b/Mode3Test/backend/cache-api-keys.cjs
@@ -0,0 +1,37 @@
+// Express API for Redis/Valkey: keys list and single key fetch (for fast UI)
+const express = require('express');
+const Redis = require('ioredis');
+const app = express();
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+// List all keys (no values)
+app.get('/api/cache/keys', async (req, res) => {
+ try {
+ const keys = await redis.keys('*');
+ // Optionally, add summary/metadata here
+ res.json(keys.map(key => ({ key })));
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+// Fetch value for a single key
+app.get('/api/cache/:key', async (req, res) => {
+ try {
+ const key = req.params.key;
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ res.json({ key, value });
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+const port = process.env.CACHE_API_PORT || 3006;
+app.listen(port, () => {
+ console.log(`Cache API (keys+single) running on http://localhost:${port}/api/cache/keys`);
+});
diff --git a/Mode3Test/backend/cache-api.cjs b/Mode3Test/backend/cache-api.cjs
new file mode 100644
index 0000000..f1e55eb
--- /dev/null
+++ b/Mode3Test/backend/cache-api.cjs
@@ -0,0 +1,29 @@
+// Simple Express API to serve all Redis/Valkey cache keys and values as JSON (CommonJS)
+const express = require('express');
+const Redis = require('ioredis');
+const app = express();
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+app.get('/api/cache', async (req, res) => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ res.json(result);
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+const port = process.env.CACHE_API_PORT || 3006;
+app.listen(port, () => {
+ console.log(`Cache API running on http://localhost:${port}/api/cache`);
+});
diff --git a/Mode3Test/backend/cache-api.js b/Mode3Test/backend/cache-api.js
new file mode 100644
index 0000000..4a33eec
--- /dev/null
+++ b/Mode3Test/backend/cache-api.js
@@ -0,0 +1,29 @@
+// Simple Express API to serve all Redis/Valkey cache keys and values as JSON
+const express = require('express');
+const Redis = require('ioredis');
+const app = express();
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+app.get('/api/cache', async (req, res) => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ res.json(result);
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+const port = process.env.CACHE_API_PORT || 3030;
+app.listen(port, () => {
+ console.log(`Cache API running on http://localhost:${port}/api/cache`);
+});
diff --git a/Mode3Test/backend/list-redis-keys.cjs b/Mode3Test/backend/list-redis-keys.cjs
new file mode 100644
index 0000000..d8d3f89
--- /dev/null
+++ b/Mode3Test/backend/list-redis-keys.cjs
@@ -0,0 +1,25 @@
+// Script to list all Redis/Valkey keys and their values for visualization (CommonJS)
+const Redis = require('ioredis');
+
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+(async () => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ console.log(JSON.stringify(result, null, 2));
+ process.exit(0);
+ } catch (err) {
+ console.error('Error listing Redis keys:', err);
+ process.exit(1);
+ }
+})();
diff --git a/Mode3Test/backend/list-redis-keys.js b/Mode3Test/backend/list-redis-keys.js
new file mode 100644
index 0000000..d309b49
--- /dev/null
+++ b/Mode3Test/backend/list-redis-keys.js
@@ -0,0 +1,25 @@
+// Script to list all Redis/Valkey keys and their values for visualization
+const Redis = require('ioredis');
+
+const redis = new Redis({
+ host: process.env.REDIS_HOST || '127.0.0.1',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+});
+
+(async () => {
+ try {
+ const keys = await redis.keys('*');
+ const result = [];
+ for (const key of keys) {
+ let value = await redis.get(key);
+ try { value = JSON.parse(value); } catch {}
+ result.push({ key, value });
+ }
+ console.log(JSON.stringify(result, null, 2));
+ process.exit(0);
+ } catch (err) {
+ console.error('Error listing Redis keys:', err);
+ process.exit(1);
+ }
+})();
diff --git a/Mode3Test/backend/redis-cache.ts b/Mode3Test/backend/redis-cache.ts
new file mode 100644
index 0000000..f6463a2
--- /dev/null
+++ b/Mode3Test/backend/redis-cache.ts
@@ -0,0 +1,101 @@
+import Redis from 'ioredis';
+
+// Create Redis client
+const redis = new Redis({
+ host: process.env.REDIS_HOST || 'localhost',
+ port: Number(process.env.REDIS_PORT || 6379),
+ password: process.env.REDIS_PASSWORD,
+ retryStrategy(times) {
+ const delay = Math.min(times * 50, 2000);
+ return delay;
+ },
+ maxRetriesPerRequest: 3,
+ lazyConnect: true,
+});
+
+// Handle connection events
+redis.on('connect', () => {
+ console.log('✓ Redis connected');
+});
+
+redis.on('error', (err) => {
+ console.error('Redis error:', err.message);
+});
+
+redis.on('close', () => {
+ console.log('Redis connection closed');
+});
+
+// Connect to Redis
+(async () => {
+ try {
+ await redis.connect();
+ } catch (err) {
+ console.error('Failed to connect to Redis:', err);
+ }
+})();
+
+/**
+ * Get a value from cache
+ */
+export async function getCache(key: string): Promise {
+ try {
+ const value = await redis.get(key);
+ if (!value) return null;
+ return JSON.parse(value);
+ } catch (err) {
+ console.error(`Cache get error for key "${key}":`, err);
+ return null;
+ }
+}
+
+/**
+ * Set a value in cache with TTL in seconds
+ */
+export async function setCache(key: string, value: any, ttl: number = 300): Promise {
+ try {
+ const serialized = JSON.stringify(value);
+ await redis.setex(key, ttl, serialized);
+ return true;
+ } catch (err) {
+ console.error(`Cache set error for key "${key}":`, err);
+ return false;
+ }
+}
+
+/**
+ * Delete a key from cache
+ */
+export async function deleteCache(key: string): Promise {
+ try {
+ await redis.del(key);
+ return true;
+ } catch (err) {
+ console.error(`Cache delete error for key "${key}":`, err);
+ return false;
+ }
+}
+
+/**
+ * Clear all cache keys matching a pattern
+ */
+export async function clearCachePattern(pattern: string): Promise {
+ try {
+ const keys = await redis.keys(pattern);
+ if (keys.length === 0) return 0;
+ await redis.del(...keys);
+ return keys.length;
+ } catch (err) {
+ console.error(`Cache clear error for pattern "${pattern}":`, err);
+ return 0;
+ }
+}
+
+/**
+ * Check if Redis is connected
+ */
+export function isRedisConnected(): boolean {
+ return redis.status === 'ready';
+}
+
+export default redis;
diff --git a/Mode3Test/backend/server.ts b/Mode3Test/backend/server.ts
new file mode 100644
index 0000000..fb31b94
--- /dev/null
+++ b/Mode3Test/backend/server.ts
@@ -0,0 +1,513 @@
+import { Hono } from 'hono';
+import { serveStatic } from 'hono/bun';
+import fs from 'fs';
+// @ts-ignore Bun project may not have dotenv types configured
+import { config } from 'dotenv';
+import { getCache, setCache, isRedisConnected } from './redis-cache';
+
+config();
+
+const app = new Hono();
+
+// Minimal log helpers
+const logLine = (path: string, line: string) => {
+ try {
+ fs.appendFileSync(path, `${new Date().toISOString()} ${line}\n`);
+ } catch (err) {
+ console.error('Failed to write log:', err);
+ }
+};
+
+// Version endpoint sourced from package.json
+app.get('/version', (c) => {
+ try {
+ const pkgRaw = fs.readFileSync('./package.json', 'utf-8');
+ const pkg = JSON.parse(pkgRaw);
+ return c.json({ version: pkg.version || '0.0.0' });
+ } catch (err) {
+ logLine('logs/error.log', `version endpoint error: ${(err as Error)?.message || String(err)}`);
+ return c.json({ version: '0.0.0' }, 200);
+ }
+});
+
+// Jobs endpoint with Redis caching
+app.get('/api/jobs', async (c) => {
+ const page = parseInt(c.req.query('page') || '1');
+ const perPage = parseInt(c.req.query('perPage') || '50');
+ const sort = c.req.query('sort') || '-Job_Number';
+
+ const cacheKey = `jobs:page:${page}:perPage:${perPage}:sort:${sort}`;
+ const ttl = 300; // 5 minutes cache
+
+ try {
+ // Try to get from cache first
+ if (isRedisConnected()) {
+ const cached = await getCache(cacheKey);
+ if (cached) {
+ logLine('logs/server.log', `Cache HIT for ${cacheKey}`);
+ return c.json(cached);
+ }
+ logLine('logs/server.log', `Cache MISS for ${cacheKey}`);
+ }
+
+ // Fetch from PocketBase
+ const pbUrl = `https://pocketbase.ccllc.pro/api/collections/pbc_1407612689/records?page=${page}&perPage=${perPage}&sort=${sort}`;
+ const authHeader = c.req.header('Authorization') || '';
+
+ const response = await fetch(pbUrl, {
+ headers: authHeader ? { Authorization: authHeader } : {}
+ });
+
+ if (!response.ok) {
+ throw new Error(`PocketBase returned ${response.status}`);
+ }
+
+ const data = await response.json();
+
+ // Cache the result
+ if (isRedisConnected()) {
+ await setCache(cacheKey, data, ttl);
+ logLine('logs/server.log', `Cached ${cacheKey} for ${ttl}s`);
+ }
+
+ return c.json(data);
+
+ } catch (err) {
+ logLine('logs/error.log', `jobs endpoint error: ${(err as Error)?.message || String(err)}`);
+ return c.json({ error: 'Failed to fetch jobs' }, 500);
+ }
+});
+
+// Fast endpoint: returns all jobs in a single cached request
+app.get('/api/jobs-all', async (c) => {
+ const cacheKey = 'jobs:all';
+ const ttl = 1800; // 30 minutes cache
+ try {
+ // Try cache first for instant response
+ if (isRedisConnected()) {
+ const cached = await getCache(cacheKey);
+ if (cached) {
+ logLine('logs/server.log', `Cache HIT for ${cacheKey} (${cached.items?.length || 0} jobs)`);
+ // Return cached data immediately
+ setImmediate(async () => {
+ try {
+ await refreshJobsCache(cacheKey, ttl, c.req.header('Authorization') || '');
+ } catch (err) {}
+ });
+ // Return all cached jobs in a single response
+ return c.json({ ...cached, partial: false });
+ } else {
+ // No cache: return empty array instantly, trigger background fetch
+ setImmediate(async () => {
+ try {
+ const result = await fetchAllJobsFromPocketBase(c.req.header('Authorization') || '');
+ if (isRedisConnected()) {
+ await setCache(cacheKey, result, ttl);
+ logLine('logs/server.log', `Cached ${cacheKey} with ${result.items.length} jobs for ${ttl}s`);
+ }
+ } catch (err) {
+ logLine('logs/error.log', `jobs-all background fetch error: ${(err as Error)?.message || String(err)}`);
+ }
+ });
+ return c.json({ items: [], partial: true });
+ }
+ }
+ // Redis not connected: fallback to direct fetch (blocking)
+ const result = await fetchAllJobsFromPocketBase(c.req.header('Authorization') || '');
+ return c.json(result);
+ } catch (err) {
+ logLine('logs/error.log', `jobs-all endpoint error: ${(err as Error)?.message || String(err)}`);
+ return c.json({ error: 'Failed to fetch jobs' }, 500);
+ }
+});
+
+// Helper function to fetch all jobs from PocketBase
+async function fetchAllJobsFromPocketBase(authHeader: string): Promise {
+ const allItems: any[] = [];
+ let page = 1;
+ const perPage = 500;
+
+ while (true) {
+ const pbUrl = `https://pocketbase.ccllc.pro/api/collections/pbc_1407612689/records?page=${page}&perPage=${perPage}&sort=-Job_Number`;
+ const response = await fetch(pbUrl, {
+ headers: authHeader ? { Authorization: authHeader } : {}
+ });
+
+ if (!response.ok) {
+ throw new Error(`PocketBase returned ${response.status}`);
+ }
+
+ const data = await response.json();
+ const items = data.items || [];
+
+ if (items.length === 0) break;
+ allItems.push(...items);
+
+ if (allItems.length >= (data.totalItems || 0)) break;
+ page++;
+ }
+
+ return {
+ page: 1,
+ perPage: allItems.length,
+ totalItems: allItems.length,
+ totalPages: 1,
+ items: allItems
+ };
+}
+
+// Helper function to refresh jobs cache in background
+async function refreshJobsCache(cacheKey: string, ttl: number, authHeader: string): Promise {
+ try {
+ const result = await fetchAllJobsFromPocketBase(authHeader);
+ await setCache(cacheKey, result, ttl);
+ logLine('logs/server.log', `Background refresh: cached ${cacheKey} with ${result.items.length} jobs`);
+ } catch (err) {
+ logLine('logs/error.log', `Background refresh error: ${(err as Error)?.message || String(err)}`);
+ }
+}
+
+
+// --- Microsoft Graph helpers ---
+const getGraphToken = (c?: any) => {
+ const headerToken = c?.req?.header ? c.req.header('x-graph-token') : '';
+ const envToken = process.env.GRAPH_TOKEN || process.env.MS_GRAPH_TOKEN || '';
+ const token = headerToken || envToken;
+ console.log('[getGraphToken] Header token:', headerToken ? headerToken.substring(0, 20) + '...' : 'NONE');
+ console.log('[getGraphToken] Env token:', envToken ? 'SET' : 'NOT SET');
+ console.log('[getGraphToken] Using:', token ? token.substring(0, 20) + '...' : 'NONE');
+ return token;
+};
+
+const b64Url = (input: string) =>
+ Buffer.from(input).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
+
+type DriveItem = {
+ id: string;
+ name: string;
+ webUrl?: string;
+ size?: number;
+ lastModifiedDateTime?: string;
+ file?: { mimeType?: string };
+ folder?: { childCount?: number };
+ parentReference?: { path?: string; driveId?: string };
+};
+
+const fetchJson = async (url: string, token: string) => {
+ const res = await fetch(url, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ Accept: 'application/json',
+ },
+ });
+ if (!res.ok) {
+ const text = await res.text();
+ const err: any = new Error(`Graph ${res.status}: ${text}`);
+ err.status = res.status;
+ throw err;
+ }
+ return res.json();
+};
+
+const resolveShareLink = async (link: string, token: string) => {
+ // Decode the link in case it comes pre-encoded from the database
+ const decodedLink = decodeURIComponent(link);
+ console.log('[resolveShareLink] Decoded link:', decodedLink);
+
+ // Check if this is a short sharing link (/:f:/ or /:b:/) or a direct document library URL
+ if (decodedLink.includes('/:f:/') || decodedLink.includes('/:b:/')) {
+ // Short sharing link - use shares API
+ const encoded = `u!${b64Url(decodedLink)}`;
+ console.log('[resolveShareLink] Using shares API, encoded:', encoded);
+ const data = await fetchJson(`https://graph.microsoft.com/v1.0/shares/${encoded}/driveItem`, token);
+ return { driveId: data.parentReference?.driveId as string, itemId: data.id as string };
+ } else {
+ // Direct document library URL - parse it and use drive API
+ // Example: https://czflex.sharepoint.com/sites/Team/Shared Documents/Forms/AllItems.aspx?RootFolder=/sites/Team/Shared Documents/General/...
+ const url = new URL(decodedLink);
+ const pathMatch = url.hostname.match(/^([^.]+)\.sharepoint\.com$/);
+ if (!pathMatch) throw new Error('Invalid SharePoint URL');
+
+ const hostname = pathMatch[1]; // e.g., 'czflex'
+ const sitePath = url.pathname.split('/Shared')[0]; // e.g., /sites/Team
+ const rootFolderParam = url.searchParams.get('RootFolder');
+ if (!rootFolderParam) throw new Error('RootFolder parameter missing');
+
+ // Extract the folder path relative to the document library
+ // RootFolder format: /sites/Team/Shared Documents/General/Operations [Server]/...
+ // We need: General/Operations [Server]/...
+ const folderPath = rootFolderParam.split('/Shared Documents/')[1];
+ if (!folderPath) throw new Error('Could not parse folder path');
+
+ console.log('[resolveShareLink] Hostname:', hostname);
+ console.log('[resolveShareLink] Site path:', sitePath);
+ console.log('[resolveShareLink] Folder path:', folderPath);
+
+ // Get the site ID first using hostname:sitePath format
+ const siteData = await fetchJson(`https://graph.microsoft.com/v1.0/sites/${hostname}.sharepoint.com:${sitePath}`, token);
+ const siteId = siteData.id;
+
+ // Get the default document library drive
+ const driveData = await fetchJson(`https://graph.microsoft.com/v1.0/sites/${siteId}/drive`, token);
+ const driveId = driveData.id;
+
+ // Get the folder item by path
+ const itemData = await fetchJson(
+ `https://graph.microsoft.com/v1.0/drives/${driveId}/root:/${folderPath}`,
+ token
+ );
+
+ console.log('[resolveShareLink] Resolved to driveId:', driveId, 'itemId:', itemData.id);
+ return { driveId, itemId: itemData.id };
+ }
+};
+
+const listChildrenRecursive = async (
+ driveId: string,
+ itemId: string,
+ depth = 0,
+ maxDepth = 5,
+ token: string,
+): Promise => {
+ const out: DriveItem[] = [];
+ const data = await fetchJson(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/children`, token);
+ for (const child of data.value || []) {
+ out.push(child as DriveItem);
+ if (child.folder && depth < maxDepth) {
+ const nested = await listChildrenRecursive(driveId, child.id, depth + 1, maxDepth, token);
+ out.push(...nested);
+ }
+ }
+ return out;
+};
+
+const searchWithinFolder = async (driveId: string, itemId: string, query: string, token: string): Promise => {
+ const data = await fetchJson(
+ `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/search(q='${encodeURIComponent(query)}')`,
+ token,
+ );
+ return (data.value || []) as DriveItem[];
+};
+
+const filterByCategory = (items: DriveItem[], category?: string, pdfOnly: boolean = true) => {
+ // First filter: show PDF files and Word documents (which will be converted to PDF)
+ let filtered = items;
+ if (pdfOnly) {
+ filtered = items.filter((i) => {
+ if (i.folder) return false;
+ const name = i.name.toLowerCase();
+ const mimeType = i.file?.mimeType?.toLowerCase() || '';
+ // Include PDFs, Word documents, and images
+ return name.endsWith('.pdf') || mimeType.includes('pdf') ||
+ name.endsWith('.doc') || name.endsWith('.docx') || mimeType.includes('word') ||
+ name.endsWith('.jpg') || name.endsWith('.jpeg') || name.endsWith('.png') ||
+ name.endsWith('.gif') || name.endsWith('.bmp') || name.endsWith('.tiff') ||
+ name.endsWith('.webp') || mimeType.includes('image');
+ });
+ }
+
+ // Second filter: category filtering (if specified)
+ if (!category) return filtered;
+ const nameHas = (name: string, words: string[]) => words.some((w) => name.includes(w));
+ const lc = (s: string) => (s || '').toLowerCase();
+ const contractWords = ['contract', 'estimate', 'proposal', 'bid', 'award', 'agreement', 'sow'];
+ const planWords = ['plan', 'drawing', 'dwg', 'pdf', 'sheet', 'layout'];
+ return filtered.filter((i) => {
+ const n = lc(i.name);
+ if (category === 'contracts') return nameHas(n, contractWords);
+ if (category === 'plans') return nameHas(n, planWords);
+ return true;
+ });
+};
+
+// List/search job files via Graph using a shared folder link
+app.get('/api/job-files', async (c) => {
+ try {
+ console.log('[job-files] Request received');
+ const token = getGraphToken(c);
+ if (!token) {
+ console.log('[job-files] No token found');
+ return c.json({ error: 'GRAPH_TOKEN missing' }, 500);
+ }
+ console.log('[job-files] Token found:', token.substring(0, 20) + '...');
+ const link = c.req.query('link');
+ const q = c.req.query('q') || '';
+ const category = c.req.query('category') || '';
+ if (!link) return c.json({ error: 'link required' }, 400);
+ console.log('[job-files] Link:', link);
+
+ const { driveId, itemId } = await resolveShareLink(link, token);
+
+ let items: DriveItem[] = [];
+ if (q) {
+ items = await searchWithinFolder(driveId, itemId, q, token);
+ } else {
+ // Walk subfolders up to depth 5
+ items = await listChildrenRecursive(driveId, itemId, 0, 5, token);
+ }
+
+ // Filter to show only PDFs by default (can be disabled with pdfOnly=false query param)
+ const pdfOnly = c.req.query('pdfOnly') !== 'false';
+ const filtered = filterByCategory(items, category, pdfOnly);
+ console.log(`[job-files] Found ${items.length} total items, ${filtered.length} after filtering`);
+
+ const mapped = filtered.map((i) => ({
+ id: i.id,
+ name: i.name,
+ url: i.webUrl,
+ driveId: i.parentReference?.driveId || driveId,
+ size: i.size,
+ modified: i.lastModifiedDateTime,
+ contentType: i.file?.mimeType,
+ isFolder: Boolean(i.folder),
+ path: i.parentReference?.path || '',
+ }));
+
+ return c.json({ items: mapped, total: mapped.length, source: q ? 'search' : 'walk', driveId });
+ } catch (err) {
+ const message = (err as Error)?.message || String(err);
+ const status = (err as any)?.status || 500;
+ console.error('[job-files] ERROR:', message);
+ logLine('logs/error.log', `/api/job-files error: ${message}`);
+ return c.json({ error: message }, status);
+ }
+});
+
+// Stream file content via Graph to avoid CSP issues for inline preview
+app.get('/api/job-file-content', async (c) => {
+ try {
+ const token = getGraphToken(c);
+ if (!token) return c.json({ error: 'GRAPH_TOKEN missing' }, 500);
+ const driveId = c.req.query('driveId');
+ const itemId = c.req.query('itemId');
+ if (!driveId || !itemId) return c.json({ error: 'driveId and itemId required' }, 400);
+
+ const res = await fetch(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/content`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+ if (!res.ok) {
+ const text = await res.text();
+ logLine('logs/error.log', `/api/job-file-content failed: ${res.status} - ${text}`);
+ return c.json({ error: `Graph ${res.status}: ${text}` }, 502);
+ }
+ const headers: Record = {};
+ const ct = res.headers.get('content-type');
+ const cd = res.headers.get('content-disposition');
+ if (ct) headers['Content-Type'] = ct;
+ if (cd) headers['Content-Disposition'] = cd;
+ return new Response(res.body, { status: 200, headers });
+ } catch (err) {
+ const message = (err as Error)?.message || String(err);
+ const status = (err as any)?.status || 500;
+ logLine('logs/error.log', `/api/job-file-content error: ${message}`);
+ return c.json({ error: message }, status);
+ }
+});
+
+// Convert Word documents to PDF for display
+app.get('/api/job-file-pdf', async (c) => {
+ try {
+ const token = getGraphToken(c);
+ if (!token) return c.json({ error: 'GRAPH_TOKEN missing' }, 500);
+ const driveId = c.req.query('driveId');
+ const itemId = c.req.query('itemId');
+ if (!driveId || !itemId) return c.json({ error: 'driveId and itemId required' }, 400);
+
+ // Use Graph API to convert to PDF format
+ const res = await fetch(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/content?format=pdf`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+ if (!res.ok) {
+ const text = await res.text();
+ logLine('logs/error.log', `/api/job-file-pdf conversion failed: ${res.status} - ${text}`);
+ return c.json({ error: `PDF conversion failed: ${res.status}` }, 502);
+ }
+ const headers: Record = {
+ 'Content-Type': 'application/pdf',
+ };
+ const cd = res.headers.get('content-disposition');
+ if (cd) {
+ // Replace .docx/.doc extension with .pdf in filename
+ headers['Content-Disposition'] = cd.replace(/\.(docx?)/gi, '.pdf');
+ }
+ logLine('logs/server.log', `Successfully converted document to PDF: driveId=${driveId}, itemId=${itemId}`);
+ return new Response(res.body, { status: 200, headers });
+ } catch (err) {
+ const message = (err as Error)?.message || String(err);
+ const status = (err as any)?.status || 500;
+ logLine('logs/error.log', `/api/job-file-pdf error: ${message}`);
+ return c.json({ error: message }, status);
+ }
+});
+
+// Mutation logging endpoint
+app.post('/log-change', async (c) => {
+ try {
+ const body = await c.req.json();
+ const { action = 'unknown', user = 'unknown', target = '', detail = '' } = body || {};
+ const payload = JSON.stringify({ action, user, target, detail });
+ logLine('logs/changes.log', payload);
+ return c.json({ status: 'ok' });
+ } catch (err) {
+ logLine('logs/error.log', `log-change error: ${(err as Error)?.message || String(err)}`);
+ return c.text('Bad Request', 400);
+ }
+});
+
+// Serve static files from the frontend directory (must come after API routes)
+// Add cache headers for static assets
+app.use('/assets/*', async (c, next) => {
+ await next();
+ // Cache assets for 1 year
+ c.header('Cache-Control', 'public, max-age=31536000, immutable');
+});
+app.use('/*', serveStatic({ root: './frontend' }));
+
+// Error handler
+app.onError((err, c) => {
+ logLine('logs/error.log', `Unhandled error: ${err?.message || err}`);
+ return c.text('Internal Server Error', 500);
+});
+
+// Default to 3005 for test instance; can be overridden by Environment=PORT
+const PORT = Number(process.env.PORT || 3005);
+
+logLine('logs/server.log', `Starting frontend server (Redis version) on port ${PORT}`);
+
+// Warm up cache on startup
+(async () => {
+ try {
+ if (isRedisConnected()) {
+ logLine('logs/server.log', 'Warming up jobs cache...');
+ const result = await fetchAllJobsFromPocketBase('');
+ await setCache('jobs:all', result, 1800);
+ logLine('logs/server.log', `✓ Cache warmed with ${result.items.length} jobs`);
+ }
+ } catch (err) {
+ logLine('logs/error.log', `Cache warmup failed: ${(err as Error)?.message || String(err)}`);
+ }
+})();
+
+// Background refresh every 5 minutes to keep cache hot
+setInterval(async () => {
+ try {
+ if (isRedisConnected()) {
+ await refreshJobsCache('jobs:all', 1800, '');
+ }
+ } catch (err) {
+ logLine('logs/error.log', `Periodic refresh error: ${(err as Error)?.message || String(err)}`);
+ }
+}, 5 * 60 * 1000); // Every 5 minutes
+
+// Graceful shutdown logging
+const shutdown = (signal: string) => {
+ logLine('logs/server.log', `Shutting down due to ${signal}`);
+ process.exit(0);
+};
+process.on('SIGINT', () => shutdown('SIGINT'));
+process.on('SIGTERM', () => shutdown('SIGTERM'));
+
+export default {
+ port: PORT,
+ fetch: app.fetch,
+};
diff --git a/Mode3Test/bun.lock b/Mode3Test/bun.lock
new file mode 100644
index 0000000..6b92901
--- /dev/null
+++ b/Mode3Test/bun.lock
@@ -0,0 +1,600 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 0,
+ "workspaces": {
+ "": {
+ "name": "job-info",
+ "dependencies": {
+ "dotenv": "^17.2.3",
+ "hono": "^4.10.8",
+ "ioredis": "^5.9.2",
+ "pocketbase": "^0.26.5",
+ "tailwind": "^4.0.0",
+ },
+ "devDependencies": {
+ "@types/bun": "latest",
+ "autoprefixer": "^10.4.23",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18",
+ },
+ "peerDependencies": {
+ "typescript": "^5",
+ },
+ },
+ },
+ "packages": {
+ "@babel/runtime": ["@babel/runtime@7.3.4", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g=="],
+
+ "@ioredis/commands": ["@ioredis/commands@1.5.0", "", {}, "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow=="],
+
+ "@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="],
+
+ "@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
+
+ "@types/react": ["@types/react@19.2.4", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-tBFxBp9Nfyy5rsmefN+WXc1JeW/j2BpBHFdLZbEVfs9wn3E3NRFxwV0pJg8M1qQAexFpvz73hJXFofV0ZAu92A=="],
+
+ "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
+
+ "ajv": ["ajv@6.10.0", "", { "dependencies": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg=="],
+
+ "amqplib": ["amqplib@0.5.2", "", { "dependencies": { "bitsyntax": "~0.0.4", "bluebird": "^3.4.6", "buffer-more-ints": "0.0.2", "readable-stream": "1.x >=1.1.9", "safe-buffer": "^5.0.1" } }, "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA=="],
+
+ "ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
+
+ "app-root-path": ["app-root-path@2.1.0", "", {}, "sha512-z5BqVjscbjmJBybKlICogJR2jCr2q/Ixu7Pvui5D4y97i7FLsJlvEG9XOR/KJRlkxxZz7UaaS2TMwQh1dRJ2dA=="],
+
+ "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
+
+ "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="],
+
+ "array.prototype.reduce": ["array.prototype.reduce@1.0.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-array-method-boxes-properly": "^1.0.0", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "is-string": "^1.1.1" } }, "sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw=="],
+
+ "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
+
+ "asn1": ["asn1@0.2.3", "", {}, "sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w=="],
+
+ "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
+
+ "async-limiter": ["async-limiter@1.0.1", "", {}, "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="],
+
+ "async-retry": ["async-retry@1.2.3", "", { "dependencies": { "retry": "0.12.0" } }, "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q=="],
+
+ "autoprefixer": ["autoprefixer@10.4.23", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001760", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA=="],
+
+ "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
+
+ "babel-runtime": ["babel-runtime@6.26.0", "", { "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" } }, "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g=="],
+
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.9.8", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Y1fOuNDowLfgKOypdc9SPABfoWXuZHBOyCS4cD52IeZBhr4Md6CLLs6atcxVrzRmQ06E7hSlm5bHHApPKR/byA=="],
+
+ "basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="],
+
+ "bitsyntax": ["bitsyntax@0.0.4", "", { "dependencies": { "buffer-more-ints": "0.0.2" } }, "sha512-Pav3HSZXD2NLQOWfJldY3bpJLt8+HS2nUo5Z1bLLmHg2vCE/cM1qfEvNjlYo7GgYQPneNr715Bh42i01ZHZPvw=="],
+
+ "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
+
+ "body-parser": ["body-parser@1.18.3", "", { "dependencies": { "bytes": "3.0.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "~1.6.3", "iconv-lite": "0.4.23", "on-finished": "~2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", "type-is": "~1.6.16" } }, "sha512-YQyoqQG3sO8iCmf8+hyVpgHHOv0/hCEFiS4zTGUwTA1HjAFX66wRcNQrVCeJq9pgESMRvUAOvSil5MJlmccuKQ=="],
+
+ "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
+
+ "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
+
+ "buffer-more-ints": ["buffer-more-ints@0.0.2", "", {}, "sha512-PDgX2QJgUc5+Jb2xAoBFP5MxhtVUmZHR33ak+m/SDxRdCrbnX1BggRIaxiW7ImwfmO4iJeCQKN18ToSXWGjYkA=="],
+
+ "bun-types": ["bun-types@1.3.2", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg=="],
+
+ "bytes": ["bytes@3.0.0", "", {}, "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw=="],
+
+ "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
+
+ "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
+
+ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="],
+
+ "chalk": ["chalk@2.4.1", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ=="],
+
+ "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
+
+ "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
+
+ "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
+
+ "commands-events": ["commands-events@1.0.4", "", { "dependencies": { "@babel/runtime": "7.2.0", "formats": "1.0.0", "uuidv4": "2.0.0" } }, "sha512-HdP/+1Anoc7z+6L2h7nd4Imz54+LW+BjMGt30riBZrZ3ZeP/8el93wD8Jj8ltAaqVslqNgjX6qlhSBJwuDSmpg=="],
+
+ "comparejs": ["comparejs@1.0.0", "", {}, "sha512-Ue/Zd9aOucHzHXwaCe4yeHR7jypp7TKrIBZ5yls35nPNiVXlW14npmNVKM1ZaLlQTKZ6/4ewA//gYKHHIwCpOw=="],
+
+ "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="],
+
+ "compression": ["compression@1.7.3", "", { "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", "compressible": "~2.0.14", "debug": "2.6.9", "on-headers": "~1.0.1", "safe-buffer": "5.1.2", "vary": "~1.1.2" } }, "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg=="],
+
+ "content-disposition": ["content-disposition@0.5.2", "", {}, "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA=="],
+
+ "content-type": ["content-type@1.0.4", "", {}, "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="],
+
+ "cookie": ["cookie@0.3.1", "", {}, "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw=="],
+
+ "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="],
+
+ "core-js": ["core-js@2.6.12", "", {}, "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="],
+
+ "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
+
+ "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="],
+
+ "crypto2": ["crypto2@2.0.0", "", { "dependencies": { "babel-runtime": "6.26.0", "node-rsa": "0.4.2", "util.promisify": "1.0.0" } }, "sha512-jdXdAgdILldLOF53md25FiQ6ybj2kUFTiRjs7msKTUoZrzgT/M1FPX5dYGJjbbwFls+RJIiZxNTC02DE/8y0ZQ=="],
+
+ "csstype": ["csstype@3.2.0", "", {}, "sha512-si++xzRAY9iPp60roQiFta7OFbhrgvcthrhlNAGeQptSY25uJjkfUV8OArC3KLocB8JT8ohz+qgxWCmz8RhjIg=="],
+
+ "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
+
+ "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
+
+ "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
+
+ "datasette": ["datasette@1.0.1", "", { "dependencies": { "comparejs": "1.0.0", "eventemitter2": "5.0.1", "lodash": "4.17.5" } }, "sha512-aJdlCBToEJUP4M57r67r4V6tltwGKa3qetnjpBtXYIlqbX9tM9jsoDMxb4xd9AGjpp3282oHRmqI5Z8TVAU0Mg=="],
+
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
+ "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
+
+ "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
+
+ "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
+
+ "depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="],
+
+ "destroy": ["destroy@1.0.4", "", {}, "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg=="],
+
+ "dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
+
+ "draht": ["draht@1.0.1", "", { "dependencies": { "eventemitter2": "5.0.1" } }, "sha512-yNNHL864dniNmIE9ZKD++mKypiAUAvVZtyV0QrbXH/ak3ebzFqo5xsmRBRqV8pZVhImOSBiyq500Wcmrf44zAg=="],
+
+ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
+
+ "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
+
+ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="],
+
+ "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
+
+ "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="],
+
+ "es-array-method-boxes-properly": ["es-array-method-boxes-properly@1.0.0", "", {}, "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="],
+
+ "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
+
+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+ "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
+
+ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
+
+ "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
+
+ "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
+
+ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
+
+ "eventemitter2": ["eventemitter2@5.0.1", "", {}, "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg=="],
+
+ "express": ["express@4.16.4", "", { "dependencies": { "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.3", "content-disposition": "0.5.2", "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.4", "qs": "6.5.2", "range-parser": "~1.2.0", "safe-buffer": "5.1.2", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", "statuses": "~1.4.0", "type-is": "~1.6.16", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg=="],
+
+ "fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="],
+
+ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
+
+ "finalhandler": ["finalhandler@1.1.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "statuses": "~1.4.0", "unpipe": "~1.0.0" } }, "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg=="],
+
+ "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
+
+ "flaschenpost": ["flaschenpost@1.1.3", "", { "dependencies": { "@babel/runtime": "7.2.0", "app-root-path": "2.1.0", "babel-runtime": "6.26.0", "chalk": "2.4.1", "find-root": "1.1.0", "lodash": "4.17.11", "moment": "2.22.2", "processenv": "1.1.0", "split2": "3.0.0", "stack-trace": "0.0.10", "stringify-object": "3.3.0", "untildify": "3.0.3", "util.promisify": "1.0.0", "varname": "2.0.3" }, "bin": { "flaschenpost-uncork": "dist/bin/flaschenpost-uncork.js", "flaschenpost-normalize": "dist/bin/flaschenpost-normalize.js" } }, "sha512-1VAYPvDsVBGFJyUrOa/6clnJwZYC3qVq9nJLcypy6lvaaNbo1wOQiH8HQ+4Fw/k51pVG7JHzSf5epb8lmIW86g=="],
+
+ "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
+
+ "formats": ["formats@1.0.0", "", {}, "sha512-For0Y8egwEK96JgJo4NONErPhtl7H2QzeB2NYGmzeGeJ8a1JZqPgLYOtM3oJRCYhmgsdDFd6KGRYyfe37XY4Yg=="],
+
+ "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
+
+ "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
+
+ "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="],
+
+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+ "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
+
+ "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
+
+ "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
+
+ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
+
+ "get-own-enumerable-property-symbols": ["get-own-enumerable-property-symbols@3.0.2", "", {}, "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g=="],
+
+ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+
+ "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
+
+ "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
+
+ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
+
+ "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
+
+ "has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
+
+ "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
+
+ "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
+
+ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
+
+ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
+
+ "hase": ["hase@2.0.0", "", { "dependencies": { "@babel/runtime": "7.1.2", "amqplib": "0.5.2" } }, "sha512-L83pBR/oZvQQNjv4kw9aUpTqBxERPiY7B42jsmkt1VDeUaRVhYkEIKzkCqrppjtxHe2EZqzZJzuhMXsWsxYIsw=="],
+
+ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
+
+ "hono": ["hono@4.10.8", "", {}, "sha512-DDT0A0r6wzhe8zCGoYOmMeuGu3dyTAE40HHjwUsWFTEy5WxK1x2WDSsBPlEXgPbRIFY6miDualuUDbasPogIww=="],
+
+ "http-errors": ["http-errors@1.6.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" } }, "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A=="],
+
+ "iconv-lite": ["iconv-lite@0.4.23", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA=="],
+
+ "inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="],
+
+ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
+
+ "ioredis": ["ioredis@5.9.2", "", { "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ=="],
+
+ "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
+
+ "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
+
+ "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
+
+ "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
+
+ "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
+
+ "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
+
+ "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
+
+ "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
+
+ "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
+
+ "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
+
+ "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
+
+ "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
+
+ "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
+
+ "is-obj": ["is-obj@1.0.1", "", {}, "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="],
+
+ "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
+
+ "is-regexp": ["is-regexp@1.0.0", "", {}, "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA=="],
+
+ "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
+
+ "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
+
+ "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
+
+ "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
+
+ "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
+
+ "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
+
+ "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
+
+ "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
+
+ "isarray": ["isarray@0.0.1", "", {}, "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="],
+
+ "json-lines": ["json-lines@1.0.0", "", { "dependencies": { "timer2": "1.0.0" } }, "sha512-ytuLZb4RBQb3bTRsG/QBenyIo5oHLpjeCVph3s2NnoAsZE9K6h+uR+OWpEOWV1UeHdX63tYctGppBpGAc+JNMA=="],
+
+ "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
+
+ "jsonwebtoken": ["jsonwebtoken@8.5.0", "", { "dependencies": { "jws": "^3.2.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^5.6.0" } }, "sha512-IqEycp0znWHNA11TpYi77bVgyBO/pGESDh7Ajhas+u0ttkGkKYIIAjniL4Bw5+oVejVF+SYkaI7XKfwCCyeTuA=="],
+
+ "jwa": ["jwa@1.4.2", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw=="],
+
+ "jws": ["jws@3.2.3", "", { "dependencies": { "jwa": "^1.4.2", "safe-buffer": "^5.0.1" } }, "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g=="],
+
+ "limes": ["limes@2.0.0", "", { "dependencies": { "@babel/runtime": "7.3.4", "jsonwebtoken": "8.5.0" } }, "sha512-evWD0pnTgPX7QueaSoJl5JBUL30T1ZVzo34ke97tIKmeagqhBTYK/JkKL0vtG3MpNApw8ZY9TlbybfwEz9knBA=="],
+
+ "lodash": ["lodash@4.17.11", "", {}, "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="],
+
+ "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="],
+
+ "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="],
+
+ "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="],
+
+ "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="],
+
+ "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="],
+
+ "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="],
+
+ "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
+
+ "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="],
+
+ "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
+
+ "lusca": ["lusca@1.6.1", "", { "dependencies": { "tsscmp": "^1.0.5" } }, "sha512-+JzvUMH/rsE/4XfHdDOl70bip0beRcHSviYATQM0vtls59uVtdn1JMu4iD7ZShBpAmFG8EnaA+PrYG9sECMIOQ=="],
+
+ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+
+ "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="],
+
+ "merge-descriptors": ["merge-descriptors@1.0.1", "", {}, "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="],
+
+ "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="],
+
+ "mime": ["mime@1.4.1", "", { "bin": { "mime": "cli.js" } }, "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="],
+
+ "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
+
+ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
+ "moment": ["moment@2.22.2", "", {}, "sha512-LRvkBHaJGnrcWvqsElsOhHCzj8mU39wLx5pQ0pc6s153GynCTsPdGdqsVNKAQD9sKnWj11iF7TZx9fpLwdD3fw=="],
+
+ "morgan": ["morgan@1.9.1", "", { "dependencies": { "basic-auth": "~2.0.0", "debug": "2.6.9", "depd": "~1.1.2", "on-finished": "~2.3.0", "on-headers": "~1.0.1" } }, "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+ "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
+
+ "nocache": ["nocache@2.0.0", "", {}, "sha512-YdKcy2x0dDwOh+8BEuHvA+mnOKAhmMQDgKBOCUGaLpewdmsRYguYZSom3yA+/OrE61O/q+NMQANnun65xpI1Hw=="],
+
+ "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
+
+ "node-rsa": ["node-rsa@0.4.2", "", { "dependencies": { "asn1": "0.2.3" } }, "sha512-Bvso6Zi9LY4otIZefYrscsUpo2mUpiAVIEmSZV2q41sP8tHZoert3Yu6zv4f/RXJqMNZQKCtnhDugIuCma23YA=="],
+
+ "node-statsd": ["node-statsd@0.1.1", "", {}, "sha512-QDf6R8VXF56QVe1boek8an/Rb3rSNaxoFWb7Elpsv2m1+Noua1yy0F1FpKpK5VluF8oymWM4w764A4KsYL4pDg=="],
+
+ "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
+
+ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
+
+ "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
+
+ "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
+
+ "object.getownpropertydescriptors": ["object.getownpropertydescriptors@2.1.9", "", { "dependencies": { "array.prototype.reduce": "^1.0.8", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "gopd": "^1.2.0", "safe-array-concat": "^1.1.3" } }, "sha512-mt8YM6XwsTTovI+kdZdHSxoyF2DI59up034orlC9NfweclcWOt7CVascNNLp6U+bjFVCVCIh9PwS76tDM/rH8g=="],
+
+ "on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
+
+ "on-headers": ["on-headers@1.0.2", "", {}, "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="],
+
+ "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
+
+ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
+
+ "partof": ["partof@1.0.0", "", {}, "sha512-+TXdhKCySpJDynCxgAPoGVyAkiK3QPusQ63/BdU5t68QcYzyU6zkP/T7F3gkMQBVUYqdWEADKa6Kx5zg8QIKrg=="],
+
+ "path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "pocketbase": ["pocketbase@0.26.5", "", {}, "sha512-SXcq+sRvVpNxfLxPB1C+8eRatL7ZY4o3EVl/0OdE3MeR9fhPyZt0nmmxLqYmkLvXCN9qp3lXWV/0EUYb3MmMXQ=="],
+
+ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
+
+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
+ "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
+
+ "processenv": ["processenv@1.1.0", "", { "dependencies": { "babel-runtime": "6.26.0" } }, "sha512-SymqIsn8GjEUy8nG7HiyEjgbfk1xFosRIakUX1NHLpriq3vVpKniGrr9RdMWCaGYWByIovbRt2f/WvmP/IOApQ=="],
+
+ "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
+
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+
+ "qs": ["qs@6.5.2", "", {}, "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="],
+
+ "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
+
+ "raw-body": ["raw-body@2.3.3", "", { "dependencies": { "bytes": "3.0.0", "http-errors": "1.6.3", "iconv-lite": "0.4.23", "unpipe": "1.0.0" } }, "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw=="],
+
+ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
+
+ "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="],
+
+ "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="],
+
+ "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
+
+ "regenerator-runtime": ["regenerator-runtime@0.12.1", "", {}, "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="],
+
+ "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
+
+ "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
+
+ "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
+
+ "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
+
+ "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
+
+ "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
+
+ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
+
+ "semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
+
+ "send": ["send@0.16.2", "", { "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", "on-finished": "~2.3.0", "range-parser": "~1.2.0", "statuses": "~1.4.0" } }, "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw=="],
+
+ "serve-static": ["serve-static@1.13.2", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.2", "send": "0.16.2" } }, "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw=="],
+
+ "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
+
+ "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
+
+ "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
+
+ "setprototypeof": ["setprototypeof@1.1.0", "", {}, "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="],
+
+ "sha-1": ["sha-1@0.1.1", "", {}, "sha512-dexizf3hB7d4Jq6Cd0d/NYQiqgEqIfZIpuMfwPfvSb6h06DZKmHyUe55jYwpHC12R42wpqXO6ouhiBpRzIcD/g=="],
+
+ "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
+
+ "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
+
+ "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
+
+ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "split2": ["split2@3.0.0", "", { "dependencies": { "readable-stream": "^3.0.0" } }, "sha512-Cp7G+nUfKJyHCrAI8kze3Q00PFGEG1pMgrAlTFlDbn+GW24evSZHJuMl+iUJx1w/NTRDeBiTgvwnf6YOt94FMw=="],
+
+ "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="],
+
+ "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
+
+ "statuses": ["statuses@1.4.0", "", {}, "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="],
+
+ "stethoskop": ["stethoskop@1.0.0", "", { "dependencies": { "node-statsd": "0.1.1" } }, "sha512-4JnZ+UmTs9SFfDjSHFlD/EoXcb1bfwntkt4h1ipNGrpxtRzmHTxOmdquCJvIrVu608Um7a09cGX0ZSOSllWJNQ=="],
+
+ "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
+
+ "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
+
+ "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
+
+ "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
+
+ "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
+
+ "stringify-object": ["stringify-object@3.3.0", "", { "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" } }, "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw=="],
+
+ "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
+
+ "tailwind": ["tailwind@4.0.0", "", { "dependencies": { "@babel/runtime": "7.3.4", "ajv": "6.10.0", "app-root-path": "2.1.0", "async-retry": "1.2.3", "body-parser": "1.18.3", "commands-events": "1.0.4", "compression": "1.7.3", "content-type": "1.0.4", "cors": "2.8.5", "crypto2": "2.0.0", "datasette": "1.0.1", "draht": "1.0.1", "express": "4.16.4 ", "flaschenpost": "1.1.3", "hase": "2.0.0", "json-lines": "1.0.0", "limes": "2.0.0", "lodash": "4.17.11", "lusca": "1.6.1", "morgan": "1.9.1", "nocache": "2.0.0", "partof": "1.0.0", "processenv": "1.1.0", "stethoskop": "1.0.0", "timer2": "1.0.0", "uuidv4": "3.0.1", "ws": "6.2.0" } }, "sha512-LlUNoD/5maFG1h5kQ6/hXfFPdcnYw+1Z7z+kUD/W/E71CUMwcnrskxiBM8c3G8wmPsD1VvCuqGYMHviI8+yrmg=="],
+
+ "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
+
+ "timer2": ["timer2@1.0.0", "", {}, "sha512-UOZql+P2ET0da+B7V3/RImN3IhC5ghb+9cpecfUhmYGIm0z73dDr3A781nBLnFYmRzeT1AmoT4w9Lgr8n7n7xg=="],
+
+ "tsscmp": ["tsscmp@1.0.6", "", {}, "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="],
+
+ "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="],
+
+ "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
+
+ "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
+
+ "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
+
+ "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
+
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+
+ "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
+
+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
+
+ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
+
+ "untildify": ["untildify@3.0.3", "", {}, "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+
+ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
+
+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
+
+ "util.promisify": ["util.promisify@1.0.0", "", { "dependencies": { "define-properties": "^1.1.2", "object.getownpropertydescriptors": "^2.0.3" } }, "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA=="],
+
+ "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
+
+ "uuid": ["uuid@3.3.2", "", { "bin": { "uuid": "./bin/uuid" } }, "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="],
+
+ "uuidv4": ["uuidv4@3.0.1", "", { "dependencies": { "uuid": "3.3.2" } }, "sha512-PPzksdWRl2a5C9hrs3OOYrArTeyoR0ftJ3jtOy+BnVHkT2UlrrzPNt9nTdiGuxmQItHM/AcTXahwZZC57Njojg=="],
+
+ "varname": ["varname@2.0.3", "", {}, "sha512-+DofT9mJAUALhnr9ipZ5Z2icwaEZ7DAajOZT4ffXy3MQqnXtG3b7atItLQEJCkfcJTOf9WcsywneOEibD4eqJg=="],
+
+ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
+
+ "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
+
+ "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
+
+ "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
+
+ "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="],
+
+ "ws": ["ws@6.2.0", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w=="],
+
+ "amqplib/readable-stream": ["readable-stream@1.1.14", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ=="],
+
+ "babel-runtime/regenerator-runtime": ["regenerator-runtime@0.11.1", "", {}, "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="],
+
+ "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "commands-events/@babel/runtime": ["@babel/runtime@7.2.0", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg=="],
+
+ "commands-events/uuidv4": ["uuidv4@2.0.0", "", { "dependencies": { "sha-1": "0.1.1", "uuid": "3.3.2" } }, "sha512-sAUlwUVepcVk6bwnaW/oi6LCwMdueako5QQzRr90ioAVVcms6p1mV0PaSxK8gyAC4CRvKddsk217uUpZUbKd2Q=="],
+
+ "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "datasette/lodash": ["lodash@4.17.5", "", {}, "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="],
+
+ "ecdsa-sig-formatter/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+ "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "flaschenpost/@babel/runtime": ["@babel/runtime@7.2.0", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg=="],
+
+ "hase/@babel/runtime": ["@babel/runtime@7.1.2", "", { "dependencies": { "regenerator-runtime": "^0.12.0" } }, "sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg=="],
+
+ "mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+ "morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "safe-array-concat/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "send/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+ "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "amqplib/readable-stream/string_decoder": ["string_decoder@0.10.31", "", {}, "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="],
+
+ "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "morgan/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+ }
+}
diff --git a/Mode3Test/frontend/assets/CCwhiteApp.png b/Mode3Test/frontend/assets/CCwhiteApp.png
new file mode 100644
index 0000000..e4ef4f1
Binary files /dev/null and b/Mode3Test/frontend/assets/CCwhiteApp.png differ
diff --git a/Mode3Test/frontend/assets/DailyCheck.png b/Mode3Test/frontend/assets/DailyCheck.png
new file mode 100644
index 0000000..200eba4
Binary files /dev/null and b/Mode3Test/frontend/assets/DailyCheck.png differ
diff --git a/Mode3Test/frontend/assets/PalmIsland.png b/Mode3Test/frontend/assets/PalmIsland.png
new file mode 100644
index 0000000..e31ab51
Binary files /dev/null and b/Mode3Test/frontend/assets/PalmIsland.png differ
diff --git a/Mode3Test/frontend/assets/lightbulb.jpg b/Mode3Test/frontend/assets/lightbulb.jpg
new file mode 100644
index 0000000..f75425e
Binary files /dev/null and b/Mode3Test/frontend/assets/lightbulb.jpg differ
diff --git a/Mode3Test/frontend/auth.js b/Mode3Test/frontend/auth.js
new file mode 100644
index 0000000..323c570
--- /dev/null
+++ b/Mode3Test/frontend/auth.js
@@ -0,0 +1,39 @@
+// PocketBase auth bootstrap shared by pages
+(function (global) {
+ const pb = new PocketBase('https://pocketbase.ccllc.pro');
+
+ function authHeaders() {
+ if (pb.authStore.isValid && pb.authStore.token) {
+ return { Authorization: `Bearer ${pb.authStore.token}` };
+ }
+ return {};
+ }
+
+ function getDisplayName() {
+ const model = pb.authStore.model || {};
+ return (
+ model.display_name ||
+ model.name ||
+ model.email ||
+ model.username ||
+ 'Unknown'
+ );
+ }
+
+ function getEmail() {
+ const model = pb.authStore.model || {};
+ // Prefer email, but fall back to username if email missing
+ return model.email || model.username || null;
+ }
+
+ async function ensureAuth() {
+ if (pb.authStore.isValid) return true;
+ const path = new URL(window.location.href).pathname;
+ if (!path.endsWith('signin.html')) {
+ window.location.href = 'signin.html';
+ }
+ return false;
+ }
+
+ global.Auth = { pb, authHeaders, ensureAuth, getDisplayName, getEmail };
+})(window);
diff --git a/Mode3Test/frontend/index.html b/Mode3Test/frontend/index.html
new file mode 100644
index 0000000..29d4509
--- /dev/null
+++ b/Mode3Test/frontend/index.html
@@ -0,0 +1,3020 @@
+
+
+
+
+
+Job Info — Vanilla JS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Job Info
+
+
+
+
+
+
Show Filters
+
+
+
+
+
+
+
+ Sign out
+
+ v1.0.0-beta2
+
+
+
+
+
+
+
+
+
+
INFO
+
+
+
No Folder Available
+
+
+
+
+
+
NOTES
+
+
+
+
+ B
+ I
+ U
+ A
+ A
+ A
+ Reset
+
+
+
+
+
+ Submit
+ Clear
+ Close
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Back
+
+
INFO
+
NOTES
+
MANAGER INFO
+
+
+
+
+
+
+
+
+
+
+
+
+ −
+ 45%
+ +
+ 45%
+
+
+ ◀
+ ▶
+ Page 1 / 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mode3Test/frontend/output.css b/Mode3Test/frontend/output.css
new file mode 100644
index 0000000..971f4ad
--- /dev/null
+++ b/Mode3Test/frontend/output.css
@@ -0,0 +1,5 @@
+/* Generated Tailwind CSS - Basic version */
+/* This will be updated by tailwind CLI on dev */
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/Mode3Test/frontend/signin.html b/Mode3Test/frontend/signin.html
new file mode 100644
index 0000000..a0c3792
--- /dev/null
+++ b/Mode3Test/frontend/signin.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+ Sign In
+
+
+
+
+
+
+
Welcome
+
Sign in with your Microsoft account
+
+
Sign in with Microsoft
+
+
+
+
+
Signed in
+
Name:
+
Email:
+
+
Continue to Job Info
+
Sign out
+
+
+
+
+
+
diff --git a/Mode3Test/input.css b/Mode3Test/input.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/Mode3Test/input.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/Mode3Test/package.json b/Mode3Test/package.json
new file mode 100644
index 0000000..7558cd4
--- /dev/null
+++ b/Mode3Test/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "job-info-pb",
+ "version": "1.0.0-beta3",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "dev": "bun --watch backend/server.ts",
+ "start": "bun run backend/server.ts",
+ "build:css": "tailwindcss -i input.css -o frontend/output.css --watch"
+ },
+ "devDependencies": {
+ "@types/bun": "latest",
+ "autoprefixer": "^10.4.23",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "dependencies": {
+ "dotenv": "^17.2.3",
+ "hono": "^4.10.8",
+ "ioredis": "^5.9.2",
+ "pocketbase": "^0.26.5",
+ "tailwind": "^4.0.0"
+ }
+}
diff --git a/Mode3Test/postcss.config.js b/Mode3Test/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/Mode3Test/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/Mode3Test/tailwind.config.js b/Mode3Test/tailwind.config.js
new file mode 100644
index 0000000..f4decb5
--- /dev/null
+++ b/Mode3Test/tailwind.config.js
@@ -0,0 +1,10 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ './frontend/**/*.{html,js}',
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
diff --git a/ModeSwitch/activeMode.txt b/ModeSwitch/activeMode.txt
index 78fb1c6..1b66339 100644
--- a/ModeSwitch/activeMode.txt
+++ b/ModeSwitch/activeMode.txt
@@ -1 +1 @@
-Mode2Test
\ No newline at end of file
+Mode3Test
\ No newline at end of file
diff --git a/ModeSwitch/backend/orchestrator.ts b/ModeSwitch/backend/orchestrator.ts
index 9e6ba97..2cf4229 100644
--- a/ModeSwitch/backend/orchestrator.ts
+++ b/ModeSwitch/backend/orchestrator.ts
@@ -13,6 +13,7 @@ const ORCHESTRATOR_PORT = 3006;
const MODE_FOLDERS: Record = {
'Mode1Test': 'Mode1Test',
'Mode2Test': 'Mode2Test',
+ 'Mode3Test': 'Mode3Test',
};
let currentMode: string = 'Mode1Test';
@@ -82,7 +83,7 @@ async function startMode(mode: string): Promise {
// Determine server path based on mode
// Mode2Test uses AuthAndToken/backend/server.ts
- // Mode1Test uses backend/server.ts
+ // Mode1Test and Mode3Test use backend/server.ts
let serverPath = 'backend/server.ts';
if (mode === 'Mode2Test') {
serverPath = 'AuthAndToken/backend/server.ts';
@@ -94,10 +95,6 @@ async function startMode(mode: string): Promise {
cwd: modePath,
stdout: 'pipe',
stderr: 'pipe',
- env: {
- ...process.env,
- PORT: String(SHARED_PORT),
- },
});
currentMode = mode;
@@ -126,37 +123,6 @@ async function startMode(mode: string): Promise {
// Initialize app
const app = new Hono();
-// Health check
-app.get('/health', (c) => {
- return c.json({ status: 'ok', orchestratorPort: ORCHESTRATOR_PORT, sharedPort: SHARED_PORT });
-});
-
-// Get current mode
-app.get('/api/mode', (c) => {
- return c.json({ currentMode, availableModes: ['Mode1Test', 'Mode2Test'] });
-});
-
-// Switch mode (with graceful restart)
-app.post('/api/mode/switch/:mode', async (c) => {
- const newMode = c.req.param('mode');
- const validModes = ['Mode1Test', 'Mode2Test'];
-
- if (!validModes.includes(newMode)) {
- return c.json({ error: 'Invalid mode', availableModes: validModes }, 400);
- }
-
- if (newMode === currentMode) {
- return c.json({ message: 'Already in this mode', currentMode });
- }
-
- const success = await startMode(newMode);
- if (success) {
- return c.json({ message: 'Mode switched successfully', currentMode: newMode });
- } else {
- return c.json({ error: 'Failed to switch mode' }, 500);
- }
-});
-
// Startup message
console.log(`
================================================================================
diff --git a/ModeSwitch/orchestrator.log b/ModeSwitch/orchestrator.log
index cd2807d..2bfe896 100644
--- a/ModeSwitch/orchestrator.log
+++ b/ModeSwitch/orchestrator.log
@@ -8,4469 +8,13 @@ Shared mode port: 3005
Config file: /home/admin/Job-Info-Test/ModeSwitch/activeMode.txt
================================================================================
-[ModeSwitch] Starting Mode2Test (Mode2Test/) on port 3005...
-✓ Mode2Test started successfully on port 3005
+[ModeSwitch] Starting Mode3Test (Mode3Test/) on port 3005...
+✓ Mode3Test started successfully on port 3005
Started development server: http://localhost:3006
-[Mode2Test] [AuthAndToken] Background refresh started (every 5 minutes)
+[Mode3Test] [dotenv@17.2.3] injecting env (0) from .env -- tip: 🛠️ run anywhere with `dotenvx run -- yourcommand`
-[Mode2Test] Mode2Test (AuthAndToken) running on http://localhost:3005
+[Mode3Test] [Mode3Test] Background refresh started (every 5 minutes)
-[Mode2Test] Auth API: /api/auth/*
-SignIn page: /signin.html
-
-[Mode2Test] Started development server: http://localhost:3005
-
-[Mode2Test] [AuthAndToken] Tokens loaded from file
-[AuthAndToken] PB token valid: yes
-[AuthAndToken] Graph token valid: yes
-
-[ModeSwitch] Starting Mode1Test (Mode1Test/) on port 3005...
-✓ Mode1Test started successfully on port 3005
-[Mode1Test] [dotenv@17.2.3] injecting env (0) from .env -- tip: ⚙️ override existing env vars with { override: true }
-
-[Mode1Test] Started development server: http://localhost:3005
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[ModeSwitch] Starting Mode2Test (Mode2Test/) on port 3005...
-✓ Mode2Test started successfully on port 3005
-[Mode2Test] [AuthAndToken] Background refresh started (every 5 minutes)
-
-[Mode2Test] Mode2Test (AuthAndToken) running on http://localhost:3005
-Auth API: /api/auth/*
-SignIn page: /signin.html
-
-[Mode2Test] Started development server: http://localhost:3005
-
-[Mode2Test] [AuthAndToken] Tokens loaded from file
-[AuthAndToken] PB token valid: yes
-[AuthAndToken] Graph token valid: yes
-
-[Mode2Test] [AuthAndToken] Refresh error: fetch() URL is invalid
-
-[Mode2Test] [AuthAndToken] Refresh error: fetch() URL is invalid
-
-[Mode2Test] [AuthAndToken] Refresh error: fetch() URL is invalid
-
-[Mode2Test] [AuthAndToken] Refresh error: fetch() URL is invalid
-
-[Mode2Test] [AuthAndToken] Refresh error: fetch() URL is invalid
-
-[Mode2Test] [AuthAndToken] Refresh error: fetch() URL is invalid
-
-[ModeSwitch] Starting Mode1Test (Mode1Test/) on port 3005...
-✓ Mode1Test started successfully on port 3005
-[Mode1Test] [dotenv@17.2.3] injecting env (0) from .env -- tip: ✅ audit secrets and track compliance: https://dotenvx.com/ops
-
-[Mode1Test] Started development server: http://localhost:3005
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] [job-files] Request received
-
-[Mode1Test] [getGraphToken] Header token: eyJ0eXAiOiJKV1QiLCJu...
-
-[Mode1Test] [getGraphToken] Env token: NOT SET
-[getGraphToken] Using: eyJ0eXAiOiJKV1QiLCJu...
-[job-files] Token found: eyJ0eXAiOiJKV1QiLCJu...
-[job-files] Link: https://czflex.sharepoint.com/sites/Team/Shared Documents/General/Operations [Server]/1 Job Pages/COMMERCIAL/4682 - Bread of Life - Petrovskiy, Toliy
-[resolveShareLink] Decoded link: https://czflex.sharepoint.com/sites/Team/Shared Documents/General/Operations [Server]/1 Job Pages/COMMERCIAL/4682 - Bread of Life - Petrovskiy, Toliy
-
-[Mode1Test] [job-files] Request received
-[getGraphToken] Header token: eyJ0eXAiOiJKV1QiLCJu...
-[getGraphToken] Env token: NOT SET
-[getGraphToken] Using: eyJ0eXAiOiJKV1QiLCJu...
-[job-files] Token found: eyJ0eXAiOiJKV1QiLCJu...
-[job-files] Link: https://czflex.sharepoint.com/sites/Team/Shared Documents/General/Operations [Server]/1 Job Pages/COMMERCIAL/4682 - Bread of Life - Petrovskiy, Toliy
-[resolveShareLink] Decoded link: https://czflex.sharepoint.com/sites/Team/Shared Documents/General/Operations [Server]/1 Job Pages/COMMERCIAL/4682 - Bread of Life - Petrovskiy, Toliy
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
-
-[Mode1Test] Redis connection closed
+[Mode3Test] Started development server: http://localhost:3005
+[Mode3Test] No tokens.json found - login required on startup