@dyrected/core 2.16.0 → 2.17.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/{app-KSDgfXsw.d.cts → app-CLdT_0se.d.cts} +1284 -1174
- package/dist/{app-KSDgfXsw.d.ts → app-CLdT_0se.d.ts} +1284 -1174
- package/dist/index.cjs +576 -0
- package/dist/index.d.cts +60 -3
- package/dist/index.d.ts +60 -3
- package/dist/index.js +568 -0
- package/dist/server.cjs +862 -13
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +862 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1845,6 +1845,21 @@ var DyrectedAIError = class _DyrectedAIError extends Error {
|
|
|
1845
1845
|
}
|
|
1846
1846
|
};
|
|
1847
1847
|
|
|
1848
|
+
// src/types/navigation.ts
|
|
1849
|
+
function defineWorkspace(options) {
|
|
1850
|
+
return options;
|
|
1851
|
+
}
|
|
1852
|
+
var CURRENT_NAV_PREFERENCES_VERSION = 1;
|
|
1853
|
+
var DEFAULT_USER_NAV_PREFERENCES = {
|
|
1854
|
+
_version: CURRENT_NAV_PREFERENCES_VERSION,
|
|
1855
|
+
pinned: [],
|
|
1856
|
+
hidden: [],
|
|
1857
|
+
groupOrder: [],
|
|
1858
|
+
itemOrder: {},
|
|
1859
|
+
groups: [],
|
|
1860
|
+
items: []
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1848
1863
|
// src/auth/token.ts
|
|
1849
1864
|
import { SignJWT, jwtVerify, decodeJwt } from "jose";
|
|
1850
1865
|
|
|
@@ -3721,7 +3736,33 @@ function normalizeConfig(config) {
|
|
|
3721
3736
|
}
|
|
3722
3737
|
];
|
|
3723
3738
|
}
|
|
3739
|
+
if (!existingFieldNames.has("__preferences")) {
|
|
3740
|
+
fields = [
|
|
3741
|
+
...fields,
|
|
3742
|
+
{
|
|
3743
|
+
name: "__preferences",
|
|
3744
|
+
type: "json",
|
|
3745
|
+
label: "Preferences",
|
|
3746
|
+
promoted: true,
|
|
3747
|
+
admin: {
|
|
3748
|
+
hidden: true,
|
|
3749
|
+
readOnly: true
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
];
|
|
3753
|
+
}
|
|
3724
3754
|
fields = fields.map((field) => {
|
|
3755
|
+
if (field.name === "__preferences") {
|
|
3756
|
+
return {
|
|
3757
|
+
...field,
|
|
3758
|
+
promoted: true,
|
|
3759
|
+
admin: {
|
|
3760
|
+
...field.admin || {},
|
|
3761
|
+
hidden: true,
|
|
3762
|
+
readOnly: true
|
|
3763
|
+
}
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3725
3766
|
if (field.name === "email") {
|
|
3726
3767
|
return {
|
|
3727
3768
|
...field,
|
|
@@ -6528,6 +6569,525 @@ function sanitizeDocForAI(options) {
|
|
|
6528
6569
|
return result;
|
|
6529
6570
|
}
|
|
6530
6571
|
|
|
6572
|
+
// src/utils/navigation-reconciler.ts
|
|
6573
|
+
var normalizeKey = (val) => (val || "").toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
6574
|
+
function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
6575
|
+
if (!baseTree) {
|
|
6576
|
+
return {
|
|
6577
|
+
groups: [],
|
|
6578
|
+
ungrouped: [],
|
|
6579
|
+
pinnedItems: []
|
|
6580
|
+
};
|
|
6581
|
+
}
|
|
6582
|
+
const includeHidden = options?.includeHidden ?? false;
|
|
6583
|
+
const effectivePrefs = prefs || DEFAULT_USER_NAV_PREFERENCES;
|
|
6584
|
+
const hiddenSet = new Set(effectivePrefs.hidden || []);
|
|
6585
|
+
const knownCollectionSlugs = new Set((schemas?.collections || []).map((c) => c.slug));
|
|
6586
|
+
const knownGlobalSlugs = new Set((schemas?.globals || []).map((g) => g.slug));
|
|
6587
|
+
const groupsList = [];
|
|
6588
|
+
const findGroup = (query) => {
|
|
6589
|
+
const qNorm = normalizeKey(query);
|
|
6590
|
+
return groupsList.find(
|
|
6591
|
+
(g) => g.id === query || g.slug === query || g.name === query || normalizeKey(g.id) === qNorm || normalizeKey(g.slug) === qNorm || normalizeKey(g.name) === qNorm
|
|
6592
|
+
);
|
|
6593
|
+
};
|
|
6594
|
+
for (const g of baseTree.groups || []) {
|
|
6595
|
+
groupsList.push({
|
|
6596
|
+
...g,
|
|
6597
|
+
items: (g.items || []).map((item) => ({ ...item }))
|
|
6598
|
+
});
|
|
6599
|
+
}
|
|
6600
|
+
for (const ug of effectivePrefs.groups || []) {
|
|
6601
|
+
const existing = findGroup(ug.slug || ug.name);
|
|
6602
|
+
if (!existing) {
|
|
6603
|
+
groupsList.push({
|
|
6604
|
+
id: ug.slug ? `group_${ug.slug}` : `group_${normalizeKey(ug.name)}`,
|
|
6605
|
+
name: ug.name,
|
|
6606
|
+
slug: ug.slug || normalizeKey(ug.name),
|
|
6607
|
+
icon: ug.icon || "Folder",
|
|
6608
|
+
defaultExpanded: ug.defaultExpanded ?? true,
|
|
6609
|
+
order: ug.order ?? 100,
|
|
6610
|
+
items: []
|
|
6611
|
+
});
|
|
6612
|
+
}
|
|
6613
|
+
}
|
|
6614
|
+
for (const itemOpt of effectivePrefs.items || []) {
|
|
6615
|
+
const targetGroup = typeof itemOpt.group === "object" ? itemOpt.group?.name : itemOpt.group;
|
|
6616
|
+
const groupKey = targetGroup || "Custom";
|
|
6617
|
+
let group = findGroup(groupKey);
|
|
6618
|
+
if (!group) {
|
|
6619
|
+
group = {
|
|
6620
|
+
id: `group_${normalizeKey(groupKey)}`,
|
|
6621
|
+
name: groupKey,
|
|
6622
|
+
slug: normalizeKey(groupKey),
|
|
6623
|
+
icon: "Folder",
|
|
6624
|
+
defaultExpanded: true,
|
|
6625
|
+
order: 99,
|
|
6626
|
+
items: []
|
|
6627
|
+
};
|
|
6628
|
+
groupsList.push(group);
|
|
6629
|
+
}
|
|
6630
|
+
const itemId = itemOpt.slug ? `workspace_${itemOpt.slug}` : itemOpt.collection ? `collection_${itemOpt.collection}` : `custom_${Math.random()}`;
|
|
6631
|
+
for (const otherGroup of groupsList) {
|
|
6632
|
+
if (otherGroup !== group) {
|
|
6633
|
+
otherGroup.items = otherGroup.items.filter((i) => i.slug !== itemOpt.slug && i.id !== itemId);
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
const existingIndex = group.items.findIndex((i) => i.id === itemId || i.slug === itemOpt.slug);
|
|
6637
|
+
const existingItem = existingIndex >= 0 ? group.items[existingIndex] : void 0;
|
|
6638
|
+
const col = schemas?.collections?.find((c) => c.slug === itemOpt.collection);
|
|
6639
|
+
const colViews = col?.views || [];
|
|
6640
|
+
const baseViews = existingItem?.views || [];
|
|
6641
|
+
const userViews = itemOpt.views || [];
|
|
6642
|
+
const userViewSlugs = new Set(userViews.map((v) => v.slug));
|
|
6643
|
+
let mergedViews = [
|
|
6644
|
+
...baseViews.filter((v) => !userViewSlugs.has(v.slug)),
|
|
6645
|
+
...userViews
|
|
6646
|
+
];
|
|
6647
|
+
if (mergedViews.length === 0 && itemOpt.collection) {
|
|
6648
|
+
if (colViews.length > 0) {
|
|
6649
|
+
mergedViews = [...colViews];
|
|
6650
|
+
} else {
|
|
6651
|
+
mergedViews = [
|
|
6652
|
+
{
|
|
6653
|
+
slug: "default",
|
|
6654
|
+
label: col?.label || col?.labels?.plural || itemOpt.label || "All Records",
|
|
6655
|
+
layout: "table",
|
|
6656
|
+
collection: itemOpt.collection
|
|
6657
|
+
}
|
|
6658
|
+
];
|
|
6659
|
+
}
|
|
6660
|
+
}
|
|
6661
|
+
mergedViews = mergedViews.map((v) => ({
|
|
6662
|
+
...v,
|
|
6663
|
+
collection: v.collection || itemOpt.collection || existingItem?.collection
|
|
6664
|
+
}));
|
|
6665
|
+
const compiledItem = {
|
|
6666
|
+
id: itemId,
|
|
6667
|
+
type: itemOpt.slug ? "workspace" : itemOpt.collection ? "collection" : itemOpt.global ? "global" : "workspace",
|
|
6668
|
+
slug: itemOpt.slug || itemOpt.collection || itemOpt.global || "item",
|
|
6669
|
+
label: itemOpt.label || itemOpt.slug || "Item",
|
|
6670
|
+
icon: itemOpt.icon || existingItem?.icon || col?.admin?.icon || "Briefcase",
|
|
6671
|
+
group: group.name,
|
|
6672
|
+
order: itemOpt.order ?? existingItem?.order ?? 100,
|
|
6673
|
+
views: mergedViews,
|
|
6674
|
+
collection: itemOpt.collection || existingItem?.collection,
|
|
6675
|
+
global: itemOpt.global || existingItem?.global,
|
|
6676
|
+
badge: itemOpt.badge || existingItem?.badge,
|
|
6677
|
+
access: itemOpt.access || existingItem?.access
|
|
6678
|
+
};
|
|
6679
|
+
if (existingIndex >= 0) {
|
|
6680
|
+
group.items[existingIndex] = compiledItem;
|
|
6681
|
+
} else {
|
|
6682
|
+
group.items.push(compiledItem);
|
|
6683
|
+
}
|
|
6684
|
+
}
|
|
6685
|
+
const allAvailableItems = [];
|
|
6686
|
+
const reconciledGroups = [];
|
|
6687
|
+
for (const group of groupsList) {
|
|
6688
|
+
const isGroupHidden = hiddenSet.has(group.id) || !!group.slug && hiddenSet.has(group.slug) || hiddenSet.has(group.name);
|
|
6689
|
+
if (!includeHidden && isGroupHidden) {
|
|
6690
|
+
continue;
|
|
6691
|
+
}
|
|
6692
|
+
const visibleItems = [];
|
|
6693
|
+
for (const item of group.items) {
|
|
6694
|
+
const isItemHidden = hiddenSet.has(item.id) || !!item.slug && hiddenSet.has(item.slug);
|
|
6695
|
+
if (!includeHidden && isItemHidden) {
|
|
6696
|
+
continue;
|
|
6697
|
+
}
|
|
6698
|
+
const allViews = item.views || [];
|
|
6699
|
+
const visibleViews = includeHidden ? allViews : allViews.filter((v) => {
|
|
6700
|
+
const compoundKey = `${item.slug}_${v.slug}`;
|
|
6701
|
+
return !hiddenSet.has(compoundKey) && !hiddenSet.has(v.slug);
|
|
6702
|
+
});
|
|
6703
|
+
let isTombstone = false;
|
|
6704
|
+
if (schemas && schemas.collections && schemas.collections.length > 0) {
|
|
6705
|
+
if (item.collection && !knownCollectionSlugs.has(item.collection)) {
|
|
6706
|
+
isTombstone = true;
|
|
6707
|
+
}
|
|
6708
|
+
}
|
|
6709
|
+
if (schemas && schemas.globals && schemas.globals.length > 0) {
|
|
6710
|
+
if (item.global && !knownGlobalSlugs.has(item.global)) {
|
|
6711
|
+
isTombstone = true;
|
|
6712
|
+
}
|
|
6713
|
+
}
|
|
6714
|
+
const processedItem = {
|
|
6715
|
+
...item,
|
|
6716
|
+
views: visibleViews,
|
|
6717
|
+
...isTombstone ? { isTombstone: true } : {}
|
|
6718
|
+
};
|
|
6719
|
+
visibleItems.push(processedItem);
|
|
6720
|
+
allAvailableItems.push(processedItem);
|
|
6721
|
+
}
|
|
6722
|
+
const groupKey = group.slug || group.name;
|
|
6723
|
+
const itemOrderList = effectivePrefs.itemOrder?.[group.id] || effectivePrefs.itemOrder?.[groupKey];
|
|
6724
|
+
if (itemOrderList && itemOrderList.length > 0) {
|
|
6725
|
+
visibleItems.sort((a, b) => {
|
|
6726
|
+
const aIdx = itemOrderList.indexOf(a.id) >= 0 ? itemOrderList.indexOf(a.id) : a.slug ? itemOrderList.indexOf(a.slug) : -1;
|
|
6727
|
+
const bIdx = itemOrderList.indexOf(b.id) >= 0 ? itemOrderList.indexOf(b.id) : b.slug ? itemOrderList.indexOf(b.slug) : -1;
|
|
6728
|
+
if (aIdx >= 0 && bIdx >= 0) return aIdx - bIdx;
|
|
6729
|
+
if (aIdx >= 0) return -1;
|
|
6730
|
+
if (bIdx >= 0) return 1;
|
|
6731
|
+
return (a.order ?? 100) - (b.order ?? 100);
|
|
6732
|
+
});
|
|
6733
|
+
} else {
|
|
6734
|
+
visibleItems.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
6735
|
+
}
|
|
6736
|
+
reconciledGroups.push({
|
|
6737
|
+
...group,
|
|
6738
|
+
items: visibleItems
|
|
6739
|
+
});
|
|
6740
|
+
}
|
|
6741
|
+
if (effectivePrefs.groupOrder && effectivePrefs.groupOrder.length > 0) {
|
|
6742
|
+
reconciledGroups.sort((a, b) => {
|
|
6743
|
+
const aIdx = effectivePrefs.groupOrder.indexOf(a.id) >= 0 ? effectivePrefs.groupOrder.indexOf(a.id) : a.slug ? effectivePrefs.groupOrder.indexOf(a.slug) : effectivePrefs.groupOrder.indexOf(a.name);
|
|
6744
|
+
const bIdx = effectivePrefs.groupOrder.indexOf(b.id) >= 0 ? effectivePrefs.groupOrder.indexOf(b.id) : b.slug ? effectivePrefs.groupOrder.indexOf(b.slug) : effectivePrefs.groupOrder.indexOf(b.name);
|
|
6745
|
+
if (aIdx >= 0 && bIdx >= 0) return aIdx - bIdx;
|
|
6746
|
+
if (aIdx >= 0) return -1;
|
|
6747
|
+
if (bIdx >= 0) return 1;
|
|
6748
|
+
return (a.order ?? 100) - (b.order ?? 100);
|
|
6749
|
+
});
|
|
6750
|
+
} else {
|
|
6751
|
+
reconciledGroups.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
6752
|
+
}
|
|
6753
|
+
const reconciledUngrouped = (baseTree.ungrouped || []).filter((item) => {
|
|
6754
|
+
const isItemHidden = hiddenSet.has(item.id) || !!item.slug && hiddenSet.has(item.slug);
|
|
6755
|
+
return includeHidden || !isItemHidden;
|
|
6756
|
+
}).map((item) => {
|
|
6757
|
+
const allViews = item.views || [];
|
|
6758
|
+
const visibleViews = includeHidden ? allViews : allViews.filter((v) => {
|
|
6759
|
+
const compoundKey = `${item.slug}_${v.slug}`;
|
|
6760
|
+
return !hiddenSet.has(compoundKey) && !hiddenSet.has(v.slug);
|
|
6761
|
+
});
|
|
6762
|
+
const processed = { ...item, views: visibleViews };
|
|
6763
|
+
allAvailableItems.push(processed);
|
|
6764
|
+
return processed;
|
|
6765
|
+
});
|
|
6766
|
+
const pinnedItems = [];
|
|
6767
|
+
for (const pin of effectivePrefs.pinned || []) {
|
|
6768
|
+
const match = allAvailableItems.find((i) => i.slug === pin.slug || i.id === pin.slug);
|
|
6769
|
+
if (match) {
|
|
6770
|
+
pinnedItems.push({
|
|
6771
|
+
...match,
|
|
6772
|
+
id: `pin_${match.id}`,
|
|
6773
|
+
label: pin.label || match.label,
|
|
6774
|
+
icon: pin.icon || match.icon
|
|
6775
|
+
});
|
|
6776
|
+
} else {
|
|
6777
|
+
pinnedItems.push({
|
|
6778
|
+
id: `pin_${pin.slug}`,
|
|
6779
|
+
type: pin.type,
|
|
6780
|
+
slug: pin.slug,
|
|
6781
|
+
label: pin.label || pin.slug,
|
|
6782
|
+
icon: pin.icon || "Star",
|
|
6783
|
+
order: 0,
|
|
6784
|
+
views: []
|
|
6785
|
+
});
|
|
6786
|
+
}
|
|
6787
|
+
}
|
|
6788
|
+
return {
|
|
6789
|
+
groups: reconciledGroups,
|
|
6790
|
+
ungrouped: reconciledUngrouped,
|
|
6791
|
+
pinnedItems
|
|
6792
|
+
};
|
|
6793
|
+
}
|
|
6794
|
+
|
|
6795
|
+
// src/utils/navigation.ts
|
|
6796
|
+
var RESERVED_NAVIGATION_SLUGS = /* @__PURE__ */ new Set([
|
|
6797
|
+
"collections",
|
|
6798
|
+
"globals",
|
|
6799
|
+
"setup",
|
|
6800
|
+
"api",
|
|
6801
|
+
"login",
|
|
6802
|
+
"logout",
|
|
6803
|
+
"settings",
|
|
6804
|
+
"admin",
|
|
6805
|
+
"preferences",
|
|
6806
|
+
"auth"
|
|
6807
|
+
]);
|
|
6808
|
+
function assertValidNavigationSlugs(navigation) {
|
|
6809
|
+
for (const item of navigation) {
|
|
6810
|
+
if (item.slug) {
|
|
6811
|
+
const normalizedSlug = item.slug.toLowerCase().trim().replace(/^\//, "");
|
|
6812
|
+
if (RESERVED_NAVIGATION_SLUGS.has(normalizedSlug)) {
|
|
6813
|
+
throw new Error(
|
|
6814
|
+
`[Dyrected Config] The slug '${item.slug}' in navigation item '${item.label || item.slug}' is a reserved system path and cannot be used as an operational workspace slug.`
|
|
6815
|
+
);
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6819
|
+
}
|
|
6820
|
+
function resolveGroupMeta(groupProp, defaultGroupName = "Collections") {
|
|
6821
|
+
if (!groupProp) {
|
|
6822
|
+
return { name: defaultGroupName };
|
|
6823
|
+
}
|
|
6824
|
+
if (typeof groupProp === "string") {
|
|
6825
|
+
return { name: groupProp };
|
|
6826
|
+
}
|
|
6827
|
+
return { name: groupProp.name, meta: groupProp };
|
|
6828
|
+
}
|
|
6829
|
+
function compileNavigation(config) {
|
|
6830
|
+
const collections = config.collections || [];
|
|
6831
|
+
const globals = config.globals || [];
|
|
6832
|
+
const explicitNav = config.admin?.navigation || [];
|
|
6833
|
+
assertValidNavigationSlugs(explicitNav);
|
|
6834
|
+
const collectionsBySlug = /* @__PURE__ */ new Map();
|
|
6835
|
+
for (const col of collections) {
|
|
6836
|
+
collectionsBySlug.set(col.slug, col);
|
|
6837
|
+
}
|
|
6838
|
+
const globalsBySlug = /* @__PURE__ */ new Map();
|
|
6839
|
+
for (const gl of globals) {
|
|
6840
|
+
globalsBySlug.set(gl.slug, gl);
|
|
6841
|
+
}
|
|
6842
|
+
const mentionedCollections = /* @__PURE__ */ new Set();
|
|
6843
|
+
const mentionedGlobals = /* @__PURE__ */ new Set();
|
|
6844
|
+
const injectedViewsByCollection = /* @__PURE__ */ new Map();
|
|
6845
|
+
for (const item of explicitNav) {
|
|
6846
|
+
if (item.addToCollection) {
|
|
6847
|
+
const existing = injectedViewsByCollection.get(item.addToCollection) || [];
|
|
6848
|
+
if (item.views && item.views.length > 0) {
|
|
6849
|
+
injectedViewsByCollection.set(item.addToCollection, [...existing, ...item.views]);
|
|
6850
|
+
}
|
|
6851
|
+
}
|
|
6852
|
+
if (item.collection) mentionedCollections.add(item.collection);
|
|
6853
|
+
if (item.global) mentionedGlobals.add(item.global);
|
|
6854
|
+
}
|
|
6855
|
+
const groupMetadataMap = /* @__PURE__ */ new Map();
|
|
6856
|
+
const itemsByGroup = /* @__PURE__ */ new Map();
|
|
6857
|
+
const ungroupedItems = [];
|
|
6858
|
+
const registerItem = (groupName, item) => {
|
|
6859
|
+
if (!groupName) {
|
|
6860
|
+
ungroupedItems.push(item);
|
|
6861
|
+
} else {
|
|
6862
|
+
const list = itemsByGroup.get(groupName) || [];
|
|
6863
|
+
list.push(item);
|
|
6864
|
+
itemsByGroup.set(groupName, list);
|
|
6865
|
+
}
|
|
6866
|
+
};
|
|
6867
|
+
for (const item of explicitNav) {
|
|
6868
|
+
if (item.addToCollection && !item.slug && !item.collection && !item.global && !item.dashboard && !item.href) {
|
|
6869
|
+
continue;
|
|
6870
|
+
}
|
|
6871
|
+
const { name: groupName, meta: groupMeta } = resolveGroupMeta(item.group, void 0);
|
|
6872
|
+
if (groupName && groupMeta) {
|
|
6873
|
+
groupMetadataMap.set(groupName, { ...groupMetadataMap.get(groupName) || {}, ...groupMeta });
|
|
6874
|
+
}
|
|
6875
|
+
if (item.dashboard) {
|
|
6876
|
+
registerItem(groupName, {
|
|
6877
|
+
id: "dashboard",
|
|
6878
|
+
type: "dashboard",
|
|
6879
|
+
slug: "dashboard",
|
|
6880
|
+
label: item.label || "Dashboard",
|
|
6881
|
+
icon: item.icon || "LayoutDashboard",
|
|
6882
|
+
group: groupName,
|
|
6883
|
+
order: item.order ?? 0,
|
|
6884
|
+
views: [],
|
|
6885
|
+
access: item.access
|
|
6886
|
+
});
|
|
6887
|
+
continue;
|
|
6888
|
+
}
|
|
6889
|
+
if (item.collection) {
|
|
6890
|
+
const col = collectionsBySlug.get(item.collection);
|
|
6891
|
+
const combinedViews = [
|
|
6892
|
+
...col?.views || [],
|
|
6893
|
+
...injectedViewsByCollection.get(item.collection) || [],
|
|
6894
|
+
...item.views || []
|
|
6895
|
+
];
|
|
6896
|
+
registerItem(groupName, {
|
|
6897
|
+
id: item.slug || `collection_${item.collection}`,
|
|
6898
|
+
type: item.slug ? "workspace" : "collection",
|
|
6899
|
+
slug: item.slug || item.collection,
|
|
6900
|
+
collection: item.collection,
|
|
6901
|
+
label: item.label || col?.labels?.plural || item.collection,
|
|
6902
|
+
icon: item.icon || col?.admin?.icon || "Folder",
|
|
6903
|
+
group: groupName,
|
|
6904
|
+
order: item.order ?? col?.admin?.order ?? 100,
|
|
6905
|
+
views: combinedViews,
|
|
6906
|
+
badge: item.badge,
|
|
6907
|
+
access: item.access || col?.access?.read
|
|
6908
|
+
});
|
|
6909
|
+
continue;
|
|
6910
|
+
}
|
|
6911
|
+
if (item.global) {
|
|
6912
|
+
const gl = globalsBySlug.get(item.global);
|
|
6913
|
+
registerItem(groupName, {
|
|
6914
|
+
id: item.slug || `global_${item.global}`,
|
|
6915
|
+
type: "global",
|
|
6916
|
+
slug: item.slug || item.global,
|
|
6917
|
+
global: item.global,
|
|
6918
|
+
label: item.label || gl?.label || item.global,
|
|
6919
|
+
icon: item.icon || "Settings",
|
|
6920
|
+
group: groupName,
|
|
6921
|
+
order: item.order ?? 100,
|
|
6922
|
+
views: [],
|
|
6923
|
+
badge: item.badge,
|
|
6924
|
+
access: item.access
|
|
6925
|
+
});
|
|
6926
|
+
continue;
|
|
6927
|
+
}
|
|
6928
|
+
if (item.href) {
|
|
6929
|
+
registerItem(groupName, {
|
|
6930
|
+
id: `link_${item.slug || item.href}`,
|
|
6931
|
+
type: "link",
|
|
6932
|
+
slug: item.slug || "link",
|
|
6933
|
+
label: item.label || "Link",
|
|
6934
|
+
href: item.href,
|
|
6935
|
+
icon: item.icon || "ExternalLink",
|
|
6936
|
+
group: groupName,
|
|
6937
|
+
order: item.order ?? 100,
|
|
6938
|
+
views: [],
|
|
6939
|
+
badge: item.badge,
|
|
6940
|
+
access: item.access
|
|
6941
|
+
});
|
|
6942
|
+
continue;
|
|
6943
|
+
}
|
|
6944
|
+
const workspaceSlug = item.slug || "workspace";
|
|
6945
|
+
registerItem(groupName, {
|
|
6946
|
+
id: `workspace_${workspaceSlug}`,
|
|
6947
|
+
type: "workspace",
|
|
6948
|
+
slug: workspaceSlug,
|
|
6949
|
+
label: item.label || workspaceSlug,
|
|
6950
|
+
icon: item.icon || "Briefcase",
|
|
6951
|
+
group: groupName,
|
|
6952
|
+
order: item.order ?? 100,
|
|
6953
|
+
views: item.views || [],
|
|
6954
|
+
badge: item.badge,
|
|
6955
|
+
access: item.access
|
|
6956
|
+
});
|
|
6957
|
+
}
|
|
6958
|
+
for (const col of collections) {
|
|
6959
|
+
if (mentionedCollections.has(col.slug)) continue;
|
|
6960
|
+
if (col.admin?.hidden) continue;
|
|
6961
|
+
const groupProp = col.admin?.group;
|
|
6962
|
+
const { name: groupName, meta: groupMeta } = resolveGroupMeta(groupProp, "Collections");
|
|
6963
|
+
if (groupMeta) {
|
|
6964
|
+
groupMetadataMap.set(groupName, { ...groupMetadataMap.get(groupName) || {}, ...groupMeta });
|
|
6965
|
+
}
|
|
6966
|
+
const combinedViews = [
|
|
6967
|
+
...col.views || [],
|
|
6968
|
+
...injectedViewsByCollection.get(col.slug) || []
|
|
6969
|
+
];
|
|
6970
|
+
registerItem(groupName, {
|
|
6971
|
+
id: `collection_${col.slug}`,
|
|
6972
|
+
type: "collection",
|
|
6973
|
+
slug: col.slug,
|
|
6974
|
+
collection: col.slug,
|
|
6975
|
+
label: col.labels?.plural || col.slug,
|
|
6976
|
+
icon: col.admin?.icon || "Folder",
|
|
6977
|
+
group: groupName,
|
|
6978
|
+
order: col?.admin?.order ?? 100,
|
|
6979
|
+
views: combinedViews,
|
|
6980
|
+
access: col.access?.read
|
|
6981
|
+
});
|
|
6982
|
+
}
|
|
6983
|
+
for (const gl of globals) {
|
|
6984
|
+
if (mentionedGlobals.has(gl.slug)) continue;
|
|
6985
|
+
const groupName = "Configuration";
|
|
6986
|
+
registerItem(groupName, {
|
|
6987
|
+
id: `global_${gl.slug}`,
|
|
6988
|
+
type: "global",
|
|
6989
|
+
slug: gl.slug,
|
|
6990
|
+
global: gl.slug,
|
|
6991
|
+
label: gl.label || gl.slug,
|
|
6992
|
+
icon: "Settings",
|
|
6993
|
+
group: groupName,
|
|
6994
|
+
order: 100,
|
|
6995
|
+
views: []
|
|
6996
|
+
});
|
|
6997
|
+
}
|
|
6998
|
+
const sortAndSpliceItems = (items) => {
|
|
6999
|
+
const sorted = [...items].sort((a, b) => a.order - b.order);
|
|
7000
|
+
const explicitMap = /* @__PURE__ */ new Map();
|
|
7001
|
+
for (const opt of explicitNav) {
|
|
7002
|
+
if (opt.slug) explicitMap.set(opt.slug, opt);
|
|
7003
|
+
if (opt.collection) explicitMap.set(opt.collection, opt);
|
|
7004
|
+
if (opt.global) explicitMap.set(opt.global, opt);
|
|
7005
|
+
}
|
|
7006
|
+
for (const opt of explicitNav) {
|
|
7007
|
+
const itemKey = opt.slug || opt.collection || opt.global;
|
|
7008
|
+
if (!itemKey) continue;
|
|
7009
|
+
if (opt.after) {
|
|
7010
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7011
|
+
const targetIdx = sorted.findIndex((i) => i.slug === opt.after);
|
|
7012
|
+
if (itemIdx !== -1 && targetIdx !== -1 && itemIdx !== targetIdx) {
|
|
7013
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7014
|
+
const newTargetIdx = sorted.findIndex((i) => i.slug === opt.after);
|
|
7015
|
+
sorted.splice(newTargetIdx + 1, 0, moved);
|
|
7016
|
+
}
|
|
7017
|
+
} else if (opt.before) {
|
|
7018
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7019
|
+
const targetIdx = sorted.findIndex((i) => i.slug === opt.before);
|
|
7020
|
+
if (itemIdx !== -1 && targetIdx !== -1 && itemIdx !== targetIdx) {
|
|
7021
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7022
|
+
const newTargetIdx = sorted.findIndex((i) => i.slug === opt.before);
|
|
7023
|
+
sorted.splice(newTargetIdx, 0, moved);
|
|
7024
|
+
}
|
|
7025
|
+
} else if (opt.position === "first") {
|
|
7026
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7027
|
+
if (itemIdx > 0) {
|
|
7028
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7029
|
+
sorted.unshift(moved);
|
|
7030
|
+
}
|
|
7031
|
+
} else if (opt.position === "last") {
|
|
7032
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7033
|
+
if (itemIdx !== -1 && itemIdx < sorted.length - 1) {
|
|
7034
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7035
|
+
sorted.push(moved);
|
|
7036
|
+
}
|
|
7037
|
+
}
|
|
7038
|
+
}
|
|
7039
|
+
return sorted;
|
|
7040
|
+
};
|
|
7041
|
+
const compiledGroups = [];
|
|
7042
|
+
for (const [groupName, rawItems] of itemsByGroup.entries()) {
|
|
7043
|
+
const meta = groupMetadataMap.get(groupName);
|
|
7044
|
+
const sortedItems = sortAndSpliceItems(rawItems);
|
|
7045
|
+
compiledGroups.push({
|
|
7046
|
+
id: `group_${groupName.toLowerCase().replace(/\s+/g, "_")}`,
|
|
7047
|
+
name: groupName,
|
|
7048
|
+
slug: meta?.slug || groupName.toLowerCase().replace(/\s+/g, "-"),
|
|
7049
|
+
icon: meta?.icon,
|
|
7050
|
+
defaultExpanded: meta?.defaultExpanded ?? true,
|
|
7051
|
+
order: meta?.order ?? 100,
|
|
7052
|
+
items: sortedItems
|
|
7053
|
+
});
|
|
7054
|
+
}
|
|
7055
|
+
compiledGroups.sort((a, b) => a.order - b.order);
|
|
7056
|
+
return {
|
|
7057
|
+
groups: compiledGroups,
|
|
7058
|
+
ungrouped: sortAndSpliceItems(ungroupedItems)
|
|
7059
|
+
};
|
|
7060
|
+
}
|
|
7061
|
+
function pruneNavigationForUser(tree, user) {
|
|
7062
|
+
const userRoles = /* @__PURE__ */ new Set();
|
|
7063
|
+
if (user?.role) userRoles.add(user.role);
|
|
7064
|
+
if (Array.isArray(user?.roles)) {
|
|
7065
|
+
for (const r of user.roles) userRoles.add(r);
|
|
7066
|
+
}
|
|
7067
|
+
const isAllowed = (item) => {
|
|
7068
|
+
if (!item.access) return true;
|
|
7069
|
+
if (Array.isArray(item.access)) {
|
|
7070
|
+
if (item.access.length === 0) return true;
|
|
7071
|
+
return item.access.some((role) => userRoles.has(role));
|
|
7072
|
+
}
|
|
7073
|
+
return true;
|
|
7074
|
+
};
|
|
7075
|
+
const prunedGroups = [];
|
|
7076
|
+
for (const group of tree.groups) {
|
|
7077
|
+
const visibleItems = group.items.filter(isAllowed);
|
|
7078
|
+
if (visibleItems.length > 0) {
|
|
7079
|
+
prunedGroups.push({
|
|
7080
|
+
...group,
|
|
7081
|
+
items: visibleItems
|
|
7082
|
+
});
|
|
7083
|
+
}
|
|
7084
|
+
}
|
|
7085
|
+
return {
|
|
7086
|
+
groups: prunedGroups,
|
|
7087
|
+
ungrouped: tree.ungrouped.filter(isAllowed)
|
|
7088
|
+
};
|
|
7089
|
+
}
|
|
7090
|
+
|
|
6531
7091
|
// src/index.ts
|
|
6532
7092
|
import { z } from "zod";
|
|
6533
7093
|
function defineCollection(config) {
|
|
@@ -6594,8 +7154,10 @@ export {
|
|
|
6594
7154
|
BASE62_ALPHABET,
|
|
6595
7155
|
BUILTIN_JEXL_HELPERS,
|
|
6596
7156
|
CROCKFORD_BASE32,
|
|
7157
|
+
CURRENT_NAV_PREFERENCES_VERSION,
|
|
6597
7158
|
ConfigValidationError,
|
|
6598
7159
|
ConflictError,
|
|
7160
|
+
DEFAULT_USER_NAV_PREFERENCES,
|
|
6599
7161
|
DuplicateKeyError,
|
|
6600
7162
|
DyrectedAIError,
|
|
6601
7163
|
DyrectedError,
|
|
@@ -6608,6 +7170,7 @@ export {
|
|
|
6608
7170
|
NON_NEGOTIABLE_CREDENTIAL_FIELDS,
|
|
6609
7171
|
NotFoundError,
|
|
6610
7172
|
PII_REGEX_PATTERNS,
|
|
7173
|
+
RESERVED_NAVIGATION_SLUGS,
|
|
6611
7174
|
ValidationError,
|
|
6612
7175
|
WORKFLOW_HISTORY_COLLECTION,
|
|
6613
7176
|
abs,
|
|
@@ -6618,6 +7181,7 @@ export {
|
|
|
6618
7181
|
assertValidDeclarativeHookExpression,
|
|
6619
7182
|
assertValidDeclarativeHookResult,
|
|
6620
7183
|
assertValidDeclarativeHooksInConfig,
|
|
7184
|
+
assertValidNavigationSlugs,
|
|
6621
7185
|
assertValidPreviewUrlsInConfig,
|
|
6622
7186
|
availableWorkflowTransitions,
|
|
6623
7187
|
buildSqlOrderBy,
|
|
@@ -6632,6 +7196,7 @@ export {
|
|
|
6632
7196
|
collectDeclarativeHookValidationIssues,
|
|
6633
7197
|
collectPreviewUrlValidationIssues,
|
|
6634
7198
|
compact,
|
|
7199
|
+
compileNavigation,
|
|
6635
7200
|
count,
|
|
6636
7201
|
createLifecycleEvent,
|
|
6637
7202
|
createWorkflowDocument,
|
|
@@ -6672,6 +7237,7 @@ export {
|
|
|
6672
7237
|
defineTimeField,
|
|
6673
7238
|
defineUrlField,
|
|
6674
7239
|
defineView,
|
|
7240
|
+
defineWorkspace,
|
|
6675
7241
|
diffDays,
|
|
6676
7242
|
dispatchLifecycleEvent,
|
|
6677
7243
|
dispatchPendingLifecycleEvents,
|
|
@@ -6738,9 +7304,11 @@ export {
|
|
|
6738
7304
|
parseSqlWhere,
|
|
6739
7305
|
pow,
|
|
6740
7306
|
prefixedId,
|
|
7307
|
+
pruneNavigationForUser,
|
|
6741
7308
|
publishedStateName,
|
|
6742
7309
|
publishingWorkflow,
|
|
6743
7310
|
readingTime,
|
|
7311
|
+
reconcileNavigation,
|
|
6744
7312
|
registerJexlHelpers,
|
|
6745
7313
|
replace,
|
|
6746
7314
|
resolveAdminAuthCollection,
|