From 94e79f12ac005287598c3a771639ad7ff2cb75fe Mon Sep 17 00:00:00 2001 From: Lucas Orth Date: Mon, 24 Aug 2026 12:13:58 +0200 Subject: [PATCH] Import aus Monorepo (frischer Start) --- .env.example | 57 + .gitignore | 4 + bootstrap/README.md | 52 + bootstrap/bootstrap.mjs | 1290 ++++++++++++ bootstrap/package.json | 13 + docker-compose.yml | 108 + .../dist/index.js | 572 ++++++ .../dist/swagger-ui-bundle.js | 2 + .../dist/swagger-ui.css | 3 + .../package.json | 13 + .../dist/index.js | 37 + .../package.json | 13 + .../dist/index.js | 276 +++ .../package.json | 13 + .../dist/index.js | 205 ++ .../package.json | 13 + .../dist/index.js | 397 ++++ .../package.json | 13 + .../dist/index.js | 291 +++ .../package.json | 13 + .../dist/index.js | 720 +++++++ .../package.json | 13 + .../dist/index.js | 149 ++ .../package.json | 13 + .../dist/index.js | 105 + .../package.json | 13 + .../dist/index.js | 1739 +++++++++++++++++ .../package.json | 13 + .../dist/index.js | 83 + .../package.json | 13 + .../dist/index.js | 1107 +++++++++++ .../package.json | 13 + .../dist/index.js | 59 + .../package.json | 13 + 34 files changed, 7438 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 bootstrap/README.md create mode 100644 bootstrap/bootstrap.mjs create mode 100644 bootstrap/package.json create mode 100644 docker-compose.yml create mode 100644 extensions/directus-extension-skrift-api/dist/index.js create mode 100644 extensions/directus-extension-skrift-api/dist/swagger-ui-bundle.js create mode 100644 extensions/directus-extension-skrift-api/dist/swagger-ui.css create mode 100644 extensions/directus-extension-skrift-api/package.json create mode 100644 extensions/directus-extension-skrift-apikey/dist/index.js create mode 100644 extensions/directus-extension-skrift-apikey/package.json create mode 100644 extensions/directus-extension-skrift-auth/dist/index.js create mode 100644 extensions/directus-extension-skrift-auth/package.json create mode 100644 extensions/directus-extension-skrift-contacts/dist/index.js create mode 100644 extensions/directus-extension-skrift-contacts/package.json create mode 100644 extensions/directus-extension-skrift-kontakte/dist/index.js create mode 100644 extensions/directus-extension-skrift-kontakte/package.json create mode 100644 extensions/directus-extension-skrift-mailer/dist/index.js create mode 100644 extensions/directus-extension-skrift-mailer/package.json create mode 100644 extensions/directus-extension-skrift-neuauftrag/dist/index.js create mode 100644 extensions/directus-extension-skrift-neuauftrag/package.json create mode 100644 extensions/directus-extension-skrift-orderentries/dist/index.js create mode 100644 extensions/directus-extension-skrift-orderentries/package.json create mode 100644 extensions/directus-extension-skrift-orderfiles/dist/index.js create mode 100644 extensions/directus-extension-skrift-orderfiles/package.json create mode 100644 extensions/directus-extension-skrift-orders/dist/index.js create mode 100644 extensions/directus-extension-skrift-orders/package.json create mode 100644 extensions/directus-extension-skrift-printbutton/dist/index.js create mode 100644 extensions/directus-extension-skrift-printbutton/package.json create mode 100644 extensions/directus-extension-skrift-produktion/dist/index.js create mode 100644 extensions/directus-extension-skrift-produktion/package.json create mode 100644 extensions/directus-extension-skrift-testprint/dist/index.js create mode 100644 extensions/directus-extension-skrift-testprint/package.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1c88e7d --- /dev/null +++ b/.env.example @@ -0,0 +1,57 @@ +# Directus – kopiere zu .env und fülle die Werte aus. .env NICHT committen. + +# ── Postgres ──────────────────────────────────────────────── +DB_DATABASE=skrift +DB_USER=directus +DB_PASSWORD=CHANGE-ME-strong-db-password + +# ── Directus ──────────────────────────────────────────────── +# SECRET: langer Zufallswert, z. B. openssl rand -hex 32 +DIRECTUS_SECRET=CHANGE-ME-64-hex-random +PUBLIC_URL=https://admin.skrift.de + +# Erster Admin (nur beim ersten Start relevant) +ADMIN_EMAIL=admin@skrift.de +ADMIN_PASSWORD=CHANGE-ME-strong-admin-password + +# CORS: URL des Frontends (Portal/Konfigurator). Kommagetrennt möglich. +CORS_ORIGIN=https://app.skrift.de + +# ── E-Mail (SMTP) — für passwortlosen Login-Code + Benachrichtigungen ── +# WICHTIG: PORT und SECURE müssen zusammenpassen, sonst schlägt die Verbindung +# mit "SSL routines: wrong version number" fehl: +# Port 587 → STARTTLS → EMAIL_SMTP_SECURE=false +# Port 465 → implizites TLS → EMAIL_SMTP_SECURE=true +EMAIL_FROM=noreply@skrift.de +EMAIL_SMTP_HOST= +EMAIL_SMTP_PORT=587 +EMAIL_SMTP_USER= +EMAIL_SMTP_PASSWORD= +EMAIL_SMTP_SECURE=false + +# Nur falls der Mailserver ein selbstsigniertes Zertifikat nutzt: +# EMAIL_SMTP_TLS_REJECT_UNAUTHORIZED=false + +# ── Skrift-Backend (Vorschau + finaler Auftrag) ───────────── +# Intern über das gemeinsame npm-Netz erreichbar (container_name). +SKRIFT_BACKEND_URL=http://skrift-backend:4000 +# MUSS exakt dem API_TOKEN aus Docker/skrift-backend/.env entsprechen, +# sonst antwortet das Backend mit 401 Unauthorized. +SKRIFT_BACKEND_TOKEN=CHANGE-ME-gleich-wie-backend-API_TOKEN +# Vorschauen pro Kennung und Tag +SKRIFT_PREVIEW_LIMIT=10 +# Zieladresse für Angebots-/Musteranfragen +SKRIFT_TEAM_EMAIL=hello@skrift.de +# Shared Secret für den WordPress-Webhook (JetFormBuilder → /skrift-orders/inbound/*). +# Frei wählbarer langer Zufallswert; muss identisch als ?token=... in der +# Webhook-URL stehen. Ohne diesen Wert lehnt der Webhook alle Anfragen ab. +SKRIFT_WEBHOOK_TOKEN=CHANGE-ME-langer-zufallswert +# Signatur-Plotter-Service (intern über das npm-Netz). Default passt zum container_name. +SKRIFT_SIGN_URL=http://skrift-signature-service:8000 + +# ── PayPal (server-seitige Zahlungsprüfung) ───────────────── +# Client-ID ist öffentlich (auch im Frontend), das Secret bleibt NUR hier. +PAYPAL_CLIENT_ID= +PAYPAL_CLIENT_SECRET= +# sandbox oder live +PAYPAL_ENV=sandbox diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5cecbc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +.env.* +!.env.example diff --git a/bootstrap/README.md b/bootstrap/README.md new file mode 100644 index 0000000..91766d6 --- /dev/null +++ b/bootstrap/README.md @@ -0,0 +1,52 @@ +# Directus Bootstrap + +Legt das Skrift-Datenmodell (Collections, Beziehungen, Rollen/Rechte, Seed) idempotent in einer laufenden Directus-Instanz an. Mehrfach ausführbar – Vorhandenes wird übersprungen. + +## Voraussetzungen +- Directus läuft (siehe `../docker-compose.yml`) und ist erreichbar. +- Node ≥ 18 (kein `npm install` nötig – nutzt nur Bordmittel). +- Ein Admin-Zugang: entweder ein **statischer Admin-Token** oder Admin-E-Mail/Passwort. + +## Ausführen + +Mit Token (empfohlen – Token im Directus-Admin unter dem Admin-Nutzer erzeugen): + +```bash +DIRECTUS_URL=https://admin.skrift.de \ +DIRECTUS_TOKEN= \ +node bootstrap.mjs +``` + +Alternativ mit Login: + +```bash +DIRECTUS_URL=https://admin.skrift.de \ +ADMIN_EMAIL=admin@skrift.de \ +ADMIN_PASSWORD=... \ +node bootstrap.mjs +``` + +Nur Schema + Seed, ohne Rollen/Rechte (zum stufenweisen Testen): + +```bash +SKIP_PERMISSIONS=1 DIRECTUS_URL=... DIRECTUS_TOKEN=... node bootstrap.mjs +``` + +## Was es anlegt +- **Collections:** customers, products, formats, motifs, price_items, pricing_settings, + vouchers, voucher_redemptions, orders, order_entries, order_addons, jobs, status_history. +- **Rollen/Policies:** Staff (volle Verwaltung), Customer (nur Eigenes + Katalog lesen), + Public (aktive Kataloge lesen), Service (Backend/Produktion: lesen + Status schreiben). +- **Seed:** Produkte (inkl. Kontakt-Produkte), Formate, `price_items` mit den + Konfigurator-Preisen, `pricing_settings` inkl. Zeichen-Whitelist (1:1 aus job-manager). + +## Nach dem Lauf – manuell +- **Service-Token:** Nutzer in Rolle *Service* anlegen, statischen Token erzeugen und in + die `.env` von skrift-backend und skrift-produktion eintragen. +- **Preise prüfen:** `price_items` mit Preis `0` (Schreib-/Gestaltungsservice, Motiv-Upload) + und die Produkt-Basispreise im Admin auf die echten Werte setzen. +- **Preisformel:** `pricing_settings.formula` ist ein Platzhalter – hier die reale Formel hinterlegen. + +> Hinweis: Das Skript zielt auf Directus 11 (Policy-Rechtemodell) und wurde nicht gegen +> eine Live-Instanz getestet. Falls beim Lauf ein Schritt fehlschlägt, die Konsolenausgabe +> schicken – dann wird die betroffene Stelle gezielt korrigiert. diff --git a/bootstrap/bootstrap.mjs b/bootstrap/bootstrap.mjs new file mode 100644 index 0000000..82e4c65 --- /dev/null +++ b/bootstrap/bootstrap.mjs @@ -0,0 +1,1290 @@ +/** + * Skrift – Directus Bootstrap + * --------------------------------------------------------------------------- + * Legt Collections, Felder, Beziehungen, Rollen/Policies/Rechte und Seed-Daten + * idempotent an (mehrfach ausführbar – Vorhandenes wird übersprungen). + * + * Ausführen (Node >= 18, kein npm install nötig): + * DIRECTUS_URL=https://admin.skrift.de \ + * DIRECTUS_TOKEN= node bootstrap.mjs + * ODER mit Login statt Token: + * DIRECTUS_URL=... ADMIN_EMAIL=... ADMIN_PASSWORD=... node bootstrap.mjs + * + * Flags (optional): + * SKIP_PERMISSIONS=1 nur Schema + Seed, ohne Rollen/Rechte + * + * Zielt auf Directus 11 (Policy-basiertes Rechtemodell). Da nicht gegen eine + * Live-Instanz getestet: bei Fehlern die Konsolenausgabe schicken, dann fixe ich + * die betroffene Stelle gezielt. + */ + +const DIRECTUS_URL = (process.env.DIRECTUS_URL || '').replace(/\/$/, ''); +let token = process.env.DIRECTUS_TOKEN || ''; +const ADMIN_EMAIL = process.env.ADMIN_EMAIL || ''; +const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || ''; +const SKIP_PERMISSIONS = process.env.SKIP_PERMISSIONS === '1'; + +if (!DIRECTUS_URL) { console.error('DIRECTUS_URL fehlt.'); process.exit(1); } + +// ── Erlaubter Zeichensatz: 1:1 aus skrift-job-manager (job-app.js) ────────── +// Basis-Klasse (ohne \n\r\t – die fügt das Frontend für mehrzeilige Felder an). +const CHAR_WHITELIST = + '\\x20-\\x5F\\x61-\\x7B\\x7D' + + 'ÄÖÜäöüß' + // ÄÖÜäöüß + '¡£§«»¿' + // ¡£§«»¿ + '‐–—‘’“”€'; // ‐ – — ' ' " " € + +// ── HTTP-Helfer ───────────────────────────────────────────────────────────── +async function api(method, path, body) { + const res = await fetch(DIRECTUS_URL + path, { + method, + headers: { + 'Content-Type': 'application/json', + ...(token ? { Authorization: `Bearer ${token}` } : {}), + }, + body: body ? JSON.stringify(body) : undefined, + }); + const text = await res.text(); + let data = null; + try { data = text ? JSON.parse(text) : null; } catch { /* non-json */ } + if (!res.ok) { + const msg = data?.errors?.[0]?.message || text || res.statusText; + const err = new Error(`${method} ${path} → ${res.status}: ${msg}`); + err.status = res.status; + throw err; + } + return data?.data ?? data; +} + +/** Prüft, ob der gesetzte Token wirklich gültig ist. */ +async function tokenGueltig() { + try { + const res = await fetch(DIRECTUS_URL + '/users/me?fields=id', { + headers: { Authorization: `Bearer ${token}` }, + }); + return res.ok; + } catch { return false; } +} + +async function login() { + // Ein mitgegebener DIRECTUS_TOKEN (z. B. versehentlich aus der .env + // übernommen) wird geprüft – sonst schlägt erst der nächste Aufruf mit einem + // wenig hilfreichen 401 fehl. + if (token) { + if (await tokenGueltig()) return; + console.warn(' DIRECTUS_TOKEN ist ungültig – versuche Login mit ADMIN_EMAIL/ADMIN_PASSWORD.'); + token = ''; + } + if (!ADMIN_EMAIL || !ADMIN_PASSWORD) { + console.error('DIRECTUS_TOKEN ungültig bzw. nicht gesetzt und ADMIN_EMAIL/ADMIN_PASSWORD fehlen.'); + process.exit(1); + } + const res = await fetch(DIRECTUS_URL + '/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email: ADMIN_EMAIL, password: ADMIN_PASSWORD }), + }); + if (!res.ok) { console.error('Login fehlgeschlagen:', await res.text()); process.exit(1); } + token = (await res.json()).data.access_token; +} + +const log = (...a) => console.log(' ', ...a); + +// ── Feld-DSL ──────────────────────────────────────────────────────────────── +const ID = { + field: 'id', type: 'integer', + meta: { hidden: true, interface: 'input', readonly: true }, + schema: { is_primary_key: true, has_auto_increment: true }, +}; +const f = (field, type, extra = {}) => ({ + field, type, + meta: { interface: extra.interface, options: extra.options, note: extra.note, + required: extra.required || false, special: extra.special }, + schema: { is_nullable: extra.nullable !== false, is_unique: extra.unique || false, + default_value: extra.default }, +}); +const dropdown = (field, choices, extra = {}) => + f(field, 'string', { interface: 'select-dropdown', + options: { choices: choices.map((v) => ({ text: v, value: v })) }, ...extra }); +const m2o = (field, related, extra = {}) => + ({ field, type: related === 'directus_users' || related === 'directus_files' ? 'uuid' : 'integer', + meta: { interface: 'select-dropdown-m2o', note: extra.note, special: null }, + schema: { is_nullable: extra.nullable !== false }, __related: related, __onDelete: extra.onDelete || 'SET NULL' }); + +// Kunden sind Directus-Login-Nutzer (directus_users). Kein eigener „customers"- +// Datensatz mehr – das Profil hängt direkt am Konto (Felder siehe USER_FIELDS). + +// Unterfelder der Adressliste – ohne diese zeigt die „list"-Oberfläche ein +// leeres Formular („no visible fields"). +const ADDRESS_SUBFIELDS = [ + { field: 'label', name: 'Bezeichnung', type: 'string', meta: { interface: 'input', width: 'full', options: { placeholder: 'z. B. Rechnung, Lieferung' } } }, + { field: 'street', name: 'Straße & Hausnummer', type: 'string', meta: { interface: 'input', width: 'full' } }, + { field: 'zip', name: 'PLZ', type: 'string', meta: { interface: 'input', width: 'half' } }, + { field: 'city', name: 'Ort', type: 'string', meta: { interface: 'input', width: 'half' } }, + { field: 'country', name: 'Land', type: 'string', meta: { interface: 'input', width: 'full', options: { placeholder: 'Deutschland' } } }, +]; + +// Nur die Felder, die Skrift wirklich braucht. Alias-Felder (signatures, +// discounts) zeigen die zugehörigen o2m-Collections direkt am Kundenkonto. +const USER_FIELDS = [ + dropdown('person_type', ['privat', 'unternehmen'], { default: 'privat', note: 'Einstufung – nur Betreiber ändert sie.' }), + f('company', 'string', { interface: 'input', note: 'Firmenname (bei Unternehmen).' }), + f('phone', 'string', { interface: 'input' }), + // Genau zwei feste Adressen je Konto (ohne Namen/Bezeichnung): Rechnung + Lieferung. + // Werden automatisch an der passenden Stelle im Bestellvorgang eingesetzt. + f('billing_address', 'json', { interface: 'input-code', note: 'Rechnungsadresse {street,zip,city,country}.' }), + f('shipping_address', 'json', { interface: 'input-code', note: 'Lieferadresse {street,zip,city,country}.' }), + // Veraltet (frühere Mehrfach-Adressliste) – bleibt für Alt-Daten erhalten. + f('addresses', 'json', { interface: 'list', hidden: true, note: 'Veraltet – ersetzt durch billing_address/shipping_address.', options: { fields: ADDRESS_SUBFIELDS } }), + f('notes', 'text', { interface: 'input-multiline', note: 'Interne Notizen (für den Kunden nicht sichtbar).' }), + // Zusätzliche Login-Mailadressen: Wer sich mit einer dieser Mails per Code + // anmeldet, landet im SELBEN Konto (voller Zugriff). Liste von E-Mails. + f('alt_emails', 'json', { interface: 'tags', note: 'Weitere Login-Mailadressen (gleiches Konto).' }), + { field: 'signatures', type: 'alias', meta: { interface: 'list-o2m', special: ['o2m'], note: 'Hinterlegte Unterschriften des Kunden.' }, schema: null }, + { field: 'discounts', type: 'alias', meta: { interface: 'list-o2m', special: ['o2m'], note: 'Kundenspezifische Rabatte.' }, schema: null }, + { field: 'unlocked_products', type: 'alias', meta: { interface: 'list-o2m', special: ['o2m'], note: 'Individuell freigeschaltete Produkte.' }, schema: null }, +]; + +// directus_users-Felder, die Skrift nicht braucht – werden ausgeblendet. +const HIDE_USER_FIELDS = ['location', 'title', 'description', 'tags', 'avatar', 'language', + 'appearance', 'theme_light', 'theme_dark', 'theme_light_overrides', 'theme_dark_overrides', + 'text_direction', 'email_notifications']; + +// ── Collections ───────────────────────────────────────────────────────────── +const collections = [ + + { collection: 'products', meta: { icon: 'inventory_2', note: 'Produkte inkl. Kontakt-Produkte.' }, fields: [ + f('key', 'string', { interface: 'input', unique: true, required: true }), + f('name', 'string', { interface: 'input', required: true }), + f('description', 'text', { interface: 'input-multiline' }), + dropdown('type', ['letter', 'postcard', 'envelope', 'sample', 'contact'], { required: true }), + dropdown('visibility', ['alle', 'privat', 'unternehmen'], { default: 'alle', note: 'Für wen im Konfigurator sichtbar.' }), + dropdown('pricing_mode', ['formel', 'auf_anfrage'], { default: 'formel' }), + f('base_price', 'float', { interface: 'input', note: 'Basispreis (netto). Leer bei auf_anfrage.' }), + // Ab dieser Menge gilt der Normalpreis (Multiplikator 1) – je Produkt. + // Leer = Rückfall auf die globale Norm-Menge in den Preis-Einstellungen. + f('norm_qty', 'float', { interface: 'input', note: 'Menge, ab der der Normalpreis gilt (Multiplikator 1). Leer = globaler Wert.' }), + // Kleinmengen-Aufschlag je Produkt (fließt als a/e in die Multiplikator-Formel): + // a = Deckel (bei Menge→0 ist der Multiplikator 1 + a), e = Abklingform + // (großes e = Aufschlag fällt schnell; kleines e = bleibt über mittlere Mengen hoch). + // Leer → a = 1, e = 3 (bisheriges Verhalten). Postkarten z. B. a = 1.5, e = 2. + f('price_factor_a', 'float', { interface: 'input', default: 1, note: 'Kleinmengen-Aufschlag: Deckel a (Multiplikator bei Menge→0 = 1 + a). Leer = 1.' }), + f('price_factor_e', 'float', { interface: 'input', default: 3, note: 'Kleinmengen-Aufschlag: Exponent e (größer = fällt schneller ab). Leer = 3.' }), + // Eingabeart im Konfigurator: freier Text oder Datei-Upload (z. B. ein zu + // unterschreibendes PDF beim Unterschriftenservice). + dropdown('input_mode', ['text', 'datei'], { default: 'text', note: 'Text-Eingabe oder Datei-Upload.' }), + f('active', 'boolean', { interface: 'boolean', default: true }), + f('sort', 'integer', { interface: 'input' }), + ] }, + + { collection: 'formats', meta: { icon: 'aspect_ratio', note: 'Formate je Produkt (admin-erweiterbar).' }, fields: [ + m2o('product', 'products', { onDelete: 'CASCADE' }), + f('key', 'string', { interface: 'input', required: true }), + f('name', 'string', { interface: 'input', required: true }), + f('active', 'boolean', { interface: 'boolean', default: true }), + ] }, + + { collection: 'motifs', meta: { icon: 'image', note: 'Motiv-Katalog für Postkarten.' }, fields: [ + f('name', 'string', { interface: 'input', required: true }), + m2o('image', 'directus_files'), + dropdown('orientation', ['quer', 'hochkant'], { default: 'quer', note: 'Passend zum Postkartenformat.' }), + f('active', 'boolean', { interface: 'boolean', default: true }), + f('sort', 'integer', { interface: 'input' }), + ] }, + + { collection: 'price_items', meta: { icon: 'sell', note: 'Alle Options-/Zusatzpreise – hier editierbar.' }, fields: [ + f('key', 'string', { interface: 'input', unique: true, required: true }), + f('label', 'string', { interface: 'input', required: true }), + dropdown('category', ['versand', 'kuvert', 'beschriftung', 'zusatzleistung', 'zuschlag'], { required: true }), + f('price', 'float', { interface: 'input', required: true }), + dropdown('unit', ['einmalig', 'pro_stueck', 'prozent'], { default: 'einmalig' }), + f('active', 'boolean', { interface: 'boolean', default: true }), + ] }, + + { collection: 'pricing_settings', meta: { icon: 'calculate', singleton: true, note: 'Formel + globale Werte.' }, fields: [ + f('formula', 'text', { interface: 'input-multiline', note: 'Grundpreis-Formel. Variablen: base_price, menge.' }), + // Mengen-Multiplikator (Kleinmengen-Aufschlag), je Segment editierbar. + // Variablen: qty, norm_b, norm_c, mind_b, mind_c, base_price. Funktionen: + // sqrt/abs/min/max/round. Vergleiche + Ternär (cond ? a : b) erlaubt. + // Beispiel: (qty >= norm_b) ? 1 : (2 - sqrt(qty / norm_b)) + // Eine gemeinsame Formel für Privat und Unternehmen. `norm` ist die + // Normalpreis-Menge des jeweiligen Produkts (products.norm_qty). + f('multiplier_formula', 'text', { interface: 'input-multiline', note: 'Mengen-Multiplikator (gilt für Privat und Unternehmen). Variablen: qty, norm, base_price, a, e (a/e je Produkt). Funktionen: sqrt, pow, min, max, round …' }), + f('mwst_percent', 'float', { interface: 'input', default: 19 }), + // Mengenrabatt-Staffel: ab min_qty Stück gilt percent % Rabatt auf den + // Grundpreis. Es greift die höchste passende Stufe. Frei in Directus pflegbar. + { field: 'quantity_discounts', type: 'json', + meta: { interface: 'list', note: 'Mengenrabatt-Staffel (ab X Stück Y %). Höchste passende Stufe greift.', + options: { fields: [ + { field: 'min_qty', name: 'ab Menge', type: 'integer', meta: { interface: 'input', width: 'half' } }, + { field: 'percent', name: 'Rabatt %', type: 'float', meta: { interface: 'input', width: 'half' } }, + ] } }, + schema: {} }, + f('paypal_limit_net', 'float', { interface: 'input', default: 200, note: 'Ab diesem Netto-Wert nur Rechnung.' }), + f('char_whitelist', 'text', { interface: 'input-multiline', note: 'Erlaubte Zeichen (Regex-Klasse, 1:1 aus job-manager).' }), + f('currency', 'string', { interface: 'input', default: 'EUR' }), + // PayPal: NUR die Client-ID (öffentlich). Das Secret gehört nicht hierher – + // diese Collection ist für Gäste lesbar, und clientseitig wird es nicht gebraucht. + f('paypal_enabled', 'boolean', { interface: 'boolean', default: false }), + dropdown('paypal_mode', ['sandbox', 'live'], { default: 'sandbox' }), + f('paypal_client_id_sandbox', 'string', { interface: 'input', note: 'Öffentliche Client-ID (Sandbox).' }), + f('paypal_client_id_live', 'string', { interface: 'input', note: 'Öffentliche Client-ID (Live).' }), + ] }, + + { collection: 'vouchers', meta: { icon: 'confirmation_number', note: 'Gutscheine.' }, fields: [ + f('code', 'string', { interface: 'input', unique: true, required: true }), + dropdown('type', ['prozent', 'fest'], { required: true }), + f('value', 'float', { interface: 'input', required: true }), + f('active', 'boolean', { interface: 'boolean', default: true }), + f('valid_until', 'timestamp', { interface: 'datetime' }), + f('max_uses', 'integer', { interface: 'input' }), + f('used_count', 'integer', { interface: 'input', default: 0 }), + ] }, + + { collection: 'orders', meta: { icon: 'receipt_long', note: 'Auftrag.' }, fields: [ + f('order_number', 'string', { interface: 'input', unique: true, required: true }), + m2o('customer', 'directus_users', { note: 'Kunde = Login-Konto (Zuordnung per E-Mail).' }), + f('customer_email', 'string', { interface: 'input', required: true, note: 'Zuordnungsschlüssel.' }), + m2o('product', 'products'), + m2o('format', 'formats'), + dropdown('person_type', ['privat', 'unternehmen'], { default: 'privat' }), + dropdown('font', ['tilda', 'alva', 'ellie']), + f('realistic', 'boolean', { interface: 'boolean', default: true, note: 'Natürliche Handschrift-Variation (Jitter/Neigung).' }), + m2o('api_client', 'api_clients', { onDelete: 'SET NULL', note: 'Gesetzt bei Aufträgen über die Public-API.' }), + dropdown('shipping_day', ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'], { note: 'Vom Kunden gewünschter Versandtag (optional, v. a. Public-API).' }), + f('font_scale_letter', 'float', { interface: 'input', default: 1, note: 'Relative Schriftgröße Brief (0.8–1.5, 1 = Standard).' }), + f('font_scale_envelope', 'float', { interface: 'input', default: 1, note: 'Relative Schriftgröße Kuvert (0.8–1.5, 1 = Standard).' }), + f('signatures_manual', 'json', { interface: 'input-code', note: 'Signatur(en) auf dem Brief bei manuellen Aufträgen: { signatures:{signatur1:svg}, offsets:{signatur1:{x,y,scale}} }.' }), + f('multi_page', 'boolean', { interface: 'boolean', default: false, note: 'Mehrseitiges Schriftstück (Auto-Fluss über mehrere A4-Seiten).' }), + f('page_count', 'integer', { interface: 'input', note: 'Seiten je Schriftstück (bei mehrseitig; wird bei der Generierung gesetzt).' }), + // Kontakt-/Akquise-Steuerung (siehe Collection „contacts"). + f('keep_contacts', 'boolean', { interface: 'boolean', default: false, note: 'In Kontakte speichern: legt die Empfänger dieses Auftrags als Kontakte/Leads an (nur auf ausdrückliche Anforderung). Schützt zugleich die Empfängerdaten vor dem DSGVO-Strip.' }), + f('contacts_created', 'boolean', { interface: 'boolean', default: false, hidden: true, note: 'Guard: Kontakte für diesen Auftrag wurden bereits angelegt.' }), + f('entries_stripped', 'boolean', { interface: 'boolean', default: false, hidden: true, note: 'Guard: Empfängerdaten wurden nach Ablauf der Aufbewahrung anonymisiert.' }), + dropdown('source', ['configurator', 'portal', 'operator', 'extern', 'api'], { default: 'configurator', note: '„extern" = andere Plattform (z. B. Etsy); „api" = Public-API-Zugang.' }), + dropdown('status', ['entwurf', 'vorbereitet', 'wartet_auf_zahlung', 'bezahlt', 'material_erwartet', + 'material_eingegangen', 'in_queue', 'in_produktion', 'gedruckt', 'versendet', 'abgeschlossen', 'storniert'], + { default: 'entwurf' }), + // Produktionsstatus (fürs Kanban) – getrennt vom kaufmännischen Status. + dropdown('production_status', ['eingegangen', 'im_druck', 'kuvertieren', 'versandfertig', 'versendet', 'storniert'], + { default: 'eingegangen', note: 'Produktions-/Kanban-Status.' }), + f('brief_gedruckt', 'boolean', { interface: 'boolean', default: false, note: 'Schriftstücke gedruckt (vom Agent gesetzt).' }), + f('kuvert_gedruckt', 'boolean', { interface: 'boolean', default: false, note: 'Umschläge gedruckt (vom Agent gesetzt).' }), + // Zeitpunkt des Versands – Basis fürs Auto-Archiv (nach 14 Tagen). + { field: 'versandt_am', type: 'timestamp', meta: { interface: 'datetime', note: 'Wird beim Wechsel auf „versendet" gesetzt.' }, schema: { is_nullable: true } }, + { field: 'production_status_changed_at', type: 'timestamp', meta: { interface: 'datetime', note: 'Zeitpunkt der letzten Produktionsstatus-Änderung (für „status_since" der Public-API).' }, schema: { is_nullable: true } }, + dropdown('shipping_type', ['einzeln', 'sammel'], { default: 'sammel' }), + f('needs_envelope', 'boolean', { interface: 'boolean', default: false }), + dropdown('envelope_labeling', ['empfaenger', 'freitext', 'keine']), + f('envelope_text', 'text', { interface: 'input-multiline', note: 'Individueller Kuverttext (bei envelope_labeling = freitext).' }), + dropdown('envelope_format', ['c6', 'dinlang'], { note: 'Automatisch aus Format.' }), + dropdown('motif_mode', ['katalog', 'upload', 'ohne', 'eigene_karten']), + m2o('motif', 'motifs'), + m2o('motif_upload', 'directus_files'), + f('own_cards', 'boolean', { interface: 'boolean', default: false, note: 'Eigene Karten (≤ 240 g/m²).' }), + f('text_briefing', 'text', { interface: 'input-multiline', note: 'Nur bei Schreibservice.' }), + f('text_template', 'text', { interface: 'input-multiline', note: 'Text mit [[Platzhaltern]].' }), + f('preview_session', 'string', { interface: 'input', note: 'Vorschau-Session – gezeigte Dokumente werden 1:1 übernommen.' }), + // Hochgeladenes Dokument (Datei-Produkte, z. B. zu unterschreibendes PDF/Word). + { field: 'source_file', type: 'uuid', + meta: { interface: 'file', special: ['file'], note: 'Hochgeladenes Dokument (Datei-Produkte) – erstes/primäres.' }, + schema: { is_nullable: true }, __related: 'directus_files', __onDelete: 'SET NULL' }, + // Alle hochgeladenen Dokumente (mehrere PDF/Word/Excel möglich) als Datei-ID-Liste. + f('source_files', 'json', { interface: 'tags', note: 'Alle hochgeladenen Dokumente (Datei-IDs).' }), + // Rechnungs-/Lieferadresse als Snapshot (für Bestätigung, Rechnung, Versand). + f('billing', 'json', { interface: 'input-code', note: 'Rechnungsadresse (Snapshot bei Bestellung).' }), + f('shipping_address', 'json', { interface: 'input-code', note: 'Abweichende Lieferadresse (falls vorhanden).' }), + f('entries_count', 'integer', { interface: 'input', default: 0 }), + f('count_inland', 'integer', { interface: 'input', default: 0, note: 'Empfängerzeilen Deutschland.' }), + f('count_ausland', 'integer', { interface: 'input', default: 0, note: 'Empfängerzeilen Ausland.' }), + f('net_total', 'float', { interface: 'input' }), + f('vat_amount', 'float', { interface: 'input' }), + f('gross_total', 'float', { interface: 'input' }), + m2o('voucher', 'vouchers'), + dropdown('payment_method', ['paypal', 'rechnung']), + dropdown('payment_status', ['offen', 'bezahlt', 'storniert'], { default: 'offen' }), + f('payment_ref', 'string', { interface: 'input' }), + f('artifact_path', 'string', { interface: 'input', note: 'Verweis auf Backend-Output.' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + { field: 'date_updated', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-updated'] }, schema: {} }, + // Produktionsansicht: durchsuchbare Empfängertabelle (Briefnummer + volle + // Anschrift, ganze Zeile) – wie im alten Job-Manager. Nur lesend/suchend. + { field: 'entries_view', type: 'alias', + meta: { interface: 'skrift-order-entries', special: ['alias', 'no-data'], + note: 'Alle Empfänger durchsuchbar (Briefnummer + volle Anschrift).' }, + schema: null }, + // Empfängerzeilen direkt im Auftrag (Adresse bzw. alle Freitext-Zeilen + // bearbeitbar) – kein Wechsel auf eine eigene Seite nötig. + { field: 'entries', type: 'alias', + meta: { interface: 'list-o2m', special: ['o2m'], + options: { template: '#{{letter_number}} · {{first_name}} {{last_name}} · {{zip}} {{city}}' }, + note: 'Empfängerzeilen bearbeiten (Adresse korrigieren).' }, + schema: null }, + // m2m-Alias zu price_items über order_addons: + { field: 'addons', type: 'alias', meta: { interface: 'list-m2m', special: ['m2m'] }, schema: null }, + // Präsentationsfeld: zeigt die generierten Dateien per Interface-Plugin + // (Direktzugriff auf den Ausgabe-Ordner, keine Kopie). + { field: 'files_view', type: 'alias', + meta: { interface: 'skrift-order-files', special: ['alias', 'no-data'], note: 'Generierte Dateien (Direktzugriff).' }, + schema: null }, + // Präsentationsfeld: „Drucken"-Button (reiht Druck-Jobs für eine Maschine ein). + { field: 'print_action', type: 'alias', + meta: { interface: 'skrift-print-button', special: ['alias', 'no-data'], note: 'In die Druck-Warteschlange einreihen.' }, + schema: null }, + ] }, + + { collection: 'order_entries', meta: { icon: 'table_rows', note: 'Empfängerzeilen (Tabelle/Excel).' }, fields: [ + m2o('order', 'orders', { onDelete: 'CASCADE' }), + f('letter_number', 'integer', { interface: 'input', note: 'Briefnummer – systemvergeben, immer gesetzt.' }), + f('salutation', 'string', { interface: 'input' }), + f('first_name', 'string', { interface: 'input' }), + f('last_name', 'string', { interface: 'input' }), + f('street', 'string', { interface: 'input' }), + f('house_no', 'string', { interface: 'input' }), + f('zip', 'string', { interface: 'input' }), + f('city', 'string', { interface: 'input' }), + f('country', 'string', { interface: 'input' }), + f('free_text', 'text', { interface: 'input-multiline', note: 'Alternativ zur strukturierten Adresse.' }), + f('placeholders', 'json', { interface: 'list', note: 'Zusätzliche Platzhalterwerte.' }), + f('text', 'text', { interface: 'input-multiline', note: 'Abweichender Brieftext NUR für dieses Schriftstück (leer = Standardtext des Auftrags).' }), + ] }, + + { collection: 'order_addons', meta: { icon: 'add_shopping_cart', note: 'Junction Auftrag ↔ Zusatzleistung.', hidden: true }, fields: [ + m2o('order', 'orders', { onDelete: 'CASCADE' }), + m2o('price_item', 'price_items', { onDelete: 'CASCADE' }), + ] }, + + // Plotter/Schreibmaschinen – im Admin pflegbar, Basis für die Warteschlange. + { collection: 'machines', meta: { icon: 'print', note: 'Produktionsmaschinen (Plotter).' }, fields: [ + f('name', 'string', { interface: 'input', required: true }), + f('base_url', 'string', { interface: 'input', required: true, note: 'z. B. http://192.168.2.32:90' }), + f('mid', 'string', { interface: 'input', note: 'Maschinen-ID an der Steuerung (optional).' }), + f('username', 'string', { interface: 'input', note: 'Login an der Steuerung (falls nötig).' }), + f('password', 'string', { interface: 'input', options: { masked: true }, note: 'Login-Passwort (falls nötig).' }), + f('poll_interval_seconds', 'integer', { interface: 'input', default: 5 }), + f('active', 'boolean', { interface: 'boolean', default: true }), + dropdown('status', ['unbekannt', 'bereit', 'druckt', 'fehler', 'offline'], { default: 'unbekannt', note: 'Vom Agent gemeldet.' }), + { field: 'last_seen', type: 'timestamp', meta: { interface: 'datetime', note: 'Letzte Rückmeldung des Agents.' }, schema: {} }, + // Aktuell eingelegtes Format: Der Agent druckt NUR Jobs mit passendem + // format-Schlüssel und springt nie selbstständig auf ein anderes Format. + // Leer = Maschine wartet, bis im Board ein Format als eingelegt gewählt wird. + f('current_format', 'string', { interface: 'input', note: 'Aktuell eingelegtes Format (Agent druckt nur passende Jobs). Leer = wartet auf Formatwahl.' }), + f('notes', 'text', { interface: 'input-multiline' }), + ] }, + + // Testdruck: beliebiges Template + Daten schnell generieren und drucken. + { collection: 'test_prints', meta: { icon: 'science', note: 'Testdrucke zum Verproben von Templates & Maschinen.' }, fields: [ + f('label', 'string', { interface: 'input', note: 'Bezeichnung (optional).' }), + m2o('template', 'format_templates', { note: 'Druck-Template (Platzierung an der Maschine).' }), + dropdown('format', ['a4', 'a6_hoch', 'a6_quer'], { default: 'a4', note: 'Layout für die Textgenerierung.' }), + dropdown('font', ['tilda', 'alva', 'ellie'], { default: 'tilda' }), + m2o('machine', 'machines'), + f('text', 'text', { interface: 'input-multiline', note: 'Testtext (Platzhalter werden nicht ersetzt).' }), + dropdown('status', ['neu', 'generiert', 'fehler'], { default: 'neu' }), + f('output_ref', 'string', { interface: 'input', readonly: true, note: 'Ausgabe-Ordner des Testdrucks.' }), + { field: 'run_action', type: 'alias', + meta: { interface: 'skrift-testprint-button', special: ['alias', 'no-data'], note: 'Generieren & in die Druck-Warteschlange legen.' }, + schema: null }, + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, + + // Druck-Templates (Maße/Position/Rotation in Zoll) – aus config.json. + { collection: 'format_templates', meta: { icon: 'straighten', note: 'Druck-Templates (Zoll).' }, fields: [ + f('key', 'string', { interface: 'input', unique: true, required: true }), + f('name', 'string', { interface: 'input', required: true }), + dropdown('type', ['brief', 'umschlag', 'signatur'], { default: 'brief' }), + f('width', 'float', { interface: 'input', note: 'Zoll' }), + f('height', 'float', { interface: 'input', note: 'Zoll' }), + f('xpos', 'float', { interface: 'input', default: 0 }), + f('ypos', 'float', { interface: 'input', default: 0 }), + f('scale', 'float', { interface: 'input', default: 1 }), + f('rotation', 'integer', { interface: 'input', default: 0 }), + ] }, + + // Zentrale Rendering-Formate: Seitengröße, Ränder, Zeilenhöhe/-limit. Das + // Backend liest diese (gecacht) statt hartkodierter Werte – so lassen sich + // eigene Formate anlegen, ohne Code zu ändern (eine Quelle für App + Backend). + { collection: 'render_formats', meta: { icon: 'crop_free', note: 'Rendering-Formate (Seitengröße, Ränder, Zeilenlimit) – zentral fürs Backend.' }, fields: [ + f('key', 'string', { interface: 'input', unique: true, required: true, note: 'Technischer Schlüssel, z. B. a4, a6p, din_lang, oder ein eigener.' }), + f('name', 'string', { interface: 'input', required: true }), + dropdown('kind', ['brief', 'umschlag'], { default: 'brief' }), + f('page_width_mm', 'float', { interface: 'input', required: true, note: 'Seitenbreite in mm.' }), + f('page_height_mm', 'float', { interface: 'input', required: true, note: 'Seitenhöhe in mm.' }), + f('margin_top_mm', 'float', { interface: 'input', default: 25 }), + f('margin_left_mm', 'float', { interface: 'input', default: 20 }), + f('margin_right_mm', 'float', { interface: 'input', note: 'Optional (v. a. Querformat).' }), + f('line_height_factor', 'float', { interface: 'input', default: 1.35, note: 'Zeilenhöhe = Schriftgröße × Faktor.' }), + f('line_limit', 'integer', { interface: 'input', note: 'Max. Zeilen. Leer = automatisch aus Höhe.' }), + // Zugehöriges Plotter-Druck-Template (Platzierung an der Maschine). + m2o('print_template', 'format_templates'), + f('active', 'boolean', { interface: 'boolean', default: true }), + ] }, + + { collection: 'jobs', meta: { icon: 'print', note: 'Produktions-Job (Druck-Warteschlange je Maschine).' }, fields: [ + m2o('order', 'orders', { onDelete: 'CASCADE' }), + f('output_ref', 'string', { interface: 'input', note: 'Ausgabe-Ordner ohne Auftrag (z. B. Testdruck).' }), + m2o('machine', 'machines'), + dropdown('type', ['brief', 'umschlag', 'signatur'], { default: 'brief', note: 'Was gedruckt wird.' }), + m2o('template', 'format_templates', { note: 'Aufgelöstes Druck-Template.' }), + // Format-Schlüssel des Jobs (Brief: a4/a6…, Kuvert: dinlang/c6). Grundlage + // für die Format-Warteschlange: der Agent druckt nur Jobs, deren Format dem + // an der Maschine eingelegten Format entspricht. + f('format', 'string', { interface: 'input', note: 'Format-Schlüssel (Brief: a4/a6…, Kuvert: dinlang/c6). Grundlage der Format-Warteschlange.' }), + f('format_label', 'string', { interface: 'input', note: 'Lesbare Formatbezeichnung für die Warteschlangen-Ansicht.' }), + dropdown('status', ['queued', 'printing', 'printed', 'failed', 'shipped'], { default: 'queued' }), + f('priority', 'integer', { interface: 'input', default: 0, note: 'Höher = zuerst. Direktdruck bekommt hohe Priorität.' }), + // Pro-Druck-Übersteuerung der Template-Maße (Breite/Höhe/X/Y/Scale/Rot). + // Vom Druck-Popup gesetzt; leer = Template-Werte verwenden. + f('params', 'json', { interface: 'input-code', note: 'Maß-Übersteuerung {width,height,xpos,ypos,scale,rotation} (leer = Template).' }), + // Welche Dokumentnummern gedruckt werden (1-basiert, z. B. „1-20" oder „1,3,5-7"). Leer = alle. + f('numbers', 'string', { interface: 'input', note: 'Zu druckende Briefnummern (1-basiert). Leer = alle.' }), + f('error', 'text', { interface: 'input-multiline', note: 'Fehlermeldung vom Agent (falls fehlgeschlagen).' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + { field: 'date_updated', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-updated'] }, schema: {} }, + ] }, + + { collection: 'status_history', meta: { icon: 'history', note: 'Status-Timeline fürs Portal.' }, fields: [ + m2o('order', 'orders', { onDelete: 'CASCADE' }), + f('status', 'string', { interface: 'input' }), + f('note', 'text', { interface: 'input-multiline' }), + m2o('changed_by', 'directus_users'), + { field: 'timestamp', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, + + // API-Zugänge für Kunden (Public-API). Keys werden nur als SHA-256-Hash gespeichert. + { collection: 'api_clients', meta: { icon: 'vpn_key', note: 'API-Zugänge für Kunden (Public-API).' }, fields: [ + f('name', 'string', { interface: 'input', required: true, note: 'Bezeichnung, z. B. Firmenname.' }), + f('key_plain', 'string', { interface: 'input', note: 'Wird beim Anlegen automatisch erzeugt und EINMALIG angezeigt – jetzt kopieren! Verschwindet bei der nächsten Änderung. Nur der Hash bleibt gespeichert.' }), + f('key_prefix', 'string', { interface: 'input', note: 'Erkennungspräfix des Keys (nur Anzeige).' }), + f('key_hash', 'string', { interface: 'input', note: 'SHA-256 des API-Keys – automatisch gesetzt. Nicht manuell ändern.' }), + m2o('customer', 'directus_users', { note: 'Verknüpftes Kundenkonto (optional).' }), + // Mehrere erlaubte Produkte (m2m). Die Order gibt per „product" an, welches genutzt wird. + { field: 'products', type: 'alias', meta: { interface: 'list-m2m', special: ['m2m'], note: 'Erlaubte Produkte für diesen Zugang (Mehrfachauswahl).' }, schema: null }, + // Einzelprodukt (optional, Fallback/alt) – wird nur genutzt, wenn keine m2m-Produkte gesetzt sind. + m2o('product', 'products', { note: 'Einzelprodukt (Fallback). Für mehrere Produkte „products" nutzen.' }), + f('active', 'boolean', { interface: 'boolean', default: true }), + f('webhook_url', 'string', { interface: 'input', note: 'Optionaler Webhook für Statusänderungen (derzeit ungenutzt – Kunde pollt).' }), + f('config', 'json', { interface: 'input-code', note: 'Kundenspezifische Konfiguration (optional).' }), + f('last_used', 'timestamp', { interface: 'datetime' }), + // AGB/Vertrag – einmalige Zustimmung beim Onboarding festhalten (Nachweis). + f('terms_version', 'string', { interface: 'input', note: 'Akzeptierte AGB-Version, z. B. „2026-01".' }), + f('terms_accepted_at', 'timestamp', { interface: 'datetime', note: 'Zeitpunkt der AGB-/Vertragszustimmung.' }), + f('contract_ref', 'string', { interface: 'input', note: 'Referenz zum unterschriebenen Vertrag (Aktenzeichen/Link).' }), + ] }, + + // Junction API-Zugang ↔ Produkt (m2m für api_clients.products). + { collection: 'api_client_products', meta: { icon: 'link', note: 'Junction API-Zugang ↔ Produkt.', hidden: true }, fields: [ + m2o('api_client', 'api_clients', { onDelete: 'CASCADE' }), + m2o('product', 'products', { onDelete: 'CASCADE' }), + ] }, + + // Unterschriften je Kunde (SVG-Datei). Wird am Kundenkonto als o2m gezeigt. + { collection: 'signatures', meta: { icon: 'draw', note: 'Unterschriften je Kunde.' }, fields: [ + m2o('customer', 'directus_users', { onDelete: 'CASCADE' }), + f('label', 'string', { interface: 'input', note: 'z. B. „Standard", „mit Titel".' }), + // Datei-Upload (SVG) statt Textfeld. + { field: 'file', type: 'uuid', + meta: { interface: 'file', special: ['file'], note: 'Signatur als SVG-Datei (Upload).' }, + schema: { is_nullable: true }, __related: 'directus_files', __onDelete: 'SET NULL' }, + // Voreingestellte Platzierung relativ zum Marker im PDF (§§SIG1§§ …). + // Wird im Signatur-Modul als Vorgabe geladen, dort manuell überschreibbar. + f('marker_key', 'string', { interface: 'input', default: 'SIG1', note: 'Marker-Token im PDF (ohne §§), z. B. SIG1.' }), + f('offset_x_mm', 'float', { interface: 'input', default: 0, note: 'Versatz X zum Marker (mm).' }), + f('offset_y_mm', 'float', { interface: 'input', default: 0, note: 'Versatz Y zum Marker (mm).' }), + f('width_mm', 'float', { interface: 'input', default: 40, note: 'Breite der Signatur (mm).' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, + + // Kundenspezifische Rabatte. Wird am Kundenkonto als o2m gezeigt. + { collection: 'customer_discounts', meta: { icon: 'percent', note: 'Kundenspezifische Rabatte.' }, fields: [ + m2o('customer', 'directus_users', { onDelete: 'CASCADE' }), + f('label', 'string', { interface: 'input', note: 'z. B. „Einführungsrabatt".' }), + dropdown('type', ['prozent', 'fest'], { default: 'prozent' }), + f('value', 'float', { interface: 'input', note: 'Prozent oder €-Betrag.' }), + dropdown('scope', ['alle', 'erste_n_stueck'], { default: 'alle', note: 'Gilt für alle oder nur die ersten N Stück.' }), + f('limit_stueck', 'integer', { interface: 'input', note: 'N bei „erste_n_stueck".' }), + f('active', 'boolean', { interface: 'boolean', default: true }), + f('valid_until', 'timestamp', { interface: 'datetime', note: 'Optionales Ablaufdatum.' }), + ] }, + + // Für einzelne Kunden freigeschaltete Produkte (Override der Sichtbarkeit). + { collection: 'customer_products', meta: { icon: 'lock_open', note: 'Freigeschaltete Produkte je Kunde.', hidden: true }, fields: [ + m2o('customer', 'directus_users', { onDelete: 'CASCADE' }), + m2o('product', 'products', { onDelete: 'CASCADE' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, + + // E-Mail-Vorlagen (Betreff + HTML-Text, WYSIWYG). Ein Datensatz je Ereignis. + { collection: 'email_templates', meta: { icon: 'mail', note: 'E-Mail-Vorlagen (Betreff + Text).' }, fields: [ + f('key', 'string', { interface: 'input', unique: true, required: true, note: 'Ereignis-Schlüssel (login_code, order_created, versendet …).' }), + f('label', 'string', { interface: 'input', note: 'Bezeichnung im Admin.' }), + f('subject', 'string', { interface: 'input', required: true, note: 'Betreff. Platzhalter: {{order_id}}, {{name}}, {{code}}, {{link}} …' }), + f('body', 'text', { interface: 'input-rich-text-html', note: 'Text (WYSIWYG/HTML). Platzhalter in {{...}}.' }), + f('append_signature', 'boolean', { interface: 'boolean', default: true, note: 'Signatur automatisch anhängen (bei Mails mit eigenem Footer aus).' }), + f('attach_agb', 'boolean', { interface: 'boolean', default: false, note: 'AGB-PDF an diese Mail anhängen.' }), + f('enabled', 'boolean', { interface: 'boolean', default: true }), + ] }, + + // Gemeinsame E-Mail-Einstellungen (Signatur, Portal-Link, AGB, Footer). + { collection: 'email_settings', meta: { icon: 'alternate_email', singleton: true, note: 'Absender, Signatur, Portal-Link, AGB + Footer für alle Mails.' }, fields: [ + f('sender_name', 'string', { interface: 'input', note: 'Absendername (erscheint als Absender, z. B. „Skrift").' }), + f('sender_email', 'string', { interface: 'input', note: 'Absenderadresse (muss vom SMTP-Server erlaubt sein).' }), + f('team_email', 'string', { interface: 'input', note: 'Interne Benachrichtigungen (neue Bestellung/Muster/Anfrage). Leer = keine Team-Mails.' }), + f('signature', 'text', { interface: 'input-rich-text-html', note: 'Signatur unter Mails ohne eigenen Footer (WYSIWYG/HTML).' }), + f('portal_url', 'string', { interface: 'input', note: 'Basis-URL des Kundenportals (Platzhalter {{link}}).' }), + f('company_footer', 'text', { interface: 'input-rich-text-html', note: 'Footer-Adresszeile (Platzhalter {{footer}}).' }), + { field: 'agb_file', type: 'uuid', + meta: { interface: 'file', special: ['file'], note: 'AGB als PDF – wird an Mails mit „AGB anhängen" gehängt. Zum Ändern einfach neue Datei hochladen.' }, + schema: { is_nullable: true }, __related: 'directus_files', __onDelete: 'SET NULL' }, + ] }, + + // Standard-Mustertexte für den manuellen Muster-Druck (Du-/Sie-Form). + // Platzhalter [[abschnitt]] füllt der Bediener im Druck-Dialog kurz aus. + { collection: 'muster_settings', meta: { icon: 'science', singleton: true, note: 'Standard-Mustertexte (Du/Sie) für den Muster-Druck.' }, fields: [ + f('text_du', 'text', { interface: 'input-multiline', note: 'Standard-Mustertext (Du-Form). Platzhalter [[abschnitt]] wird im Druck-Dialog gefüllt.' }), + f('text_sie', 'text', { interface: 'input-multiline', note: 'Standard-Mustertext (Sie-Form). Platzhalter [[abschnitt]] wird im Druck-Dialog gefüllt.' }), + ] }, + + // Frei anlegbare Mustertexte (beliebig viele) – erscheinen im „Manueller Druck"- + // Dropdown. Ersetzt langfristig die feste Du/Sie-Vorgabe (die als Fallback bleibt). + { collection: 'muster_texts', meta: { icon: 'science', note: 'Frei anlegbare Mustertexte für den manuellen Druck.' }, fields: [ + f('label', 'string', { interface: 'input', required: true, note: 'Bezeichnung im Dropdown.' }), + f('text', 'text', { interface: 'input-multiline', note: 'Mustertext. Platzhalter [[…]] erlaubt.' }), + f('sort', 'integer', { interface: 'input' }), + f('active', 'boolean', { interface: 'boolean', default: true }), + ] }, + + // Angebots- und Musteranfragen aus der App. + { collection: 'offer_requests', meta: { icon: 'request_quote', note: 'Angebots- und Musteranfragen aus der App.' }, fields: [ + dropdown('type', ['angebot', 'muster'], { default: 'angebot' }), + f('name', 'string', { interface: 'input', required: true }), + f('email', 'string', { interface: 'input', required: true }), + f('phone', 'string', { interface: 'input' }), + f('quantity', 'integer', { interface: 'input' }), + f('product', 'string', { interface: 'input', note: 'Bei Muster: gewünschtes Produkt.' }), + f('message', 'text', { interface: 'input-multiline' }), + f('address', 'json', { interface: 'input-code', note: 'Bei Muster: Lieferadresse.' }), + dropdown('status', ['neu', 'in_bearbeitung', 'beantwortet', 'abgelehnt'], { default: 'neu' }), + m2o('customer', 'directus_users', { note: 'Falls die Anfrage von einem bestehenden Konto kommt.' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, + + // Vorschau-Kontingent (serverseitig – der Client darf das nicht bestimmen). + { collection: 'preview_usage', meta: { icon: 'speed', hidden: true, note: 'Vorschau-Verbrauch je Kennung und Tag.' }, fields: [ + f('key', 'string', { interface: 'input', required: true, note: 'E-Mail oder anonyme Kennung.' }), + f('day', 'string', { interface: 'input', required: true }), + f('count', 'integer', { interface: 'input', default: 0 }), + ] }, + + // Einmalcodes für den passwortlosen Login (nur die Extension greift darauf zu). + { collection: 'login_codes', meta: { icon: 'key', hidden: true, note: 'Einmalcodes für den passwortlosen Login (nur Hashes).' }, fields: [ + f('email', 'string', { interface: 'input', required: true }), + f('code_hash', 'string', { interface: 'input', required: true }), + f('expires_at', 'timestamp', { interface: 'datetime', required: true }), + f('attempts', 'integer', { interface: 'input', default: 0 }), + f('used', 'boolean', { interface: 'boolean', default: false }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, + + // Kontakte/Leads – Empfänger gesendeter Schriftstücke. Werden bei Versand + // automatisch angelegt (Hook) und nach 30 Tagen wieder gelöscht, außer der + // Auftrag ist als „Kontakte behalten" (Akquise) markiert. Telefon/E-Mail sind + // manuell zu pflegen (Empfänger liefern sie nicht mit). CSV-Import/-Export + // über die normale Collection-Seite. + { collection: 'contacts', meta: { icon: 'contacts', note: 'Kontakte/Leads – Empfänger gesendeter Schriftstücke.' }, fields: [ + f('salutation', 'string', { interface: 'input' }), + f('first_name', 'string', { interface: 'input' }), + f('last_name', 'string', { interface: 'input' }), + f('company', 'string', { interface: 'input' }), + f('street', 'string', { interface: 'input' }), + f('house_no', 'string', { interface: 'input' }), + f('zip', 'string', { interface: 'input' }), + f('city', 'string', { interface: 'input' }), + f('country', 'string', { interface: 'input' }), + f('email', 'string', { interface: 'input', note: 'Manuell nachtragen.' }), + f('phone', 'string', { interface: 'input', note: 'Manuell nachtragen. Klick im Kontakte-Modul öffnet GroundWire.' }), + f('notes', 'text', { interface: 'input-multiline', note: 'Anruf-/Lead-Notizen.' }), + dropdown('lead_status', ['neu', 'kontaktiert', 'interessiert', 'kein_interesse', 'kunde'], { default: 'neu', note: 'Nur Kontakte mit „kein_interesse" werden nach 30 Tagen automatisch gelöscht; alle anderen bleiben.' }), + m2o('source_order', 'orders', { onDelete: 'SET NULL', note: 'Auftrag, aus dem der Kontakt stammt.' }), + m2o('source_entry', 'order_entries', { onDelete: 'SET NULL', note: 'Empfängerzeile, aus der der Kontakt stammt.' }), + f('sent_at', 'timestamp', { interface: 'datetime', note: 'Versandzeitpunkt – Grundlage für die 30-Tage-Löschung.' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + { field: 'date_updated', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-updated'] }, schema: {} }, + ] }, + + // Standardaktionen im Kontakte-Modul (Rückruf-Wiedervorlage, Angebot senden). + // „angebot" verschickt sofort die Eckdaten an die interne Adresse; „rueckruf" + // löst am fälligen Tag früh eine Erinnerungs-Mail aus (Hook skrift-contacts). + { collection: 'contact_actions', meta: { icon: 'task_alt', hidden: true, note: 'Aktionen/Wiedervorlagen je Kontakt (Rückruf, Angebot).' }, fields: [ + m2o('contact', 'contacts', { onDelete: 'CASCADE' }), + dropdown('type', ['rueckruf', 'angebot', 'mail'], { default: 'rueckruf' }), + f('due_date', 'timestamp', { interface: 'datetime', note: 'Fälligkeit (nur Rückruf) – Basis der Erinnerungs-Mail.' }), + f('note', 'text', { interface: 'input-multiline', note: 'Notiz zur Aktion (optional).' }), + dropdown('status', ['offen', 'erledigt'], { default: 'offen' }), + f('notified', 'boolean', { interface: 'boolean', default: false, note: 'Erinnerungs-Mail bereits verschickt (verhindert Wiederholung).' }), + { field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} }, + ] }, +]; + +// ── Schema anlegen ────────────────────────────────────────────────────────── +async function applySchema() { + console.log('› Collections & Felder'); + const existingCols = new Set((await api('GET', '/collections')).map((c) => c.collection)); + const allFields = await api('GET', '/fields'); + const existingFields = new Set(allFields.map((x) => `${x.collection}.${x.field}`)); + const existingRels = new Set((await api('GET', '/relations')).map((r) => `${r.collection}.${r.field}`)); + const relationsToCreate = []; + + for (const c of collections) { + if (!existingCols.has(c.collection)) { + await api('POST', '/collections', { collection: c.collection, meta: c.meta, schema: {}, fields: [ID] }); + log('collection +', c.collection); + } else { log('collection ok', c.collection); } + + for (const fld of c.fields) { + const { __related, __onDelete, ...clean } = fld; + if (!existingFields.has(`${c.collection}.${fld.field}`)) { + await api('POST', `/fields/${c.collection}`, clean); + log('field +', `${c.collection}.${fld.field}`); + } + if (__related) relationsToCreate.push({ collection: c.collection, field: fld.field, related: __related, onDelete: __onDelete }); + } + } + + // Profilfelder direkt am Login-Konto (Kunde = directus_users). + console.log('› Kundenfelder an directus_users'); + for (const fld of USER_FIELDS) { + if (!existingFields.has(`directus_users.${fld.field}`)) { + await api('POST', '/fields/directus_users', fld); + log('field +', `directus_users.${fld.field}`); + } else { + // Vorhandenes Feld: Oberfläche/Optionen aktualisieren (z. B. Adressliste). + try { await api('PATCH', `/fields/directus_users/${fld.field}`, { meta: fld.meta }); } catch { /* egal */ } + } + } + // Ungenutzte Standardfelder ausblenden. Direkt patchen (System-Felder existieren + // immer); ein Fehler wird geloggt statt still verschluckt – so sieht man, falls + // ein Feldname in dieser Directus-Version anders heißt. + for (const field of HIDE_USER_FIELDS) { + try { + await api('PATCH', `/fields/directus_users/${field}`, { meta: { hidden: true } }); + log('feld versteckt', `directus_users.${field}`); + } catch (e) { + console.warn(` Feld directus_users.${field} nicht ausgeblendet: ${e.message}`); + } + } + + console.log('› Beziehungen (m2o)'); + for (const r of relationsToCreate) { + if (existingRels.has(`${r.collection}.${r.field}`)) { continue; } + await api('POST', '/relations', { + collection: r.collection, field: r.field, related_collection: r.related, + schema: { on_delete: r.onDelete }, meta: {}, + }); + log('relation +', `${r.collection}.${r.field} → ${r.related}`); + } + + // m2m-Verdrahtung orders.addons ↔ price_items über order_addons + console.log('› m2m orders.addons'); + try { + await api('PATCH', '/relations/order_addons/order', { meta: { one_field: 'addons', junction_field: 'price_item' } }); + await api('PATCH', '/relations/order_addons/price_item', { meta: { junction_field: 'order' } }); + // m2m api_clients.products ↔ products über api_client_products + await api('PATCH', '/relations/api_client_products/api_client', { meta: { one_field: 'products', junction_field: 'product' } }); + await api('PATCH', '/relations/api_client_products/product', { meta: { junction_field: 'api_client' } }); + log('m2m verdrahtet'); + } catch (e) { console.warn(' m2m-Verdrahtung übersprungen (bitte melden):', e.message); } + + // o2m am Kundenkonto: Unterschriften + Rabatte direkt im User anzeigen. + console.log('› o2m-Verdrahtung'); + try { + await api('PATCH', '/relations/signatures/customer', { meta: { one_field: 'signatures' } }); + await api('PATCH', '/relations/customer_discounts/customer', { meta: { one_field: 'discounts' } }); + await api('PATCH', '/relations/customer_products/customer', { meta: { one_field: 'unlocked_products' } }); + await api('PATCH', '/relations/order_entries/order', { meta: { one_field: 'entries' } }); + log('o2m verdrahtet'); + } catch (e) { console.warn(' o2m-Verdrahtung übersprungen (bitte melden):', e.message); } +} + +// ── Seed-Daten ────────────────────────────────────────────────────────────── +async function seedItem(collection, uniqueField, item) { + const existing = await api('GET', `/items/${collection}?filter[${uniqueField}][_eq]=${encodeURIComponent(item[uniqueField])}&limit=1`); + if (existing && existing.length) return existing[0]; + const created = await api('POST', `/items/${collection}`, item); + log('seed +', `${collection}.${item[uniqueField]}`); + return created; +} + +async function applySeed() { + console.log('› Seed'); + const products = [ + { key: 'briefe', name: 'Briefe', type: 'letter', visibility: 'alle', pricing_mode: 'formel', base_price: 4.0, norm_qty: 100, price_factor_a: 1, price_factor_e: 3, active: true, sort: 1 }, + // Postkarten: höherer Deckel + sanfterer Exponent, damit kleine/mittlere + // Mengen nicht zu günstig werden (Fixaufwand relativ größer als bei Briefen). + { key: 'postkarten', name: 'Postkarten', type: 'postcard', visibility: 'alle', pricing_mode: 'formel', base_price: 1.3, norm_qty: 100, price_factor_a: 1.5, price_factor_e: 2, active: true, sort: 2 }, + { key: 'muster', name: 'Muster', type: 'sample', visibility: 'alle', pricing_mode: 'formel', base_price: 0, active: true, sort: 3 }, + // Datei-Produkt: pro Kunde freischaltbar, Kunde lädt ein PDF/Word hoch. + // pricing_mode „formel" + base_price, damit es für freigeschaltete Kunden + // bestellbar ist; für andere bleibt es (type contact) ein Anfrage-Produkt. + { key: 'unterschriftenservice', name: 'Unterschriftenservice', type: 'contact', visibility: 'unternehmen', pricing_mode: 'formel', base_price: 5.0, input_mode: 'datei', active: true, sort: 4 }, + { key: 'follow_ups', name: 'Automatisierte Follow-ups', type: 'contact', visibility: 'unternehmen', pricing_mode: 'auf_anfrage', active: true, sort: 5 }, + ]; + const productByKey = {}; + for (const p of products) productByKey[p.key] = await seedItem('products', 'key', p); + // Unterschriftenservice muss im Datei-Modus laufen (Text-Schritt = Upload) UND + // bepreisbar sein (formel), damit freigeschaltete Kunden ihn regulär bestellen + // können. Auch für bestehende Datensätze erzwingen (seedItem aktualisiert nicht). + try { + const us = productByKey.unterschriftenservice; + if (us?.id) { + const patch = {}; + if (us.input_mode !== 'datei') patch.input_mode = 'datei'; + if (us.pricing_mode !== 'formel') patch.pricing_mode = 'formel'; + if (Object.keys(patch).length) { + await api('PATCH', `/items/products/${us.id}`, patch); + log('unterschriftenservice →', JSON.stringify(patch)); + } + } + } catch { /* nicht kritisch */ } + + const formats = [ + { product: productByKey.briefe.id, key: 'a4', name: 'A4', active: true }, + { product: productByKey.postkarten.id, key: 'a6_hoch', name: 'A6 Hochformat', active: true }, + { product: productByKey.postkarten.id, key: 'a6_quer', name: 'A6 Querformat', active: true }, + ]; + for (const fmt of formats) await seedItem('formats', 'key', fmt); + + // Preise: kundenseitige Werte aus dem Konfigurator; 0 = im Admin setzen. + const priceItems = [ + { key: 'porto_inland', label: 'Porto Inland', category: 'versand', price: 2.2, unit: 'pro_stueck', active: true }, + { key: 'porto_ausland', label: 'Porto Ausland', category: 'versand', price: 2.5, unit: 'pro_stueck', active: true }, + { key: 'sammelversand', label: 'Sammelversand', category: 'versand', price: 4.95, unit: 'einmalig', active: true }, + { key: 'sammelversand_klein', label: 'Sammelversand (bis 5 Stück)', category: 'versand', price: 1.80, unit: 'einmalig', active: true }, + { key: 'kuvert', label: 'Kuvert', category: 'kuvert', price: 0.5, unit: 'pro_stueck', active: true }, + { key: 'beschriftung', label: 'Kuvert-Beschriftung', category: 'beschriftung', price: 0.5, unit: 'pro_stueck', active: true }, + { key: 'schreibservice', label: 'Schreibservice', category: 'zusatzleistung', price: 0, unit: 'einmalig', active: true }, + { key: 'gestaltungsservice', label: 'Gestaltungsservice', category: 'zusatzleistung', price: 0, unit: 'einmalig', active: true }, + { key: 'motiv_upload', label: 'Motiv-Upload', category: 'zusatzleistung', price: 0, unit: 'einmalig', active: true }, + ]; + for (const pi of priceItems) await seedItem('price_items', 'key', pi); + + // pricing_settings (Singleton) + const ps = await api('GET', '/items/pricing_settings'); + if (!ps || !ps.formula) { + await api('PATCH', '/items/pricing_settings', { + formula: 'base_price * menge', mwst_percent: 19, paypal_limit_net: 200, + currency: 'EUR', char_whitelist: CHAR_WHITELIST, + // Beispiel-Staffel (relativ hoch angesetzt) – in Directus anpassbar. + quantity_discounts: [ + { min_qty: 250, percent: 5 }, + { min_qty: 500, percent: 10 }, + { min_qty: 1000, percent: 15 }, + ], + }); + log('seed singleton pricing_settings'); + } + // Gemeinsame Mengen-Multiplikator-Formel: nur setzen, wenn leer (Edits bleiben + // erhalten). `norm` kommt je Produkt aus products.norm_qty, a/e je Produkt. + const CANON_MULT = '(qty >= norm) ? 1 : (1 + a * pow(1 - qty / norm, e))'; + if (!ps || !ps.multiplier_formula) { + await api('PATCH', '/items/pricing_settings', { multiplier_formula: CANON_MULT }); + log('seed multiplier-formel'); + } else { + // Migration: eine bestehende Formel mit fest verdrahtetem Koeffizient/Exponent + // (1 + N * pow(1 - qty / norm, M)) auf die a/e-Variante umstellen und die + // Altwerte in die Produkte übernehmen – Verhalten bleibt exakt erhalten. + const m = String(ps.multiplier_formula).match( + /^\(\s*qty\s*>=\s*norm\s*\)\s*\?\s*1\s*:\s*\(\s*1\s*\+\s*([\d.]+)\s*\*\s*pow\(\s*1\s*-\s*qty\s*\/\s*norm\s*,\s*([\d.]+)\s*\)\s*\)$/, + ); + if (m) { + const aOld = Number(m[1]); const eOld = Number(m[2]); + await api('PATCH', '/items/pricing_settings', { multiplier_formula: CANON_MULT }); + const prods = await api('GET', '/items/products?fields=id,price_factor_a,price_factor_e&limit=-1'); + for (const p of (prods || [])) { + const patch = {}; + if (p.price_factor_a == null) patch.price_factor_a = aOld; + if (p.price_factor_e == null) patch.price_factor_e = eOld; + if (Object.keys(patch).length) await api('PATCH', `/items/products/${p.id}`, patch); + } + log(`migriere multiplier-formel → a/e (Altwerte a=${aOld}, e=${eOld} in Produkte übernommen)`); + } + } + + // E-Mail-Vorlagen (nur anlegen, wenn noch nicht vorhanden – Edits bleiben erhalten). + const G = 'Guten Tag {{name}},'; // gemeinsame Anrede + // Reiche Bestellbestätigung (Design an das bisherige n8n-Template angelehnt, + // aber mit flachen {{platzhaltern}}, die der Mailer-Hook befüllt). + const orderCreatedBody = ` + +
+ + + + + + + +{{lieferadresse_block}} + + +

Bestellbestätigung

Guten Tag {{name}},

vielen Dank für Ihre Bestellung bei Skrift. Wir haben sie erhalten und bearbeiten sie schnellstmöglich.

Ihre Bestellnummer:

{{order_id}}

Ihre Bestellung

+ + + + + +
Produkt:{{product}}
Menge:{{menge}} Stück
Format:{{format}}
Versand:{{versand}}
{{kuvert_block}}

Preisübersicht

+ + + + + +
Zwischensumme (netto):{{netto}} {{waehrung}}
MwSt. ({{mwst_satz}} %):{{mwst_betrag}} {{waehrung}}

Gesamt (brutto):{{brutto}} {{waehrung}}

Rechnungsadresse

{{rechnungsadresse}}

Wie geht es weiter?

  1. Wir prüfen Ihre Bestellung und bereiten die Produktion vor.
  2. Nach Fertigstellung erhalten Sie eine Versandbestätigung.

Mit freundlichen Grüßen
Ihr Skrift-Team

{{footer}}

`.trim(); + + const templates = [ + { key: 'login_code', label: 'Anmeldecode', subject: 'Ihr Anmeldecode: {{code}}', append_signature: true, attach_agb: false, + body: `

Guten Tag,

Ihr Anmeldecode für Skrift lautet:

` + + `

{{code}}

` + + `

Der Code ist 10 Minuten gültig. Falls Sie keine Anmeldung angefordert haben, ignorieren Sie diese E-Mail.

` }, + { key: 'order_created', label: 'Bestellbestätigung', subject: 'Ihre Bestellung {{order_id}} ist eingegangen', + append_signature: false, attach_agb: true, body: orderCreatedBody }, + { key: 'bezahlt', label: 'Status: bezahlt', subject: 'Zahlung erhalten – {{order_id}}', append_signature: true, attach_agb: false, + body: `

${G}

Ihre Zahlung zu Auftrag {{order_id}} ist bei uns eingegangen. Wir starten die Produktion.

` }, + { key: 'in_produktion', label: 'Status: in Produktion', subject: '{{order_id}} ist in Produktion', append_signature: true, attach_agb: false, + body: `

${G}

Ihr Auftrag {{order_id}} ist jetzt in Produktion.

` }, + { key: 'versendet', label: 'Status: versendet', subject: '{{order_id}} wurde versendet', append_signature: true, attach_agb: false, + body: `

${G}

Ihre Schriftstücke zu Auftrag {{order_id}} wurden versendet bzw. an Sie übergeben. Vielen Dank für Ihr Vertrauen!

` }, + { key: 'abgeschlossen', label: 'Status: abgeschlossen', subject: '{{order_id}} abgeschlossen', append_signature: true, attach_agb: false, + body: `

${G}

Ihr Auftrag {{order_id}} ist abgeschlossen. Wir freuen uns auf Ihre nächste Bestellung.

` }, + { key: 'storniert', label: 'Status: storniert', subject: '{{order_id}} wurde storniert', append_signature: true, attach_agb: false, + body: `

${G}

Ihr Auftrag {{order_id}} wurde storniert. Bei Fragen sind wir gerne für Sie da.

{{reason}}` }, + // Separate, frei editierbare Mails für Unterschriftenservice- und Extern-Bestellungen. + { key: 'unterschriften_eingang', label: 'Unterschriften: Eingang', subject: 'Ihr Unterschriften-Auftrag {{order_number}} ist eingegangen', append_signature: true, attach_agb: false, + body: `

${G}

vielen Dank – Ihr Auftrag {{order_number}} für den Unterschriftenservice ist bei uns eingegangen. Wir prüfen Ihr Dokument und melden uns mit den nächsten Schritten.

` }, + { key: 'extern_eingang', label: 'Externe Bestellung: Eingang', subject: 'Ihre Bestellung {{order_number}} ist eingegangen', append_signature: true, attach_agb: false, + body: `

${G}

vielen Dank – Ihre Bestellung {{order_number}} ist bei uns eingegangen und geht direkt in die Produktion.

` }, + ]; + for (const t of templates) await seedItem('email_templates', 'key', { enabled: true, ...t }); + + // Druck-Templates – Werte 1:1 aus der config.json des alten Job-Managers. + // Je Format gibt es zwei Varianten (v1/v2); die zweite ist die zusätzliche + // Platzierung (u. a. für individuelle Kuvert-Beschriftung). Werte werden per + // Upsert gesetzt, damit falsche Altwerte beim Bootstrap korrigiert werden. + const formatTemplates = [ + { key: 'a4_single', name: 'A4 Brief', type: 'brief', width: 8.27, height: 11.69, xpos: 0.0, ypos: -0.3, scale: 1.0, rotation: 0 }, + { key: 'a6_v1', name: 'A6 Hochformat – Variante 1', type: 'brief', width: 4.1, height: 5.8, xpos: -0.3, ypos: -0.3, scale: 1.0, rotation: 0 }, + { key: 'a6_v2', name: 'A6 Hochformat – Variante 2', type: 'brief', width: 4.1, height: 5.8, xpos: 4.0, ypos: -0.3, scale: 1.0, rotation: 90 }, + { key: 'a6l_v1', name: 'A6 Querformat – Variante 1', type: 'brief', width: 5.8, height: 4.1, xpos: -0.3, ypos: -0.3, scale: 1.0, rotation: 0 }, + { key: 'a6l_v2', name: 'A6 Querformat – Variante 2', type: 'brief', width: 5.8, height: 4.1, xpos: 4.0, ypos: -0.3, scale: 1.0, rotation: 90 }, + // DIN Lang – v1 = Empfängeradresse, v2 = individuelle Beschriftung. + { key: 'kuvert_a_v1', name: 'Kuvert DIN Lang – Variante 1', type: 'umschlag', width: 4.33, height: 8.27, xpos: 4.0, ypos: -0.2, scale: 1.0, rotation: 90 }, + { key: 'kuvert_a_v2', name: 'Kuvert DIN Lang – Variante 2', type: 'umschlag', width: 3.9, height: 8.27, xpos: 4.49, ypos: -0.2, scale: 1.0, rotation: 90 }, + // C6 – v1 = Empfängeradresse, v2 = individuelle Beschriftung. + { key: 'kuvert_b_v1', name: 'Kuvert C6 – Variante 1', type: 'umschlag', width: 4.49, height: 6.38, xpos: 4.2, ypos: -0.2, scale: 1.0, rotation: 90 }, + { key: 'kuvert_b_v2', name: 'Kuvert C6 – Variante 2', type: 'umschlag', width: 4.33, height: 6.38, xpos: 4.0, ypos: -0.2, scale: 1.0, rotation: 90 }, + ]; + for (const t of formatTemplates) { + const vorhanden = await api('GET', `/items/format_templates?filter[key][_eq]=${encodeURIComponent(t.key)}&limit=1&fields=id`); + if (vorhanden && vorhanden.length) await api('PATCH', `/items/format_templates/${vorhanden[0].id}`, t); + else { await api('POST', '/items/format_templates', t); log('seed + format_templates.' + t.key); } + } + + // Rendering-Formate (zentral fürs Backend). Werte = bisherige Defaults. + const renderFormats = [ + { key: 'a4', name: 'A4', kind: 'brief', page_width_mm: 210, page_height_mm: 297, margin_top_mm: 25, margin_left_mm: 20, line_height_factor: 1.35, line_limit: 27, active: true }, + { key: 'a6p', name: 'A6 Hochformat', kind: 'brief', page_width_mm: 105, page_height_mm: 148, margin_top_mm: 8, margin_left_mm: 8, line_height_factor: 1.3, line_limit: 14, active: true }, + { key: 'a6l', name: 'A6 Querformat', kind: 'brief', page_width_mm: 148, page_height_mm: 105, margin_top_mm: 8, margin_left_mm: 8, margin_right_mm: 14, line_height_factor: 1.2, line_limit: 11, active: true }, + { key: 'din_lang', name: 'DIN Lang Kuvert', kind: 'umschlag', page_width_mm: 220, page_height_mm: 110, margin_top_mm: 50, margin_left_mm: 10, line_height_factor: 1.2, active: true }, + { key: 'c6', name: 'C6 Kuvert', kind: 'umschlag', page_width_mm: 162, page_height_mm: 114, margin_top_mm: 60, margin_left_mm: 10, line_height_factor: 1.2, active: true }, + ]; + // Upsert (nicht nur anlegen), damit falsche Alt-Maße korrigiert werden – z. B. + // Postkarten (a6p/a6l), die sonst nicht aufs Kartenformat passen. + for (const rf of renderFormats) { + const vorhanden = await api('GET', `/items/render_formats?filter[key][_eq]=${encodeURIComponent(rf.key)}&limit=1&fields=id`); + if (vorhanden && vorhanden.length) await api('PATCH', `/items/render_formats/${vorhanden[0].id}`, rf); + else { await api('POST', '/items/render_formats', rf); log('seed + render_formats.' + rf.key); } + } + + // email_settings (Singleton) – Signatur nur setzen, wenn leer. + const es = await api('GET', '/items/email_settings'); + if (!es || !es.signature) { + await api('PATCH', '/items/email_settings', { + sender_name: 'Skrift', + sender_email: (process.env.EMAIL_FROM || 'noreply@skrift.de').trim(), + team_email: (process.env.SKRIFT_TEAM_EMAIL || 'hello@skrift.de').trim(), + signature: '

Mit freundlichen Grüßen
Ihr Skrift-Team

', + portal_url: (process.env.CORS_ORIGIN || 'https://app.skrift.de').split(',')[0].trim(), + company_footer: 'Skrift | Hundscheiderweg 4 | 66679 Losheim am See | www.skrift.de', + }); + log('seed singleton email_settings'); + } + + // muster_settings (Singleton) – Standardtexte nur setzen, wenn leer. + const ms = await api('GET', '/items/muster_settings'); + if (!ms || (!ms.text_du && !ms.text_sie)) { + await api('PATCH', '/items/muster_settings', { + text_du: 'Hallo [[Vorname]],\n\nschön, dass Du Skrift ausprobierst! Dieser Brief wurde von einem Roboter mit einem echten Stift geschrieben.\n\n[[abschnitt]]\n\nHerzliche Grüße\nDein Skrift-Team', + text_sie: 'Sehr geehrte/r [[Anrede]] [[Nachname]],\n\nschön, dass Sie Skrift ausprobieren! Dieser Brief wurde von einem Roboter mit einem echten Stift geschrieben.\n\n[[abschnitt]]\n\nMit freundlichen Grüßen\nIhr Skrift-Team', + }); + log('seed singleton muster_settings'); + } + + // muster_texts – Starteinträge (Du/Sie) nur anlegen, wenn noch keine da sind. + const mtx = await api('GET', '/items/muster_texts?limit=1'); + if (!mtx || !mtx.length) { + await api('POST', '/items/muster_texts', { label: 'Sie-Form', sort: 1, active: true, + text: 'Sehr geehrte/r [[Anrede]] [[Nachname]],\n\nschön, dass Sie Skrift ausprobieren! Dieser Brief wurde von einem Roboter mit einem echten Stift geschrieben.\n\n[[abschnitt]]\n\nMit freundlichen Grüßen\nIhr Skrift-Team' }); + await api('POST', '/items/muster_texts', { label: 'Du-Form', sort: 2, active: true, + text: 'Hallo [[Vorname]],\n\nschön, dass Du Skrift ausprobierst! Dieser Brief wurde von einem Roboter mit einem echten Stift geschrieben.\n\n[[abschnitt]]\n\nHerzliche Grüße\nDein Skrift-Team' }); + log('seed muster_texts'); + } +} + +// ── Rollen / Policies / Rechte (Directus 11) ──────────────────────────────── +const BIZ = ['products', 'formats', 'motifs', 'price_items', 'pricing_settings', + 'vouchers', 'voucher_redemptions', 'orders', 'order_entries', 'order_addons', 'jobs', 'status_history', + 'offer_requests', 'signatures', 'customer_discounts', 'customer_products', 'contacts', + 'email_templates', 'email_settings', 'muster_settings', 'muster_texts', 'machines', 'format_templates', 'render_formats', 'test_prints']; +// Kunde = Login-Konto: Aufträge hängen direkt am Nutzer. +const OWN_ORDER = { customer: { _eq: '$CURRENT_USER' } }; +const OWN_VIA_ORDER = { order: { customer: { _eq: '$CURRENT_USER' } } }; + +const CUSTOMER_ROLE_NAME = 'Kunde'; + +/** Benennt eine bestehende Rolle um (idempotent – tut nichts, wenn schon umbenannt). */ +async function renameRole(oldName, newName) { + const neu = await api('GET', `/roles?filter[name][_eq]=${encodeURIComponent(newName)}&limit=1`); + if (neu && neu.length) return; + const alt = await api('GET', `/roles?filter[name][_eq]=${encodeURIComponent(oldName)}&limit=1`); + if (alt && alt.length) { + await api('PATCH', `/roles/${alt[0].id}`, { name: newName }); + log('role umbenannt', `${oldName} → ${newName}`); + } +} + +async function ensureRole(name, icon) { + const roles = await api('GET', `/roles?filter[name][_eq]=${encodeURIComponent(name)}&limit=1`); + if (roles && roles.length) return roles[0]; + const r = await api('POST', '/roles', { name, icon }); + log('role +', name); + return r; +} +async function ensurePolicy(name, opts = {}) { + const ps = await api('GET', `/policies?filter[name][_eq]=${encodeURIComponent(name)}&limit=1`); + if (ps && ps.length) return ps[0]; + const p = await api('POST', '/policies', { name, app_access: !!opts.app, admin_access: !!opts.admin, enforce_tfa: false }); + log('policy +', name); + return p; +} +async function ensureAccess(roleId, policyId) { + const filt = roleId + ? `filter[role][_eq]=${roleId}&filter[policy][_eq]=${policyId}` + : `filter[role][_null]=true&filter[policy][_eq]=${policyId}`; + const a = await api('GET', `/access?${filt}&limit=1`); + if (a && a.length) return; + await api('POST', '/access', { role: roleId, policy: policyId }); + log('access +', `${roleId || 'public'} ↔ policy`); +} +/** + * Legt eine Berechtigung an ODER gleicht eine bestehende an. + * + * Wichtig: Früher wurde ein vorhandener Eintrag unangetastet gelassen. Dadurch + * blieben einmal angelegte, zu enge Feldlisten für immer bestehen – spätere + * Erweiterungen (z. B. production_status für den Produktions-Agent) kamen nie + * an und führten zu 403-Fehlern. Der Bootstrap ist die Quelle der Wahrheit, + * deshalb werden Felder und Filter jetzt aktiv nachgezogen. + */ +async function ensurePermission(policyId, collection, action, fields = ['*'], permissions = {}) { + const existing = await api('GET', + `/permissions?filter[policy][_eq]=${policyId}&filter[collection][_eq]=${collection}&filter[action][_eq]=${action}&limit=1&fields=id,fields,permissions`); + if (existing && existing.length) { + const cur = existing[0]; + const gleich = JSON.stringify(cur.fields ?? null) === JSON.stringify(fields) + && JSON.stringify(cur.permissions ?? {}) === JSON.stringify(permissions); + if (!gleich) { + await api('PATCH', `/permissions/${cur.id}`, { fields, permissions }); + log('perm ~', `${collection}.${action}`); + } + return; + } + await api('POST', '/permissions', { policy: policyId, collection, action, fields, permissions, validation: {} }); +} + +async function applyPermissions() { + console.log('› Rollen, Policies, Rechte'); + + // Staff: volle Verwaltung + const staffRole = await ensureRole('Staff', 'badge'); + const staffPol = await ensurePolicy('Staff', { app: true }); + await ensureAccess(staffRole.id, staffPol.id); + for (const col of BIZ) + for (const act of ['create', 'read', 'update', 'delete']) + await ensurePermission(staffPol.id, col, act); + + // Customer: nur Eigenes + Lesen der Kataloge + // Alt-Namen auf den finalen "Kunde" ziehen (idempotent). + await renameRole('Customer', CUSTOMER_ROLE_NAME); + await renameRole('Kunde (Login)', CUSTOMER_ROLE_NAME); + const custRole = await ensureRole(CUSTOMER_ROLE_NAME, 'person'); + const custPol = await ensurePolicy('Customer', { app: false }); + await ensureAccess(custRole.id, custPol.id); + // Kunde = eigenes Login-Konto: eigenes Profil lesen … + await ensurePermission(custPol.id, 'directus_users', 'read', + ['id', 'email', 'first_name', 'last_name', 'company', 'phone', 'person_type', 'addresses', 'billing_address', 'shipping_address', 'alt_emails'], + { id: { _eq: '$CURRENT_USER' } }); + // … und begrenzt selbst pflegen. person_type bewusst NICHT enthalten – die + // Einstufung privat/Unternehmen legt der Betreiber fest, nicht der Kunde. + await ensurePermission(custPol.id, 'directus_users', 'update', + ['first_name', 'last_name', 'company', 'phone', 'addresses', 'billing_address', 'shipping_address'], + { id: { _eq: '$CURRENT_USER' } }); + for (const act of ['create', 'read', 'update']) await ensurePermission(custPol.id, 'orders', act, ['*'], OWN_ORDER); + for (const col of ['order_entries', 'order_addons']) for (const act of ['create', 'read', 'update']) await ensurePermission(custPol.id, col, act, ['*'], OWN_VIA_ORDER); + await ensurePermission(custPol.id, 'status_history', 'read', ['*'], OWN_VIA_ORDER); + await ensurePermission(custPol.id, 'jobs', 'read', ['*'], OWN_VIA_ORDER); + // Eigene Produkt-Freischaltungen lesen (bestimmt, welche Produkte der Kunde + // im Konfigurator konfigurieren darf). + await ensurePermission(custPol.id, 'customer_products', 'read', ['*'], { customer: { _eq: '$CURRENT_USER' } }); + for (const col of ['products', 'formats', 'motifs', 'price_items', 'pricing_settings']) + await ensurePermission(custPol.id, col, 'read'); + // Datei-Upload: Motiv-Bilder und hochzuladende Dokumente (Unterschriftenservice). + await ensurePermission(custPol.id, 'directus_files', 'create'); + await ensurePermission(custPol.id, 'directus_files', 'read', ['*'], { uploaded_by: { _eq: '$CURRENT_USER' } }); + + // Public (Gast): nur aktive Kataloge lesen + const pubPol = await ensurePolicy('Public (Skrift)', { app: false }); + await ensureAccess(null, pubPol.id); + for (const col of ['products', 'formats', 'motifs', 'price_items']) + await ensurePermission(pubPol.id, col, 'read', ['*'], { active: { _eq: true } }); + await ensurePermission(pubPol.id, 'pricing_settings', 'read'); + + // Service (Backend + Produktion): Jobs/Orders lesen + Status schreiben + const svcRole = await ensureRole('Service', 'smart_toy'); + const svcPol = await ensurePolicy('Service', { app: false }); + await ensureAccess(svcRole.id, svcPol.id); + for (const col of ['orders', 'order_entries', 'order_addons', 'jobs', 'products', 'formats', + 'motifs', 'price_items', 'machines', 'format_templates', 'render_formats']) + await ensurePermission(svcPol.id, col, 'read'); + await ensurePermission(svcPol.id, 'orders', 'update', + ['status', 'artifact_path', 'payment_status', 'payment_ref', 'production_status', 'brief_gedruckt', 'kuvert_gedruckt']); + await ensurePermission(svcPol.id, 'jobs', 'create'); + // Agent meldet Druckfortschritt zurück. + await ensurePermission(svcPol.id, 'jobs', 'update', ['status', 'priority', 'error']); + // Agent meldet Maschinenzustand (Heartbeat). + await ensurePermission(svcPol.id, 'machines', 'update', ['status', 'last_seen']); + await ensurePermission(svcPol.id, 'status_history', 'create'); + // Hochgeladene Druckdateien lesen (Backend führt PDFs für den Charge-Sammeldruck + // zusammen und lädt sie dafür über /assets). + await ensurePermission(svcPol.id, 'directus_files', 'read'); + + console.log(' Hinweis: Für Service einen Nutzer in Rolle "Service" anlegen und dessen', + 'statischen Token in .env von Backend/Produktion eintragen.'); +} + +// ── Anzeigenamen (Klarheit im Admin) ──────────────────────────────────────── +async function applyLabels() { + console.log('› Anzeigenamen'); + const labels = { + orders: { de: ['Auftrag', 'Aufträge'], en: ['Order', 'Orders'] }, + order_entries: { de: ['Empfängerzeile', 'Empfängerzeilen'], en: ['Entry', 'Entries'] }, + price_items: { de: ['Preisposition', 'Preise'], en: ['Price item', 'Price items'] }, + products: { de: ['Produkt', 'Produkte'], en: ['Product', 'Products'] }, + motifs: { de: ['Motiv', 'Motive'], en: ['Motif', 'Motifs'] }, + vouchers: { de: ['Gutschein', 'Gutscheine'], en: ['Voucher', 'Vouchers'] }, + }; + for (const [collection, l] of Object.entries(labels)) { + try { + await api('PATCH', `/collections/${collection}`, { + meta: { translations: [ + { language: 'de-DE', translation: l.de[1], singular: l.de[0], plural: l.de[1] }, + { language: 'en-US', translation: l.en[1], singular: l.en[0], plural: l.en[1] }, + ] }, + }); + } catch (e) { console.warn(` Label ${collection} übersprungen: ${e.message}`); } + } +} + +// ── Navigation gruppieren ──────────────────────────────────────────────────── +// Hauptansicht bewusst schlank: nur Aufträge, Jobs, Gutscheine, Verlauf. +// Alles Konfigurations-artige (Produkte, Preise, Motive …) wandert in einen +// Ordner „Einstellungen"; reine Detail-/Technik-Collections werden versteckt. +async function organizeNav() { + console.log('› Navigation gruppieren'); + const FOLDER = 'einstellungen'; + + // Ordner (Collection ohne Tabelle) anlegen, falls noch nicht vorhanden. + let folderDa = true; + try { await api('GET', `/collections/${FOLDER}`); } catch { folderDa = false; } + if (!folderDa) { + await api('POST', '/collections', { + collection: FOLDER, schema: null, + meta: { icon: 'settings', note: 'Konfiguration: Produkte, Preise, Motive, Gutschein-Einlösungen …', + translations: [ + { language: 'de-DE', translation: 'Einstellungen', singular: 'Einstellung', plural: 'Einstellungen' }, + { language: 'en-US', translation: 'Settings', singular: 'Setting', plural: 'Settings' }, + ] }, + }); + log('folder +', FOLDER); + } + + const patch = async (col, meta) => { + try { await api('PATCH', `/collections/${col}`, { meta }); } + catch (e) { console.warn(` Nav ${col} übersprungen: ${e.message}`); } + }; + + // Hauptebene + for (const col of ['orders', 'jobs', 'vouchers', 'status_history', 'contacts']) + await patch(col, { group: null, hidden: false }); + // Unter „Einstellungen" + for (const col of ['products', 'formats', 'motifs', 'price_items', 'pricing_settings', 'offer_requests', + 'email_templates', 'email_settings', 'muster_settings', 'muster_texts', 'machines', 'format_templates', 'render_formats', 'test_prints']) + await patch(col, { group: FOLDER, hidden: false }); + // Reine Detail-/Technik-Collections aus der Navigation nehmen (Signaturen und + // Rabatte werden direkt am Kundenkonto gepflegt, nicht als eigener Menüpunkt). + // Empfängerzeilen werden direkt im Auftrag gepflegt (o2m) → keine eigene Seite. + for (const col of ['order_entries', 'order_addons', 'voucher_redemptions', 'preview_usage', + 'login_codes', 'signatures', 'customer_discounts', 'customer_products']) + await patch(col, { hidden: true }); +} + +// ── Anzeige-Vorlagen für Verknüpfungen ────────────────────────────────────── +// Ohne diese zeigt Directus bei m2o-Feldern nur die ID (z. B. Produkt „1"). +// Mit „related-values" + Template erscheint der aussagekräftige Wert. +async function applyDisplays() { + console.log('› Anzeige-Vorlagen (m2o)'); + const displays = [ + ['orders', 'product', '{{name}}'], + ['orders', 'format', '{{name}}'], + ['orders', 'motif', '{{name}}'], + ['orders', 'customer', '{{first_name}} {{last_name}}'], + ['orders', 'voucher', '{{code}}'], + ['formats', 'product', '{{name}}'], + ['jobs', 'order', '{{order_number}}'], + ['jobs', 'machine', '{{name}}'], + ['jobs', 'template', '{{name}}'], + ['test_prints', 'template', '{{name}}'], + ['test_prints', 'machine', '{{name}}'], + ['status_history', 'order', '{{order_number}}'], + ['order_entries', 'order', '{{order_number}}'], + ['order_addons', 'order', '{{order_number}}'], + ['order_addons', 'price_item', '{{label}}'], + ['signatures', 'customer', '{{first_name}} {{last_name}}'], + ['customer_discounts', 'customer', '{{first_name}} {{last_name}}'], + ['customer_products', 'customer', '{{first_name}} {{last_name}}'], + ['customer_products', 'product', '{{name}}'], + ['offer_requests', 'customer', '{{first_name}} {{last_name}}'], + ['voucher_redemptions', 'voucher', '{{code}}'], + ['contacts', 'source_order', '{{order_number}}'], + ]; + for (const [collection, field, template] of displays) { + try { + await api('PATCH', `/fields/${collection}/${field}`, { + meta: { display: 'related-values', display_options: { template } }, + }); + } catch (e) { console.warn(` Display ${collection}.${field} übersprungen: ${e.message}`); } + } +} + +// ── Altlasten entfernen ───────────────────────────────────────────────────── +// Ersetzt durch: eine gemeinsame `multiplier_formula` + `products.norm_qty`. +async function removeDeprecatedFields() { + console.log('› Alte Felder entfernen'); + const weg = [ + ['pricing_settings', 'multiplier_formula_business'], + ['pricing_settings', 'multiplier_formula_privat'], + ['pricing_settings', 'norm_qty_business'], + ['pricing_settings', 'norm_qty_privat'], + ['pricing_settings', 'min_qty_business'], + ['pricing_settings', 'min_qty_privat'], + ]; + for (const [col, fld] of weg) { + try { await api('DELETE', `/fields/${col}/${fld}`); log('field -', `${col}.${fld}`); } + catch { /* bereits entfernt */ } + } +} + +// ── Projektname ───────────────────────────────────────────────────────────── +// Directus nutzt den Projektnamen als ABSENDERNAMEN aller Mails. Steht hier +// „Directus", kommen die Mails auch so beim Kunden an. +async function applyProjectName() { + console.log('› Projektname'); + try { + await api('PATCH', '/settings', { project_name: 'Skrift' }); + log('settings', 'project_name = Skrift'); + } catch (e) { console.warn(` Projektname übersprungen: ${e.message}`); } +} + +// ── Auftrags-Übersicht (Produktion) ───────────────────────────────────────── +// Sammel-Anzeigevorlage + globaler Tabellen-Preset: auf einen Blick sieht man +// je Auftrag Nummer, Empfängeranzahl, Kuvert-Bedarf, Versandart und Bezahlt. +async function applyOrdersLayout() { + console.log('› Auftrags-Übersicht (Liste)'); + try { + await api('PATCH', '/collections/orders', { + meta: { display_template: '{{order_number}} · {{entries_count}}× · {{shipping_type}} · {{payment_status}}' }, + }); + } catch (e) { console.warn(` Sammel-Template orders übersprungen: ${e.message}`); } + + const spalten = ['order_number', 'customer', 'entries_count', 'needs_envelope', + 'shipping_type', 'payment_status', 'production_status', 'date_created']; + try { + const vorhanden = await api('GET', + '/presets?filter[collection][_eq]=orders&filter[role][_null]=true&filter[user][_null]=true&filter[bucket][_null]=true&limit=1'); + const preset = { + collection: 'orders', bucket: null, role: null, user: null, + layout: 'tabular', + layout_query: { tabular: { fields: spalten, sort: ['-date_created'], page: 1 } }, + layout_options: { tabular: { widths: {} } }, + }; + if (vorhanden && vorhanden[0]) await api('PATCH', `/presets/${vorhanden[0].id}`, preset); + else { await api('POST', '/presets', preset); log('preset +', 'orders (Übersicht)'); } + } catch (e) { console.warn(` Listen-Preset orders übersprungen: ${e.message}`); } +} + +// ── Insights-Dashboard „Übersicht" ────────────────────────────────────────── +// Zählt neue Aufträge, Anfragen und Musterbestellungen auf einen Blick. +async function applyDashboard() { + console.log('› Dashboard (Insights)'); + try { + let dash = (await api('GET', `/dashboards?filter[name][_eq]=${encodeURIComponent('Übersicht')}&limit=1`))?.[0]; + if (!dash) { + dash = await api('POST', '/dashboards', { + name: 'Übersicht', icon: 'dashboard', note: 'Neue Aufträge, Anfragen & Muster auf einen Blick.', + }); + log('dashboard +', 'Übersicht'); + } + const vorhanden = new Set(((await api('GET', `/panels?filter[dashboard][_eq]=${dash.id}&limit=-1&fields=name`)) || []).map((p) => p.name)); + const metric = (name, icon, collection, filter, x) => ({ + dashboard: dash.id, name, icon, type: 'metric', show_header: true, + position_x: x, position_y: 1, width: 6, height: 6, + options: { collection, field: 'id', function: 'count', filter }, + }); + const panels = [ + metric('Neue Aufträge', 'receipt_long', 'orders', { production_status: { _eq: 'eingegangen' } }, 1), + metric('Neue Anfragen', 'request_quote', 'offer_requests', { _and: [{ type: { _eq: 'angebot' } }, { status: { _eq: 'neu' } }] }, 7), + metric('Neue Muster', 'science', 'offer_requests', { _and: [{ type: { _eq: 'muster' } }, { status: { _eq: 'neu' } }] }, 13), + ]; + for (const p of panels) { + if (vorhanden.has(p.name)) continue; + try { await api('POST', '/panels', p); log('panel +', p.name); } + catch (e) { console.warn(` Panel ${p.name} übersprungen: ${e.message}`); } + } + } catch (e) { console.warn(' Dashboard übersprungen (bitte melden):', e.message); } +} + +// ── Main ──────────────────────────────────────────────────────────────────── +(async () => { + await login(); + console.log(`Bootstrap gegen ${DIRECTUS_URL}`); + await applySchema(); + await applySeed(); + await applyLabels(); + await organizeNav(); + await applyDisplays(); + await removeDeprecatedFields(); + await applyProjectName(); + await applyOrdersLayout(); + await applyDashboard(); + if (SKIP_PERMISSIONS) console.log('› Rechte übersprungen (SKIP_PERMISSIONS=1)'); + else await applyPermissions(); + console.log('✓ Fertig.'); +})().catch((e) => { console.error('\n✗ Abbruch:', e.message); process.exit(1); }); diff --git a/bootstrap/package.json b/bootstrap/package.json new file mode 100644 index 0000000..ead33e1 --- /dev/null +++ b/bootstrap/package.json @@ -0,0 +1,13 @@ +{ + "name": "skrift-directus-bootstrap", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Idempotentes Anlegen von Collections, Rollen, Rechten und Seed-Daten in Directus.", + "scripts": { + "bootstrap": "node bootstrap.mjs" + }, + "engines": { + "node": ">=18" + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..45fd84c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,108 @@ +# Directus + Postgres — Daten-/Auth-/Admin-Schicht für Skrift. +# +# Hinter dem Nginx Proxy Manager (kein Host-Port; NPM proxyt intern per container_name). +# Im NPM als Proxy Host anlegen: +# Domain Names : admin.skrift.de (PUBLIC_URL in .env muss dazu passen) +# Scheme : http +# Forward Hostname : skrift-directus +# Forward Port : 8055 +# SSL : Let's-Encrypt-Zertifikat aktivieren +# +# Start: cp .env.example .env → Werte setzen → docker compose up -d + +services: + database: + image: postgres:16-alpine + container_name: skrift-directus-db + restart: unless-stopped + volumes: + - directus-db:/var/lib/postgresql/data + environment: + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_DATABASE} + healthcheck: + test: ["CMD", "pg_isready", "-U", "${DB_USER}", "-d", "${DB_DATABASE}"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - internal + + directus: + image: directus/directus:11 + container_name: skrift-directus + restart: unless-stopped + depends_on: + database: + condition: service_healthy + volumes: + - directus-uploads:/directus/uploads + # Bind-Mount: Extensions kommen aus dem Repo-Ordner ./extensions + - ./extensions:/directus/extensions + # Generierte Auftragsdateien read-only einblenden (gleicher Ordner wie + # das Backend beschreibt / SFTP-Ziel) – für Direktzugriff statt Kopie. + - /var/skrift-output:/var/skrift-output:ro + environment: + SECRET: ${DIRECTUS_SECRET} + + DB_CLIENT: pg + DB_HOST: database + DB_PORT: 5432 + DB_DATABASE: ${DB_DATABASE} + DB_USER: ${DB_USER} + DB_PASSWORD: ${DB_PASSWORD} + + # Erster Admin – wird nur beim allerersten Start angelegt + ADMIN_EMAIL: ${ADMIN_EMAIL} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + + PUBLIC_URL: ${PUBLIC_URL} + + # CORS für das Frontend (Portal/Konfigurator) + CORS_ENABLED: "true" + CORS_ORIGIN: ${CORS_ORIGIN} + + # E-Mail: für passwortlosen Login-Code + Benachrichtigungen (Flows) + EMAIL_FROM: ${EMAIL_FROM} + EMAIL_TRANSPORT: smtp + EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST} + EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT} + EMAIL_SMTP_USER: ${EMAIL_SMTP_USER} + EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD} + EMAIL_SMTP_SECURE: ${EMAIL_SMTP_SECURE} + + # Skrift-Backend (SVG-Generierung: Vorschau + finaler Auftrag). + # SKRIFT_BACKEND_TOKEN MUSS dem API_TOKEN des Backends entsprechen, + # sonst antwortet das Backend mit 401. + SKRIFT_BACKEND_URL: ${SKRIFT_BACKEND_URL:-http://skrift-backend:4000} + SKRIFT_BACKEND_TOKEN: ${SKRIFT_BACKEND_TOKEN} + SKRIFT_PREVIEW_LIMIT: ${SKRIFT_PREVIEW_LIMIT:-10} + SKRIFT_TEAM_EMAIL: ${SKRIFT_TEAM_EMAIL:-hello@skrift.de} + + # Shared Secret für den WordPress-Webhook (JetFormBuilder → /skrift-orders/inbound/*). + # Muss identisch als ?token=... in der Webhook-URL stehen. + SKRIFT_WEBHOOK_TOKEN: ${SKRIFT_WEBHOOK_TOKEN} + + # Signatur-Plotter-Service (Vorschau/Render im Unterschriftenservice-Modul). + SKRIFT_SIGN_URL: ${SKRIFT_SIGN_URL:-http://skrift-signature-service:8000} + + # PayPal – server-seitige Zahlungsprüfung (Secret liegt NUR hier, nie im Frontend) + PAYPAL_CLIENT_ID: ${PAYPAL_CLIENT_ID} + PAYPAL_CLIENT_SECRET: ${PAYPAL_CLIENT_SECRET} + PAYPAL_ENV: ${PAYPAL_ENV:-sandbox} + expose: + - "8055" + networks: + - internal + - npm + +volumes: + directus-db: + directus-uploads: + +networks: + internal: + npm: + name: nginx-proxy-manager_default + external: true diff --git a/extensions/directus-extension-skrift-api/dist/index.js b/extensions/directus-extension-skrift-api/dist/index.js new file mode 100644 index 0000000..916fbd9 --- /dev/null +++ b/extensions/directus-extension-skrift-api/dist/index.js @@ -0,0 +1,572 @@ +/** + * Skrift – Public-API (v1) für Kunden + * =========================================================================== + * Eigener, versionierter API-Namespace, gedacht hinter einer eigenen Domain + * (z. B. api.skrift.de → NPM proxyt auf /skrift-api/*). Der Kunde sieht NIE das + * Directus-Dashboard. + * + * POST /v1/orders – Auftrag anlegen (Brief/Postkarte: Text ODER Datei) + * GET /v1/orders/:nummer – Status abfragen (wartend | in_bearbeitung | versendet) + * POST /v1/files – Druckdatei hochladen (Base64) → file_id + * GET /v1/openapi.json – OpenAPI-Spezifikation + * GET /docs – interaktive Doku (Scalar) + * POST /v1/clients – (Admin) neuen API-Zugang + Key erzeugen + * + * Auth: Header `X-Api-Key: ` (NICHT Authorization – den reserviert Directus). + * Gespeichert wird nur der SHA-256-Hash (api_clients). Jeder Zugang ist an GENAU + * EIN Produkt gebunden. + */ +import crypto from 'node:crypto'; +import { Readable } from 'node:stream'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +// Verzeichnis dieser Extension (für die selbst gehosteten Swagger-UI-Assets). +const EXT_DIR = path.dirname(fileURLToPath(import.meta.url)); + +const BACKEND_URL = (process.env.SKRIFT_BACKEND_URL || 'http://skrift-backend:4000').replace(/\/$/, ''); +const BACKEND_TOKEN = process.env.SKRIFT_BACKEND_TOKEN || ''; +const STORAGE = (process.env.STORAGE_LOCATIONS || 'local').split(',')[0].trim() || 'local'; + +const sha256 = (s) => crypto.createHash('sha256').update(String(s)).digest('hex'); +const pad3 = (n) => String(n).padStart(3, '0'); +const WOCHENTAGE = ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag']; + +/** + * Internal order → public status (pending | processing | shipped | cancelled). + * Der Betreiber steuert im Produktions-Board `production_status`; der kaufmännische + * `status` dient als Rückfall. Beide werden berücksichtigt. + */ +function kundenStatus(order) { + const ps = String(order?.production_status || ''); + const s = String(order?.status || ''); + if (ps === 'storniert' || s === 'storniert') return 'cancelled'; + if (ps === 'versendet' || s === 'versendet' || s === 'abgeschlossen') return 'shipped'; + if (['im_druck', 'kuvertieren', 'versandfertig'].includes(ps) || ['in_produktion', 'gedruckt'].includes(s)) return 'processing'; + return 'pending'; +} + +// Selbst ausgelieferte HTML-Doku (kein externes Script → CSP-sicher). Inline-CSS. +const DOCS_HTML = ` + +Skrift API Reference + +
+

Skrift API Reference

+

Handwritten mail as a service · API v1 · Base URL https://dev.skrift.de

+ +

Overview

+
+

REST API over HTTPS. Request and response bodies are JSON (Content-Type: application/json, UTF-8). An order yields one document and/or one envelope per recipient; the quantity is derived from the number of recipients. One or more products are bound to your API key; each order selects one via the product field.

+
+ +

Authentication

+
+

Every request must include your API key in the X-Api-Key header:

+
X-Api-Key: <API_KEY>
+

Each key is scoped to exactly one product. Keys are secrets — never expose them in client-side code.

+
+ +

Errors

+
+

Errors use standard HTTP status codes and a uniform body:

+
{ "error": "human-readable message" }
+ + + + + + + + + +
StatusMeaning
200 / 201Success / order created
400Invalid request (missing or invalid fields)
401Missing or invalid API key
404Resource not found
413Payload too large (file > 80 MB)
415Unsupported media type (only PDF is accepted)
500Internal error
+
+ +

Order status

+
+

The status field returns one of:

+pending received, not yet in production +processing being written / printed +shipped dispatched +cancelled cancelled +
+ +

Create an order

+
+
POST /v1/orders
+

Creates an order and returns its order number.

+

Request body

+ + + + + + + + + + + + +
FieldTypeDescription
productstringProduct key to use. Required if your key allows multiple products; optional (auto) if exactly one.
recipientsarrayRequired. One entry per recipient; count = quantity. Address as free_text (up to 5 lines, separated by \\n).
document_formatstringDocument format: a4, a6h or a6l.
fontstringtilda, alva or ellie.
realisticbooleanNatural handwriting variation. Default true.
shipping_typestringbulk (consolidated shipment to you; default) or single (direct to each recipient).
shipping_daystringPreferred dispatch weekday, e.g. montag (optional).
letter.textstringLetter body, fully written out — no placeholders. Long text flows across multiple pages automatically; [[seitenumbruch]] forces a page break.
letter.filesarrayfile_id(s) from POST /v1/files (file / PDF products).
envelope.modestringnone (no envelope) or recipient (recipient address on the envelope). Envelope size is selected automatically: A4 → DIN Lang, otherwise C6.
+

Example — text letter

+
curl -X POST https://dev.skrift.de/v1/orders \\
+  -H "X-Api-Key: <KEY>" -H "Content-Type: application/json" \\
+  -d '{
+    "product":"briefe","document_format":"a4","font":"tilda","realistic":true,
+    "shipping_type":"bulk","shipping_day":"montag",
+    "letter":{"text":"Dear Anna,\\n\\nthank you for ..."},
+    "envelope":{"mode":"recipient"},
+    "recipients":[
+      {"free_text":"Anna Meier\\nMusterstr. 1\\n12345 Musterstadt"}
+    ]
+  }'
+

Example — print uploaded PDFs (file product)

+
curl -X POST https://dev.skrift.de/v1/orders \\
+  -H "X-Api-Key: <KEY>" -H "Content-Type: application/json" \\
+  -d '{"document_format":"a4","letter":{"files":["<file_id>"]},
+       "envelope":{"mode":"recipient"},
+       "recipients":[{"free_text":"Anna Meier\\nMusterstr. 1\\n12345 Musterstadt"}]}'
+

Example — address envelopes only

+
curl -X POST https://dev.skrift.de/v1/orders \\
+  -H "X-Api-Key: <KEY>" -H "Content-Type: application/json" \\
+  -d '{"envelope":{"mode":"recipient"},
+       "recipients":[{"free_text":"Anna Meier\\nMusterstr. 1\\n12345 Musterstadt"}]}'
+

Response · 201

+
{ "order_number": "18-08-26-001", "status": "pending" }
+
+ +

Retrieve order status

+
+
GET /v1/orders/{order_number}
+

Returns the current status of one of your orders. status_since is the ISO 8601 timestamp (UTC) since which the order has been in its current status.

+
curl https://dev.skrift.de/v1/orders/18-08-26-001 -H "X-Api-Key: <KEY>"
+
+{ "order_number":"18-08-26-001", "status":"shipped", "status_since":"2026-08-20T09:14:00.000Z", "recipients":1 }
+
+ +

Upload a PDF

+
+
POST /v1/files
+

Uploads a base64-encoded print file. PDF only, max. 80 MB. Returns a file_id to reference in letter.files.

+
curl -X POST https://dev.skrift.de/v1/files \\
+  -H "X-Api-Key: <KEY>" -H "Content-Type: application/json" \\
+  -d '{"filename":"letter.pdf","content_base64":"<BASE64>"}'
+
+{ "file_id": "..." }
+
+ +

Machine-readable specification: OpenAPI (JSON) — import into Postman, Insomnia, or any OpenAPI client.

+
`; + +// Swagger UI (selbst gehostet). Assets liegen als swagger-ui.css + swagger-ui-bundle.js +// im Extension-Ordner; init.js wird generiert. Kein CDN → CSP-/Brave-sicher. +const SWAGGER_HTML = ` + +Skrift API Reference + + + +
+ + +`; + +const INIT_JS = "window.addEventListener('DOMContentLoaded',function(){window.ui=SwaggerUIBundle({url:'v1/openapi.json',dom_id:'#swagger-ui',deepLinking:true,presets:[SwaggerUIBundle.presets.apis],layout:'BaseLayout'});});"; + +const handler = (router, { services, getSchema, logger }) => { + const { ItemsService, FilesService } = services; + const svcFactory = (schema) => (c) => new ItemsService(c, { schema, accountability: null }); + + /** Zeichen-Whitelist (wie im übrigen System) als Sanitizer laden. */ + async function ladeClean(schema) { + try { + const ps = await new ItemsService('pricing_settings', { schema, accountability: null }) + .readSingleton({ fields: ['char_whitelist'] }); + const wl = ps?.char_whitelist; + const re = wl ? new RegExp(`[^${wl}\\n\\r\\t]`, 'g') : null; + return (v) => (typeof v === 'string' && re ? v.replace(re, '') : v); + } catch { return (v) => v; } + } + + /** API-Key aus dem X-Api-Key-Header lesen und den aktiven Zugang finden. + * (NICHT Authorization: Bearer – den reserviert Directus für eigene Tokens + * und lehnt fremde Werte global mit INVALID_CREDENTIALS ab.) */ + async function authClient(req) { + const raw = String(req.headers['x-api-key'] || '').trim(); + if (!raw) return null; + const schema = await getSchema(); + const rows = await new ItemsService('api_clients', { schema, accountability: null }).readByQuery({ + filter: { key_hash: { _eq: sha256(raw) }, active: { _eq: true } }, + limit: 1, + fields: ['id', 'name', 'customer', 'webhook_url', 'config', + 'product.id', 'product.key', 'product.type', 'product.input_mode', + 'products.product.id', 'products.product.key', 'products.product.type', 'products.product.input_mode'], + }); + const client = rows?.[0] || null; + if (client) { + // Letzte Nutzung vermerken (best effort, nicht blockierend). + new ItemsService('api_clients', { schema, accountability: null }) + .updateOne(client.id, { last_used: new Date().toISOString() }).catch(() => {}); + } + return client; + } + + const fehler = (res, code, msg) => res.status(code).json({ error: msg }); + + // ── POST /v1/files ───────────────────────────────────────────────────────── + // Body: { filename, content_base64 } → { file_id }. NUR PDF (Sicherheit). + router.post('/v1/files', async (req, res) => { + const client = await authClient(req); + if (!client) return fehler(res, 401, 'Missing or invalid API key.'); + const { filename, content_base64 } = req.body || {}; + if (!filename || !content_base64) return fehler(res, 400, 'filename and content_base64 are required.'); + if (!/\.pdf$/i.test(String(filename))) return fehler(res, 415, 'Only PDF files are accepted (filename must end in .pdf).'); + let buf; + try { buf = Buffer.from(String(content_base64), 'base64'); } catch { return fehler(res, 400, 'content_base64 is not valid base64.'); } + if (!buf.length) return fehler(res, 400, 'File is empty.'); + if (buf.length > 80 * 1024 * 1024) return fehler(res, 413, 'File too large (max. 80 MB).'); + // Inhalts-Prüfung: echte PDF-Signatur, nicht nur die Endung. + if (buf.slice(0, 5).toString('latin1') !== '%PDF-') return fehler(res, 415, 'File is not a valid PDF.'); + try { + const schema = await getSchema(); + const filesSvc = new FilesService({ schema, accountability: null }); + const id = await filesSvc.uploadOne(Readable.from(buf), { + storage: STORAGE, + filename_download: String(filename), + title: String(filename), + type: 'application/pdf', + }); + return res.json({ file_id: id }); + } catch (err) { + logger.error(`[skrift-api] files: ${err.stack || err.message}`); + return fehler(res, 500, 'File upload failed.'); + } + }); + + // ── POST /v1/orders ───────────────────────────────────────────────────────── + router.post('/v1/orders', async (req, res) => { + const client = await authClient(req); + if (!client) return fehler(res, 401, 'Missing or invalid API key.'); + + const body = req.body || {}; + + // Erlaubte Produkte des Keys: m2m-Liste + (Fallback) Einzelprodukt, dedupliziert. + const erlaubt = {}; + if (Array.isArray(client.products)) for (const j of client.products) if (j && j.product && j.product.id != null) erlaubt[j.product.id] = j.product; + if (client.product && client.product.id != null) erlaubt[client.product.id] = client.product; + const erlaubteListe = Object.values(erlaubt); + if (!erlaubteListe.length) return fehler(res, 409, 'No product is assigned to this API key.'); + + // Produktwahl: body.product (Key) muss erlaubt sein; bei genau einem Produkt optional. + const gewuenscht = String(body.product || '').trim(); + let product; + if (gewuenscht) { + product = erlaubteListe.find((p) => String(p.key) === gewuenscht); + if (!product) return fehler(res, 400, `product "${gewuenscht}" is not allowed for this key. Allowed: ${erlaubteListe.map((p) => p.key).join(', ')}.`); + } else if (erlaubteListe.length === 1) { + product = erlaubteListe[0]; + } else { + return fehler(res, 400, `Field "product" is required. Allowed: ${erlaubteListe.map((p) => p.key).join(', ')}.`); + } + + const recipients = Array.isArray(body.recipients) ? body.recipients : []; + if (!recipients.length) return fehler(res, 400, 'At least one recipient is required.'); + if (recipients.length > 5000) return fehler(res, 400, 'Too many recipients (max. 5000).'); + + const istKuvertOnly = product.type === 'envelope'; + const istDatei = product.input_mode === 'datei'; + const letter = body.letter || {}; + const files = Array.isArray(letter.files) ? letter.files.filter(Boolean) : []; + // Kuvert-only: kein Brief nötig (nur adressierte Kuverts); PDF-Dateien optional. + if (!istKuvertOnly) { + if (istDatei && !files.length) return fehler(res, 400, 'This product requires uploaded print files (letter.files).'); + if (!istDatei && !String(letter.text || '').trim()) return fehler(res, 400, 'letter.text is required.'); + } + + try { + const schema = await getSchema(); + const svc = svcFactory(schema); + const clean = await ladeClean(schema); + + // Schriftstückformat: nur A4 / A6H / A6L (freundliche Werte → interne Keys). + const FORMAT_MAP = { a4: 'a4', a6h: 'a6_hoch', a6l: 'a6_quer', a6_hoch: 'a6_hoch', a6_quer: 'a6_quer' }; + const fmtKey = FORMAT_MAP[String(body.document_format || '').trim().toLowerCase()] || null; + if (!fmtKey && !istKuvertOnly) return fehler(res, 400, 'document_format must be a4, a6h or a6l.'); + let formatId = null; + if (fmtKey) { + const fr = await svc('formats').readByQuery({ filter: { key: { _eq: fmtKey } }, limit: 1, fields: ['id'] }); + formatId = fr?.[0]?.id ?? null; + if (!formatId) return fehler(res, 400, `Format ${fmtKey} is not active.`); + } + + // Kuvert: NUR "recipient" (Empfängeradresse) oder "none" (gar kein Kuvert). + const envMode = String((body.envelope || {}).mode || '').toLowerCase() === 'recipient' + ? 'recipient' : (istKuvertOnly ? 'recipient' : 'none'); + // Kuvertformat automatisch aus dem Dokumentformat: A4 → DIN Lang, sonst C6. + const envFormat = envMode === 'none' ? null : (fmtKey === 'a4' ? 'dinlang' : 'c6'); + const hatDateien = files.length > 0; + + const font = ['tilda', 'alva', 'ellie'].includes(body.font) ? body.font : 'tilda'; + // Versandart nur Englisch: "single" (direkt an Empfänger) / "bulk" (Sammelversand an dich). + const shippingType = String(body.shipping_type || '').toLowerCase() === 'single' ? 'einzeln' : 'sammel'; + // Gewünschter Versandtag (optional), z. B. "montag". + const shippingDay = WOCHENTAGE.includes(String(body.shipping_day || '').toLowerCase()) + ? String(body.shipping_day).toLowerCase() : null; + + const orderData = { + api_client: client.id, + customer: client.customer || null, + customer_email: (client.config && client.config.email) || null, + product: product.id, + format: formatId, + person_type: 'unternehmen', + font, + realistic: body.realistic !== false, + source: 'api', + status: 'in_queue', + production_status: 'eingegangen', + payment_status: 'offen', + payment_method: 'rechnung', + shipping_type: shippingType, + needs_envelope: envMode === 'recipient', + envelope_labeling: envMode === 'recipient' ? 'empfaenger' : 'keine', + envelope_text: null, + envelope_format: envFormat, + // Kein Brieftext bei Datei- oder Kuvert-only-Produkten. + text_template: (istDatei || istKuvertOnly) ? null : clean(String(letter.text || '')), + // Hochgeladene PDF-Briefe (Datei-Produkt ODER optional bei Kuvert-only). + source_files: (istDatei || (istKuvertOnly && hatDateien)) ? files : null, + source_file: (istDatei || (istKuvertOnly && hatDateien)) ? (files[0] || null) : null, + entries_count: recipients.length, + shipping_day: shippingDay, + // Mehrseitigkeit läuft selbstständig (Auto-Fluss); nicht vom Kunden wählbar. + multi_page: true, + // Schriftgröße nicht vom Kunden wählbar. + font_scale_letter: 1, + font_scale_envelope: 1, + }; + + // Auftragsnummer (Tages-Präfix) mit Kollisions-Wiederholung. + const jt = new Date(); + const praefix = `${String(jt.getDate()).padStart(2, '0')}-${String(jt.getMonth() + 1).padStart(2, '0')}-${String(jt.getFullYear()).slice(2)}`; + const naechsteNummer = async () => { + const heutige = await svc('orders').readByQuery({ filter: { order_number: { _starts_with: `${praefix}-` } }, limit: -1, fields: ['id'] }); + return `${praefix}-${pad3((heutige?.length ?? 0) + 1)}`; + }; + + let orderId, orderNumber; + for (let v = 0; v < 6; v += 1) { + orderNumber = await naechsteNummer(); + try { orderId = await svc('orders').createOne({ order_number: orderNumber, ...orderData }); break; } + catch (e) { if (v === 5 || !/unique|duplicate|bereits|exists/i.test(String(e?.message || ''))) throw e; } + } + + // Empfängerzeilen – Briefnummer wird vom System vergeben. + const entriesSvc = svc('order_entries'); + let n = 0; + for (const e of recipients) { + n += 1; + await entriesSvc.createOne({ + order: orderId, letter_number: n, + salutation: clean(e.salutation ?? null), first_name: clean(e.first_name ?? null), last_name: clean(e.last_name ?? null), + street: clean(e.street ?? null), house_no: clean(e.house_no ?? null), zip: clean(e.zip ?? null), + city: clean(e.city ?? null), country: clean(e.country ?? null), free_text: clean(e.free_text ?? null), + // Keine Platzhalter über die API – der Brieftext wird 1:1 verwendet. + placeholders: null, + }); + } + + await svc('status_history').createOne({ order: orderId, status: 'eingegangen', note: 'Über die Public-API angelegt.' }).catch(() => {}); + + // Generierung IMMER anstoßen (fire-and-forget) – für jedes Produkt. Das + // Backend entscheidet, was zu erzeugen ist: Schriftstücke bei Handschrift- + // Produkten, Kuverts immer wenn gewünscht; bei Datei-Produkten (z. B. + // Unterschriftenservice) NUR die Kuverts. Ohne zu Erzeugendes = No-Op. + fetch(`${BACKEND_URL}/api/order/from-directus`, { + method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Token': BACKEND_TOKEN }, + body: JSON.stringify({ orderId }), + }).catch((e) => logger.warn(`[skrift-api] Generierung nicht gestartet: ${e.message}`)); + + return res.status(201).json({ order_number: orderNumber, status: 'pending' }); + } catch (err) { + logger.error(`[skrift-api] orders: ${err.stack || err.message}`); + return fehler(res, 500, 'Order could not be created.'); + } + }); + + // ── GET /v1/orders/:nummer ────────────────────────────────────────────────── + router.get('/v1/orders/:nummer', async (req, res) => { + const client = await authClient(req); + if (!client) return fehler(res, 401, 'Missing or invalid API key.'); + try { + const schema = await getSchema(); + const rows = await new ItemsService('orders', { schema, accountability: null }).readByQuery({ + // Nur eigene Aufträge des Zugangs. + filter: { order_number: { _eq: String(req.params.nummer) }, api_client: { _eq: client.id } }, + limit: 1, fields: ['order_number', 'status', 'production_status', 'production_status_changed_at', + 'versandt_am', 'entries_count', 'date_created'], + }); + const order = rows?.[0]; + if (!order) return fehler(res, 404, 'Order not found.'); + const status = kundenStatus(order); + // Seit wann der Status so ist: Zeitpunkt der letzten Produktionsstatus- + // Änderung; bei „shipped" ersatzweise der Versandzeitpunkt, sonst Anlage. + const statusSince = order.production_status_changed_at + || (status === 'shipped' ? order.versandt_am : null) + || order.date_created || null; + return res.json({ + order_number: order.order_number, + status, + status_since: statusSince, + recipients: order.entries_count ?? null, + created_at: order.date_created ?? null, + }); + } catch (err) { + logger.error(`[skrift-api] status: ${err.stack || err.message}`); + return fehler(res, 500, 'Failed to retrieve order status.'); + } + }); + + // ── POST /v1/clients (Admin) – neuen Zugang + Key erzeugen ─────────────────── + // Nur mit Directus-Admin-Token/Session. Der Klartext-Key wird EINMALIG geliefert. + router.post('/v1/clients', async (req, res) => { + if (!req.accountability || req.accountability.admin !== true) return fehler(res, 403, 'Administrators only.'); + const { name, product, products, customer, webhook_url } = req.body || {}; + // Mehrere Produkte (Array von IDs) bevorzugt; „product" (einzeln) als Kurzform. + const prodIds = Array.isArray(products) ? products.filter((x) => x != null) : (product != null ? [product] : []); + if (!name || !prodIds.length) return fehler(res, 400, 'name and products (array of product IDs) are required.'); + try { + const schema = await getSchema(); + const key = `sk_live_${crypto.randomBytes(24).toString('base64url')}`; + const id = await new ItemsService('api_clients', { schema, accountability: null }).createOne({ + name: String(name), products: prodIds.map((pid) => ({ product: pid })), + customer: customer || null, webhook_url: webhook_url || null, + key_hash: sha256(key), key_prefix: key.slice(0, 14), active: true, + }); + // Klartext-Key nur JETZT – wird nirgends gespeichert. + return res.status(201).json({ id, name, api_key: key, note: 'Store this key securely — it will not be shown again.' }); + } catch (err) { + logger.error(`[skrift-api] clients: ${err.stack || err.message}`); + return fehler(res, 500, 'API client could not be created.'); + } + }); + + // ── OpenAPI + Doku ────────────────────────────────────────────────────────── + const OPENAPI = { + openapi: '3.0.3', + info: { title: 'Skrift API', version: '1.0.0', description: 'Handwritten mail as a service. Authentication: API key in the X-Api-Key header. Bodies are JSON (UTF-8).' }, + servers: [{ url: 'https://dev.skrift.de' }], + components: { + securitySchemes: { ApiKey: { type: 'apiKey', in: 'header', name: 'X-Api-Key' } }, + schemas: { + Recipient: { + type: 'object', + properties: { + free_text: { type: 'string', description: 'Recipient address as free text, up to 5 lines separated by \\n.' }, + salutation: { type: 'string' }, first_name: { type: 'string' }, last_name: { type: 'string' }, + street: { type: 'string' }, house_no: { type: 'string' }, zip: { type: 'string' }, city: { type: 'string' }, country: { type: 'string' }, + }, + }, + OrderRequest: { + type: 'object', required: ['recipients'], + properties: { + product: { type: 'string', description: 'Product key to use. Required if the API key is bound to more than one product; optional (auto) if exactly one.' }, + document_format: { type: 'string', enum: ['a4', 'a6h', 'a6l'], description: 'Document format.' }, + font: { type: 'string', enum: ['tilda', 'alva', 'ellie'] }, + realistic: { type: 'boolean', default: true, description: 'Natural handwriting variation.' }, + shipping_type: { type: 'string', enum: ['single', 'bulk'], default: 'bulk', description: 'single = direct to each recipient; bulk = consolidated shipment to you.' }, + shipping_day: { type: 'string', enum: ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'], description: 'Preferred dispatch weekday (optional).' }, + letter: { + type: 'object', + properties: { + text: { type: 'string', description: 'Letter body, fully written out (no placeholders). Long text flows across multiple pages automatically; [[seitenumbruch]] forces a page break.' }, + files: { type: 'array', items: { type: 'string' }, description: 'file_id(s) from POST /v1/files (file / PDF products).' }, + }, + }, + envelope: { + type: 'object', + properties: { + mode: { type: 'string', enum: ['none', 'recipient'], default: 'none', description: 'none = no envelope; recipient = recipient address on the envelope. Envelope size is selected automatically (A4 → DIN Lang, otherwise C6).' }, + }, + }, + recipients: { type: 'array', items: { $ref: '#/components/schemas/Recipient' } }, + }, + }, + }, + }, + security: [{ ApiKey: [] }], + paths: { + '/v1/orders': { + post: { + summary: 'Create an order', description: 'Quantity equals the number of recipients. Returns the order number.', + requestBody: { required: true, content: { 'application/json': { schema: { $ref: '#/components/schemas/OrderRequest' } } } }, + responses: { 201: { description: 'Order created', content: { 'application/json': { schema: { type: 'object', properties: { order_number: { type: 'string' }, status: { type: 'string' } } } } } } }, + }, + }, + '/v1/orders/{order_number}': { + get: { + summary: 'Retrieve order status', parameters: [{ name: 'order_number', in: 'path', required: true, schema: { type: 'string' } }], + responses: { 200: { description: 'Order status', content: { 'application/json': { schema: { type: 'object', properties: { order_number: { type: 'string' }, status: { type: 'string', enum: ['pending', 'processing', 'shipped', 'cancelled'] }, status_since: { type: 'string', format: 'date-time', description: 'ISO 8601 timestamp since which the order has held its current status.' }, recipients: { type: 'integer' } } } } } } }, + }, + }, + '/v1/files': { + post: { + summary: 'Upload a PDF (PDF only, max. 80 MB)', + requestBody: { required: true, content: { 'application/json': { schema: { type: 'object', required: ['filename', 'content_base64'], properties: { filename: { type: 'string', description: 'Must end in .pdf.' }, content_base64: { type: 'string', description: 'PDF as base64.' } } } } } }, + responses: { 200: { description: 'Uploaded', content: { 'application/json': { schema: { type: 'object', properties: { file_id: { type: 'string' } } } } } } }, + }, + }, + }, + }; + + router.get('/v1/openapi.json', (_req, res) => res.json(OPENAPI)); + + router.get('/docs', (_req, res) => { + // Swagger UI, wenn die Assets im Extension-Ordner liegen; sonst die statische + // HTML-Doku als Fallback (nie leer). Beides CSP-/Brave-sicher (kein CDN). + let hasSwagger = false; + try { hasSwagger = fs.existsSync(path.join(EXT_DIR, 'swagger-ui-bundle.js')); } catch { /* ignore */ } + res.type('html').send(hasSwagger ? SWAGGER_HTML : DOCS_HTML); + }); + + // Statische Doku-Assets (Swagger UI) – von der eigenen Domain, whitelisted. + router.get('/docs-assets/:file', (req, res) => { + const name = String(req.params.file || ''); + if (name === 'init.js') { res.type('application/javascript').send(INIT_JS); return; } + const TYPES = { 'swagger-ui.css': 'text/css', 'swagger-ui-bundle.js': 'application/javascript' }; + if (!TYPES[name]) return res.status(404).json({ error: 'Not found.' }); + try { + const buf = fs.readFileSync(path.join(EXT_DIR, name)); + res.setHeader('Content-Type', TYPES[name]); + res.setHeader('Cache-Control', 'public, max-age=86400'); + return res.send(buf); + } catch { + return res.status(404).json({ error: 'Docs asset missing – place swagger-ui.css and swagger-ui-bundle.js in the extension folder.' }); + } + }); +}; + +// Objekt-Form mit fester id → Mount unter /skrift-api (wie skrift-orders). +export default { id: 'skrift-api', handler }; diff --git a/extensions/directus-extension-skrift-api/dist/swagger-ui-bundle.js b/extensions/directus-extension-skrift-api/dist/swagger-ui-bundle.js new file mode 100644 index 0000000..d69f6eb --- /dev/null +++ b/extensions/directus-extension-skrift-api/dist/swagger-ui-bundle.js @@ -0,0 +1,2 @@ +/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ +!function webpackUniversalModuleDefinition(s,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.SwaggerUIBundle=o():s.SwaggerUIBundle=o()}(this,(()=>(()=>{var s={67526(s,o){"use strict";o.byteLength=function byteLength(s){var o=getLens(s),i=o[0],a=o[1];return 3*(i+a)/4-a},o.toByteArray=function toByteArray(s){var o,i,_=getLens(s),w=_[0],x=_[1],C=new u(function _byteLength(s,o,i){return 3*(o+i)/4-i}(0,w,x)),j=0,L=x>0?w-4:w;for(i=0;i>16&255,C[j++]=o>>8&255,C[j++]=255&o;2===x&&(o=a[s.charCodeAt(i)]<<2|a[s.charCodeAt(i+1)]>>4,C[j++]=255&o);1===x&&(o=a[s.charCodeAt(i)]<<10|a[s.charCodeAt(i+1)]<<4|a[s.charCodeAt(i+2)]>>2,C[j++]=o>>8&255,C[j++]=255&o);return C},o.fromByteArray=function fromByteArray(s){for(var o,a=s.length,u=a%3,_=[],w=16383,x=0,C=a-u;xC?C:x+w));1===u?(o=s[a-1],_.push(i[o>>2]+i[o<<4&63]+"==")):2===u&&(o=(s[a-2]<<8)+s[a-1],_.push(i[o>>10]+i[o>>4&63]+i[o<<2&63]+"="));return _.join("")};for(var i=[],a=[],u="undefined"!=typeof Uint8Array?Uint8Array:Array,_="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",w=0;w<64;++w)i[w]=_[w],a[_.charCodeAt(w)]=w;function getLens(s){var o=s.length;if(o%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var i=s.indexOf("=");return-1===i&&(i=o),[i,i===o?0:4-i%4]}function encodeChunk(s,o,a){for(var u,_,w=[],x=o;x>18&63]+i[_>>12&63]+i[_>>6&63]+i[63&_]);return w.join("")}a["-".charCodeAt(0)]=62,a["_".charCodeAt(0)]=63},48287(s,o,i){"use strict";const a=i(67526),u=i(251),_="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;o.Buffer=Buffer,o.SlowBuffer=function SlowBuffer(s){+s!=s&&(s=0);return Buffer.alloc(+s)},o.INSPECT_MAX_BYTES=50;const w=2147483647;function createBuffer(s){if(s>w)throw new RangeError('The value "'+s+'" is invalid for option "size"');const o=new Uint8Array(s);return Object.setPrototypeOf(o,Buffer.prototype),o}function Buffer(s,o,i){if("number"==typeof s){if("string"==typeof o)throw new TypeError('The "string" argument must be of type string. Received type number');return allocUnsafe(s)}return from(s,o,i)}function from(s,o,i){if("string"==typeof s)return function fromString(s,o){"string"==typeof o&&""!==o||(o="utf8");if(!Buffer.isEncoding(o))throw new TypeError("Unknown encoding: "+o);const i=0|byteLength(s,o);let a=createBuffer(i);const u=a.write(s,o);u!==i&&(a=a.slice(0,u));return a}(s,o);if(ArrayBuffer.isView(s))return function fromArrayView(s){if(isInstance(s,Uint8Array)){const o=new Uint8Array(s);return fromArrayBuffer(o.buffer,o.byteOffset,o.byteLength)}return fromArrayLike(s)}(s);if(null==s)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof s);if(isInstance(s,ArrayBuffer)||s&&isInstance(s.buffer,ArrayBuffer))return fromArrayBuffer(s,o,i);if("undefined"!=typeof SharedArrayBuffer&&(isInstance(s,SharedArrayBuffer)||s&&isInstance(s.buffer,SharedArrayBuffer)))return fromArrayBuffer(s,o,i);if("number"==typeof s)throw new TypeError('The "value" argument must not be of type number. Received type number');const a=s.valueOf&&s.valueOf();if(null!=a&&a!==s)return Buffer.from(a,o,i);const u=function fromObject(s){if(Buffer.isBuffer(s)){const o=0|checked(s.length),i=createBuffer(o);return 0===i.length||s.copy(i,0,0,o),i}if(void 0!==s.length)return"number"!=typeof s.length||numberIsNaN(s.length)?createBuffer(0):fromArrayLike(s);if("Buffer"===s.type&&Array.isArray(s.data))return fromArrayLike(s.data)}(s);if(u)return u;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof s[Symbol.toPrimitive])return Buffer.from(s[Symbol.toPrimitive]("string"),o,i);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof s)}function assertSize(s){if("number"!=typeof s)throw new TypeError('"size" argument must be of type number');if(s<0)throw new RangeError('The value "'+s+'" is invalid for option "size"')}function allocUnsafe(s){return assertSize(s),createBuffer(s<0?0:0|checked(s))}function fromArrayLike(s){const o=s.length<0?0:0|checked(s.length),i=createBuffer(o);for(let a=0;a=w)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+w.toString(16)+" bytes");return 0|s}function byteLength(s,o){if(Buffer.isBuffer(s))return s.length;if(ArrayBuffer.isView(s)||isInstance(s,ArrayBuffer))return s.byteLength;if("string"!=typeof s)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof s);const i=s.length,a=arguments.length>2&&!0===arguments[2];if(!a&&0===i)return 0;let u=!1;for(;;)switch(o){case"ascii":case"latin1":case"binary":return i;case"utf8":case"utf-8":return utf8ToBytes(s).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*i;case"hex":return i>>>1;case"base64":return base64ToBytes(s).length;default:if(u)return a?-1:utf8ToBytes(s).length;o=(""+o).toLowerCase(),u=!0}}function slowToString(s,o,i){let a=!1;if((void 0===o||o<0)&&(o=0),o>this.length)return"";if((void 0===i||i>this.length)&&(i=this.length),i<=0)return"";if((i>>>=0)<=(o>>>=0))return"";for(s||(s="utf8");;)switch(s){case"hex":return hexSlice(this,o,i);case"utf8":case"utf-8":return utf8Slice(this,o,i);case"ascii":return asciiSlice(this,o,i);case"latin1":case"binary":return latin1Slice(this,o,i);case"base64":return base64Slice(this,o,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,o,i);default:if(a)throw new TypeError("Unknown encoding: "+s);s=(s+"").toLowerCase(),a=!0}}function swap(s,o,i){const a=s[o];s[o]=s[i],s[i]=a}function bidirectionalIndexOf(s,o,i,a,u){if(0===s.length)return-1;if("string"==typeof i?(a=i,i=0):i>2147483647?i=2147483647:i<-2147483648&&(i=-2147483648),numberIsNaN(i=+i)&&(i=u?0:s.length-1),i<0&&(i=s.length+i),i>=s.length){if(u)return-1;i=s.length-1}else if(i<0){if(!u)return-1;i=0}if("string"==typeof o&&(o=Buffer.from(o,a)),Buffer.isBuffer(o))return 0===o.length?-1:arrayIndexOf(s,o,i,a,u);if("number"==typeof o)return o&=255,"function"==typeof Uint8Array.prototype.indexOf?u?Uint8Array.prototype.indexOf.call(s,o,i):Uint8Array.prototype.lastIndexOf.call(s,o,i):arrayIndexOf(s,[o],i,a,u);throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(s,o,i,a,u){let _,w=1,x=s.length,C=o.length;if(void 0!==a&&("ucs2"===(a=String(a).toLowerCase())||"ucs-2"===a||"utf16le"===a||"utf-16le"===a)){if(s.length<2||o.length<2)return-1;w=2,x/=2,C/=2,i/=2}function read(s,o){return 1===w?s[o]:s.readUInt16BE(o*w)}if(u){let a=-1;for(_=i;_x&&(i=x-C),_=i;_>=0;_--){let i=!0;for(let a=0;au&&(a=u):a=u;const _=o.length;let w;for(a>_/2&&(a=_/2),w=0;w>8,u=i%256,_.push(u),_.push(a);return _}(o,s.length-i),s,i,a)}function base64Slice(s,o,i){return 0===o&&i===s.length?a.fromByteArray(s):a.fromByteArray(s.slice(o,i))}function utf8Slice(s,o,i){i=Math.min(s.length,i);const a=[];let u=o;for(;u239?4:o>223?3:o>191?2:1;if(u+w<=i){let i,a,x,C;switch(w){case 1:o<128&&(_=o);break;case 2:i=s[u+1],128==(192&i)&&(C=(31&o)<<6|63&i,C>127&&(_=C));break;case 3:i=s[u+1],a=s[u+2],128==(192&i)&&128==(192&a)&&(C=(15&o)<<12|(63&i)<<6|63&a,C>2047&&(C<55296||C>57343)&&(_=C));break;case 4:i=s[u+1],a=s[u+2],x=s[u+3],128==(192&i)&&128==(192&a)&&128==(192&x)&&(C=(15&o)<<18|(63&i)<<12|(63&a)<<6|63&x,C>65535&&C<1114112&&(_=C))}}null===_?(_=65533,w=1):_>65535&&(_-=65536,a.push(_>>>10&1023|55296),_=56320|1023&_),a.push(_),u+=w}return function decodeCodePointsArray(s){const o=s.length;if(o<=x)return String.fromCharCode.apply(String,s);let i="",a=0;for(;aa.length?(Buffer.isBuffer(o)||(o=Buffer.from(o)),o.copy(a,u)):Uint8Array.prototype.set.call(a,o,u);else{if(!Buffer.isBuffer(o))throw new TypeError('"list" argument must be an Array of Buffers');o.copy(a,u)}u+=o.length}return a},Buffer.byteLength=byteLength,Buffer.prototype._isBuffer=!0,Buffer.prototype.swap16=function swap16(){const s=this.length;if(s%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let o=0;oi&&(s+=" ... "),""},_&&(Buffer.prototype[_]=Buffer.prototype.inspect),Buffer.prototype.compare=function compare(s,o,i,a,u){if(isInstance(s,Uint8Array)&&(s=Buffer.from(s,s.offset,s.byteLength)),!Buffer.isBuffer(s))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof s);if(void 0===o&&(o=0),void 0===i&&(i=s?s.length:0),void 0===a&&(a=0),void 0===u&&(u=this.length),o<0||i>s.length||a<0||u>this.length)throw new RangeError("out of range index");if(a>=u&&o>=i)return 0;if(a>=u)return-1;if(o>=i)return 1;if(this===s)return 0;let _=(u>>>=0)-(a>>>=0),w=(i>>>=0)-(o>>>=0);const x=Math.min(_,w),C=this.slice(a,u),j=s.slice(o,i);for(let s=0;s>>=0,isFinite(i)?(i>>>=0,void 0===a&&(a="utf8")):(a=i,i=void 0)}const u=this.length-o;if((void 0===i||i>u)&&(i=u),s.length>0&&(i<0||o<0)||o>this.length)throw new RangeError("Attempt to write outside buffer bounds");a||(a="utf8");let _=!1;for(;;)switch(a){case"hex":return hexWrite(this,s,o,i);case"utf8":case"utf-8":return utf8Write(this,s,o,i);case"ascii":case"latin1":case"binary":return asciiWrite(this,s,o,i);case"base64":return base64Write(this,s,o,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,s,o,i);default:if(_)throw new TypeError("Unknown encoding: "+a);a=(""+a).toLowerCase(),_=!0}},Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};const x=4096;function asciiSlice(s,o,i){let a="";i=Math.min(s.length,i);for(let u=o;ua)&&(i=a);let u="";for(let a=o;ai)throw new RangeError("Trying to access beyond buffer length")}function checkInt(s,o,i,a,u,_){if(!Buffer.isBuffer(s))throw new TypeError('"buffer" argument must be a Buffer instance');if(o>u||o<_)throw new RangeError('"value" argument is out of bounds');if(i+a>s.length)throw new RangeError("Index out of range")}function wrtBigUInt64LE(s,o,i,a,u){checkIntBI(o,a,u,s,i,7);let _=Number(o&BigInt(4294967295));s[i++]=_,_>>=8,s[i++]=_,_>>=8,s[i++]=_,_>>=8,s[i++]=_;let w=Number(o>>BigInt(32)&BigInt(4294967295));return s[i++]=w,w>>=8,s[i++]=w,w>>=8,s[i++]=w,w>>=8,s[i++]=w,i}function wrtBigUInt64BE(s,o,i,a,u){checkIntBI(o,a,u,s,i,7);let _=Number(o&BigInt(4294967295));s[i+7]=_,_>>=8,s[i+6]=_,_>>=8,s[i+5]=_,_>>=8,s[i+4]=_;let w=Number(o>>BigInt(32)&BigInt(4294967295));return s[i+3]=w,w>>=8,s[i+2]=w,w>>=8,s[i+1]=w,w>>=8,s[i]=w,i+8}function checkIEEE754(s,o,i,a,u,_){if(i+a>s.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("Index out of range")}function writeFloat(s,o,i,a,_){return o=+o,i>>>=0,_||checkIEEE754(s,0,i,4),u.write(s,o,i,a,23,4),i+4}function writeDouble(s,o,i,a,_){return o=+o,i>>>=0,_||checkIEEE754(s,0,i,8),u.write(s,o,i,a,52,8),i+8}Buffer.prototype.slice=function slice(s,o){const i=this.length;(s=~~s)<0?(s+=i)<0&&(s=0):s>i&&(s=i),(o=void 0===o?i:~~o)<0?(o+=i)<0&&(o=0):o>i&&(o=i),o>>=0,o>>>=0,i||checkOffset(s,o,this.length);let a=this[s],u=1,_=0;for(;++_>>=0,o>>>=0,i||checkOffset(s,o,this.length);let a=this[s+--o],u=1;for(;o>0&&(u*=256);)a+=this[s+--o]*u;return a},Buffer.prototype.readUint8=Buffer.prototype.readUInt8=function readUInt8(s,o){return s>>>=0,o||checkOffset(s,1,this.length),this[s]},Buffer.prototype.readUint16LE=Buffer.prototype.readUInt16LE=function readUInt16LE(s,o){return s>>>=0,o||checkOffset(s,2,this.length),this[s]|this[s+1]<<8},Buffer.prototype.readUint16BE=Buffer.prototype.readUInt16BE=function readUInt16BE(s,o){return s>>>=0,o||checkOffset(s,2,this.length),this[s]<<8|this[s+1]},Buffer.prototype.readUint32LE=Buffer.prototype.readUInt32LE=function readUInt32LE(s,o){return s>>>=0,o||checkOffset(s,4,this.length),(this[s]|this[s+1]<<8|this[s+2]<<16)+16777216*this[s+3]},Buffer.prototype.readUint32BE=Buffer.prototype.readUInt32BE=function readUInt32BE(s,o){return s>>>=0,o||checkOffset(s,4,this.length),16777216*this[s]+(this[s+1]<<16|this[s+2]<<8|this[s+3])},Buffer.prototype.readBigUInt64LE=defineBigIntMethod((function readBigUInt64LE(s){validateNumber(s>>>=0,"offset");const o=this[s],i=this[s+7];void 0!==o&&void 0!==i||boundsError(s,this.length-8);const a=o+256*this[++s]+65536*this[++s]+this[++s]*2**24,u=this[++s]+256*this[++s]+65536*this[++s]+i*2**24;return BigInt(a)+(BigInt(u)<>>=0,"offset");const o=this[s],i=this[s+7];void 0!==o&&void 0!==i||boundsError(s,this.length-8);const a=o*2**24+65536*this[++s]+256*this[++s]+this[++s],u=this[++s]*2**24+65536*this[++s]+256*this[++s]+i;return(BigInt(a)<>>=0,o>>>=0,i||checkOffset(s,o,this.length);let a=this[s],u=1,_=0;for(;++_=u&&(a-=Math.pow(2,8*o)),a},Buffer.prototype.readIntBE=function readIntBE(s,o,i){s>>>=0,o>>>=0,i||checkOffset(s,o,this.length);let a=o,u=1,_=this[s+--a];for(;a>0&&(u*=256);)_+=this[s+--a]*u;return u*=128,_>=u&&(_-=Math.pow(2,8*o)),_},Buffer.prototype.readInt8=function readInt8(s,o){return s>>>=0,o||checkOffset(s,1,this.length),128&this[s]?-1*(255-this[s]+1):this[s]},Buffer.prototype.readInt16LE=function readInt16LE(s,o){s>>>=0,o||checkOffset(s,2,this.length);const i=this[s]|this[s+1]<<8;return 32768&i?4294901760|i:i},Buffer.prototype.readInt16BE=function readInt16BE(s,o){s>>>=0,o||checkOffset(s,2,this.length);const i=this[s+1]|this[s]<<8;return 32768&i?4294901760|i:i},Buffer.prototype.readInt32LE=function readInt32LE(s,o){return s>>>=0,o||checkOffset(s,4,this.length),this[s]|this[s+1]<<8|this[s+2]<<16|this[s+3]<<24},Buffer.prototype.readInt32BE=function readInt32BE(s,o){return s>>>=0,o||checkOffset(s,4,this.length),this[s]<<24|this[s+1]<<16|this[s+2]<<8|this[s+3]},Buffer.prototype.readBigInt64LE=defineBigIntMethod((function readBigInt64LE(s){validateNumber(s>>>=0,"offset");const o=this[s],i=this[s+7];void 0!==o&&void 0!==i||boundsError(s,this.length-8);const a=this[s+4]+256*this[s+5]+65536*this[s+6]+(i<<24);return(BigInt(a)<>>=0,"offset");const o=this[s],i=this[s+7];void 0!==o&&void 0!==i||boundsError(s,this.length-8);const a=(o<<24)+65536*this[++s]+256*this[++s]+this[++s];return(BigInt(a)<>>=0,o||checkOffset(s,4,this.length),u.read(this,s,!0,23,4)},Buffer.prototype.readFloatBE=function readFloatBE(s,o){return s>>>=0,o||checkOffset(s,4,this.length),u.read(this,s,!1,23,4)},Buffer.prototype.readDoubleLE=function readDoubleLE(s,o){return s>>>=0,o||checkOffset(s,8,this.length),u.read(this,s,!0,52,8)},Buffer.prototype.readDoubleBE=function readDoubleBE(s,o){return s>>>=0,o||checkOffset(s,8,this.length),u.read(this,s,!1,52,8)},Buffer.prototype.writeUintLE=Buffer.prototype.writeUIntLE=function writeUIntLE(s,o,i,a){if(s=+s,o>>>=0,i>>>=0,!a){checkInt(this,s,o,i,Math.pow(2,8*i)-1,0)}let u=1,_=0;for(this[o]=255&s;++_>>=0,i>>>=0,!a){checkInt(this,s,o,i,Math.pow(2,8*i)-1,0)}let u=i-1,_=1;for(this[o+u]=255&s;--u>=0&&(_*=256);)this[o+u]=s/_&255;return o+i},Buffer.prototype.writeUint8=Buffer.prototype.writeUInt8=function writeUInt8(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,1,255,0),this[o]=255&s,o+1},Buffer.prototype.writeUint16LE=Buffer.prototype.writeUInt16LE=function writeUInt16LE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,2,65535,0),this[o]=255&s,this[o+1]=s>>>8,o+2},Buffer.prototype.writeUint16BE=Buffer.prototype.writeUInt16BE=function writeUInt16BE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,2,65535,0),this[o]=s>>>8,this[o+1]=255&s,o+2},Buffer.prototype.writeUint32LE=Buffer.prototype.writeUInt32LE=function writeUInt32LE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,4,4294967295,0),this[o+3]=s>>>24,this[o+2]=s>>>16,this[o+1]=s>>>8,this[o]=255&s,o+4},Buffer.prototype.writeUint32BE=Buffer.prototype.writeUInt32BE=function writeUInt32BE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,4,4294967295,0),this[o]=s>>>24,this[o+1]=s>>>16,this[o+2]=s>>>8,this[o+3]=255&s,o+4},Buffer.prototype.writeBigUInt64LE=defineBigIntMethod((function writeBigUInt64LE(s,o=0){return wrtBigUInt64LE(this,s,o,BigInt(0),BigInt("0xffffffffffffffff"))})),Buffer.prototype.writeBigUInt64BE=defineBigIntMethod((function writeBigUInt64BE(s,o=0){return wrtBigUInt64BE(this,s,o,BigInt(0),BigInt("0xffffffffffffffff"))})),Buffer.prototype.writeIntLE=function writeIntLE(s,o,i,a){if(s=+s,o>>>=0,!a){const a=Math.pow(2,8*i-1);checkInt(this,s,o,i,a-1,-a)}let u=0,_=1,w=0;for(this[o]=255&s;++u>>=0,!a){const a=Math.pow(2,8*i-1);checkInt(this,s,o,i,a-1,-a)}let u=i-1,_=1,w=0;for(this[o+u]=255&s;--u>=0&&(_*=256);)s<0&&0===w&&0!==this[o+u+1]&&(w=1),this[o+u]=(s/_|0)-w&255;return o+i},Buffer.prototype.writeInt8=function writeInt8(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,1,127,-128),s<0&&(s=255+s+1),this[o]=255&s,o+1},Buffer.prototype.writeInt16LE=function writeInt16LE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,2,32767,-32768),this[o]=255&s,this[o+1]=s>>>8,o+2},Buffer.prototype.writeInt16BE=function writeInt16BE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,2,32767,-32768),this[o]=s>>>8,this[o+1]=255&s,o+2},Buffer.prototype.writeInt32LE=function writeInt32LE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,4,2147483647,-2147483648),this[o]=255&s,this[o+1]=s>>>8,this[o+2]=s>>>16,this[o+3]=s>>>24,o+4},Buffer.prototype.writeInt32BE=function writeInt32BE(s,o,i){return s=+s,o>>>=0,i||checkInt(this,s,o,4,2147483647,-2147483648),s<0&&(s=4294967295+s+1),this[o]=s>>>24,this[o+1]=s>>>16,this[o+2]=s>>>8,this[o+3]=255&s,o+4},Buffer.prototype.writeBigInt64LE=defineBigIntMethod((function writeBigInt64LE(s,o=0){return wrtBigUInt64LE(this,s,o,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),Buffer.prototype.writeBigInt64BE=defineBigIntMethod((function writeBigInt64BE(s,o=0){return wrtBigUInt64BE(this,s,o,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),Buffer.prototype.writeFloatLE=function writeFloatLE(s,o,i){return writeFloat(this,s,o,!0,i)},Buffer.prototype.writeFloatBE=function writeFloatBE(s,o,i){return writeFloat(this,s,o,!1,i)},Buffer.prototype.writeDoubleLE=function writeDoubleLE(s,o,i){return writeDouble(this,s,o,!0,i)},Buffer.prototype.writeDoubleBE=function writeDoubleBE(s,o,i){return writeDouble(this,s,o,!1,i)},Buffer.prototype.copy=function copy(s,o,i,a){if(!Buffer.isBuffer(s))throw new TypeError("argument should be a Buffer");if(i||(i=0),a||0===a||(a=this.length),o>=s.length&&(o=s.length),o||(o=0),a>0&&a=this.length)throw new RangeError("Index out of range");if(a<0)throw new RangeError("sourceEnd out of bounds");a>this.length&&(a=this.length),s.length-o>>=0,i=void 0===i?this.length:i>>>0,s||(s=0),"number"==typeof s)for(u=o;u=a+4;i-=3)o=`_${s.slice(i-3,i)}${o}`;return`${s.slice(0,i)}${o}`}function checkIntBI(s,o,i,a,u,_){if(s>i||s3?0===o||o===BigInt(0)?`>= 0${a} and < 2${a} ** ${8*(_+1)}${a}`:`>= -(2${a} ** ${8*(_+1)-1}${a}) and < 2 ** ${8*(_+1)-1}${a}`:`>= ${o}${a} and <= ${i}${a}`,new C.ERR_OUT_OF_RANGE("value",u,s)}!function checkBounds(s,o,i){validateNumber(o,"offset"),void 0!==s[o]&&void 0!==s[o+i]||boundsError(o,s.length-(i+1))}(a,u,_)}function validateNumber(s,o){if("number"!=typeof s)throw new C.ERR_INVALID_ARG_TYPE(o,"number",s)}function boundsError(s,o,i){if(Math.floor(s)!==s)throw validateNumber(s,i),new C.ERR_OUT_OF_RANGE(i||"offset","an integer",s);if(o<0)throw new C.ERR_BUFFER_OUT_OF_BOUNDS;throw new C.ERR_OUT_OF_RANGE(i||"offset",`>= ${i?1:0} and <= ${o}`,s)}E("ERR_BUFFER_OUT_OF_BOUNDS",(function(s){return s?`${s} is outside of buffer bounds`:"Attempt to access memory outside buffer bounds"}),RangeError),E("ERR_INVALID_ARG_TYPE",(function(s,o){return`The "${s}" argument must be of type number. Received type ${typeof o}`}),TypeError),E("ERR_OUT_OF_RANGE",(function(s,o,i){let a=`The value of "${s}" is out of range.`,u=i;return Number.isInteger(i)&&Math.abs(i)>2**32?u=addNumericalSeparator(String(i)):"bigint"==typeof i&&(u=String(i),(i>BigInt(2)**BigInt(32)||i<-(BigInt(2)**BigInt(32)))&&(u=addNumericalSeparator(u)),u+="n"),a+=` It must be ${o}. Received ${u}`,a}),RangeError);const j=/[^+/0-9A-Za-z-_]/g;function utf8ToBytes(s,o){let i;o=o||1/0;const a=s.length;let u=null;const _=[];for(let w=0;w55295&&i<57344){if(!u){if(i>56319){(o-=3)>-1&&_.push(239,191,189);continue}if(w+1===a){(o-=3)>-1&&_.push(239,191,189);continue}u=i;continue}if(i<56320){(o-=3)>-1&&_.push(239,191,189),u=i;continue}i=65536+(u-55296<<10|i-56320)}else u&&(o-=3)>-1&&_.push(239,191,189);if(u=null,i<128){if((o-=1)<0)break;_.push(i)}else if(i<2048){if((o-=2)<0)break;_.push(i>>6|192,63&i|128)}else if(i<65536){if((o-=3)<0)break;_.push(i>>12|224,i>>6&63|128,63&i|128)}else{if(!(i<1114112))throw new Error("Invalid code point");if((o-=4)<0)break;_.push(i>>18|240,i>>12&63|128,i>>6&63|128,63&i|128)}}return _}function base64ToBytes(s){return a.toByteArray(function base64clean(s){if((s=(s=s.split("=")[0]).trim().replace(j,"")).length<2)return"";for(;s.length%4!=0;)s+="=";return s}(s))}function blitBuffer(s,o,i,a){let u;for(u=0;u=o.length||u>=s.length);++u)o[u+i]=s[u];return u}function isInstance(s,o){return s instanceof o||null!=s&&null!=s.constructor&&null!=s.constructor.name&&s.constructor.name===o.name}function numberIsNaN(s){return s!=s}const L=function(){const s="0123456789abcdef",o=new Array(256);for(let i=0;i<16;++i){const a=16*i;for(let u=0;u<16;++u)o[a+u]=s[i]+s[u]}return o}();function defineBigIntMethod(s){return"undefined"==typeof BigInt?BufferBigIntNotDefined:s}function BufferBigIntNotDefined(){throw new Error("BigInt not supported")}},13144(s,o,i){"use strict";var a=i(66743),u=i(11002),_=i(10076),w=i(47119);s.exports=w||a.call(_,u)},12205(s,o,i){"use strict";var a=i(66743),u=i(11002),_=i(13144);s.exports=function applyBind(){return _(a,u,arguments)}},11002(s){"use strict";s.exports=Function.prototype.apply},10076(s){"use strict";s.exports=Function.prototype.call},73126(s,o,i){"use strict";var a=i(66743),u=i(69675),_=i(10076),w=i(13144);s.exports=function callBindBasic(s){if(s.length<1||"function"!=typeof s[0])throw new u("a function is required");return w(a,_,s)}},47119(s){"use strict";s.exports="undefined"!=typeof Reflect&&Reflect&&Reflect.apply},10487(s,o,i){"use strict";var a=i(96897),u=i(30655),_=i(73126),w=i(12205);s.exports=function callBind(s){var o=_(arguments),i=s.length-(arguments.length-1);return a(o,1+(i>0?i:0),!0)},u?u(s.exports,"apply",{value:w}):s.exports.apply=w},36556(s,o,i){"use strict";var a=i(70453),u=i(73126),_=u([a("%String.prototype.indexOf%")]);s.exports=function callBoundIntrinsic(s,o){var i=a(s,!!o);return"function"==typeof i&&_(s,".prototype.")>-1?u([i]):i}},17965(s,o,i){"use strict";var a=i(16426),u={"text/plain":"Text","text/html":"Url",default:"Text"};s.exports=function copy(s,o){var i,_,w,x,C,j,L=!1;o||(o={}),i=o.debug||!1;try{if(w=a(),x=document.createRange(),C=document.getSelection(),(j=document.createElement("span")).textContent=s,j.ariaHidden="true",j.style.all="unset",j.style.position="fixed",j.style.top=0,j.style.clip="rect(0, 0, 0, 0)",j.style.whiteSpace="pre",j.style.webkitUserSelect="text",j.style.MozUserSelect="text",j.style.msUserSelect="text",j.style.userSelect="text",j.addEventListener("copy",(function(a){if(a.stopPropagation(),o.format)if(a.preventDefault(),void 0===a.clipboardData){i&&console.warn("unable to use e.clipboardData"),i&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var _=u[o.format]||u.default;window.clipboardData.setData(_,s)}else a.clipboardData.clearData(),a.clipboardData.setData(o.format,s);o.onCopy&&(a.preventDefault(),o.onCopy(a.clipboardData))})),document.body.appendChild(j),x.selectNodeContents(j),C.addRange(x),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");L=!0}catch(a){i&&console.error("unable to copy using execCommand: ",a),i&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(o.format||"text",s),o.onCopy&&o.onCopy(window.clipboardData),L=!0}catch(a){i&&console.error("unable to copy using clipboardData: ",a),i&&console.error("falling back to prompt"),_=function format(s){var o=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return s.replace(/#{\s*key\s*}/g,o)}("message"in o?o.message:"Copy to clipboard: #{key}, Enter"),window.prompt(_,s)}}finally{C&&("function"==typeof C.removeRange?C.removeRange(x):C.removeAllRanges()),j&&document.body.removeChild(j),w()}return L}},2205(s,o,i){var a;a=void 0!==i.g?i.g:this,s.exports=function(s){if(s.CSS&&s.CSS.escape)return s.CSS.escape;var cssEscape=function(s){if(0==arguments.length)throw new TypeError("`CSS.escape` requires an argument.");for(var o,i=String(s),a=i.length,u=-1,_="",w=i.charCodeAt(0);++u=1&&o<=31||127==o||0==u&&o>=48&&o<=57||1==u&&o>=48&&o<=57&&45==w?"\\"+o.toString(16)+" ":0==u&&1==a&&45==o||!(o>=128||45==o||95==o||o>=48&&o<=57||o>=65&&o<=90||o>=97&&o<=122)?"\\"+i.charAt(u):i.charAt(u):_+="�";return _};return s.CSS||(s.CSS={}),s.CSS.escape=cssEscape,cssEscape}(a)},81919(s,o,i){"use strict";var a=i(48287).Buffer;function isSpecificValue(s){return s instanceof a||s instanceof Date||s instanceof RegExp}function cloneSpecificValue(s){if(s instanceof a){var o=a.alloc?a.alloc(s.length):new a(s.length);return s.copy(o),o}if(s instanceof Date)return new Date(s.getTime());if(s instanceof RegExp)return new RegExp(s);throw new Error("Unexpected situation")}function deepCloneArray(s){var o=[];return s.forEach((function(s,i){"object"==typeof s&&null!==s?Array.isArray(s)?o[i]=deepCloneArray(s):isSpecificValue(s)?o[i]=cloneSpecificValue(s):o[i]=u({},s):o[i]=s})),o}function safeGetProperty(s,o){return"__proto__"===o?void 0:s[o]}var u=s.exports=function(){if(arguments.length<1||"object"!=typeof arguments[0])return!1;if(arguments.length<2)return arguments[0];var s,o,i=arguments[0];return Array.prototype.slice.call(arguments,1).forEach((function(a){"object"!=typeof a||null===a||Array.isArray(a)||Object.keys(a).forEach((function(_){return o=safeGetProperty(i,_),(s=safeGetProperty(a,_))===i?void 0:"object"!=typeof s||null===s?void(i[_]=s):Array.isArray(s)?void(i[_]=deepCloneArray(s)):isSpecificValue(s)?void(i[_]=cloneSpecificValue(s)):"object"!=typeof o||null===o||Array.isArray(o)?void(i[_]=u({},s)):void(i[_]=u(o,s))}))})),i}},14744(s){"use strict";var o=function isMergeableObject(s){return function isNonNullObject(s){return!!s&&"object"==typeof s}(s)&&!function isSpecial(s){var o=Object.prototype.toString.call(s);return"[object RegExp]"===o||"[object Date]"===o||function isReactElement(s){return s.$$typeof===i}(s)}(s)};var i="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function cloneUnlessOtherwiseSpecified(s,o){return!1!==o.clone&&o.isMergeableObject(s)?deepmerge(function emptyTarget(s){return Array.isArray(s)?[]:{}}(s),s,o):s}function defaultArrayMerge(s,o,i){return s.concat(o).map((function(s){return cloneUnlessOtherwiseSpecified(s,i)}))}function getKeys(s){return Object.keys(s).concat(function getEnumerableOwnPropertySymbols(s){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(s).filter((function(o){return Object.propertyIsEnumerable.call(s,o)})):[]}(s))}function propertyIsOnObject(s,o){try{return o in s}catch(s){return!1}}function mergeObject(s,o,i){var a={};return i.isMergeableObject(s)&&getKeys(s).forEach((function(o){a[o]=cloneUnlessOtherwiseSpecified(s[o],i)})),getKeys(o).forEach((function(u){(function propertyIsUnsafe(s,o){return propertyIsOnObject(s,o)&&!(Object.hasOwnProperty.call(s,o)&&Object.propertyIsEnumerable.call(s,o))})(s,u)||(propertyIsOnObject(s,u)&&i.isMergeableObject(o[u])?a[u]=function getMergeFunction(s,o){if(!o.customMerge)return deepmerge;var i=o.customMerge(s);return"function"==typeof i?i:deepmerge}(u,i)(s[u],o[u],i):a[u]=cloneUnlessOtherwiseSpecified(o[u],i))})),a}function deepmerge(s,i,a){(a=a||{}).arrayMerge=a.arrayMerge||defaultArrayMerge,a.isMergeableObject=a.isMergeableObject||o,a.cloneUnlessOtherwiseSpecified=cloneUnlessOtherwiseSpecified;var u=Array.isArray(i);return u===Array.isArray(s)?u?a.arrayMerge(s,i,a):mergeObject(s,i,a):cloneUnlessOtherwiseSpecified(i,a)}deepmerge.all=function deepmergeAll(s,o){if(!Array.isArray(s))throw new Error("first argument should be an array");return s.reduce((function(s,i){return deepmerge(s,i,o)}),{})};var a=deepmerge;s.exports=a},30041(s,o,i){"use strict";var a=i(30655),u=i(58068),_=i(69675),w=i(75795);s.exports=function defineDataProperty(s,o,i){if(!s||"object"!=typeof s&&"function"!=typeof s)throw new _("`obj` must be an object or a function`");if("string"!=typeof o&&"symbol"!=typeof o)throw new _("`property` must be a string or a symbol`");if(arguments.length>3&&"boolean"!=typeof arguments[3]&&null!==arguments[3])throw new _("`nonEnumerable`, if provided, must be a boolean or null");if(arguments.length>4&&"boolean"!=typeof arguments[4]&&null!==arguments[4])throw new _("`nonWritable`, if provided, must be a boolean or null");if(arguments.length>5&&"boolean"!=typeof arguments[5]&&null!==arguments[5])throw new _("`nonConfigurable`, if provided, must be a boolean or null");if(arguments.length>6&&"boolean"!=typeof arguments[6])throw new _("`loose`, if provided, must be a boolean");var x=arguments.length>3?arguments[3]:null,C=arguments.length>4?arguments[4]:null,j=arguments.length>5?arguments[5]:null,L=arguments.length>6&&arguments[6],B=!!w&&w(s,o);if(a)a(s,o,{configurable:null===j&&B?B.configurable:!j,enumerable:null===x&&B?B.enumerable:!x,value:i,writable:null===C&&B?B.writable:!C});else{if(!L&&(x||C||j))throw new u("This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.");s[o]=i}}},78004(s){"use strict";class SubRange{constructor(s,o){this.low=s,this.high=o,this.length=1+o-s}overlaps(s){return!(this.highs.high)}touches(s){return!(this.high+1s.high)}add(s){return new SubRange(Math.min(this.low,s.low),Math.max(this.high,s.high))}subtract(s){return s.low<=this.low&&s.high>=this.high?[]:s.low>this.low&&s.highs+o.length),0)}add(s,o){var _add=s=>{for(var o=0;o{for(var o=0;o{for(var o=0;o{for(var i=o.low;i<=o.high;)s.push(i),i++;return s}),[])}subranges(){return this.ranges.map((s=>({low:s.low,high:s.high,length:1+s.high-s.low})))}}s.exports=DRange},7176(s,o,i){"use strict";var a,u=i(73126),_=i(75795);try{a=[].__proto__===Array.prototype}catch(s){if(!s||"object"!=typeof s||!("code"in s)||"ERR_PROTO_ACCESS"!==s.code)throw s}var w=!!a&&_&&_(Object.prototype,"__proto__"),x=Object,C=x.getPrototypeOf;s.exports=w&&"function"==typeof w.get?u([w.get]):"function"==typeof C&&function getDunder(s){return C(null==s?s:x(s))}},30655(s){"use strict";var o=Object.defineProperty||!1;if(o)try{o({},"a",{value:1})}catch(s){o=!1}s.exports=o},41237(s){"use strict";s.exports=EvalError},69383(s){"use strict";s.exports=Error},79290(s){"use strict";s.exports=RangeError},79538(s){"use strict";s.exports=ReferenceError},58068(s){"use strict";s.exports=SyntaxError},69675(s){"use strict";s.exports=TypeError},35345(s){"use strict";s.exports=URIError},79612(s){"use strict";s.exports=Object},37007(s){"use strict";var o,i="object"==typeof Reflect?Reflect:null,a=i&&"function"==typeof i.apply?i.apply:function ReflectApply(s,o,i){return Function.prototype.apply.call(s,o,i)};o=i&&"function"==typeof i.ownKeys?i.ownKeys:Object.getOwnPropertySymbols?function ReflectOwnKeys(s){return Object.getOwnPropertyNames(s).concat(Object.getOwnPropertySymbols(s))}:function ReflectOwnKeys(s){return Object.getOwnPropertyNames(s)};var u=Number.isNaN||function NumberIsNaN(s){return s!=s};function EventEmitter(){EventEmitter.init.call(this)}s.exports=EventEmitter,s.exports.once=function once(s,o){return new Promise((function(i,a){function errorListener(i){s.removeListener(o,resolver),a(i)}function resolver(){"function"==typeof s.removeListener&&s.removeListener("error",errorListener),i([].slice.call(arguments))}eventTargetAgnosticAddListener(s,o,resolver,{once:!0}),"error"!==o&&function addErrorHandlerIfEventEmitter(s,o,i){"function"==typeof s.on&&eventTargetAgnosticAddListener(s,"error",o,i)}(s,errorListener,{once:!0})}))},EventEmitter.EventEmitter=EventEmitter,EventEmitter.prototype._events=void 0,EventEmitter.prototype._eventsCount=0,EventEmitter.prototype._maxListeners=void 0;var _=10;function checkListener(s){if("function"!=typeof s)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof s)}function _getMaxListeners(s){return void 0===s._maxListeners?EventEmitter.defaultMaxListeners:s._maxListeners}function _addListener(s,o,i,a){var u,_,w;if(checkListener(i),void 0===(_=s._events)?(_=s._events=Object.create(null),s._eventsCount=0):(void 0!==_.newListener&&(s.emit("newListener",o,i.listener?i.listener:i),_=s._events),w=_[o]),void 0===w)w=_[o]=i,++s._eventsCount;else if("function"==typeof w?w=_[o]=a?[i,w]:[w,i]:a?w.unshift(i):w.push(i),(u=_getMaxListeners(s))>0&&w.length>u&&!w.warned){w.warned=!0;var x=new Error("Possible EventEmitter memory leak detected. "+w.length+" "+String(o)+" listeners added. Use emitter.setMaxListeners() to increase limit");x.name="MaxListenersExceededWarning",x.emitter=s,x.type=o,x.count=w.length,function ProcessEmitWarning(s){console&&console.warn&&console.warn(s)}(x)}return s}function onceWrapper(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function _onceWrap(s,o,i){var a={fired:!1,wrapFn:void 0,target:s,type:o,listener:i},u=onceWrapper.bind(a);return u.listener=i,a.wrapFn=u,u}function _listeners(s,o,i){var a=s._events;if(void 0===a)return[];var u=a[o];return void 0===u?[]:"function"==typeof u?i?[u.listener||u]:[u]:i?function unwrapListeners(s){for(var o=new Array(s.length),i=0;i0&&(w=o[0]),w instanceof Error)throw w;var x=new Error("Unhandled error."+(w?" ("+w.message+")":""));throw x.context=w,x}var C=_[s];if(void 0===C)return!1;if("function"==typeof C)a(C,this,o);else{var j=C.length,L=arrayClone(C,j);for(i=0;i=0;_--)if(i[_]===o||i[_].listener===o){w=i[_].listener,u=_;break}if(u<0)return this;0===u?i.shift():function spliceOne(s,o){for(;o+1=0;a--)this.removeListener(s,o[a]);return this},EventEmitter.prototype.listeners=function listeners(s){return _listeners(this,s,!0)},EventEmitter.prototype.rawListeners=function rawListeners(s){return _listeners(this,s,!1)},EventEmitter.listenerCount=function(s,o){return"function"==typeof s.listenerCount?s.listenerCount(o):listenerCount.call(s,o)},EventEmitter.prototype.listenerCount=listenerCount,EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?o(this._events):[]}},85587(s,o,i){"use strict";var a=i(26311),u=create(Error);function create(s){return FormattedError.displayName=s.displayName||s.name,FormattedError;function FormattedError(o){return o&&(o=a.apply(null,arguments)),new s(o)}}s.exports=u,u.eval=create(EvalError),u.range=create(RangeError),u.reference=create(ReferenceError),u.syntax=create(SyntaxError),u.type=create(TypeError),u.uri=create(URIError),u.create=create},82682(s,o,i){"use strict";var a=i(69600),u=Object.prototype.toString,_=Object.prototype.hasOwnProperty;s.exports=function forEach(s,o,i){if(!a(o))throw new TypeError("iterator must be a function");var w;arguments.length>=3&&(w=i),function isArray(s){return"[object Array]"===u.call(s)}(s)?function forEachArray(s,o,i){for(var a=0,u=s.length;a0?parseInt(i):null};x1&&"boolean"!=typeof o)throw new L('"allowMissing" argument must be a boolean');if(null===Xe(/^%?[^%]*%?$/,s))throw new j("`%` may not be present anywhere but at the beginning and end of the intrinsic name");var i=function stringToPath(s){var o=Ye(s,0,1),i=Ye(s,-1);if("%"===o&&"%"!==i)throw new j("invalid intrinsic syntax, expected closing `%`");if("%"===i&&"%"!==o)throw new j("invalid intrinsic syntax, expected opening `%`");var a=[];return He(s,Qe,(function(s,o,i,u){a[a.length]=i?He(u,et,"$1"):o||s})),a}(s),a=i.length>0?i[0]:"",u=tt("%"+a+"%",o),_=u.name,w=u.value,x=!1,C=u.alias;C&&(a=C[0],We(i,ze([0,1],C)));for(var B=1,$=!0;B=i.length){var Y=ae(w,U);w=($=!!Y)&&"get"in Y&&!("originalValue"in Y.get)?Y.get:w[U]}else $=$e(w,U),w=w[U];$&&!x&&(xe[_]=w)}}return w}},71064(s,o,i){"use strict";var a=i(79612);s.exports=a.getPrototypeOf||null},48648(s){"use strict";s.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null},93628(s,o,i){"use strict";var a=i(48648),u=i(71064),_=i(7176);s.exports=a?function getProto(s){return a(s)}:u?function getProto(s){if(!s||"object"!=typeof s&&"function"!=typeof s)throw new TypeError("getProto: not an object");return u(s)}:_?function getProto(s){return _(s)}:null},6549(s){"use strict";s.exports=Object.getOwnPropertyDescriptor},75795(s,o,i){"use strict";var a=i(6549);if(a)try{a([],"length")}catch(s){a=null}s.exports=a},30592(s,o,i){"use strict";var a=i(30655),u=function hasPropertyDescriptors(){return!!a};u.hasArrayLengthDefineBug=function hasArrayLengthDefineBug(){if(!a)return null;try{return 1!==a([],"length",{value:1}).length}catch(s){return!0}},s.exports=u},64039(s,o,i){"use strict";var a="undefined"!=typeof Symbol&&Symbol,u=i(41333);s.exports=function hasNativeSymbols(){return"function"==typeof a&&("function"==typeof Symbol&&("symbol"==typeof a("foo")&&("symbol"==typeof Symbol("bar")&&u())))}},41333(s){"use strict";s.exports=function hasSymbols(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"==typeof Symbol.iterator)return!0;var s={},o=Symbol("test"),i=Object(o);if("string"==typeof o)return!1;if("[object Symbol]"!==Object.prototype.toString.call(o))return!1;if("[object Symbol]"!==Object.prototype.toString.call(i))return!1;for(var a in s[o]=42,s)return!1;if("function"==typeof Object.keys&&0!==Object.keys(s).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(s).length)return!1;var u=Object.getOwnPropertySymbols(s);if(1!==u.length||u[0]!==o)return!1;if(!Object.prototype.propertyIsEnumerable.call(s,o))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){var _=Object.getOwnPropertyDescriptor(s,o);if(42!==_.value||!0!==_.enumerable)return!1}return!0}},49092(s,o,i){"use strict";var a=i(41333);s.exports=function hasToStringTagShams(){return a()&&!!Symbol.toStringTag}},9957(s,o,i){"use strict";var a=Function.prototype.call,u=Object.prototype.hasOwnProperty,_=i(66743);s.exports=_.call(a,u)},45981(s){function deepFreeze(s){return s instanceof Map?s.clear=s.delete=s.set=function(){throw new Error("map is read-only")}:s instanceof Set&&(s.add=s.clear=s.delete=function(){throw new Error("set is read-only")}),Object.freeze(s),Object.getOwnPropertyNames(s).forEach((function(o){var i=s[o];"object"!=typeof i||Object.isFrozen(i)||deepFreeze(i)})),s}var o=deepFreeze,i=deepFreeze;o.default=i;class Response{constructor(s){void 0===s.data&&(s.data={}),this.data=s.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function escapeHTML(s){return s.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function inherit(s,...o){const i=Object.create(null);for(const o in s)i[o]=s[o];return o.forEach((function(s){for(const o in s)i[o]=s[o]})),i}const emitsWrappingTags=s=>!!s.kind;class HTMLRenderer{constructor(s,o){this.buffer="",this.classPrefix=o.classPrefix,s.walk(this)}addText(s){this.buffer+=escapeHTML(s)}openNode(s){if(!emitsWrappingTags(s))return;let o=s.kind;s.sublanguage||(o=`${this.classPrefix}${o}`),this.span(o)}closeNode(s){emitsWrappingTags(s)&&(this.buffer+="")}value(){return this.buffer}span(s){this.buffer+=``}}class TokenTree{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(s){this.top.children.push(s)}openNode(s){const o={kind:s,children:[]};this.add(o),this.stack.push(o)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(s){return this.constructor._walk(s,this.rootNode)}static _walk(s,o){return"string"==typeof o?s.addText(o):o.children&&(s.openNode(o),o.children.forEach((o=>this._walk(s,o))),s.closeNode(o)),s}static _collapse(s){"string"!=typeof s&&s.children&&(s.children.every((s=>"string"==typeof s))?s.children=[s.children.join("")]:s.children.forEach((s=>{TokenTree._collapse(s)})))}}class TokenTreeEmitter extends TokenTree{constructor(s){super(),this.options=s}addKeyword(s,o){""!==s&&(this.openNode(o),this.addText(s),this.closeNode())}addText(s){""!==s&&this.add(s)}addSublanguage(s,o){const i=s.root;i.kind=o,i.sublanguage=!0,this.add(i)}toHTML(){return new HTMLRenderer(this,this.options).value()}finalize(){return!0}}function source(s){return s?"string"==typeof s?s:s.source:null}const a=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;const u="[a-zA-Z]\\w*",_="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",x="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",C="\\b(0b[01]+)",j={begin:"\\\\[\\s\\S]",relevance:0},L={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[j]},B={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[j]},$={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},COMMENT=function(s,o,i={}){const a=inherit({className:"comment",begin:s,end:o,contains:[]},i);return a.contains.push($),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},U=COMMENT("//","$"),V=COMMENT("/\\*","\\*/"),z=COMMENT("#","$"),Y={className:"number",begin:w,relevance:0},Z={className:"number",begin:x,relevance:0},ee={className:"number",begin:C,relevance:0},ie={className:"number",begin:w+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},ae={begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[j,{begin:/\[/,end:/\]/,relevance:0,contains:[j]}]}]},ce={className:"title",begin:u,relevance:0},le={className:"title",begin:_,relevance:0},pe={begin:"\\.\\s*"+_,relevance:0};var de=Object.freeze({__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:u,UNDERSCORE_IDENT_RE:_,NUMBER_RE:w,C_NUMBER_RE:x,BINARY_NUMBER_RE:C,RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(s={})=>{const o=/^#![ ]*\//;return s.binary&&(s.begin=function concat(...s){return s.map((s=>source(s))).join("")}(o,/.*\b/,s.binary,/\b.*/)),inherit({className:"meta",begin:o,end:/$/,relevance:0,"on:begin":(s,o)=>{0!==s.index&&o.ignoreMatch()}},s)},BACKSLASH_ESCAPE:j,APOS_STRING_MODE:L,QUOTE_STRING_MODE:B,PHRASAL_WORDS_MODE:$,COMMENT,C_LINE_COMMENT_MODE:U,C_BLOCK_COMMENT_MODE:V,HASH_COMMENT_MODE:z,NUMBER_MODE:Y,C_NUMBER_MODE:Z,BINARY_NUMBER_MODE:ee,CSS_NUMBER_MODE:ie,REGEXP_MODE:ae,TITLE_MODE:ce,UNDERSCORE_TITLE_MODE:le,METHOD_GUARD:pe,END_SAME_AS_BEGIN:function(s){return Object.assign(s,{"on:begin":(s,o)=>{o.data._beginMatch=s[1]},"on:end":(s,o)=>{o.data._beginMatch!==s[1]&&o.ignoreMatch()}})}});function skipIfhasPrecedingDot(s,o){"."===s.input[s.index-1]&&o.ignoreMatch()}function beginKeywords(s,o){o&&s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",s.__beforeBegin=skipIfhasPrecedingDot,s.keywords=s.keywords||s.beginKeywords,delete s.beginKeywords,void 0===s.relevance&&(s.relevance=0))}function compileIllegal(s,o){Array.isArray(s.illegal)&&(s.illegal=function either(...s){return"("+s.map((s=>source(s))).join("|")+")"}(...s.illegal))}function compileMatch(s,o){if(s.match){if(s.begin||s.end)throw new Error("begin & end are not supported with match");s.begin=s.match,delete s.match}}function compileRelevance(s,o){void 0===s.relevance&&(s.relevance=1)}const fe=["of","and","for","in","not","or","if","then","parent","list","value"];function compileKeywords(s,o,i="keyword"){const a={};return"string"==typeof s?compileList(i,s.split(" ")):Array.isArray(s)?compileList(i,s):Object.keys(s).forEach((function(i){Object.assign(a,compileKeywords(s[i],o,i))})),a;function compileList(s,i){o&&(i=i.map((s=>s.toLowerCase()))),i.forEach((function(o){const i=o.split("|");a[i[0]]=[s,scoreForKeyword(i[0],i[1])]}))}}function scoreForKeyword(s,o){return o?Number(o):function commonKeyword(s){return fe.includes(s.toLowerCase())}(s)?0:1}function compileLanguage(s,{plugins:o}){function langRe(o,i){return new RegExp(source(o),"m"+(s.case_insensitive?"i":"")+(i?"g":""))}class MultiRegex{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(s,o){o.position=this.position++,this.matchIndexes[this.matchAt]=o,this.regexes.push([o,s]),this.matchAt+=function countMatchGroups(s){return new RegExp(s.toString()+"|").exec("").length-1}(s)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const s=this.regexes.map((s=>s[1]));this.matcherRe=langRe(function join(s,o="|"){let i=0;return s.map((s=>{i+=1;const o=i;let u=source(s),_="";for(;u.length>0;){const s=a.exec(u);if(!s){_+=u;break}_+=u.substring(0,s.index),u=u.substring(s.index+s[0].length),"\\"===s[0][0]&&s[1]?_+="\\"+String(Number(s[1])+o):(_+=s[0],"("===s[0]&&i++)}return _})).map((s=>`(${s})`)).join(o)}(s),!0),this.lastIndex=0}exec(s){this.matcherRe.lastIndex=this.lastIndex;const o=this.matcherRe.exec(s);if(!o)return null;const i=o.findIndex(((s,o)=>o>0&&void 0!==s)),a=this.matchIndexes[i];return o.splice(0,i),Object.assign(o,a)}}class ResumableMultiRegex{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(s){if(this.multiRegexes[s])return this.multiRegexes[s];const o=new MultiRegex;return this.rules.slice(s).forEach((([s,i])=>o.addRule(s,i))),o.compile(),this.multiRegexes[s]=o,o}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(s,o){this.rules.push([s,o]),"begin"===o.type&&this.count++}exec(s){const o=this.getMatcher(this.regexIndex);o.lastIndex=this.lastIndex;let i=o.exec(s);if(this.resumingScanAtSamePosition())if(i&&i.index===this.lastIndex);else{const o=this.getMatcher(0);o.lastIndex=this.lastIndex+1,i=o.exec(s)}return i&&(this.regexIndex+=i.position+1,this.regexIndex===this.count&&this.considerAll()),i}}if(s.compilerExtensions||(s.compilerExtensions=[]),s.contains&&s.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return s.classNameAliases=inherit(s.classNameAliases||{}),function compileMode(o,i){const a=o;if(o.isCompiled)return a;[compileMatch].forEach((s=>s(o,i))),s.compilerExtensions.forEach((s=>s(o,i))),o.__beforeBegin=null,[beginKeywords,compileIllegal,compileRelevance].forEach((s=>s(o,i))),o.isCompiled=!0;let u=null;if("object"==typeof o.keywords&&(u=o.keywords.$pattern,delete o.keywords.$pattern),o.keywords&&(o.keywords=compileKeywords(o.keywords,s.case_insensitive)),o.lexemes&&u)throw new Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return u=u||o.lexemes||/\w+/,a.keywordPatternRe=langRe(u,!0),i&&(o.begin||(o.begin=/\B|\b/),a.beginRe=langRe(o.begin),o.endSameAsBegin&&(o.end=o.begin),o.end||o.endsWithParent||(o.end=/\B|\b/),o.end&&(a.endRe=langRe(o.end)),a.terminatorEnd=source(o.end)||"",o.endsWithParent&&i.terminatorEnd&&(a.terminatorEnd+=(o.end?"|":"")+i.terminatorEnd)),o.illegal&&(a.illegalRe=langRe(o.illegal)),o.contains||(o.contains=[]),o.contains=[].concat(...o.contains.map((function(s){return function expandOrCloneMode(s){s.variants&&!s.cachedVariants&&(s.cachedVariants=s.variants.map((function(o){return inherit(s,{variants:null},o)})));if(s.cachedVariants)return s.cachedVariants;if(dependencyOnParent(s))return inherit(s,{starts:s.starts?inherit(s.starts):null});if(Object.isFrozen(s))return inherit(s);return s}("self"===s?o:s)}))),o.contains.forEach((function(s){compileMode(s,a)})),o.starts&&compileMode(o.starts,i),a.matcher=function buildModeRegex(s){const o=new ResumableMultiRegex;return s.contains.forEach((s=>o.addRule(s.begin,{rule:s,type:"begin"}))),s.terminatorEnd&&o.addRule(s.terminatorEnd,{type:"end"}),s.illegal&&o.addRule(s.illegal,{type:"illegal"}),o}(a),a}(s)}function dependencyOnParent(s){return!!s&&(s.endsWithParent||dependencyOnParent(s.starts))}function BuildVuePlugin(s){const o={props:["language","code","autodetect"],data:function(){return{detectedLanguage:"",unknownLanguage:!1}},computed:{className(){return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){if(!this.autoDetect&&!s.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`),this.unknownLanguage=!0,escapeHTML(this.code);let o={};return this.autoDetect?(o=s.highlightAuto(this.code),this.detectedLanguage=o.language):(o=s.highlight(this.language,this.code,this.ignoreIllegals),this.detectedLanguage=this.language),o.value},autoDetect(){return!this.language||function hasValueOrEmptyAttribute(s){return Boolean(s||""===s)}(this.autodetect)},ignoreIllegals:()=>!0},render(s){return s("pre",{},[s("code",{class:this.className,domProps:{innerHTML:this.highlighted}})])}};return{Component:o,VuePlugin:{install(s){s.component("highlightjs",o)}}}}const ye={"after:highlightElement":({el:s,result:o,text:i})=>{const a=nodeStream(s);if(!a.length)return;const u=document.createElement("div");u.innerHTML=o.value,o.value=function mergeStreams(s,o,i){let a=0,u="";const _=[];function selectStream(){return s.length&&o.length?s[0].offset!==o[0].offset?s[0].offset"}function close(s){u+=""}function render(s){("start"===s.event?open:close)(s.node)}for(;s.length||o.length;){let o=selectStream();if(u+=escapeHTML(i.substring(a,o[0].offset)),a=o[0].offset,o===s){_.reverse().forEach(close);do{render(o.splice(0,1)[0]),o=selectStream()}while(o===s&&o.length&&o[0].offset===a);_.reverse().forEach(open)}else"start"===o[0].event?_.push(o[0].node):_.pop(),render(o.splice(0,1)[0])}return u+escapeHTML(i.substr(a))}(a,nodeStream(u),i)}};function tag(s){return s.nodeName.toLowerCase()}function nodeStream(s){const o=[];return function _nodeStream(s,i){for(let a=s.firstChild;a;a=a.nextSibling)3===a.nodeType?i+=a.nodeValue.length:1===a.nodeType&&(o.push({event:"start",offset:i,node:a}),i=_nodeStream(a,i),tag(a).match(/br|hr|img|input/)||o.push({event:"stop",offset:i,node:a}));return i}(s,0),o}const be={},error=s=>{console.error(s)},warn=(s,...o)=>{console.log(`WARN: ${s}`,...o)},deprecated=(s,o)=>{be[`${s}/${o}`]||(console.log(`Deprecated as of ${s}. ${o}`),be[`${s}/${o}`]=!0)},Se=escapeHTML,_e=inherit,we=Symbol("nomatch");var xe=function(s){const i=Object.create(null),a=Object.create(null),u=[];let _=!0;const w=/(^(<[^>]+>|\t|)+|\n)/gm,x="Could not find the language '{}', did you forget to load/include a language module?",C={disableAutodetect:!0,name:"Plain text",contains:[]};let j={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:TokenTreeEmitter};function shouldNotHighlight(s){return j.noHighlightRe.test(s)}function highlight(s,o,i,a){let u="",_="";"object"==typeof o?(u=s,i=o.ignoreIllegals,_=o.language,a=void 0):(deprecated("10.7.0","highlight(lang, code, ...args) has been deprecated."),deprecated("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),_=s,u=o);const w={code:u,language:_};fire("before:highlight",w);const x=w.result?w.result:_highlight(w.language,w.code,i,a);return x.code=w.code,fire("after:highlight",x),x}function _highlight(s,o,a,w){function keywordData(s,o){const i=L.case_insensitive?o[0].toLowerCase():o[0];return Object.prototype.hasOwnProperty.call(s.keywords,i)&&s.keywords[i]}function processBuffer(){null!=U.subLanguage?function processSubLanguage(){if(""===Y)return;let s=null;if("string"==typeof U.subLanguage){if(!i[U.subLanguage])return void z.addText(Y);s=_highlight(U.subLanguage,Y,!0,V[U.subLanguage]),V[U.subLanguage]=s.top}else s=highlightAuto(Y,U.subLanguage.length?U.subLanguage:null);U.relevance>0&&(Z+=s.relevance),z.addSublanguage(s.emitter,s.language)}():function processKeywords(){if(!U.keywords)return void z.addText(Y);let s=0;U.keywordPatternRe.lastIndex=0;let o=U.keywordPatternRe.exec(Y),i="";for(;o;){i+=Y.substring(s,o.index);const a=keywordData(U,o);if(a){const[s,u]=a;if(z.addText(i),i="",Z+=u,s.startsWith("_"))i+=o[0];else{const i=L.classNameAliases[s]||s;z.addKeyword(o[0],i)}}else i+=o[0];s=U.keywordPatternRe.lastIndex,o=U.keywordPatternRe.exec(Y)}i+=Y.substr(s),z.addText(i)}(),Y=""}function startNewMode(s){return s.className&&z.openNode(L.classNameAliases[s.className]||s.className),U=Object.create(s,{parent:{value:U}}),U}function endOfMode(s,o,i){let a=function startsWith(s,o){const i=s&&s.exec(o);return i&&0===i.index}(s.endRe,i);if(a){if(s["on:end"]){const i=new Response(s);s["on:end"](o,i),i.isMatchIgnored&&(a=!1)}if(a){for(;s.endsParent&&s.parent;)s=s.parent;return s}}if(s.endsWithParent)return endOfMode(s.parent,o,i)}function doIgnore(s){return 0===U.matcher.regexIndex?(Y+=s[0],1):(ae=!0,0)}function doBeginMatch(s){const o=s[0],i=s.rule,a=new Response(i),u=[i.__beforeBegin,i["on:begin"]];for(const i of u)if(i&&(i(s,a),a.isMatchIgnored))return doIgnore(o);return i&&i.endSameAsBegin&&(i.endRe=function escape(s){return new RegExp(s.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")}(o)),i.skip?Y+=o:(i.excludeBegin&&(Y+=o),processBuffer(),i.returnBegin||i.excludeBegin||(Y=o)),startNewMode(i),i.returnBegin?0:o.length}function doEndMatch(s){const i=s[0],a=o.substr(s.index),u=endOfMode(U,s,a);if(!u)return we;const _=U;_.skip?Y+=i:(_.returnEnd||_.excludeEnd||(Y+=i),processBuffer(),_.excludeEnd&&(Y=i));do{U.className&&z.closeNode(),U.skip||U.subLanguage||(Z+=U.relevance),U=U.parent}while(U!==u.parent);return u.starts&&(u.endSameAsBegin&&(u.starts.endRe=u.endRe),startNewMode(u.starts)),_.returnEnd?0:i.length}let C={};function processLexeme(i,u){const w=u&&u[0];if(Y+=i,null==w)return processBuffer(),0;if("begin"===C.type&&"end"===u.type&&C.index===u.index&&""===w){if(Y+=o.slice(u.index,u.index+1),!_){const o=new Error("0 width match regex");throw o.languageName=s,o.badRule=C.rule,o}return 1}if(C=u,"begin"===u.type)return doBeginMatch(u);if("illegal"===u.type&&!a){const s=new Error('Illegal lexeme "'+w+'" for mode "'+(U.className||"")+'"');throw s.mode=U,s}if("end"===u.type){const s=doEndMatch(u);if(s!==we)return s}if("illegal"===u.type&&""===w)return 1;if(ie>1e5&&ie>3*u.index){throw new Error("potential infinite loop, way more iterations than matches")}return Y+=w,w.length}const L=getLanguage(s);if(!L)throw error(x.replace("{}",s)),new Error('Unknown language: "'+s+'"');const B=compileLanguage(L,{plugins:u});let $="",U=w||B;const V={},z=new j.__emitter(j);!function processContinuations(){const s=[];for(let o=U;o!==L;o=o.parent)o.className&&s.unshift(o.className);s.forEach((s=>z.openNode(s)))}();let Y="",Z=0,ee=0,ie=0,ae=!1;try{for(U.matcher.considerAll();;){ie++,ae?ae=!1:U.matcher.considerAll(),U.matcher.lastIndex=ee;const s=U.matcher.exec(o);if(!s)break;const i=processLexeme(o.substring(ee,s.index),s);ee=s.index+i}return processLexeme(o.substr(ee)),z.closeAllNodes(),z.finalize(),$=z.toHTML(),{relevance:Math.floor(Z),value:$,language:s,illegal:!1,emitter:z,top:U}}catch(i){if(i.message&&i.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:i.message,context:o.slice(ee-100,ee+100),mode:i.mode},sofar:$,relevance:0,value:Se(o),emitter:z};if(_)return{illegal:!1,relevance:0,value:Se(o),emitter:z,language:s,top:U,errorRaised:i};throw i}}function highlightAuto(s,o){o=o||j.languages||Object.keys(i);const a=function justTextHighlightResult(s){const o={relevance:0,emitter:new j.__emitter(j),value:Se(s),illegal:!1,top:C};return o.emitter.addText(s),o}(s),u=o.filter(getLanguage).filter(autoDetection).map((o=>_highlight(o,s,!1)));u.unshift(a);const _=u.sort(((s,o)=>{if(s.relevance!==o.relevance)return o.relevance-s.relevance;if(s.language&&o.language){if(getLanguage(s.language).supersetOf===o.language)return 1;if(getLanguage(o.language).supersetOf===s.language)return-1}return 0})),[w,x]=_,L=w;return L.second_best=x,L}const L={"before:highlightElement":({el:s})=>{j.useBR&&(s.innerHTML=s.innerHTML.replace(/\n/g,"").replace(//g,"\n"))},"after:highlightElement":({result:s})=>{j.useBR&&(s.value=s.value.replace(/\n/g,"
"))}},B=/^(<[^>]+>|\t)+/gm,$={"after:highlightElement":({result:s})=>{j.tabReplace&&(s.value=s.value.replace(B,(s=>s.replace(/\t/g,j.tabReplace))))}};function highlightElement(s){let o=null;const i=function blockLanguage(s){let o=s.className+" ";o+=s.parentNode?s.parentNode.className:"";const i=j.languageDetectRe.exec(o);if(i){const o=getLanguage(i[1]);return o||(warn(x.replace("{}",i[1])),warn("Falling back to no-highlight mode for this block.",s)),o?i[1]:"no-highlight"}return o.split(/\s+/).find((s=>shouldNotHighlight(s)||getLanguage(s)))}(s);if(shouldNotHighlight(i))return;fire("before:highlightElement",{el:s,language:i}),o=s;const u=o.textContent,_=i?highlight(u,{language:i,ignoreIllegals:!0}):highlightAuto(u);fire("after:highlightElement",{el:s,result:_,text:u}),s.innerHTML=_.value,function updateClassName(s,o,i){const u=o?a[o]:i;s.classList.add("hljs"),u&&s.classList.add(u)}(s,i,_.language),s.result={language:_.language,re:_.relevance,relavance:_.relevance},_.second_best&&(s.second_best={language:_.second_best.language,re:_.second_best.relevance,relavance:_.second_best.relevance})}const initHighlighting=()=>{if(initHighlighting.called)return;initHighlighting.called=!0,deprecated("10.6.0","initHighlighting() is deprecated. Use highlightAll() instead.");document.querySelectorAll("pre code").forEach(highlightElement)};let U=!1;function highlightAll(){if("loading"===document.readyState)return void(U=!0);document.querySelectorAll("pre code").forEach(highlightElement)}function getLanguage(s){return s=(s||"").toLowerCase(),i[s]||i[a[s]]}function registerAliases(s,{languageName:o}){"string"==typeof s&&(s=[s]),s.forEach((s=>{a[s.toLowerCase()]=o}))}function autoDetection(s){const o=getLanguage(s);return o&&!o.disableAutodetect}function fire(s,o){const i=s;u.forEach((function(s){s[i]&&s[i](o)}))}"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(function boot(){U&&highlightAll()}),!1),Object.assign(s,{highlight,highlightAuto,highlightAll,fixMarkup:function deprecateFixMarkup(s){return deprecated("10.2.0","fixMarkup will be removed entirely in v11.0"),deprecated("10.2.0","Please see https://github.com/highlightjs/highlight.js/issues/2534"),function fixMarkup(s){return j.tabReplace||j.useBR?s.replace(w,(s=>"\n"===s?j.useBR?"
":s:j.tabReplace?s.replace(/\t/g,j.tabReplace):s)):s}(s)},highlightElement,highlightBlock:function deprecateHighlightBlock(s){return deprecated("10.7.0","highlightBlock will be removed entirely in v12.0"),deprecated("10.7.0","Please use highlightElement now."),highlightElement(s)},configure:function configure(s){s.useBR&&(deprecated("10.3.0","'useBR' will be removed entirely in v11.0"),deprecated("10.3.0","Please see https://github.com/highlightjs/highlight.js/issues/2559")),j=_e(j,s)},initHighlighting,initHighlightingOnLoad:function initHighlightingOnLoad(){deprecated("10.6.0","initHighlightingOnLoad() is deprecated. Use highlightAll() instead."),U=!0},registerLanguage:function registerLanguage(o,a){let u=null;try{u=a(s)}catch(s){if(error("Language definition for '{}' could not be registered.".replace("{}",o)),!_)throw s;error(s),u=C}u.name||(u.name=o),i[o]=u,u.rawDefinition=a.bind(null,s),u.aliases&®isterAliases(u.aliases,{languageName:o})},unregisterLanguage:function unregisterLanguage(s){delete i[s];for(const o of Object.keys(a))a[o]===s&&delete a[o]},listLanguages:function listLanguages(){return Object.keys(i)},getLanguage,registerAliases,requireLanguage:function requireLanguage(s){deprecated("10.4.0","requireLanguage will be removed entirely in v11."),deprecated("10.4.0","Please see https://github.com/highlightjs/highlight.js/pull/2844");const o=getLanguage(s);if(o)return o;throw new Error("The '{}' language is required, but not loaded.".replace("{}",s))},autoDetection,inherit:_e,addPlugin:function addPlugin(s){!function upgradePluginAPI(s){s["before:highlightBlock"]&&!s["before:highlightElement"]&&(s["before:highlightElement"]=o=>{s["before:highlightBlock"](Object.assign({block:o.el},o))}),s["after:highlightBlock"]&&!s["after:highlightElement"]&&(s["after:highlightElement"]=o=>{s["after:highlightBlock"](Object.assign({block:o.el},o))})}(s),u.push(s)},vuePlugin:BuildVuePlugin(s).VuePlugin}),s.debugMode=function(){_=!1},s.safeMode=function(){_=!0},s.versionString="10.7.3";for(const s in de)"object"==typeof de[s]&&o(de[s]);return Object.assign(s,de),s.addPlugin(L),s.addPlugin(ye),s.addPlugin($),s}({});s.exports=xe},35344(s){function concat(...s){return s.map((s=>function source(s){return s?"string"==typeof s?s:s.source:null}(s))).join("")}s.exports=function bash(s){const o={},i={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[o]}]};Object.assign(o,{className:"variable",variants:[{begin:concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},i]});const a={className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},u={begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},_={className:"string",begin:/"/,end:/"/,contains:[s.BACKSLASH_ESCAPE,o,a]};a.contains.push(_);const w={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,o]},x=s.SHEBANG({binary:`(${["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"].join("|")})`,relevance:10}),C={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp"},contains:[x,s.SHEBANG(),C,w,s.HASH_COMMENT_MODE,u,_,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},o]}}},73402(s){function concat(...s){return s.map((s=>function source(s){return s?"string"==typeof s?s:s.source:null}(s))).join("")}s.exports=function http(s){const o="HTTP/(2|1\\.[01])",i={className:"attribute",begin:concat("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]}},a=[i,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+o+" \\d{3})",end:/$/,contains:[{className:"meta",begin:o},{className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:a}},{begin:"(?=^[A-Z]+ (.*?) "+o+"$)",end:/$/,contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:o},{className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:a}},s.inherit(i,{relevance:0})]}}},95089(s){const o="[A-Za-z$_][0-9A-Za-z$_]*",i=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],u=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function lookahead(s){return concat("(?=",s,")")}function concat(...s){return s.map((s=>function source(s){return s?"string"==typeof s?s:s.source:null}(s))).join("")}s.exports=function javascript(s){const _=o,w="<>",x="",C={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(s,o)=>{const i=s[0].length+s.index,a=s.input[i];"<"!==a?">"===a&&(((s,{after:o})=>{const i="",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:s.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:j,contains:ce}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:w,end:x},{begin:C.begin,"on:begin":C.isTrulyOpeningTag,end:C.end}],subLanguage:"xml",contains:[{begin:C.begin,end:C.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:j,contains:["self",s.inherit(s.TITLE_MODE,{begin:_}),le],illegal:/%/},{beginKeywords:"while if switch catch for"},{className:"function",begin:s.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,contains:[le,s.inherit(s.TITLE_MODE,{begin:_})]},{variants:[{begin:"\\."+_},{begin:"\\$"+_}],relevance:0},{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{beginKeywords:"extends"},s.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/,end:/[{;]/,excludeEnd:!0,contains:[s.inherit(s.TITLE_MODE,{begin:_}),"self",le]},{begin:"(get|set)\\s+(?="+_+"\\()",end:/\{/,keywords:"get set",contains:[s.inherit(s.TITLE_MODE,{begin:_}),{begin:/\(\)/},le]},{begin:/\$[(.]/}]}}},65772(s){s.exports=function json(s){const o={literal:"true false null"},i=[s.C_LINE_COMMENT_MODE,s.C_BLOCK_COMMENT_MODE],a=[s.QUOTE_STRING_MODE,s.C_NUMBER_MODE],u={end:",",endsWithParent:!0,excludeEnd:!0,contains:a,keywords:o},_={begin:/\{/,end:/\}/,contains:[{className:"attr",begin:/"/,end:/"/,contains:[s.BACKSLASH_ESCAPE],illegal:"\\n"},s.inherit(u,{begin:/:/})].concat(i),illegal:"\\S"},w={begin:"\\[",end:"\\]",contains:[s.inherit(u)],illegal:"\\S"};return a.push(_,w),i.forEach((function(s){a.push(s)})),{name:"JSON",contains:a,keywords:o,illegal:"\\S"}}},26571(s){s.exports=function powershell(s){const o={$pattern:/-?[A-z\.\-]+\b/,keyword:"if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter",built_in:"ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write"},i={begin:"`[\\s\\S]",relevance:0},a={className:"variable",variants:[{begin:/\$\B/},{className:"keyword",begin:/\$this/},{begin:/\$[\w\d][\w\d_:]*/}]},u={className:"string",variants:[{begin:/"/,end:/"/},{begin:/@"/,end:/^"@/}],contains:[i,a,{className:"variable",begin:/\$[A-z]/,end:/[^A-z]/}]},_={className:"string",variants:[{begin:/'/,end:/'/},{begin:/@'/,end:/^'@/}]},w=s.inherit(s.COMMENT(null,null),{variants:[{begin:/#/,end:/$/},{begin:/<#/,end:/#>/}],contains:[{className:"doctag",variants:[{begin:/\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/},{begin:/\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/}]}]}),x={className:"built_in",variants:[{begin:"(".concat("Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where",")+(-)[\\w\\d]+")}]},C={className:"class",beginKeywords:"class enum",end:/\s*[{]/,excludeEnd:!0,relevance:0,contains:[s.TITLE_MODE]},j={className:"function",begin:/function\s+/,end:/\s*\{|$/,excludeEnd:!0,returnBegin:!0,relevance:0,contains:[{begin:"function",relevance:0,className:"keyword"},{className:"title",begin:/\w[\w\d]*((-)[\w\d]+)*/,relevance:0},{begin:/\(/,end:/\)/,className:"params",relevance:0,contains:[a]}]},L={begin:/using\s/,end:/$/,returnBegin:!0,contains:[u,_,{className:"keyword",begin:/(using|assembly|command|module|namespace|type)/}]},B={variants:[{className:"operator",begin:"(".concat("-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor",")\\b")},{className:"literal",begin:/(-)[\w\d]+/,relevance:0}]},$={className:"function",begin:/\[.*\]\s*[\w]+[ ]??\(/,end:/$/,returnBegin:!0,relevance:0,contains:[{className:"keyword",begin:"(".concat(o.keyword.toString().replace(/\s/g,"|"),")\\b"),endsParent:!0,relevance:0},s.inherit(s.TITLE_MODE,{endsParent:!0})]},U=[$,w,i,s.NUMBER_MODE,u,_,x,a,{className:"literal",begin:/\$(null|true|false)\b/},{className:"selector-tag",begin:/@\B/,relevance:0}],V={begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[].concat("self",U,{begin:"("+["string","char","byte","int","long","bool","decimal","single","double","DateTime","xml","array","hashtable","void"].join("|")+")",className:"built_in",relevance:0},{className:"type",begin:/[\.\w\d]+/,relevance:0})};return $.contains.unshift(V),{name:"PowerShell",aliases:["ps","ps1"],case_insensitive:!0,keywords:o,contains:U.concat(C,j,L,B,V)}}},17285(s){function source(s){return s?"string"==typeof s?s:s.source:null}function lookahead(s){return concat("(?=",s,")")}function concat(...s){return s.map((s=>source(s))).join("")}function either(...s){return"("+s.map((s=>source(s))).join("|")+")"}s.exports=function xml(s){const o=concat(/[A-Z_]/,function optional(s){return concat("(",s,")?")}(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),i={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},a={begin:/\s/,contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},u=s.inherit(a,{begin:/\(/,end:/\)/}),_=s.inherit(s.APOS_STRING_MODE,{className:"meta-string"}),w=s.inherit(s.QUOTE_STRING_MODE,{className:"meta-string"}),x={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[a,w,_,u,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[a,u,w,_]}]}]},s.COMMENT(//,{relevance:10}),{begin://,relevance:10},i,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[x],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[x],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:o,relevance:0,starts:x}]},{className:"tag",begin:concat(/<\//,lookahead(concat(o,/>/))),contains:[{className:"name",begin:o,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}},17533(s){s.exports=function yaml(s){var o="true false yes no null",i="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[s.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},u=s.inherit(a,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),_={className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},w={end:",",endsWithParent:!0,excludeEnd:!0,keywords:o,relevance:0},x={begin:/\{/,end:/\}/,contains:[w],illegal:"\\n",relevance:0},C={begin:"\\[",end:"\\]",contains:[w],illegal:"\\n",relevance:0},j=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+i},{className:"type",begin:"!<"+i+">"},{className:"type",begin:"!"+i},{className:"type",begin:"!!"+i},{className:"meta",begin:"&"+s.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+s.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},s.HASH_COMMENT_MODE,{beginKeywords:o,keywords:{literal:o}},_,{className:"number",begin:s.C_NUMBER_RE+"\\b",relevance:0},x,C,a],L=[...j];return L.pop(),L.push(u),w.contains=L,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:j}}},251(s,o){o.read=function(s,o,i,a,u){var _,w,x=8*u-a-1,C=(1<>1,L=-7,B=i?u-1:0,$=i?-1:1,U=s[o+B];for(B+=$,_=U&(1<<-L)-1,U>>=-L,L+=x;L>0;_=256*_+s[o+B],B+=$,L-=8);for(w=_&(1<<-L)-1,_>>=-L,L+=a;L>0;w=256*w+s[o+B],B+=$,L-=8);if(0===_)_=1-j;else{if(_===C)return w?NaN:1/0*(U?-1:1);w+=Math.pow(2,a),_-=j}return(U?-1:1)*w*Math.pow(2,_-a)},o.write=function(s,o,i,a,u,_){var w,x,C,j=8*_-u-1,L=(1<>1,$=23===u?Math.pow(2,-24)-Math.pow(2,-77):0,U=a?0:_-1,V=a?1:-1,z=o<0||0===o&&1/o<0?1:0;for(o=Math.abs(o),isNaN(o)||o===1/0?(x=isNaN(o)?1:0,w=L):(w=Math.floor(Math.log(o)/Math.LN2),o*(C=Math.pow(2,-w))<1&&(w--,C*=2),(o+=w+B>=1?$/C:$*Math.pow(2,1-B))*C>=2&&(w++,C/=2),w+B>=L?(x=0,w=L):w+B>=1?(x=(o*C-1)*Math.pow(2,u),w+=B):(x=o*Math.pow(2,B-1)*Math.pow(2,u),w=0));u>=8;s[i+U]=255&x,U+=V,x/=256,u-=8);for(w=w<0;s[i+U]=255&w,U+=V,w/=256,j-=8);s[i+U-V]|=128*z}},49568(s,o,i){"use strict";i.r(o),i.d(o,{Collection:()=>L,Iterable:()=>Zt,List:()=>Et,Map:()=>at,OrderedMap:()=>jt,OrderedSet:()=>zt,PairSorting:()=>Ht,Range:()=>Bt,Record:()=>Kt,Repeat:()=>Xt,Seq:()=>le,Set:()=>Rt,Stack:()=>Tt,default:()=>er,fromJS:()=>fromJS,get:()=>get,getIn:()=>getIn$1,has:()=>has,hasIn:()=>hasIn$1,hash:()=>hash,is:()=>is,isAssociative:()=>isAssociative,isCollection:()=>isCollection,isImmutable:()=>isImmutable,isIndexed:()=>isIndexed,isKeyed:()=>isKeyed,isList:()=>isList,isMap:()=>isMap,isOrdered:()=>isOrdered,isOrderedMap:()=>isOrderedMap,isOrderedSet:()=>isOrderedSet,isPlainObject:()=>isPlainObject,isRecord:()=>isRecord,isSeq:()=>isSeq,isSet:()=>isSet,isStack:()=>isStack,isValueObject:()=>isValueObject,merge:()=>merge,mergeDeep:()=>mergeDeep$1,mergeDeepWith:()=>mergeDeepWith$1,mergeWith:()=>mergeWith,remove:()=>remove,removeIn:()=>removeIn,set:()=>set,setIn:()=>setIn$1,update:()=>update$1,updateIn:()=>updateIn$1,version:()=>Qt});var a="delete",u=32,_=31,w={};function SetRef(s){s&&(s.value=!0)}function OwnerID(){}function ensureSize(s){return void 0===s.size&&(s.size=s.__iterate(returnTrue)),s.size}function wrapIndex(s,o){if("number"!=typeof o){var i=o>>>0;if(""+i!==o||4294967295===i)return NaN;o=i}return o<0?ensureSize(s)+o:o}function returnTrue(){return!0}function wholeSlice(s,o,i){return(0===s&&!isNeg(s)||void 0!==i&&s<=-i)&&(void 0===o||void 0!==i&&o>=i)}function resolveBegin(s,o){return resolveIndex(s,o,0)}function resolveEnd(s,o){return resolveIndex(s,o,o)}function resolveIndex(s,o,i){return void 0===s?i:isNeg(s)?o===1/0?o:0|Math.max(0,o+s):void 0===o||o===s?s:0|Math.min(o,s)}function isNeg(s){return s<0||0===s&&1/s==-1/0}var x="@@__IMMUTABLE_ITERABLE__@@";function isCollection(s){return Boolean(s&&s[x])}var C="@@__IMMUTABLE_KEYED__@@";function isKeyed(s){return Boolean(s&&s[C])}var j="@@__IMMUTABLE_INDEXED__@@";function isIndexed(s){return Boolean(s&&s[j])}function isAssociative(s){return isKeyed(s)||isIndexed(s)}var L=function Collection(s){return isCollection(s)?s:le(s)},B=function(s){function KeyedCollection(s){return isKeyed(s)?s:pe(s)}return s&&(KeyedCollection.__proto__=s),KeyedCollection.prototype=Object.create(s&&s.prototype),KeyedCollection.prototype.constructor=KeyedCollection,KeyedCollection}(L),$=function(s){function IndexedCollection(s){return isIndexed(s)?s:de(s)}return s&&(IndexedCollection.__proto__=s),IndexedCollection.prototype=Object.create(s&&s.prototype),IndexedCollection.prototype.constructor=IndexedCollection,IndexedCollection}(L),U=function(s){function SetCollection(s){return isCollection(s)&&!isAssociative(s)?s:fe(s)}return s&&(SetCollection.__proto__=s),SetCollection.prototype=Object.create(s&&s.prototype),SetCollection.prototype.constructor=SetCollection,SetCollection}(L);L.Keyed=B,L.Indexed=$,L.Set=U;var V="@@__IMMUTABLE_SEQ__@@";function isSeq(s){return Boolean(s&&s[V])}var z="@@__IMMUTABLE_RECORD__@@";function isRecord(s){return Boolean(s&&s[z])}function isImmutable(s){return isCollection(s)||isRecord(s)}var Y="@@__IMMUTABLE_ORDERED__@@";function isOrdered(s){return Boolean(s&&s[Y])}var Z="function"==typeof Symbol&&Symbol.iterator,ee="@@iterator",ie=Z||ee,ae=function Iterator(s){this.next=s};function iteratorValue(s,o,i,a){var u=0===s?o:1===s?i:[o,i];return a?a.value=u:a={value:u,done:!1},a}function iteratorDone(){return{value:void 0,done:!0}}function hasIterator(s){return!!Array.isArray(s)||!!getIteratorFn(s)}function isIterator(s){return s&&"function"==typeof s.next}function getIterator(s){var o=getIteratorFn(s);return o&&o.call(s)}function getIteratorFn(s){var o=s&&(Z&&s[Z]||s[ee]);if("function"==typeof o)return o}ae.prototype.toString=function toString(){return"[Iterator]"},ae.KEYS=0,ae.VALUES=1,ae.ENTRIES=2,ae.prototype.inspect=ae.prototype.toSource=function(){return this.toString()},ae.prototype[ie]=function(){return this};var ce=Object.prototype.hasOwnProperty;function isArrayLike(s){return!(!Array.isArray(s)&&"string"!=typeof s)||s&&"object"==typeof s&&Number.isInteger(s.length)&&s.length>=0&&(0===s.length?1===Object.keys(s).length:s.hasOwnProperty(s.length-1))}var le=function(s){function Seq(s){return null==s?emptySequence():isImmutable(s)?s.toSeq():function seqFromValue(s){var o=maybeIndexedSeqFromValue(s);if(o)return function isEntriesIterable(s){var o=getIteratorFn(s);return o&&o===s.entries}(s)?o.fromEntrySeq():function isKeysIterable(s){var o=getIteratorFn(s);return o&&o===s.keys}(s)?o.toSetSeq():o;if("object"==typeof s)return new be(s);throw new TypeError("Expected Array or collection object of values, or keyed object: "+s)}(s)}return s&&(Seq.__proto__=s),Seq.prototype=Object.create(s&&s.prototype),Seq.prototype.constructor=Seq,Seq.prototype.toSeq=function toSeq(){return this},Seq.prototype.toString=function toString(){return this.__toString("Seq {","}")},Seq.prototype.cacheResult=function cacheResult(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},Seq.prototype.__iterate=function __iterate(s,o){var i=this._cache;if(i){for(var a=i.length,u=0;u!==a;){var _=i[o?a-++u:u++];if(!1===s(_[1],_[0],this))break}return u}return this.__iterateUncached(s,o)},Seq.prototype.__iterator=function __iterator(s,o){var i=this._cache;if(i){var a=i.length,u=0;return new ae((function(){if(u===a)return{value:void 0,done:!0};var _=i[o?a-++u:u++];return iteratorValue(s,_[0],_[1])}))}return this.__iteratorUncached(s,o)},Seq}(L),pe=function(s){function KeyedSeq(s){return null==s?emptySequence().toKeyedSeq():isCollection(s)?isKeyed(s)?s.toSeq():s.fromEntrySeq():isRecord(s)?s.toSeq():keyedSeqFromValue(s)}return s&&(KeyedSeq.__proto__=s),KeyedSeq.prototype=Object.create(s&&s.prototype),KeyedSeq.prototype.constructor=KeyedSeq,KeyedSeq.prototype.toKeyedSeq=function toKeyedSeq(){return this},KeyedSeq}(le),de=function(s){function IndexedSeq(s){return null==s?emptySequence():isCollection(s)?isKeyed(s)?s.entrySeq():s.toIndexedSeq():isRecord(s)?s.toSeq().entrySeq():indexedSeqFromValue(s)}return s&&(IndexedSeq.__proto__=s),IndexedSeq.prototype=Object.create(s&&s.prototype),IndexedSeq.prototype.constructor=IndexedSeq,IndexedSeq.of=function of(){return IndexedSeq(arguments)},IndexedSeq.prototype.toIndexedSeq=function toIndexedSeq(){return this},IndexedSeq.prototype.toString=function toString(){return this.__toString("Seq [","]")},IndexedSeq}(le),fe=function(s){function SetSeq(s){return(isCollection(s)&&!isAssociative(s)?s:de(s)).toSetSeq()}return s&&(SetSeq.__proto__=s),SetSeq.prototype=Object.create(s&&s.prototype),SetSeq.prototype.constructor=SetSeq,SetSeq.of=function of(){return SetSeq(arguments)},SetSeq.prototype.toSetSeq=function toSetSeq(){return this},SetSeq}(le);le.isSeq=isSeq,le.Keyed=pe,le.Set=fe,le.Indexed=de,le.prototype[V]=!0;var ye=function(s){function ArraySeq(s){this._array=s,this.size=s.length}return s&&(ArraySeq.__proto__=s),ArraySeq.prototype=Object.create(s&&s.prototype),ArraySeq.prototype.constructor=ArraySeq,ArraySeq.prototype.get=function get(s,o){return this.has(s)?this._array[wrapIndex(this,s)]:o},ArraySeq.prototype.__iterate=function __iterate(s,o){for(var i=this._array,a=i.length,u=0;u!==a;){var _=o?a-++u:u++;if(!1===s(i[_],_,this))break}return u},ArraySeq.prototype.__iterator=function __iterator(s,o){var i=this._array,a=i.length,u=0;return new ae((function(){if(u===a)return{value:void 0,done:!0};var _=o?a-++u:u++;return iteratorValue(s,_,i[_])}))},ArraySeq}(de),be=function(s){function ObjectSeq(s){var o=Object.keys(s).concat(Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(s):[]);this._object=s,this._keys=o,this.size=o.length}return s&&(ObjectSeq.__proto__=s),ObjectSeq.prototype=Object.create(s&&s.prototype),ObjectSeq.prototype.constructor=ObjectSeq,ObjectSeq.prototype.get=function get(s,o){return void 0===o||this.has(s)?this._object[s]:o},ObjectSeq.prototype.has=function has(s){return ce.call(this._object,s)},ObjectSeq.prototype.__iterate=function __iterate(s,o){for(var i=this._object,a=this._keys,u=a.length,_=0;_!==u;){var w=a[o?u-++_:_++];if(!1===s(i[w],w,this))break}return _},ObjectSeq.prototype.__iterator=function __iterator(s,o){var i=this._object,a=this._keys,u=a.length,_=0;return new ae((function(){if(_===u)return{value:void 0,done:!0};var w=a[o?u-++_:_++];return iteratorValue(s,w,i[w])}))},ObjectSeq}(pe);be.prototype[Y]=!0;var Se,_e=function(s){function CollectionSeq(s){this._collection=s,this.size=s.length||s.size}return s&&(CollectionSeq.__proto__=s),CollectionSeq.prototype=Object.create(s&&s.prototype),CollectionSeq.prototype.constructor=CollectionSeq,CollectionSeq.prototype.__iterateUncached=function __iterateUncached(s,o){if(o)return this.cacheResult().__iterate(s,o);var i=getIterator(this._collection),a=0;if(isIterator(i))for(var u;!(u=i.next()).done&&!1!==s(u.value,a++,this););return a},CollectionSeq.prototype.__iteratorUncached=function __iteratorUncached(s,o){if(o)return this.cacheResult().__iterator(s,o);var i=getIterator(this._collection);if(!isIterator(i))return new ae(iteratorDone);var a=0;return new ae((function(){var o=i.next();return o.done?o:iteratorValue(s,a++,o.value)}))},CollectionSeq}(de);function emptySequence(){return Se||(Se=new ye([]))}function keyedSeqFromValue(s){var o=maybeIndexedSeqFromValue(s);if(o)return o.fromEntrySeq();if("object"==typeof s)return new be(s);throw new TypeError("Expected Array or collection object of [k, v] entries, or keyed object: "+s)}function indexedSeqFromValue(s){var o=maybeIndexedSeqFromValue(s);if(o)return o;throw new TypeError("Expected Array or collection object of values: "+s)}function maybeIndexedSeqFromValue(s){return isArrayLike(s)?new ye(s):hasIterator(s)?new _e(s):void 0}var we="@@__IMMUTABLE_MAP__@@";function isMap(s){return Boolean(s&&s[we])}function isOrderedMap(s){return isMap(s)&&isOrdered(s)}function isValueObject(s){return Boolean(s&&"function"==typeof s.equals&&"function"==typeof s.hashCode)}function is(s,o){if(s===o||s!=s&&o!=o)return!0;if(!s||!o)return!1;if("function"==typeof s.valueOf&&"function"==typeof o.valueOf){if((s=s.valueOf())===(o=o.valueOf())||s!=s&&o!=o)return!0;if(!s||!o)return!1}return!!(isValueObject(s)&&isValueObject(o)&&s.equals(o))}var xe="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function imul(s,o){var i=65535&(s|=0),a=65535&(o|=0);return i*a+((s>>>16)*a+i*(o>>>16)<<16>>>0)|0};function smi(s){return s>>>1&1073741824|3221225471&s}var Pe=Object.prototype.valueOf;function hash(s){if(null==s)return hashNullish(s);if("function"==typeof s.hashCode)return smi(s.hashCode(s));var o=function valueOf(s){return s.valueOf!==Pe&&"function"==typeof s.valueOf?s.valueOf(s):s}(s);if(null==o)return hashNullish(o);switch(typeof o){case"boolean":return o?1108378657:1108378656;case"number":return function hashNumber(s){if(s!=s||s===1/0)return 0;var o=0|s;o!==s&&(o^=4294967295*s);for(;s>4294967295;)o^=s/=4294967295;return smi(o)}(o);case"string":return o.length>Xe?function cachedHashString(s){var o=tt[s];void 0===o&&(o=hashString(s),et===Qe&&(et=0,tt={}),et++,tt[s]=o);return o}(o):hashString(o);case"object":case"function":return function hashJSObj(s){var o;if(ze&&void 0!==(o=$e.get(s)))return o;if(void 0!==(o=s[Ye]))return o;if(!qe){if(void 0!==(o=s.propertyIsEnumerable&&s.propertyIsEnumerable[Ye]))return o;if(void 0!==(o=function getIENodeHash(s){if(s&&s.nodeType>0)switch(s.nodeType){case 1:return s.uniqueID;case 9:return s.documentElement&&s.documentElement.uniqueID}}(s)))return o}if(o=nextHash(),ze)$e.set(s,o);else{if(void 0!==Re&&!1===Re(s))throw new Error("Non-extensible objects are not allowed as keys.");if(qe)Object.defineProperty(s,Ye,{enumerable:!1,configurable:!1,writable:!1,value:o});else if(void 0!==s.propertyIsEnumerable&&s.propertyIsEnumerable===s.constructor.prototype.propertyIsEnumerable)s.propertyIsEnumerable=function(){return this.constructor.prototype.propertyIsEnumerable.apply(this,arguments)},s.propertyIsEnumerable[Ye]=o;else{if(void 0===s.nodeType)throw new Error("Unable to set a non-enumerable property on object.");s[Ye]=o}}return o}(o);case"symbol":return function hashSymbol(s){var o=We[s];if(void 0!==o)return o;return o=nextHash(),We[s]=o,o}(o);default:if("function"==typeof o.toString)return hashString(o.toString());throw new Error("Value type "+typeof o+" cannot be hashed.")}}function hashNullish(s){return null===s?1108378658:1108378659}function hashString(s){for(var o=0,i=0;i=0&&(C.get=function(o,i){return(o=wrapIndex(this,o))>=0&&o<_?s.get(o+w,i):i}),C.__iterateUncached=function(o,i){var u=this;if(0===_)return 0;if(i)return this.cacheResult().__iterate(o,i);var x=0,C=!0,j=0;return s.__iterate((function(s,i){if(!C||!(C=x++_)return{value:void 0,done:!0};var s=u.next();return a||1===o||s.done?s:iteratorValue(o,C-1,0===o?void 0:s.value[1],s)}))},C}function skipWhileFactory(s,o,i,a){var u=makeSequence(s);return u.__iterateUncached=function(u,_){var w=this;if(_)return this.cacheResult().__iterate(u,_);var x=!0,C=0;return s.__iterate((function(s,_,j){if(!x||!(x=o.call(i,s,_,j)))return C++,u(s,a?_:C-1,w)})),C},u.__iteratorUncached=function(u,_){var w=this;if(_)return this.cacheResult().__iterator(u,_);var x=s.__iterator(2,_),C=!0,j=0;return new ae((function(){var s,_,L;do{if((s=x.next()).done)return a||1===u?s:iteratorValue(u,j++,0===u?void 0:s.value[1],s);var B=s.value;_=B[0],L=B[1],C&&(C=o.call(i,L,_,w))}while(C);return 2===u?s:iteratorValue(u,_,L,s)}))},u}function flattenFactory(s,o,i){var a=makeSequence(s);return a.__iterateUncached=function(u,_){if(_)return this.cacheResult().__iterate(u,_);var w=0,x=!1;return function flatDeep(s,C){s.__iterate((function(s,_){return(!o||C0}function zipWithFactory(s,o,i,a){var u=makeSequence(s),_=new ye(i).map((function(s){return s.size}));return u.size=a?_.max():_.min(),u.__iterate=function(s,o){for(var i,a=this.__iterator(1,o),u=0;!(i=a.next()).done&&!1!==s(i.value,u++,this););return u},u.__iteratorUncached=function(s,u){var _=i.map((function(s){return s=L(s),getIterator(u?s.reverse():s)})),w=0,x=!1;return new ae((function(){var i;return x||(i=_.map((function(s){return s.next()})),x=a?i.every((function(s){return s.done})):i.some((function(s){return s.done}))),x?{value:void 0,done:!0}:iteratorValue(s,w++,o.apply(null,i.map((function(s){return s.value}))))}))},u}function reify(s,o){return s===o?s:isSeq(s)?o:s.constructor(o)}function validateEntry(s){if(s!==Object(s))throw new TypeError("Expected [K, V] tuple: "+s)}function collectionClass(s){return isKeyed(s)?B:isIndexed(s)?$:U}function makeSequence(s){return Object.create((isKeyed(s)?pe:isIndexed(s)?de:fe).prototype)}function cacheResultThrough(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):le.prototype.cacheResult.call(this)}function defaultComparator(s,o){return void 0===s&&void 0===o?0:void 0===s?1:void 0===o?-1:s>o?1:s0;)o[i]=arguments[i+1];if("function"!=typeof s)throw new TypeError("Invalid merger function: "+s);return mergeIntoKeyedWith(this,o,s)}function mergeIntoKeyedWith(s,o,i){for(var a=[],u=0;u0;)o[i]=arguments[i+1];return mergeWithSources(s,o)}function mergeWith(s,o){for(var i=[],a=arguments.length-2;a-- >0;)i[a]=arguments[a+2];return mergeWithSources(o,i,s)}function mergeDeep$1(s){for(var o=[],i=arguments.length-1;i-- >0;)o[i]=arguments[i+1];return mergeDeepWithSources(s,o)}function mergeDeepWith$1(s,o){for(var i=[],a=arguments.length-2;a-- >0;)i[a]=arguments[a+2];return mergeDeepWithSources(o,i,s)}function mergeDeepWithSources(s,o,i){return mergeWithSources(s,o,function deepMergerWith(s){function deepMerger(o,i,a){return isDataStructure(o)&&isDataStructure(i)&&function areMergeable(s,o){var i=le(s),a=le(o);return isIndexed(i)===isIndexed(a)&&isKeyed(i)===isKeyed(a)}(o,i)?mergeWithSources(o,[i],deepMerger):s?s(o,i,a):i}return deepMerger}(i))}function mergeWithSources(s,o,i){if(!isDataStructure(s))throw new TypeError("Cannot merge into non-data-structure value: "+s);if(isImmutable(s))return"function"==typeof i&&s.mergeWith?s.mergeWith.apply(s,[i].concat(o)):s.merge?s.merge.apply(s,o):s.concat.apply(s,o);for(var a=Array.isArray(s),u=s,_=a?$:B,w=a?function(o){u===s&&(u=shallowCopy(u)),u.push(o)}:function(o,a){if(!isProtoKey(a)){var _=ce.call(u,a),w=_&&i?i(u[a],o,a):o;_&&w===u[a]||(u===s&&(u=shallowCopy(u)),u[a]=w)}},x=0;x0;)o[i]=arguments[i+1];return mergeDeepWithSources(this,o,s)}function mergeIn(s){for(var o=[],i=arguments.length-1;i-- >0;)o[i]=arguments[i+1];return updateIn$1(this,s,emptyMap(),(function(s){return mergeWithSources(s,o)}))}function mergeDeepIn(s){for(var o=[],i=arguments.length-1;i-- >0;)o[i]=arguments[i+1];return updateIn$1(this,s,emptyMap(),(function(s){return mergeDeepWithSources(s,o)}))}function withMutations(s){var o=this.asMutable();return s(o),o.wasAltered()?o.__ensureOwner(this.__ownerID):this}function asMutable(){return this.__ownerID?this:this.__ensureOwner(new OwnerID)}function asImmutable(){return this.__ensureOwner()}function wasAltered(){return this.__altered}var at=function(s){function Map(o){return null==o?emptyMap():isMap(o)&&!isOrdered(o)?o:emptyMap().withMutations((function(i){var a=s(o);assertNotInfinite(a.size),a.forEach((function(s,o){return i.set(o,s)}))}))}return s&&(Map.__proto__=s),Map.prototype=Object.create(s&&s.prototype),Map.prototype.constructor=Map,Map.of=function of(){for(var s=[],o=arguments.length;o--;)s[o]=arguments[o];return emptyMap().withMutations((function(o){for(var i=0;i=s.length)throw new Error("Missing value for key: "+s[i]);o.set(s[i],s[i+1])}}))},Map.prototype.toString=function toString(){return this.__toString("Map {","}")},Map.prototype.get=function get(s,o){return this._root?this._root.get(0,void 0,s,o):o},Map.prototype.set=function set(s,o){return updateMap(this,s,o)},Map.prototype.remove=function remove(s){return updateMap(this,s,w)},Map.prototype.deleteAll=function deleteAll(s){var o=L(s);return 0===o.size?this:this.withMutations((function(s){o.forEach((function(o){return s.remove(o)}))}))},Map.prototype.clear=function clear(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):emptyMap()},Map.prototype.sort=function sort(s){return jt(sortFactory(this,s))},Map.prototype.sortBy=function sortBy(s,o){return jt(sortFactory(this,o,s))},Map.prototype.map=function map(s,o){var i=this;return this.withMutations((function(a){a.forEach((function(u,_){a.set(_,s.call(o,u,_,i))}))}))},Map.prototype.__iterator=function __iterator(s,o){return new gt(this,s,o)},Map.prototype.__iterate=function __iterate(s,o){var i=this,a=0;return this._root&&this._root.iterate((function(o){return a++,s(o[1],o[0],i)}),o),a},Map.prototype.__ensureOwner=function __ensureOwner(s){return s===this.__ownerID?this:s?makeMap(this.size,this._root,s,this.__hash):0===this.size?emptyMap():(this.__ownerID=s,this.__altered=!1,this)},Map}(B);at.isMap=isMap;var ct=at.prototype;ct[we]=!0,ct[a]=ct.remove,ct.removeAll=ct.deleteAll,ct.setIn=setIn,ct.removeIn=ct.deleteIn=deleteIn,ct.update=update,ct.updateIn=updateIn,ct.merge=ct.concat=merge$1,ct.mergeWith=mergeWith$1,ct.mergeDeep=mergeDeep,ct.mergeDeepWith=mergeDeepWith,ct.mergeIn=mergeIn,ct.mergeDeepIn=mergeDeepIn,ct.withMutations=withMutations,ct.wasAltered=wasAltered,ct.asImmutable=asImmutable,ct["@@transducer/init"]=ct.asMutable=asMutable,ct["@@transducer/step"]=function(s,o){return s.set(o[0],o[1])},ct["@@transducer/result"]=function(s){return s.asImmutable()};var lt=function ArrayMapNode(s,o){this.ownerID=s,this.entries=o};lt.prototype.get=function get(s,o,i,a){for(var u=this.entries,_=0,w=u.length;_=yt)return function createNodes(s,o,i,a){s||(s=new OwnerID);for(var u=new dt(s,hash(i),[i,a]),_=0;_>>s)&_),w=this.bitmap;return w&u?this.nodes[popCount(w&u-1)].get(s+5,o,i,a):a},ut.prototype.update=function update(s,o,i,a,x,C,j){void 0===i&&(i=hash(a));var L=(0===o?i:i>>>o)&_,B=1<=vt)return function expandNodes(s,o,i,a,_){for(var w=0,x=new Array(u),C=0;0!==i;C++,i>>>=1)x[C]=1&i?o[w++]:void 0;return x[a]=_,new pt(s,w+1,x)}(s,z,$,L,Z);if(U&&!Z&&2===z.length&&isLeafNode(z[1^V]))return z[1^V];if(U&&Z&&1===z.length&&isLeafNode(Z))return Z;var ee=s&&s===this.ownerID,ie=U?Z?$:$^B:$|B,ae=U?Z?setAt(z,V,Z,ee):function spliceOut(s,o,i){var a=s.length-1;if(i&&o===a)return s.pop(),s;for(var u=new Array(a),_=0,w=0;w>>s)&_,w=this.nodes[u];return w?w.get(s+5,o,i,a):a},pt.prototype.update=function update(s,o,i,a,u,x,C){void 0===i&&(i=hash(a));var j=(0===o?i:i>>>o)&_,L=u===w,B=this.nodes,$=B[j];if(L&&!$)return this;var U=updateNode($,s,o+5,i,a,u,x,C);if(U===$)return this;var V=this.count;if($){if(!U&&--V=St&&(a=this._buildIndex()),void 0!==a){var u=a[hashCollisionKey(s)];if(void 0!==u)for(var _=0;_>>i)&_,C=(0===i?a:a>>>i)&_,j=x===C?[mergeIntoNode(s,o,i+5,a,u)]:(w=new dt(o,a,u),x>1&1431655765))+(s>>2&858993459))+(s>>4)&252645135,s+=s>>8,127&(s+=s>>16)}function setAt(s,o,i,a){var u=a?s:arrCopy(s);return u[o]=i,u}var yt=8,vt=16,bt=8,St=16,_t="@@__IMMUTABLE_LIST__@@";function isList(s){return Boolean(s&&s[_t])}var Et=function(s){function List(o){var i=emptyList();if(null==o)return i;if(isList(o))return o;var a=s(o),_=a.size;return 0===_?i:(assertNotInfinite(_),_>0&&_=0&&s=s.size||o<0)return s.withMutations((function(s){o<0?setListBounds(s,o).set(0,i):setListBounds(s,0,o+1).set(o,i)}));o+=s._origin;var a=s._tail,u=s._root,_={value:!1};o>=getTailOffset(s._capacity)?a=updateVNode(a,s.__ownerID,0,o,i,_):u=updateVNode(u,s.__ownerID,s._level,o,i,_);if(!_.value)return s;if(s.__ownerID)return s._root=u,s._tail=a,s.__hash=void 0,s.__altered=!0,s;return makeList(s._origin,s._capacity,s._level,u,a)}(this,s,o)},List.prototype.remove=function remove(s){return this.has(s)?0===s?this.shift():s===this.size-1?this.pop():this.splice(s,1):this},List.prototype.insert=function insert(s,o){return this.splice(s,0,o)},List.prototype.clear=function clear(){return 0===this.size?this:this.__ownerID?(this.size=this._origin=this._capacity=0,this._level=5,this._root=this._tail=this.__hash=void 0,this.__altered=!0,this):emptyList()},List.prototype.push=function push(){var s=arguments,o=this.size;return this.withMutations((function(i){setListBounds(i,0,o+s.length);for(var a=0;a>>o&_;if(a>=this.array.length)return new xt([],s);var u,w=0===a;if(o>0){var x=this.array[a];if((u=x&&x.removeBefore(s,o-5,i))===x&&w)return this}if(w&&!u)return this;var C=editableVNode(this,s);if(!w)for(var j=0;j>>o&_;if(u>=this.array.length)return this;if(o>0){var w=this.array[u];if((a=w&&w.removeAfter(s,o-5,i))===w&&u===this.array.length-1)return this}var x=editableVNode(this,s);return x.array.splice(u+1),a&&(x.array[u]=a),x};var kt,Ot={};function iterateList(s,o){var i=s._origin,a=s._capacity,_=getTailOffset(a),w=s._tail;return iterateNodeOrLeaf(s._root,s._level,0);function iterateNodeOrLeaf(s,x,C){return 0===x?function iterateLeaf(s,x){var C=x===_?w&&w.array:s&&s.array,j=x>i?0:i-x,L=a-x;L>u&&(L=u);return function(){if(j===L)return Ot;var s=o?--L:j++;return C&&C[s]}}(s,C):function iterateNode(s,_,w){var x,C=s&&s.array,j=w>i?0:i-w>>_,L=1+(a-w>>_);L>u&&(L=u);return function(){for(;;){if(x){var s=x();if(s!==Ot)return s;x=null}if(j===L)return Ot;var i=o?--L:j++;x=iterateNodeOrLeaf(C&&C[i],_-5,w+(i<<_))}}}(s,x,C)}}function makeList(s,o,i,a,u,_,w){var x=Object.create(wt);return x.size=o-s,x._origin=s,x._capacity=o,x._level=i,x._root=a,x._tail=u,x.__ownerID=_,x.__hash=w,x.__altered=!1,x}function emptyList(){return kt||(kt=makeList(0,0,5))}function updateVNode(s,o,i,a,u,w){var x,C=a>>>i&_,j=s&&C0){var L=s&&s.array[C],B=updateVNode(L,o,i-5,a,u,w);return B===L?s:((x=editableVNode(s,o)).array[C]=B,x)}return j&&s.array[C]===u?s:(w&&SetRef(w),x=editableVNode(s,o),void 0===u&&C===x.array.length-1?x.array.pop():x.array[C]=u,x)}function editableVNode(s,o){return o&&s&&o===s.ownerID?s:new xt(s?s.array.slice():[],o)}function listNodeFor(s,o){if(o>=getTailOffset(s._capacity))return s._tail;if(o<1<0;)i=i.array[o>>>a&_],a-=5;return i}}function setListBounds(s,o,i){!function validateListBoundsRequest(s,o,i){var a=s._origin+(void 0===o?0:o),u=void 0===i?s._capacity:i<0?s._capacity+i:s._origin+i;if(Number.isFinite(u)&&u>At||Number.isFinite(a)&&a<-At||Number.isFinite(u)&&Number.isFinite(a)&&u-a>At)throw new RangeError("Invalid List size: a List cannot hold more than "+At+" (2 ** 30) values.")}(s,o,i),void 0!==o&&(o|=0),void 0!==i&&(i|=0);var a=s.__ownerID||new OwnerID,u=s._origin,w=s._capacity,x=u+o,C=void 0===i?w:i<0?w+i:u+i;if(x===u&&C===w)return s;if(x>=C)return s.clear();for(var j=s._level,L=s._root,B=0;x+B<0;)L=new xt(L&&L.array.length?[void 0,L]:[],a),B+=levelCapacity(j+=5);B&&(x+=B,u+=B,C+=B,w+=B);for(var $=getTailOffset(w),U=getTailOffset(C);U>=levelCapacity(j+5);)L=new xt(L&&L.array.length?[L]:[],a),j+=5;var V=s._tail,z=U<$?listNodeFor(s,C-1):U>$?new xt([],a):V;if(V&&U>$&&x5;Z-=5){var ee=$>>>Z&_;Y=Y.array[ee]=editableVNode(Y.array[ee],a)}Y.array[$>>>5&_]=V}if(C=U)x-=U,C-=U,j=5,L=null,z=z&&z.removeBefore(a,0,x);else if(x>u||U<$){for(B=0;L;){var ie=x>>>j&_;if(ie!==U>>>j&_)break;ie&&(B+=(1<u&&(L=L.removeBefore(a,j,x-B)),L&&U<$&&(L=L.removeAfter(a,j,U-B)),B&&(x-=B,C-=B)}return s.__ownerID?(s.size=C-x,s._origin=x,s._capacity=C,s._level=j,s._root=L,s._tail=z,s.__hash=void 0,s.__altered=!0,s):makeList(x,C,j,L,z)}function getTailOffset(s){return s>>5<<5}var At=Math.pow(2,30);function levelCapacity(s){return s<31?1<=u&&C.size>=2*x.size?(a=(_=C.filter((function(s,o){return void 0!==s&&j!==o}))).toKeyedSeq().map((function(s){return s[0]})).flip().toMap(),s.__ownerID&&(a.__ownerID=_.__ownerID=s.__ownerID)):(a=x.remove(o),_=j===C.size-1?C.pop():C.set(j,void 0))}else if(L){if(i===C.get(j)[1])return s;a=x,_=C.set(j,[o,i])}else a=x.set(o,C.size),_=C.set(C.size,[o,i]);return s.__ownerID?(s.size=a.size,s._map=a,s._list=_,s.__hash=void 0,s.__altered=!0,s):makeOrderedMap(a,_)}jt.isOrderedMap=isOrderedMap,jt.prototype[Y]=!0,jt.prototype[a]=jt.prototype.remove;var Pt="@@__IMMUTABLE_STACK__@@";function isStack(s){return Boolean(s&&s[Pt])}var Tt=function(s){function Stack(s){return null==s?emptyStack():isStack(s)?s:emptyStack().pushAll(s)}return s&&(Stack.__proto__=s),Stack.prototype=Object.create(s&&s.prototype),Stack.prototype.constructor=Stack,Stack.of=function of(){return this(arguments)},Stack.prototype.toString=function toString(){return this.__toString("Stack [","]")},Stack.prototype.get=function get(s,o){var i=this._head;for(s=wrapIndex(this,s);i&&s--;)i=i.next;return i?i.value:o},Stack.prototype.peek=function peek(){return this._head&&this._head.value},Stack.prototype.push=function push(){var s=arguments;if(0===arguments.length)return this;for(var o=this.size+arguments.length,i=this._head,a=arguments.length-1;a>=0;a--)i={value:s[a],next:i};return this.__ownerID?(this.size=o,this._head=i,this.__hash=void 0,this.__altered=!0,this):makeStack(o,i)},Stack.prototype.pushAll=function pushAll(o){if(0===(o=s(o)).size)return this;if(0===this.size&&isStack(o))return o;assertNotInfinite(o.size);var i=this.size,a=this._head;return o.__iterate((function(s){i++,a={value:s,next:a}}),!0),this.__ownerID?(this.size=i,this._head=a,this.__hash=void 0,this.__altered=!0,this):makeStack(i,a)},Stack.prototype.pop=function pop(){return this.slice(1)},Stack.prototype.clear=function clear(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):emptyStack()},Stack.prototype.slice=function slice(o,i){if(wholeSlice(o,i,this.size))return this;var a=resolveBegin(o,this.size);if(resolveEnd(i,this.size)!==this.size)return s.prototype.slice.call(this,o,i);for(var u=this.size-a,_=this._head;a--;)_=_.next;return this.__ownerID?(this.size=u,this._head=_,this.__hash=void 0,this.__altered=!0,this):makeStack(u,_)},Stack.prototype.__ensureOwner=function __ensureOwner(s){return s===this.__ownerID?this:s?makeStack(this.size,this._head,s,this.__hash):0===this.size?emptyStack():(this.__ownerID=s,this.__altered=!1,this)},Stack.prototype.__iterate=function __iterate(s,o){var i=this;if(o)return new ye(this.toArray()).__iterate((function(o,a){return s(o,a,i)}),o);for(var a=0,u=this._head;u&&!1!==s(u.value,a++,this);)u=u.next;return a},Stack.prototype.__iterator=function __iterator(s,o){if(o)return new ye(this.toArray()).__iterator(s,o);var i=0,a=this._head;return new ae((function(){if(a){var o=a.value;return a=a.next,iteratorValue(s,i++,o)}return{value:void 0,done:!0}}))},Stack}($);Tt.isStack=isStack;var It,Nt=Tt.prototype;function makeStack(s,o,i,a){var u=Object.create(Nt);return u.size=s,u._head=o,u.__ownerID=i,u.__hash=a,u.__altered=!1,u}function emptyStack(){return It||(It=makeStack(0))}Nt[Pt]=!0,Nt.shift=Nt.pop,Nt.unshift=Nt.push,Nt.unshiftAll=Nt.pushAll,Nt.withMutations=withMutations,Nt.wasAltered=wasAltered,Nt.asImmutable=asImmutable,Nt["@@transducer/init"]=Nt.asMutable=asMutable,Nt["@@transducer/step"]=function(s,o){return s.unshift(o)},Nt["@@transducer/result"]=function(s){return s.asImmutable()};var Mt="@@__IMMUTABLE_SET__@@";function isSet(s){return Boolean(s&&s[Mt])}function isOrderedSet(s){return isSet(s)&&isOrdered(s)}function deepEqual(s,o){if(s===o)return!0;if(!isCollection(o)||void 0!==s.size&&void 0!==o.size&&s.size!==o.size||void 0!==s.__hash&&void 0!==o.__hash&&s.__hash!==o.__hash||isKeyed(s)!==isKeyed(o)||isIndexed(s)!==isIndexed(o)||isOrdered(s)!==isOrdered(o))return!1;if(0===s.size&&0===o.size)return!0;var i=!isAssociative(s);if(isOrdered(s)){var a=s.entries();return o.every((function(s,o){var u=a.next().value;return u&&is(u[1],s)&&(i||is(u[0],o))}))&&a.next().done}var u=!1;if(void 0===s.size)if(void 0===o.size)"function"==typeof s.cacheResult&&s.cacheResult();else{u=!0;var _=s;s=o,o=_}var x=!0,C=o.__iterate((function(o,a){if(i?!s.has(o):u?!is(o,s.get(a,w)):!is(s.get(a,w),o))return x=!1,!1}));return x&&s.size===C}function mixin(s,o){var keyCopier=function(i){s.prototype[i]=o[i]};return Object.keys(o).forEach(keyCopier),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(o).forEach(keyCopier),s}function toJS(s){if(!s||"object"!=typeof s)return s;if(!isCollection(s)){if(!isDataStructure(s))return s;s=le(s)}if(isKeyed(s)){var o={};return s.__iterate((function(s,i){isProtoKey(i)||(o[i]=toJS(s))})),o}var i=[];return s.__iterate((function(s){i.push(toJS(s))})),i}var Rt=function(s){function Set(o){return null==o?emptySet():isSet(o)&&!isOrdered(o)?o:emptySet().withMutations((function(i){var a=s(o);assertNotInfinite(a.size),a.forEach((function(s){return i.add(s)}))}))}return s&&(Set.__proto__=s),Set.prototype=Object.create(s&&s.prototype),Set.prototype.constructor=Set,Set.of=function of(){return this(arguments)},Set.fromKeys=function fromKeys(s){return this(B(s).keySeq())},Set.intersect=function intersect(s){return(s=L(s).toArray()).length?Lt.intersect.apply(Set(s.pop()),s):emptySet()},Set.union=function union(s){return(s=L(s).toArray()).length?Lt.union.apply(Set(s.pop()),s):emptySet()},Set.prototype.toString=function toString(){return this.__toString("Set {","}")},Set.prototype.has=function has(s){return this._map.has(s)},Set.prototype.add=function add(s){return updateSet(this,this._map.set(s,s))},Set.prototype.remove=function remove(s){return updateSet(this,this._map.remove(s))},Set.prototype.clear=function clear(){return updateSet(this,this._map.clear())},Set.prototype.map=function map(s,o){var i=this,a=!1,u=updateSet(this,this._map.mapEntries((function(u){var _=u[1],w=s.call(o,_,_,i);return w!==_&&(a=!0),[w,w]}),o));return a?u:this},Set.prototype.union=function union(){for(var o=[],i=arguments.length;i--;)o[i]=arguments[i];return 0===(o=o.filter((function(s){return 0!==s.size}))).length?this:0!==this.size||this.__ownerID||1!==o.length?this.withMutations((function(i){for(var a=0;a=0&&o=0&&i>>-15,461845907),o=xe(o<<13|o>>>-13,5),o=o+3864292196^s,o=xe(o^o>>>16,2246822507),o=xe(o^o>>>13,3266489909),o=smi(o^o>>>16),o}(s.__iterate(i?o?function(s,o){a=31*a+hashMerge(hash(s),hash(o))|0}:function(s,o){a=a+hashMerge(hash(s),hash(o))|0}:o?function(s){a=31*a+hash(s)|0}:function(s){a=a+hash(s)|0}),a)}(this))}});var qt=L.prototype;qt[x]=!0,qt[ie]=qt.values,qt.toJSON=qt.toArray,qt.__toStringMapper=quoteString,qt.inspect=qt.toSource=function(){return this.toString()},qt.chain=qt.flatMap,qt.contains=qt.includes,mixin(B,{flip:function flip(){return reify(this,flipFactory(this))},mapEntries:function mapEntries(s,o){var i=this,a=0;return reify(this,this.toSeq().map((function(u,_){return s.call(o,[_,u],a++,i)})).fromEntrySeq())},mapKeys:function mapKeys(s,o){var i=this;return reify(this,this.toSeq().flip().map((function(a,u){return s.call(o,a,u,i)})).flip())}});var $t=B.prototype;$t[C]=!0,$t[ie]=qt.entries,$t.toJSON=toObject,$t.__toStringMapper=function(s,o){return quoteString(o)+": "+quoteString(s)},mixin($,{toKeyedSeq:function toKeyedSeq(){return new rt(this,!1)},filter:function filter(s,o){return reify(this,filterFactory(this,s,o,!1))},findIndex:function findIndex(s,o){var i=this.findEntry(s,o);return i?i[0]:-1},indexOf:function indexOf(s){var o=this.keyOf(s);return void 0===o?-1:o},lastIndexOf:function lastIndexOf(s){var o=this.lastKeyOf(s);return void 0===o?-1:o},reverse:function reverse(){return reify(this,reverseFactory(this,!1))},slice:function slice(s,o){return reify(this,sliceFactory(this,s,o,!1))},splice:function splice(s,o){var i=arguments.length;if(o=Math.max(o||0,0),0===i||2===i&&!o)return this;s=resolveBegin(s,s<0?this.count():this.size);var a=this.slice(0,s);return reify(this,1===i?a:a.concat(arrCopy(arguments,2),this.slice(s+o)))},findLastIndex:function findLastIndex(s,o){var i=this.findLastEntry(s,o);return i?i[0]:-1},first:function first(s){return this.get(0,s)},flatten:function flatten(s){return reify(this,flattenFactory(this,s,!1))},get:function get(s,o){return(s=wrapIndex(this,s))<0||this.size===1/0||void 0!==this.size&&s>this.size?o:this.find((function(o,i){return i===s}),void 0,o)},has:function has(s){return(s=wrapIndex(this,s))>=0&&(void 0!==this.size?this.size===1/0||so?-1:0}function hashMerge(s,o){return s^o+2654435769+(s<<6)+(s>>2)}Vt.has=qt.includes,Vt.contains=Vt.includes,Vt.keys=Vt.values,mixin(pe,$t),mixin(de,Ut),mixin(fe,Vt);var zt=function(s){function OrderedSet(s){return null==s?emptyOrderedSet():isOrderedSet(s)?s:emptyOrderedSet().withMutations((function(o){var i=U(s);assertNotInfinite(i.size),i.forEach((function(s){return o.add(s)}))}))}return s&&(OrderedSet.__proto__=s),OrderedSet.prototype=Object.create(s&&s.prototype),OrderedSet.prototype.constructor=OrderedSet,OrderedSet.of=function of(){return this(arguments)},OrderedSet.fromKeys=function fromKeys(s){return this(B(s).keySeq())},OrderedSet.prototype.toString=function toString(){return this.__toString("OrderedSet {","}")},OrderedSet}(Rt);zt.isOrderedSet=isOrderedSet;var Wt,Jt=zt.prototype;function makeOrderedSet(s,o){var i=Object.create(Jt);return i.size=s?s.size:0,i._map=s,i.__ownerID=o,i}function emptyOrderedSet(){return Wt||(Wt=makeOrderedSet(emptyOrderedMap()))}Jt[Y]=!0,Jt.zip=Ut.zip,Jt.zipWith=Ut.zipWith,Jt.zipAll=Ut.zipAll,Jt.__empty=emptyOrderedSet,Jt.__make=makeOrderedSet;var Ht={LeftThenRight:-1,RightThenLeft:1};var Kt=function Record(s,o){var i;!function throwOnInvalidDefaultValues(s){if(isRecord(s))throw new Error("Can not call `Record` with an immutable Record as default values. Use a plain javascript object instead.");if(isImmutable(s))throw new Error("Can not call `Record` with an immutable Collection as default values. Use a plain javascript object instead.");if(null===s||"object"!=typeof s)throw new Error("Can not call `Record` with a non-object as default values. Use a plain javascript object instead.")}(s);var a=function Record(_){var w=this;if(_ instanceof a)return _;if(!(this instanceof a))return new a(_);if(!i){i=!0;var x=Object.keys(s),C=u._indices={};u._name=o,u._keys=x,u._defaultValues=s;for(var j=0;j2?[]:void 0,{"":s})}function fromJSWith(s,o,i,a,u,_){if("string"!=typeof i&&!isImmutable(i)&&(isArrayLike(i)||hasIterator(i)||isPlainObject(i))){if(~s.indexOf(i))throw new TypeError("Cannot convert circular structure to Immutable");s.push(i),u&&""!==a&&u.push(a);var w=o.call(_,a,le(i).map((function(a,_){return fromJSWith(s,o,a,_,u,i)})),u&&u.slice());return s.pop(),u&&u.pop(),w}return i}function defaultConverter(s,o){return isIndexed(o)?o.toList():isKeyed(o)?o.toMap():o.toSet()}var Qt="4.3.9",Zt=L;const er={version:Qt,Collection:L,Iterable:L,Seq:le,Map:at,OrderedMap:jt,List:Et,Stack:Tt,Set:Rt,OrderedSet:zt,PairSorting:Ht,Record:Kt,Range:Bt,Repeat:Xt,is,fromJS,hash,isImmutable,isCollection,isKeyed,isIndexed,isAssociative,isOrdered,isValueObject,isPlainObject,isSeq,isList,isMap,isOrderedMap,isStack,isSet,isOrderedSet,isRecord,get,getIn:getIn$1,has,hasIn:hasIn$1,merge,mergeDeep:mergeDeep$1,mergeWith,mergeDeepWith:mergeDeepWith$1,remove,removeIn,set,setIn:setIn$1,update:update$1,updateIn:updateIn$1}},56698(s){"function"==typeof Object.create?s.exports=function inherits(s,o){o&&(s.super_=o,s.prototype=Object.create(o.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}))}:s.exports=function inherits(s,o){if(o){s.super_=o;var TempCtor=function(){};TempCtor.prototype=o.prototype,s.prototype=new TempCtor,s.prototype.constructor=s}}},69600(s){"use strict";var o,i,a=Function.prototype.toString,u="object"==typeof Reflect&&null!==Reflect&&Reflect.apply;if("function"==typeof u&&"function"==typeof Object.defineProperty)try{o=Object.defineProperty({},"length",{get:function(){throw i}}),i={},u((function(){throw 42}),null,o)}catch(s){s!==i&&(u=null)}else u=null;var _=/^\s*class\b/,w=function isES6ClassFunction(s){try{var o=a.call(s);return _.test(o)}catch(s){return!1}},x=function tryFunctionToStr(s){try{return!w(s)&&(a.call(s),!0)}catch(s){return!1}},C=Object.prototype.toString,j="function"==typeof Symbol&&!!Symbol.toStringTag,L=!(0 in[,]),B=function isDocumentDotAll(){return!1};if("object"==typeof document){var $=document.all;C.call($)===C.call(document.all)&&(B=function isDocumentDotAll(s){if((L||!s)&&(void 0===s||"object"==typeof s))try{var o=C.call(s);return("[object HTMLAllCollection]"===o||"[object HTML document.all class]"===o||"[object HTMLCollection]"===o||"[object Object]"===o)&&null==s("")}catch(s){}return!1})}s.exports=u?function isCallable(s){if(B(s))return!0;if(!s)return!1;if("function"!=typeof s&&"object"!=typeof s)return!1;try{u(s,null,o)}catch(s){if(s!==i)return!1}return!w(s)&&x(s)}:function isCallable(s){if(B(s))return!0;if(!s)return!1;if("function"!=typeof s&&"object"!=typeof s)return!1;if(j)return x(s);if(w(s))return!1;var o=C.call(s);return!("[object Function]"!==o&&"[object GeneratorFunction]"!==o&&!/^\[object HTML/.test(o))&&x(s)}},35680(s,o,i){"use strict";var a=i(25767);s.exports=function isTypedArray(s){return!!a(s)}},64634(s){var o={}.toString;s.exports=Array.isArray||function(s){return"[object Array]"==o.call(s)}},5419(s){s.exports=function(s,o,i,a){var u=new Blob(void 0!==a?[a,s]:[s],{type:i||"application/octet-stream"});if(void 0!==window.navigator.msSaveBlob)window.navigator.msSaveBlob(u,o);else{var _=window.URL&&window.URL.createObjectURL?window.URL.createObjectURL(u):window.webkitURL.createObjectURL(u),w=document.createElement("a");w.style.display="none",w.href=_,w.setAttribute("download",o),void 0===w.download&&w.setAttribute("target","_blank"),document.body.appendChild(w),w.click(),setTimeout((function(){document.body.removeChild(w),window.URL.revokeObjectURL(_)}),200)}}},20181(s,o,i){var a=/^\s+|\s+$/g,u=/^[-+]0x[0-9a-f]+$/i,_=/^0b[01]+$/i,w=/^0o[0-7]+$/i,x=parseInt,C="object"==typeof i.g&&i.g&&i.g.Object===Object&&i.g,j="object"==typeof self&&self&&self.Object===Object&&self,L=C||j||Function("return this")(),B=Object.prototype.toString,$=Math.max,U=Math.min,now=function(){return L.Date.now()};function isObject(s){var o=typeof s;return!!s&&("object"==o||"function"==o)}function toNumber(s){if("number"==typeof s)return s;if(function isSymbol(s){return"symbol"==typeof s||function isObjectLike(s){return!!s&&"object"==typeof s}(s)&&"[object Symbol]"==B.call(s)}(s))return NaN;if(isObject(s)){var o="function"==typeof s.valueOf?s.valueOf():s;s=isObject(o)?o+"":o}if("string"!=typeof s)return 0===s?s:+s;s=s.replace(a,"");var i=_.test(s);return i||w.test(s)?x(s.slice(2),i?2:8):u.test(s)?NaN:+s}s.exports=function debounce(s,o,i){var a,u,_,w,x,C,j=0,L=!1,B=!1,V=!0;if("function"!=typeof s)throw new TypeError("Expected a function");function invokeFunc(o){var i=a,_=u;return a=u=void 0,j=o,w=s.apply(_,i)}function shouldInvoke(s){var i=s-C;return void 0===C||i>=o||i<0||B&&s-j>=_}function timerExpired(){var s=now();if(shouldInvoke(s))return trailingEdge(s);x=setTimeout(timerExpired,function remainingWait(s){var i=o-(s-C);return B?U(i,_-(s-j)):i}(s))}function trailingEdge(s){return x=void 0,V&&a?invokeFunc(s):(a=u=void 0,w)}function debounced(){var s=now(),i=shouldInvoke(s);if(a=arguments,u=this,C=s,i){if(void 0===x)return function leadingEdge(s){return j=s,x=setTimeout(timerExpired,o),L?invokeFunc(s):w}(C);if(B)return x=setTimeout(timerExpired,o),invokeFunc(C)}return void 0===x&&(x=setTimeout(timerExpired,o)),w}return o=toNumber(o)||0,isObject(i)&&(L=!!i.leading,_=(B="maxWait"in i)?$(toNumber(i.maxWait)||0,o):_,V="trailing"in i?!!i.trailing:V),debounced.cancel=function cancel(){void 0!==x&&clearTimeout(x),j=0,a=C=u=x=void 0},debounced.flush=function flush(){return void 0===x?w:trailingEdge(now())},debounced}},55580(s,o,i){var a=i(56110)(i(9325),"DataView");s.exports=a},21549(s,o,i){var a=i(22032),u=i(63862),_=i(66721),w=i(12749),x=i(35749);function Hash(s){var o=-1,i=null==s?0:s.length;for(this.clear();++o-1}},70695(s,o,i){var a=i(78096),u=i(72428),_=i(56449),w=i(3656),x=i(30361),C=i(37167),j=Object.prototype.hasOwnProperty;s.exports=function arrayLikeKeys(s,o){var i=_(s),L=!i&&u(s),B=!i&&!L&&w(s),$=!i&&!L&&!B&&C(s),U=i||L||B||$,V=U?a(s.length,String):[],z=V.length;for(var Y in s)!o&&!j.call(s,Y)||U&&("length"==Y||B&&("offset"==Y||"parent"==Y)||$&&("buffer"==Y||"byteLength"==Y||"byteOffset"==Y)||x(Y,z))||V.push(Y);return V}},34932(s){s.exports=function arrayMap(s,o){for(var i=-1,a=null==s?0:s.length,u=Array(a);++i0&&i(j)?o>1?baseFlatten(j,o-1,i,_,w):a(w,j):_||(w[w.length]=j)}return w}},86649(s,o,i){var a=i(83221)();s.exports=a},30641(s,o,i){var a=i(86649),u=i(95950);s.exports=function baseForOwn(s,o){return s&&a(s,o,u)}},47422(s,o,i){var a=i(31769),u=i(77797);s.exports=function baseGet(s,o){for(var i=0,_=(o=a(o,s)).length;null!=s&&i<_;)s=s[u(o[i++])];return i&&i==_?s:void 0}},82199(s,o,i){var a=i(14528),u=i(56449);s.exports=function baseGetAllKeys(s,o,i){var _=o(s);return u(s)?_:a(_,i(s))}},72552(s,o,i){var a=i(51873),u=i(659),_=i(59350),w=a?a.toStringTag:void 0;s.exports=function baseGetTag(s){return null==s?void 0===s?"[object Undefined]":"[object Null]":w&&w in Object(s)?u(s):_(s)}},20426(s){var o=Object.prototype.hasOwnProperty;s.exports=function baseHas(s,i){return null!=s&&o.call(s,i)}},28077(s){s.exports=function baseHasIn(s,o){return null!=s&&o in Object(s)}},96131(s,o,i){var a=i(2523),u=i(85463),_=i(76959);s.exports=function baseIndexOf(s,o,i){return o==o?_(s,o,i):a(s,u,i)}},27534(s,o,i){var a=i(72552),u=i(40346);s.exports=function baseIsArguments(s){return u(s)&&"[object Arguments]"==a(s)}},60270(s,o,i){var a=i(87068),u=i(40346);s.exports=function baseIsEqual(s,o,i,_,w){return s===o||(null==s||null==o||!u(s)&&!u(o)?s!=s&&o!=o:a(s,o,i,_,baseIsEqual,w))}},87068(s,o,i){var a=i(37217),u=i(25911),_=i(21986),w=i(50689),x=i(5861),C=i(56449),j=i(3656),L=i(37167),B="[object Arguments]",$="[object Array]",U="[object Object]",V=Object.prototype.hasOwnProperty;s.exports=function baseIsEqualDeep(s,o,i,z,Y,Z){var ee=C(s),ie=C(o),ae=ee?$:x(s),ce=ie?$:x(o),le=(ae=ae==B?U:ae)==U,pe=(ce=ce==B?U:ce)==U,de=ae==ce;if(de&&j(s)){if(!j(o))return!1;ee=!0,le=!1}if(de&&!le)return Z||(Z=new a),ee||L(s)?u(s,o,i,z,Y,Z):_(s,o,ae,i,z,Y,Z);if(!(1&i)){var fe=le&&V.call(s,"__wrapped__"),ye=pe&&V.call(o,"__wrapped__");if(fe||ye){var be=fe?s.value():s,Se=ye?o.value():o;return Z||(Z=new a),Y(be,Se,i,z,Z)}}return!!de&&(Z||(Z=new a),w(s,o,i,z,Y,Z))}},29172(s,o,i){var a=i(5861),u=i(40346);s.exports=function baseIsMap(s){return u(s)&&"[object Map]"==a(s)}},41799(s,o,i){var a=i(37217),u=i(60270);s.exports=function baseIsMatch(s,o,i,_){var w=i.length,x=w,C=!_;if(null==s)return!x;for(s=Object(s);w--;){var j=i[w];if(C&&j[2]?j[1]!==s[j[0]]:!(j[0]in s))return!1}for(;++wu?0:u+o),(i=i>u?u:i)<0&&(i+=u),u=o>i?0:i-o>>>0,o>>>=0;for(var _=Array(u);++a=u?s:a(s,o,i)}},49653(s,o,i){var a=i(37828);s.exports=function cloneArrayBuffer(s){var o=new s.constructor(s.byteLength);return new a(o).set(new a(s)),o}},93290(s,o,i){s=i.nmd(s);var a=i(9325),u=o&&!o.nodeType&&o,_=u&&s&&!s.nodeType&&s,w=_&&_.exports===u?a.Buffer:void 0,x=w?w.allocUnsafe:void 0;s.exports=function cloneBuffer(s,o){if(o)return s.slice();var i=s.length,a=x?x(i):new s.constructor(i);return s.copy(a),a}},76169(s,o,i){var a=i(49653);s.exports=function cloneDataView(s,o){var i=o?a(s.buffer):s.buffer;return new s.constructor(i,s.byteOffset,s.byteLength)}},73201(s){var o=/\w*$/;s.exports=function cloneRegExp(s){var i=new s.constructor(s.source,o.exec(s));return i.lastIndex=s.lastIndex,i}},93736(s,o,i){var a=i(51873),u=a?a.prototype:void 0,_=u?u.valueOf:void 0;s.exports=function cloneSymbol(s){return _?Object(_.call(s)):{}}},71961(s,o,i){var a=i(49653);s.exports=function cloneTypedArray(s,o){var i=o?a(s.buffer):s.buffer;return new s.constructor(i,s.byteOffset,s.length)}},91596(s){var o=Math.max;s.exports=function composeArgs(s,i,a,u){for(var _=-1,w=s.length,x=a.length,C=-1,j=i.length,L=o(w-x,0),B=Array(j+L),$=!u;++C1?i[_-1]:void 0,x=_>2?i[2]:void 0;for(w=s.length>3&&"function"==typeof w?(_--,w):void 0,x&&u(i[0],i[1],x)&&(w=_<3?void 0:w,_=1),o=Object(o);++a<_;){var C=i[a];C&&s(o,C,a,w)}return o}))}},38329(s,o,i){var a=i(64894);s.exports=function createBaseEach(s,o){return function(i,u){if(null==i)return i;if(!a(i))return s(i,u);for(var _=i.length,w=o?_:-1,x=Object(i);(o?w--:++w<_)&&!1!==u(x[w],w,x););return i}}},83221(s){s.exports=function createBaseFor(s){return function(o,i,a){for(var u=-1,_=Object(o),w=a(o),x=w.length;x--;){var C=w[s?x:++u];if(!1===i(_[C],C,_))break}return o}}},11842(s,o,i){var a=i(82819),u=i(9325);s.exports=function createBind(s,o,i){var _=1&o,w=a(s);return function wrapper(){return(this&&this!==u&&this instanceof wrapper?w:s).apply(_?i:this,arguments)}}},12507(s,o,i){var a=i(28754),u=i(49698),_=i(63912),w=i(13222);s.exports=function createCaseFirst(s){return function(o){o=w(o);var i=u(o)?_(o):void 0,x=i?i[0]:o.charAt(0),C=i?a(i,1).join(""):o.slice(1);return x[s]()+C}}},45539(s,o,i){var a=i(40882),u=i(50828),_=i(66645),w=RegExp("['’]","g");s.exports=function createCompounder(s){return function(o){return a(_(u(o).replace(w,"")),s,"")}}},82819(s,o,i){var a=i(39344),u=i(23805);s.exports=function createCtor(s){return function(){var o=arguments;switch(o.length){case 0:return new s;case 1:return new s(o[0]);case 2:return new s(o[0],o[1]);case 3:return new s(o[0],o[1],o[2]);case 4:return new s(o[0],o[1],o[2],o[3]);case 5:return new s(o[0],o[1],o[2],o[3],o[4]);case 6:return new s(o[0],o[1],o[2],o[3],o[4],o[5]);case 7:return new s(o[0],o[1],o[2],o[3],o[4],o[5],o[6])}var i=a(s.prototype),_=s.apply(i,o);return u(_)?_:i}}},77078(s,o,i){var a=i(91033),u=i(82819),_=i(37471),w=i(18073),x=i(11287),C=i(36306),j=i(9325);s.exports=function createCurry(s,o,i){var L=u(s);return function wrapper(){for(var u=arguments.length,B=Array(u),$=u,U=x(wrapper);$--;)B[$]=arguments[$];var V=u<3&&B[0]!==U&&B[u-1]!==U?[]:C(B,U);return(u-=V.length)-1?x[C?o[j]:j]:void 0}}},37471(s,o,i){var a=i(91596),u=i(53320),_=i(58523),w=i(82819),x=i(18073),C=i(11287),j=i(68294),L=i(36306),B=i(9325);s.exports=function createHybrid(s,o,i,$,U,V,z,Y,Z,ee){var ie=128&o,ae=1&o,ce=2&o,le=24&o,pe=512&o,de=ce?void 0:w(s);return function wrapper(){for(var fe=arguments.length,ye=Array(fe),be=fe;be--;)ye[be]=arguments[be];if(le)var Se=C(wrapper),_e=_(ye,Se);if($&&(ye=a(ye,$,U,le)),V&&(ye=u(ye,V,z,le)),fe-=_e,le&&fe1&&ye.reverse(),ie&&ZL))return!1;var $=C.get(s),U=C.get(o);if($&&U)return $==o&&U==s;var V=-1,z=!0,Y=2&i?new a:void 0;for(C.set(s,o),C.set(o,s);++V1?"& ":"")+i[u],i=i.join(a>2?", ":" "),s.replace(o,"{\n/* [wrapped with "+i+"] */\n")}},45891(s,o,i){var a=i(51873),u=i(72428),_=i(56449),w=a?a.isConcatSpreadable:void 0;s.exports=function isFlattenable(s){return _(s)||u(s)||!!(w&&s&&s[w])}},30361(s){var o=/^(?:0|[1-9]\d*)$/;s.exports=function isIndex(s,i){var a=typeof s;return!!(i=null==i?9007199254740991:i)&&("number"==a||"symbol"!=a&&o.test(s))&&s>-1&&s%1==0&&s-1}},31175(s,o,i){var a=i(26025);s.exports=function listCacheSet(s,o){var i=this.__data__,u=a(i,s);return u<0?(++this.size,i.push([s,o])):i[u][1]=o,this}},63040(s,o,i){var a=i(21549),u=i(80079),_=i(68223);s.exports=function mapCacheClear(){this.size=0,this.__data__={hash:new a,map:new(_||u),string:new a}}},17670(s,o,i){var a=i(12651);s.exports=function mapCacheDelete(s){var o=a(this,s).delete(s);return this.size-=o?1:0,o}},90289(s,o,i){var a=i(12651);s.exports=function mapCacheGet(s){return a(this,s).get(s)}},4509(s,o,i){var a=i(12651);s.exports=function mapCacheHas(s){return a(this,s).has(s)}},72949(s,o,i){var a=i(12651);s.exports=function mapCacheSet(s,o){var i=a(this,s),u=i.size;return i.set(s,o),this.size+=i.size==u?0:1,this}},20317(s){s.exports=function mapToArray(s){var o=-1,i=Array(s.size);return s.forEach((function(s,a){i[++o]=[a,s]})),i}},67197(s){s.exports=function matchesStrictComparable(s,o){return function(i){return null!=i&&(i[s]===o&&(void 0!==o||s in Object(i)))}}},62224(s,o,i){var a=i(50104);s.exports=function memoizeCapped(s){var o=a(s,(function(s){return 500===i.size&&i.clear(),s})),i=o.cache;return o}},3209(s,o,i){var a=i(91596),u=i(53320),_=i(36306),w="__lodash_placeholder__",x=128,C=Math.min;s.exports=function mergeData(s,o){var i=s[1],j=o[1],L=i|j,B=L<131,$=j==x&&8==i||j==x&&256==i&&s[7].length<=o[8]||384==j&&o[7].length<=o[8]&&8==i;if(!B&&!$)return s;1&j&&(s[2]=o[2],L|=1&i?0:4);var U=o[3];if(U){var V=s[3];s[3]=V?a(V,U,o[4]):U,s[4]=V?_(s[3],w):o[4]}return(U=o[5])&&(V=s[5],s[5]=V?u(V,U,o[6]):U,s[6]=V?_(s[5],w):o[6]),(U=o[7])&&(s[7]=U),j&x&&(s[8]=null==s[8]?o[8]:C(s[8],o[8])),null==s[9]&&(s[9]=o[9]),s[0]=o[0],s[1]=L,s}},48152(s,o,i){var a=i(28303),u=a&&new a;s.exports=u},81042(s,o,i){var a=i(56110)(Object,"create");s.exports=a},3650(s,o,i){var a=i(74335)(Object.keys,Object);s.exports=a},90181(s){s.exports=function nativeKeysIn(s){var o=[];if(null!=s)for(var i in Object(s))o.push(i);return o}},86009(s,o,i){s=i.nmd(s);var a=i(34840),u=o&&!o.nodeType&&o,_=u&&s&&!s.nodeType&&s,w=_&&_.exports===u&&a.process,x=function(){try{var s=_&&_.require&&_.require("util").types;return s||w&&w.binding&&w.binding("util")}catch(s){}}();s.exports=x},59350(s){var o=Object.prototype.toString;s.exports=function objectToString(s){return o.call(s)}},74335(s){s.exports=function overArg(s,o){return function(i){return s(o(i))}}},56757(s,o,i){var a=i(91033),u=Math.max;s.exports=function overRest(s,o,i){return o=u(void 0===o?s.length-1:o,0),function(){for(var _=arguments,w=-1,x=u(_.length-o,0),C=Array(x);++w0){if(++i>=800)return arguments[0]}else i=0;return s.apply(void 0,arguments)}}},51420(s,o,i){var a=i(80079);s.exports=function stackClear(){this.__data__=new a,this.size=0}},90938(s){s.exports=function stackDelete(s){var o=this.__data__,i=o.delete(s);return this.size=o.size,i}},63605(s){s.exports=function stackGet(s){return this.__data__.get(s)}},29817(s){s.exports=function stackHas(s){return this.__data__.has(s)}},80945(s,o,i){var a=i(80079),u=i(68223),_=i(53661);s.exports=function stackSet(s,o){var i=this.__data__;if(i instanceof a){var w=i.__data__;if(!u||w.length<199)return w.push([s,o]),this.size=++i.size,this;i=this.__data__=new _(w)}return i.set(s,o),this.size=i.size,this}},76959(s){s.exports=function strictIndexOf(s,o,i){for(var a=i-1,u=s.length;++a=o||i<0||Y&&s-V>=L}function timerExpired(){var s=u();if(shouldInvoke(s))return trailingEdge(s);$=setTimeout(timerExpired,function remainingWait(s){var i=o-(s-U);return Y?x(i,L-(s-V)):i}(s))}function trailingEdge(s){return $=void 0,Z&&C?invokeFunc(s):(C=j=void 0,B)}function debounced(){var s=u(),i=shouldInvoke(s);if(C=arguments,j=this,U=s,i){if(void 0===$)return function leadingEdge(s){return V=s,$=setTimeout(timerExpired,o),z?invokeFunc(s):B}(U);if(Y)return clearTimeout($),$=setTimeout(timerExpired,o),invokeFunc(U)}return void 0===$&&($=setTimeout(timerExpired,o)),B}return o=_(o)||0,a(i)&&(z=!!i.leading,L=(Y="maxWait"in i)?w(_(i.maxWait)||0,o):L,Z="trailing"in i?!!i.trailing:Z),debounced.cancel=function cancel(){void 0!==$&&clearTimeout($),V=0,C=U=j=$=void 0},debounced.flush=function flush(){return void 0===$?B:trailingEdge(u())},debounced}},50828(s,o,i){var a=i(24647),u=i(13222),_=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,w=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g");s.exports=function deburr(s){return(s=u(s))&&s.replace(_,a).replace(w,"")}},75288(s){s.exports=function eq(s,o){return s===o||s!=s&&o!=o}},60680(s,o,i){var a=i(13222),u=/[\\^$.*+?()[\]{}|]/g,_=RegExp(u.source);s.exports=function escapeRegExp(s){return(s=a(s))&&_.test(s)?s.replace(u,"\\$&"):s}},7309(s,o,i){var a=i(62006)(i(24713));s.exports=a},24713(s,o,i){var a=i(2523),u=i(15389),_=i(61489),w=Math.max;s.exports=function findIndex(s,o,i){var x=null==s?0:s.length;if(!x)return-1;var C=null==i?0:_(i);return C<0&&(C=w(x+C,0)),a(s,u(o,3),C)}},35970(s,o,i){var a=i(83120);s.exports=function flatten(s){return(null==s?0:s.length)?a(s,1):[]}},73424(s,o,i){var a=i(16962),u=i(2874),_=Array.prototype.push;function baseAry(s,o){return 2==o?function(o,i){return s(o,i)}:function(o){return s(o)}}function cloneArray(s){for(var o=s?s.length:0,i=Array(o);o--;)i[o]=s[o];return i}function wrapImmutable(s,o){return function(){var i=arguments.length;if(i){for(var a=Array(i);i--;)a[i]=arguments[i];var u=a[0]=o.apply(void 0,a);return s.apply(void 0,a),u}}}s.exports=function baseConvert(s,o,i,w){var x="function"==typeof o,C=o===Object(o);if(C&&(w=i,i=o,o=void 0),null==i)throw new TypeError;w||(w={});var j=!("cap"in w)||w.cap,L=!("curry"in w)||w.curry,B=!("fixed"in w)||w.fixed,$=!("immutable"in w)||w.immutable,U=!("rearg"in w)||w.rearg,V=x?i:u,z="curry"in w&&w.curry,Y="fixed"in w&&w.fixed,Z="rearg"in w&&w.rearg,ee=x?i.runInContext():void 0,ie=x?i:{ary:s.ary,assign:s.assign,clone:s.clone,curry:s.curry,forEach:s.forEach,isArray:s.isArray,isError:s.isError,isFunction:s.isFunction,isWeakMap:s.isWeakMap,iteratee:s.iteratee,keys:s.keys,rearg:s.rearg,toInteger:s.toInteger,toPath:s.toPath},ae=ie.ary,ce=ie.assign,le=ie.clone,pe=ie.curry,de=ie.forEach,fe=ie.isArray,ye=ie.isError,be=ie.isFunction,Se=ie.isWeakMap,_e=ie.keys,we=ie.rearg,xe=ie.toInteger,Pe=ie.toPath,Te=_e(a.aryMethod),Re={castArray:function(s){return function(){var o=arguments[0];return fe(o)?s(cloneArray(o)):s.apply(void 0,arguments)}},iteratee:function(s){return function(){var o=arguments[1],i=s(arguments[0],o),a=i.length;return j&&"number"==typeof o?(o=o>2?o-2:1,a&&a<=o?i:baseAry(i,o)):i}},mixin:function(s){return function(o){var i=this;if(!be(i))return s(i,Object(o));var a=[];return de(_e(o),(function(s){be(o[s])&&a.push([s,i.prototype[s]])})),s(i,Object(o)),de(a,(function(s){var o=s[1];be(o)?i.prototype[s[0]]=o:delete i.prototype[s[0]]})),i}},nthArg:function(s){return function(o){var i=o<0?1:xe(o)+1;return pe(s(o),i)}},rearg:function(s){return function(o,i){var a=i?i.length:0;return pe(s(o,i),a)}},runInContext:function(o){return function(i){return baseConvert(s,o(i),w)}}};function castCap(s,o){if(j){var i=a.iterateeRearg[s];if(i)return function iterateeRearg(s,o){return overArg(s,(function(s){var i=o.length;return function baseArity(s,o){return 2==o?function(o,i){return s.apply(void 0,arguments)}:function(o){return s.apply(void 0,arguments)}}(we(baseAry(s,i),o),i)}))}(o,i);var u=!x&&a.iterateeAry[s];if(u)return function iterateeAry(s,o){return overArg(s,(function(s){return"function"==typeof s?baseAry(s,o):s}))}(o,u)}return o}function castFixed(s,o,i){if(B&&(Y||!a.skipFixed[s])){var u=a.methodSpread[s],w=u&&u.start;return void 0===w?ae(o,i):function flatSpread(s,o){return function(){for(var i=arguments.length,a=i-1,u=Array(i);i--;)u[i]=arguments[i];var w=u[o],x=u.slice(0,o);return w&&_.apply(x,w),o!=a&&_.apply(x,u.slice(o+1)),s.apply(this,x)}}(o,w)}return o}function castRearg(s,o,i){return U&&i>1&&(Z||!a.skipRearg[s])?we(o,a.methodRearg[s]||a.aryRearg[i]):o}function cloneByPath(s,o){for(var i=-1,a=(o=Pe(o)).length,u=a-1,_=le(Object(s)),w=_;null!=w&&++i1?pe(o,i):o}(0,u=castCap(_,u),s),!1}})),!u})),u||(u=w),u==o&&(u=z?pe(u,1):function(){return o.apply(this,arguments)}),u.convert=createConverter(_,o),u.placeholder=o.placeholder=i,u}if(!C)return wrap(o,i,V);var qe=i,$e=[];return de(Te,(function(s){de(a.aryMethod[s],(function(s){var o=qe[a.remap[s]||s];o&&$e.push([s,wrap(s,o,qe)])}))})),de(_e(qe),(function(s){var o=qe[s];if("function"==typeof o){for(var i=$e.length;i--;)if($e[i][0]==s)return;o.convert=createConverter(s,o),$e.push([s,o])}})),de($e,(function(s){qe[s[0]]=s[1]})),qe.convert=function convertLib(s){return qe.runInContext.convert(s)(void 0)},qe.placeholder=qe,de(_e(qe),(function(s){de(a.realToAlias[s]||[],(function(o){qe[o]=qe[s]}))})),qe}},16962(s,o){o.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},o.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],4:["fill","setWith","updateWith"]},o.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},o.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},o.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},o.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},o.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},o.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},o.realToAlias=function(){var s=Object.prototype.hasOwnProperty,i=o.aliasToReal,a={};for(var u in i){var _=i[u];s.call(a,_)?a[_].push(u):a[_]=[u]}return a}(),o.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},o.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},o.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},47934(s,o,i){s.exports={ary:i(64626),assign:i(74733),clone:i(32629),curry:i(49747),forEach:i(83729),isArray:i(56449),isError:i(23546),isFunction:i(1882),isWeakMap:i(47886),iteratee:i(33855),keys:i(88984),rearg:i(84195),toInteger:i(61489),toPath:i(42072)}},56367(s,o,i){s.exports=i(77731)},79920(s,o,i){var a=i(73424),u=i(47934);s.exports=function convert(s,o,i){return a(u,s,o,i)}},2874(s){s.exports={}},77731(s,o,i){var a=i(79920)("set",i(63560));a.placeholder=i(2874),s.exports=a},58156(s,o,i){var a=i(47422);s.exports=function get(s,o,i){var u=null==s?void 0:a(s,o);return void 0===u?i:u}},61448(s,o,i){var a=i(20426),u=i(49326);s.exports=function has(s,o){return null!=s&&u(s,o,a)}},80631(s,o,i){var a=i(28077),u=i(49326);s.exports=function hasIn(s,o){return null!=s&&u(s,o,a)}},83488(s){s.exports=function identity(s){return s}},72428(s,o,i){var a=i(27534),u=i(40346),_=Object.prototype,w=_.hasOwnProperty,x=_.propertyIsEnumerable,C=a(function(){return arguments}())?a:function(s){return u(s)&&w.call(s,"callee")&&!x.call(s,"callee")};s.exports=C},56449(s){var o=Array.isArray;s.exports=o},64894(s,o,i){var a=i(1882),u=i(30294);s.exports=function isArrayLike(s){return null!=s&&u(s.length)&&!a(s)}},83693(s,o,i){var a=i(64894),u=i(40346);s.exports=function isArrayLikeObject(s){return u(s)&&a(s)}},53812(s,o,i){var a=i(72552),u=i(40346);s.exports=function isBoolean(s){return!0===s||!1===s||u(s)&&"[object Boolean]"==a(s)}},3656(s,o,i){s=i.nmd(s);var a=i(9325),u=i(89935),_=o&&!o.nodeType&&o,w=_&&s&&!s.nodeType&&s,x=w&&w.exports===_?a.Buffer:void 0,C=(x?x.isBuffer:void 0)||u;s.exports=C},62193(s,o,i){var a=i(88984),u=i(5861),_=i(72428),w=i(56449),x=i(64894),C=i(3656),j=i(55527),L=i(37167),B=Object.prototype.hasOwnProperty;s.exports=function isEmpty(s){if(null==s)return!0;if(x(s)&&(w(s)||"string"==typeof s||"function"==typeof s.splice||C(s)||L(s)||_(s)))return!s.length;var o=u(s);if("[object Map]"==o||"[object Set]"==o)return!s.size;if(j(s))return!a(s).length;for(var i in s)if(B.call(s,i))return!1;return!0}},2404(s,o,i){var a=i(60270);s.exports=function isEqual(s,o){return a(s,o)}},23546(s,o,i){var a=i(72552),u=i(40346),_=i(11331);s.exports=function isError(s){if(!u(s))return!1;var o=a(s);return"[object Error]"==o||"[object DOMException]"==o||"string"==typeof s.message&&"string"==typeof s.name&&!_(s)}},1882(s,o,i){var a=i(72552),u=i(23805);s.exports=function isFunction(s){if(!u(s))return!1;var o=a(s);return"[object Function]"==o||"[object GeneratorFunction]"==o||"[object AsyncFunction]"==o||"[object Proxy]"==o}},30294(s){s.exports=function isLength(s){return"number"==typeof s&&s>-1&&s%1==0&&s<=9007199254740991}},87730(s,o,i){var a=i(29172),u=i(27301),_=i(86009),w=_&&_.isMap,x=w?u(w):a;s.exports=x},5187(s){s.exports=function isNull(s){return null===s}},98023(s,o,i){var a=i(72552),u=i(40346);s.exports=function isNumber(s){return"number"==typeof s||u(s)&&"[object Number]"==a(s)}},23805(s){s.exports=function isObject(s){var o=typeof s;return null!=s&&("object"==o||"function"==o)}},40346(s){s.exports=function isObjectLike(s){return null!=s&&"object"==typeof s}},11331(s,o,i){var a=i(72552),u=i(28879),_=i(40346),w=Function.prototype,x=Object.prototype,C=w.toString,j=x.hasOwnProperty,L=C.call(Object);s.exports=function isPlainObject(s){if(!_(s)||"[object Object]"!=a(s))return!1;var o=u(s);if(null===o)return!0;var i=j.call(o,"constructor")&&o.constructor;return"function"==typeof i&&i instanceof i&&C.call(i)==L}},38440(s,o,i){var a=i(16038),u=i(27301),_=i(86009),w=_&&_.isSet,x=w?u(w):a;s.exports=x},85015(s,o,i){var a=i(72552),u=i(56449),_=i(40346);s.exports=function isString(s){return"string"==typeof s||!u(s)&&_(s)&&"[object String]"==a(s)}},44394(s,o,i){var a=i(72552),u=i(40346);s.exports=function isSymbol(s){return"symbol"==typeof s||u(s)&&"[object Symbol]"==a(s)}},37167(s,o,i){var a=i(4901),u=i(27301),_=i(86009),w=_&&_.isTypedArray,x=w?u(w):a;s.exports=x},47886(s,o,i){var a=i(5861),u=i(40346);s.exports=function isWeakMap(s){return u(s)&&"[object WeakMap]"==a(s)}},33855(s,o,i){var a=i(9999),u=i(15389);s.exports=function iteratee(s){return u("function"==typeof s?s:a(s,1))}},95950(s,o,i){var a=i(70695),u=i(88984),_=i(64894);s.exports=function keys(s){return _(s)?a(s):u(s)}},37241(s,o,i){var a=i(70695),u=i(72903),_=i(64894);s.exports=function keysIn(s){return _(s)?a(s,!0):u(s)}},68090(s){s.exports=function last(s){var o=null==s?0:s.length;return o?s[o-1]:void 0}},50104(s,o,i){var a=i(53661);function memoize(s,o){if("function"!=typeof s||null!=o&&"function"!=typeof o)throw new TypeError("Expected a function");var memoized=function(){var i=arguments,a=o?o.apply(this,i):i[0],u=memoized.cache;if(u.has(a))return u.get(a);var _=s.apply(this,i);return memoized.cache=u.set(a,_)||u,_};return memoized.cache=new(memoize.Cache||a),memoized}memoize.Cache=a,s.exports=memoize},55364(s,o,i){var a=i(85250),u=i(20999)((function(s,o,i){a(s,o,i)}));s.exports=u},6048(s){s.exports=function negate(s){if("function"!=typeof s)throw new TypeError("Expected a function");return function(){var o=arguments;switch(o.length){case 0:return!s.call(this);case 1:return!s.call(this,o[0]);case 2:return!s.call(this,o[0],o[1]);case 3:return!s.call(this,o[0],o[1],o[2])}return!s.apply(this,o)}}},63950(s){s.exports=function noop(){}},10124(s,o,i){var a=i(9325);s.exports=function(){return a.Date.now()}},90179(s,o,i){var a=i(34932),u=i(9999),_=i(19931),w=i(31769),x=i(21791),C=i(53138),j=i(38816),L=i(83349),B=j((function(s,o){var i={};if(null==s)return i;var j=!1;o=a(o,(function(o){return o=w(o,s),j||(j=o.length>1),o})),x(s,L(s),i),j&&(i=u(i,7,C));for(var B=o.length;B--;)_(i,o[B]);return i}));s.exports=B},50583(s,o,i){var a=i(47237),u=i(17255),_=i(28586),w=i(77797);s.exports=function property(s){return _(s)?a(w(s)):u(s)}},84195(s,o,i){var a=i(66977),u=i(38816),_=u((function(s,o){return a(s,256,void 0,void 0,void 0,o)}));s.exports=_},40860(s,o,i){var a=i(40882),u=i(80909),_=i(15389),w=i(85558),x=i(56449);s.exports=function reduce(s,o,i){var C=x(s)?a:w,j=arguments.length<3;return C(s,_(o,4),i,j,u)}},63560(s,o,i){var a=i(73170);s.exports=function set(s,o,i){return null==s?s:a(s,o,i)}},42426(s,o,i){var a=i(14248),u=i(15389),_=i(90916),w=i(56449),x=i(36800);s.exports=function some(s,o,i){var C=w(s)?a:_;return i&&x(s,o,i)&&(o=void 0),C(s,u(o,3))}},63345(s){s.exports=function stubArray(){return[]}},89935(s){s.exports=function stubFalse(){return!1}},17400(s,o,i){var a=i(99374),u=1/0;s.exports=function toFinite(s){return s?(s=a(s))===u||s===-1/0?17976931348623157e292*(s<0?-1:1):s==s?s:0:0===s?s:0}},61489(s,o,i){var a=i(17400);s.exports=function toInteger(s){var o=a(s),i=o%1;return o==o?i?o-i:o:0}},80218(s,o,i){var a=i(13222);s.exports=function toLower(s){return a(s).toLowerCase()}},99374(s,o,i){var a=i(54128),u=i(23805),_=i(44394),w=/^[-+]0x[0-9a-f]+$/i,x=/^0b[01]+$/i,C=/^0o[0-7]+$/i,j=parseInt;s.exports=function toNumber(s){if("number"==typeof s)return s;if(_(s))return NaN;if(u(s)){var o="function"==typeof s.valueOf?s.valueOf():s;s=u(o)?o+"":o}if("string"!=typeof s)return 0===s?s:+s;s=a(s);var i=x.test(s);return i||C.test(s)?j(s.slice(2),i?2:8):w.test(s)?NaN:+s}},42072(s,o,i){var a=i(34932),u=i(23007),_=i(56449),w=i(44394),x=i(61802),C=i(77797),j=i(13222);s.exports=function toPath(s){return _(s)?a(s,C):w(s)?[s]:u(x(j(s)))}},69884(s,o,i){var a=i(21791),u=i(37241);s.exports=function toPlainObject(s){return a(s,u(s))}},13222(s,o,i){var a=i(77556);s.exports=function toString(s){return null==s?"":a(s)}},55808(s,o,i){var a=i(12507)("toUpperCase");s.exports=a},66645(s,o,i){var a=i(1733),u=i(45434),_=i(13222),w=i(22225);s.exports=function words(s,o,i){return s=_(s),void 0===(o=i?void 0:o)?u(s)?w(s):a(s):s.match(o)||[]}},53758(s,o,i){var a=i(30980),u=i(56017),_=i(94033),w=i(56449),x=i(40346),C=i(80257),j=Object.prototype.hasOwnProperty;function lodash(s){if(x(s)&&!w(s)&&!(s instanceof a)){if(s instanceof u)return s;if(j.call(s,"__wrapped__"))return C(s)}return new u(s)}lodash.prototype=_.prototype,lodash.prototype.constructor=lodash,s.exports=lodash},47248(s,o,i){var a=i(16547),u=i(51234);s.exports=function zipObject(s,o){return u(s||[],o||[],a)}},43768(s,o,i){"use strict";var a=i(45981),u=i(85587);o.highlight=highlight,o.highlightAuto=function highlightAuto(s,o){var i,w,x,C,j=o||{},L=j.subset||a.listLanguages(),B=j.prefix,$=L.length,U=-1;null==B&&(B=_);if("string"!=typeof s)throw u("Expected `string` for value, got `%s`",s);w={relevance:0,language:null,value:[]},i={relevance:0,language:null,value:[]};for(;++U<$;)C=L[U],a.getLanguage(C)&&((x=highlight(C,s,o)).language=C,x.relevance>w.relevance&&(w=x),x.relevance>i.relevance&&(w=i,i=x));w.language&&(i.secondBest=w);return i},o.registerLanguage=function registerLanguage(s,o){a.registerLanguage(s,o)},o.listLanguages=function listLanguages(){return a.listLanguages()},o.registerAlias=function registerAlias(s,o){var i,u=s;o&&((u={})[s]=o);for(i in u)a.registerAliases(u[i],{languageName:i})},Emitter.prototype.addText=function text(s){var o,i,a=this.stack;if(""===s)return;o=a[a.length-1],(i=o.children[o.children.length-1])&&"text"===i.type?i.value+=s:o.children.push({type:"text",value:s})},Emitter.prototype.addKeyword=function addKeyword(s,o){this.openNode(o),this.addText(s),this.closeNode()},Emitter.prototype.addSublanguage=function addSublanguage(s,o){var i=this.stack,a=i[i.length-1],u=s.rootNode.children,_=o?{type:"element",tagName:"span",properties:{className:[o]},children:u}:u;a.children=a.children.concat(_)},Emitter.prototype.openNode=function open(s){var o=this.stack,i=this.options.classPrefix+s,a=o[o.length-1],u={type:"element",tagName:"span",properties:{className:[i]},children:[]};a.children.push(u),o.push(u)},Emitter.prototype.closeNode=function close(){this.stack.pop()},Emitter.prototype.closeAllNodes=noop,Emitter.prototype.finalize=noop,Emitter.prototype.toHTML=function toHtmlNoop(){return""};var _="hljs-";function highlight(s,o,i){var w,x=a.configure({}),C=(i||{}).prefix;if("string"!=typeof s)throw u("Expected `string` for name, got `%s`",s);if(!a.getLanguage(s))throw u("Unknown language: `%s` is not registered",s);if("string"!=typeof o)throw u("Expected `string` for value, got `%s`",o);if(null==C&&(C=_),a.configure({__emitter:Emitter,classPrefix:C}),w=a.highlight(o,{language:s,ignoreIllegals:!0}),a.configure(x||{}),w.errorRaised)throw w.errorRaised;return{relevance:w.relevance,language:w.language,value:w.emitter.rootNode.children}}function Emitter(s){this.options=s,this.rootNode={children:[]},this.stack=[this.rootNode]}function noop(){}},71514(s){"use strict";s.exports=Math.abs},58968(s){"use strict";s.exports=Math.floor},94459(s){"use strict";s.exports=Number.isNaN||function isNaN(s){return s!=s}},6188(s){"use strict";s.exports=Math.max},68002(s){"use strict";s.exports=Math.min},75880(s){"use strict";s.exports=Math.pow},70414(s){"use strict";s.exports=Math.round},73093(s,o,i){"use strict";var a=i(94459);s.exports=function sign(s){return a(s)||0===s?s:s<0?-1:1}},92340(s,o,i){const a=i(6048);function coerceElementMatchingCallback(s){return"string"==typeof s?o=>o.element===s:s.constructor&&s.extend?o=>o instanceof s:s}class ArraySlice{constructor(s){this.elements=s||[]}toValue(){return this.elements.map((s=>s.toValue()))}map(s,o){return this.elements.map(s,o)}flatMap(s,o){return this.map(s,o).reduce(((s,o)=>s.concat(o)),[])}compactMap(s,o){const i=[];return this.forEach((a=>{const u=s.bind(o)(a);u&&i.push(u)})),i}filter(s,o){return s=coerceElementMatchingCallback(s),new ArraySlice(this.elements.filter(s,o))}reject(s,o){return s=coerceElementMatchingCallback(s),new ArraySlice(this.elements.filter(a(s),o))}find(s,o){return s=coerceElementMatchingCallback(s),this.elements.find(s,o)}forEach(s,o){this.elements.forEach(s,o)}reduce(s,o){return this.elements.reduce(s,o)}includes(s){return this.elements.some((o=>o.equals(s)))}shift(){return this.elements.shift()}unshift(s){this.elements.unshift(this.refract(s))}push(s){return this.elements.push(this.refract(s)),this}add(s){this.push(s)}get(s){return this.elements[s]}getValue(s){const o=this.elements[s];if(o)return o.toValue()}get length(){return this.elements.length}get isEmpty(){return 0===this.elements.length}get first(){return this.elements[0]}}"undefined"!=typeof Symbol&&(ArraySlice.prototype[Symbol.iterator]=function symbol(){return this.elements[Symbol.iterator]()}),s.exports=ArraySlice},55973(s){class KeyValuePair{constructor(s,o){this.key=s,this.value=o}clone(){const s=new KeyValuePair;return this.key&&(s.key=this.key.clone()),this.value&&(s.value=this.value.clone()),s}}s.exports=KeyValuePair},3110(s,o,i){const a=i(5187),u=i(85015),_=i(98023),w=i(53812),x=i(23805),C=i(85105),j=i(86804);class Namespace{constructor(s){this.elementMap={},this.elementDetection=[],this.Element=j.Element,this.KeyValuePair=j.KeyValuePair,s&&s.noDefault||this.useDefault(),this._attributeElementKeys=[],this._attributeElementArrayKeys=[]}use(s){return s.namespace&&s.namespace({base:this}),s.load&&s.load({base:this}),this}useDefault(){return this.register("null",j.NullElement).register("string",j.StringElement).register("number",j.NumberElement).register("boolean",j.BooleanElement).register("array",j.ArrayElement).register("object",j.ObjectElement).register("member",j.MemberElement).register("ref",j.RefElement).register("link",j.LinkElement),this.detect(a,j.NullElement,!1).detect(u,j.StringElement,!1).detect(_,j.NumberElement,!1).detect(w,j.BooleanElement,!1).detect(Array.isArray,j.ArrayElement,!1).detect(x,j.ObjectElement,!1),this}register(s,o){return this._elements=void 0,this.elementMap[s]=o,this}unregister(s){return this._elements=void 0,delete this.elementMap[s],this}detect(s,o,i){return void 0===i||i?this.elementDetection.unshift([s,o]):this.elementDetection.push([s,o]),this}toElement(s){if(s instanceof this.Element)return s;let o;for(let i=0;i{const o=s[0].toUpperCase()+s.substr(1);this._elements[o]=this.elementMap[s]}))),this._elements}get serialiser(){return new C(this)}}C.prototype.Namespace=Namespace,s.exports=Namespace},10866(s,o,i){const a=i(6048),u=i(92340);class ObjectSlice extends u{map(s,o){return this.elements.map((i=>s.bind(o)(i.value,i.key,i)))}filter(s,o){return new ObjectSlice(this.elements.filter((i=>s.bind(o)(i.value,i.key,i))))}reject(s,o){return this.filter(a(s.bind(o)))}forEach(s,o){return this.elements.forEach(((i,a)=>{s.bind(o)(i.value,i.key,i,a)}))}keys(){return this.map(((s,o)=>o.toValue()))}values(){return this.map((s=>s.toValue()))}}s.exports=ObjectSlice},86804(s,o,i){const a=i(10316),u=i(41067),_=i(71167),w=i(40239),x=i(12242),C=i(6233),j=i(87726),L=i(61045),B=i(86303),$=i(14540),U=i(92340),V=i(10866),z=i(55973);function refract(s){if(s instanceof a)return s;if("string"==typeof s)return new _(s);if("number"==typeof s)return new w(s);if("boolean"==typeof s)return new x(s);if(null===s)return new u;if(Array.isArray(s))return new C(s.map(refract));if("object"==typeof s){return new L(s)}return s}a.prototype.ObjectElement=L,a.prototype.RefElement=$,a.prototype.MemberElement=j,a.prototype.refract=refract,U.prototype.refract=refract,s.exports={Element:a,NullElement:u,StringElement:_,NumberElement:w,BooleanElement:x,ArrayElement:C,MemberElement:j,ObjectElement:L,LinkElement:B,RefElement:$,refract,ArraySlice:U,ObjectSlice:V,KeyValuePair:z}},86303(s,o,i){const a=i(10316);s.exports=class LinkElement extends a{constructor(s,o,i){super(s||[],o,i),this.element="link"}get relation(){return this.attributes.get("relation")}set relation(s){this.attributes.set("relation",s)}get href(){return this.attributes.get("href")}set href(s){this.attributes.set("href",s)}}},14540(s,o,i){const a=i(10316);s.exports=class RefElement extends a{constructor(s,o,i){super(s||[],o,i),this.element="ref",this.path||(this.path="element")}get path(){return this.attributes.get("path")}set path(s){this.attributes.set("path",s)}}},34035(s,o,i){const a=i(3110),u=i(86804);o.g$=a,o.KeyValuePair=i(55973),o.G6=u.ArraySlice,o.ot=u.ObjectSlice,o.Hg=u.Element,o.Om=u.StringElement,o.kT=u.NumberElement,o.bd=u.BooleanElement,o.Os=u.NullElement,o.wE=u.ArrayElement,o.Sh=u.ObjectElement,o.Pr=u.MemberElement,o.sI=u.RefElement,o.Ft=u.LinkElement,o.e=u.refract,i(85105),i(75147)},6233(s,o,i){const a=i(6048),u=i(10316),_=i(92340);class ArrayElement extends u{constructor(s,o,i){super(s||[],o,i),this.element="array"}primitive(){return"array"}get(s){return this.content[s]}getValue(s){const o=this.get(s);if(o)return o.toValue()}getIndex(s){return this.content[s]}set(s,o){return this.content[s]=this.refract(o),this}remove(s){const o=this.content.splice(s,1);return o.length?o[0]:null}map(s,o){return this.content.map(s,o)}flatMap(s,o){return this.map(s,o).reduce(((s,o)=>s.concat(o)),[])}compactMap(s,o){const i=[];return this.forEach((a=>{const u=s.bind(o)(a);u&&i.push(u)})),i}filter(s,o){return new _(this.content.filter(s,o))}reject(s,o){return this.filter(a(s),o)}reduce(s,o){let i,a;void 0!==o?(i=0,a=this.refract(o)):(i=1,a="object"===this.primitive()?this.first.value:this.first);for(let o=i;o{s.bind(o)(i,this.refract(a))}))}shift(){return this.content.shift()}unshift(s){this.content.unshift(this.refract(s))}push(s){return this.content.push(this.refract(s)),this}add(s){this.push(s)}findElements(s,o){const i=o||{},a=!!i.recursive,u=void 0===i.results?[]:i.results;return this.forEach(((o,i,_)=>{a&&void 0!==o.findElements&&o.findElements(s,{results:u,recursive:a}),s(o,i,_)&&u.push(o)})),u}find(s){return new _(this.findElements(s,{recursive:!0}))}findByElement(s){return this.find((o=>o.element===s))}findByClass(s){return this.find((o=>o.classes.includes(s)))}getById(s){return this.find((o=>o.id.toValue()===s)).first}includes(s){return this.content.some((o=>o.equals(s)))}contains(s){return this.includes(s)}empty(){return new this.constructor([])}"fantasy-land/empty"(){return this.empty()}concat(s){return new this.constructor(this.content.concat(s.content))}"fantasy-land/concat"(s){return this.concat(s)}"fantasy-land/map"(s){return new this.constructor(this.map(s))}"fantasy-land/chain"(s){return this.map((o=>s(o)),this).reduce(((s,o)=>s.concat(o)),this.empty())}"fantasy-land/filter"(s){return new this.constructor(this.content.filter(s))}"fantasy-land/reduce"(s,o){return this.content.reduce(s,o)}get length(){return this.content.length}get isEmpty(){return 0===this.content.length}get first(){return this.getIndex(0)}get second(){return this.getIndex(1)}get last(){return this.getIndex(this.length-1)}}ArrayElement.empty=function empty(){return new this},ArrayElement["fantasy-land/empty"]=ArrayElement.empty,"undefined"!=typeof Symbol&&(ArrayElement.prototype[Symbol.iterator]=function symbol(){return this.content[Symbol.iterator]()}),s.exports=ArrayElement},12242(s,o,i){const a=i(10316);s.exports=class BooleanElement extends a{constructor(s,o,i){super(s,o,i),this.element="boolean"}primitive(){return"boolean"}}},10316(s,o,i){const a=i(2404),u=i(55973),_=i(92340);class Element{constructor(s,o,i){o&&(this.meta=o),i&&(this.attributes=i),this.content=s}freeze(){Object.isFrozen(this)||(this._meta&&(this.meta.parent=this,this.meta.freeze()),this._attributes&&(this.attributes.parent=this,this.attributes.freeze()),this.children.forEach((s=>{s.parent=this,s.freeze()}),this),this.content&&Array.isArray(this.content)&&Object.freeze(this.content),Object.freeze(this))}primitive(){}clone(){const s=new this.constructor;return s.element=this.element,this.meta.length&&(s._meta=this.meta.clone()),this.attributes.length&&(s._attributes=this.attributes.clone()),this.content?this.content.clone?s.content=this.content.clone():Array.isArray(this.content)?s.content=this.content.map((s=>s.clone())):s.content=this.content:s.content=this.content,s}toValue(){return this.content instanceof Element?this.content.toValue():this.content instanceof u?{key:this.content.key.toValue(),value:this.content.value?this.content.value.toValue():void 0}:this.content&&this.content.map?this.content.map((s=>s.toValue()),this):this.content}toRef(s){if(""===this.id.toValue())throw Error("Cannot create reference to an element that does not contain an ID");const o=new this.RefElement(this.id.toValue());return s&&(o.path=s),o}findRecursive(...s){if(arguments.length>1&&!this.isFrozen)throw new Error("Cannot find recursive with multiple element names without first freezing the element. Call `element.freeze()`");const o=s.pop();let i=new _;const append=(s,o)=>(s.push(o),s),checkElement=(s,i)=>{i.element===o&&s.push(i);const a=i.findRecursive(o);return a&&a.reduce(append,s),i.content instanceof u&&(i.content.key&&checkElement(s,i.content.key),i.content.value&&checkElement(s,i.content.value)),s};return this.content&&(this.content.element&&checkElement(i,this.content),Array.isArray(this.content)&&this.content.reduce(checkElement,i)),s.isEmpty||(i=i.filter((o=>{let i=o.parents.map((s=>s.element));for(const o in s){const a=s[o],u=i.indexOf(a);if(-1===u)return!1;i=i.splice(0,u)}return!0}))),i}set(s){return this.content=s,this}equals(s){return a(this.toValue(),s)}getMetaProperty(s,o){if(!this.meta.hasKey(s)){if(this.isFrozen){const s=this.refract(o);return s.freeze(),s}this.meta.set(s,o)}return this.meta.get(s)}setMetaProperty(s,o){this.meta.set(s,o)}get element(){return this._storedElement||"element"}set element(s){this._storedElement=s}get content(){return this._content}set content(s){if(s instanceof Element)this._content=s;else if(s instanceof _)this.content=s.elements;else if("string"==typeof s||"number"==typeof s||"boolean"==typeof s||"null"===s||null==s)this._content=s;else if(s instanceof u)this._content=s;else if(Array.isArray(s))this._content=s.map(this.refract);else{if("object"!=typeof s)throw new Error("Cannot set content to given value");this._content=Object.keys(s).map((o=>new this.MemberElement(o,s[o])))}}get meta(){if(!this._meta){if(this.isFrozen){const s=new this.ObjectElement;return s.freeze(),s}this._meta=new this.ObjectElement}return this._meta}set meta(s){s instanceof this.ObjectElement?this._meta=s:this.meta.set(s||{})}get attributes(){if(!this._attributes){if(this.isFrozen){const s=new this.ObjectElement;return s.freeze(),s}this._attributes=new this.ObjectElement}return this._attributes}set attributes(s){s instanceof this.ObjectElement?this._attributes=s:this.attributes.set(s||{})}get id(){return this.getMetaProperty("id","")}set id(s){this.setMetaProperty("id",s)}get classes(){return this.getMetaProperty("classes",[])}set classes(s){this.setMetaProperty("classes",s)}get title(){return this.getMetaProperty("title","")}set title(s){this.setMetaProperty("title",s)}get description(){return this.getMetaProperty("description","")}set description(s){this.setMetaProperty("description",s)}get links(){return this.getMetaProperty("links",[])}set links(s){this.setMetaProperty("links",s)}get isFrozen(){return Object.isFrozen(this)}get parents(){let{parent:s}=this;const o=new _;for(;s;)o.push(s),s=s.parent;return o}get children(){if(Array.isArray(this.content))return new _(this.content);if(this.content instanceof u){const s=new _([this.content.key]);return this.content.value&&s.push(this.content.value),s}return this.content instanceof Element?new _([this.content]):new _}get recursiveChildren(){const s=new _;return this.children.forEach((o=>{s.push(o),o.recursiveChildren.forEach((o=>{s.push(o)}))})),s}}s.exports=Element},87726(s,o,i){const a=i(55973),u=i(10316);s.exports=class MemberElement extends u{constructor(s,o,i,u){super(new a,i,u),this.element="member",this.key=s,this.value=o}get key(){return this.content.key}set key(s){this.content.key=this.refract(s)}get value(){return this.content.value}set value(s){this.content.value=this.refract(s)}}},41067(s,o,i){const a=i(10316);s.exports=class NullElement extends a{constructor(s,o,i){super(s||null,o,i),this.element="null"}primitive(){return"null"}set(){return new Error("Cannot set the value of null")}}},40239(s,o,i){const a=i(10316);s.exports=class NumberElement extends a{constructor(s,o,i){super(s,o,i),this.element="number"}primitive(){return"number"}}},61045(s,o,i){const a=i(6048),u=i(23805),_=i(6233),w=i(87726),x=i(10866);s.exports=class ObjectElement extends _{constructor(s,o,i){super(s||[],o,i),this.element="object"}primitive(){return"object"}toValue(){return this.content.reduce(((s,o)=>(s[o.key.toValue()]=o.value?o.value.toValue():void 0,s)),{})}get(s){const o=this.getMember(s);if(o)return o.value}getMember(s){if(void 0!==s)return this.content.find((o=>o.key.toValue()===s))}remove(s){let o=null;return this.content=this.content.filter((i=>i.key.toValue()!==s||(o=i,!1))),o}getKey(s){const o=this.getMember(s);if(o)return o.key}set(s,o){if(u(s))return Object.keys(s).forEach((o=>{this.set(o,s[o])})),this;const i=s,a=this.getMember(i);return a?a.value=o:this.content.push(new w(i,o)),this}keys(){return this.content.map((s=>s.key.toValue()))}values(){return this.content.map((s=>s.value.toValue()))}hasKey(s){return this.content.some((o=>o.key.equals(s)))}items(){return this.content.map((s=>[s.key.toValue(),s.value.toValue()]))}map(s,o){return this.content.map((i=>s.bind(o)(i.value,i.key,i)))}compactMap(s,o){const i=[];return this.forEach(((a,u,_)=>{const w=s.bind(o)(a,u,_);w&&i.push(w)})),i}filter(s,o){return new x(this.content).filter(s,o)}reject(s,o){return this.filter(a(s),o)}forEach(s,o){return this.content.forEach((i=>s.bind(o)(i.value,i.key,i)))}}},71167(s,o,i){const a=i(10316);s.exports=class StringElement extends a{constructor(s,o,i){super(s,o,i),this.element="string"}primitive(){return"string"}get length(){return this.content.length}}},75147(s,o,i){const a=i(85105);s.exports=class JSON06Serialiser extends a{serialise(s){if(!(s instanceof this.namespace.elements.Element))throw new TypeError(`Given element \`${s}\` is not an Element instance`);let o;s._attributes&&s.attributes.get("variable")&&(o=s.attributes.get("variable"));const i={element:s.element};s._meta&&s._meta.length>0&&(i.meta=this.serialiseObject(s.meta));const a="enum"===s.element||-1!==s.attributes.keys().indexOf("enumerations");if(a){const o=this.enumSerialiseAttributes(s);o&&(i.attributes=o)}else if(s._attributes&&s._attributes.length>0){let{attributes:a}=s;a.get("metadata")&&(a=a.clone(),a.set("meta",a.get("metadata")),a.remove("metadata")),"member"===s.element&&o&&(a=a.clone(),a.remove("variable")),a.length>0&&(i.attributes=this.serialiseObject(a))}if(a)i.content=this.enumSerialiseContent(s,i);else if(this[`${s.element}SerialiseContent`])i.content=this[`${s.element}SerialiseContent`](s,i);else if(void 0!==s.content){let a;o&&s.content.key?(a=s.content.clone(),a.key.attributes.set("variable",o),a=this.serialiseContent(a)):a=this.serialiseContent(s.content),this.shouldSerialiseContent(s,a)&&(i.content=a)}else this.shouldSerialiseContent(s,s.content)&&s instanceof this.namespace.elements.Array&&(i.content=[]);return i}shouldSerialiseContent(s,o){return"parseResult"===s.element||"httpRequest"===s.element||"httpResponse"===s.element||"category"===s.element||"link"===s.element||void 0!==o&&(!Array.isArray(o)||0!==o.length)}refSerialiseContent(s,o){return delete o.attributes,{href:s.toValue(),path:s.path.toValue()}}sourceMapSerialiseContent(s){return s.toValue()}dataStructureSerialiseContent(s){return[this.serialiseContent(s.content)]}enumSerialiseAttributes(s){const o=s.attributes.clone(),i=o.remove("enumerations")||new this.namespace.elements.Array([]),a=o.get("default");let u=o.get("samples")||new this.namespace.elements.Array([]);if(a&&a.content&&(a.content.attributes&&a.content.attributes.remove("typeAttributes"),o.set("default",new this.namespace.elements.Array([a.content]))),u.forEach((s=>{s.content&&s.content.element&&s.content.attributes.remove("typeAttributes")})),s.content&&0!==i.length&&u.unshift(s.content),u=u.map((s=>s instanceof this.namespace.elements.Array?[s]:new this.namespace.elements.Array([s.content]))),u.length&&o.set("samples",u),o.length>0)return this.serialiseObject(o)}enumSerialiseContent(s){if(s._attributes){const o=s.attributes.get("enumerations");if(o&&o.length>0)return o.content.map((s=>{const o=s.clone();return o.attributes.remove("typeAttributes"),this.serialise(o)}))}if(s.content){const o=s.content.clone();return o.attributes.remove("typeAttributes"),[this.serialise(o)]}return[]}deserialise(s){if("string"==typeof s)return new this.namespace.elements.String(s);if("number"==typeof s)return new this.namespace.elements.Number(s);if("boolean"==typeof s)return new this.namespace.elements.Boolean(s);if(null===s)return new this.namespace.elements.Null;if(Array.isArray(s))return new this.namespace.elements.Array(s.map(this.deserialise,this));const o=this.namespace.getElementClass(s.element),i=new o;i.element!==s.element&&(i.element=s.element),s.meta&&this.deserialiseObject(s.meta,i.meta),s.attributes&&this.deserialiseObject(s.attributes,i.attributes);const a=this.deserialiseContent(s.content);if(void 0===a&&null!==i.content||(i.content=a),"enum"===i.element){i.content&&i.attributes.set("enumerations",i.content);let s=i.attributes.get("samples");if(i.attributes.remove("samples"),s){const a=s;s=new this.namespace.elements.Array,a.forEach((a=>{a.forEach((a=>{const u=new o(a);u.element=i.element,s.push(u)}))}));const u=s.shift();i.content=u?u.content:void 0,i.attributes.set("samples",s)}else i.content=void 0;let a=i.attributes.get("default");if(a&&a.length>0){a=a.get(0);const s=new o(a);s.element=i.element,i.attributes.set("default",s)}}else if("dataStructure"===i.element&&Array.isArray(i.content))[i.content]=i.content;else if("category"===i.element){const s=i.attributes.get("meta");s&&(i.attributes.set("metadata",s),i.attributes.remove("meta"))}else"member"===i.element&&i.key&&i.key._attributes&&i.key._attributes.getValue("variable")&&(i.attributes.set("variable",i.key.attributes.get("variable")),i.key.attributes.remove("variable"));return i}serialiseContent(s){if(s instanceof this.namespace.elements.Element)return this.serialise(s);if(s instanceof this.namespace.KeyValuePair){const o={key:this.serialise(s.key)};return s.value&&(o.value=this.serialise(s.value)),o}return s&&s.map?s.map(this.serialise,this):s}deserialiseContent(s){if(s){if(s.element)return this.deserialise(s);if(s.key){const o=new this.namespace.KeyValuePair(this.deserialise(s.key));return s.value&&(o.value=this.deserialise(s.value)),o}if(s.map)return s.map(this.deserialise,this)}return s}shouldRefract(s){return!!(s._attributes&&s.attributes.keys().length||s._meta&&s.meta.keys().length)||"enum"!==s.element&&(s.element!==s.primitive()||"member"===s.element)}convertKeyToRefract(s,o){return this.shouldRefract(o)?this.serialise(o):"enum"===o.element?this.serialiseEnum(o):"array"===o.element?o.map((o=>this.shouldRefract(o)||"default"===s?this.serialise(o):"array"===o.element||"object"===o.element||"enum"===o.element?o.children.map((s=>this.serialise(s))):o.toValue())):"object"===o.element?(o.content||[]).map(this.serialise,this):o.toValue()}serialiseEnum(s){return s.children.map((s=>this.serialise(s)))}serialiseObject(s){const o={};return s.forEach(((s,i)=>{if(s){const a=i.toValue();o[a]=this.convertKeyToRefract(a,s)}})),o}deserialiseObject(s,o){Object.keys(s).forEach((i=>{o.set(i,this.deserialise(s[i]))}))}}},85105(s){s.exports=class JSONSerialiser{constructor(s){this.namespace=s||new this.Namespace}serialise(s){if(!(s instanceof this.namespace.elements.Element))throw new TypeError(`Given element \`${s}\` is not an Element instance`);const o={element:s.element};s._meta&&s._meta.length>0&&(o.meta=this.serialiseObject(s.meta)),s._attributes&&s._attributes.length>0&&(o.attributes=this.serialiseObject(s.attributes));const i=this.serialiseContent(s.content);return void 0!==i&&(o.content=i),o}deserialise(s){if(!s.element)throw new Error("Given value is not an object containing an element name");const o=new(this.namespace.getElementClass(s.element));o.element!==s.element&&(o.element=s.element),s.meta&&this.deserialiseObject(s.meta,o.meta),s.attributes&&this.deserialiseObject(s.attributes,o.attributes);const i=this.deserialiseContent(s.content);return void 0===i&&null!==o.content||(o.content=i),o}serialiseContent(s){if(s instanceof this.namespace.elements.Element)return this.serialise(s);if(s instanceof this.namespace.KeyValuePair){const o={key:this.serialise(s.key)};return s.value&&(o.value=this.serialise(s.value)),o}if(s&&s.map){if(0===s.length)return;return s.map(this.serialise,this)}return s}deserialiseContent(s){if(s){if(s.element)return this.deserialise(s);if(s.key){const o=new this.namespace.KeyValuePair(this.deserialise(s.key));return s.value&&(o.value=this.deserialise(s.value)),o}if(s.map)return s.map(this.deserialise,this)}return s}serialiseObject(s){const o={};if(s.forEach(((s,i)=>{s&&(o[i.toValue()]=this.serialise(s))})),0!==Object.keys(o).length)return o}deserialiseObject(s,o){Object.keys(s).forEach((i=>{o.set(i,this.deserialise(s[i]))}))}}},76578(s){"use strict";s.exports=["Float16Array","Float32Array","Float64Array","Int8Array","Int16Array","Int32Array","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array"]},65606(s){var o,i,a=s.exports={};function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}function runTimeout(s){if(o===setTimeout)return setTimeout(s,0);if((o===defaultSetTimout||!o)&&setTimeout)return o=setTimeout,setTimeout(s,0);try{return o(s,0)}catch(i){try{return o.call(null,s,0)}catch(i){return o.call(this,s,0)}}}!function(){try{o="function"==typeof setTimeout?setTimeout:defaultSetTimout}catch(s){o=defaultSetTimout}try{i="function"==typeof clearTimeout?clearTimeout:defaultClearTimeout}catch(s){i=defaultClearTimeout}}();var u,_=[],w=!1,x=-1;function cleanUpNextTick(){w&&u&&(w=!1,u.length?_=u.concat(_):x=-1,_.length&&drainQueue())}function drainQueue(){if(!w){var s=runTimeout(cleanUpNextTick);w=!0;for(var o=_.length;o;){for(u=_,_=[];++x1)for(var i=1;i_)throw new RangeError("requested too many random bytes");var i=w.allocUnsafe(s);if(s>0)if(s>u)for(var C=0;C=0||(u[i]=s[i]);return u}(s,o);if(Object.getOwnPropertySymbols){var _=Object.getOwnPropertySymbols(s);for(a=0;a<_.length;a++)i=_[a],o.indexOf(i)>=0||Object.prototype.propertyIsEnumerable.call(s,i)&&(u[i]=s[i])}return u}function ownKeys(s,o){var i=Object.keys(s);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(s);o&&(a=a.filter((function(o){return Object.getOwnPropertyDescriptor(s,o).enumerable}))),i.push.apply(i,a)}return i}function _objectSpread(s){for(var o=1;o=a?i.notify(s):o.length>u.length&&i.notify(_objectSpread(_objectSpread({},s),{},{target:_objectSpread(_objectSpread({},s.target),{},{value:""})}))}))})),_defineProperty(_assertThisInitialized(i),"onKeyDown",(function(s){"Enter"===s.key&&i.forceNotify(s);var o=i.props.onKeyDown;o&&(s.persist(),o(s))})),_defineProperty(_assertThisInitialized(i),"onBlur",(function(s){i.forceNotify(s);var o=i.props.onBlur;o&&(s.persist(),o(s))})),_defineProperty(_assertThisInitialized(i),"createNotifier",(function(s){if(s<0)i.notify=function(){return null};else if(0===s)i.notify=i.doNotify;else{var o=(0,u.default)((function(s){i.isDebouncing=!1,i.doNotify(s)}),s);i.notify=function(s){i.isDebouncing=!0,o(s)},i.flush=function(){return o.flush()},i.cancel=function(){i.isDebouncing=!1,o.cancel()}}})),_defineProperty(_assertThisInitialized(i),"doNotify",(function(){i.props.onChange.apply(void 0,arguments)})),_defineProperty(_assertThisInitialized(i),"forceNotify",(function(s){var o=i.props.debounceTimeout;if(i.isDebouncing||!(o>0)){i.cancel&&i.cancel();var a=i.state.value,u=i.props.minLength;a.length>=u?i.doNotify(s):i.doNotify(_objectSpread(_objectSpread({},s),{},{target:_objectSpread(_objectSpread({},s.target),{},{value:a})}))}})),i.isDebouncing=!1,i.state={value:void 0===s.value||null===s.value?"":s.value};var a=i.props.debounceTimeout;return i.createNotifier(a),i}return function _createClass(s,o,i){return o&&_defineProperties(s.prototype,o),i&&_defineProperties(s,i),Object.defineProperty(s,"prototype",{writable:!1}),s}(DebounceInput,[{key:"componentDidUpdate",value:function componentDidUpdate(s){if(!this.isDebouncing){var o=this.props,i=o.value,a=o.debounceTimeout,u=s.debounceTimeout,_=s.value,w=this.state.value;void 0!==i&&_!==i&&w!==i&&this.setState({value:i}),a!==u&&this.createNotifier(a)}}},{key:"componentWillUnmount",value:function componentWillUnmount(){this.flush&&this.flush()}},{key:"render",value:function render(){var s,o,i=this.props,u=i.element,w=(i.onChange,i.value,i.minLength,i.debounceTimeout,i.forceNotifyByEnter),x=i.forceNotifyOnBlur,C=i.onKeyDown,j=i.onBlur,L=i.inputRef,B=_objectWithoutProperties(i,_),$=this.state.value;s=w?{onKeyDown:this.onKeyDown}:C?{onKeyDown:C}:{},o=x?{onBlur:this.onBlur}:j?{onBlur:j}:{};var U=L?{ref:L}:{};return a.default.createElement(u,_objectSpread(_objectSpread(_objectSpread(_objectSpread({},B),{},{onChange:this.onChange,value:$},s),o),U))}}]),DebounceInput}(a.default.PureComponent);o.DebounceInput=w,_defineProperty(w,"defaultProps",{element:"input",type:"text",onKeyDown:void 0,onBlur:void 0,value:void 0,minLength:0,debounceTimeout:100,forceNotifyByEnter:!0,forceNotifyOnBlur:!0,inputRef:void 0})},24677(s,o,i){"use strict";var a=i(81214).DebounceInput;a.DebounceInput=a,s.exports=a},22551(s,o,i){"use strict";var a=i(96540),u=i(69982);function p(s){for(var o="https://reactjs.org/docs/error-decoder.html?invariant="+s,i=1;i