@materializecms/cli 0.2.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -4,6 +4,29 @@ Ogni versione, dalla più recente. Le novità in arrivo si scrivono sotto «Pros
4
4
 
5
5
  ## Prossima versione
6
6
 
7
+ ## 0.4.0 — 2026-11-03
8
+
9
+ - **Immagini di riferimento nell'assistente**: allega, incolla (⌘V) o trascina nella chat lo screenshot di un sito che ti piace, un mockup o uno schizzo, e l'assistente ne riprende impaginazione e atmosfera con le sezioni e lo stile del tuo sito. Fino a 4 immagini per messaggio; non vanno nella libreria e non finiscono sulla pagina.
10
+ - **Conversazioni con l'assistente più solide**: un secondo messaggio dopo aver cambiato la selezione sulla tela non fallisce più, e ogni nuovo messaggio rilegge dalla cache tutta la conversazione precedente, così costa una frazione.
11
+ - **L'assistente costa meno**: con Claude usa la cache dei prompt, così istruzioni, strumenti e pagina, rimandati a ogni passaggio, si pagano a una frazione del prezzo dopo il primo.
12
+ - **Azioni rapide più economiche**: ✨ sui testi, SEO e testo alternativo usano Claude Haiku 5.5, molto più economico di Opus; l'assistente e le traduzioni delle pagine restano sul modello principale. Si può scegliere un altro modello in Impostazioni → AI e MCP.
13
+ - **Uso dell'AI del mese** in Impostazioni → AI e MCP: richieste, token letti (e quanti dalla cache) e scritti, per tenere d'occhio la spesa.
14
+ - **AI sul testo formattato**: il pulsante ✨ c'è anche nel corpo degli articoli, e riscrive, accorcia o traduce mantenendo titoli, elenchi, grassetti, link e immagini.
15
+ - **✨ sulla tela mantiene grassetti, corsivi e link** di un testo, nell'Inspector e in modalità Contenuto.
16
+ - **Accorcia e Allunga più affidabili**: chiedono una lunghezza precisa (circa un terzo in meno, circa la metà in più), così un testo breve non torna quasi uguale e uno da allungare non diventa sette volte più lungo.
17
+ - **L'AI rispetta la lunghezza dei campi**: un testo riscritto non supera più il massimo del campo (prima, per esempio, un sommario di 220 caratteri poteva arrivare a 234 e bloccare la pubblicazione).
18
+ - **Descrivi con l'AI conserva i crediti**: il testo alternativo nuovo mantiene il credito della foto già scritto, come «foto di … su Unsplash», e la sua lingua.
19
+ - **Nastri con i bordi sfumati**: le lettere che scendono sotto la riga (g, p, y) non vengono più tagliate in basso.
20
+ - **Indirizzi del pannello scritti a mano**: `/admin/media`, `/admin/persone` e `/admin/impostazioni` portano alla sezione giusta, se nessuna raccolta ha quel nome.
21
+
22
+ ## 0.3.0 — 2026-11-01
23
+
24
+ - **Backup fuori dal server**, ogni notte e cifrati, su uno spazio S3 compatibile (Cloudflare R2, Backblaze B2, Hetzner, Amazon S3…) o in una cartella WebDAV (Nextcloud, NAS Synology e QNAP…). Si attiva in Impostazioni → Backup; `materialize decrypt` rende di nuovo leggibili i file scaricati.
25
+ - **Email più facile da configurare**: si sceglie il fornitore (Brevo, Postmark, Mailgun, Amazon SES, Gmail…) e il server si compila da solo; se la prova non riesce, il pannello spiega perché (porta bloccata, password rifiutata, mittente non verificato…); **Controlla il dominio** verifica SPF, DKIM e DMARC.
26
+ - **Pannello più chiaro**: Impostazioni → Protezione divisa in Sicurezza, Backup e Registro attività; barra dell'editor a gruppi, con gli elementi meno usati in **⋯**; pannello sinistro dell'editor allargabile; menu a tendina, intestazioni e testi d'aiuto uniformi e più leggibili; pagina dedicata per gli indirizzi del pannello che non esistono; in Persone, chi entra con la sola password si riconosce a colpo d'occhio; accesso e installazione con l'aspetto del pannello.
27
+ - **Chi ha fatto ogni versione**: la cronologia mostra il nome dell'autore accanto alla data.
28
+ - **Informazioni su Materialize** in Impostazioni: versione, autore, licenza, novità, guida e licenze di terzi.
29
+
7
30
  ## 0.2.0 — 2026-11-01
8
31
 
9
32
  - **Password dimenticata?** nella pagina di accesso: un link per email, valido un'ora. Senza email configurata, il comando `materialize reset-password` stampa il link sul server, anche per l'unico amministratore.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Cristiano Casazza
3
+ Copyright (c) 2026 Cristiano Casazza Consulting
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@materializecms/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Il comando materialize: sviluppo, produzione con aggiornamenti dal pannello, generazione del sito, backup, MCP.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,10 +21,10 @@
21
21
  }
