gavaengine 0.1.2 → 2.0.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/dist/DashboardSplashTrigger-CRpueuUi.d.ts +154 -0
- package/dist/auth/index.d.ts +42 -0
- package/dist/auth/index.js +12 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/{chunk-D5PTZWTT.js → chunk-4LM22T36.js} +2 -2
- package/dist/chunk-MC3FBYWV.js +534 -0
- package/dist/chunk-MC3FBYWV.js.map +1 -0
- package/dist/chunk-QO42DDRU.js +113 -0
- package/dist/chunk-QO42DDRU.js.map +1 -0
- package/dist/{chunk-3C3AAR3S.js → chunk-YSVQQBBU.js} +474 -50
- package/dist/chunk-YSVQQBBU.js.map +1 -0
- package/dist/components/index.d.ts +64 -132
- package/dist/components/index.js +22 -2
- package/dist/content/index.d.ts +45 -0
- package/dist/content/index.js +38 -0
- package/dist/content/index.js.map +1 -0
- package/dist/handlers/index.d.ts +60 -3
- package/dist/handlers/index.js +477 -126
- package/dist/handlers/index.js.map +1 -1
- package/dist/i18n/index.d.ts +114 -0
- package/dist/i18n/index.js +249 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/{index-B1ZYC5TP.d.ts → index-CCsSC4nF.d.ts} +119 -2
- package/dist/index.d.ts +45 -7
- package/dist/index.js +226 -39
- package/dist/index.js.map +1 -1
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.js +2 -2
- package/dist/types-X07o_zKf.d.ts +198 -0
- package/dist/types-d8-k_4dN.d.ts +19 -0
- package/package.json +16 -1
- package/dist/chunk-3C3AAR3S.js.map +0 -1
- package/dist/chunk-BVLJYZ6T.js +0 -252
- package/dist/chunk-BVLJYZ6T.js.map +0 -1
- package/dist/types-BZgSeTU8.d.ts +0 -101
- /package/dist/{chunk-D5PTZWTT.js.map → chunk-4LM22T36.js.map} +0 -0
package/dist/handlers/index.js
CHANGED
|
@@ -1,4 +1,317 @@
|
|
|
1
|
+
// src/i18n/it.ts
|
|
2
|
+
var it = {
|
|
3
|
+
content: {
|
|
4
|
+
articles: "Articoli",
|
|
5
|
+
newArticle: "Nuovo articolo",
|
|
6
|
+
titlePlaceholder: "Titolo dell'articolo",
|
|
7
|
+
excerptPlaceholder: "Breve descrizione dell'articolo...",
|
|
8
|
+
slugPlaceholder: "slug-articolo",
|
|
9
|
+
authorPlaceholder: "Nome dell'autore",
|
|
10
|
+
category: "Categoria",
|
|
11
|
+
selectCategory: "Seleziona categoria",
|
|
12
|
+
excerpt: "Estratto",
|
|
13
|
+
author: "Autore",
|
|
14
|
+
slugUrl: "Slug URL",
|
|
15
|
+
noArticles: "Nessun articolo.",
|
|
16
|
+
noArticlesSearch: "Nessun articolo trovato.",
|
|
17
|
+
searchArticles: "Cerca articoli...",
|
|
18
|
+
coverImageLabel: "Immagine di copertina",
|
|
19
|
+
coverImageHint: "Scegli dalla libreria o carica un nuovo file",
|
|
20
|
+
viewArticle: "Vedi articolo pubblicato",
|
|
21
|
+
untitled: "Senza titolo"
|
|
22
|
+
},
|
|
23
|
+
editor: {
|
|
24
|
+
publish: "Pubblica",
|
|
25
|
+
unpublish: "Ritira",
|
|
26
|
+
saveDraft: "Salva bozza",
|
|
27
|
+
revisions: "Cronologia",
|
|
28
|
+
saving: "Salvando...",
|
|
29
|
+
saved: "Salvato",
|
|
30
|
+
saveError: "Errore nel salvataggio",
|
|
31
|
+
noRevisions: "Nessuna revisione salvata.",
|
|
32
|
+
restore: "Ripristina",
|
|
33
|
+
restoreConfirm: "Ripristinare questa revisione? Lo stato attuale verr\xE0 salvato prima del ripristino.",
|
|
34
|
+
beforeRestore: "Prima del ripristino",
|
|
35
|
+
publishedNote: "Pubblicato",
|
|
36
|
+
preview: "Anteprima",
|
|
37
|
+
placeholder: "Inizia a scrivere il tuo articolo..."
|
|
38
|
+
},
|
|
39
|
+
media: {
|
|
40
|
+
media: "Media",
|
|
41
|
+
noMedia: "Nessun file caricato.",
|
|
42
|
+
noMediaSearch: "Nessun file trovato.",
|
|
43
|
+
chooseFile: "Scegli file",
|
|
44
|
+
dragHint: "Trascina un'immagine qui oppure",
|
|
45
|
+
uploadHint: "JPEG, PNG, WebP, GIF (max 5MB)",
|
|
46
|
+
mediaLibrary: "Libreria media",
|
|
47
|
+
uploadNew: "Carica nuovo",
|
|
48
|
+
searchFiles: "Cerca file...",
|
|
49
|
+
selectImage: "Seleziona immagine",
|
|
50
|
+
noImages: "Nessuna immagine nella libreria.",
|
|
51
|
+
noImagesSearch: "Nessuna immagine trovata.",
|
|
52
|
+
copyUrl: "Copia URL",
|
|
53
|
+
editImage: "Modifica immagine",
|
|
54
|
+
restoreOriginal: "Ripristina originale",
|
|
55
|
+
freeAspect: "Libero"
|
|
56
|
+
},
|
|
57
|
+
users: {
|
|
58
|
+
users: "Utenti",
|
|
59
|
+
name: "Nome",
|
|
60
|
+
email: "Email",
|
|
61
|
+
password: "Password",
|
|
62
|
+
passwordEditHint: " (lascia vuoto per non modificarla)",
|
|
63
|
+
role: "Ruolo",
|
|
64
|
+
createdAt: "Creato il",
|
|
65
|
+
actions: "Azioni",
|
|
66
|
+
createUser: "Crea utente",
|
|
67
|
+
unauthorized: "Non autorizzato",
|
|
68
|
+
notAuthenticated: "Non autenticato",
|
|
69
|
+
allFieldsRequired: "Tutti i campi sono obbligatori.",
|
|
70
|
+
passwordMinLength: "La password deve avere almeno 6 caratteri.",
|
|
71
|
+
emailExists: "Esiste gi\xE0 un utente con questa email.",
|
|
72
|
+
invalidRole: "Ruolo non valido.",
|
|
73
|
+
cannotDeleteSelf: "Non puoi eliminare il tuo stesso account."
|
|
74
|
+
},
|
|
75
|
+
common: {
|
|
76
|
+
statistics: "Statistiche",
|
|
77
|
+
settings: "Impostazioni",
|
|
78
|
+
delete: "Elimina",
|
|
79
|
+
edit: "Modifica",
|
|
80
|
+
search: "Cerca",
|
|
81
|
+
draft: "Bozza",
|
|
82
|
+
published: "Pubblicato",
|
|
83
|
+
all: "Tutti",
|
|
84
|
+
drafts: "Bozze",
|
|
85
|
+
loading: "Caricamento...",
|
|
86
|
+
confirm: "Conferma",
|
|
87
|
+
cancel: "Annulla",
|
|
88
|
+
apply: "Applica",
|
|
89
|
+
change: "Cambia",
|
|
90
|
+
logout: "Esci",
|
|
91
|
+
saveChanges: "Salva modifiche",
|
|
92
|
+
updated: "Aggiornato",
|
|
93
|
+
status: "Stato",
|
|
94
|
+
title: "Titolo",
|
|
95
|
+
deleteConfirm: (title) => `Eliminare "${title || "Senza titolo"}"?`,
|
|
96
|
+
unpublishConfirm: (title) => `Ritirare "${title || "Senza titolo"}"? L'articolo torner\xE0 in bozza.`,
|
|
97
|
+
deleteUserConfirm: (name) => `Sei sicuro di voler eliminare l'utente "${name}"?`,
|
|
98
|
+
totalArticles: (count) => `${count} articol${count === 1 ? "o" : "i"} totali`,
|
|
99
|
+
totalFiles: (count) => `${count} file caricati`
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/i18n/en.ts
|
|
104
|
+
var en = {
|
|
105
|
+
content: {
|
|
106
|
+
articles: "Articles",
|
|
107
|
+
newArticle: "New article",
|
|
108
|
+
titlePlaceholder: "Article title",
|
|
109
|
+
excerptPlaceholder: "Brief description of the article...",
|
|
110
|
+
slugPlaceholder: "article-slug",
|
|
111
|
+
authorPlaceholder: "Author name",
|
|
112
|
+
category: "Category",
|
|
113
|
+
selectCategory: "Select category",
|
|
114
|
+
excerpt: "Excerpt",
|
|
115
|
+
author: "Author",
|
|
116
|
+
slugUrl: "URL Slug",
|
|
117
|
+
noArticles: "No articles.",
|
|
118
|
+
noArticlesSearch: "No articles found.",
|
|
119
|
+
searchArticles: "Search articles...",
|
|
120
|
+
coverImageLabel: "Cover image",
|
|
121
|
+
coverImageHint: "Choose from library or upload a new file",
|
|
122
|
+
viewArticle: "View published article",
|
|
123
|
+
untitled: "Untitled"
|
|
124
|
+
},
|
|
125
|
+
editor: {
|
|
126
|
+
publish: "Publish",
|
|
127
|
+
unpublish: "Unpublish",
|
|
128
|
+
saveDraft: "Save draft",
|
|
129
|
+
revisions: "History",
|
|
130
|
+
saving: "Saving...",
|
|
131
|
+
saved: "Saved",
|
|
132
|
+
saveError: "Error saving",
|
|
133
|
+
noRevisions: "No revisions saved.",
|
|
134
|
+
restore: "Restore",
|
|
135
|
+
restoreConfirm: "Restore this revision? The current state will be saved before restoring.",
|
|
136
|
+
beforeRestore: "Before restore",
|
|
137
|
+
publishedNote: "Published",
|
|
138
|
+
preview: "Preview",
|
|
139
|
+
placeholder: "Start writing your article..."
|
|
140
|
+
},
|
|
141
|
+
media: {
|
|
142
|
+
media: "Media",
|
|
143
|
+
noMedia: "No files uploaded.",
|
|
144
|
+
noMediaSearch: "No files found.",
|
|
145
|
+
chooseFile: "Choose file",
|
|
146
|
+
dragHint: "Drag an image here or",
|
|
147
|
+
uploadHint: "JPEG, PNG, WebP, GIF (max 5MB)",
|
|
148
|
+
mediaLibrary: "Media library",
|
|
149
|
+
uploadNew: "Upload new",
|
|
150
|
+
searchFiles: "Search files...",
|
|
151
|
+
selectImage: "Select image",
|
|
152
|
+
noImages: "No images in library.",
|
|
153
|
+
noImagesSearch: "No images found.",
|
|
154
|
+
copyUrl: "Copy URL",
|
|
155
|
+
editImage: "Edit image",
|
|
156
|
+
restoreOriginal: "Restore original",
|
|
157
|
+
freeAspect: "Free"
|
|
158
|
+
},
|
|
159
|
+
users: {
|
|
160
|
+
users: "Users",
|
|
161
|
+
name: "Name",
|
|
162
|
+
email: "Email",
|
|
163
|
+
password: "Password",
|
|
164
|
+
passwordEditHint: " (leave blank to keep current)",
|
|
165
|
+
role: "Role",
|
|
166
|
+
createdAt: "Created at",
|
|
167
|
+
actions: "Actions",
|
|
168
|
+
createUser: "Create user",
|
|
169
|
+
unauthorized: "Unauthorized",
|
|
170
|
+
notAuthenticated: "Not authenticated",
|
|
171
|
+
allFieldsRequired: "All fields are required.",
|
|
172
|
+
passwordMinLength: "Password must be at least 6 characters.",
|
|
173
|
+
emailExists: "A user with this email already exists.",
|
|
174
|
+
invalidRole: "Invalid role.",
|
|
175
|
+
cannotDeleteSelf: "You cannot delete your own account."
|
|
176
|
+
},
|
|
177
|
+
common: {
|
|
178
|
+
statistics: "Statistics",
|
|
179
|
+
settings: "Settings",
|
|
180
|
+
delete: "Delete",
|
|
181
|
+
edit: "Edit",
|
|
182
|
+
search: "Search",
|
|
183
|
+
draft: "Draft",
|
|
184
|
+
published: "Published",
|
|
185
|
+
all: "All",
|
|
186
|
+
drafts: "Drafts",
|
|
187
|
+
loading: "Loading...",
|
|
188
|
+
confirm: "Confirm",
|
|
189
|
+
cancel: "Cancel",
|
|
190
|
+
apply: "Apply",
|
|
191
|
+
change: "Change",
|
|
192
|
+
logout: "Logout",
|
|
193
|
+
saveChanges: "Save changes",
|
|
194
|
+
updated: "Updated",
|
|
195
|
+
status: "Status",
|
|
196
|
+
title: "Title",
|
|
197
|
+
deleteConfirm: (title) => `Delete "${title || "Untitled"}"?`,
|
|
198
|
+
unpublishConfirm: (title) => `Unpublish "${title || "Untitled"}"? The article will go back to draft.`,
|
|
199
|
+
deleteUserConfirm: (name) => `Are you sure you want to delete user "${name}"?`,
|
|
200
|
+
totalArticles: (count) => `${count} total article${count === 1 ? "" : "s"}`,
|
|
201
|
+
totalFiles: (count) => `${count} uploaded file${count === 1 ? "" : "s"}`
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// src/i18n/index.ts
|
|
206
|
+
var builtinLocales = { it, en };
|
|
207
|
+
function loadLocale(locale) {
|
|
208
|
+
const found = builtinLocales[locale];
|
|
209
|
+
if (!found) {
|
|
210
|
+
throw new Error(
|
|
211
|
+
`Locale "${locale}" not found. Available: ${Object.keys(builtinLocales).join(", ")}`
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
return found;
|
|
215
|
+
}
|
|
216
|
+
|
|
1
217
|
// src/config.ts
|
|
218
|
+
function localeToStrings(locale) {
|
|
219
|
+
return {
|
|
220
|
+
// content
|
|
221
|
+
articles: locale.content.articles,
|
|
222
|
+
newArticle: locale.content.newArticle,
|
|
223
|
+
titlePlaceholder: locale.content.titlePlaceholder,
|
|
224
|
+
excerptPlaceholder: locale.content.excerptPlaceholder,
|
|
225
|
+
slugPlaceholder: locale.content.slugPlaceholder,
|
|
226
|
+
authorPlaceholder: locale.content.authorPlaceholder,
|
|
227
|
+
category: locale.content.category,
|
|
228
|
+
selectCategory: locale.content.selectCategory,
|
|
229
|
+
excerpt: locale.content.excerpt,
|
|
230
|
+
author: locale.content.author,
|
|
231
|
+
slugUrl: locale.content.slugUrl,
|
|
232
|
+
noArticles: locale.content.noArticles,
|
|
233
|
+
noArticlesSearch: locale.content.noArticlesSearch,
|
|
234
|
+
searchArticles: locale.content.searchArticles,
|
|
235
|
+
coverImageLabel: locale.content.coverImageLabel,
|
|
236
|
+
coverImageHint: locale.content.coverImageHint,
|
|
237
|
+
viewArticle: locale.content.viewArticle,
|
|
238
|
+
untitled: locale.content.untitled,
|
|
239
|
+
// editor
|
|
240
|
+
publish: locale.editor.publish,
|
|
241
|
+
unpublish: locale.editor.unpublish,
|
|
242
|
+
saveDraft: locale.editor.saveDraft,
|
|
243
|
+
revisions: locale.editor.revisions,
|
|
244
|
+
saving: locale.editor.saving,
|
|
245
|
+
saved: locale.editor.saved,
|
|
246
|
+
saveError: locale.editor.saveError,
|
|
247
|
+
noRevisions: locale.editor.noRevisions,
|
|
248
|
+
restore: locale.editor.restore,
|
|
249
|
+
restoreConfirm: locale.editor.restoreConfirm,
|
|
250
|
+
beforeRestore: locale.editor.beforeRestore,
|
|
251
|
+
publishedNote: locale.editor.publishedNote,
|
|
252
|
+
preview: locale.editor.preview,
|
|
253
|
+
// media
|
|
254
|
+
media: locale.media.media,
|
|
255
|
+
noMedia: locale.media.noMedia,
|
|
256
|
+
noMediaSearch: locale.media.noMediaSearch,
|
|
257
|
+
chooseFile: locale.media.chooseFile,
|
|
258
|
+
dragHint: locale.media.dragHint,
|
|
259
|
+
uploadHint: locale.media.uploadHint,
|
|
260
|
+
mediaLibrary: locale.media.mediaLibrary,
|
|
261
|
+
uploadNew: locale.media.uploadNew,
|
|
262
|
+
searchFiles: locale.media.searchFiles,
|
|
263
|
+
selectImage: locale.media.selectImage,
|
|
264
|
+
noImages: locale.media.noImages,
|
|
265
|
+
noImagesSearch: locale.media.noImagesSearch,
|
|
266
|
+
copyUrl: locale.media.copyUrl,
|
|
267
|
+
editImage: locale.media.editImage,
|
|
268
|
+
restoreOriginal: locale.media.restoreOriginal,
|
|
269
|
+
freeAspect: locale.media.freeAspect,
|
|
270
|
+
// users
|
|
271
|
+
users: locale.users.users,
|
|
272
|
+
name: locale.users.name,
|
|
273
|
+
email: locale.users.email,
|
|
274
|
+
password: locale.users.password,
|
|
275
|
+
passwordEditHint: locale.users.passwordEditHint,
|
|
276
|
+
role: locale.users.role,
|
|
277
|
+
createdAt: locale.users.createdAt,
|
|
278
|
+
actions: locale.users.actions,
|
|
279
|
+
createUser: locale.users.createUser,
|
|
280
|
+
unauthorized: locale.users.unauthorized,
|
|
281
|
+
notAuthenticated: locale.users.notAuthenticated,
|
|
282
|
+
allFieldsRequired: locale.users.allFieldsRequired,
|
|
283
|
+
passwordMinLength: locale.users.passwordMinLength,
|
|
284
|
+
emailExists: locale.users.emailExists,
|
|
285
|
+
invalidRole: locale.users.invalidRole,
|
|
286
|
+
cannotDeleteSelf: locale.users.cannotDeleteSelf,
|
|
287
|
+
// common
|
|
288
|
+
statistics: locale.common.statistics,
|
|
289
|
+
settings: locale.common.settings,
|
|
290
|
+
delete: locale.common.delete,
|
|
291
|
+
edit: locale.common.edit,
|
|
292
|
+
search: locale.common.search,
|
|
293
|
+
draft: locale.common.draft,
|
|
294
|
+
published: locale.common.published,
|
|
295
|
+
all: locale.common.all,
|
|
296
|
+
drafts: locale.common.drafts,
|
|
297
|
+
loading: locale.common.loading,
|
|
298
|
+
confirm: locale.common.confirm,
|
|
299
|
+
cancel: locale.common.cancel,
|
|
300
|
+
apply: locale.common.apply,
|
|
301
|
+
change: locale.common.change,
|
|
302
|
+
logout: locale.common.logout,
|
|
303
|
+
saveChanges: locale.common.saveChanges,
|
|
304
|
+
updated: locale.common.updated,
|
|
305
|
+
status: locale.common.status,
|
|
306
|
+
title: locale.common.title,
|
|
307
|
+
deleteConfirm: locale.common.deleteConfirm,
|
|
308
|
+
unpublishConfirm: locale.common.unpublishConfirm,
|
|
309
|
+
deleteUserConfirm: locale.common.deleteUserConfirm,
|
|
310
|
+
totalArticles: locale.common.totalArticles,
|
|
311
|
+
totalFiles: locale.common.totalFiles
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
var DEFAULT_STRINGS = localeToStrings(loadLocale("it"));
|
|
2
315
|
var DEFAULT_CONFIG = {
|
|
3
316
|
branding: {
|
|
4
317
|
name: "GavaEngine"
|
|
@@ -15,6 +328,18 @@ var DEFAULT_CONFIG = {
|
|
|
15
328
|
canPublish: (role) => role === "admin" || role === "redattore",
|
|
16
329
|
adminRole: "admin"
|
|
17
330
|
},
|
|
331
|
+
statuses: {
|
|
332
|
+
draft: "bozza",
|
|
333
|
+
published: "pubblicato"
|
|
334
|
+
},
|
|
335
|
+
locale: "it",
|
|
336
|
+
models: {
|
|
337
|
+
article: "article",
|
|
338
|
+
articleRevision: "articleRevision",
|
|
339
|
+
articleView: "articleView",
|
|
340
|
+
media: "media",
|
|
341
|
+
user: "user"
|
|
342
|
+
},
|
|
18
343
|
categories: [
|
|
19
344
|
"Cultura ed Intercultura",
|
|
20
345
|
"Fatti ed Eventi",
|
|
@@ -49,95 +374,7 @@ var DEFAULT_CONFIG = {
|
|
|
49
374
|
login: "/login",
|
|
50
375
|
home: "/"
|
|
51
376
|
},
|
|
52
|
-
strings:
|
|
53
|
-
articles: "Articoli",
|
|
54
|
-
newArticle: "Nuovo articolo",
|
|
55
|
-
media: "Media",
|
|
56
|
-
users: "Utenti",
|
|
57
|
-
statistics: "Statistiche",
|
|
58
|
-
settings: "Impostazioni",
|
|
59
|
-
revisions: "Cronologia",
|
|
60
|
-
publish: "Pubblica",
|
|
61
|
-
unpublish: "Ritira",
|
|
62
|
-
saveDraft: "Salva bozza",
|
|
63
|
-
delete: "Elimina",
|
|
64
|
-
edit: "Modifica",
|
|
65
|
-
search: "Cerca",
|
|
66
|
-
titlePlaceholder: "Titolo dell'articolo",
|
|
67
|
-
excerptPlaceholder: "Breve descrizione dell'articolo...",
|
|
68
|
-
slugPlaceholder: "slug-articolo",
|
|
69
|
-
authorPlaceholder: "Nome dell'autore",
|
|
70
|
-
category: "Categoria",
|
|
71
|
-
selectCategory: "Seleziona categoria",
|
|
72
|
-
excerpt: "Estratto",
|
|
73
|
-
author: "Autore",
|
|
74
|
-
slugUrl: "Slug URL",
|
|
75
|
-
draft: "Bozza",
|
|
76
|
-
published: "Pubblicato",
|
|
77
|
-
all: "Tutti",
|
|
78
|
-
drafts: "Bozze",
|
|
79
|
-
saving: "Salvando...",
|
|
80
|
-
saved: "Salvato",
|
|
81
|
-
saveError: "Errore nel salvataggio",
|
|
82
|
-
noArticles: "Nessun articolo.",
|
|
83
|
-
noArticlesSearch: "Nessun articolo trovato.",
|
|
84
|
-
noMedia: "Nessun file caricato.",
|
|
85
|
-
noMediaSearch: "Nessun file trovato.",
|
|
86
|
-
noRevisions: "Nessuna revisione salvata.",
|
|
87
|
-
loading: "Caricamento...",
|
|
88
|
-
confirm: "Conferma",
|
|
89
|
-
cancel: "Annulla",
|
|
90
|
-
apply: "Applica",
|
|
91
|
-
change: "Cambia",
|
|
92
|
-
logout: "Esci",
|
|
93
|
-
viewArticle: "Vedi articolo pubblicato",
|
|
94
|
-
preview: "Anteprima",
|
|
95
|
-
restore: "Ripristina",
|
|
96
|
-
restoreConfirm: "Ripristinare questa revisione? Lo stato attuale verr\xE0 salvato prima del ripristino.",
|
|
97
|
-
beforeRestore: "Prima del ripristino",
|
|
98
|
-
publishedNote: "Pubblicato",
|
|
99
|
-
deleteConfirm: (title) => `Eliminare "${title || "Senza titolo"}"?`,
|
|
100
|
-
unpublishConfirm: (title) => `Ritirare "${title || "Senza titolo"}"? L'articolo torner\xE0 in bozza.`,
|
|
101
|
-
deleteUserConfirm: (name) => `Sei sicuro di voler eliminare l'utente "${name}"?`,
|
|
102
|
-
totalArticles: (count) => `${count} articol${count === 1 ? "o" : "i"} totali`,
|
|
103
|
-
totalFiles: (count) => `${count} file caricati`,
|
|
104
|
-
coverImageLabel: "Immagine di copertina",
|
|
105
|
-
coverImageHint: "Scegli dalla libreria o carica un nuovo file",
|
|
106
|
-
chooseFile: "Scegli file",
|
|
107
|
-
dragHint: "Trascina un'immagine qui oppure",
|
|
108
|
-
uploadHint: "JPEG, PNG, WebP, GIF (max 5MB)",
|
|
109
|
-
mediaLibrary: "Libreria media",
|
|
110
|
-
uploadNew: "Carica nuovo",
|
|
111
|
-
searchFiles: "Cerca file...",
|
|
112
|
-
searchArticles: "Cerca articoli...",
|
|
113
|
-
selectImage: "Seleziona immagine",
|
|
114
|
-
noImages: "Nessuna immagine nella libreria.",
|
|
115
|
-
noImagesSearch: "Nessuna immagine trovata.",
|
|
116
|
-
copyUrl: "Copia URL",
|
|
117
|
-
editImage: "Modifica immagine",
|
|
118
|
-
restoreOriginal: "Ripristina originale",
|
|
119
|
-
freeAspect: "Libero",
|
|
120
|
-
unauthorized: "Non autorizzato",
|
|
121
|
-
notAuthenticated: "Non autenticato",
|
|
122
|
-
allFieldsRequired: "Tutti i campi sono obbligatori.",
|
|
123
|
-
passwordMinLength: "La password deve avere almeno 6 caratteri.",
|
|
124
|
-
emailExists: "Esiste gi\xE0 un utente con questa email.",
|
|
125
|
-
invalidRole: "Ruolo non valido.",
|
|
126
|
-
cannotDeleteSelf: "Non puoi eliminare il tuo stesso account.",
|
|
127
|
-
name: "Nome",
|
|
128
|
-
email: "Email",
|
|
129
|
-
password: "Password",
|
|
130
|
-
passwordEditHint: " (lascia vuoto per non modificarla)",
|
|
131
|
-
role: "Ruolo",
|
|
132
|
-
createdAt: "Creato il",
|
|
133
|
-
actions: "Azioni",
|
|
134
|
-
createUser: "Crea utente",
|
|
135
|
-
saveChanges: "Salva modifiche",
|
|
136
|
-
updated: "Aggiornato",
|
|
137
|
-
status: "Stato",
|
|
138
|
-
title: "Titolo",
|
|
139
|
-
untitled: "Senza titolo"
|
|
140
|
-
}
|
|
377
|
+
strings: DEFAULT_STRINGS
|
|
141
378
|
};
|
|
142
379
|
function deepMerge(target, source) {
|
|
143
380
|
const result = { ...target };
|
|
@@ -156,32 +393,47 @@ function deepMerge(target, source) {
|
|
|
156
393
|
return result;
|
|
157
394
|
}
|
|
158
395
|
function defineConfig(overrides = {}) {
|
|
159
|
-
|
|
396
|
+
const locale = overrides.locale ?? DEFAULT_CONFIG.locale;
|
|
397
|
+
const baseStrings = localeToStrings(loadLocale(locale));
|
|
398
|
+
const configWithLocale = {
|
|
399
|
+
...DEFAULT_CONFIG,
|
|
400
|
+
strings: baseStrings
|
|
401
|
+
};
|
|
402
|
+
if (!overrides.editor?.placeholder) {
|
|
403
|
+
const localeData = loadLocale(locale);
|
|
404
|
+
configWithLocale.editor = {
|
|
405
|
+
...configWithLocale.editor,
|
|
406
|
+
placeholder: localeData.editor.placeholder
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return deepMerge(configWithLocale, overrides);
|
|
160
410
|
}
|
|
161
411
|
|
|
162
412
|
// src/handlers/revisions.ts
|
|
163
413
|
function createRevisionHandlers(prisma, config) {
|
|
164
414
|
const throttleMs = config.editor.revisionThrottleMinutes * 60 * 1e3;
|
|
415
|
+
const articleModel = config.models.article;
|
|
416
|
+
const revisionModel = config.models.articleRevision;
|
|
165
417
|
return {
|
|
166
418
|
async getRevisions(articleId) {
|
|
167
|
-
return prisma.
|
|
419
|
+
return prisma[revisionModel].findMany({
|
|
168
420
|
where: { articleId },
|
|
169
421
|
include: { editor: { select: { name: true } } },
|
|
170
422
|
orderBy: { createdAt: "desc" }
|
|
171
423
|
});
|
|
172
424
|
},
|
|
173
425
|
async restoreRevision(articleId, revisionId, editorId) {
|
|
174
|
-
const article = await prisma.
|
|
426
|
+
const article = await prisma[articleModel].findUnique({
|
|
175
427
|
where: { id: articleId }
|
|
176
428
|
});
|
|
177
429
|
if (!article) throw new Error("Article not found");
|
|
178
|
-
const revision = await prisma.
|
|
430
|
+
const revision = await prisma[revisionModel].findUnique({
|
|
179
431
|
where: { id: revisionId }
|
|
180
432
|
});
|
|
181
433
|
if (!revision || revision.articleId !== articleId) {
|
|
182
434
|
throw new Error("Revision not found");
|
|
183
435
|
}
|
|
184
|
-
await prisma.
|
|
436
|
+
await prisma[revisionModel].create({
|
|
185
437
|
data: {
|
|
186
438
|
articleId,
|
|
187
439
|
title: article.title,
|
|
@@ -193,7 +445,7 @@ function createRevisionHandlers(prisma, config) {
|
|
|
193
445
|
note: config.strings.beforeRestore
|
|
194
446
|
}
|
|
195
447
|
});
|
|
196
|
-
await prisma.
|
|
448
|
+
await prisma[articleModel].update({
|
|
197
449
|
where: { id: articleId },
|
|
198
450
|
data: {
|
|
199
451
|
title: revision.title,
|
|
@@ -207,17 +459,17 @@ function createRevisionHandlers(prisma, config) {
|
|
|
207
459
|
return { success: true };
|
|
208
460
|
},
|
|
209
461
|
async createRevisionSnapshot(articleId, editorId, note = "") {
|
|
210
|
-
const article = await prisma.
|
|
462
|
+
const article = await prisma[articleModel].findUnique({
|
|
211
463
|
where: { id: articleId }
|
|
212
464
|
});
|
|
213
465
|
if (!article) return;
|
|
214
466
|
const threshold = new Date(Date.now() - throttleMs);
|
|
215
|
-
const recent = await prisma.
|
|
467
|
+
const recent = await prisma[revisionModel].findFirst({
|
|
216
468
|
where: { articleId, createdAt: { gte: threshold } },
|
|
217
469
|
orderBy: { createdAt: "desc" }
|
|
218
470
|
});
|
|
219
471
|
if (recent && !note) return;
|
|
220
|
-
await prisma.
|
|
472
|
+
await prisma[revisionModel].create({
|
|
221
473
|
data: {
|
|
222
474
|
articleId,
|
|
223
475
|
title: article.title,
|
|
@@ -236,19 +488,20 @@ function createRevisionHandlers(prisma, config) {
|
|
|
236
488
|
// src/handlers/articles.ts
|
|
237
489
|
function createArticleHandlers(prisma, config) {
|
|
238
490
|
const revisionHandlers = createRevisionHandlers(prisma, config);
|
|
491
|
+
const articleModel = config.models.article;
|
|
239
492
|
return {
|
|
240
493
|
async getArticles() {
|
|
241
|
-
return prisma.
|
|
494
|
+
return prisma[articleModel].findMany({
|
|
242
495
|
orderBy: { updatedAt: "desc" }
|
|
243
496
|
});
|
|
244
497
|
},
|
|
245
498
|
async getArticleById(id) {
|
|
246
|
-
return prisma.
|
|
499
|
+
return prisma[articleModel].findUnique({
|
|
247
500
|
where: { id }
|
|
248
501
|
});
|
|
249
502
|
},
|
|
250
503
|
async createArticle(authorName) {
|
|
251
|
-
const article = await prisma.
|
|
504
|
+
const article = await prisma[articleModel].create({
|
|
252
505
|
data: {
|
|
253
506
|
authorName
|
|
254
507
|
}
|
|
@@ -256,23 +509,23 @@ function createArticleHandlers(prisma, config) {
|
|
|
256
509
|
return article.id;
|
|
257
510
|
},
|
|
258
511
|
async updateArticle(userId, id, data) {
|
|
259
|
-
const article = await prisma.
|
|
512
|
+
const article = await prisma[articleModel].findUnique({ where: { id } });
|
|
260
513
|
if (!article) throw new Error("Article not found");
|
|
261
514
|
await revisionHandlers.createRevisionSnapshot(id, userId);
|
|
262
|
-
await prisma.
|
|
515
|
+
await prisma[articleModel].update({
|
|
263
516
|
where: { id },
|
|
264
517
|
data: { ...data, updatedAt: /* @__PURE__ */ new Date() }
|
|
265
518
|
});
|
|
266
519
|
return { success: true };
|
|
267
520
|
},
|
|
268
521
|
async deleteArticle(id) {
|
|
269
|
-
const article = await prisma.
|
|
522
|
+
const article = await prisma[articleModel].findUnique({ where: { id } });
|
|
270
523
|
if (!article) throw new Error("Article not found");
|
|
271
|
-
await prisma.
|
|
524
|
+
await prisma[articleModel].delete({ where: { id } });
|
|
272
525
|
return { success: true };
|
|
273
526
|
},
|
|
274
527
|
async publishArticle(userId, id) {
|
|
275
|
-
const article = await prisma.
|
|
528
|
+
const article = await prisma[articleModel].findUnique({ where: { id } });
|
|
276
529
|
if (!article) throw new Error("Article not found");
|
|
277
530
|
if (!article.title || !article.slug) {
|
|
278
531
|
throw new Error(
|
|
@@ -284,22 +537,22 @@ function createArticleHandlers(prisma, config) {
|
|
|
284
537
|
userId,
|
|
285
538
|
config.strings.publishedNote
|
|
286
539
|
);
|
|
287
|
-
await prisma.
|
|
540
|
+
await prisma[articleModel].update({
|
|
288
541
|
where: { id },
|
|
289
542
|
data: {
|
|
290
|
-
status:
|
|
543
|
+
status: config.statuses.published,
|
|
291
544
|
publishedAt: /* @__PURE__ */ new Date()
|
|
292
545
|
}
|
|
293
546
|
});
|
|
294
547
|
return { success: true };
|
|
295
548
|
},
|
|
296
549
|
async unpublishArticle(id) {
|
|
297
|
-
const article = await prisma.
|
|
550
|
+
const article = await prisma[articleModel].findUnique({ where: { id } });
|
|
298
551
|
if (!article) throw new Error("Article not found");
|
|
299
|
-
await prisma.
|
|
552
|
+
await prisma[articleModel].update({
|
|
300
553
|
where: { id },
|
|
301
554
|
data: {
|
|
302
|
-
status:
|
|
555
|
+
status: config.statuses.draft,
|
|
303
556
|
publishedAt: null
|
|
304
557
|
}
|
|
305
558
|
});
|
|
@@ -311,9 +564,10 @@ function createArticleHandlers(prisma, config) {
|
|
|
311
564
|
// src/handlers/users.ts
|
|
312
565
|
import bcrypt from "bcryptjs";
|
|
313
566
|
function createUserHandlers(prisma, config) {
|
|
567
|
+
const userModel = config.models.user;
|
|
314
568
|
return {
|
|
315
569
|
async getUsers() {
|
|
316
|
-
return prisma.
|
|
570
|
+
return prisma[userModel].findMany({
|
|
317
571
|
select: {
|
|
318
572
|
id: true,
|
|
319
573
|
name: true,
|
|
@@ -325,7 +579,7 @@ function createUserHandlers(prisma, config) {
|
|
|
325
579
|
});
|
|
326
580
|
},
|
|
327
581
|
async getUserById(id) {
|
|
328
|
-
return prisma.
|
|
582
|
+
return prisma[userModel].findUnique({
|
|
329
583
|
where: { id },
|
|
330
584
|
select: {
|
|
331
585
|
id: true,
|
|
@@ -349,12 +603,12 @@ function createUserHandlers(prisma, config) {
|
|
|
349
603
|
if (password.length < 6) {
|
|
350
604
|
return { error: config.strings.passwordMinLength };
|
|
351
605
|
}
|
|
352
|
-
const existing = await prisma.
|
|
606
|
+
const existing = await prisma[userModel].findUnique({ where: { email } });
|
|
353
607
|
if (existing) {
|
|
354
608
|
return { error: config.strings.emailExists };
|
|
355
609
|
}
|
|
356
610
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
357
|
-
await prisma.
|
|
611
|
+
await prisma[userModel].create({
|
|
358
612
|
data: {
|
|
359
613
|
name,
|
|
360
614
|
email,
|
|
@@ -375,7 +629,7 @@ function createUserHandlers(prisma, config) {
|
|
|
375
629
|
if (!config.roles.list.includes(role)) {
|
|
376
630
|
return { error: config.strings.invalidRole };
|
|
377
631
|
}
|
|
378
|
-
const existing = await prisma.
|
|
632
|
+
const existing = await prisma[userModel].findUnique({ where: { email } });
|
|
379
633
|
if (existing && existing.id !== id) {
|
|
380
634
|
return { error: config.strings.emailExists };
|
|
381
635
|
}
|
|
@@ -390,7 +644,7 @@ function createUserHandlers(prisma, config) {
|
|
|
390
644
|
}
|
|
391
645
|
data.password = await bcrypt.hash(password, 10);
|
|
392
646
|
}
|
|
393
|
-
await prisma.
|
|
647
|
+
await prisma[userModel].update({
|
|
394
648
|
where: { id },
|
|
395
649
|
data
|
|
396
650
|
});
|
|
@@ -400,29 +654,31 @@ function createUserHandlers(prisma, config) {
|
|
|
400
654
|
if (currentUserId === id) {
|
|
401
655
|
return { error: config.strings.cannotDeleteSelf };
|
|
402
656
|
}
|
|
403
|
-
await prisma.
|
|
657
|
+
await prisma[userModel].delete({ where: { id } });
|
|
404
658
|
return { success: true };
|
|
405
659
|
}
|
|
406
660
|
};
|
|
407
661
|
}
|
|
408
662
|
|
|
409
663
|
// src/handlers/media.ts
|
|
410
|
-
function createMediaHandlers(prisma,
|
|
664
|
+
function createMediaHandlers(prisma, config) {
|
|
665
|
+
const mediaModel = config.models.media;
|
|
666
|
+
const articleModel = config.models.article;
|
|
411
667
|
return {
|
|
412
668
|
async getMedia(search) {
|
|
413
|
-
return prisma.
|
|
669
|
+
return prisma[mediaModel].findMany({
|
|
414
670
|
where: search ? { filename: { contains: search } } : void 0,
|
|
415
671
|
include: { uploader: { select: { name: true } } },
|
|
416
672
|
orderBy: { createdAt: "desc" }
|
|
417
673
|
});
|
|
418
674
|
},
|
|
419
675
|
async deleteMedia(userId, userRole, id, deleteFileFromDisk) {
|
|
420
|
-
const media = await prisma.
|
|
676
|
+
const media = await prisma[mediaModel].findUnique({ where: { id } });
|
|
421
677
|
if (!media) throw new Error("File not found");
|
|
422
678
|
if (userRole === "scrittore" && media.uploaderId !== userId) {
|
|
423
679
|
throw new Error("Unauthorized");
|
|
424
680
|
}
|
|
425
|
-
const usedInArticles = await prisma.
|
|
681
|
+
const usedInArticles = await prisma[articleModel].findMany({
|
|
426
682
|
where: {
|
|
427
683
|
OR: [
|
|
428
684
|
{ coverImage: media.path },
|
|
@@ -443,7 +699,7 @@ function createMediaHandlers(prisma, _config) {
|
|
|
443
699
|
} catch {
|
|
444
700
|
}
|
|
445
701
|
}
|
|
446
|
-
await prisma.
|
|
702
|
+
await prisma[mediaModel].delete({ where: { id } });
|
|
447
703
|
return { success: true };
|
|
448
704
|
}
|
|
449
705
|
};
|
|
@@ -455,6 +711,7 @@ function createUploadHandler(prisma, config, storage) {
|
|
|
455
711
|
...config.upload.imageTypes,
|
|
456
712
|
...config.upload.videoTypes
|
|
457
713
|
];
|
|
714
|
+
const mediaModel = config.models.media;
|
|
458
715
|
return {
|
|
459
716
|
async handleUpload(file, uploaderId) {
|
|
460
717
|
if (!allowedTypes.includes(file.type)) {
|
|
@@ -469,7 +726,7 @@ function createUploadHandler(prisma, config, storage) {
|
|
|
469
726
|
}
|
|
470
727
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
471
728
|
const url = await storage.save(file.name, buffer, file.type);
|
|
472
|
-
await prisma.
|
|
729
|
+
await prisma[mediaModel].create({
|
|
473
730
|
data: {
|
|
474
731
|
filename: file.name,
|
|
475
732
|
path: url,
|
|
@@ -485,7 +742,8 @@ function createUploadHandler(prisma, config, storage) {
|
|
|
485
742
|
|
|
486
743
|
// src/handlers/auth.ts
|
|
487
744
|
import bcrypt2 from "bcryptjs";
|
|
488
|
-
function buildCredentialsProvider(prisma) {
|
|
745
|
+
function buildCredentialsProvider(prisma, config) {
|
|
746
|
+
const userModel = config?.models?.user ?? "user";
|
|
489
747
|
return {
|
|
490
748
|
credentials: {
|
|
491
749
|
email: {},
|
|
@@ -495,7 +753,7 @@ function buildCredentialsProvider(prisma) {
|
|
|
495
753
|
const email = credentials.email;
|
|
496
754
|
const password = credentials.password;
|
|
497
755
|
if (!email || !password) return null;
|
|
498
|
-
const user = await prisma.
|
|
756
|
+
const user = await prisma[userModel].findUnique({
|
|
499
757
|
where: { email }
|
|
500
758
|
});
|
|
501
759
|
if (!user) return null;
|
|
@@ -571,12 +829,105 @@ function createAuthUtils(config) {
|
|
|
571
829
|
}
|
|
572
830
|
};
|
|
573
831
|
}
|
|
832
|
+
|
|
833
|
+
// src/handlers/content.ts
|
|
834
|
+
function createContentHandlers(prisma, contentType, config) {
|
|
835
|
+
const modelName = contentType.slug.replace(/s$/, "").replace(/(^|\-)(\w)/g, (_m, _p1, p2) => p2.toUpperCase());
|
|
836
|
+
const model = prisma[modelName] ?? prisma[contentType.slug];
|
|
837
|
+
if (!model) {
|
|
838
|
+
throw new Error(
|
|
839
|
+
`Prisma model "${modelName}" not found for content type "${contentType.slug}"`
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
const defaultSort = contentType.admin?.defaultSort ? { [contentType.admin.defaultSort.field]: contentType.admin.defaultSort.direction } : { updatedAt: "desc" };
|
|
843
|
+
const searchableFields = contentType.admin?.searchableFields ?? ["title"];
|
|
844
|
+
return {
|
|
845
|
+
async getAll(options) {
|
|
846
|
+
const where = {};
|
|
847
|
+
if (options?.search) {
|
|
848
|
+
where.OR = searchableFields.map((field) => ({
|
|
849
|
+
[field]: { contains: options.search }
|
|
850
|
+
}));
|
|
851
|
+
}
|
|
852
|
+
if (options?.status) {
|
|
853
|
+
where.status = options.status;
|
|
854
|
+
}
|
|
855
|
+
return model.findMany({
|
|
856
|
+
where: Object.keys(where).length > 0 ? where : void 0,
|
|
857
|
+
orderBy: options?.orderBy ?? defaultSort
|
|
858
|
+
});
|
|
859
|
+
},
|
|
860
|
+
async getById(id) {
|
|
861
|
+
return model.findUnique({ where: { id } });
|
|
862
|
+
},
|
|
863
|
+
async create(data) {
|
|
864
|
+
const createData = {};
|
|
865
|
+
for (const field of contentType.fields) {
|
|
866
|
+
if (field.defaultValue !== void 0) {
|
|
867
|
+
createData[field.name] = field.defaultValue;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
if (contentType.defaultStatus) {
|
|
871
|
+
createData.status = contentType.defaultStatus;
|
|
872
|
+
}
|
|
873
|
+
if (data) {
|
|
874
|
+
Object.assign(createData, data);
|
|
875
|
+
}
|
|
876
|
+
const record = await model.create({
|
|
877
|
+
data: createData
|
|
878
|
+
});
|
|
879
|
+
return record.id;
|
|
880
|
+
},
|
|
881
|
+
async update(id, data) {
|
|
882
|
+
const record = await model.findUnique({ where: { id } });
|
|
883
|
+
if (!record) throw new Error(`${contentType.labels.singular} not found`);
|
|
884
|
+
await model.update({
|
|
885
|
+
where: { id },
|
|
886
|
+
data: { ...data, updatedAt: /* @__PURE__ */ new Date() }
|
|
887
|
+
});
|
|
888
|
+
return { success: true };
|
|
889
|
+
},
|
|
890
|
+
async delete(id) {
|
|
891
|
+
const record = await model.findUnique({ where: { id } });
|
|
892
|
+
if (!record) throw new Error(`${contentType.labels.singular} not found`);
|
|
893
|
+
await model.delete({ where: { id } });
|
|
894
|
+
return { success: true };
|
|
895
|
+
},
|
|
896
|
+
async publish(userId, id) {
|
|
897
|
+
if (!contentType.publishedStatus) return { success: false };
|
|
898
|
+
const record = await model.findUnique({ where: { id } });
|
|
899
|
+
if (!record) throw new Error(`${contentType.labels.singular} not found`);
|
|
900
|
+
await model.update({
|
|
901
|
+
where: { id },
|
|
902
|
+
data: {
|
|
903
|
+
status: contentType.publishedStatus,
|
|
904
|
+
publishedAt: /* @__PURE__ */ new Date()
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
return { success: true };
|
|
908
|
+
},
|
|
909
|
+
async unpublish(id) {
|
|
910
|
+
if (!contentType.defaultStatus) return { success: false };
|
|
911
|
+
const record = await model.findUnique({ where: { id } });
|
|
912
|
+
if (!record) throw new Error(`${contentType.labels.singular} not found`);
|
|
913
|
+
await model.update({
|
|
914
|
+
where: { id },
|
|
915
|
+
data: {
|
|
916
|
+
status: contentType.defaultStatus,
|
|
917
|
+
publishedAt: null
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
return { success: true };
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
}
|
|
574
924
|
export {
|
|
575
925
|
DEFAULT_CONFIG,
|
|
576
926
|
buildAuthCallbacks,
|
|
577
927
|
buildCredentialsProvider,
|
|
578
928
|
createArticleHandlers,
|
|
579
929
|
createAuthUtils,
|
|
930
|
+
createContentHandlers,
|
|
580
931
|
createMediaHandlers,
|
|
581
932
|
createRevisionHandlers,
|
|
582
933
|
createUploadHandler,
|