scrapme-flow 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -2
- package/dashboard/dist/assets/index-D-otDb0Z.css +1 -0
- package/dashboard/dist/assets/index-F0JnDwTs.js +2 -0
- package/dashboard/dist/index.html +14 -0
- package/dist/src/commands/commands.models.d.ts +41 -0
- package/dist/src/commands/commands.models.js +2 -0
- package/dist/src/commands/commands.models.js.map +1 -0
- package/dist/src/commands/save-document.command.d.ts +9 -0
- package/dist/src/commands/save-document.command.js +33 -0
- package/dist/src/commands/save-document.command.js.map +1 -0
- package/dist/src/commands/scrape-page.command.d.ts +20 -0
- package/dist/src/commands/scrape-page.command.js +93 -0
- package/dist/src/commands/scrape-page.command.js.map +1 -0
- package/dist/src/commands/send-mail.command.d.ts +11 -0
- package/dist/src/commands/send-mail.command.js +39 -0
- package/dist/src/commands/send-mail.command.js.map +1 -0
- package/dist/src/config/config-builder.d.ts +24 -0
- package/dist/src/config/config-builder.js +131 -0
- package/dist/src/config/config-builder.js.map +1 -0
- package/dist/src/config/config-loader.d.ts +10 -0
- package/dist/src/config/config-loader.js +79 -0
- package/dist/src/config/config-loader.js.map +1 -0
- package/dist/src/config/config.models.d.ts +154 -0
- package/dist/src/config/config.models.js +2 -0
- package/dist/src/config/config.models.js.map +1 -0
- package/dist/src/config/config.schema.d.ts +75 -0
- package/dist/src/config/config.schema.js +87 -0
- package/dist/src/config/config.schema.js.map +1 -0
- package/dist/src/config/dsn-check.d.ts +5 -0
- package/dist/src/config/dsn-check.js +12 -0
- package/dist/src/config/dsn-check.js.map +1 -0
- package/dist/src/di/container.d.ts +13 -0
- package/dist/src/di/container.js +74 -0
- package/dist/src/di/container.js.map +1 -0
- package/dist/src/di/types.d.ts +30 -0
- package/dist/src/di/types.js +31 -0
- package/dist/src/di/types.js.map +1 -0
- package/dist/src/flow/command-executor.d.ts +18 -0
- package/dist/src/flow/command-executor.js +87 -0
- package/dist/src/flow/command-executor.js.map +1 -0
- package/dist/src/flow/command-resolver.d.ts +11 -0
- package/dist/src/flow/command-resolver.js +35 -0
- package/dist/src/flow/command-resolver.js.map +1 -0
- package/dist/src/flow/flow-catalog.d.ts +12 -0
- package/dist/src/flow/flow-catalog.js +31 -0
- package/dist/src/flow/flow-catalog.js.map +1 -0
- package/dist/src/flow/flow-errors.d.ts +66 -0
- package/dist/src/flow/flow-errors.js +119 -0
- package/dist/src/flow/flow-errors.js.map +1 -0
- package/dist/src/flow/flow-job-processor.d.ts +33 -0
- package/dist/src/flow/flow-job-processor.js +208 -0
- package/dist/src/flow/flow-job-processor.js.map +1 -0
- package/dist/src/flow/flow-params.d.ts +9 -0
- package/dist/src/flow/flow-params.js +52 -0
- package/dist/src/flow/flow-params.js.map +1 -0
- package/dist/src/flow/flow-runner.d.ts +36 -0
- package/dist/src/flow/flow-runner.js +209 -0
- package/dist/src/flow/flow-runner.js.map +1 -0
- package/dist/src/flow/flow-scheduler.d.ts +24 -0
- package/dist/src/flow/flow-scheduler.js +96 -0
- package/dist/src/flow/flow-scheduler.js.map +1 -0
- package/dist/src/flow/flow-validator.d.ts +29 -0
- package/dist/src/flow/flow-validator.js +141 -0
- package/dist/src/flow/flow-validator.js.map +1 -0
- package/dist/src/flow/flow.d.ts +32 -0
- package/dist/src/flow/flow.js +50 -0
- package/dist/src/flow/flow.js.map +1 -0
- package/dist/src/flow/flow.models.d.ts +288 -0
- package/dist/src/flow/flow.models.js +38 -0
- package/dist/src/flow/flow.models.js.map +1 -0
- package/dist/src/flow/retry-policy.d.ts +9 -0
- package/dist/src/flow/retry-policy.js +15 -0
- package/dist/src/flow/retry-policy.js.map +1 -0
- package/dist/src/flow/state-path.d.ts +21 -0
- package/dist/src/flow/state-path.js +37 -0
- package/dist/src/flow/state-path.js.map +1 -0
- package/dist/src/flow/step-input-builder.d.ts +15 -0
- package/dist/src/flow/step-input-builder.js +63 -0
- package/dist/src/flow/step-input-builder.js.map +1 -0
- package/dist/src/flows/scrape.flow.d.ts +6 -0
- package/dist/src/flows/scrape.flow.js +31 -0
- package/dist/src/flows/scrape.flow.js.map +1 -0
- package/dist/src/index.d.ts +60 -0
- package/dist/src/index.js +52 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logging/logger.d.ts +17 -0
- package/dist/src/logging/logger.js +55 -0
- package/dist/src/logging/logger.js.map +1 -0
- package/dist/src/logging/logger.models.d.ts +25 -0
- package/dist/src/logging/logger.models.js +7 -0
- package/dist/src/logging/logger.models.js.map +1 -0
- package/dist/src/mail/mail.models.d.ts +15 -0
- package/dist/src/mail/mail.models.js +2 -0
- package/dist/src/mail/mail.models.js.map +1 -0
- package/dist/src/mail/smtp-mailer.d.ts +13 -0
- package/dist/src/mail/smtp-mailer.js +70 -0
- package/dist/src/mail/smtp-mailer.js.map +1 -0
- package/dist/src/mail/unconfigured-mailer.d.ts +6 -0
- package/dist/src/mail/unconfigured-mailer.js +20 -0
- package/dist/src/mail/unconfigured-mailer.js.map +1 -0
- package/dist/src/monitor/monitor-api.d.ts +18 -0
- package/dist/src/monitor/monitor-api.js +62 -0
- package/dist/src/monitor/monitor-api.js.map +1 -0
- package/dist/src/monitor/monitor-server.d.ts +33 -0
- package/dist/src/monitor/monitor-server.js +142 -0
- package/dist/src/monitor/monitor-server.js.map +1 -0
- package/dist/src/monitor/monitor.models.d.ts +27 -0
- package/dist/src/monitor/monitor.models.js +2 -0
- package/dist/src/monitor/monitor.models.js.map +1 -0
- package/dist/src/queue/pg-boss-flow-queue.d.ts +22 -0
- package/dist/src/queue/pg-boss-flow-queue.js +102 -0
- package/dist/src/queue/pg-boss-flow-queue.js.map +1 -0
- package/dist/src/queue/queue.models.d.ts +38 -0
- package/dist/src/queue/queue.models.js +2 -0
- package/dist/src/queue/queue.models.js.map +1 -0
- package/dist/src/reporting/lighty-error-reporter.d.ts +24 -0
- package/dist/src/reporting/lighty-error-reporter.js +96 -0
- package/dist/src/reporting/lighty-error-reporter.js.map +1 -0
- package/dist/src/reporting/log-error-reporter.d.ts +12 -0
- package/dist/src/reporting/log-error-reporter.js +35 -0
- package/dist/src/reporting/log-error-reporter.js.map +1 -0
- package/dist/src/reporting/reporting.models.d.ts +27 -0
- package/dist/src/reporting/reporting.models.js +2 -0
- package/dist/src/reporting/reporting.models.js.map +1 -0
- package/dist/src/scrapme.d.ts +62 -0
- package/dist/src/scrapme.js +140 -0
- package/dist/src/scrapme.js.map +1 -0
- package/dist/src/scrapme.models.d.ts +18 -0
- package/dist/src/scrapme.models.js +2 -0
- package/dist/src/scrapme.models.js.map +1 -0
- package/dist/src/storage/couch-connection.d.ts +19 -0
- package/dist/src/storage/couch-connection.js +67 -0
- package/dist/src/storage/couch-connection.js.map +1 -0
- package/dist/src/storage/couch-database.d.ts +44 -0
- package/dist/src/storage/couch-database.js +118 -0
- package/dist/src/storage/couch-database.js.map +1 -0
- package/dist/src/storage/couch-document-store.d.ts +14 -0
- package/dist/src/storage/couch-document-store.js +36 -0
- package/dist/src/storage/couch-document-store.js.map +1 -0
- package/dist/src/storage/couch-error.d.ts +12 -0
- package/dist/src/storage/couch-error.js +19 -0
- package/dist/src/storage/couch-error.js.map +1 -0
- package/dist/src/storage/couch-flow-run-store.d.ts +24 -0
- package/dist/src/storage/couch-flow-run-store.js +66 -0
- package/dist/src/storage/couch-flow-run-store.js.map +1 -0
- package/dist/src/storage/couch-run-store.d.ts +17 -0
- package/dist/src/storage/couch-run-store.js +58 -0
- package/dist/src/storage/couch-run-store.js.map +1 -0
- package/dist/src/storage/run-doc-ids.d.ts +6 -0
- package/dist/src/storage/run-doc-ids.js +9 -0
- package/dist/src/storage/run-doc-ids.js.map +1 -0
- package/dist/src/storage/storage.models.d.ts +95 -0
- package/dist/src/storage/storage.models.js +5 -0
- package/dist/src/storage/storage.models.js.map +1 -0
- package/dist/src/storage/unconfigured-document-store.d.ts +8 -0
- package/dist/src/storage/unconfigured-document-store.js +26 -0
- package/dist/src/storage/unconfigured-document-store.js.map +1 -0
- package/dist/src/util/preview.d.ts +10 -0
- package/dist/src/util/preview.js +44 -0
- package/dist/src/util/preview.js.map +1 -0
- package/dist/src/util/text.d.ts +8 -0
- package/dist/src/util/text.js +16 -0
- package/dist/src/util/text.js.map +1 -0
- package/dist/src/util/timing.d.ts +10 -0
- package/dist/src/util/timing.js +59 -0
- package/dist/src/util/timing.js.map +1 -0
- package/dist/src/util/url.d.ts +5 -0
- package/dist/src/util/url.js +11 -0
- package/dist/src/util/url.js.map +1 -0
- package/package.json +77 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 lastseeds
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,124 @@
|
|
|
1
|
-
#
|
|
1
|
+
# scrapme-flow
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Scraping flows for Node apps. A flow is a **`*.flow.ts` file** exporting `new Flow({...})`: a list of steps, each
|
|
4
|
+
running a small command class (scrape a page, parse it, save it, mail it…). Every command has its own **retries and
|
|
5
|
+
timeout**. `scrapme.flow(flow, input)` puts a run on a **pg-boss queue** (Postgres) and returns at once; a worker runs
|
|
6
|
+
it, and a failed run is run again by pg-boss. The progress of every run is kept in **CouchDB** and shown by a
|
|
7
|
+
**Svelte monitor**.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Container } from 'inversify';
|
|
11
|
+
import { Scrapme } from 'scrapme-flow';
|
|
12
|
+
import { helloFlow } from './hello.flow.js';
|
|
13
|
+
|
|
14
|
+
const scrapme = Scrapme.create({
|
|
15
|
+
container: appContainer, // your inversify container: commands get your services from it
|
|
16
|
+
postgres: { connectionString: 'postgres://scrapme:scrapme@localhost:5434/scrapme' },
|
|
17
|
+
couch: { url: 'http://localhost:5984', user: 'admin', password: secret },
|
|
18
|
+
});
|
|
19
|
+
await scrapme.start(); // connects pg-boss
|
|
20
|
+
|
|
21
|
+
const runId = await scrapme.flow(helloFlow, { name: 'Ada' }); // queues a run; this process runs it
|
|
22
|
+
const run = await scrapme.waitFor(runId); // optional: wait for the end
|
|
23
|
+
console.log(run.status, run.steps[0]?.output);
|
|
24
|
+
await scrapme.stop();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
scrapme is a library: it reads **no environment variables** — the app passes the connection data of everything it
|
|
28
|
+
needs. `postgres` and `couch` are required; `scrapAnything`, `mail` and `lighty` only when a flow uses them
|
|
29
|
+
(without them `ScrapePageCommand` / `SendMailCommand` fail with `NOT_CONFIGURED`, errors are only logged).
|
|
30
|
+
Flows are not registered anywhere: you pass the flow to `flow()`.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install scrapme-flow inversify reflect-metadata
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Node 26+, ESM. `inversify` and `reflect-metadata` are peer dependencies (one copy for your app and scrapme).
|
|
39
|
+
|
|
40
|
+
## Hello world
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// print-message.command.ts
|
|
44
|
+
@injectable()
|
|
45
|
+
export class PrintMessageCommand implements Command<{ text: string }, string> {
|
|
46
|
+
public constructor(@inject(ConsolePrinter) private readonly printer: ConsolePrinter) {}
|
|
47
|
+
public async execute(input: { text: string }) {
|
|
48
|
+
this.printer.print(input.text);
|
|
49
|
+
return input.text;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// hello.flow.ts
|
|
54
|
+
export const helloFlow = new Flow({
|
|
55
|
+
name: 'hello',
|
|
56
|
+
params: { name: { default: 'World' } },
|
|
57
|
+
steps: [{ command: PrintMessageCommand, input: { text: (s) => 'Hello, ' + s.name + '!' } }],
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- **State:** each step's output is stored under its `key` (default: the command's class name). `input` picks from it
|
|
62
|
+
(`{ from: 'page.html' }`), adds literals (`{ value }`) or computes in plain JS (`(s) => 'doc:' + s.url`);
|
|
63
|
+
`inputFrom` passes one value; neither = the whole state. Format: [docs/FLOWS.md](docs/FLOWS.md).
|
|
64
|
+
- **Commands:** `@injectable()` classes, nothing to bind — scrapme's container is a child of yours (`autobind`), so
|
|
65
|
+
`@inject(YourService)` just works. Built in: `ScrapePageCommand` (scrap-anything), `SaveDocumentCommand` (CouchDB),
|
|
66
|
+
`SendMailCommand` (SMTP).
|
|
67
|
+
|
|
68
|
+
## Retries and timeouts
|
|
69
|
+
|
|
70
|
+
| level | what | settings | default |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| command | attempts of one step inside a flow attempt, each with a timeout (`ctx.signal` aborts) | step `retries`, `timeoutMs`, `retryDelayMs` > command `options` > `defaults` | 3 retries, 60 s |
|
|
73
|
+
| flow | the pg-boss job: run the whole flow again after a delay (backoff), expire a too long attempt | flow `retries`, `retryDelaySeconds`, `retryBackoff`, `timeoutSeconds` > `queue` | 3 retries, 30 s, backoff, 1 h |
|
|
74
|
+
|
|
75
|
+
When a step runs out of attempts, the flow attempt fails and pg-boss runs the flow again from its first step.
|
|
76
|
+
`PermanentError` (or a missing input value) is not retried. A run that fails for good is reported once to
|
|
77
|
+
LightyErrors (`lighty.dsn`).
|
|
78
|
+
|
|
79
|
+
## Monitor
|
|
80
|
+
|
|
81
|
+
`monitor: { port: 3100 }` serves the dashboard (Svelte, built into the package) and its JSON API: runs with status
|
|
82
|
+
counts and a flow filter, each run's steps (which one is running, which failed and why), every flow attempt and every
|
|
83
|
+
command attempt with error and duration. API: `GET /api/overview`, `/api/runs?flow=&status=&limit=`,
|
|
84
|
+
`/api/runs/:runId`. It only reads CouchDB, so it can run in its own process. Bound to `127.0.0.1` unless `host` says
|
|
85
|
+
otherwise — it has no login.
|
|
86
|
+
|
|
87
|
+
## API
|
|
88
|
+
|
|
89
|
+
| | |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `Scrapme.create(options)` | `container?`, `postgres`, `couch`, `queue?`, `monitor?`, `scrapAnything?`, `mail?`, `lighty?`, `defaults?`, `logLevel?` |
|
|
92
|
+
| `start({ worker? })` | connect pg-boss, start the monitor. `worker: false` = this process only queues runs |
|
|
93
|
+
| `flow(flow, input, { runId?, startAfter?, priority? })` | queue a run → run id (UUID); starts the flow's worker here on first use |
|
|
94
|
+
| `work(flow)` | run this flow's queued runs in this process without queueing one (a worker-only process) |
|
|
95
|
+
| `getRun(id)`, `listRuns(limit)` | run documents: status, steps with outputs, attempts, errors |
|
|
96
|
+
| `waitFor(id, { timeoutMs? })` | until succeeded / failed (`RunWaitTimeoutError`) |
|
|
97
|
+
| `monitorUrl`, `stop()` | |
|
|
98
|
+
|
|
99
|
+
## This repository
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
nvm use && npm install
|
|
103
|
+
./scripts/up.sh # everything at once: restarts scrap-anything, sentry-clone, the containers, the
|
|
104
|
+
# monitor (background) and runs hello; ./scripts/up.sh down stops it all
|
|
105
|
+
./scripts/deps.sh # own containers: Postgres :5434, CouchDB :5985, Mailpit :1026/:8026; checks scrap-anything
|
|
106
|
+
./scripts/monitor.sh # terminal 1, leave it open: the monitor on http://localhost:3100
|
|
107
|
+
./scripts/example.sh hello Ada # terminal 2: the hello flow, then look at it in the monitor
|
|
108
|
+
./scripts/example.sh biznesradar DOM-DEVELOPMENT # scrape → cheerio → CouchDB → e-mail (needs scrap-anything)
|
|
109
|
+
npm run dashboard:dev # the dashboard with hot reload (proxies /api to a running monitor)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The examples read `.env` (see `.env.example`) in `examples/example-services.ts` and pass the values to
|
|
113
|
+
`Scrapme.create`. Examples have no tests.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm test # every src/**/*.test.ts — no docker / internet / .env (fake queue, CouchDB, SMTP, Lighty)
|
|
117
|
+
npm run build # dist/ (tsc) + dashboard/dist (vite)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Code layout and rules: `AGENTS.md`. Decisions: `docs/adr/`.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.badge.svelte-1hfd60x{display:inline-block;padding:1px 8px;border-radius:999px;font-size:12px;font-weight:600;text-transform:lowercase;white-space:nowrap}.ok.svelte-1hfd60x{background:var(--ok-bg);color:var(--ok)}.fail.svelte-1hfd60x{background:var(--fail-bg);color:var(--fail)}.run.svelte-1hfd60x{background:var(--run-bg);color:var(--run)}.wait.svelte-1hfd60x{background:var(--wait-bg);color:var(--wait)}.idle.svelte-1hfd60x{background:var(--idle-bg);color:var(--idle)}.pulse.svelte-1hfd60x{animation:svelte-1hfd60x-pulse 1.4s ease-in-out infinite}@keyframes svelte-1hfd60x-pulse{50%{opacity:.55}}.head.svelte-hcc72y{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap}h2.svelte-hcc72y{margin:0 0 4px;display:flex;gap:10px;align-items:center}h3.svelte-hcc72y{margin:22px 0 8px;font-size:14px}dl.svelte-hcc72y{display:flex;gap:18px;margin:0}dt.svelte-hcc72y{color:var(--muted);font-size:12px}dd.svelte-hcc72y{margin:0;font-weight:600}.muted.svelte-hcc72y{color:var(--muted);font-weight:400}.fail.svelte-hcc72y{color:var(--fail)}.error-box.svelte-hcc72y{background:var(--fail-bg);color:var(--fail);padding:10px 12px;border-radius:8px;margin:14px 0 0}.pipeline.svelte-hcc72y{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px 0}.pipeline.svelte-hcc72y li:where(.svelte-hcc72y){display:flex;align-items:center}.pipeline.svelte-hcc72y li:where(.svelte-hcc72y)+li:where(.svelte-hcc72y):before{content:"→";color:var(--muted);padding:0 8px}.step.svelte-hcc72y{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;min-width:170px;padding:10px 12px;background:var(--panel);border:1px solid var(--line);border-top:4px solid var(--idle);border-radius:8px;text-align:left;cursor:pointer}.step.open.svelte-hcc72y{box-shadow:0 0 0 2px var(--accent)}.step.ok.svelte-hcc72y{border-top-color:var(--ok)}.step.fail.svelte-hcc72y{border-top-color:var(--fail)}.step.run.svelte-hcc72y{border-top-color:var(--run)}.step.wait.svelte-hcc72y{border-top-color:var(--wait)}.n.svelte-hcc72y{grid-row:span 2;color:var(--muted);font-weight:700}.name.svelte-hcc72y{font-weight:600}.cmd.svelte-hcc72y{color:var(--muted);font-size:12px;font-family:var(--mono)}.meta.svelte-hcc72y{grid-column:1 / -1;display:flex;gap:8px;align-items:center;color:var(--muted);font-size:12px;margin-top:4px}table.svelte-hcc72y{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--line);border-radius:8px}th.svelte-hcc72y,td.svelte-hcc72y{padding:6px 10px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}th.svelte-hcc72y{color:var(--muted);font-weight:500;font-size:12px}.err.svelte-hcc72y{color:var(--fail);max-width:520px;overflow-wrap:anywhere}details.svelte-hcc72y{margin-top:14px}pre.svelte-hcc72y{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:10px;overflow:auto;max-height:320px}.dots.svelte-wkwx94{display:inline-flex;gap:4px;align-items:center}.dot.svelte-wkwx94{width:10px;height:10px;border-radius:50%;background:var(--idle-bg);border:1px solid var(--line)}.ok.svelte-wkwx94{background:var(--ok);border-color:var(--ok)}.fail.svelte-wkwx94{background:var(--fail);border-color:var(--fail)}.run.svelte-wkwx94{background:var(--run);border-color:var(--run);animation:svelte-wkwx94-pulse 1.2s infinite}.wait.svelte-wkwx94{background:var(--wait);border-color:var(--wait)}@keyframes svelte-wkwx94-pulse{50%{transform:scale(.7)}}.runs.svelte-l5tdp5{list-style:none;margin:0;padding:0}li.svelte-l5tdp5+li:where(.svelte-l5tdp5){border-top:1px solid var(--line)}button.svelte-l5tdp5{display:grid;gap:4px;width:100%;padding:10px 14px;text-align:left;background:none;border:0;border-left:3px solid transparent;cursor:pointer}button.svelte-l5tdp5:hover{background:var(--bg)}button.selected.svelte-l5tdp5{background:var(--bg);border-left-color:var(--accent)}.top.svelte-l5tdp5,.mid.svelte-l5tdp5,.bottom.svelte-l5tdp5{display:flex;gap:10px;align-items:center}.top.svelte-l5tdp5{justify-content:space-between}.bottom.svelte-l5tdp5{color:var(--muted);font-size:12px}.mid.svelte-l5tdp5 code:where(.svelte-l5tdp5){color:var(--muted)}.error.svelte-l5tdp5{color:var(--fail);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.empty.svelte-l5tdp5{padding:24px 14px;color:var(--muted)}header.svelte-d3ct2b{display:flex;flex-wrap:wrap;gap:12px 24px;align-items:center;padding:12px 20px;background:var(--panel);border-bottom:1px solid var(--line)}h1.svelte-d3ct2b{margin:0;font-size:18px}h1.svelte-d3ct2b span:where(.svelte-d3ct2b){color:var(--muted);font-weight:400}.counts.svelte-d3ct2b{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.count.svelte-d3ct2b{border:1px solid var(--line);background:var(--bg);border-radius:999px;padding:2px 10px;cursor:pointer}.count.active.svelte-d3ct2b{outline:2px solid var(--accent)}.count.ok.svelte-d3ct2b strong:where(.svelte-d3ct2b){color:var(--ok)}.count.fail.svelte-d3ct2b strong:where(.svelte-d3ct2b){color:var(--fail)}.count.run.svelte-d3ct2b strong:where(.svelte-d3ct2b){color:var(--run)}.count.wait.svelte-d3ct2b strong:where(.svelte-d3ct2b){color:var(--wait)}a.svelte-d3ct2b{color:var(--accent);font-size:12px}main.svelte-d3ct2b{display:grid;grid-template-columns:minmax(280px,380px) 1fr;min-height:calc(100vh - 58px)}aside.svelte-d3ct2b{background:var(--panel);border-right:1px solid var(--line);overflow-y:auto}.filters.svelte-d3ct2b{padding:10px 14px;border-bottom:1px solid var(--line)}select.svelte-d3ct2b{width:100%;padding:4px 6px;border:1px solid var(--line);border-radius:6px;background:var(--bg)}.detail.svelte-d3ct2b{padding:18px 24px;overflow-x:auto}.muted.svelte-d3ct2b{color:var(--muted)}.error.svelte-d3ct2b{margin:0;padding:8px 20px;background:var(--fail-bg);color:var(--fail)}@media(max-width:800px){main.svelte-d3ct2b{grid-template-columns:1fr}aside.svelte-d3ct2b{border-right:0;border-bottom:1px solid var(--line);max-height:40vh}}:root{--bg: #f6f7f9;--panel: #ffffff;--text: #1c2330;--muted: #687385;--line: #e3e7ed;--accent: #3b82f6;--ok: #16a34a;--ok-bg: #dcfce7;--fail: #dc2626;--fail-bg: #fee2e2;--run: #2563eb;--run-bg: #dbeafe;--wait: #d97706;--wait-bg: #fef3c7;--idle: #9aa4b2;--idle-bg: #eef1f5;--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;color-scheme:light dark}@media(prefers-color-scheme:dark){:root{--bg: #0f1318;--panel: #171c23;--text: #e6eaf0;--muted: #8b96a6;--line: #262d37;--ok-bg: #12351f;--fail-bg: #3b1515;--run-bg: #132a4d;--wait-bg: #3a2a0c;--idle-bg: #222934}}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.45 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}button,select,input{font:inherit;color:inherit}code,pre{font-family:var(--mono);font-size:12.5px}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))n(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const l of i.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&n(l)}).observe(document,{childList:!0,subtree:!0});function r(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(s){if(s.ep)return;s.ep=!0;const i=r(s);fetch(s.href,i)}})();const Dr=!1;var Ft=Array.isArray,Rn=Array.prototype.indexOf,gt=Array.prototype.includes,Ht=Array.from,Lr=Object.defineProperty,vt=Object.getOwnPropertyDescriptor,In=Object.getOwnPropertyDescriptors,Cn=Object.prototype,Dn=Array.prototype,Ur=Object.getPrototypeOf,wr=Object.isExtensible;const Ln=()=>{};function Un(e){for(var t=0;t<e.length;t++)e[t]()}function Pr(){var e,t,r=new Promise((n,s)=>{e=n,t=s});return{promise:r,resolve:e,reject:t}}const J=2,Je=4,jt=8,Fr=1<<24,de=16,pe=32,Le=64,Jt=128,lr=256,_e=512,B=1024,F=2048,fe=4096,ee=8192,W=16384,rt=32768,Rt=1<<25,Ze=65536,It=1<<17,Pn=1<<18,nt=1<<19,Fn=1<<20,Ee=1<<25,Ct=1<<21,We=1<<22,De=1<<23,ht=Symbol("$state"),Hr=Symbol("component"),Hn=Symbol(""),jr=Symbol("attributes"),Zt=Symbol("class"),jn=Symbol("style"),$t=Symbol("text"),Mt=Symbol("form reset"),yt=new class extends Error{name="StaleReactionError";message="The reaction that called `getAbortSignal()` was re-run or destroyed"},qn=1,Bn=2,qr=4,Yn=8,Gn=16,zn=1,Vn=2,Br={},q=Symbol("uninitialized"),Kn="http://www.w3.org/1999/xhtml";function Qn(){console.warn("https://svelte.dev/e/derived_inert")}function Wn(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Xn(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function Yr(e){return e===this.v}function Jn(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function Gr(e){return!Jn(e,this.v)}function zr(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Zn(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function $n(e,t,r){throw new Error("https://svelte.dev/e/each_key_duplicate")}function es(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function ts(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function rs(e){throw new Error("https://svelte.dev/e/effect_orphan")}function ns(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function ss(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function is(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function ls(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function as(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}let os=!1,X=null;function $e(e){X=e}function st(e,t=!1,r){X={p:X,i:!1,c:null,e:null,s:e,x:null,r:A,l:null}}function it(e){var t=X,r=t.e;if(r!==null){t.e=null;for(var n of r)cn(n)}return t.i=!0,X=t.p,Vr(e)}function Vr(e={}){return Lr(e,Hr,{value:!0}),e}function Kr(){return!0}let Qe=[];function us(){var e=Qe;Qe=[],Un(e)}function Ce(e){if(Qe.length===0){var t=Qe;queueMicrotask(()=>{t===Qe&&us()})}Qe.push(e)}const fs=-7169;function P(e,t){e.f=e.f&fs|t}function ar(e){(e.f&_e)!==0||e.deps===null?P(e,B):P(e,fe)}function Qr(e,t,r){(e.f&F)!==0?t.add(e):(e.f&fe)!==0&&r.add(e),P(e,B)}let yr=!1;function cs(){yr||(yr=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(const t of e.target.elements)t[Mt]?.()})},{capture:!0}))}function bt(e){var t=S,r=A;ce(null),Te(null);try{return e()}finally{ce(t),Te(r)}}function ds(e,t,r,n=r){e.addEventListener(t,()=>bt(r));const s=e[Mt];s?e[Mt]=()=>{s(),n(!0)}:e[Mt]=()=>n(!0),cs()}function vs(e,t,r,n){const s=or;var i=e.filter(d=>!d.settled),l=t.map(s);if(r.length===0&&i.length===0){n(l);return}var a=A,o=hs(),u=i.length===1?i[0].promise:i.length>1?Promise.all(i.map(d=>d.promise)):null;function f(d){if((a.f&W)===0){o();try{n([...l,...d])}catch(p){ye(p,a)}Dt()}}var c=Wr();if(r.length===0){u.then(()=>f([])).finally(c);return}function h(){Promise.all(r.map(d=>_s(d))).then(f).catch(d=>ye(d,a)).finally(c)}u?u.then(()=>{if((a.f&W)!==0){c();return}o(),h(),Dt()}):h()}function hs(){var e=A,t=S,r=X,n=E;return function(i=!0){Te(e),ce(t),$e(r),i&&(e.f&W)===0&&(n?.activate(),n?.apply())}}function Dt(e=!0){Te(null),ce(null),$e(null),e&&E?.deactivate()}function Wr(){var e=A,t=e.b,r=E,n=!!t?.is_rendered();return t?.update_pending_count(1,r),r.increment(n,e),()=>{t?.update_pending_count(-1,r),r.decrement(n,e)}}function or(e){var t=J|F;return A!==null&&(A.f|=nt),{ctx:X,deps:null,effects:null,equals:Yr,f:t,fn:e,reactions:null,rv:0,v:q,wv:0,parent:A,ac:null}}const ft=Symbol("obsolete");function _s(e,t,r){let n=A;n===null&&Zn();var s=void 0,i=ze(q),l=!S,a=new Set;return Is(()=>{var o=A,u=Pr();s=u.promise;try{Promise.resolve(e()).then(u.resolve,d=>{d!==yt&&u.reject(d)}).finally(Dt)}catch(d){u.reject(d),Dt()}var f=E;if(l){if((o.f&rt)!==0)var c=Wr();if(n.b?.is_rendered())f.async_deriveds.get(o)?.reject(ft);else for(const d of a.values())d.reject(ft);a.add(u),f.async_deriveds.set(o,u)}const h=(d,p=void 0)=>{c?.(),a.delete(u),p!==ft&&(f.activate(),p?(i.f|=De,et(i,p)):((i.f&De)!==0&&(i.f^=De),et(i,d)),f.deactivate())};u.promise.then(h,d=>h(null,d||"unknown"))}),fn(()=>{for(const o of a)o.reject(ft)}),new Promise(o=>{function u(f){function c(){f===s?o(i):u(s)}f.then(c,c)}u(s)})}function Xr(e){const t=or(e);return pn(t),t}function ps(e){const t=or(e);return t.equals=Gr,t}function gs(e){var t=e.effects;if(t!==null){e.effects=null;for(var r=0;r<t.length;r+=1)ne(t[r])}}function ur(e){var t,r=A,n=e.parent;if(!Pe&&n!==null&&e.v!==q&&(n.f&(W|ee))!==0)return Qn(),e.v;Te(n);try{gs(e),t=yn(e)}finally{Te(r)}return t}function Jr(e){var t=ur(e);if(!e.equals(t)&&(e.wv=mn(),(!E?.is_fork||e.deps===null)&&(E!==null?(E.capture(e,t,!0),er?.capture(e,t,!0)):e.v=t,e.deps===null))){P(e,B);return}Pe||(ve!==null?(dr()||E?.is_fork)&&ve.set(e,t):ar(e))}function ms(e){if(e.effects!==null)for(const t of e.effects)(t.teardown||t.ac)&&(t.teardown?.(),t.ac!==null&&bt(()=>{t.ac.abort(yt),t.ac=null}),t.fn!==null&&(t.teardown=Ln),wt(t,0),hr(t))}function Zr(e){if(e.effects!==null)for(const t of e.effects)t.teardown&&t.fn!==null&&tt(t)}let Kt=null,Ve=null,E=null,er=null,ve=null,tr=null,Qt=!1,_t=null,Ot=null;var br=0;let ws=1;class Ue{id=ws++;#t=!1;linked=!0;#l=null;#e=null;async_deriveds=new Map;current=new Map;previous=new Map;#o=new Set;#n=new Set;#i=0;#r=new Map;#a=null;#s=[];#p=[];#u=new Set;#f=new Set;#d=new Map;#g=new Set;is_fork=!1;#c=!1;constructor(){Ve===null?Kt=Ve=this:(Ve.#e=this,this.#l=Ve),Ve=this}#b(){if(this.is_fork)return!0;for(const n of this.#r.keys()){for(var t=n,r=!1;t.parent!==null;){if(this.#d.has(t)){r=!0;break}t=t.parent}if(!r)return!0}return!1}skip_effect(t){this.#d.has(t)||this.#d.set(t,{d:[],m:[]}),this.#g.delete(t)}unskip_effect(t,r=n=>this.schedule(n)){var n=this.#d.get(t);if(n){this.#d.delete(t);for(var s of n.d)P(s,F),r(s);for(s of n.m)P(s,fe),r(s)}this.#g.add(t)}#E(){var t=[];for(const i of this.#s)if(!((i.f&W)!==0||(i.f&(F|fe))===0)){for(var r=i,n=!1;r.parent!==null;){r=r.parent;var s=r.f;if((s&(Le|pe))!==0){if((s&B)===0){n=!0;break}r.f^=B}}n||t.push(r)}return this.#s=[],t}#m(){this.#t=!0;for(const a of this.#u)this.#f.delete(a),P(a,F),this.schedule(a);for(const a of this.#f)P(a,fe),this.schedule(a);this.apply();for(var t=_t=[],r=[],n=Ot=[];this.#s.length>0;){br++>1e3&&(this.#_(),ys());for(const a of this.#E())try{this.#w(a,t,r)}catch(o){throw tn(a),this.#b()||this.discard(),o}}if(E=null,n.length>0){var s=Ue.ensure();for(const a of n)s.schedule(a)}if(_t=null,Ot=null,this.#b()){this.#h(r),this.#h(t);for(const[a,o]of this.#d)en(a,o);n.length>0&&E.#m();return}const i=this.#v();if(i){this.#h(r),this.#h(t),i.#S(this);return}this.#u.clear(),this.#f.clear();for(const a of this.#o)a(this);this.#o.clear(),er=this,Er(r),Er(t),er=null,this.#a?.resolve();var l=E;if(this.#i===0&&(this.#s.length===0||l!==null)&&this.#_(),this.#s.length>0)if(l!==null){for(const a of this.#s)l.#s.push(a);this.#s=[]}else l=this;l!==null&&(Se.clear(),l.#m())}#w(t,r,n){t.f^=B;for(var s=t.first;s!==null;){var i=s.f,l=(i&(pe|Le))!==0,a=l&&(i&B)!==0,o=a||(i&ee)!==0||this.#d.has(s);if(!o&&s.fn!==null){l?s.f^=B:(i&Je)!==0?r.push(s):St(s)&&((i&de)!==0&&this.#f.add(s),tt(s));var u=s.first;if(u!==null){s=u;continue}}for(;s!==null;){var f=s.next;if(f!==null){s=f;break}s=s.parent}}}#v(){for(var t=this.#l;t!==null;){if(!t.is_fork){for(const[r,[,n]]of this.current)if(t.current.has(r)&&!n)return t}t=t.#l}return null}#S(t){for(const[n,s]of t.current)!this.previous.has(n)&&t.previous.has(n)&&this.previous.set(n,t.previous.get(n)),this.current.set(n,s);for(const[n,s]of t.async_deriveds){const i=this.async_deriveds.get(n);i&&s.promise.then(i.resolve).catch(i.reject)}t.async_deriveds.clear(),this.transfer_effects(t.#u,t.#f);const r=n=>{var s=n.reactions;if(s!==null&&!((n.f&J)!==0&&(n.f&(F|fe))===0))for(const a of s){var i=a.f;if((i&J)!==0)r(a);else{var l=a;i&(We|de)&&!this.async_deriveds.has(l)&&(this.#f.delete(l),P(l,F),this.schedule(l))}}};for(const n of this.current.keys())r(n);this.oncommit(()=>t.discard()),t.#_(),E=this,this.#m()}#h(t){for(var r=0;r<t.length;r+=1)Qr(t[r],this.#u,this.#f)}capture(t,r,n=!1){t.v!==q&&!this.previous.has(t)&&this.previous.set(t,t.v),(t.f&De)===0&&(this.current.set(t,[r,n]),ve?.set(t,r)),this.is_fork||(t.v=r)}activate(){E=this}deactivate(){E=null,ve=null}flush(){try{Qt=!0,E=this,this.#m()}finally{br=0,tr=null,_t=null,Ot=null,Qt=!1,E=null,ve=null,Se.clear()}}discard(){for(const t of this.#n)t(this);this.#n.clear();for(const t of this.async_deriveds.values())t.reject(ft);this.#_(),this.#a?.resolve()}register_created_effect(t){this.#p.push(t)}#y(){for(let c=Kt;c!==null;c=c.#e){var t=c.id<this.id,r=[];for(const[h,[d,p]]of this.current){if(c.current.has(h)){var n=c.current.get(h)[0];if(t&&d!==n)c.current.set(h,[d,p]);else continue}r.push(h)}if(t)for(const[h,d]of this.async_deriveds){const p=c.async_deriveds.get(h);p&&d.promise.then(p.resolve).catch(p.reject)}var s=[...c.current.keys()].filter(h=>!c.current.get(h)[1]);if(!(!c.#t||s.length===0)){var i=s.filter(h=>!this.current.has(h));if(i.length===0)t&&c.discard();else if(r.length>0){if(t)for(const h of this.#g)c.unskip_effect(h,d=>{(d.f&(de|We))!==0?c.schedule(d):c.#h([d])});c.activate();var l=new Set,a=new Map;for(var o of r)$r(o,i,l,a);a=new Map;var u=[...c.current].filter(([h,d])=>{const p=this.current.get(h);return p?p[0]!==d[0]||p[1]!==d[1]:!0}).map(([h])=>h);if(u.length>0)for(const h of this.#p)(h.f&(W|ee|It))===0&&fr(h,u,a)&&((h.f&(We|de))!==0?(P(h,F),c.schedule(h)):c.#u.add(h));if(c.#s.length>0&&!c.#c){c.apply();for(var f of c.#E())c.#w(f,[],[])}c.deactivate()}}}}increment(t,r){if(this.#i+=1,t){let n=this.#r.get(r)??0;this.#r.set(r,n+1)}}decrement(t,r){if(this.#i-=1,t){let n=this.#r.get(r)??0;n===1?this.#r.delete(r):this.#r.set(r,n-1)}this.#c||(this.#c=!0,Ce(()=>{this.#c=!1,this.linked&&this.flush()}))}transfer_effects(t,r){for(const n of t)this.#u.add(n);for(const n of r)this.#f.add(n);t.clear(),r.clear()}oncommit(t){this.#o.add(t)}ondiscard(t){this.#n.add(t)}settled(){return(this.#a??=Pr()).promise}static ensure(){if(E===null){const t=E=new Ue;Qt||Ce(()=>{t.#t||t.flush()})}return E}apply(){{ve=null;return}}schedule(t){if(tr=t,t.b?.is_pending&&(t.f&(Je|jt|Fr))!==0&&(t.f&rt)===0){t.b.defer_effect(t);return}this.#s.push(t)}#_(){if(this.linked){var t=this.#l,r=this.#e;t===null?Kt=r:t.#e=r,r===null?Ve=t:r.#l=t,this.linked=!1}}}function ys(){try{ns()}catch(e){ye(e,tr)}}let Ne=null;function Er(e){var t=e.length;if(t!==0){for(var r=0;r<t;){var n=e[r++];if((n.f&(W|ee))===0&&St(n)&&(Ne=new Set,tt(n),n.deps===null&&n.first===null&&n.nodes===null&&n.teardown===null&&n.ac===null&&vn(n),Ne?.size>0)){Se.clear();for(const s of Ne){if((s.f&(W|ee))!==0)continue;const i=[s];let l=s.parent;for(;l!==null;)Ne.has(l)&&(Ne.delete(l),i.push(l)),l=l.parent;for(let a=i.length-1;a>=0;a--){const o=i[a];(o.f&(W|ee))===0&&tt(o)}}Ne.clear()}}Ne=null}}function $r(e,t,r,n){if(!r.has(e)&&(r.add(e),e.reactions!==null))for(const s of e.reactions){const i=s.f;(i&J)!==0?$r(s,t,r,n):(i&(We|de))!==0&&(i&F)===0&&fr(s,t,n)&&(P(s,F),cr(s))}}function fr(e,t,r){const n=r.get(e);if(n!==void 0)return n;if(e.deps!==null)for(const s of e.deps){if(gt.call(t,s))return!0;if((s.f&J)!==0&&fr(s,t,r))return r.set(s,!0),!0}return r.set(e,!1),!1}function cr(e){E.schedule(e)}function en(e,t){if(!((e.f&pe)!==0&&(e.f&B)!==0)){(e.f&F)!==0?t.d.push(e):(e.f&fe)!==0&&t.m.push(e),P(e,B);for(var r=e.first;r!==null;)en(r,t),r=r.next}}function tn(e){P(e,B);for(var t=e.first;t!==null;)tn(t),t=t.next}let Lt=new Set;const Se=new Map;let rn=!1;function ze(e,t){var r={f:0,v:e,reactions:null,equals:Yr,rv:0,wv:0};return r}function Q(e,t){const r=ze(e);return pn(r),r}function bs(e,t=!1,r=!0){const n=ze(e);return t||(n.equals=Gr),n}function G(e,t,r=!1){S!==null&&(!he||(S.f&It)!==0)&&Kr()&&(S.f&(J|de|We|It))!==0&&(xe===null||!xe.has(e))&&ls();let n=r?He(t):t;return et(e,n,Ot)}var Fe=null,rr=0;function et(e,t,r=null){if(!e.equals(t)){Pe?Se.set(e,t):Se.has(e)||Se.set(e,e.v);var n=Ue.ensure();if(n.capture(e,t),(e.f&J)!==0){const s=e;(e.f&F)!==0&&ur(s),ve===null&&ar(s)}e.wv=mn(),Fe=null,rr=0,nn(e,F,r),Fe=null,A!==null&&(A.f&B)!==0&&(A.f&(pe|Le))===0&&(oe===null?Us([e]):oe.push(e)),!n.is_fork&&Lt.size>0&&!rn&&Es()}return t}function Es(){rn=!1;for(const e of Lt){(e.f&B)!==0&&P(e,fe);let t;try{t=St(e)}catch{t=!0}t&&tt(e)}Lt.clear()}function pt(e){G(e,e.v+1)}function nn(e,t,r){var n=e.reactions;if(n!==null){var s=n.length;if(rr+=s,rr>1e5&&Fe===null&&(Fe=new Set),Fe!==null){if(Fe.has(e))return;Fe.add(e)}for(var i=0;i<s;i++){var l=n[i],a=l.f,o=(a&F)===0;if(o&&P(l,t),(a&It)!==0)Lt.add(l);else if((a&J)!==0){var u=l;ve?.delete(u),nn(u,fe,r)}else if(o){var f=l;(a&de)!==0&&Ne!==null&&Ne.add(f),r!==null?r.push(f):cr(f)}}}}function He(e){if(typeof e!="object"||e===null||ht in e||Hr in e)return e;const t=Ur(e);if(t!==Cn&&t!==Dn)return e;var r=new Map,n=Ft(e),s=Q(0),i=Ye,l=a=>{if(Ye===i)return a();var o=S,u=Ye;ce(null),kr(i);var f=a();return ce(o),kr(u),f};return n&&r.set("length",Q(e.length)),new Proxy(e,{defineProperty(a,o,u){(!("value"in u)||u.configurable===!1||u.enumerable===!1||u.writable===!1)&&ss();var f=r.get(o);return f===void 0?l(()=>{var c=Q(u.value);return r.set(o,c),c}):G(f,u.value,!0),!0},deleteProperty(a,o){var u=r.get(o);if(u===void 0){if(o in a){const f=l(()=>Q(q));r.set(o,f),pt(s)}}else G(u,q),pt(s);return!0},get(a,o,u){if(o===ht)return e;var f=r.get(o),c=o in a;if(f===void 0&&(!c||vt(a,o)?.writable)&&(f=l(()=>{var d=He(c?a[o]:q),p=Q(d);return p}),r.set(o,f)),f!==void 0){var h=v(f);return h===q?void 0:h}return Reflect.get(a,o,u)},getOwnPropertyDescriptor(a,o){this.has?.(a,o);var u=Reflect.getOwnPropertyDescriptor(a,o),f=r.get(o);if(f!==void 0){var c=v(f);if(c===q)return;if(u&&"value"in u)u.value=c;else return{enumerable:!0,configurable:!0,value:c,writable:!0}}return u},has(a,o){if(o===ht)return!0;var u=r.get(o),f=u!==void 0&&u.v!==q||Reflect.has(a,o);if(u!==void 0||A!==null&&(!f||vt(a,o)?.writable)){u===void 0&&(u=l(()=>{var h=f?He(a[o]):q,d=Q(h);return d}),r.set(o,u));var c=v(u);if(c===q)return!1}return f},set(a,o,u,f){var c=r.get(o),h=o in a;if(n&&o==="length")for(var d=u;d<c.v;d+=1){var p=r.get(d+"");p!==void 0?G(p,q):d in a&&(p=l(()=>Q(q)),r.set(d+"",p))}if(c===void 0)(!h||vt(a,o)?.writable)&&(c=l(()=>Q(void 0)),G(c,He(u)),r.set(o,c));else{h=c.v!==q;var k=l(()=>He(u));G(c,k)}var _=Reflect.getOwnPropertyDescriptor(a,o);if(_?.set&&_.set.call(f,u),!h){if(n&&typeof o=="string"){var w=r.get("length"),O=Number(o);Number.isInteger(O)&&O>=w.v&&G(w,O+1)}pt(s)}return!0},ownKeys(a){v(s);var o=Reflect.ownKeys(a).filter(c=>{var h=r.get(c);return h===void 0||h.v!==q});for(var[u,f]of r)f.v!==q&&!(u in a)&&o.push(u);return o},setPrototypeOf(){is()}})}function Sr(e){try{if(e!==null&&typeof e=="object"&&ht in e)return e[ht]}catch{}return e}function sn(e,t){return Object.is(Sr(e),Sr(t))}var xr,ln,an,on;function Ss(){if(xr===void 0){xr=window,ln=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,r=Text.prototype;an=vt(t,"firstChild").get,on=vt(t,"nextSibling").get,wr(e)&&(e[Zt]=void 0,e[jr]=null,e[jn]=void 0,e.__e=void 0),wr(r)&&(r[$t]=void 0)}}function qe(e=""){return document.createTextNode(e)}function mt(e){return an.call(e)}function Et(e){return on.call(e)}function x(e,t){return mt(e)}function nr(e,t=!1){{var r=mt(e);return r instanceof Comment&&r.data===""?Et(r):r}}function T(e,t=!1){return mt(e)}function m(e,t=1,r=!1){let n=e;for(;t--;)n=Et(n);return n}function xs(e){e.textContent=""}function un(){return!1}function Ts(e,t,r){return r?document.createElement(e,{is:r}):document.createElement(e)}function ks(e){var t=A;if(t===null)return S.f|=De,e;if((t.f&rt)===0&&(t.f&Je)===0)throw e;ye(e,t)}function ye(e,t){if(e===Br)throw e;if(!(t!==null&&(t.f&W)!==0)){for(;t!==null;){if((t.f&Jt)!==0&&(t.f&(W|Rt))===0){if((t.f&rt)===0)throw e;try{t.b.error(e);return}catch(r){e=r}}t=t.parent}throw e}}function As(e){A===null&&(S===null&&rs(),ts()),Pe&&es()}function Ns(e,t){var r=t.last;r===null?t.last=t.first=e:(r.next=e,e.prev=r,t.last=e)}function Me(e,t){var r=A;r!==null&&(r.f&ee)!==0&&(e|=ee);var n={ctx:X,deps:null,nodes:null,f:e|F|_e,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};E?.register_created_effect(n);var s=n;if((e&Je)!==0)_t!==null?_t.push(n):Ue.ensure().schedule(n);else if(t!==null){try{tt(n)}catch(l){throw ne(n),l}s.deps===null&&s.teardown===null&&s.nodes===null&&s.first===s.last&&(s.f&nt)===0&&(s=s.first,(e&de)!==0&&(e&Ze)!==0&&s!==null&&(s.f|=Ze))}if(s!==null&&(s.parent=r,r!==null&&Ns(s,r),S!==null&&(S.f&J)!==0&&(e&Le)===0)){var i=S;(i.effects??=[]).push(s)}return n}function dr(){return S!==null&&!he}function fn(e){const t=Me(jt,null);return P(t,B),t.teardown=e,t}function Ms(e){As();var t=A.f,r=!S&&(t&pe)!==0&&X!==null&&!X.i;if(r){var n=X;(n.e??=[]).push(e)}else return cn(e)}function cn(e){return Me(Je|Fn,e)}function Os(e){Ue.ensure();const t=Me(Le|nt,e);return(r={})=>new Promise(n=>{r.outro?Be(t,()=>{ne(t),n(void 0)}):(ne(t),n(void 0))})}function Rs(e){return Me(Je,e)}function Is(e){return Me(We|nt,e)}function Cs(e,t=0){return Me(jt|t,e)}function K(e,t=[],r=[],n=[]){vs(n,t,r,s=>{Me(jt,()=>{e(...s.map(v))})})}function vr(e,t=0){var r=Me(de|t,e);return r}function ue(e){return Me(pe|nt,e)}function dn(e){var t=e.teardown;if(t!==null){const r=Pe,n=S;Tr(!0),ce(null);try{t.call(null)}catch(s){ye(s,e.parent)}finally{Tr(r),ce(n)}}}function hr(e,t=!1){var r=e.first;for(e.first=e.last=null;r!==null;){const s=r.ac;s!==null&&bt(()=>{s.abort(yt)});var n=r.next;(r.f&Le)!==0?r.parent=null:ne(r,t),r=n}}function Ds(e){for(var t=e.first;t!==null;){var r=t.next;(t.f&pe)===0&&ne(t),t=r}}function ne(e,t=!0){var r=!1;(t||(e.f&Pn)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(Ls(e.nodes.start,e.nodes.end),r=!0),e.f|=Rt,hr(e,t&&!r),wt(e,0);var n=e.nodes&&e.nodes.t;if(n!==null)for(const i of n)i.stop();dn(e),e.f^=Rt,e.f|=W;var s=e.parent;s!==null&&s.first!==null&&vn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Ls(e,t){for(;e!==null;){var r=e===t?null:Et(e);e.remove(),e=r}}function vn(e){var t=e.parent,r=e.prev,n=e.next;r!==null&&(r.next=n),n!==null&&(n.prev=r),t!==null&&(t.first===e&&(t.first=n),t.last===e&&(t.last=r))}function Be(e,t,r=!0){var n=[];e.f|=lr,hn(e,n,!0);var s=()=>{r&&ne(e),t&&t()},i=n.length;if(i>0){var l=()=>--i||s();for(var a of n)a.out(l)}else s()}function hn(e,t,r){if((e.f&ee)===0){e.f^=ee;var n=e.nodes&&e.nodes.t;if(n!==null)for(const a of n)(a.is_global||r)&&t.push(a);for(var s=e.first;s!==null;){var i=s.next;if((s.f&Le)===0){var l=(s.f&Ze)!==0||(s.f&pe)!==0&&(e.f&de)!==0;hn(s,t,l?r:!1)}s=i}}}function Ut(e){e.f&=~lr,_n(e,!0)}function _n(e,t){if((e.f&lr)===0&&(e.f&ee)!==0){e.f^=ee,(e.f&B)===0&&(P(e,F),Ue.ensure().schedule(e));for(var r=e.first;r!==null;){var n=r.next,s=(r.f&Ze)!==0||(r.f&pe)!==0;_n(r,s?t:!1),r=n}var i=e.nodes&&e.nodes.t;if(i!==null)for(const l of i)(l.is_global||t)&&l.in()}}function _r(e,t){if(e.nodes)for(var r=e.nodes.start,n=e.nodes.end;r!==null;){var s=r===n?null:Et(r);t.append(r),r=s}}let Pe=!1;function Tr(e){Pe=e}let S=null,he=!1;function ce(e){S=e}let A=null;function Te(e){A=e}let xe=null;function pn(e){S!==null&&((S.f&Ct)!==0||(S.f&J)!==0)&&(xe??=new Set).add(e)}let re=null,ae=0,oe=null;function Us(e){oe=e}let gn=1,je=0,Ye=je;function kr(e){Ye=e}function mn(){return++gn}function St(e){var t=e.f;if((t&F)!==0)return!0;if((t&fe)!==0){for(var r=e.deps,n=r.length,s=0;s<n;s++){var i=r[s];if(St(i)&&Jr(i),i.wv>e.wv)return!0}(t&_e)!==0&&ve===null&&P(e,B)}return!1}function wn(e,t,r=!0){var n=e.reactions;if(n!==null&&!(xe!==null&&xe.has(e)))for(var s=0;s<n.length;s++){var i=n[s];(i.f&J)!==0?wn(i,t,!1):t===i&&(r?P(i,F):(i.f&B)!==0&&P(i,fe),cr(i))}}function yn(e){var t=re,r=ae,n=oe,s=S,i=xe,l=X,a=he,o=Ye,u=e.f;re=null,ae=0,oe=null,S=(u&(pe|Le))===0?e:null,xe=null,$e(e.ctx),he=!1,Ye=++je,e.ac!==null&&(bt(()=>{e.ac.abort(yt)}),e.ac=null);try{e.f|=Ct;var f=e.fn,c=f();e.f|=rt;var h=Ar(e);if(Kr()&&oe!==null&&!he&&h!==null&&(e.f&(J|fe|F))===0)for(var d=0;d<oe.length;d++)wn(oe[d],e);if(s!==null&&s!==e){if(je++,s.deps!==null)for(let p=0;p<r;p+=1)s.deps[p].rv=je;if(t!==null)for(const p of t)p.rv=je;oe!==null&&(n===null?n=oe:n.push(...oe))}return(e.f&De)!==0&&(e.f^=De),c}catch(p){return Ar(e),ks(p)}finally{e.f^=Ct,re=t,ae=r,oe=n,S=s,xe=i,$e(l),he=a,Ye=o}}function Ar(e){var t=e.deps,r=E?.is_fork;if(re!==null){var n;if(r||wt(e,ae),t!==null&&ae>0)for(t.length=ae+re.length,n=0;n<re.length;n++)t[ae+n]=re[n];else e.deps=t=re;if(dr()&&(e.f&_e)!==0)for(n=ae;n<t.length;n++)(t[n].reactions??=[]).push(e)}else!r&&t!==null&&ae<t.length&&(wt(e,ae),t.length=ae);return t}function Ps(e,t){let r=t.reactions;if(r!==null){var n=Rn.call(r,e);if(n!==-1){var s=r.length-1;s===0?r=t.reactions=null:(r[n]=r[s],r.pop())}}if(r===null&&(t.f&J)!==0&&(re===null||!gt.call(re,t))){var i=t;(i.f&_e)!==0&&(i.f^=_e),i.v!==q&&ar(i),i.ac!==null&&bt(()=>{i.ac.abort(yt),i.ac=null,P(i,F)}),ms(i),wt(i,0)}}function wt(e,t){var r=e.deps;if(r!==null)for(var n=t;n<r.length;n++)Ps(e,r[n])}function tt(e){var t=e.f;if((t&W)===0){P(e,B);var r=A;A=e;try{(t&(de|Fr))!==0?Ds(e):hr(e),dn(e);var n=yn(e);e.teardown=typeof n=="function"?n:null,e.wv=gn;var s;Dr&&os&&(e.f&F)!==0&&e.deps}finally{A=r}}}function v(e){var t=e.f,r=(t&J)!==0;if(S!==null&&!he){var n=A!==null&&(A.f&W)!==0;if(!n&&(xe===null||!xe.has(e))){var s=S.deps;if((S.f&Ct)!==0)e.rv<je&&(e.rv=je,re===null&&s!==null&&s[ae]===e?ae++:re===null?re=[e]:re.push(e));else{S.deps??=[],gt.call(S.deps,e)||S.deps.push(e);var i=e.reactions;i===null?e.reactions=[S]:gt.call(i,S)||i.push(S)}}}if(Pe&&Se.has(e))return Se.get(e);if(r){var l=e;if(Pe){var a=l.v;return((l.f&B)===0&&l.reactions!==null||En(l))&&(a=ur(l)),Se.set(l,a),a}var o=(l.f&_e)===0&&!he&&S!==null&&(S.f&_e)!==0,u=(l.f&rt)===0;St(l)&&(o&&(l.f|=_e),Jr(l)),o&&!u&&(Zr(l),bn(l))}if(ve?.has(e))return ve.get(e);if((e.f&De)!==0)throw e.v;return e.v}function bn(e){if(e.f|=_e,e.deps!==null)for(const r of e.deps){var t=r.reactions;t===null?r.reactions=[e]:gt.call(t,e)||t.push(e),(r.f&J)!==0&&(r.f&_e)===0&&(Zr(r),bn(r))}}function En(e){if(e.v===q)return!0;if(e.deps===null)return!1;for(const t of e.deps)if(Se.has(t)||(t.f&J)!==0&&En(t))return!0;return!1}function pr(e){var t=he;try{return he=!0,e()}finally{he=t}}const Fs=["touchstart","touchmove"];function Hs(e){return Fs.includes(e)}const ct=Symbol("events"),Sn=new Set,sr=new Set;function Pt(e,t,r){(t[ct]??={})[e]=r}function gr(e){for(var t=0;t<e.length;t++)Sn.add(e[t]);for(var r of sr)r(e)}let Wt=null,Xt=!1;function Nr(e){var t=this,r=t.ownerDocument,n=e.type,s=e.composedPath?.()||[],i=s[0]||e.target;Wt=e,Xt||(Xt=!0,setTimeout(()=>{Xt=!1,Wt=null}));var l=0,a=Wt===e&&e[ct];if(a){var o=s.indexOf(a);if(o!==-1&&(t===document||t===window)){e[ct]=t;return}var u=s.indexOf(t);if(u===-1)return;o<=u&&(l=o)}if(i=s[l]||e.target,i!==t){Lr(e,"currentTarget",{configurable:!0,get(){return i||r}});var f=S,c=A;ce(null),Te(null);try{for(var h,d=[];i!==null&&i!==t;){try{var p=i[ct]?.[n];p!=null&&(!i.disabled||e.target===i)&&p.call(i,e)}catch(k){h?d.push(k):h=k}if(e.cancelBubble)break;l++,i=l<s.length?s[l]:null}if(h){for(let k of d)queueMicrotask(()=>{throw k});throw h}}finally{e[ct]=t,delete e.currentTarget,ce(f),Te(c)}}}const js=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function qs(e){return js?.createHTML(e)??e}function Bs(e){var t=Ts("template");return t.innerHTML=qs(e.replaceAll("<!>","<!---->")),t.content}function Mr(e,t){var r=A;r.nodes===null&&(r.nodes={start:e,end:t,a:null,t:null})}function I(e,t){var r=(t&zn)!==0,n=(t&Vn)!==0,s,i=!e.startsWith("<!>");return()=>{s===void 0&&(s=Bs(i?e:"<!>"+e),r||(s=mt(s)));var l=n||ln?document.importNode(s,!0):s.cloneNode(!0);if(r){var a=mt(l),o=l.lastChild;Mr(a,o)}else Mr(l,l);return l}}function R(e,t){e!==null&&e.before(t)}function Ys(e){let t=0,r=ze(0),n;return()=>{dr()&&(v(r),Cs(()=>(t===0&&(n=pr(()=>e(()=>pt(r)))),t+=1,()=>{Ce(()=>{t-=1,t===0&&(n?.(),n=void 0,pt(r))})})))}}var Gs=Ze|nt;function zs(e,t,r,n){new Vs(e,t,r,n)}class Vs{parent;is_pending=!1;transform_error;#t;#l=null;#e;#o;#n;#i=null;#r=null;#a=null;#s=null;#p=0;#u=0;#f=!1;#d=new Set;#g=new Set;#c=null;#b=Ys(()=>(this.#c=ze(this.#p),()=>{this.#c=null}));constructor(t,r,n,s){this.#t=t,this.#e=r,this.#o=i=>{var l=A;l.b=this,l.f|=Jt,n(i)},this.parent=A.b,this.transform_error=s??this.parent?.transform_error??(i=>i),this.#n=vr(()=>{this.#h()},Gs)}#E(){try{this.#i=ue(()=>this.#o(this.#t))}catch(t){this.error(t)}}#m(t){const r=this.#e.failed,{reset:n,invoke_onerror:s}=this.#w(t);Ce(s),r&&(this.#a=ue(()=>{r(this.#t,()=>t,()=>n)}))}#w(t){var r=!1,n=!1;const s=()=>{if(!this.#v()){if(r){Xn();return}r=!0,n&&as(),this.#a!==null&&Be(this.#a,()=>{this.#a=null}),this.#_(()=>{this.#h()})}};return{reset:s,invoke_onerror:()=>{if(!this.#v())try{n=!0,this.#e.onerror?.(t,s),n=!1}catch(l){ye(l,this.#n&&this.#n.parent)}}}}#v(){return(this.#n.f&(W|Rt))!==0}#S(){const t=this.#e.pending;t&&(this.is_pending=!0,this.#r=ue(()=>t(this.#t)),Ce(()=>{if(!this.#v()){var r=this.#s=document.createDocumentFragment(),n=qe(),s=!1;if(r.append(n),this.#i=this.#_(()=>{try{return ue(()=>this.#o(n))}catch(i){try{this.error(i),s=!0}catch(l){ye(l,this.#n.parent)}return null}}),this.#i===null){this.#s=null,s&&this.#y(E);return}this.#u===0&&(this.#t.before(r),this.#s=null,Be(this.#r,()=>{this.#r=null}),this.#y(E))}}))}#h(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#p=0,this.#i=ue(()=>{this.#o(this.#t)}),this.#u>0){var t=this.#s=document.createDocumentFragment();_r(this.#i,t);const r=this.#e.pending;this.#r=ue(()=>r(this.#t))}else this.#y(E)}catch(r){this.error(r)}}#y(t){this.is_pending=!1,t.transfer_effects(this.#d,this.#g)}defer_effect(t){Qr(t,this.#d,this.#g)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#e.pending}#_(t){var r=A,n=S,s=X;Te(this.#n),ce(this.#n),$e(this.#n.ctx);try{return Ue.ensure(),t()}finally{Te(r),ce(n),$e(s)}}#x(t,r){if(!this.has_pending_snippet()){this.parent&&this.parent.#x(t,r);return}this.#u+=t,this.#u===0&&(this.#y(r),this.#r&&Be(this.#r,()=>{this.#r=null}),this.#s&&(this.#t.before(this.#s),this.#s=null))}update_pending_count(t,r){this.#x(t,r),this.#p+=t,!(!this.#c||this.#f)&&(this.#f=!0,Ce(()=>{this.#f=!1,this.#c&&et(this.#c,this.#p)}))}get_effect_pending(){return this.#b(),v(this.#c)}error(t){if(t===Br||!this.#e.onerror&&!this.#e.failed)throw t;E?.is_fork?(this.#i&&E.skip_effect(this.#i),this.#r&&E.skip_effect(this.#r),this.#a&&E.skip_effect(this.#a),E.oncommit(()=>{this.#v()||this.#T(t)})):this.#T(t)}#T(t){this.#i&&(ne(this.#i),this.#i=null),this.#r&&(ne(this.#r),this.#r=null),this.#a&&(ne(this.#a),this.#a=null);let r=this.#e.failed;const n=s=>{if(this.#v())return;const{reset:i,invoke_onerror:l}=this.#w(s);l(),r&&!this.#v()&&(this.#a=this.#_(()=>{try{return ue(()=>{var a=A;a.b=this,a.f|=Jt,r(this.#t,()=>s,()=>i)})}catch(a){return ye(a,this.#n.parent),null}}))};Ce(()=>{if(!this.#v()){var s;try{s=this.transform_error(t)}catch(i){ye(i,this.#n&&this.#n.parent);return}s!==null&&typeof s=="object"&&typeof s.then=="function"?s.then(n,i=>ye(i,this.#n&&this.#n.parent)):n(s)}})}}function b(e,t){var r=t==null?"":typeof t=="object"?`${t}`:t;r!==(e[$t]??=e.nodeValue)&&(e[$t]=r,e.nodeValue=`${r}`)}function Ks(e,t){return Qs(e,t)}const Nt=new Map;function Qs(e,{target:t,anchor:r,props:n={},events:s,context:i,intro:l=!0,transformError:a}){Ss();var o=void 0,u=Os(()=>{var f=r??t.appendChild(qe());zs(f,{pending:()=>{}},d=>{st({});var p=X;i&&(p.c=i),s&&(n.$$events=s),o=e(d,n)||Vr(),it()},a);var c=new Set,h=d=>{for(var p=0;p<d.length;p++){var k=d[p];if(!c.has(k)){c.add(k);var _=Hs(k);for(const C of[t,document]){var w=Nt.get(C);w===void 0&&(w=new Map,Nt.set(C,w));var O=w.get(k);O===void 0?(C.addEventListener(k,Nr,{passive:_}),w.set(k,1)):w.set(k,O+1)}}}};return h(Ht(Sn)),sr.add(h),()=>{for(var d of c)for(const _ of[t,document]){var p=Nt.get(_),k=p.get(d);--k==0?(_.removeEventListener(d,Nr),p.delete(d),p.size===0&&Nt.delete(_)):p.set(d,k)}sr.delete(h),f!==r&&f.parentNode?.removeChild(f)}});return Ws.set(o,u),o}let Ws=new WeakMap;class Xs{anchor;#t=new Map;#l=new Map;#e=new Map;#o=new Set;#n=!0;constructor(t,r=!0){this.anchor=t,this.#n=r}#i=t=>{if(this.#t.has(t)){var r=this.#t.get(t),n=this.#l.get(r);if(n)Ut(n),this.#o.delete(r);else{var s=this.#e.get(r);s&&(Ut(s.effect),this.#l.set(r,s.effect),this.#e.delete(r),s.fragment.lastChild.remove(),this.anchor.before(s.fragment),n=s.effect)}for(const[i,l]of this.#t){if(this.#t.delete(i),i===t)break;const a=this.#e.get(l);a&&(ne(a.effect),this.#e.delete(l))}for(const[i,l]of this.#l){if(i===r||this.#o.has(i))continue;const a=()=>{if(Array.from(this.#t.values()).includes(i)){var u=document.createDocumentFragment();_r(l,u),u.append(qe()),this.#e.set(i,{effect:l,fragment:u})}else ne(l);this.#o.delete(i),this.#l.delete(i)};this.#n||!n?(this.#o.add(i),Be(l,a,!1)):a()}}};#r=t=>{this.#t.delete(t);const r=Array.from(this.#t.values());for(const[n,s]of this.#e)r.includes(n)||(ne(s.effect),this.#e.delete(n))};ensure(t,r){var n=E,s=un();if(r&&!this.#l.has(t)&&!this.#e.has(t))if(s){var i=document.createDocumentFragment(),l=qe();i.append(l),this.#e.set(t,{effect:ue(()=>r(l)),fragment:i})}else this.#l.set(t,ue(()=>r(this.anchor)));if(this.#t.set(n,t),s){for(const[a,o]of this.#l)a===t?n.unskip_effect(o):n.skip_effect(o);for(const[a,o]of this.#e)a===t?n.unskip_effect(o.effect):n.skip_effect(o.effect);n.oncommit(this.#i),n.ondiscard(this.#r)}else this.#i(n)}}function be(e,t,r=!1){var n=new Xs(e),s=r?Ze:0;function i(l,a){n.ensure(l,a)}vr(()=>{var l=!1;t((a,o=0)=>{l=!0,i(o,a)}),l||i(-1,null)},s)}function Js(e,t){return t}function Zs(e,t,r){for(var n=[],s=t.length,i,l=t.length,a=0;a<s;a++){let c=t[a];Be(c,()=>{if(i){if(i.pending.delete(c),i.done.add(c),i.pending.size===0){var h=e.outrogroups;ir(e,Ht(i.done)),h.delete(i),h.size===0&&(e.outrogroups=null)}}else l-=1},!1)}if(l===0){var o=n.length===0&&r!==null&&e.pending.size===0;if(o){var u=r,f=u.parentNode;xs(f),f.append(u),e.items.clear()}ir(e,t,!o)}else i={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(i)}function ir(e,t,r=!0){var n;if(e.pending.size>0){n=new Set;for(const l of e.pending.values())for(const a of l)n.add(e.items.get(a).e)}for(var s=0;s<t.length;s++){var i=t[s];if(n?.has(i)){i.f|=Ee;const l=document.createDocumentFragment();_r(i,l)}else ne(t[s],r)}}var Or;function Ge(e,t,r,n,s,i=null){var l=e,a=new Map,o=(t&qr)!==0;if(o){var u=e;l=u.appendChild(qe())}var f=null,c=ps(()=>{var O=r();return Ft(O)?O:O==null?[]:Ht(O)}),h=new Map,d=!0;function p(O){if((w.effect.f&W)===0){w.pending.delete(O);var C=v(c);w.fallback=f,$s(w,C,l,t,n),f!==null&&(C.length===0?(f.f&Ee)===0?Ut(f):(f.f^=Ee,dt(f,null,l)):Be(f,()=>{f=null}))}}function k(O){w.pending.delete(O)}var _=vr(()=>{for(var O=v(c),C=O.length,j=new Set,Z=E,te=un(),H=0;H<C;H+=1){var z=O[H],D=n(z,H),N=d?null:a.get(D);N?(N.v&&et(N.v,z),N.i&&et(N.i,H),te&&Z.unskip_effect(N.e)):(N=ei(a,d?l:Or??=qe(),z,D,H,s,t,r),d||(N.e.f|=Ee),a.set(D,N)),j.add(D)}if(C===0&&i&&!f&&(d?f=ue(()=>i(l)):(f=ue(()=>i(Or??=qe())),f.f|=Ee)),C>j.size&&$n(),!d)if(h.set(Z,j),te){for(const[ge,at]of a)j.has(ge)||Z.skip_effect(at.e);Z.oncommit(p),Z.ondiscard(k)}else p(Z);v(c)}),w={effect:_,items:a,pending:h,outrogroups:null,fallback:f};d=!1}function ut(e){for(;e!==null&&(e.f&pe)===0;)e=e.next;return e}function $s(e,t,r,n,s){var i=(n&Yn)!==0,l=t.length,a=e.items,o=ut(e.effect.first),u,f=null,c,h=[],d=[],p,k,_,w;if(i)for(w=0;w<l;w+=1)p=t[w],k=s(p,w),_=a.get(k).e,(_.f&Ee)===0&&(_.nodes?.a?.measure(),(c??=new Set).add(_));for(w=0;w<l;w+=1){if(p=t[w],k=s(p,w),_=a.get(k).e,e.outrogroups!==null)for(const N of e.outrogroups)N.pending.delete(_),N.done.delete(_);if((_.f&ee)!==0&&(Ut(_),i&&(_.nodes?.a?.unfix(),(c??=new Set).delete(_))),(_.f&Ee)!==0)if(_.f^=Ee,_===o)dt(_,null,r);else{var O=f?f.next:o;_===e.effect.last&&(e.effect.last=_.prev),_.prev&&(_.prev.next=_.next),_.next&&(_.next.prev=_.prev),Ie(e,f,_),Ie(e,_,O),dt(_,O,r),f=_,h=[],d=[],o=ut(f.next);continue}if(_!==o){if(u!==void 0&&u.has(_)){if(h.length<d.length){var C=d[0],j;f=C.prev;var Z=h[0],te=h[h.length-1];for(j=0;j<h.length;j+=1)dt(h[j],C,r);for(j=0;j<d.length;j+=1)u.delete(d[j]);Ie(e,Z.prev,te.next),Ie(e,f,Z),Ie(e,te,C),o=C,f=te,w-=1,h=[],d=[]}else u.delete(_),dt(_,o,r),Ie(e,_.prev,_.next),Ie(e,_,f===null?e.effect.first:f.next),Ie(e,f,_),f=_;continue}for(h=[],d=[];o!==null&&o!==_;)(u??=new Set).add(o),d.push(o),o=ut(o.next);if(o===null)continue}(_.f&Ee)===0&&h.push(_),f=_,o=ut(_.next)}if(e.outrogroups!==null){for(const N of e.outrogroups)N.pending.size===0&&(ir(e,Ht(N.done)),e.outrogroups?.delete(N));e.outrogroups.size===0&&(e.outrogroups=null)}if(o!==null||u!==void 0){var H=[];if(u!==void 0)for(_ of u)(_.f&ee)===0&&H.push(_);for(;o!==null;)(o.f&ee)===0&&o!==e.fallback&&H.push(o),o=ut(o.next);var z=H.length;if(z>0){var D=(n&qr)!==0&&l===0?r:null;if(i){for(w=0;w<z;w+=1)H[w].nodes?.a?.measure();for(w=0;w<z;w+=1)H[w].nodes?.a?.fix()}Zs(e,H,D)}}i&&Ce(()=>{if(c!==void 0)for(_ of c)_.nodes?.a?.apply()})}function ei(e,t,r,n,s,i,l,a){var o=(l&qn)!==0?(l&Gn)===0?bs(r,!1,!1):ze(r):null,u=(l&Bn)!==0?ze(s):null;return{v:o,i:u,e:ue(()=>(i(t,o??r,u??s,a),()=>{e.delete(n)}))}}function dt(e,t,r){if(e.nodes)for(var n=e.nodes.start,s=e.nodes.end,i=t&&(t.f&Ee)===0?t.nodes.start:r;n!==null;){var l=Et(n);if(i.before(n),n===s)return;n=l}}function Ie(e,t,r){t===null?e.effect.first=r:t.next=r,r===null?e.effect.last=t:r.prev=t}const Rr=[...`
|
|
2
|
+
\r\f \v\uFEFF`];function ti(e,t,r){var n=e==null?"":""+e;if(t&&(n=n?n+" "+t:t),r){for(var s of Object.keys(r))if(r[s])n=n?n+" "+s:s;else if(n.length)for(var i=s.length,l=0;(l=n.indexOf(s,l))>=0;){var a=l+i;(l===0||Rr.includes(n[l-1]))&&(a===n.length||Rr.includes(n[a]))?n=(l===0?"":n.substring(0,l))+n.substring(a+1):l=a}}return n===""?null:n}function xt(e,t,r,n,s,i){var l=e[Zt];if(l!==r||l===void 0){var a=ti(r,n,i);a==null?e.removeAttribute("class"):e.className=a,e[Zt]=r}else if(i&&s!==i)for(var o in i){var u=!!i[o];(s==null||u!==!!s[o])&&e.classList.toggle(o,u)}return i}function ri(e,t){t?e.hasAttribute("selected")||e.setAttribute("selected",""):e.removeAttribute("selected")}function ni(e,t){var r=e.__defaultValue,n=e.multiple,s=n?r??[]:null;if(!(n&&!Ft(s))){e.selectedIndex;for(var i of e.options){var l=Xe(i);ri(i,n?s.includes(l):sn(l,r))}}}function xn(e,t,r=!1){if(e.multiple){if(t==null)return;if(!Ft(t))return Wn();for(var n of e.options)n.selected=t.includes(Xe(n));return}for(n of e.options){var s=Xe(n);if(sn(s,t)){n.selected=!0;return}}(!r||t!==void 0)&&(e.selectedIndex=-1)}function si(e){var t=new MutationObserver(r=>{r.every(li)||("__defaultValue"in e&&ni(e),"__value"in e&&xn(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),fn(()=>{t.disconnect()})}function ii(e,t,r=t){var n=new WeakSet,s=!0;ds(e,"change",i=>{var l=i?"[selected]":":checked",a;if(e.multiple)a=[].map.call(e.querySelectorAll(l),Xe);else{var o=e.querySelector(l)??e.querySelector("option:not([disabled])");a=o&&Xe(o)}r(a),e.__value=a,E!==null&&n.add(E)}),Rs(()=>{var i=t();if(e===document.activeElement){var l=E;if(n.has(l))return}if(xn(e,i,s),s&&i===void 0){var a=e.querySelector(":checked");a!==null&&(i=Xe(a),r(i))}e.__value=i,s=!1})}function Xe(e){return"__value"in e?e.__value:e.value}function li(e){if(e.target.closest("selectedcontent")!==null)return!0;if(e.type==="childList"){var t=[...e.addedNodes,...e.removedNodes];return t.length>0&&t.every(r=>r.nodeName==="SELECTEDCONTENT")}return!1}const ai=Symbol("is custom element"),oi=Symbol("is html");function Tn(e,t,r,n){var s=ui(e);s[t]!==(s[t]=r)&&(t==="loading"&&(e[Hn]=r),r==null?e.removeAttribute(t):typeof r!="string"&&fi(e).has(t)?e[t]=r:e.setAttribute(t,r))}function ui(e){return e[jr]??={[ai]:e.nodeName.includes("-"),[oi]:e.namespaceURI===Kn}}var Ir=new Map;function fi(e){var t=e.getAttribute("is")||e.nodeName,r=Ir.get(t);if(r)return r;Ir.set(t,r=new Set);for(var n,s=e,i=Element.prototype;i!==s;){n=In(s);for(var l in n)n[l].set&&l!=="innerHTML"&&l!=="textContent"&&l!=="innerText"&&r.add(l);s=Ur(s)}return r}function ci(e){X===null&&zr(),Ms(()=>{const t=pr(e);if(typeof t=="function")return t})}function Cr(e){X===null&&zr(),ci(()=>()=>pr(e))}const di="5";typeof window<"u"&&((window.__svelte??={}).v??=new Set).add(di);class mr{static BASE="/api";overview(){return this.get("/overview")}runs(t={}){const r=new URLSearchParams;return t.flow&&r.set("flow",t.flow),t.status&&r.set("status",t.status),r.set("limit",String(t.limit??100)),this.get("/runs?"+r.toString())}run(t){return this.get("/runs/"+encodeURIComponent(t))}async get(t){const r=await fetch(mr.BASE+t,{headers:{accept:"application/json"}});if(!r.ok)throw new Error(r.status+" "+await r.text());return await r.json()}}const we={QUEUED:"queued",RUNNING:"running",RETRYING:"retrying",SUCCEEDED:"succeeded",FAILED:"failed"},vi={PENDING:"pending"},hi={TIMEOUT:"timeout"};class M{static SECOND=1e3;static MINUTE=6e4;static HOUR=36e5;static DAY=864e5;static duration(t){return t==null?"—":t<M.SECOND?t+" ms":t<M.MINUTE?(t/M.SECOND).toFixed(1)+" s":t<M.HOUR?Math.floor(t/M.MINUTE)+" min "+Math.round(t%M.MINUTE/M.SECOND)+" s":Math.floor(t/M.HOUR)+" h "+Math.round(t%M.HOUR/M.MINUTE)+" min"}static ago(t,r=Date.now()){if(!t)return"—";const n=r-Date.parse(t);return n<M.MINUTE?Math.max(0,Math.round(n/M.SECOND))+" s ago":n<M.HOUR?Math.round(n/M.MINUTE)+" min ago":n<M.DAY?Math.round(n/M.HOUR)+" h ago":new Date(t).toLocaleString()}static time(t){return t?new Date(t).toLocaleTimeString():"—"}static json(t){return JSON.stringify(t,null,2)??""}}class lt{static TONES={[we.SUCCEEDED]:"ok",[we.FAILED]:"fail",[we.RUNNING]:"run",[we.RETRYING]:"wait",[we.QUEUED]:"idle",[vi.PENDING]:"idle",[hi.TIMEOUT]:"wait"};static tone(t){return lt.TONES[t]??"idle"}static isActive(t){return t===we.RUNNING||t===we.RETRYING||t===we.QUEUED}}var _i=I("<span> </span>");function Ke(e,t){st(t,!0);const r=Xr(()=>lt.tone(t.status));var n=_i();let s;var i=T(n,!0);K(()=>{s=xt(n,1,`badge ${v(r)??""}`,"svelte-1hfd60x",s,{pulse:v(r)==="run"}),b(i,t.status)}),R(e,n),it()}var pi=I('<p class="error-box svelte-hcc72y"><strong> </strong> at <code> </code> </p>'),gi=I("<span> </span>"),mi=I('<li class="svelte-hcc72y"><button><span class="n svelte-hcc72y"> </span> <span class="name svelte-hcc72y"> </span> <span class="cmd svelte-hcc72y"> </span> <span class="meta svelte-hcc72y"><!> <span> </span> <!></span></button></li>'),wi=I('<tr><td class="svelte-hcc72y"> </td><td class="svelte-hcc72y"> </td><td class="svelte-hcc72y"><!></td><td class="err svelte-hcc72y"> </td></tr>'),yi=I('<tr><td colspan="4" class="muted svelte-hcc72y">waiting in the queue</td></tr>'),bi=I('<tr><td class="svelte-hcc72y"> </td><td class="svelte-hcc72y"> </td><td class="svelte-hcc72y"> </td><td class="svelte-hcc72y"> </td><td class="svelte-hcc72y"><!></td><td class="err svelte-hcc72y"> </td></tr>'),Ei=I('<tr><td colspan="6" class="muted svelte-hcc72y">not started</td></tr>'),Si=I('<details class="svelte-hcc72y"><summary>output (shortened)</summary> <pre class="svelte-hcc72y"> </pre></details>'),xi=I('<h3 class="svelte-hcc72y">Step <code> </code> — attempts</h3> <table class="svelte-hcc72y"><thead><tr><th class="svelte-hcc72y">flow</th><th class="svelte-hcc72y">#</th><th class="svelte-hcc72y">started</th><th class="svelte-hcc72y">took</th><th class="svelte-hcc72y">outcome</th><th class="svelte-hcc72y">error</th></tr></thead><tbody></tbody></table> <!>',1),Ti=I('<section class="head svelte-hcc72y"><div><h2 class="svelte-hcc72y"> <!></h2> <code class="muted svelte-hcc72y"> </code></div> <dl class="svelte-hcc72y"><div><dt class="svelte-hcc72y">created</dt><dd class="svelte-hcc72y"> </dd></div> <div><dt class="svelte-hcc72y">duration</dt><dd class="svelte-hcc72y"> </dd></div> <div><dt class="svelte-hcc72y">flow attempt</dt><dd class="svelte-hcc72y"> </dd></div></dl></section> <!> <h3 class="svelte-hcc72y">Steps</h3> <ol class="pipeline svelte-hcc72y"></ol> <h3 class="svelte-hcc72y">Flow attempts <span class="muted svelte-hcc72y">(pg-boss job; a retry runs the whole flow again)</span></h3> <table class="svelte-hcc72y"><thead><tr><th class="svelte-hcc72y">#</th><th class="svelte-hcc72y">started</th><th class="svelte-hcc72y">outcome</th><th class="svelte-hcc72y">error</th></tr></thead><tbody></tbody></table> <!> <details class="svelte-hcc72y"><summary>input</summary> <pre class="svelte-hcc72y"> </pre></details>',1);function ki(e,t){st(t,!0);let r=Q(null);const n=Xr(()=>t.run.steps.find(g=>g.key===(v(r)??t.run.currentStep??t.run.steps[0]?.key)));var s=Ti(),i=nr(s),l=x(i),a=x(l),o=x(a),u=m(o);Ke(u,{get status(){return t.run.status}});var f=m(a,2),c=T(f,!0),h=m(l,2),d=x(h),p=m(x(d)),k=T(p,!0),_=m(d,2),w=m(x(_)),O=T(w,!0),C=m(_,2),j=m(x(C)),Z=T(j),te=m(i,2);{var H=g=>{var y=pi(),U=x(y),se=T(U),Y=m(U,2),V=T(Y,!0),ie=m(Y);K(()=>{b(se,`${t.run.error.name??""}${t.run.error.code?" "+t.run.error.code:""}`),b(V,t.run.error.step),b(ie,`: ${t.run.error.message??""}`)}),R(g,y)};be(te,g=>{t.run.error&&g(H)})}var z=m(te,4);Ge(z,23,()=>t.run.steps,g=>g.key,(g,y,U)=>{var se=mi(),Y=x(se);let V;var ie=x(Y),ke=T(ie,!0),Ae=m(ie,2),le=T(Ae,!0),L=m(Ae,2),me=T(L,!0),Oe=m(L,2),$=x(Oe);Ke($,{get status(){return v(y).status}});var ot=m($,2),Gt=T(ot),Tt=m(ot,2);{var zt=Re=>{var kt=gi(),At=T(kt,!0);K(Vt=>b(At,Vt),[()=>M.duration(v(y).durationMs)]),R(Re,kt)};be(Tt,Re=>{v(y).durationMs!==void 0&&Re(zt)})}K(Re=>{V=xt(Y,1,`step ${Re??""}`,"svelte-hcc72y",V,{open:v(n)?.key===v(y).key}),b(ke,v(U)+1),b(le,v(y).key),b(me,v(y).command),b(Gt,`${v(y).attempts.length??""} ${v(y).attempts.length===1?"attempt":"attempts"}`)},[()=>lt.tone(v(y).status)]),Pt("click",Y,()=>G(r,v(y).key,!0)),R(g,se)});var D=m(z,4),N=m(x(D));Ge(N,21,()=>t.run.flowAttempts,g=>g.attempt,(g,y)=>{var U=wi(),se=x(U),Y=T(se,!0),V=m(se),ie=T(V,!0),ke=m(V),Ae=x(ke);{var le=$=>{Ke($,{get status(){return v(y).outcome}})},L=$=>{Ke($,{get status(){return we.RUNNING}})};be(Ae,$=>{v(y).outcome?$(le):$(L,-1)})}var me=m(ke),Oe=T(me,!0);K($=>{b(Y,v(y).attempt),b(ie,$),b(Oe,v(y).error?.message??"")},[()=>M.time(v(y).startedAt)]),R(g,U)},g=>{var y=yi();R(g,y)});var ge=m(D,2);{var at=g=>{var y=xi(),U=nr(y),se=m(x(U)),Y=T(se,!0),V=m(U,2),ie=m(x(V));Ge(ie,21,()=>v(n).attempts,Js,(le,L)=>{var me=bi(),Oe=x(me),$=T(Oe,!0),ot=m(Oe),Gt=T(ot,!0),Tt=m(ot),zt=T(Tt,!0),Re=m(Tt),kt=T(Re,!0),At=m(Re),Vt=x(At);Ke(Vt,{get status(){return v(L).outcome}});var kn=m(At),An=T(kn);K((Nn,Mn,On)=>{b($,v(L).flowAttempt),b(Gt,v(L).attempt),b(zt,Nn),b(kt,Mn),b(An,`${v(L).error?(v(L).error.code?v(L).error.code+": ":"")+v(L).error.message:""}${On??""}`)},[()=>M.time(v(L).startedAt),()=>M.duration(v(L).durationMs),()=>v(L).retryInMs?" (retry in "+M.duration(v(L).retryInMs)+")":""]),R(le,me)},le=>{var L=Ei();R(le,L)});var ke=m(V,2);{var Ae=le=>{var L=Si(),me=m(x(L),2),Oe=T(me,!0);K($=>b(Oe,$),[()=>M.json(v(n).output)]),R(le,L)};be(ke,le=>{v(n).output!==void 0&&le(Ae)})}K(()=>b(Y,v(n).key)),R(g,y)};be(ge,g=>{v(n)&&g(at)})}var qt=m(ge,2),Bt=m(x(qt),2),Yt=T(Bt,!0);K((g,y,U)=>{b(o,`${t.run.flow??""} `),b(c,t.run.runId),b(k,g),b(O,y),b(Z,`${t.run.flowAttempts.length??""}/${t.run.maxFlowAttempts??""}`),b(Yt,U)},[()=>M.ago(t.run.createdAt),()=>M.duration(t.run.durationMs),()=>M.json(t.run.input)]),R(e,s),it()}gr(["click"]);var Ai=I("<span></span>"),Ni=I('<span class="dots svelte-wkwx94"></span>');function Mi(e,t){st(t,!0);var r=Ni();Ge(r,21,()=>t.steps,n=>n.key,(n,s)=>{var i=Ai();K(l=>{xt(i,1,`dot ${l??""}`,"svelte-wkwx94"),Tn(i,"title",`${v(s).key??""}: ${v(s).status??""} (${v(s).attempts??""} attempts)`)},[()=>lt.tone(v(s).status)]),R(n,i)}),R(e,r),it()}var Oi=I('<code class="svelte-l5tdp5"> </code>'),Ri=I('<span class="error svelte-l5tdp5"> </span>'),Ii=I('<li class="svelte-l5tdp5"><button><span class="top svelte-l5tdp5"><strong> </strong> <!></span> <span class="mid svelte-l5tdp5"><!> <!></span> <span class="bottom svelte-l5tdp5"><span> </span> <span> </span> <span> </span></span> <!></button></li>'),Ci=I('<li class="empty svelte-l5tdp5">No runs yet — schedule one with <code>scrapme.flow(…)</code>.</li>'),Di=I('<ul class="runs svelte-l5tdp5"></ul>');function Li(e,t){st(t,!0);var r=Di();Ge(r,21,()=>t.runs,n=>n.runId,(n,s)=>{var i=Ii(),l=x(i);let a;var o=x(l),u=x(o),f=T(u,!0),c=m(u,2);Ke(c,{get status(){return v(s).status}});var h=m(o,2),d=x(h);Mi(d,{get steps(){return v(s).steps}});var p=m(d,2);{var k=D=>{var N=Oi(),ge=T(N,!0);K(()=>b(ge,v(s).currentStep)),R(D,N)};be(p,D=>{v(s).currentStep&&D(k)})}var _=m(h,2),w=x(_),O=T(w,!0),C=m(w,2),j=T(C),Z=m(C,2),te=T(Z,!0),H=m(_,2);{var z=D=>{var N=Ri(),ge=T(N,!0);K(()=>b(ge,v(s).error)),R(D,N)};be(H,D=>{v(s).error&&D(z)})}K((D,N)=>{a=xt(l,1,"svelte-l5tdp5",null,a,{selected:v(s).runId===t.selected}),b(f,v(s).flow),b(O,D),b(j,`attempt ${v(s).flowAttempt??""}/${v(s).maxFlowAttempts??""}`),b(te,N)},[()=>M.ago(v(s).createdAt),()=>M.duration(v(s).durationMs)]),Pt("click",l,()=>t.onselect(v(s).runId)),R(n,i)},n=>{var s=Ci();R(n,s)}),R(e,r),it()}gr(["click"]);var Ui=I('<button><strong class="svelte-d3ct2b"> </strong> </button>'),Pi=I('<nav class="counts svelte-d3ct2b"><!> <a target="_blank" rel="noreferrer" class="svelte-d3ct2b">CouchDB</a></nav>'),Fi=I('<p class="error svelte-d3ct2b"> </p>'),Hi=I("<option> </option>"),ji=I('<p class="muted svelte-d3ct2b">Select a run.</p>'),qi=I('<header class="svelte-d3ct2b"><h1 class="svelte-d3ct2b">scrapme <span class="svelte-d3ct2b">monitor</span></h1> <!></header> <!> <main class="svelte-d3ct2b"><aside class="svelte-d3ct2b"><div class="filters svelte-d3ct2b"><select class="svelte-d3ct2b"><option>all flows</option><!></select></div> <!></aside> <section class="detail svelte-d3ct2b"><!></section></main>',1);function Bi(e,t){st(t,!0);const r=2e3,n=new mr;let s=Q(null),i=Q(He([])),l=Q(null),a=Q(He(location.hash.slice(1)||null)),o=Q(""),u=Q(""),f=Q(null);async function c(){try{const[g,y]=await Promise.all([n.overview(),n.runs({flow:v(o),status:v(u)})]);G(s,g,!0),G(i,y,!0),G(a,v(a)??v(i)[0]?.runId??null,!0),G(l,v(a)?await n.run(v(a)):null,!0),G(f,null)}catch(g){G(f,g.message,!0)}}function h(g){G(a,g,!0),location.hash=g,c()}function d(){const g=location.hash.slice(1)||null;g!==v(a)&&(G(a,g,!0),c())}window.addEventListener("hashchange",d),Cr(()=>window.removeEventListener("hashchange",d)),c();const p=setInterval(()=>{c()},r);Cr(()=>clearInterval(p));var k=qi(),_=nr(k),w=m(x(_),2);{var O=g=>{var y=Pi(),U=x(y);Ge(U,16,()=>Object.values(we),Y=>Y,(Y,V)=>{var ie=Ui();let ke;var Ae=x(ie),le=T(Ae,!0),L=m(Ae);K(me=>{ke=xt(ie,1,`count ${me??""}`,"svelte-d3ct2b",ke,{active:v(u)===V}),b(le,v(s).counts[V]),b(L,` ${V??""}`)},[()=>lt.tone(V)]),Pt("click",ie,()=>{G(u,v(u)===V?"":V,!0),c()}),R(Y,ie)});var se=m(U,2);K(()=>Tn(se,"href",`${v(s).couchUrl??""}/_utils/#database/${v(s).runsDb??""}/_all_docs`)),R(g,y)};be(w,g=>{v(s)&&g(O)})}var C=m(_,2);{var j=g=>{var y=Fi(),U=T(y);K(()=>b(U,`Monitor API not reachable: ${v(f)??""}`)),R(g,y)};be(C,g=>{v(f)&&g(j)})}var Z=m(C,2),te=x(Z),H=x(te),z=x(H),D=x(z);D.value=D.__value="";var N=m(D);Ge(N,16,()=>v(s)?.flows??[],g=>g,(g,y)=>{var U=Hi(),se=T(U,!0),Y={};K(()=>{b(se,y),Y!==(Y=y)&&(U.value=(U.__value=Y)??"")}),R(g,U)}),si(z);var ge=m(H,2);Li(ge,{get runs(){return v(i)},get selected(){return v(a)},onselect:h});var at=m(te,2),qt=x(at);{var Bt=g=>{ki(g,{get run(){return v(l)}})},Yt=g=>{var y=ji();R(g,y)};be(qt,g=>{v(l)?g(Bt):g(Yt,-1)})}Pt("change",z,()=>{c()}),ii(z,()=>v(o),g=>G(o,g)),R(e,k),it()}gr(["click","change"]);Ks(Bi,{target:document.getElementById("app")});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>scrapme monitor</title>
|
|
7
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='8' cy='8' r='6' fill='%233b82f6'/></svg>" />
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-F0JnDwTs.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-D-otDb0Z.css">
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="app"></div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input of ScrapePageCommand. scrap-anything decides how long to wait (it always waits until the page —
|
|
3
|
+
* SPA or not — has rendered) and retries on its own, so there is nothing to tune per page.
|
|
4
|
+
*/
|
|
5
|
+
export interface ScrapePageInput {
|
|
6
|
+
url: string;
|
|
7
|
+
/** Extra request headers for the target (e.g. Accept-Language). */
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
/** 0–100, higher runs first on the server. */
|
|
10
|
+
priority?: number;
|
|
11
|
+
/** Accept HTTP 4xx answers of the target as a result (default: PermanentError HTTP_STATUS). */
|
|
12
|
+
allowHttpErrors?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Output of ScrapePageCommand. */
|
|
15
|
+
export interface ScrapedPage {
|
|
16
|
+
jobId: string;
|
|
17
|
+
url: string;
|
|
18
|
+
finalUrl: string;
|
|
19
|
+
httpStatus: number;
|
|
20
|
+
title: string | null;
|
|
21
|
+
contentType: string;
|
|
22
|
+
html: string;
|
|
23
|
+
durationMs: number;
|
|
24
|
+
fetchedAt: string;
|
|
25
|
+
}
|
|
26
|
+
/** Input of SaveDocumentCommand. */
|
|
27
|
+
export interface SaveDocumentInput {
|
|
28
|
+
/** Document id (same id = new revision of the same document). */
|
|
29
|
+
id: string;
|
|
30
|
+
document: Record<string, unknown>;
|
|
31
|
+
/** Default couch.db. */
|
|
32
|
+
db?: string;
|
|
33
|
+
}
|
|
34
|
+
/** Input of SendMailCommand. */
|
|
35
|
+
export interface SendMailInput {
|
|
36
|
+
/** Default MAIL_TO. */
|
|
37
|
+
to?: string | string[];
|
|
38
|
+
subject: string;
|
|
39
|
+
text: string;
|
|
40
|
+
html?: string;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.models.js","sourceRoot":"","sources":["../../../src/commands/commands.models.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Command, type CommandContext } from '../flow/flow.models.js';
|
|
2
|
+
import type { DocumentStore, SavedDocument } from '../storage/storage.models.js';
|
|
3
|
+
import type { SaveDocumentInput } from './commands.models.js';
|
|
4
|
+
/** Upserts a document into CouchDB (couch.db or input.db). Idempotent: a retry writes the same id again. */
|
|
5
|
+
export declare class SaveDocumentCommand implements Command<SaveDocumentInput, SavedDocument> {
|
|
6
|
+
private readonly store;
|
|
7
|
+
constructor(store: DocumentStore);
|
|
8
|
+
execute(input: SaveDocumentInput, ctx: CommandContext): Promise<SavedDocument>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { inject, injectable } from 'inversify';
|
|
11
|
+
import { TYPES } from '../di/types.js';
|
|
12
|
+
import { PermanentError } from '../flow/flow-errors.js';
|
|
13
|
+
import { ERROR_CODE } from '../flow/flow.models.js';
|
|
14
|
+
/** Upserts a document into CouchDB (couch.db or input.db). Idempotent: a retry writes the same id again. */
|
|
15
|
+
let SaveDocumentCommand = class SaveDocumentCommand {
|
|
16
|
+
store;
|
|
17
|
+
constructor(store) {
|
|
18
|
+
this.store = store;
|
|
19
|
+
}
|
|
20
|
+
async execute(input, ctx) {
|
|
21
|
+
if (!input?.id || !input.document)
|
|
22
|
+
throw new PermanentError('SaveDocumentCommand needs { id, document }', { code: ERROR_CODE.BAD_INPUT });
|
|
23
|
+
const saved = await this.store.save(input.id, input.document, input.db ? { db: input.db } : {});
|
|
24
|
+
ctx.logger.info(saved.created ? 'document created' : 'document updated', { db: saved.db, id: saved.id, rev: saved.rev, url: saved.url });
|
|
25
|
+
return saved;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
SaveDocumentCommand = __decorate([
|
|
29
|
+
injectable(),
|
|
30
|
+
__param(0, inject(TYPES.DocumentStore))
|
|
31
|
+
], SaveDocumentCommand);
|
|
32
|
+
export { SaveDocumentCommand };
|
|
33
|
+
//# sourceMappingURL=save-document.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-document.command.js","sourceRoot":"","sources":["../../../src/commands/save-document.command.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAqC,MAAM,wBAAwB,CAAC;AAIvF,4GAA4G;AAErG,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IACmC;IAAjE,YAAiE,KAAoB;QAApB,UAAK,GAAL,KAAK,CAAe;IAAG,CAAC;IAElF,KAAK,CAAC,OAAO,CAAC,KAAwB,EAAE,GAAmB;QAChE,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,MAAM,IAAI,cAAc,CAAC,4CAA4C,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1I,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAChG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACzI,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAA;AATY,mBAAmB;IAD/B,UAAU,EAAE;IAES,WAAA,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;GADpC,mBAAmB,CAS/B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ScrapAnythingClient } from 'scrap-anything-client';
|
|
2
|
+
import type { ScrapmeConfig } from '../config/config.models.js';
|
|
3
|
+
import { type Command, type CommandContext, type CommandOptions } from '../flow/flow.models.js';
|
|
4
|
+
import type { ScrapedPage, ScrapePageInput } from './commands.models.js';
|
|
5
|
+
/**
|
|
6
|
+
* Renders a page with scrap-anything: schedules a job (createJob), waits for it (collect — the API is
|
|
7
|
+
* asynchronous, a queue with its own retries behind it) and returns the HTML. One attempt = one server job.
|
|
8
|
+
* When the attempt is aborted (step timeout, cancelled run) the server job is cancelled too. Retries follow the
|
|
9
|
+
* client's `retryable` (TLS / invalid target / 4xx from the API = permanent).
|
|
10
|
+
*/
|
|
11
|
+
export declare class ScrapePageCommand implements Command<ScrapePageInput, ScrapedPage> {
|
|
12
|
+
private readonly client;
|
|
13
|
+
private static readonly FIRST_CLIENT_ERROR;
|
|
14
|
+
readonly options: CommandOptions;
|
|
15
|
+
constructor(client: ScrapAnythingClient | undefined, config: ScrapmeConfig);
|
|
16
|
+
execute(input: ScrapePageInput, ctx: CommandContext): Promise<ScrapedPage>;
|
|
17
|
+
isRetryable(error: unknown): boolean;
|
|
18
|
+
/** Wait for the job; an abort of the attempt cancels it on the server (the next poll then ends the wait). */
|
|
19
|
+
private collect;
|
|
20
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
var ScrapePageCommand_1;
|
|
11
|
+
import { inject, injectable, optional } from 'inversify';
|
|
12
|
+
import { RESULT_KIND, ScrapAnythingError } from 'scrap-anything-client';
|
|
13
|
+
import { TYPES } from '../di/types.js';
|
|
14
|
+
import { FlowErrors, NotConfiguredError, PermanentError } from '../flow/flow-errors.js';
|
|
15
|
+
import { ERROR_CODE } from '../flow/flow.models.js';
|
|
16
|
+
/**
|
|
17
|
+
* Renders a page with scrap-anything: schedules a job (createJob), waits for it (collect — the API is
|
|
18
|
+
* asynchronous, a queue with its own retries behind it) and returns the HTML. One attempt = one server job.
|
|
19
|
+
* When the attempt is aborted (step timeout, cancelled run) the server job is cancelled too. Retries follow the
|
|
20
|
+
* client's `retryable` (TLS / invalid target / 4xx from the API = permanent).
|
|
21
|
+
*/
|
|
22
|
+
let ScrapePageCommand = class ScrapePageCommand {
|
|
23
|
+
static { ScrapePageCommand_1 = this; }
|
|
24
|
+
client;
|
|
25
|
+
static FIRST_CLIENT_ERROR = 400;
|
|
26
|
+
options;
|
|
27
|
+
constructor(client, config) {
|
|
28
|
+
this.client = client;
|
|
29
|
+
// waiting for the server job is the slow part: the attempt must outlive scrapAnything.waitTimeoutMs
|
|
30
|
+
const s = config.scrapAnything;
|
|
31
|
+
this.options = s ? { timeoutMs: s.stepTimeoutMs, retries: s.stepRetries } : { retries: 0 };
|
|
32
|
+
}
|
|
33
|
+
async execute(input, ctx) {
|
|
34
|
+
if (!this.client)
|
|
35
|
+
throw new NotConfiguredError('scrapAnything', 'ScrapePageCommand');
|
|
36
|
+
if (!input?.url)
|
|
37
|
+
throw new PermanentError('ScrapePageCommand needs { url }', { code: ERROR_CODE.BAD_INPUT });
|
|
38
|
+
const client = this.client;
|
|
39
|
+
const created = await client.createJob({
|
|
40
|
+
url: input.url,
|
|
41
|
+
...(input.headers ? { headers: input.headers } : {}),
|
|
42
|
+
...(input.priority !== undefined ? { priority: input.priority } : {}),
|
|
43
|
+
});
|
|
44
|
+
ctx.logger.info('scrape job scheduled', { jobId: created.jobId, url: input.url, status: created.status });
|
|
45
|
+
const res = await this.collect(client, created.jobId, ctx);
|
|
46
|
+
ctx.logger.info('scrape job done', { jobId: res.jobId, httpStatus: res.result.httpStatus, attempts: res.job.attempts, ms: res.result.durationMs });
|
|
47
|
+
if (res.result.kind !== RESULT_KIND.HTML || res.html === undefined) {
|
|
48
|
+
throw new PermanentError(`${input.url} is not an HTML page (${res.result.contentType})`, { code: ERROR_CODE.NOT_HTML });
|
|
49
|
+
}
|
|
50
|
+
if (res.result.httpStatus >= ScrapePageCommand_1.FIRST_CLIENT_ERROR && !input.allowHttpErrors) {
|
|
51
|
+
throw new PermanentError(`${input.url} answered HTTP ${res.result.httpStatus}`, { code: ERROR_CODE.HTTP_STATUS });
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
jobId: res.jobId,
|
|
55
|
+
url: input.url,
|
|
56
|
+
finalUrl: res.result.finalUrl,
|
|
57
|
+
httpStatus: res.result.httpStatus,
|
|
58
|
+
title: res.result.title,
|
|
59
|
+
contentType: res.result.contentType,
|
|
60
|
+
html: res.html,
|
|
61
|
+
durationMs: res.result.durationMs,
|
|
62
|
+
fetchedAt: new Date().toISOString(),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
isRetryable(error) {
|
|
66
|
+
return error instanceof ScrapAnythingError ? error.retryable : FlowErrors.isRetryable(error);
|
|
67
|
+
}
|
|
68
|
+
/** Wait for the job; an abort of the attempt cancels it on the server (the next poll then ends the wait). */
|
|
69
|
+
async collect(client, jobId, ctx) {
|
|
70
|
+
const cancel = () => {
|
|
71
|
+
ctx.logger.warn('attempt aborted, cancelling the scrape job', { jobId });
|
|
72
|
+
client.cancelJob(jobId).catch((error) => ctx.logger.warn('could not cancel the scrape job', { jobId, error }));
|
|
73
|
+
};
|
|
74
|
+
if (ctx.signal.aborted)
|
|
75
|
+
cancel();
|
|
76
|
+
else
|
|
77
|
+
ctx.signal.addEventListener('abort', cancel, { once: true });
|
|
78
|
+
try {
|
|
79
|
+
return await client.collect(jobId);
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
ctx.signal.removeEventListener('abort', cancel);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
ScrapePageCommand = ScrapePageCommand_1 = __decorate([
|
|
87
|
+
injectable(),
|
|
88
|
+
__param(0, inject(TYPES.ScrapAnythingClient)),
|
|
89
|
+
__param(0, optional()),
|
|
90
|
+
__param(1, inject(TYPES.Config))
|
|
91
|
+
], ScrapePageCommand);
|
|
92
|
+
export { ScrapePageCommand };
|
|
93
|
+
//# sourceMappingURL=scrape-page.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrape-page.command.js","sourceRoot":"","sources":["../../../src/commands/scrape-page.command.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAA+C,MAAM,uBAAuB,CAAC;AAErH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,UAAU,EAA0D,MAAM,wBAAwB,CAAC;AAG5G;;;;;GAKG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;;IAKsC;IAJ1D,MAAM,CAAU,kBAAkB,GAAG,GAAG,CAAC;IACjC,OAAO,CAAiB;IAExC,YACkE,MAAuC,EACjF,MAAqB;QADqB,WAAM,GAAN,MAAM,CAAiC;QAGvG,oGAAoG;QACpG,MAAM,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAC7F,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,KAAsB,EAAE,GAAmB;QAC9D,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,kBAAkB,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;QACrF,IAAI,CAAC,KAAK,EAAE,GAAG;YAAE,MAAM,IAAI,cAAc,CAAC,iCAAiC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;QAC7G,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC;YACrC,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE,CAAC,CAAC;QACH,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1G,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC3D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAEnJ,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACnE,MAAM,IAAI,cAAc,CAAC,GAAG,KAAK,CAAC,GAAG,yBAAyB,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1H,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,mBAAiB,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAC5F,MAAM,IAAI,cAAc,CAAC,GAAG,KAAK,CAAC,GAAG,kBAAkB,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;QACpH,CAAC;QACD,OAAO;YACL,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ;YAC7B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU;YACjC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK;YACvB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW;YACnC,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU;YACjC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;IAEM,WAAW,CAAC,KAAc;QAC/B,OAAO,KAAK,YAAY,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/F,CAAC;IAED,6GAA6G;IACrG,KAAK,CAAC,OAAO,CAAC,MAA2B,EAAE,KAAa,EAAE,GAAmB;QACnF,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1H,CAAC,CAAC;QACF,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,EAAE,CAAC;;YAC5B,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;gBAAS,CAAC;YACT,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;;AA9DU,iBAAiB;IAD7B,UAAU,EAAE;IAMR,WAAA,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;IAAE,WAAA,QAAQ,EAAE,CAAA;IAC7C,WAAA,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;GANZ,iBAAiB,CA+D7B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ScrapmeConfig } from '../config/config.models.js';
|
|
2
|
+
import { type Command, type CommandContext } from '../flow/flow.models.js';
|
|
3
|
+
import type { Mailer, SentMail } from '../mail/mail.models.js';
|
|
4
|
+
import type { SendMailInput } from './commands.models.js';
|
|
5
|
+
/** Sends an e-mail (SMTP from Scrapme.create({ mail })). Recipients default to mail.to. Rejected addresses are not retried. */
|
|
6
|
+
export declare class SendMailCommand implements Command<SendMailInput, SentMail> {
|
|
7
|
+
private readonly mailer;
|
|
8
|
+
private readonly config;
|
|
9
|
+
constructor(mailer: Mailer, config: ScrapmeConfig);
|
|
10
|
+
execute(input: SendMailInput, ctx: CommandContext): Promise<SentMail>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { inject, injectable } from 'inversify';
|
|
11
|
+
import { TYPES } from '../di/types.js';
|
|
12
|
+
import { PermanentError } from '../flow/flow-errors.js';
|
|
13
|
+
import { ERROR_CODE } from '../flow/flow.models.js';
|
|
14
|
+
/** Sends an e-mail (SMTP from Scrapme.create({ mail })). Recipients default to mail.to. Rejected addresses are not retried. */
|
|
15
|
+
let SendMailCommand = class SendMailCommand {
|
|
16
|
+
mailer;
|
|
17
|
+
config;
|
|
18
|
+
constructor(mailer, config) {
|
|
19
|
+
this.mailer = mailer;
|
|
20
|
+
this.config = config;
|
|
21
|
+
}
|
|
22
|
+
async execute(input, ctx) {
|
|
23
|
+
if (!input?.subject || !input.text)
|
|
24
|
+
throw new PermanentError('SendMailCommand needs { subject, text }', { code: ERROR_CODE.BAD_INPUT });
|
|
25
|
+
const to = input.to === undefined ? [...(this.config.mail?.to ?? [])] : Array.isArray(input.to) ? input.to : [input.to];
|
|
26
|
+
if (to.length === 0)
|
|
27
|
+
throw new PermanentError('no recipients (input.to or mail.to in Scrapme.create)', { code: ERROR_CODE.BAD_INPUT });
|
|
28
|
+
const sent = await this.mailer.send({ to, subject: input.subject, text: input.text, ...(input.html ? { html: input.html } : {}) });
|
|
29
|
+
ctx.logger.info('mail sent', { to, subject: input.subject, messageId: sent.messageId });
|
|
30
|
+
return sent;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
SendMailCommand = __decorate([
|
|
34
|
+
injectable(),
|
|
35
|
+
__param(0, inject(TYPES.Mailer)),
|
|
36
|
+
__param(1, inject(TYPES.Config))
|
|
37
|
+
], SendMailCommand);
|
|
38
|
+
export { SendMailCommand };
|
|
39
|
+
//# sourceMappingURL=send-mail.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-mail.command.js","sourceRoot":"","sources":["../../../src/commands/send-mail.command.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAqC,MAAM,wBAAwB,CAAC;AAIvF,+HAA+H;AAExH,IAAM,eAAe,GAArB,MAAM,eAAe;IAEe;IACA;IAFzC,YACyC,MAAc,EACd,MAAqB;QADrB,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAe;IAC3D,CAAC;IAEG,KAAK,CAAC,OAAO,CAAC,KAAoB,EAAE,GAAmB;QAC5D,IAAI,CAAC,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI;YAAE,MAAM,IAAI,cAAc,CAAC,yCAAyC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;QACxI,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxH,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,uDAAuD,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;QACvI,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACxF,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAdY,eAAe;IAD3B,UAAU,EAAE;IAGR,WAAA,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACpB,WAAA,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;GAHZ,eAAe,CAc3B"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ScrapmeConfig, ServiceOptions } from './config.models.js';
|
|
2
|
+
/** The services given to Scrapme.create are invalid (thrown by Scrapme.create). */
|
|
3
|
+
export declare class ConfigError extends Error {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
6
|
+
/** Checks the services an app gives to Scrapme.create (zod), fills in defaults and freezes the result. */
|
|
7
|
+
export declare class ConfigBuilder {
|
|
8
|
+
/**
|
|
9
|
+
* CouchDB's own rule for database names (docs.couchdb.org, "PUT /{db}"). It is a rule about characters, so a
|
|
10
|
+
* regex is the clearest way to state it.
|
|
11
|
+
*/
|
|
12
|
+
private static readonly COUCH_DB_NAME;
|
|
13
|
+
private static readonly STEP_TIMEOUT_MARGIN_MS;
|
|
14
|
+
private static readonly SMTP_PORT;
|
|
15
|
+
private static readonly SMTPS_PORT;
|
|
16
|
+
/** pg-boss schema names go into SQL as identifiers. */
|
|
17
|
+
private static readonly SQL_IDENTIFIER;
|
|
18
|
+
private static readonly QUEUE_PREFIX;
|
|
19
|
+
private static readonly ms;
|
|
20
|
+
private static readonly dbName;
|
|
21
|
+
private static readonly schema;
|
|
22
|
+
static build(options: ServiceOptions): ScrapmeConfig;
|
|
23
|
+
private static deepFreeze;
|
|
24
|
+
}
|