strom-research 1.12.1 → 1.13.0-beta.1
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/README.md +29 -0
- package/assets/lang/cs.json +61 -2
- package/assets/lang/de.json +61 -2
- package/assets/plugins/connectors/DISCOVERY.md +5 -0
- package/assets/plugins/connectors/README.md +7 -2
- package/dist/cli/backups.js +79 -0
- package/dist/cli/context.js +90 -4
- package/dist/cli/execute.js +14 -6
- package/dist/cli/format.js +32 -0
- package/dist/cli/help.js +1 -1
- package/dist/cli/main.js +64 -8
- package/dist/cli/menu-links.js +1 -1
- package/dist/cli/menu.js +23 -4
- package/dist/cli/registry.js +2 -2
- package/dist/cli/ui.js +61 -2
- package/dist/cli/wizard.js +25 -9
- package/dist/commands/connectors.js +7 -4
- package/dist/commands/guide.js +2 -1
- package/dist/commands/links.js +19 -8
- package/dist/commands/session.js +1 -0
- package/dist/commands/setup.js +226 -49
- package/dist/commands/start.js +34 -13
- package/dist/commands/sync.js +6 -3
- package/dist/commands/trees.js +5 -0
- package/dist/core/actions.js +2 -1
- package/dist/core/appbrowser.js +32 -18
- package/dist/core/backup.js +244 -0
- package/dist/core/chromium.js +5 -4
- package/dist/core/config.js +1 -1
- package/dist/core/connector.js +63 -9
- package/dist/core/deps.js +3 -2
- package/dist/core/errors.js +5 -0
- package/dist/core/import.js +19 -2
- package/dist/core/links.js +64 -40
- package/dist/core/live.js +48 -5
- package/dist/core/material.js +66 -0
- package/dist/core/migrate.js +5 -1
- package/dist/core/paths.js +45 -2
- package/dist/core/people.js +37 -7
- package/dist/core/relocate.js +9 -3
- package/dist/core/self.js +81 -2
- package/dist/core/stromapp.js +118 -23
- package/dist/core/sync.js +8 -3
- package/dist/core/tree.js +27 -2
- package/dist/core/uninstall.js +160 -22
- package/dist/core/update.js +157 -36
- package/dist/gedcom/export.js +4 -1
- package/dist/gedcom/validate.js +2 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -152,6 +152,35 @@ npm run release # release/: strom-app.tar.gz, SHASUMS256.t
|
|
|
152
152
|
|
|
153
153
|
Zero runtime dependencies: TypeScript on Node's built-ins, and git.
|
|
154
154
|
|
|
155
|
+
## A second strom beside the first
|
|
156
|
+
|
|
157
|
+
For testers and developers: another version of strom, e.g. to try one, next to
|
|
158
|
+
the one you use — with its own command, program folder, settings and research
|
|
159
|
+
folder, so the two never share data.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
curl -fsSL https://raw.githubusercontent.com/ACiDekCZ/strom-research/main/install/install.sh | \
|
|
163
|
+
STROM_ISOLATED=1 STROM_INSTALL_DIR="$HOME/strom-try" STROM_CONFIG_DIR="$HOME/.config/strom-try" \
|
|
164
|
+
STROM_COMMAND=strom-try sh
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Windows (PowerShell):
|
|
168
|
+
`$env:STROM_ISOLATED='1'; $env:STROM_INSTALL_DIR="$env:LOCALAPPDATA\Programs\Strom-try"; $env:STROM_CONFIG_DIR="$env:APPDATA\strom-try"; $env:STROM_COMMAND='strom-try'; irm https://raw.githubusercontent.com/ACiDekCZ/strom-research/main/install/install.ps1 | iex`
|
|
169
|
+
|
|
170
|
+
- `STROM_ISOLATED=1` with `STROM_INSTALL_DIR` and `STROM_CONFIG_DIR`: the
|
|
171
|
+
program and its settings live in those folders only; it teaches no agent,
|
|
172
|
+
puts no shortcut on the desktop and leaves your `strom` alone.
|
|
173
|
+
- `STROM_COMMAND=strom-<letters and digits>` (optional): the command it starts
|
|
174
|
+
with, next to `strom` (macOS, Linux: `~/.local/bin`; Windows: a `bin` folder
|
|
175
|
+
of its own on your PATH). It never overwrites a command it did not write. Its
|
|
176
|
+
research folder is suggested as `Documents/Strom <name>` (`Strom try`), and
|
|
177
|
+
links from the Strom app can reach it as `strom-research-<name>://` (on your
|
|
178
|
+
yes, as with the first). Without a command it is started by its full path and
|
|
179
|
+
takes no links.
|
|
180
|
+
- To remove it: `strom-try uninstall` — its command, its links, its PATH entry
|
|
181
|
+
and its program folder go; its settings and research stay (delete them by
|
|
182
|
+
hand when not needed), and so does the first strom with everything of it.
|
|
183
|
+
|
|
155
184
|
## License
|
|
156
185
|
|
|
157
186
|
Copyright © 2026 Milan Víšek.
|
package/assets/lang/cs.json
CHANGED
|
@@ -62,6 +62,9 @@
|
|
|
62
62
|
"ui.dialog.refused": "Nepovoleno – nic se nezměnilo.",
|
|
63
63
|
"ui.link.isolated": "Tohle je izolovaná instalace (STROM_ISOLATED): odkazy strom-research:// nezapisuje – zůstávají běžné instalaci stromu.",
|
|
64
64
|
"ui.doc.isolated": "izolovaná instalace v {folder}",
|
|
65
|
+
"ui.doc.second": "druhá instalace: příkaz {command}, ve složce {folder}, její odkazy {scheme}://",
|
|
66
|
+
"ui.doc.home.regular": "je to i složka běžného stromu: dvě instalace nad jedním výzkumem",
|
|
67
|
+
"ui.doc.home.program": "ve složce programu strom – aktualizace nebo odinstalace by ji mohla vzít; lépe přesunout jinam (strom setup v terminálu ji přesune i s výzkumem)",
|
|
65
68
|
"ui.doc.knows.isolated": "izolovaná instalace: agenty mimo ni nic neučí",
|
|
66
69
|
"ui.doc.links.isolated": "izolovaná instalace: odkazy nezapisuje",
|
|
67
70
|
"ui.doc.app.isolated": "izolovaná instalace: úmyslně se nepoužívá",
|
|
@@ -74,6 +77,8 @@
|
|
|
74
77
|
"ui.consent.connector.revoke": "Zastavit stahovač „{name}“?",
|
|
75
78
|
"ui.consent.host": "Povolit automatické stahování z {host}?",
|
|
76
79
|
"ui.consent.host.revoke": "Zastavit automatické stahování z {host}?",
|
|
80
|
+
"ui.consent.elsewhere.connector": "Spustit stahovač „{name}“? Žádá o to agent mimo složku výzkumu ({cwd}).",
|
|
81
|
+
"ui.consent.elsewhere.run": "Spustit samostatnou práci agenta na výzkumu „{tree}“? Žádá o to agent mimo složku výzkumu ({cwd}); práce stojí peníze.",
|
|
77
82
|
"ui.consent.connectors.off": "Nechat stahovače běžet bez ptaní předem?",
|
|
78
83
|
"ui.menu.title": "Strom výzkum {version}",
|
|
79
84
|
"ui.menu.tree": "Rodokmen: {name} · osob: {persons}",
|
|
@@ -150,6 +155,7 @@
|
|
|
150
155
|
"ui.consent.connector.hosts": "Připojí se jen k {hosts} – pomalu, přes omezovač stromu.",
|
|
151
156
|
"ui.consent.connector.changed": "Jeho kód se od povolení změnil.",
|
|
152
157
|
"ui.consent.connector.direct": "Pozor: jeho kód se připojuje k síti sám, mimo omezovač stromu.",
|
|
158
|
+
"ui.consent.connector.unfenced": "Pozor: spouští program, který strom neohraničí ({run}) – může číst a měnit všechny soubory tohoto uživatele, spouštět jiné programy a připojit se kamkoli. Po každé změně jeho kódu se dotaz zopakuje.",
|
|
153
159
|
"ui.consent.connector.terms": "Podmínky užití archivu: {terms}",
|
|
154
160
|
"ui.consent.host.unblock": "{host} nás odmítl. Povolit znovu – jen pokud archiv řekl, že je to v pořádku?",
|
|
155
161
|
"ui.menu.otheragent": "Tentokrát mluvit s jiným agentem nebo jinde",
|
|
@@ -253,6 +259,8 @@
|
|
|
253
259
|
"ui.doc.app": "aplikace Strom",
|
|
254
260
|
"ui.doc.tree": "tento rodokmen",
|
|
255
261
|
"ui.doc.innode": "strom {version} v Node {node}",
|
|
262
|
+
"ui.doc.fence": "stahovače v ohrádce",
|
|
263
|
+
"ui.doc.fence.net": "Node {node}: stahovače běží v ohrádce, ale síť jim zavře až Node 25 nebo novější",
|
|
256
264
|
"ui.doc.oldnode": "Node {node} je příliš starý (potřeba 22.18 nebo novější)",
|
|
257
265
|
"ui.doc.missing": "chybí",
|
|
258
266
|
"ui.doc.notsetup": "zatím nenastaveno",
|
|
@@ -396,7 +404,9 @@
|
|
|
396
404
|
"ui.uninstall.npm": "Samotný program (nainstalovaný přes npm): npm uninstall -g strom-research",
|
|
397
405
|
"ui.uninstall.done": "strom je odinstalovaný. Děkujeme za bádání s ním.",
|
|
398
406
|
"ui.uninstall.running": "strom z této instalace ještě běží v jiném okně ({list}): zavřít ho – menu, rozhovor, práci agenta – a spustit strom uninstall znovu. Nic se neodebralo.",
|
|
399
|
-
"ui.uninstall.
|
|
407
|
+
"ui.uninstall.folderKept": "Složka {folder} zůstává: je v ní, co do ní strom nedal ({what}).",
|
|
408
|
+
"ui.uninstall.later": "zmizí několik sekund po skončení tohoto příkazu",
|
|
409
|
+
"ui.uninstall.skipped": "{path} je v install.json uveden jako spouštěč programu strom, ale spouštěč to není (jiné jméno, nebo leží ve výzkumu) – zůstává.",
|
|
400
410
|
"ui.menu.update.line": "Vyšla nová verze stromu: {version}.",
|
|
401
411
|
"ui.menu.update": "Aktualizovat strom na {version}",
|
|
402
412
|
"ui.doc.update": "nová verze",
|
|
@@ -404,7 +414,7 @@
|
|
|
404
414
|
"ui.update.unknown": "Nepodařilo se zjistit nejnovější verzi stromu.",
|
|
405
415
|
"ui.update.current": "strom {version} je nejnovější verze.",
|
|
406
416
|
"ui.update.available": "Vyšla nová verze: {version} (tato je {current}) – nainstaluje ji strom update.",
|
|
407
|
-
"ui.update.npm": "Vyšla nová verze: {version}. strom je tu nainstalovaný přes npm: npm install -g strom-research@
|
|
417
|
+
"ui.update.npm": "Vyšla nová verze: {version}. strom je tu nainstalovaný přes npm: npm install -g strom-research@{tag}",
|
|
408
418
|
"ui.update.sure": "Aktualizovat strom z {current} na {version}? Výzkumy zůstanou, jak jsou.",
|
|
409
419
|
"ui.update.later": "Teď ne – kdykoli strom update.",
|
|
410
420
|
"ui.update.downloading": "Stahuji strom {version}…",
|
|
@@ -432,6 +442,19 @@
|
|
|
432
442
|
"ui.update.node.sure": "Aktualizovat Node stromu z {from} na {to} (bezpečnostní opravy)?",
|
|
433
443
|
"ui.update.node.done": "✓ Node je aktualizovaný: {from} → {to}.",
|
|
434
444
|
"ui.update.bridges": "Živé sledování v aplikaci Strom pokračuje s novou verzí ({n}).",
|
|
445
|
+
"ui.update.npm.channel": "strom je tu nainstalovaný přes npm: npm install -g strom-research@{tag}",
|
|
446
|
+
"ui.update.channel.beta.sure": "Přepnout strom na beta verze: {current} → {version}?",
|
|
447
|
+
"ui.update.channel.stable.sure": "Vrátit strom k vydaným verzím: {current} → {version}?",
|
|
448
|
+
"ui.update.channel.beta.now": "Od teď strom bere beta verze.",
|
|
449
|
+
"ui.update.channel.stable.now": "Od teď strom bere vydané verze.",
|
|
450
|
+
"ui.update.older": "{version} je starší verze než {current}; výzkumy zůstanou, jak jsou.",
|
|
451
|
+
"ui.update.stays": "Výzkumy zůstanou, jak jsou.",
|
|
452
|
+
"ui.doc.beta": "beta verze",
|
|
453
|
+
"ui.doc.backup": "záloha",
|
|
454
|
+
"ui.backup.made": "Záloha před přechodem z {from} na {to}: {path} ({size}).",
|
|
455
|
+
"ui.backup.last": "Poslední záloha (před přechodem z {from} na {to}, {date}): {path}",
|
|
456
|
+
"ui.backup.readme": "Strom výzkum – záloha\n\nVytvořena {date}, před přechodem ze stromu {from} na {to}.\n\nUvnitř:\n- trees: všechny rodokmeny tohoto počítače, každý celou svou složkou i s historií (.git);\n- settings: nastavení stromu s klíči pečetí a přihlášeními, jak byly na tomto počítači.\n\nNení uvnitř: sdílené obrázky (složka shared/media). Každý je tam uložen podle svého obsahu a strom žádný nemaže; každá verze stromu čte tytéž. Vynecháno je i to, co strom vytvoří znovu sám (náhledy skenů, výřezy).\n\nVrácení rodokmenu: zkopírovat jeho složku z trees zpět tam, kde rodokmeny jsou (místo té, která tam je, nebo vedle ní pod jiným jménem), a spustit strom: strom ho zkontroluje (strom check).",
|
|
457
|
+
"ui.trees.locked": "zamčeno: zapsal strom {by}",
|
|
435
458
|
"ui.setup.stromapp": "Aplikace Strom (zdarma, v prohlížeči) ukáže výzkum jako rodokmen – u každého zápisu jeho obrázek vyříznutý ze skenu, příběhy předků – a když agent pracuje, sleduje výzkum živě. Používat ji?",
|
|
436
459
|
"ui.setup.stromapp.install": "Ano – nainstalovat ji teď (otevře se v prohlížeči, strom řekne, kam kliknout)",
|
|
437
460
|
"ui.setup.stromapp.later": "Ano, ale teď ne",
|
|
@@ -1304,6 +1327,7 @@
|
|
|
1304
1327
|
"ui.home.stays": "Výzkum zůstává ve složce {from}.",
|
|
1305
1328
|
"ui.home.inside": "{to} je uvnitř složky výzkumu {from} (nebo naopak) – vybrat složku mimo ni.",
|
|
1306
1329
|
"ui.home.notEmpty": "Ve složce {to} už něco je – výzkum se přesune jen do prázdné nebo nové složky.",
|
|
1330
|
+
"ui.home.program": "{to} leží ve složce programu strom – aktualizace nahrazuje, co tam je; je potřeba složka mimo ni.",
|
|
1307
1331
|
"ui.home.busy": "V rodokmenu {trees} teď někdo pracuje (agent, samostatná práce nebo živé sledování v aplikaci Strom) – výzkum půjde přesunout, až skončí.",
|
|
1308
1332
|
"ui.home.failed": "Přesunout se nepodařilo ({reason}) – nic se nezměnilo.",
|
|
1309
1333
|
"ui.app.notinstalled": "Aplikace Strom na tomto počítači ještě není nainstalovaná. Nainstalovat ji teď jako aplikaci z prohlížeče (zdarma; strom ukáže, kam kliknout)?",
|
|
@@ -1467,6 +1491,23 @@
|
|
|
1467
1491
|
"ui.error.arg.missing": "chybí <{arg}>",
|
|
1468
1492
|
"ui.error.arg.missing.hint": "strom help {cmd}",
|
|
1469
1493
|
"ui.error.prefix": "chyba",
|
|
1494
|
+
"ui.error.backup.failed": "Zálohu před přechodem z {from} na {to} se nepodařilo vytvořit: {detail}. Nic se nepřepíná: tento strom neotevře žádný rodokmen k zápisu, dokud záloha nebude hotová.",
|
|
1495
|
+
"ui.error.backup.failed.hint": "Uvolnit místo na disku ({where}) a spustit strom znovu – nebo se vrátit: strom update --channel {back}",
|
|
1496
|
+
"ui.error.backup.failed.update": "Zálohu před přechodem z {from} na {to} se nepodařilo vytvořit: {detail}. Nic se nenainstalovalo.",
|
|
1497
|
+
"ui.error.backup.failed.update.hint": "Uvolnit místo na disku ({where}) a znovu strom update --channel {channel}",
|
|
1498
|
+
"ui.error.folder.in-program": "{folder} leží ve složce programu strom {program} – aktualizace ji nahrazuje a odinstalace odstraňuje, výzkum by šel s ní. Nic se nezměnilo.",
|
|
1499
|
+
"ui.error.folder.in-program.hint": "Zvolit složku mimo ni, například {suggested}",
|
|
1500
|
+
"ui.error.folder.in-program.default.hint": "Zadat složku mimo ni: strom setup --home \"{suggested}\" --yes",
|
|
1501
|
+
"ui.error.update.in-program": "{folder} leží uvnitř {entry}, kterou aktualizace nahrazuje – výzkum by šel s ní. Nic se nenainstalovalo.",
|
|
1502
|
+
"ui.error.update.in-program.hint": "Nejdřív přesunout výzkum ze složky programu strom: strom setup ve vlastním terminálu (otázka na složku ho přesune i s výzkumem), pak znovu strom update",
|
|
1503
|
+
"ui.error.tree.newer": "Tento rodokmen zapsal strom {by}, novější než tento strom {version}. Tento strom ho nechává beze změny.",
|
|
1504
|
+
"ui.error.tree.newer.hint": "Aktualizovat strom: strom update",
|
|
1505
|
+
"ui.error.tree.newer.backup": "Tento rodokmen zapsal strom {by}, novější než tento strom {version}. Tento strom ho nechává beze změny.",
|
|
1506
|
+
"ui.error.tree.newer.backup.hint": "Aktualizovat strom: strom update\nZáloha z doby před přechodem: {backup}",
|
|
1507
|
+
"ui.error.tree.newer.beta": "Tento rodokmen zapsal strom {by}, novější než tento strom {version}. Tento strom ho nechává beze změny.",
|
|
1508
|
+
"ui.error.tree.newer.beta.hint": "Vrátit se k betě: strom update --channel beta – nebo počkat na vydání {release}",
|
|
1509
|
+
"ui.error.tree.newer.beta.backup": "Tento rodokmen zapsal strom {by}, novější než tento strom {version}. Tento strom ho nechává beze změny.",
|
|
1510
|
+
"ui.error.tree.newer.beta.backup.hint": "Vrátit se k betě: strom update --channel beta – nebo počkat na vydání {release}\nZáloha z doby před přechodem: {backup}",
|
|
1470
1511
|
"log.input.app": "Úpravy poslané z aplikace Strom",
|
|
1471
1512
|
"log.input.app.undo": "Úpravy z aplikace Strom vráceny",
|
|
1472
1513
|
"ui.init.created": "Rodokmen „{name}“ založen v {path}",
|
|
@@ -1474,6 +1515,22 @@
|
|
|
1474
1515
|
"ui.init.lang.detected": "jazyk výzkumu: {lang} ({code}) – podle systému; jiný: strom lang <kód>",
|
|
1475
1516
|
"ui.init.archive": "archiv: data přicházejí z aplikace Strom (výzkum se zapíná přes strom mode research)",
|
|
1476
1517
|
"ui.init.next": "dál {command}",
|
|
1518
|
+
"ui.setup.summary": "Strom je nastavený.",
|
|
1519
|
+
"ui.setup.summary.home": "domov",
|
|
1520
|
+
"ui.setup.summary.trees": "rodokmeny",
|
|
1521
|
+
"ui.setup.summary.shared": "sdílená data",
|
|
1522
|
+
"ui.setup.summary.lang": "jazyk",
|
|
1523
|
+
"ui.setup.summary.detected": " – podle systému; jiný jazyk: strom config set lang <kód>",
|
|
1524
|
+
"ui.setup.summary.agent": "agent",
|
|
1525
|
+
"ui.setup.summary.missing": " – zatím není nainstalovaný",
|
|
1526
|
+
"ui.setup.summary.talk": "rozhovor",
|
|
1527
|
+
"ui.setup.summary.app": "v aplikaci {app}",
|
|
1528
|
+
"ui.setup.summary.terminal": "v terminálu (jeho CLI)",
|
|
1529
|
+
"ui.setup.summary.both": " – obojí je tu; rozhoduje uživatel: strom setup --where {where}",
|
|
1530
|
+
"ui.setup.summary.knows": "zná strom",
|
|
1531
|
+
"ui.setup.summary.anywhere": "{agent}, v každé složce",
|
|
1532
|
+
"ui.setup.summary.config": "nastavení",
|
|
1533
|
+
"ui.arg.family-tree-name": "název, např. příjmení rodu",
|
|
1477
1534
|
"ui.arg.agent": "agent",
|
|
1478
1535
|
"ui.arg.batch": "dávka",
|
|
1479
1536
|
"ui.arg.book": "kniha",
|
|
@@ -1536,6 +1593,8 @@
|
|
|
1536
1593
|
"ui.error.option.is-arg.hint": "{cmd} <{arg}>",
|
|
1537
1594
|
"ui.error.option.unknown": "neznámá volba {opt} u {cmd}",
|
|
1538
1595
|
"ui.error.option.unknown.hint": "volby: {options} · strom help {path}",
|
|
1596
|
+
"ui.error.option.unknown.none": "neznámá volba {opt} u {cmd}",
|
|
1597
|
+
"ui.error.option.unknown.none.hint": "{help}",
|
|
1539
1598
|
"ui.error.option.no-value": "{opt} se píše bez hodnoty",
|
|
1540
1599
|
"ui.error.option.needs-value": "{opt} potřebuje hodnotu {value}",
|
|
1541
1600
|
"ui.error.option.needs-value.hint": "strom help {path}",
|
package/assets/lang/de.json
CHANGED
|
@@ -62,6 +62,9 @@
|
|
|
62
62
|
"ui.dialog.refused": "Nicht erlaubt – nichts wurde geändert.",
|
|
63
63
|
"ui.link.isolated": "Dies ist eine isolierte Installation (STROM_ISOLATED): sie registriert keine strom-research://-Links – diese bleiben beim eigenen strom.",
|
|
64
64
|
"ui.doc.isolated": "isolierte Installation in {folder}",
|
|
65
|
+
"ui.doc.second": "zweite Installation: der Befehl {command}, in {folder}, ihre Links {scheme}://",
|
|
66
|
+
"ui.doc.home.regular": "auch der Ordner des regulären strom: zwei Installationen an einer Forschung",
|
|
67
|
+
"ui.doc.home.program": "im Programmordner von strom – ein Update oder die Deinstallation könnte sie mitnehmen; besser woandershin (strom setup im Terminal verschiebt sie mit)",
|
|
65
68
|
"ui.doc.knows.isolated": "isolierte Installation: den Agenten wird außerhalb nichts beigebracht",
|
|
66
69
|
"ui.doc.links.isolated": "isolierte Installation: registriert keine Links",
|
|
67
70
|
"ui.doc.app.isolated": "isolierte Installation: absichtlich nicht verwendet",
|
|
@@ -74,6 +77,8 @@
|
|
|
74
77
|
"ui.consent.connector.revoke": "Den Downloader „{name}“ stoppen?",
|
|
75
78
|
"ui.consent.host": "Automatisches Herunterladen von {host} erlauben?",
|
|
76
79
|
"ui.consent.host.revoke": "Automatisches Herunterladen von {host} stoppen?",
|
|
80
|
+
"ui.consent.elsewhere.connector": "Den Downloader „{name}“ starten? Ein Agent fragt danach von außerhalb des Forschungsordners ({cwd}).",
|
|
81
|
+
"ui.consent.elsewhere.run": "Den Agenten allein an der Forschung „{tree}“ arbeiten lassen? Ein Agent fragt danach von außerhalb des Forschungsordners ({cwd}); die Arbeit kostet Geld.",
|
|
77
82
|
"ui.consent.connectors.off": "Downloader laufen lassen, ohne vorher zu fragen?",
|
|
78
83
|
"ui.menu.title": "Strom Ahnenforschung {version}",
|
|
79
84
|
"ui.menu.tree": "Stammbaum: {name} · Personen: {persons}",
|
|
@@ -150,6 +155,7 @@
|
|
|
150
155
|
"ui.consent.connector.hosts": "Er verbindet sich nur mit {hosts} – langsam, über den Begrenzer von strom.",
|
|
151
156
|
"ui.consent.connector.changed": "Sein Code hat sich seit der Erlaubnis geändert.",
|
|
152
157
|
"ui.consent.connector.direct": "Achtung: sein Code greift selbst auf das Netz zu, am Begrenzer von strom vorbei.",
|
|
158
|
+
"ui.consent.connector.unfenced": "Achtung: er startet ein Programm, das strom nicht eingrenzt ({run}) – es kann alle Dateien dieses Benutzers lesen und ändern, andere Programme starten und jede Adresse erreichen. Nach jeder Änderung seines Codes wird erneut gefragt.",
|
|
153
159
|
"ui.consent.connector.terms": "Nutzungsbedingungen des Archivs: {terms}",
|
|
154
160
|
"ui.consent.host.unblock": "{host} hat uns abgewiesen. Wieder erlauben – nur wenn das Archiv gesagt hat, dass es in Ordnung ist?",
|
|
155
161
|
"ui.menu.otheragent": "Diesmal mit einem anderen Agenten oder woanders sprechen",
|
|
@@ -253,6 +259,8 @@
|
|
|
253
259
|
"ui.doc.app": "Strom-App",
|
|
254
260
|
"ui.doc.tree": "dieser Stammbaum",
|
|
255
261
|
"ui.doc.innode": "strom {version} in Node {node}",
|
|
262
|
+
"ui.doc.fence": "Downloader eingegrenzt",
|
|
263
|
+
"ui.doc.fence.net": "Node {node}: Downloader laufen eingegrenzt, aber erst Node 25 oder neuer hält sie auch vom Netz fern",
|
|
256
264
|
"ui.doc.oldnode": "Node {node} ist zu alt (nötig: 22.18 oder neuer)",
|
|
257
265
|
"ui.doc.missing": "fehlt",
|
|
258
266
|
"ui.doc.notsetup": "noch nicht eingerichtet",
|
|
@@ -396,7 +404,9 @@
|
|
|
396
404
|
"ui.uninstall.npm": "Das Programm selbst (mit npm installiert): npm uninstall -g strom-research",
|
|
397
405
|
"ui.uninstall.done": "strom ist deinstalliert. Danke fürs Forschen mit strom.",
|
|
398
406
|
"ui.uninstall.running": "strom läuft aus dieser Installation noch in einem anderen Fenster ({list}): es schließen – das Menü, ein Gespräch, eine Arbeit des Agenten – und strom uninstall erneut starten. Nichts wurde entfernt.",
|
|
399
|
-
"ui.uninstall.
|
|
407
|
+
"ui.uninstall.folderKept": "Der Ordner {folder} bleibt: darin liegt, was strom nicht hineingelegt hat ({what}).",
|
|
408
|
+
"ui.uninstall.later": "verschwindet wenige Sekunden nach dem Ende dieses Befehls",
|
|
409
|
+
"ui.uninstall.skipped": "{path} steht in install.json als Starter von strom, ist aber keiner (ein anderer Name, oder es liegt in der Forschung) – es bleibt.",
|
|
400
410
|
"ui.menu.update.line": "Eine neue Version von strom ist da: {version}.",
|
|
401
411
|
"ui.menu.update": "strom auf {version} aktualisieren",
|
|
402
412
|
"ui.doc.update": "neue Version",
|
|
@@ -404,7 +414,7 @@
|
|
|
404
414
|
"ui.update.unknown": "Die neueste Version von strom ließ sich nicht ermitteln.",
|
|
405
415
|
"ui.update.current": "strom {version} ist die neueste Version.",
|
|
406
416
|
"ui.update.available": "Eine neue Version ist da: {version} (diese ist {current}) – strom update installiert sie.",
|
|
407
|
-
"ui.update.npm": "Eine neue Version ist da: {version}. strom ist hier mit npm installiert: npm install -g strom-research@
|
|
417
|
+
"ui.update.npm": "Eine neue Version ist da: {version}. strom ist hier mit npm installiert: npm install -g strom-research@{tag}",
|
|
408
418
|
"ui.update.sure": "strom von {current} auf {version} aktualisieren? Die Forschungen bleiben, wie sie sind.",
|
|
409
419
|
"ui.update.later": "Nicht jetzt – jederzeit strom update.",
|
|
410
420
|
"ui.update.downloading": "strom {version} wird heruntergeladen…",
|
|
@@ -432,6 +442,19 @@
|
|
|
432
442
|
"ui.update.node.sure": "strom's Node von {from} auf {to} aktualisieren (Sicherheitskorrekturen)?",
|
|
433
443
|
"ui.update.node.done": "✓ Node ist aktualisiert: {from} → {to}.",
|
|
434
444
|
"ui.update.bridges": "Die Live-Ansicht in der Strom-App läuft mit der neuen Version weiter ({n}).",
|
|
445
|
+
"ui.update.npm.channel": "strom ist hier mit npm installiert: npm install -g strom-research@{tag}",
|
|
446
|
+
"ui.update.channel.beta.sure": "strom auf die Beta-Versionen umstellen: {current} → {version}?",
|
|
447
|
+
"ui.update.channel.stable.sure": "strom zu den veröffentlichten Versionen zurückstellen: {current} → {version}?",
|
|
448
|
+
"ui.update.channel.beta.now": "Ab jetzt nimmt strom die Beta-Versionen.",
|
|
449
|
+
"ui.update.channel.stable.now": "Ab jetzt nimmt strom die veröffentlichten Versionen.",
|
|
450
|
+
"ui.update.older": "{version} ist eine ältere Version als {current}; die Forschungen bleiben, wie sie sind.",
|
|
451
|
+
"ui.update.stays": "Die Forschungen bleiben, wie sie sind.",
|
|
452
|
+
"ui.doc.beta": "Beta-Versionen",
|
|
453
|
+
"ui.doc.backup": "Sicherung",
|
|
454
|
+
"ui.backup.made": "Sicherung vor dem Wechsel von {from} auf {to}: {path} ({size}).",
|
|
455
|
+
"ui.backup.last": "Letzte Sicherung (vor dem Wechsel von {from} auf {to}, {date}): {path}",
|
|
456
|
+
"ui.backup.readme": "Strom-Forschung – eine Sicherung\n\nErstellt {date}, vor dem Wechsel von strom {from} auf {to}.\n\nDarin:\n- trees: alle Stammbäume dieses Computers, jeder mit seinem ganzen Ordner samt Verlauf (.git);\n- settings: die Einstellungen von strom mit den Siegelschlüsseln und den Anmeldungen, wie sie auf diesem Computer waren.\n\nNicht darin: die gemeinsamen Bilder (der Ordner shared/media). Jedes liegt dort nach seinem Inhalt, und strom löscht keines; jede Version von strom liest dieselben. Ebenfalls weggelassen: was strom selbst wieder erstellt (Ansichten von Scans, Ausschnitte).\n\nEinen Stammbaum zurückholen: seinen Ordner aus trees dorthin zurückkopieren, wo die Stammbäume liegen (anstelle des vorhandenen oder daneben unter anderem Namen), dann strom starten: strom prüft ihn (strom check).",
|
|
457
|
+
"ui.trees.locked": "gesperrt: geschrieben von strom {by}",
|
|
435
458
|
"ui.setup.stromapp": "Die Strom-App (kostenlos, im Browser) zeigt die Forschung als Stammbaum – jeden Eintrag mit seinem Bild aus dem Scan, die Geschichten der Vorfahren – und verfolgt sie live, während der Agent arbeitet. Soll sie verwendet werden?",
|
|
436
459
|
"ui.setup.stromapp.install": "Ja – jetzt installieren (sie öffnet sich im Browser, strom zeigt, wo zu klicken ist)",
|
|
437
460
|
"ui.setup.stromapp.later": "Ja, aber nicht jetzt",
|
|
@@ -1304,6 +1327,7 @@
|
|
|
1304
1327
|
"ui.home.stays": "Die Forschung bleibt in {from}.",
|
|
1305
1328
|
"ui.home.inside": "{to} liegt im Ordner der Forschung {from} (oder umgekehrt) – einen Ordner daneben wählen.",
|
|
1306
1329
|
"ui.home.notEmpty": "In {to} liegt schon etwas – die Forschung zieht nur in einen leeren oder neuen Ordner.",
|
|
1330
|
+
"ui.home.program": "{to} liegt im Programmordner von strom – ein Update ersetzt, was dort liegt; ein Ordner außerhalb ist nötig.",
|
|
1307
1331
|
"ui.home.busy": "Im Stammbaum {trees} arbeitet gerade jemand (ein Agent, ein Lauf oder die Strom-App live) – die Forschung kann umziehen, wenn das fertig ist.",
|
|
1308
1332
|
"ui.home.failed": "Das Verschieben ging nicht ({reason}) – nichts wurde geändert.",
|
|
1309
1333
|
"ui.app.notinstalled": "Die Strom-App ist auf diesem Computer noch nicht installiert. Jetzt als App aus dem Browser installieren (kostenlos; strom zeigt, wo zu klicken ist)?",
|
|
@@ -1467,6 +1491,23 @@
|
|
|
1467
1491
|
"ui.error.arg.missing": "<{arg}> fehlt",
|
|
1468
1492
|
"ui.error.arg.missing.hint": "strom help {cmd}",
|
|
1469
1493
|
"ui.error.prefix": "Fehler",
|
|
1494
|
+
"ui.error.backup.failed": "Die Sicherung vor dem Wechsel von {from} auf {to} ließ sich nicht erstellen: {detail}. Es wird nichts umgestellt: dieses strom öffnet keinen Stammbaum zum Schreiben, bis die Sicherung erstellt ist.",
|
|
1495
|
+
"ui.error.backup.failed.hint": "Platz auf dem Datenträger freimachen ({where}) und strom erneut starten – oder zurück: strom update --channel {back}",
|
|
1496
|
+
"ui.error.backup.failed.update": "Die Sicherung vor dem Wechsel von {from} auf {to} ließ sich nicht erstellen: {detail}. Es wurde nichts installiert.",
|
|
1497
|
+
"ui.error.backup.failed.update.hint": "Platz auf dem Datenträger freimachen ({where}), dann erneut strom update --channel {channel}",
|
|
1498
|
+
"ui.error.folder.in-program": "{folder} liegt im Programmordner von strom {program} – ein Update von strom ersetzt, was dort liegt, und die Deinstallation entfernt es, die Forschung mit. Nichts wurde geändert.",
|
|
1499
|
+
"ui.error.folder.in-program.hint": "Einen Ordner außerhalb wählen, zum Beispiel {suggested}",
|
|
1500
|
+
"ui.error.folder.in-program.default.hint": "Einen Ordner außerhalb angeben: strom setup --home \"{suggested}\" --yes",
|
|
1501
|
+
"ui.error.update.in-program": "{folder} liegt in {entry}, das das Update ersetzt – die Forschung ginge mit. Nichts wurde installiert.",
|
|
1502
|
+
"ui.error.update.in-program.hint": "Zuerst die Forschung aus dem Programmordner von strom verschieben: strom setup in einem eigenen Terminal (die Frage nach dem Ordner verschiebt sie mit), dann erneut strom update",
|
|
1503
|
+
"ui.error.tree.newer": "Diesen Stammbaum hat strom {by} geschrieben, neuer als dieses strom {version}. Dieses strom lässt ihn unverändert.",
|
|
1504
|
+
"ui.error.tree.newer.hint": "strom aktualisieren: strom update",
|
|
1505
|
+
"ui.error.tree.newer.backup": "Diesen Stammbaum hat strom {by} geschrieben, neuer als dieses strom {version}. Dieses strom lässt ihn unverändert.",
|
|
1506
|
+
"ui.error.tree.newer.backup.hint": "strom aktualisieren: strom update\nDie Sicherung vor dem Wechsel: {backup}",
|
|
1507
|
+
"ui.error.tree.newer.beta": "Diesen Stammbaum hat strom {by} geschrieben, neuer als dieses strom {version}. Dieses strom lässt ihn unverändert.",
|
|
1508
|
+
"ui.error.tree.newer.beta.hint": "Zurück zur Beta: strom update --channel beta – oder auf die Veröffentlichung von {release} warten",
|
|
1509
|
+
"ui.error.tree.newer.beta.backup": "Diesen Stammbaum hat strom {by} geschrieben, neuer als dieses strom {version}. Dieses strom lässt ihn unverändert.",
|
|
1510
|
+
"ui.error.tree.newer.beta.backup.hint": "Zurück zur Beta: strom update --channel beta – oder auf die Veröffentlichung von {release} warten\nDie Sicherung vor dem Wechsel: {backup}",
|
|
1470
1511
|
"log.input.app": "Aus der Strom-App gesendete Änderungen",
|
|
1471
1512
|
"log.input.app.undo": "Änderungen aus der Strom-App zurückgenommen",
|
|
1472
1513
|
"ui.init.created": "Stammbaum „{name}“ angelegt in {path}",
|
|
@@ -1474,6 +1515,22 @@
|
|
|
1474
1515
|
"ui.init.lang.detected": "Sprache der Forschung: {lang} ({code}) – vom System übernommen; eine andere: strom lang <Code>",
|
|
1475
1516
|
"ui.init.archive": "ein Archiv: die Daten kommen aus der Strom-App (die Forschung wird mit strom mode research eingeschaltet)",
|
|
1476
1517
|
"ui.init.next": "weiter {command}",
|
|
1518
|
+
"ui.setup.summary": "Strom ist eingerichtet.",
|
|
1519
|
+
"ui.setup.summary.home": "Zuhause",
|
|
1520
|
+
"ui.setup.summary.trees": "Stammbäume",
|
|
1521
|
+
"ui.setup.summary.shared": "gemeinsame Daten",
|
|
1522
|
+
"ui.setup.summary.lang": "Sprache",
|
|
1523
|
+
"ui.setup.summary.detected": " – vom System erkannt; eine andere Sprache: strom config set lang <Code>",
|
|
1524
|
+
"ui.setup.summary.agent": "Agent",
|
|
1525
|
+
"ui.setup.summary.missing": " – noch nicht installiert",
|
|
1526
|
+
"ui.setup.summary.talk": "Gespräch",
|
|
1527
|
+
"ui.setup.summary.app": "in der App {app}",
|
|
1528
|
+
"ui.setup.summary.terminal": "im Terminal (seine CLI)",
|
|
1529
|
+
"ui.setup.summary.both": " – beides ist hier; die Entscheidung liegt beim Benutzer: strom setup --where {where}",
|
|
1530
|
+
"ui.setup.summary.knows": "kennt strom",
|
|
1531
|
+
"ui.setup.summary.anywhere": "{agent}, in jedem Ordner",
|
|
1532
|
+
"ui.setup.summary.config": "Einstellungen",
|
|
1533
|
+
"ui.arg.family-tree-name": "Name, z. B. der Familienname",
|
|
1477
1534
|
"ui.arg.agent": "Agent",
|
|
1478
1535
|
"ui.arg.batch": "Stapel",
|
|
1479
1536
|
"ui.arg.book": "Buch",
|
|
@@ -1536,6 +1593,8 @@
|
|
|
1536
1593
|
"ui.error.option.is-arg.hint": "{cmd} <{arg}>",
|
|
1537
1594
|
"ui.error.option.unknown": "unbekannte Option {opt} für {cmd}",
|
|
1538
1595
|
"ui.error.option.unknown.hint": "Optionen: {options} · strom help {path}",
|
|
1596
|
+
"ui.error.option.unknown.none": "unbekannte Option {opt} für {cmd}",
|
|
1597
|
+
"ui.error.option.unknown.none.hint": "{help}",
|
|
1539
1598
|
"ui.error.option.no-value": "{opt} hat keinen Wert",
|
|
1540
1599
|
"ui.error.option.needs-value": "{opt} braucht einen Wert {value}",
|
|
1541
1600
|
"ui.error.option.needs-value.hint": "strom help {path}",
|
|
@@ -148,6 +148,11 @@ as well: see step 2.
|
|
|
148
148
|
- strom shows each image's size (width × height). It should be the right page
|
|
149
149
|
and full size, not a thumbnail. Check that the number of images of a book
|
|
150
150
|
matches the portal.
|
|
151
|
+
- Keep `run` in connector.json as `["node", "connector.ts"]`: then it runs
|
|
152
|
+
fenced in (Node's permission model) and you may change the code without
|
|
153
|
+
asking. Split it into more files of this folder if you like, imported from
|
|
154
|
+
connector.ts. Another program, or a switch of Node's in `run`, needs the
|
|
155
|
+
user's consent after every change.
|
|
151
156
|
- If strom answers with exit code 4 (consent required), stop and tell the
|
|
152
157
|
user: they give it in their own terminal after reading the warning
|
|
153
158
|
(`strom allow connector __NAME__`). You never do that.
|
|
@@ -56,6 +56,10 @@ starts with `.` or `_` are ignored (`_old-version/`).
|
|
|
56
56
|
- `title`: the archive or portal, as people call it.
|
|
57
57
|
- `run`: the program and its arguments, started in the connector's folder.
|
|
58
58
|
`"node"` is the Node that runs strom (it runs TypeScript as it is).
|
|
59
|
+
`"node"` followed only by files of the connector's folder (no switches, no
|
|
60
|
+
`..`, no absolute paths) runs in Node's permission model. Any other program,
|
|
61
|
+
or a switch of Node's, runs only with the user's consent to the code exactly
|
|
62
|
+
as it is, asked again after every change of it.
|
|
59
63
|
- `hosts`: every host it contacts. `"example.org"` includes its subdomains.
|
|
60
64
|
strom refuses requests anywhere else, and each host needs the user's consent.
|
|
61
65
|
- `can`: what it does: any of `find`, `list`, `fetch`, `part`, `locate`.
|
|
@@ -384,8 +388,9 @@ with the text round it.
|
|
|
384
388
|
A connector runs as soon as it is in the folder. Two things need the user's
|
|
385
389
|
consent, given in their own terminal (`strom allow connector <name>`, or when
|
|
386
390
|
they run a test or a fetch themselves, where strom asks right away):
|
|
387
|
-
-
|
|
388
|
-
every change
|
|
391
|
+
- a `run` other than `"node"` and files of its folder, or code that seems to
|
|
392
|
+
reach the network itself, past strom: always, and again after every change
|
|
393
|
+
of it;
|
|
389
394
|
- every connector and each of its hosts, when the user asked to be asked first
|
|
390
395
|
(`strom config set connectors.consent on`).
|
|
391
396
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// The backup before another channel or an older version (core/backup.ts), as the CLI makes it: every research this
|
|
2
|
+
// computer knows and the settings, the README in the person's language, kept in the user config, said in a line.
|
|
3
|
+
import { EXIT, StromError } from "../core/errors.js";
|
|
4
|
+
import { backupOnce, backupsDir, BackupFailed, mb } from "../core/backup.js";
|
|
5
|
+
import { installation, replacedHolding } from "../core/self.js";
|
|
6
|
+
import { ui } from "./ui.js";
|
|
7
|
+
/** A local date and time for a sentence. */
|
|
8
|
+
function when(iso) {
|
|
9
|
+
const d = new Date(iso);
|
|
10
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
11
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
12
|
+
}
|
|
13
|
+
/** The versions as a sentence says them: their channels too where the version stays the same. */
|
|
14
|
+
function sides(t) {
|
|
15
|
+
const same = t.from === t.to;
|
|
16
|
+
return { from: `${t.from}${same && t.fromChannel ? ` (${t.fromChannel})` : ""}`, to: `${t.to}${same && t.toChannel ? ` (${t.toChannel})` : ""}` };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Make the backup of this change unless one was made for it already. Returns the one made now (undefined: made
|
|
20
|
+
* before, or nothing to back up — no home). Throws a StromError (exit 6) with the reason and what to do when it
|
|
21
|
+
* cannot: `update` — strom update stops before it installs; otherwise this strom opens no research for writing.
|
|
22
|
+
*/
|
|
23
|
+
export function backupBefore(ctx, t, opts = {}) {
|
|
24
|
+
const home = ctx.settings.home()?.value;
|
|
25
|
+
if (!home)
|
|
26
|
+
return undefined;
|
|
27
|
+
const lang = ctx.uiLang();
|
|
28
|
+
const said = sides(t);
|
|
29
|
+
try {
|
|
30
|
+
// never inside what strom update replaces (app/, node/ of the installer's folder): the backup would go with it
|
|
31
|
+
const inst = installation();
|
|
32
|
+
const inside = inst.kind === "installed" && inst.root ? replacedHolding(inst.root, [backupsDir(home)])[0] : undefined;
|
|
33
|
+
if (inside)
|
|
34
|
+
throw new BackupFailed(`${backupsDir(home)} lies inside ${inside.entry}, which strom update replaces — the research belongs outside strom's program folder`);
|
|
35
|
+
return backupOnce({
|
|
36
|
+
home,
|
|
37
|
+
env: ctx.env,
|
|
38
|
+
trees: () => ctx.knownTrees().map((k) => k.root),
|
|
39
|
+
research: [ctx.settings.trees()?.value, ctx.settings.shared()?.value].filter((p) => !!p),
|
|
40
|
+
transition: t,
|
|
41
|
+
readme: ui(lang, "ui.backup.readme", { ...said, date: when(new Date().toISOString()) }),
|
|
42
|
+
record: (made, before) => {
|
|
43
|
+
ctx.settings.config.backups = [...before, made];
|
|
44
|
+
ctx.settings.save();
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
const detail = e instanceof BackupFailed ? e.message : e.message;
|
|
50
|
+
const where = backupsDir(home);
|
|
51
|
+
const back = t.fromChannel ?? "stable";
|
|
52
|
+
const params = { ...said, detail, where, back, channel: opts.update?.channel ?? "" };
|
|
53
|
+
if (opts.update)
|
|
54
|
+
throw new StromError(`the backup before going from ${said.from} to ${said.to} could not be made: ${detail} — nothing was installed`, {
|
|
55
|
+
exitCode: EXIT.noBackup,
|
|
56
|
+
hint: `free room on the disk (${where}), then strom update --channel ${opts.update.channel} again`,
|
|
57
|
+
code: "backup.failed.update",
|
|
58
|
+
params,
|
|
59
|
+
details: { from: t.from, to: t.to, where, ...(e instanceof BackupFailed && e.room ? { room: e.room } : {}) },
|
|
60
|
+
});
|
|
61
|
+
throw new StromError(`the backup before going from ${said.from} to ${said.to} could not be made: ${detail} — nothing is switched: this strom opens no family tree for writing until it is made (tried again at each run)`, {
|
|
62
|
+
exitCode: EXIT.noBackup,
|
|
63
|
+
hint: `tell the user: free room on the disk (${where}), then run strom again — or go back: strom update --channel ${back}`,
|
|
64
|
+
code: "backup.failed",
|
|
65
|
+
params,
|
|
66
|
+
details: { from: t.from, to: t.to, where, ...(e instanceof BackupFailed && e.room ? { room: e.room } : {}) },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Where the backup is, in a line: the person's language, or JSON for an agent (--json). */
|
|
71
|
+
export function backupSaid(ctx, b) {
|
|
72
|
+
if (ctx.json)
|
|
73
|
+
return JSON.stringify({ backup: { path: b.path, bytes: b.bytes, from: b.from, to: b.to } });
|
|
74
|
+
return ui(ctx.uiLang(), "ui.backup.made", { ...sides(b), path: b.path, size: mb(b.bytes) });
|
|
75
|
+
}
|
|
76
|
+
/** The last backup in a line (the menu, strom doctor). */
|
|
77
|
+
export function lastBackupLine(lang, b) {
|
|
78
|
+
return ui(lang, "ui.backup.last", { ...sides(b), date: when(b.at), path: b.path });
|
|
79
|
+
}
|
package/dist/cli/context.js
CHANGED
|
@@ -5,10 +5,13 @@ import path from "node:path";
|
|
|
5
5
|
import readline from "node:readline/promises";
|
|
6
6
|
import { Writable } from "node:stream";
|
|
7
7
|
import { Settings } from "../core/config.js";
|
|
8
|
-
import { displayPath, expandHome } from "../core/paths.js";
|
|
8
|
+
import { configDir, displayPath, expandHome, ISOLATED_HOME } from "../core/paths.js";
|
|
9
|
+
import { backupsDir } from "../core/backup.js";
|
|
10
|
+
import { insideProgram } from "../core/self.js";
|
|
9
11
|
import { Cancelled, NeedsConsentError, NeedsInputError, StromError, UsageError } from "../core/errors.js";
|
|
10
12
|
import { migrate } from "../core/migrate.js";
|
|
11
13
|
import { Tree, findTreeUpwards, isTreeDir } from "../core/tree.js";
|
|
14
|
+
import { SCHEMA_VERSION } from "../core/model.js";
|
|
12
15
|
import { readJsonIfExists } from "../core/json.js";
|
|
13
16
|
import { foldText } from "../core/text.js";
|
|
14
17
|
import { currentSession } from "../core/session.js";
|
|
@@ -27,6 +30,11 @@ export class Context {
|
|
|
27
30
|
page;
|
|
28
31
|
dryRun = false;
|
|
29
32
|
opened;
|
|
33
|
+
/**
|
|
34
|
+
* The backup before another channel or an older version could not be made (cli/backups.ts): no research is brought
|
|
35
|
+
* to this strom's schema meanwhile — reading one that needs it says why, as writing does.
|
|
36
|
+
*/
|
|
37
|
+
backupFailed;
|
|
30
38
|
constructor(opts) {
|
|
31
39
|
this.env = opts.env;
|
|
32
40
|
this.cwd = opts.cwd;
|
|
@@ -185,6 +193,36 @@ export class Context {
|
|
|
185
193
|
// a person (a script, no terminal) reads it in their language; an agent the English it goes by
|
|
186
194
|
throw new NeedsConsentError([{ key, kind: "consent", question: `${question}${agent ? " (an agent cannot answer this)" : ""}`, set }], agent ? undefined : says);
|
|
187
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* An agent strom did not start, working outside the research's folder and strom's shared one (a session in
|
|
198
|
+
* another repository, where the agents' global rule lets it run strom without asking): what runs a connector's
|
|
199
|
+
* code or starts paid work is asked in a window there — reading the research is not.
|
|
200
|
+
*/
|
|
201
|
+
agentElsewhere() {
|
|
202
|
+
if (!isAgent(this.env) || this.env.STROM_WORKER || this.env.STROM_SESSION)
|
|
203
|
+
return false;
|
|
204
|
+
if (findTreeUpwards(this.cwd))
|
|
205
|
+
return false;
|
|
206
|
+
const shared = this.settings.shared()?.value;
|
|
207
|
+
const inside = (dir, p) => {
|
|
208
|
+
const rel = path.relative(dir, p);
|
|
209
|
+
return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
|
|
210
|
+
};
|
|
211
|
+
const real = (p) => {
|
|
212
|
+
try {
|
|
213
|
+
return fs.realpathSync(p);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return path.resolve(p);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
return !(shared && inside(real(shared), real(this.cwd)));
|
|
220
|
+
}
|
|
221
|
+
/** What an agent elsewhere (agentElsewhere) may do only with the person's yes, in a window: `says` in their language. */
|
|
222
|
+
confirmElsewhere(question, set, key, says) {
|
|
223
|
+
if (this.agentElsewhere())
|
|
224
|
+
this.requireHuman(question, set, key, says);
|
|
225
|
+
}
|
|
188
226
|
/**
|
|
189
227
|
* One of numbered options (1…n, or keys of their own like "0"); Enter takes
|
|
190
228
|
* the suggested one. Asks again on anything else. `back` adds "0" with that
|
|
@@ -230,9 +268,12 @@ export class Context {
|
|
|
230
268
|
const home = this.settings.home();
|
|
231
269
|
if (home)
|
|
232
270
|
return home.value;
|
|
233
|
-
|
|
234
|
-
|
|
271
|
+
// the default inside strom's program folder (settings lying in node/): refused with --yes, never offered
|
|
272
|
+
const suggested = this.homeSuggestion();
|
|
273
|
+
if (this.yes) {
|
|
274
|
+
this.refuseProgramFolder("home", this.settings.suggestedHome(), { asDefault: true });
|
|
235
275
|
return this.saveHome(suggested);
|
|
276
|
+
}
|
|
236
277
|
if (!this.interactive)
|
|
237
278
|
throw new NeedsInputError([
|
|
238
279
|
{
|
|
@@ -248,10 +289,52 @@ export class Context {
|
|
|
248
289
|
return this.saveHome(this.resolvePath(answer));
|
|
249
290
|
}
|
|
250
291
|
saveHome(dir) {
|
|
292
|
+
this.refuseProgramFolder("home", dir);
|
|
251
293
|
this.settings.config.home = dir;
|
|
252
294
|
this.settings.save();
|
|
253
295
|
return dir;
|
|
254
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* What is the research's and the person's on this computer: the home, its backups, the folder of the trees, the
|
|
299
|
+
* shared folder, every tree known, the settings — what strom update and strom uninstall never take away.
|
|
300
|
+
*/
|
|
301
|
+
researchFolders() {
|
|
302
|
+
const home = this.settings.home()?.value;
|
|
303
|
+
return [
|
|
304
|
+
...(home ? [home, backupsDir(home)] : []),
|
|
305
|
+
...[this.settings.trees()?.value, this.settings.shared()?.value].filter((p) => !!p),
|
|
306
|
+
...this.knownTrees().map((k) => k.root),
|
|
307
|
+
configDir(this.env),
|
|
308
|
+
];
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* A folder for the research (home, trees, shared) never inside strom's program folder: an update replaces what is
|
|
312
|
+
* there and an uninstall takes it away (found 2026-10-07: a research inside app/ went with the next update, and the
|
|
313
|
+
* backup made just before it). Refused with what to do; nothing is written.
|
|
314
|
+
*/
|
|
315
|
+
refuseProgramFolder(key, folder, opts = {}) {
|
|
316
|
+
const program = insideProgram(folder, { settings: configDir(this.env) });
|
|
317
|
+
if (!program)
|
|
318
|
+
return;
|
|
319
|
+
const home = this.homeSuggestion();
|
|
320
|
+
const suggested = this.display(opts.suggested ?? (key === "shared" ? path.join(home, "shared") : home));
|
|
321
|
+
// the folder strom would take by itself (none named, --yes): the way on is naming one
|
|
322
|
+
throw new UsageError(`${this.display(folder)} is inside strom's program folder ${this.display(program)} — strom update replaces what is there and strom uninstall takes it away, the research with it; nothing was changed`, {
|
|
323
|
+
hint: opts.asDefault ? `pass --home with a folder outside it: strom setup --home "${suggested}" --yes` : `a folder outside it, e.g. ${suggested}`,
|
|
324
|
+
...(opts.asDefault ? { hintCode: "folder.in-program.default" } : {}),
|
|
325
|
+
code: "folder.in-program",
|
|
326
|
+
params: { folder: this.display(folder), program: this.display(program), key, suggested },
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* The folder suggested for the research: the usual one (defaultHome) — unless it lies inside strom's program folder
|
|
331
|
+
* (an isolated installation's settings in its node/ or app/: found on a Mac), then one beside that folder.
|
|
332
|
+
*/
|
|
333
|
+
homeSuggestion() {
|
|
334
|
+
const home = this.settings.suggestedHome();
|
|
335
|
+
const program = insideProgram(home, { settings: configDir(this.env) });
|
|
336
|
+
return program ? path.join(path.dirname(program), ISOLATED_HOME) : home;
|
|
337
|
+
}
|
|
255
338
|
treesDir() {
|
|
256
339
|
return this.settings.trees()?.value;
|
|
257
340
|
}
|
|
@@ -313,7 +396,10 @@ export class Context {
|
|
|
313
396
|
const names = known.map((t) => `"${t.name}"`).join(", ");
|
|
314
397
|
throw new UsageError("which tree? there are several", { hint: `pass --tree <name>: ${names}`, code: "tree.which", params: { names } });
|
|
315
398
|
}
|
|
316
|
-
|
|
399
|
+
const opened = Tree.open(root, this.env);
|
|
400
|
+
if (this.backupFailed && (opened.config.schema ?? 1) < SCHEMA_VERSION)
|
|
401
|
+
throw this.backupFailed;
|
|
402
|
+
this.opened = opened;
|
|
317
403
|
// Data an older strom wrote under an older schema: brought forward first (a dry run too — it is not the command's change).
|
|
318
404
|
// said in the person's language: each step by its own sentence (the commit keeps the English one)
|
|
319
405
|
for (const step of migrate(this.opened)) {
|