@momentumcms/server-analog 0.1.10 → 0.3.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 +15 -0
- package/index.cjs +36 -4
- package/index.js +36 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## 0.3.0 (2026-02-20)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- add named tabs support with nested data grouping and UI improvements ([#30](https://github.com/DonaldMurillo/momentum-cms/pull/30))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Claude Opus 4.6
|
|
10
|
+
- Donald Murillo @DonaldMurillo
|
|
11
|
+
|
|
12
|
+
## 0.2.0 (2026-02-17)
|
|
13
|
+
|
|
14
|
+
This was a version bump only for server-analog to align it with other projects, there were no code changes.
|
|
15
|
+
|
|
1
16
|
## 0.1.10 (2026-02-17)
|
|
2
17
|
|
|
3
18
|
### 🩹 Fixes
|
package/index.cjs
CHANGED
|
@@ -301,12 +301,26 @@ var ReferentialIntegrityError = class extends Error {
|
|
|
301
301
|
this.constraint = constraint;
|
|
302
302
|
}
|
|
303
303
|
};
|
|
304
|
+
function isNamedTab(tab) {
|
|
305
|
+
return typeof tab.name === "string" && tab.name.length > 0;
|
|
306
|
+
}
|
|
304
307
|
function flattenDataFields(fields) {
|
|
305
308
|
const result = [];
|
|
306
309
|
for (const field of fields) {
|
|
307
310
|
if (field.type === "tabs") {
|
|
308
311
|
for (const tab of field.tabs) {
|
|
309
|
-
|
|
312
|
+
if (isNamedTab(tab)) {
|
|
313
|
+
const syntheticGroup = {
|
|
314
|
+
name: tab.name,
|
|
315
|
+
type: "group",
|
|
316
|
+
label: tab.label,
|
|
317
|
+
description: tab.description,
|
|
318
|
+
fields: tab.fields
|
|
319
|
+
};
|
|
320
|
+
result.push(syntheticGroup);
|
|
321
|
+
} else {
|
|
322
|
+
result.push(...flattenDataFields(tab.fields));
|
|
323
|
+
}
|
|
310
324
|
}
|
|
311
325
|
} else if (field.type === "collapsible" || field.type === "row") {
|
|
312
326
|
result.push(...flattenDataFields(field.fields));
|
|
@@ -458,6 +472,9 @@ var MediaCollection = defineCollection({
|
|
|
458
472
|
singular: "Media",
|
|
459
473
|
plural: "Media"
|
|
460
474
|
},
|
|
475
|
+
upload: {
|
|
476
|
+
mimeTypes: ["image/*", "application/pdf", "video/*", "audio/*"]
|
|
477
|
+
},
|
|
461
478
|
admin: {
|
|
462
479
|
useAsTitle: "filename",
|
|
463
480
|
defaultColumns: ["filename", "mimeType", "filesize", "createdAt"]
|
|
@@ -478,7 +495,6 @@ var MediaCollection = defineCollection({
|
|
|
478
495
|
description: "File size in bytes"
|
|
479
496
|
}),
|
|
480
497
|
text("path", {
|
|
481
|
-
required: true,
|
|
482
498
|
label: "Storage Path",
|
|
483
499
|
description: "Path/key where the file is stored",
|
|
484
500
|
admin: {
|
|
@@ -670,7 +686,20 @@ async function runFieldHooks(hookType, fields, data, req, operation) {
|
|
|
670
686
|
for (const field of fields) {
|
|
671
687
|
if (field.type === "tabs") {
|
|
672
688
|
for (const tab of field.tabs) {
|
|
673
|
-
|
|
689
|
+
if (isNamedTab(tab)) {
|
|
690
|
+
const nested = processedData[tab.name];
|
|
691
|
+
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
692
|
+
processedData[tab.name] = await runFieldHooks(
|
|
693
|
+
hookType,
|
|
694
|
+
tab.fields,
|
|
695
|
+
nested,
|
|
696
|
+
req,
|
|
697
|
+
operation
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
} else {
|
|
701
|
+
processedData = await runFieldHooks(hookType, tab.fields, processedData, req, operation);
|
|
702
|
+
}
|
|
674
703
|
}
|
|
675
704
|
continue;
|
|
676
705
|
}
|
|
@@ -680,6 +709,7 @@ async function runFieldHooks(hookType, fields, data, req, operation) {
|
|
|
680
709
|
}
|
|
681
710
|
const hooks = field.hooks?.[hookType];
|
|
682
711
|
if (hooks && hooks.length > 0) {
|
|
712
|
+
const fieldExistsInData = field.name in processedData;
|
|
683
713
|
let value = processedData[field.name];
|
|
684
714
|
for (const hook of hooks) {
|
|
685
715
|
const result = await Promise.resolve(
|
|
@@ -694,7 +724,9 @@ async function runFieldHooks(hookType, fields, data, req, operation) {
|
|
|
694
724
|
value = result;
|
|
695
725
|
}
|
|
696
726
|
}
|
|
697
|
-
|
|
727
|
+
if (fieldExistsInData || value !== void 0) {
|
|
728
|
+
processedData[field.name] = value;
|
|
729
|
+
}
|
|
698
730
|
}
|
|
699
731
|
if (field.type === "group" && processedData[field.name] && typeof processedData[field.name] === "object" && !Array.isArray(processedData[field.name])) {
|
|
700
732
|
processedData[field.name] = await runFieldHooks(
|
package/index.js
CHANGED
|
@@ -263,12 +263,26 @@ var ReferentialIntegrityError = class extends Error {
|
|
|
263
263
|
this.constraint = constraint;
|
|
264
264
|
}
|
|
265
265
|
};
|
|
266
|
+
function isNamedTab(tab) {
|
|
267
|
+
return typeof tab.name === "string" && tab.name.length > 0;
|
|
268
|
+
}
|
|
266
269
|
function flattenDataFields(fields) {
|
|
267
270
|
const result = [];
|
|
268
271
|
for (const field of fields) {
|
|
269
272
|
if (field.type === "tabs") {
|
|
270
273
|
for (const tab of field.tabs) {
|
|
271
|
-
|
|
274
|
+
if (isNamedTab(tab)) {
|
|
275
|
+
const syntheticGroup = {
|
|
276
|
+
name: tab.name,
|
|
277
|
+
type: "group",
|
|
278
|
+
label: tab.label,
|
|
279
|
+
description: tab.description,
|
|
280
|
+
fields: tab.fields
|
|
281
|
+
};
|
|
282
|
+
result.push(syntheticGroup);
|
|
283
|
+
} else {
|
|
284
|
+
result.push(...flattenDataFields(tab.fields));
|
|
285
|
+
}
|
|
272
286
|
}
|
|
273
287
|
} else if (field.type === "collapsible" || field.type === "row") {
|
|
274
288
|
result.push(...flattenDataFields(field.fields));
|
|
@@ -420,6 +434,9 @@ var MediaCollection = defineCollection({
|
|
|
420
434
|
singular: "Media",
|
|
421
435
|
plural: "Media"
|
|
422
436
|
},
|
|
437
|
+
upload: {
|
|
438
|
+
mimeTypes: ["image/*", "application/pdf", "video/*", "audio/*"]
|
|
439
|
+
},
|
|
423
440
|
admin: {
|
|
424
441
|
useAsTitle: "filename",
|
|
425
442
|
defaultColumns: ["filename", "mimeType", "filesize", "createdAt"]
|
|
@@ -440,7 +457,6 @@ var MediaCollection = defineCollection({
|
|
|
440
457
|
description: "File size in bytes"
|
|
441
458
|
}),
|
|
442
459
|
text("path", {
|
|
443
|
-
required: true,
|
|
444
460
|
label: "Storage Path",
|
|
445
461
|
description: "Path/key where the file is stored",
|
|
446
462
|
admin: {
|
|
@@ -632,7 +648,20 @@ async function runFieldHooks(hookType, fields, data, req, operation) {
|
|
|
632
648
|
for (const field of fields) {
|
|
633
649
|
if (field.type === "tabs") {
|
|
634
650
|
for (const tab of field.tabs) {
|
|
635
|
-
|
|
651
|
+
if (isNamedTab(tab)) {
|
|
652
|
+
const nested = processedData[tab.name];
|
|
653
|
+
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
654
|
+
processedData[tab.name] = await runFieldHooks(
|
|
655
|
+
hookType,
|
|
656
|
+
tab.fields,
|
|
657
|
+
nested,
|
|
658
|
+
req,
|
|
659
|
+
operation
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
} else {
|
|
663
|
+
processedData = await runFieldHooks(hookType, tab.fields, processedData, req, operation);
|
|
664
|
+
}
|
|
636
665
|
}
|
|
637
666
|
continue;
|
|
638
667
|
}
|
|
@@ -642,6 +671,7 @@ async function runFieldHooks(hookType, fields, data, req, operation) {
|
|
|
642
671
|
}
|
|
643
672
|
const hooks = field.hooks?.[hookType];
|
|
644
673
|
if (hooks && hooks.length > 0) {
|
|
674
|
+
const fieldExistsInData = field.name in processedData;
|
|
645
675
|
let value = processedData[field.name];
|
|
646
676
|
for (const hook of hooks) {
|
|
647
677
|
const result = await Promise.resolve(
|
|
@@ -656,7 +686,9 @@ async function runFieldHooks(hookType, fields, data, req, operation) {
|
|
|
656
686
|
value = result;
|
|
657
687
|
}
|
|
658
688
|
}
|
|
659
|
-
|
|
689
|
+
if (fieldExistsInData || value !== void 0) {
|
|
690
|
+
processedData[field.name] = value;
|
|
691
|
+
}
|
|
660
692
|
}
|
|
661
693
|
if (field.type === "group" && processedData[field.name] && typeof processedData[field.name] === "object" && !Array.isArray(processedData[field.name])) {
|
|
662
694
|
processedData[field.name] = await runFieldHooks(
|