22
22
  },
23
23
  "dependencies": {
24
- "@materializecms/astro": "0.2.0",
25
- "@materializecms/core": "0.2.0",
26
- "@materializecms/db": "0.2.0",
27
- "@materializecms/server": "0.2.0",
24
+ "@materializecms/astro": "0.4.0",
25
+ "@materializecms/core": "0.4.0",
26
+ "@materializecms/db": "0.4.0",
27
+ "@materializecms/server": "0.4.0",
28
28
  "@modelcontextprotocol/sdk": "1.32.2"
29
29
  },
30
30
  "peerDependencies": {
@@ -42,6 +42,16 @@
42
42
  "access": "public"
43
43
  },
44
44
  "changelog": [
45
+ {
46
+ "version": "0.4.0",
47
+ "date": "2026-11-03",
48
+ "notes": "- **Immagini di riferimento nell'assistente**: allega, incolla (⌘V) o trascina nella chat lo screenshot di un sito che ti piace, un mockup o uno schizzo, e l'assistente ne riprende impaginazione e atmosfera con le sezioni e lo stile del tuo sito. Fino a 4 immagini per messaggio; non vanno nella libreria e non finiscono sulla pagina.\n- **Conversazioni con l'assistente più solide**: un secondo messaggio dopo aver cambiato la selezione sulla tela non fallisce più, e ogni nuovo messaggio rilegge dalla cache tutta la conversazione precedente, così costa una frazione.\n- **L'assistente costa meno**: con Claude usa la cache dei prompt, così istruzioni, strumenti e pagina, rimandati a ogni passaggio, si pagano a una frazione del prezzo dopo il primo.\n- **Azioni rapide più economiche**: ✨ sui testi, SEO e testo alternativo usano Claude Haiku 5.5, molto più economico di Opus; l'assistente e le traduzioni delle pagine restano sul modello principale. Si può scegliere un altro modello in Impostazioni → AI e MCP.\n- **Uso dell'AI del mese** in Impostazioni → AI e MCP: richieste, token letti (e quanti dalla cache) e scritti, per tenere d'occhio la spesa.\n- **AI sul testo formattato**: il pulsante ✨ c'è anche nel corpo degli articoli, e riscrive, accorcia o traduce mantenendo titoli, elenchi, grassetti, link e immagini.\n- **✨ sulla tela mantiene grassetti, corsivi e link** di un testo, nell'Inspector e in modalità Contenuto.\n- **Accorcia e Allunga più affidabili**: chiedono una lunghezza precisa (circa un terzo in meno, circa la metà in più), così un testo breve non torna quasi uguale e uno da allungare non diventa sette volte più lungo.\n- **L'AI rispetta la lunghezza dei campi**: un testo riscritto non supera più il massimo del campo (prima, per esempio, un sommario di 220 caratteri poteva arrivare a 234 e bloccare la pubblicazione).\n- **Descrivi con l'AI conserva i crediti**: il testo alternativo nuovo mantiene il credito della foto già scritto, come «foto di … su Unsplash», e la sua lingua.\n- **Nastri con i bordi sfumati**: le lettere che scendono sotto la riga (g, p, y) non vengono più tagliate in basso.\n- **Indirizzi del pannello scritti a mano**: `/admin/media`, `/admin/persone` e `/admin/impostazioni` portano alla sezione giusta, se nessuna raccolta ha quel nome."
49
+ },
50
+ {
51
+ "version": "0.3.0",
52
+ "date": "2026-11-01",
53
+ "notes": "- **Backup fuori dal server**, ogni notte e cifrati, su uno spazio S3 compatibile (Cloudflare R2, Backblaze B2, Hetzner, Amazon S3…) o in una cartella WebDAV (Nextcloud, NAS Synology e QNAP…). Si attiva in Impostazioni → Backup; `materialize decrypt` rende di nuovo leggibili i file scaricati.\n- **Email più facile da configurare**: si sceglie il fornitore (Brevo, Postmark, Mailgun, Amazon SES, Gmail…) e il server si compila da solo; se la prova non riesce, il pannello spiega perché (porta bloccata, password rifiutata, mittente non verificato…); **Controlla il dominio** verifica SPF, DKIM e DMARC.\n- **Pannello più chiaro**: Impostazioni → Protezione divisa in Sicurezza, Backup e Registro attività; barra dell'editor a gruppi, con gli elementi meno usati in **⋯**; pannello sinistro dell'editor allargabile; menu a tendina, intestazioni e testi d'aiuto uniformi e più leggibili; pagina dedicata per gli indirizzi del pannello che non esistono; in Persone, chi entra con la sola password si riconosce a colpo d'occhio; accesso e installazione con l'aspetto del pannello.\n- **Chi ha fatto ogni versione**: la cronologia mostra il nome dell'autore accanto alla data.\n- **Informazioni su Materialize** in Impostazioni: versione, autore, licenza, novità, guida e licenze di terzi."
54
+ },
45
55
  {
46
56
  "version": "0.2.0",
47
57
  "date": "2026-11-01",
package/src/commands.js CHANGED
@@ -5,7 +5,7 @@ import { dirname, join, relative, resolve } from 'node:path';
5
5
  import { styleText } from 'node:util';
6
6
  import { resolveRedirect } from '@materializecms/core/seo';
7
7
  import { createActivityStore, createAuthStore, createContentStore, createSettingsStore, openDatabase, } from '@materializecms/db';
8
- import { apiCaller, createFonts, createMcpServer, createMediaFiles, extractTarGz, restoreMedia, startServer, VERSION, } from '@materializecms/server';
8
+ import { apiCaller, createFonts, createMcpServer, createMediaFiles, decryptTree, extractTarGz, parseRecoveryKey, restoreMedia, startServer, VERSION, } from '@materializecms/server';
9
9
  import { findConfig, loadConfig } from './load-config.js';
10
10
  import { buildSite, exportFonts, exportMedia, hasSite, ProductionSite, startDevSite } from './site.js';
11
11
  import { RESTART } from './supervisor.js';
@@ -28,6 +28,9 @@ ${accent('materialize')} ${dim(VERSION)}
28
28
  materialize reset-password <email>
29
29
  Un link per una nuova password, valido un'ora: per chi non può riceverlo per email
30
30
  (per esempio l'unico amministratore, senza email configurata)
31
+ materialize decrypt <cartella o file> [--key <chiave>]
32
+ Decifra i backup scaricati dallo spazio esterno (S3, WebDAV); la chiave di
33
+ ripristino si può dare anche con MATERIALIZE_BACKUP_KEY
31
34
  materialize --help Mostra questo aiuto
32
35
 
33
36
  Opzioni
@@ -402,6 +405,57 @@ async function resetPassword(args) {
402
405
  database.close();
403
406
  }
404
407
  }
408
+ /**
409
+ * The backups sent outside the server, downloaded with any tool, made readable again: every .mzb
410
+ * file is decrypted next to itself. The key comes from --key, MATERIALIZE_BACKUP_KEY or, in the
411
+ * folder of a site that still has its database, from its settings.
412
+ */
413
+ async function decrypt(args) {
414
+ const flag = args.indexOf('--key');
415
+ const source = args.find((a, i) => !a.startsWith('--') && (flag < 0 || i !== flag + 1));
416
+ if (!source) {
417
+ console.error(fail('Indica la cartella (o il file) da decifrare: materialize decrypt <cartella> --key <chiave>'));
418
+ process.exit(1);
419
+ }
420
+ let text = flag >= 0 ? args[flag + 1] : process.env.MATERIALIZE_BACKUP_KEY;
421
+ if (!text) {
422
+ const path = findConfig(process.cwd());
423
+ if (path) {
424
+ const database = await openDatabase((await loadConfig(path)).database).catch(() => null);
425
+ if (database) {
426
+ text = (await createSettingsStore(database.db).get('offsite'))?.key;
427
+ database.close();
428
+ }
429
+ }
430
+ }
431
+ if (!text) {
432
+ console.error(fail('Manca la chiave di ripristino: --key mzk1-… oppure MATERIALIZE_BACKUP_KEY.'));
433
+ process.exit(1);
434
+ }
435
+ let key;
436
+ try {
437
+ key = parseRecoveryKey(text);
438
+ }
439
+ catch (error) {
440
+ console.error(fail(describeError(error)));
441
+ process.exit(1);
442
+ }
443
+ try {
444
+ const done = await decryptTree(resolve(source), key);
445
+ console.log(` ${ok('✓')} ${done.length} ${done.length === 1 ? 'file decifrato' : 'file decifrati'}, accanto agli originali.`);
446
+ const db = done
447
+ .filter((f) => /content-[^/\\]+\.db$/.test(f))
448
+ .sort()
449
+ .at(-1);
450
+ if (db)
451
+ // The shorter of the two ways to write the path.
452
+ console.log(dim(` Per rimettere il database (a server fermo): npx materialize restore ${[relative(process.cwd(), db), db].sort((x, y) => x.length - y.length)[0]}`));
453
+ }
454
+ catch (error) {
455
+ console.error(fail(describeError(error)));
456
+ process.exit(1);
457
+ }
458
+ }
405
459
  const [command = 'help', ...args] = process.argv.slice(2);
406
460
  if (command === 'dev' || command === 'start' || command === 'build') {
407
461
  await run(command, args);
@@ -409,6 +463,9 @@ if (command === 'dev' || command === 'start' || command === 'build') {
409
463
  else if (command === 'mcp') {
410
464
  await mcp(args);
411
465
  }
466
+ else if (command === 'decrypt') {
467
+ await decrypt(args);
468
+ }
412
469
  else if (command === 'reset-password') {
413
470
  await resetPassword(args);
414
471
  }