@beechcms/api 0.6.7 → 0.8.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/assets/dashboard/0auth_mcp.svg +1 -0
- package/assets/dashboard/assets/{chart-D_uST30B.js → chart-CYgKoF6U.js} +6 -6
- package/assets/dashboard/assets/dist-DHabpZqA.js +140 -0
- package/assets/dashboard/assets/index-BZMSpYrl.js +3613 -0
- package/assets/dashboard/assets/index-Dex2YZcC.css +1 -0
- package/assets/dashboard/assets/json-code-editor-DtZpKDXm.js +12 -0
- package/assets/dashboard/assets/pie-chart-recharts-C7WAhcCk.js +1 -0
- package/assets/dashboard/assets/richtext-render-x0TT0116.js +258 -0
- package/assets/dashboard/assets/timeseries-chart-recharts-B9RquiY6.js +1 -0
- package/assets/dashboard/assets/w3c-keyname-BOAvb0qz.js +1 -0
- package/assets/dashboard/index.html +4 -2
- package/dist/auth/auth.app.d.ts +13 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/factory.d.ts +14 -1
- package/dist/features/oauth/authorization-request.d.ts +127 -0
- package/dist/features/oauth/authorize.d.ts +97 -0
- package/dist/features/oauth/consents.d.ts +75 -0
- package/dist/features/oauth/constants.d.ts +48 -0
- package/dist/features/oauth/index.d.ts +31 -0
- package/dist/features/oauth/revoke.d.ts +29 -0
- package/dist/features/oauth/token-issuance.d.ts +49 -0
- package/dist/features/oauth/token.d.ts +38 -0
- package/dist/features/search/constants.d.ts +43 -0
- package/dist/features/search/handlers/embed.d.ts +31 -0
- package/dist/features/search/handlers/full-text-search.d.ts +28 -0
- package/dist/features/search/index.d.ts +20 -0
- package/dist/features/search/jobs/semantic-search.hooks.d.ts +21 -0
- package/dist/features/search/jobs/semantic-search.worker.d.ts +101 -0
- package/dist/features/search/public-search.router.d.ts +15 -0
- package/dist/features/search/search.d.ts +14 -6
- package/dist/features/search/semantic-search.hooks.d.ts +2 -0
- package/dist/features/search/semantic-search.worker.d.ts +21 -0
- package/dist/features/search/types.d.ts +100 -0
- package/dist/features/search/utils/search-utils.d.ts +56 -0
- package/dist/features/seeds/seeds.destructive.d.ts +6 -0
- package/dist/features/seeds/seeds.handler.d.ts +14 -0
- package/dist/features/seeds/seeds.helpers.d.ts +118 -0
- package/dist/features/seeds/seeds.mcp.d.ts +37 -0
- package/dist/features/upload/index.d.ts +2 -2
- package/dist/index.js +3544 -1368
- package/dist/middleware/auth.middleware.d.ts +34 -4
- package/dist/middleware/oauth-scope.middleware.d.ts +60 -0
- package/dist/middleware/rate-limit.middleware.d.ts +4 -2
- package/dist/middleware/repository.middleware.d.ts +9 -1
- package/dist/public/api-key-middleware.d.ts +0 -4
- package/dist/public/public-add.d.ts +1 -1
- package/dist/rate-limit/in-memory-rate-limiter.d.ts +1 -8
- package/dist/shared/db/repositories/content.repository.d1.d.ts +4 -2
- package/dist/shared/db/repositories/d1-oauth-authorization-code.repository.d.ts +9 -0
- package/dist/shared/db/repositories/d1-oauth-client.repository.d.ts +6 -0
- package/dist/shared/db/repositories/d1-oauth-consent.repository.d.ts +10 -0
- package/dist/shared/db/repositories/d1-oauth-token.repository.d.ts +12 -0
- package/dist/shared/db/repositories/d1-search.query.d.ts +54 -0
- package/dist/shared/db/repositories/d1-vector.repository.d.ts +11 -0
- package/dist/shared/db/repositories/in-memory-seed.repository.d.ts +2 -1
- package/dist/shared/db/repositories/seed.repository.d1.d.ts +3 -1
- package/dist/shared/db/repositories/time-trap-token.repository.d1.d.ts +7 -0
- package/dist/shared/storage/factory.d.ts +84 -4
- package/dist/shared/storage/r2-bucket.d.ts +127 -0
- package/dist/shared/storage/s3-bucket.d.ts +104 -10
- package/dist/shared/storage/upload.d.ts +33 -5
- package/dist/shared/utils/dual-key-rate-limiter.d.ts +21 -0
- package/dist/shared/utils/media-utils.d.ts +3 -3
- package/dist/shared/utils/opaque-token.d.ts +13 -0
- package/dist/types.d.ts +49 -1
- package/migrations/0000_v040_base.sql +184 -1
- package/migrations/_archive/0000_schema_init.sql +257 -0
- package/migrations/_archive/0001_init.sql +25 -0
- package/migrations/_archive/0002_seed_admin.sql +10 -0
- package/migrations/_archive/0003_refresh_tokens.sql +17 -0
- package/migrations/_archive/0004_seed_projects.sql +18 -0
- package/migrations/_archive/0005_update_projects.sql +56 -0
- package/migrations/_archive/0006_add_slug_and_unique_index.sql +7 -0
- package/migrations/_archive/0007_cleanup_test_data.sql +4 -0
- package/migrations/_archive/0008_seed_content_entries.sql +104 -0
- package/migrations/_archive/0009_public_idempotency.sql +11 -0
- package/migrations/_archive/0010_seed_real_data.sql +31 -0
- package/migrations/_archive/0010_testsite_data.sql +31 -0
- package/migrations/_archive/0011_analytics.sql +10 -0
- package/migrations/_archive/0012_seed_analytics.sql +17 -0
- package/migrations/_archive/0013_system_stats.sql +8 -0
- package/migrations/_archive/0014_activity_logs.sql +15 -0
- package/migrations/_archive/0015_notifications.sql +12 -0
- package/migrations/_archive/0016_fts5_global_search.sql +81 -0
- package/migrations/_archive/0017_seed_clienti.sql +90 -0
- package/migrations/_archive/0018_draft_data.sql +3 -0
- package/migrations/_archive/0019_drop_fts_triggers.sql +7 -0
- package/migrations/_archive/0020_composite_indexes.sql +15 -0
- package/migrations/_archive/0021_media_objects.sql +15 -0
- package/migrations/_archive/0022_analytics_seed.sql +23 -0
- package/migrations/_archive/0023_user_profile.sql +4 -0
- package/migrations/_archive/0024_activity_user_name.sql +3 -0
- package/migrations/_archive/0025_password_reset_tokens.sql +11 -0
- package/migrations/_archive/0026_remove_dev_admin.sql +4 -0
- package/migrations/_archive/0027_v040_doctype_architecture.sql +51 -0
- package/migrations/_archive/0029_fts_all_text_branches.sql +281 -0
- package/migrations/_archive/0031_site_settings.sql +9 -0
- package/migrations/_archive/0032_seeds.sql +28 -0
- package/migrations/_archive/0033_dashboard_layouts.sql +14 -0
- package/migrations/_archive/0034_kanban_foundation.sql +24 -0
- package/migrations/_archive/0035_setup_lock.sql +10 -0
- package/migrations/_archive/0036_notification_type_success.sql +23 -0
- package/migrations/_archive/0037_time_trap_tokens.sql +13 -0
- package/migrations/_archive/0038_oauth_authorization.sql +95 -0
- package/migrations/_archive/0039_oauth_client_beech_mcp.sql +20 -0
- package/package.json +3 -5
- package/assets/dashboard/assets/index-B58kBLrh.css +0 -1
- package/assets/dashboard/assets/index-DjniT5Z9.js +0 -745
- package/assets/dashboard/assets/pie-chart-recharts-CnVomiSi.js +0 -1
- package/assets/dashboard/assets/timeseries-chart-recharts-CTqi8qnV.js +0 -1
- /package/migrations/{0029_automations.sql → _archive/0029_automations.sql} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- Migrazione 0010: Seed contenuti per il testsite (DX testing)
|
|
2
|
+
-- Vengono inseriti record con immagini di alta qualita' da Unsplash.
|
|
3
|
+
|
|
4
|
+
INSERT INTO content_entries (id, schema_slug, slug, status, data, created_at, updated_at) VALUES
|
|
5
|
+
('test-art-01', 'articoli', 'design-system-vibes', 'published',
|
|
6
|
+
'{"art_01":"Design System: Il Cuore del Testsite","art_02":"2026-04-10","art_03":"https://images.unsplash.com/photo-1561070791-2526d30994b5?auto=format&fit=crop&q=80&w=2000&h=1000","art_04":"{\"design\":\"#3b82f6\",\"dx\":\"#10b981\"}","art_05":"<p>Un design system solido è la chiave per un frontend eccellente. Con Beech CMS e Shadcn UI, costruiamo interfacce in un batter d''occhio.</p>","art_06":"Design System","art_07":"Scopri come integrare componenti premium nel tuo progetto."}',
|
|
7
|
+
unixepoch(), unixepoch()),
|
|
8
|
+
('test-art-02', 'articoli', 'edge-computing-future', 'published',
|
|
9
|
+
'{"art_01":"Il Futuro è Edge Computing","art_02":"2026-04-12","art_03":"https://images.unsplash.com/photo-1451187580459-43490279c0fa?auto=format&fit=crop&q=80&w=2000&h=1000","art_04":"{\"cloud\":\"#8b5cf6\",\"edge\":\"#ec4899\"}","art_05":"<p>Beech CMS nasce per Cloudflare Workers, offrendo performance incredibili a livello globale senza la necessità di complessi bilanciatori di carico.</p>","art_06":"Edge Computing","art_07":"Perché Cloudflare Workers cambierà tutto."}',
|
|
10
|
+
unixepoch(), unixepoch()),
|
|
11
|
+
('test-art-03', 'articoli', 'premium-typography', 'published',
|
|
12
|
+
'{"art_01":"L''Arte della Tipografia","art_02":"2026-04-15","art_03":"https://images.unsplash.com/photo-1596541223140-5b565a0b9380?auto=format&fit=crop&q=80&w=2000&h=1000","art_04":"{\"ui\":\"#f59e0b\",\"typography\":\"#06b6d4\"}","art_05":"<p>Una tipografia curata può trasformare un semplice sito web in un''esperienza utente di classe mondiale. Inter, Roboto e Outfit sono le nostre prime scelte.</p>","art_06":"Tipografia Premium","art_07":"Eleva i tuoi contenuti con i font giusti."}',
|
|
13
|
+
unixepoch(), unixepoch());
|
|
14
|
+
|
|
15
|
+
-- Usiamo 'prodotti' come Galleria Fotografica
|
|
16
|
+
INSERT INTO content_entries (id, schema_slug, slug, status, data, created_at, updated_at) VALUES
|
|
17
|
+
('test-gal-01', 'prodotti', 'architecture-modern', 'published',
|
|
18
|
+
'{"prd_01":"Architettura Moderna","prd_02":0,"prd_03":1,"prd_04":true,"prd_05":"https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=800&h=800","prd_06":"[\"https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80\",\"https://images.unsplash.com/photo-1428366890462-dd4baecf492b?auto=format&fit=crop&q=80\"]","prd_07":"<p>Collezione fotografica di architetture di fascia alta, per dimostrare l''uso di immagini asset-list in Tailwind e css moderni.</p>","prd_08":"Architettura Moderna","prd_09":"Galleria di architettura contemporanea."}',
|
|
19
|
+
unixepoch(), unixepoch()),
|
|
20
|
+
('test-gal-02', 'prodotti', 'nature-landscapes', 'published',
|
|
21
|
+
'{"prd_01":"Paesaggi Incontaminati","prd_02":0,"prd_03":1,"prd_04":true,"prd_05":"https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&q=80&w=800&h=800","prd_06":"[\"https://images.unsplash.com/photo-1472214103451-9374bd1c798e?auto=format&fit=crop&q=80\",\"https://images.unsplash.com/photo-1501854140801-50d01698950b?auto=format&fit=crop&q=80\"]","prd_07":"<p>Immagini rilassanti della natura, perfette per una galleria premium responsive.</p>","prd_08":"Paesaggi Incontaminati","prd_09":"Bellezza della natura in alta definizione."}',
|
|
22
|
+
unixepoch(), unixepoch()),
|
|
23
|
+
('test-gal-03', 'prodotti', 'abstract-art', 'published',
|
|
24
|
+
'{"prd_01":"Arte Astratta e Luce","prd_02":0,"prd_03":1,"prd_04":true,"prd_05":"https://images.unsplash.com/photo-1550684848-fac1c5b4e853?auto=format&fit=crop&q=80&w=800&h=800","prd_06":"[]","prd_07":"<p>Giochi di luce e neon renderizzati per esplorare contrasti cromatici decisi nel glassmorphism UI.</p>","prd_08":"Arte Astratta e Luce","prd_09":"Un tuffo in effetti visivi astratti."}',
|
|
25
|
+
unixepoch(), unixepoch());
|
|
26
|
+
|
|
27
|
+
-- Landing Page
|
|
28
|
+
INSERT INTO content_entries (id, schema_slug, slug, status, data, created_at, updated_at) VALUES
|
|
29
|
+
('test-pag-01', 'pagine', 'test-home', 'published',
|
|
30
|
+
'{"pag_01":"BeechCMS Test Experience","pag_02":"https://images.unsplash.com/photo-1550745165-9bc0b252726f?auto=format&fit=crop&q=80&w=2000&h=1000","pag_03":"<h1>Benvenuti nella DX Demo</h1><p>Esplora il design, la reattività della Public API e prova tu stesso il contact module.</p>","pag_04":"BeechCMS - Test","pag_05":"Pagina di test del framework."}',
|
|
31
|
+
unixepoch(), unixepoch());
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Migrazione: Tabella Analytics per metriche Cloudflare-style
|
|
2
|
+
CREATE TABLE IF NOT EXISTS analytics (
|
|
3
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4
|
+
day_ts INTEGER NOT NULL, -- Timestamp inizio giornata (Unix epoch)
|
|
5
|
+
metric TEXT NOT NULL, -- 'requests', 'visitors', 'bandwidth_mb'
|
|
6
|
+
value INTEGER DEFAULT 0,
|
|
7
|
+
UNIQUE(day_ts, metric)
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_analytics_day ON analytics(day_ts);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Seed data per Analytics (ultimi 30 giorni)
|
|
2
|
+
-- Questo permette di vedere il trend nella dashboard immediatamente
|
|
3
|
+
|
|
4
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713312000, 'visitors', 120);
|
|
5
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713225600, 'visitors', 145);
|
|
6
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713139200, 'visitors', 98);
|
|
7
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713052800, 'visitors', 210);
|
|
8
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1712966400, 'visitors', 180);
|
|
9
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1712880000, 'visitors', 165);
|
|
10
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1712793600, 'visitors', 190);
|
|
11
|
+
-- Aggiungiamo dati per oggi (simulati)
|
|
12
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (strftime('%s', 'now', 'start of day'), 'visitors', 42);
|
|
13
|
+
|
|
14
|
+
-- Richieste totali
|
|
15
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713312000, 'requests', 1200);
|
|
16
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713225600, 'requests', 1450);
|
|
17
|
+
INSERT OR IGNORE INTO analytics (day_ts, metric, value) VALUES (1713139200, 'requests', 980);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Migrazione: Tabella per statistiche di sistema persistenti (es. storage R2)
|
|
2
|
+
CREATE TABLE IF NOT EXISTS system_stats (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
value TEXT NOT NULL
|
|
5
|
+
);
|
|
6
|
+
|
|
7
|
+
-- Inizializzazione contatore storage (in byte)
|
|
8
|
+
INSERT OR IGNORE INTO system_stats (id, value) VALUES ('total_storage_bytes', '0');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Migrazione: Tabella per il log delle attività (Audit Log)
|
|
2
|
+
CREATE TABLE IF NOT EXISTS activity_logs (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
user_id TEXT NOT NULL,
|
|
5
|
+
user_email TEXT NOT NULL,
|
|
6
|
+
action TEXT NOT NULL, -- 'create' | 'update' | 'delete' | 'upload'
|
|
7
|
+
entity_type TEXT NOT NULL, -- 'content' | 'media'
|
|
8
|
+
entity_id TEXT NOT NULL, -- UUID o Key R2
|
|
9
|
+
entity_slug TEXT, -- Slug del seed (es. 'progetti') o null
|
|
10
|
+
details TEXT, -- JSON con metadati (es. { title: '...' })
|
|
11
|
+
created_at INTEGER DEFAULT (unixepoch())
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
CREATE INDEX IF NOT EXISTS idx_activity_user ON activity_logs(user_id);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_activity_created ON activity_logs(created_at);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Migrazione: Tabella per le notifiche di sistema
|
|
2
|
+
CREATE TABLE IF NOT EXISTS notifications (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
title TEXT NOT NULL,
|
|
5
|
+
message TEXT NOT NULL,
|
|
6
|
+
type TEXT DEFAULT 'info',
|
|
7
|
+
is_read INTEGER DEFAULT 0,
|
|
8
|
+
created_at INTEGER DEFAULT (unixepoch())
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_created ON notifications(created_at);
|
|
12
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_unread ON notifications(is_read);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
-- Generic migration for FTS5 global search
|
|
2
|
+
|
|
3
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS content_fts USING fts5(
|
|
4
|
+
entry_id UNINDEXED, -- PK di content_entries, non cercabile
|
|
5
|
+
schema_slug UNINDEXED, -- per filtrare per tipo senza MATCH
|
|
6
|
+
title, -- campo testo principale
|
|
7
|
+
body, -- campo richtext/text secondario
|
|
8
|
+
tags, -- campo tags (array JSON → stringa piatta)
|
|
9
|
+
status UNINDEXED, -- per filtrare per status
|
|
10
|
+
tokenize = 'unicode61 remove_diacritics 1'
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
-- Backfill dati esistenti (DELETE prima per idempotenza)
|
|
14
|
+
DELETE FROM content_fts;
|
|
15
|
+
INSERT INTO content_fts (entry_id, schema_slug, title, body, tags, status)
|
|
16
|
+
SELECT
|
|
17
|
+
id,
|
|
18
|
+
schema_slug,
|
|
19
|
+
COALESCE(
|
|
20
|
+
json_extract(data, '$.art_01'), -- articoli → title
|
|
21
|
+
json_extract(data, '$.prd_01'), -- prodotti → name
|
|
22
|
+
json_extract(data, '$.pag_01'), -- pagine → title
|
|
23
|
+
json_extract(data, '$.tm_01'), -- team → name
|
|
24
|
+
json_extract(data, '$.tes_02'), -- testimonanze → company
|
|
25
|
+
''
|
|
26
|
+
),
|
|
27
|
+
COALESCE(
|
|
28
|
+
json_extract(data, '$.art_05'), -- articoli → body
|
|
29
|
+
json_extract(data, '$.prd_07'), -- prodotti → description
|
|
30
|
+
json_extract(data, '$.pag_03'), -- pagine → body
|
|
31
|
+
''
|
|
32
|
+
),
|
|
33
|
+
COALESCE(
|
|
34
|
+
json_extract(data, '$.art_04'), -- articoli → tags
|
|
35
|
+
''
|
|
36
|
+
),
|
|
37
|
+
status
|
|
38
|
+
FROM content_entries;
|
|
39
|
+
|
|
40
|
+
-- Sync Triggers
|
|
41
|
+
|
|
42
|
+
-- AFTER INSERT
|
|
43
|
+
CREATE TRIGGER IF NOT EXISTS fts_after_insert
|
|
44
|
+
AFTER INSERT ON content_entries BEGIN
|
|
45
|
+
INSERT INTO content_fts (entry_id, schema_slug, title, body, tags, status)
|
|
46
|
+
VALUES (
|
|
47
|
+
new.id,
|
|
48
|
+
new.schema_slug,
|
|
49
|
+
COALESCE(json_extract(new.data, '$.art_01'), json_extract(new.data, '$.prd_01'),
|
|
50
|
+
json_extract(new.data, '$.pag_01'), json_extract(new.data, '$.tm_01'),
|
|
51
|
+
json_extract(new.data, '$.tes_02'), ''),
|
|
52
|
+
COALESCE(json_extract(new.data, '$.art_05'), json_extract(new.data, '$.prd_07'),
|
|
53
|
+
json_extract(new.data, '$.pag_03'), ''),
|
|
54
|
+
COALESCE(json_extract(new.data, '$.art_04'), ''),
|
|
55
|
+
new.status
|
|
56
|
+
);
|
|
57
|
+
END;
|
|
58
|
+
|
|
59
|
+
-- AFTER UPDATE
|
|
60
|
+
CREATE TRIGGER IF NOT EXISTS fts_after_update
|
|
61
|
+
AFTER UPDATE ON content_entries BEGIN
|
|
62
|
+
DELETE FROM content_fts WHERE entry_id = old.id;
|
|
63
|
+
INSERT INTO content_fts (entry_id, schema_slug, title, body, tags, status)
|
|
64
|
+
VALUES (
|
|
65
|
+
new.id,
|
|
66
|
+
new.schema_slug,
|
|
67
|
+
COALESCE(json_extract(new.data, '$.art_01'), json_extract(new.data, '$.prd_01'),
|
|
68
|
+
json_extract(new.data, '$.pag_01'), json_extract(new.data, '$.tm_01'),
|
|
69
|
+
json_extract(new.data, '$.tes_02'), ''),
|
|
70
|
+
COALESCE(json_extract(new.data, '$.art_05'), json_extract(new.data, '$.prd_07'),
|
|
71
|
+
json_extract(new.data, '$.pag_03'), ''),
|
|
72
|
+
COALESCE(json_extract(new.data, '$.art_04'), ''),
|
|
73
|
+
new.status
|
|
74
|
+
);
|
|
75
|
+
END;
|
|
76
|
+
|
|
77
|
+
-- AFTER DELETE
|
|
78
|
+
CREATE TRIGGER IF NOT EXISTS fts_after_delete
|
|
79
|
+
AFTER DELETE ON content_entries BEGIN
|
|
80
|
+
DELETE FROM content_fts WHERE entry_id = old.id;
|
|
81
|
+
END;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
-- Migration 0017: Seed "clienti" — demo data for Branch.policies
|
|
2
|
+
--
|
|
3
|
+
-- Schema slug : clienti (CLIENTE_SEED)
|
|
4
|
+
-- Branch IDs : clt_01…clt_08
|
|
5
|
+
--
|
|
6
|
+
-- Policy coverage per record:
|
|
7
|
+
-- clt_02 (email) → visibility:masked, search:false, public:false
|
|
8
|
+
-- clt_03 (passwordHash) → privacy:hash stored as sha256hex, visibility:hidden, all other: false
|
|
9
|
+
-- clt_05 (phone) → visibility:masked, filter:false, public:false
|
|
10
|
+
-- clt_06 (internalNote) → visibility:hidden, search:false, public:false
|
|
11
|
+
-- clt_07 (registeredAt) → public:false
|
|
12
|
+
--
|
|
13
|
+
-- sha256 values used (pre-hashed, as the API would store them after applyPrivacy):
|
|
14
|
+
-- "password" → 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
|
|
15
|
+
-- "123456" → 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
|
|
16
|
+
-- "letmein" → 1c8bfe8f801d79745c4631d09fff36c82aa37fc4cce4fc946683d7b336b63032
|
|
17
|
+
-- "abc123" → 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
|
|
18
|
+
-- "qwerty" → 65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5
|
|
19
|
+
|
|
20
|
+
INSERT INTO content_entries (id, schema_slug, slug, status, data, created_at, updated_at) VALUES
|
|
21
|
+
|
|
22
|
+
-- Cliente 1: piano enterprise, attivo — tutti i campi policy popolati
|
|
23
|
+
('clt-0001', 'clienti', 'marco-rossi', 'published',
|
|
24
|
+
json_object(
|
|
25
|
+
'clt_01', 'Marco Rossi',
|
|
26
|
+
'clt_02', 'marco.rossi@acmecorp.it',
|
|
27
|
+
'clt_03', '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8',
|
|
28
|
+
'clt_04', 'enterprise',
|
|
29
|
+
'clt_05', '+39 02 1234 5678',
|
|
30
|
+
'clt_06', 'Cliente storico. Sconto applicato del 20% su rinnovo annuale.',
|
|
31
|
+
'clt_07', '2024-03-15',
|
|
32
|
+
'clt_08', 1
|
|
33
|
+
),
|
|
34
|
+
unixepoch(), unixepoch()),
|
|
35
|
+
|
|
36
|
+
-- Cliente 2: piano pro, attivo
|
|
37
|
+
('clt-0002', 'clienti', 'laura-bianchi', 'published',
|
|
38
|
+
json_object(
|
|
39
|
+
'clt_01', 'Laura Bianchi',
|
|
40
|
+
'clt_02', 'laura.bianchi@studiox.io',
|
|
41
|
+
'clt_03', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92',
|
|
42
|
+
'clt_04', 'pro',
|
|
43
|
+
'clt_05', '+39 06 9876 5432',
|
|
44
|
+
'clt_06', 'Contattare prima del rinnovo per upsell a enterprise.',
|
|
45
|
+
'clt_07', '2025-01-08',
|
|
46
|
+
'clt_08', 1
|
|
47
|
+
),
|
|
48
|
+
unixepoch(), unixepoch()),
|
|
49
|
+
|
|
50
|
+
-- Cliente 3: piano starter, attivo
|
|
51
|
+
('clt-0003', 'clienti', 'davide-ferrari', 'published',
|
|
52
|
+
json_object(
|
|
53
|
+
'clt_01', 'Davide Ferrari',
|
|
54
|
+
'clt_02', 'davide@mediahub.eu',
|
|
55
|
+
'clt_03', '1c8bfe8f801d79745c4631d09fff36c82aa37fc4cce4fc946683d7b336b63032',
|
|
56
|
+
'clt_04', 'starter',
|
|
57
|
+
'clt_05', '+39 011 4567 890',
|
|
58
|
+
'clt_06', 'Ha richiesto supporto per migrazione da WordPress.',
|
|
59
|
+
'clt_07', '2025-06-22',
|
|
60
|
+
'clt_08', 1
|
|
61
|
+
),
|
|
62
|
+
unixepoch(), unixepoch()),
|
|
63
|
+
|
|
64
|
+
-- Cliente 4: piano free, non attivo — dimostra active:false
|
|
65
|
+
('clt-0004', 'clienti', 'giulia-verdi', 'published',
|
|
66
|
+
json_object(
|
|
67
|
+
'clt_01', 'Giulia Verdi',
|
|
68
|
+
'clt_02', 'giulia.verdi@personal.me',
|
|
69
|
+
'clt_03', '6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090',
|
|
70
|
+
'clt_04', 'free',
|
|
71
|
+
'clt_05', '+39 081 3210 987',
|
|
72
|
+
'clt_06', 'Account free scaduto. Inviare offerta upgrade.',
|
|
73
|
+
'clt_07', '2025-09-01',
|
|
74
|
+
'clt_08', 0
|
|
75
|
+
),
|
|
76
|
+
unixepoch(), unixepoch()),
|
|
77
|
+
|
|
78
|
+
-- Cliente 5: piano pro, attivo — phone e internalNote volutamente NULL per testare null safety
|
|
79
|
+
('clt-0005', 'clienti', 'sofia-costa', 'published',
|
|
80
|
+
json_object(
|
|
81
|
+
'clt_01', 'Sofia Costa',
|
|
82
|
+
'clt_02', 'sofia.costa@fittech.com',
|
|
83
|
+
'clt_03', '65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5',
|
|
84
|
+
'clt_04', 'pro',
|
|
85
|
+
'clt_05', null,
|
|
86
|
+
'clt_06', null,
|
|
87
|
+
'clt_07', '2026-01-30',
|
|
88
|
+
'clt_08', 1
|
|
89
|
+
),
|
|
90
|
+
unixepoch(), unixepoch());
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- Rimuove i trigger FTS5 hardcoded che usavano branch ID specifici degli attuali seed di esempio.
|
|
2
|
+
-- La sincronizzazione FTS è ora gestita a livello applicativo in shared/fts-sync.ts,
|
|
3
|
+
-- usando il Botanical Engine per estrarre i campi in modo generico per qualsiasi seed.
|
|
4
|
+
|
|
5
|
+
DROP TRIGGER IF EXISTS fts_after_insert;
|
|
6
|
+
DROP TRIGGER IF EXISTS fts_after_update;
|
|
7
|
+
DROP TRIGGER IF EXISTS fts_after_delete;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Indici compositi su content_entries per ottimizzare le query di lista filtrata.
|
|
2
|
+
-- Tutti gli indici sono agnostici rispetto ai seed: funzionano per qualsiasi
|
|
3
|
+
-- content type che il developer definirà in @beechcms/core.
|
|
4
|
+
|
|
5
|
+
-- Copre il pattern più frequente: WHERE schema_slug = ? AND status = ? ORDER BY created_at DESC
|
|
6
|
+
CREATE INDEX IF NOT EXISTS idx_ce_slug_status_created
|
|
7
|
+
ON content_entries(schema_slug, status, created_at DESC);
|
|
8
|
+
|
|
9
|
+
-- Copre: ORDER BY updated_at (widget "modificati di recente" nel dashboard)
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_ce_slug_updated
|
|
11
|
+
ON content_entries(schema_slug, updated_at DESC);
|
|
12
|
+
|
|
13
|
+
-- Copre: WHERE draft_data IS NOT NULL (filtro bozze pendenti nel dashboard)
|
|
14
|
+
CREATE INDEX IF NOT EXISTS idx_ce_draft_pending
|
|
15
|
+
ON content_entries(schema_slug) WHERE draft_data IS NOT NULL;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Media library: traccia ogni file caricato su R2.
|
|
2
|
+
-- Abilita: media library UI, rilevamento orfani, utilizzo storage per utente.
|
|
3
|
+
-- Il contatore in system_stats rimane per compatibilità; SUM(size_bytes) qui è la fonte canonica.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS media_objects (
|
|
6
|
+
key TEXT PRIMARY KEY, -- chiave R2 (es. "1713600000-img.jpg")
|
|
7
|
+
filename TEXT NOT NULL, -- nome originale pre-sanitize
|
|
8
|
+
mime_type TEXT NOT NULL,
|
|
9
|
+
size_bytes INTEGER NOT NULL,
|
|
10
|
+
uploaded_by TEXT NOT NULL DEFAULT '', -- users.id (soft ref, nessun FK per portabilità D1)
|
|
11
|
+
created_at INTEGER DEFAULT (unixepoch())
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
CREATE INDEX IF NOT EXISTS idx_media_user ON media_objects(uploaded_by);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_media_created ON media_objects(created_at DESC);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- Aggiunge la dimensione seed alle analytics per il tracking del traffico per content type.
|
|
2
|
+
-- Ricrea la tabella per modificare il vincolo UNIQUE da (day_ts, metric)
|
|
3
|
+
-- a (day_ts, metric, seed). seed = '' indica metriche globali (non per-seed).
|
|
4
|
+
-- NOTA: SQLite tratta NULL come distinto da NULL nei UNIQUE index,
|
|
5
|
+
-- quindi si usa stringa vuota come sentinel per le metriche globali.
|
|
6
|
+
|
|
7
|
+
CREATE TABLE IF NOT EXISTS analytics_v2 (
|
|
8
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
day_ts INTEGER NOT NULL,
|
|
10
|
+
metric TEXT NOT NULL,
|
|
11
|
+
seed TEXT NOT NULL DEFAULT '', -- '' = metrica globale, 'articoli' = per-seed
|
|
12
|
+
value INTEGER DEFAULT 0,
|
|
13
|
+
UNIQUE(day_ts, metric, seed)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
INSERT OR IGNORE INTO analytics_v2 (id, day_ts, metric, seed, value)
|
|
17
|
+
SELECT id, day_ts, metric, '', value FROM analytics;
|
|
18
|
+
|
|
19
|
+
DROP TABLE analytics;
|
|
20
|
+
ALTER TABLE analytics_v2 RENAME TO analytics;
|
|
21
|
+
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_analytics_day ON analytics(day_ts);
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_analytics_seed ON analytics(seed, day_ts);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Password reset tokens: single-use, 30-minute TTL, stored hashed (SHA-256)
|
|
2
|
+
CREATE TABLE IF NOT EXISTS password_reset_tokens (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
5
|
+
token_hash TEXT NOT NULL,
|
|
6
|
+
expires_at INTEGER NOT NULL,
|
|
7
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
8
|
+
used_at INTEGER DEFAULT NULL
|
|
9
|
+
);
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_prt_hash ON password_reset_tokens(token_hash);
|
|
11
|
+
CREATE INDEX IF NOT EXISTS idx_prt_user ON password_reset_tokens(user_id);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
-- =============================================================================
|
|
2
|
+
-- Beech CMS v0.4.0 — Doctype Architecture
|
|
3
|
+
--
|
|
4
|
+
-- Breaking change: da singola tabella content_entries (JSON blob) a tabelle
|
|
5
|
+
-- dedicate per Seed con colonne reali tipizzate.
|
|
6
|
+
--
|
|
7
|
+
-- Questa migration:
|
|
8
|
+
-- 1. Rimuove content_entries (i dati di campo migrano a content_{slug})
|
|
9
|
+
-- 2. Rimuove content_fts (sostituita da fts_{slug} per-Seed con trigger)
|
|
10
|
+
-- 3. Crea content_event_log (ex content_entries, solo metadati)
|
|
11
|
+
--
|
|
12
|
+
-- Le tabelle content_{slug} e fts_{slug} NON sono in questa migration.
|
|
13
|
+
-- Vengono create da: beech seed:load
|
|
14
|
+
--
|
|
15
|
+
-- Fresh start (dati non migrati):
|
|
16
|
+
-- npm run db:reset:local → applica tutte le migration
|
|
17
|
+
-- beech seed:load --local → crea tabelle content e FTS per ogni Seed
|
|
18
|
+
-- =============================================================================
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
-- =============================================================================
|
|
22
|
+
-- 1. RIMOZIONE SCHEMA LEGACY
|
|
23
|
+
-- =============================================================================
|
|
24
|
+
|
|
25
|
+
-- Rimuove la vecchia FTS5 globale (sostituita da fts_{slug} per-Seed)
|
|
26
|
+
DROP TABLE IF EXISTS content_fts;
|
|
27
|
+
|
|
28
|
+
-- Rimuove la tabella monolitica (i dati non vengono migrati — fresh start)
|
|
29
|
+
DROP TABLE IF EXISTS content_entries;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
-- =============================================================================
|
|
33
|
+
-- 2. CONTENT EVENT LOG
|
|
34
|
+
-- Tabella leggera per activity feed e stats del dashboard.
|
|
35
|
+
-- NON contiene dati di campo (solo metadati dell'evento CRUD).
|
|
36
|
+
-- Rimpiazza content_entries come sorgente per activity_logs cross-seed.
|
|
37
|
+
-- =============================================================================
|
|
38
|
+
|
|
39
|
+
CREATE TABLE IF NOT EXISTS content_event_log (
|
|
40
|
+
id TEXT NOT NULL PRIMARY KEY, -- UUID v4
|
|
41
|
+
schema_slug TEXT NOT NULL, -- es. "articoli"
|
|
42
|
+
entry_id TEXT NOT NULL, -- ID dell'entry nella tabella content_{slug}
|
|
43
|
+
action TEXT NOT NULL CHECK (action IN ('create', 'update', 'delete')),
|
|
44
|
+
user_id TEXT, -- NULL = azione pubblica (API key)
|
|
45
|
+
details TEXT, -- JSON opzionale: {title, name, ...} per display
|
|
46
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_event_log_schema_slug ON content_event_log(schema_slug);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_event_log_created_at ON content_event_log(created_at DESC);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_event_log_entry_id ON content_event_log(entry_id);
|