@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.cjs
CHANGED
|
@@ -1792,8 +1792,10 @@ __export(index_exports, {
|
|
|
1792
1792
|
BASE62_ALPHABET: () => BASE62_ALPHABET,
|
|
1793
1793
|
BUILTIN_JEXL_HELPERS: () => BUILTIN_JEXL_HELPERS,
|
|
1794
1794
|
CROCKFORD_BASE32: () => CROCKFORD_BASE32,
|
|
1795
|
+
CURRENT_NAV_PREFERENCES_VERSION: () => CURRENT_NAV_PREFERENCES_VERSION,
|
|
1795
1796
|
ConfigValidationError: () => ConfigValidationError,
|
|
1796
1797
|
ConflictError: () => ConflictError,
|
|
1798
|
+
DEFAULT_USER_NAV_PREFERENCES: () => DEFAULT_USER_NAV_PREFERENCES,
|
|
1797
1799
|
DuplicateKeyError: () => DuplicateKeyError,
|
|
1798
1800
|
DyrectedAIError: () => DyrectedAIError,
|
|
1799
1801
|
DyrectedError: () => DyrectedError,
|
|
@@ -1806,6 +1808,7 @@ __export(index_exports, {
|
|
|
1806
1808
|
NON_NEGOTIABLE_CREDENTIAL_FIELDS: () => NON_NEGOTIABLE_CREDENTIAL_FIELDS,
|
|
1807
1809
|
NotFoundError: () => NotFoundError,
|
|
1808
1810
|
PII_REGEX_PATTERNS: () => PII_REGEX_PATTERNS,
|
|
1811
|
+
RESERVED_NAVIGATION_SLUGS: () => RESERVED_NAVIGATION_SLUGS,
|
|
1809
1812
|
ValidationError: () => ValidationError,
|
|
1810
1813
|
WORKFLOW_HISTORY_COLLECTION: () => WORKFLOW_HISTORY_COLLECTION,
|
|
1811
1814
|
abs: () => abs,
|
|
@@ -1816,6 +1819,7 @@ __export(index_exports, {
|
|
|
1816
1819
|
assertValidDeclarativeHookExpression: () => assertValidDeclarativeHookExpression,
|
|
1817
1820
|
assertValidDeclarativeHookResult: () => assertValidDeclarativeHookResult,
|
|
1818
1821
|
assertValidDeclarativeHooksInConfig: () => assertValidDeclarativeHooksInConfig,
|
|
1822
|
+
assertValidNavigationSlugs: () => assertValidNavigationSlugs,
|
|
1819
1823
|
assertValidPreviewUrlsInConfig: () => assertValidPreviewUrlsInConfig,
|
|
1820
1824
|
availableWorkflowTransitions: () => availableWorkflowTransitions,
|
|
1821
1825
|
buildSqlOrderBy: () => buildSqlOrderBy,
|
|
@@ -1830,6 +1834,7 @@ __export(index_exports, {
|
|
|
1830
1834
|
collectDeclarativeHookValidationIssues: () => collectDeclarativeHookValidationIssues,
|
|
1831
1835
|
collectPreviewUrlValidationIssues: () => collectPreviewUrlValidationIssues,
|
|
1832
1836
|
compact: () => compact,
|
|
1837
|
+
compileNavigation: () => compileNavigation,
|
|
1833
1838
|
count: () => count,
|
|
1834
1839
|
createLifecycleEvent: () => createLifecycleEvent,
|
|
1835
1840
|
createWorkflowDocument: () => createWorkflowDocument,
|
|
@@ -1870,6 +1875,7 @@ __export(index_exports, {
|
|
|
1870
1875
|
defineTimeField: () => defineTimeField,
|
|
1871
1876
|
defineUrlField: () => defineUrlField,
|
|
1872
1877
|
defineView: () => defineView,
|
|
1878
|
+
defineWorkspace: () => defineWorkspace,
|
|
1873
1879
|
diffDays: () => diffDays,
|
|
1874
1880
|
dispatchLifecycleEvent: () => dispatchLifecycleEvent,
|
|
1875
1881
|
dispatchPendingLifecycleEvents: () => dispatchPendingLifecycleEvents,
|
|
@@ -1936,9 +1942,11 @@ __export(index_exports, {
|
|
|
1936
1942
|
parseSqlWhere: () => parseSqlWhere,
|
|
1937
1943
|
pow: () => pow,
|
|
1938
1944
|
prefixedId: () => prefixedId,
|
|
1945
|
+
pruneNavigationForUser: () => pruneNavigationForUser,
|
|
1939
1946
|
publishedStateName: () => publishedStateName,
|
|
1940
1947
|
publishingWorkflow: () => publishingWorkflow,
|
|
1941
1948
|
readingTime: () => readingTime,
|
|
1949
|
+
reconcileNavigation: () => reconcileNavigation,
|
|
1942
1950
|
registerJexlHelpers: () => registerJexlHelpers,
|
|
1943
1951
|
replace: () => replace,
|
|
1944
1952
|
resolveAdminAuthCollection: () => resolveAdminAuthCollection,
|
|
@@ -2042,6 +2050,21 @@ var DyrectedAIError = class _DyrectedAIError extends Error {
|
|
|
2042
2050
|
}
|
|
2043
2051
|
};
|
|
2044
2052
|
|
|
2053
|
+
// src/types/navigation.ts
|
|
2054
|
+
function defineWorkspace(options) {
|
|
2055
|
+
return options;
|
|
2056
|
+
}
|
|
2057
|
+
var CURRENT_NAV_PREFERENCES_VERSION = 1;
|
|
2058
|
+
var DEFAULT_USER_NAV_PREFERENCES = {
|
|
2059
|
+
_version: CURRENT_NAV_PREFERENCES_VERSION,
|
|
2060
|
+
pinned: [],
|
|
2061
|
+
hidden: [],
|
|
2062
|
+
groupOrder: [],
|
|
2063
|
+
itemOrder: {},
|
|
2064
|
+
groups: [],
|
|
2065
|
+
items: []
|
|
2066
|
+
};
|
|
2067
|
+
|
|
2045
2068
|
// src/auth/token.ts
|
|
2046
2069
|
var import_jose = require("jose");
|
|
2047
2070
|
|
|
@@ -3918,7 +3941,33 @@ function normalizeConfig(config) {
|
|
|
3918
3941
|
}
|
|
3919
3942
|
];
|
|
3920
3943
|
}
|
|
3944
|
+
if (!existingFieldNames.has("__preferences")) {
|
|
3945
|
+
fields = [
|
|
3946
|
+
...fields,
|
|
3947
|
+
{
|
|
3948
|
+
name: "__preferences",
|
|
3949
|
+
type: "json",
|
|
3950
|
+
label: "Preferences",
|
|
3951
|
+
promoted: true,
|
|
3952
|
+
admin: {
|
|
3953
|
+
hidden: true,
|
|
3954
|
+
readOnly: true
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3957
|
+
];
|
|
3958
|
+
}
|
|
3921
3959
|
fields = fields.map((field) => {
|
|
3960
|
+
if (field.name === "__preferences") {
|
|
3961
|
+
return {
|
|
3962
|
+
...field,
|
|
3963
|
+
promoted: true,
|
|
3964
|
+
admin: {
|
|
3965
|
+
...field.admin || {},
|
|
3966
|
+
hidden: true,
|
|
3967
|
+
readOnly: true
|
|
3968
|
+
}
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3922
3971
|
if (field.name === "email") {
|
|
3923
3972
|
return {
|
|
3924
3973
|
...field,
|
|
@@ -6725,6 +6774,525 @@ function sanitizeDocForAI(options) {
|
|
|
6725
6774
|
return result;
|
|
6726
6775
|
}
|
|
6727
6776
|
|
|
6777
|
+
// src/utils/navigation-reconciler.ts
|
|
6778
|
+
var normalizeKey = (val) => (val || "").toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
6779
|
+
function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
6780
|
+
if (!baseTree) {
|
|
6781
|
+
return {
|
|
6782
|
+
groups: [],
|
|
6783
|
+
ungrouped: [],
|
|
6784
|
+
pinnedItems: []
|
|
6785
|
+
};
|
|
6786
|
+
}
|
|
6787
|
+
const includeHidden = options?.includeHidden ?? false;
|
|
6788
|
+
const effectivePrefs = prefs || DEFAULT_USER_NAV_PREFERENCES;
|
|
6789
|
+
const hiddenSet = new Set(effectivePrefs.hidden || []);
|
|
6790
|
+
const knownCollectionSlugs = new Set((schemas?.collections || []).map((c) => c.slug));
|
|
6791
|
+
const knownGlobalSlugs = new Set((schemas?.globals || []).map((g) => g.slug));
|
|
6792
|
+
const groupsList = [];
|
|
6793
|
+
const findGroup = (query) => {
|
|
6794
|
+
const qNorm = normalizeKey(query);
|
|
6795
|
+
return groupsList.find(
|
|
6796
|
+
(g) => g.id === query || g.slug === query || g.name === query || normalizeKey(g.id) === qNorm || normalizeKey(g.slug) === qNorm || normalizeKey(g.name) === qNorm
|
|
6797
|
+
);
|
|
6798
|
+
};
|
|
6799
|
+
for (const g of baseTree.groups || []) {
|
|
6800
|
+
groupsList.push({
|
|
6801
|
+
...g,
|
|
6802
|
+
items: (g.items || []).map((item) => ({ ...item }))
|
|
6803
|
+
});
|
|
6804
|
+
}
|
|
6805
|
+
for (const ug of effectivePrefs.groups || []) {
|
|
6806
|
+
const existing = findGroup(ug.slug || ug.name);
|
|
6807
|
+
if (!existing) {
|
|
6808
|
+
groupsList.push({
|
|
6809
|
+
id: ug.slug ? `group_${ug.slug}` : `group_${normalizeKey(ug.name)}`,
|
|
6810
|
+
name: ug.name,
|
|
6811
|
+
slug: ug.slug || normalizeKey(ug.name),
|
|
6812
|
+
icon: ug.icon || "Folder",
|
|
6813
|
+
defaultExpanded: ug.defaultExpanded ?? true,
|
|
6814
|
+
order: ug.order ?? 100,
|
|
6815
|
+
items: []
|
|
6816
|
+
});
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6819
|
+
for (const itemOpt of effectivePrefs.items || []) {
|
|
6820
|
+
const targetGroup = typeof itemOpt.group === "object" ? itemOpt.group?.name : itemOpt.group;
|
|
6821
|
+
const groupKey = targetGroup || "Custom";
|
|
6822
|
+
let group = findGroup(groupKey);
|
|
6823
|
+
if (!group) {
|
|
6824
|
+
group = {
|
|
6825
|
+
id: `group_${normalizeKey(groupKey)}`,
|
|
6826
|
+
name: groupKey,
|
|
6827
|
+
slug: normalizeKey(groupKey),
|
|
6828
|
+
icon: "Folder",
|
|
6829
|
+
defaultExpanded: true,
|
|
6830
|
+
order: 99,
|
|
6831
|
+
items: []
|
|
6832
|
+
};
|
|
6833
|
+
groupsList.push(group);
|
|
6834
|
+
}
|
|
6835
|
+
const itemId = itemOpt.slug ? `workspace_${itemOpt.slug}` : itemOpt.collection ? `collection_${itemOpt.collection}` : `custom_${Math.random()}`;
|
|
6836
|
+
for (const otherGroup of groupsList) {
|
|
6837
|
+
if (otherGroup !== group) {
|
|
6838
|
+
otherGroup.items = otherGroup.items.filter((i) => i.slug !== itemOpt.slug && i.id !== itemId);
|
|
6839
|
+
}
|
|
6840
|
+
}
|
|
6841
|
+
const existingIndex = group.items.findIndex((i) => i.id === itemId || i.slug === itemOpt.slug);
|
|
6842
|
+
const existingItem = existingIndex >= 0 ? group.items[existingIndex] : void 0;
|
|
6843
|
+
const col = schemas?.collections?.find((c) => c.slug === itemOpt.collection);
|
|
6844
|
+
const colViews = col?.views || [];
|
|
6845
|
+
const baseViews = existingItem?.views || [];
|
|
6846
|
+
const userViews = itemOpt.views || [];
|
|
6847
|
+
const userViewSlugs = new Set(userViews.map((v) => v.slug));
|
|
6848
|
+
let mergedViews = [
|
|
6849
|
+
...baseViews.filter((v) => !userViewSlugs.has(v.slug)),
|
|
6850
|
+
...userViews
|
|
6851
|
+
];
|
|
6852
|
+
if (mergedViews.length === 0 && itemOpt.collection) {
|
|
6853
|
+
if (colViews.length > 0) {
|
|
6854
|
+
mergedViews = [...colViews];
|
|
6855
|
+
} else {
|
|
6856
|
+
mergedViews = [
|
|
6857
|
+
{
|
|
6858
|
+
slug: "default",
|
|
6859
|
+
label: col?.label || col?.labels?.plural || itemOpt.label || "All Records",
|
|
6860
|
+
layout: "table",
|
|
6861
|
+
collection: itemOpt.collection
|
|
6862
|
+
}
|
|
6863
|
+
];
|
|
6864
|
+
}
|
|
6865
|
+
}
|
|
6866
|
+
mergedViews = mergedViews.map((v) => ({
|
|
6867
|
+
...v,
|
|
6868
|
+
collection: v.collection || itemOpt.collection || existingItem?.collection
|
|
6869
|
+
}));
|
|
6870
|
+
const compiledItem = {
|
|
6871
|
+
id: itemId,
|
|
6872
|
+
type: itemOpt.slug ? "workspace" : itemOpt.collection ? "collection" : itemOpt.global ? "global" : "workspace",
|
|
6873
|
+
slug: itemOpt.slug || itemOpt.collection || itemOpt.global || "item",
|
|
6874
|
+
label: itemOpt.label || itemOpt.slug || "Item",
|
|
6875
|
+
icon: itemOpt.icon || existingItem?.icon || col?.admin?.icon || "Briefcase",
|
|
6876
|
+
group: group.name,
|
|
6877
|
+
order: itemOpt.order ?? existingItem?.order ?? 100,
|
|
6878
|
+
views: mergedViews,
|
|
6879
|
+
collection: itemOpt.collection || existingItem?.collection,
|
|
6880
|
+
global: itemOpt.global || existingItem?.global,
|
|
6881
|
+
badge: itemOpt.badge || existingItem?.badge,
|
|
6882
|
+
access: itemOpt.access || existingItem?.access
|
|
6883
|
+
};
|
|
6884
|
+
if (existingIndex >= 0) {
|
|
6885
|
+
group.items[existingIndex] = compiledItem;
|
|
6886
|
+
} else {
|
|
6887
|
+
group.items.push(compiledItem);
|
|
6888
|
+
}
|
|
6889
|
+
}
|
|
6890
|
+
const allAvailableItems = [];
|
|
6891
|
+
const reconciledGroups = [];
|
|
6892
|
+
for (const group of groupsList) {
|
|
6893
|
+
const isGroupHidden = hiddenSet.has(group.id) || !!group.slug && hiddenSet.has(group.slug) || hiddenSet.has(group.name);
|
|
6894
|
+
if (!includeHidden && isGroupHidden) {
|
|
6895
|
+
continue;
|
|
6896
|
+
}
|
|
6897
|
+
const visibleItems = [];
|
|
6898
|
+
for (const item of group.items) {
|
|
6899
|
+
const isItemHidden = hiddenSet.has(item.id) || !!item.slug && hiddenSet.has(item.slug);
|
|
6900
|
+
if (!includeHidden && isItemHidden) {
|
|
6901
|
+
continue;
|
|
6902
|
+
}
|
|
6903
|
+
const allViews = item.views || [];
|
|
6904
|
+
const visibleViews = includeHidden ? allViews : allViews.filter((v) => {
|
|
6905
|
+
const compoundKey = `${item.slug}_${v.slug}`;
|
|
6906
|
+
return !hiddenSet.has(compoundKey) && !hiddenSet.has(v.slug);
|
|
6907
|
+
});
|
|
6908
|
+
let isTombstone = false;
|
|
6909
|
+
if (schemas && schemas.collections && schemas.collections.length > 0) {
|
|
6910
|
+
if (item.collection && !knownCollectionSlugs.has(item.collection)) {
|
|
6911
|
+
isTombstone = true;
|
|
6912
|
+
}
|
|
6913
|
+
}
|
|
6914
|
+
if (schemas && schemas.globals && schemas.globals.length > 0) {
|
|
6915
|
+
if (item.global && !knownGlobalSlugs.has(item.global)) {
|
|
6916
|
+
isTombstone = true;
|
|
6917
|
+
}
|
|
6918
|
+
}
|
|
6919
|
+
const processedItem = {
|
|
6920
|
+
...item,
|
|
6921
|
+
views: visibleViews,
|
|
6922
|
+
...isTombstone ? { isTombstone: true } : {}
|
|
6923
|
+
};
|
|
6924
|
+
visibleItems.push(processedItem);
|
|
6925
|
+
allAvailableItems.push(processedItem);
|
|
6926
|
+
}
|
|
6927
|
+
const groupKey = group.slug || group.name;
|
|
6928
|
+
const itemOrderList = effectivePrefs.itemOrder?.[group.id] || effectivePrefs.itemOrder?.[groupKey];
|
|
6929
|
+
if (itemOrderList && itemOrderList.length > 0) {
|
|
6930
|
+
visibleItems.sort((a, b) => {
|
|
6931
|
+
const aIdx = itemOrderList.indexOf(a.id) >= 0 ? itemOrderList.indexOf(a.id) : a.slug ? itemOrderList.indexOf(a.slug) : -1;
|
|
6932
|
+
const bIdx = itemOrderList.indexOf(b.id) >= 0 ? itemOrderList.indexOf(b.id) : b.slug ? itemOrderList.indexOf(b.slug) : -1;
|
|
6933
|
+
if (aIdx >= 0 && bIdx >= 0) return aIdx - bIdx;
|
|
6934
|
+
if (aIdx >= 0) return -1;
|
|
6935
|
+
if (bIdx >= 0) return 1;
|
|
6936
|
+
return (a.order ?? 100) - (b.order ?? 100);
|
|
6937
|
+
});
|
|
6938
|
+
} else {
|
|
6939
|
+
visibleItems.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
6940
|
+
}
|
|
6941
|
+
reconciledGroups.push({
|
|
6942
|
+
...group,
|
|
6943
|
+
items: visibleItems
|
|
6944
|
+
});
|
|
6945
|
+
}
|
|
6946
|
+
if (effectivePrefs.groupOrder && effectivePrefs.groupOrder.length > 0) {
|
|
6947
|
+
reconciledGroups.sort((a, b) => {
|
|
6948
|
+
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);
|
|
6949
|
+
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);
|
|
6950
|
+
if (aIdx >= 0 && bIdx >= 0) return aIdx - bIdx;
|
|
6951
|
+
if (aIdx >= 0) return -1;
|
|
6952
|
+
if (bIdx >= 0) return 1;
|
|
6953
|
+
return (a.order ?? 100) - (b.order ?? 100);
|
|
6954
|
+
});
|
|
6955
|
+
} else {
|
|
6956
|
+
reconciledGroups.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
6957
|
+
}
|
|
6958
|
+
const reconciledUngrouped = (baseTree.ungrouped || []).filter((item) => {
|
|
6959
|
+
const isItemHidden = hiddenSet.has(item.id) || !!item.slug && hiddenSet.has(item.slug);
|
|
6960
|
+
return includeHidden || !isItemHidden;
|
|
6961
|
+
}).map((item) => {
|
|
6962
|
+
const allViews = item.views || [];
|
|
6963
|
+
const visibleViews = includeHidden ? allViews : allViews.filter((v) => {
|
|
6964
|
+
const compoundKey = `${item.slug}_${v.slug}`;
|
|
6965
|
+
return !hiddenSet.has(compoundKey) && !hiddenSet.has(v.slug);
|
|
6966
|
+
});
|
|
6967
|
+
const processed = { ...item, views: visibleViews };
|
|
6968
|
+
allAvailableItems.push(processed);
|
|
6969
|
+
return processed;
|
|
6970
|
+
});
|
|
6971
|
+
const pinnedItems = [];
|
|
6972
|
+
for (const pin of effectivePrefs.pinned || []) {
|
|
6973
|
+
const match = allAvailableItems.find((i) => i.slug === pin.slug || i.id === pin.slug);
|
|
6974
|
+
if (match) {
|
|
6975
|
+
pinnedItems.push({
|
|
6976
|
+
...match,
|
|
6977
|
+
id: `pin_${match.id}`,
|
|
6978
|
+
label: pin.label || match.label,
|
|
6979
|
+
icon: pin.icon || match.icon
|
|
6980
|
+
});
|
|
6981
|
+
} else {
|
|
6982
|
+
pinnedItems.push({
|
|
6983
|
+
id: `pin_${pin.slug}`,
|
|
6984
|
+
type: pin.type,
|
|
6985
|
+
slug: pin.slug,
|
|
6986
|
+
label: pin.label || pin.slug,
|
|
6987
|
+
icon: pin.icon || "Star",
|
|
6988
|
+
order: 0,
|
|
6989
|
+
views: []
|
|
6990
|
+
});
|
|
6991
|
+
}
|
|
6992
|
+
}
|
|
6993
|
+
return {
|
|
6994
|
+
groups: reconciledGroups,
|
|
6995
|
+
ungrouped: reconciledUngrouped,
|
|
6996
|
+
pinnedItems
|
|
6997
|
+
};
|
|
6998
|
+
}
|
|
6999
|
+
|
|
7000
|
+
// src/utils/navigation.ts
|
|
7001
|
+
var RESERVED_NAVIGATION_SLUGS = /* @__PURE__ */ new Set([
|
|
7002
|
+
"collections",
|
|
7003
|
+
"globals",
|
|
7004
|
+
"setup",
|
|
7005
|
+
"api",
|
|
7006
|
+
"login",
|
|
7007
|
+
"logout",
|
|
7008
|
+
"settings",
|
|
7009
|
+
"admin",
|
|
7010
|
+
"preferences",
|
|
7011
|
+
"auth"
|
|
7012
|
+
]);
|
|
7013
|
+
function assertValidNavigationSlugs(navigation) {
|
|
7014
|
+
for (const item of navigation) {
|
|
7015
|
+
if (item.slug) {
|
|
7016
|
+
const normalizedSlug = item.slug.toLowerCase().trim().replace(/^\//, "");
|
|
7017
|
+
if (RESERVED_NAVIGATION_SLUGS.has(normalizedSlug)) {
|
|
7018
|
+
throw new Error(
|
|
7019
|
+
`[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.`
|
|
7020
|
+
);
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
function resolveGroupMeta(groupProp, defaultGroupName = "Collections") {
|
|
7026
|
+
if (!groupProp) {
|
|
7027
|
+
return { name: defaultGroupName };
|
|
7028
|
+
}
|
|
7029
|
+
if (typeof groupProp === "string") {
|
|
7030
|
+
return { name: groupProp };
|
|
7031
|
+
}
|
|
7032
|
+
return { name: groupProp.name, meta: groupProp };
|
|
7033
|
+
}
|
|
7034
|
+
function compileNavigation(config) {
|
|
7035
|
+
const collections = config.collections || [];
|
|
7036
|
+
const globals = config.globals || [];
|
|
7037
|
+
const explicitNav = config.admin?.navigation || [];
|
|
7038
|
+
assertValidNavigationSlugs(explicitNav);
|
|
7039
|
+
const collectionsBySlug = /* @__PURE__ */ new Map();
|
|
7040
|
+
for (const col of collections) {
|
|
7041
|
+
collectionsBySlug.set(col.slug, col);
|
|
7042
|
+
}
|
|
7043
|
+
const globalsBySlug = /* @__PURE__ */ new Map();
|
|
7044
|
+
for (const gl of globals) {
|
|
7045
|
+
globalsBySlug.set(gl.slug, gl);
|
|
7046
|
+
}
|
|
7047
|
+
const mentionedCollections = /* @__PURE__ */ new Set();
|
|
7048
|
+
const mentionedGlobals = /* @__PURE__ */ new Set();
|
|
7049
|
+
const injectedViewsByCollection = /* @__PURE__ */ new Map();
|
|
7050
|
+
for (const item of explicitNav) {
|
|
7051
|
+
if (item.addToCollection) {
|
|
7052
|
+
const existing = injectedViewsByCollection.get(item.addToCollection) || [];
|
|
7053
|
+
if (item.views && item.views.length > 0) {
|
|
7054
|
+
injectedViewsByCollection.set(item.addToCollection, [...existing, ...item.views]);
|
|
7055
|
+
}
|
|
7056
|
+
}
|
|
7057
|
+
if (item.collection) mentionedCollections.add(item.collection);
|
|
7058
|
+
if (item.global) mentionedGlobals.add(item.global);
|
|
7059
|
+
}
|
|
7060
|
+
const groupMetadataMap = /* @__PURE__ */ new Map();
|
|
7061
|
+
const itemsByGroup = /* @__PURE__ */ new Map();
|
|
7062
|
+
const ungroupedItems = [];
|
|
7063
|
+
const registerItem = (groupName, item) => {
|
|
7064
|
+
if (!groupName) {
|
|
7065
|
+
ungroupedItems.push(item);
|
|
7066
|
+
} else {
|
|
7067
|
+
const list = itemsByGroup.get(groupName) || [];
|
|
7068
|
+
list.push(item);
|
|
7069
|
+
itemsByGroup.set(groupName, list);
|
|
7070
|
+
}
|
|
7071
|
+
};
|
|
7072
|
+
for (const item of explicitNav) {
|
|
7073
|
+
if (item.addToCollection && !item.slug && !item.collection && !item.global && !item.dashboard && !item.href) {
|
|
7074
|
+
continue;
|
|
7075
|
+
}
|
|
7076
|
+
const { name: groupName, meta: groupMeta } = resolveGroupMeta(item.group, void 0);
|
|
7077
|
+
if (groupName && groupMeta) {
|
|
7078
|
+
groupMetadataMap.set(groupName, { ...groupMetadataMap.get(groupName) || {}, ...groupMeta });
|
|
7079
|
+
}
|
|
7080
|
+
if (item.dashboard) {
|
|
7081
|
+
registerItem(groupName, {
|
|
7082
|
+
id: "dashboard",
|
|
7083
|
+
type: "dashboard",
|
|
7084
|
+
slug: "dashboard",
|
|
7085
|
+
label: item.label || "Dashboard",
|
|
7086
|
+
icon: item.icon || "LayoutDashboard",
|
|
7087
|
+
group: groupName,
|
|
7088
|
+
order: item.order ?? 0,
|
|
7089
|
+
views: [],
|
|
7090
|
+
access: item.access
|
|
7091
|
+
});
|
|
7092
|
+
continue;
|
|
7093
|
+
}
|
|
7094
|
+
if (item.collection) {
|
|
7095
|
+
const col = collectionsBySlug.get(item.collection);
|
|
7096
|
+
const combinedViews = [
|
|
7097
|
+
...col?.views || [],
|
|
7098
|
+
...injectedViewsByCollection.get(item.collection) || [],
|
|
7099
|
+
...item.views || []
|
|
7100
|
+
];
|
|
7101
|
+
registerItem(groupName, {
|
|
7102
|
+
id: item.slug || `collection_${item.collection}`,
|
|
7103
|
+
type: item.slug ? "workspace" : "collection",
|
|
7104
|
+
slug: item.slug || item.collection,
|
|
7105
|
+
collection: item.collection,
|
|
7106
|
+
label: item.label || col?.labels?.plural || item.collection,
|
|
7107
|
+
icon: item.icon || col?.admin?.icon || "Folder",
|
|
7108
|
+
group: groupName,
|
|
7109
|
+
order: item.order ?? col?.admin?.order ?? 100,
|
|
7110
|
+
views: combinedViews,
|
|
7111
|
+
badge: item.badge,
|
|
7112
|
+
access: item.access || col?.access?.read
|
|
7113
|
+
});
|
|
7114
|
+
continue;
|
|
7115
|
+
}
|
|
7116
|
+
if (item.global) {
|
|
7117
|
+
const gl = globalsBySlug.get(item.global);
|
|
7118
|
+
registerItem(groupName, {
|
|
7119
|
+
id: item.slug || `global_${item.global}`,
|
|
7120
|
+
type: "global",
|
|
7121
|
+
slug: item.slug || item.global,
|
|
7122
|
+
global: item.global,
|
|
7123
|
+
label: item.label || gl?.label || item.global,
|
|
7124
|
+
icon: item.icon || "Settings",
|
|
7125
|
+
group: groupName,
|
|
7126
|
+
order: item.order ?? 100,
|
|
7127
|
+
views: [],
|
|
7128
|
+
badge: item.badge,
|
|
7129
|
+
access: item.access
|
|
7130
|
+
});
|
|
7131
|
+
continue;
|
|
7132
|
+
}
|
|
7133
|
+
if (item.href) {
|
|
7134
|
+
registerItem(groupName, {
|
|
7135
|
+
id: `link_${item.slug || item.href}`,
|
|
7136
|
+
type: "link",
|
|
7137
|
+
slug: item.slug || "link",
|
|
7138
|
+
label: item.label || "Link",
|
|
7139
|
+
href: item.href,
|
|
7140
|
+
icon: item.icon || "ExternalLink",
|
|
7141
|
+
group: groupName,
|
|
7142
|
+
order: item.order ?? 100,
|
|
7143
|
+
views: [],
|
|
7144
|
+
badge: item.badge,
|
|
7145
|
+
access: item.access
|
|
7146
|
+
});
|
|
7147
|
+
continue;
|
|
7148
|
+
}
|
|
7149
|
+
const workspaceSlug = item.slug || "workspace";
|
|
7150
|
+
registerItem(groupName, {
|
|
7151
|
+
id: `workspace_${workspaceSlug}`,
|
|
7152
|
+
type: "workspace",
|
|
7153
|
+
slug: workspaceSlug,
|
|
7154
|
+
label: item.label || workspaceSlug,
|
|
7155
|
+
icon: item.icon || "Briefcase",
|
|
7156
|
+
group: groupName,
|
|
7157
|
+
order: item.order ?? 100,
|
|
7158
|
+
views: item.views || [],
|
|
7159
|
+
badge: item.badge,
|
|
7160
|
+
access: item.access
|
|
7161
|
+
});
|
|
7162
|
+
}
|
|
7163
|
+
for (const col of collections) {
|
|
7164
|
+
if (mentionedCollections.has(col.slug)) continue;
|
|
7165
|
+
if (col.admin?.hidden) continue;
|
|
7166
|
+
const groupProp = col.admin?.group;
|
|
7167
|
+
const { name: groupName, meta: groupMeta } = resolveGroupMeta(groupProp, "Collections");
|
|
7168
|
+
if (groupMeta) {
|
|
7169
|
+
groupMetadataMap.set(groupName, { ...groupMetadataMap.get(groupName) || {}, ...groupMeta });
|
|
7170
|
+
}
|
|
7171
|
+
const combinedViews = [
|
|
7172
|
+
...col.views || [],
|
|
7173
|
+
...injectedViewsByCollection.get(col.slug) || []
|
|
7174
|
+
];
|
|
7175
|
+
registerItem(groupName, {
|
|
7176
|
+
id: `collection_${col.slug}`,
|
|
7177
|
+
type: "collection",
|
|
7178
|
+
slug: col.slug,
|
|
7179
|
+
collection: col.slug,
|
|
7180
|
+
label: col.labels?.plural || col.slug,
|
|
7181
|
+
icon: col.admin?.icon || "Folder",
|
|
7182
|
+
group: groupName,
|
|
7183
|
+
order: col?.admin?.order ?? 100,
|
|
7184
|
+
views: combinedViews,
|
|
7185
|
+
access: col.access?.read
|
|
7186
|
+
});
|
|
7187
|
+
}
|
|
7188
|
+
for (const gl of globals) {
|
|
7189
|
+
if (mentionedGlobals.has(gl.slug)) continue;
|
|
7190
|
+
const groupName = "Configuration";
|
|
7191
|
+
registerItem(groupName, {
|
|
7192
|
+
id: `global_${gl.slug}`,
|
|
7193
|
+
type: "global",
|
|
7194
|
+
slug: gl.slug,
|
|
7195
|
+
global: gl.slug,
|
|
7196
|
+
label: gl.label || gl.slug,
|
|
7197
|
+
icon: "Settings",
|
|
7198
|
+
group: groupName,
|
|
7199
|
+
order: 100,
|
|
7200
|
+
views: []
|
|
7201
|
+
});
|
|
7202
|
+
}
|
|
7203
|
+
const sortAndSpliceItems = (items) => {
|
|
7204
|
+
const sorted = [...items].sort((a, b) => a.order - b.order);
|
|
7205
|
+
const explicitMap = /* @__PURE__ */ new Map();
|
|
7206
|
+
for (const opt of explicitNav) {
|
|
7207
|
+
if (opt.slug) explicitMap.set(opt.slug, opt);
|
|
7208
|
+
if (opt.collection) explicitMap.set(opt.collection, opt);
|
|
7209
|
+
if (opt.global) explicitMap.set(opt.global, opt);
|
|
7210
|
+
}
|
|
7211
|
+
for (const opt of explicitNav) {
|
|
7212
|
+
const itemKey = opt.slug || opt.collection || opt.global;
|
|
7213
|
+
if (!itemKey) continue;
|
|
7214
|
+
if (opt.after) {
|
|
7215
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7216
|
+
const targetIdx = sorted.findIndex((i) => i.slug === opt.after);
|
|
7217
|
+
if (itemIdx !== -1 && targetIdx !== -1 && itemIdx !== targetIdx) {
|
|
7218
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7219
|
+
const newTargetIdx = sorted.findIndex((i) => i.slug === opt.after);
|
|
7220
|
+
sorted.splice(newTargetIdx + 1, 0, moved);
|
|
7221
|
+
}
|
|
7222
|
+
} else if (opt.before) {
|
|
7223
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7224
|
+
const targetIdx = sorted.findIndex((i) => i.slug === opt.before);
|
|
7225
|
+
if (itemIdx !== -1 && targetIdx !== -1 && itemIdx !== targetIdx) {
|
|
7226
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7227
|
+
const newTargetIdx = sorted.findIndex((i) => i.slug === opt.before);
|
|
7228
|
+
sorted.splice(newTargetIdx, 0, moved);
|
|
7229
|
+
}
|
|
7230
|
+
} else if (opt.position === "first") {
|
|
7231
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7232
|
+
if (itemIdx > 0) {
|
|
7233
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7234
|
+
sorted.unshift(moved);
|
|
7235
|
+
}
|
|
7236
|
+
} else if (opt.position === "last") {
|
|
7237
|
+
const itemIdx = sorted.findIndex((i) => i.slug === itemKey);
|
|
7238
|
+
if (itemIdx !== -1 && itemIdx < sorted.length - 1) {
|
|
7239
|
+
const [moved] = sorted.splice(itemIdx, 1);
|
|
7240
|
+
sorted.push(moved);
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
}
|
|
7244
|
+
return sorted;
|
|
7245
|
+
};
|
|
7246
|
+
const compiledGroups = [];
|
|
7247
|
+
for (const [groupName, rawItems] of itemsByGroup.entries()) {
|
|
7248
|
+
const meta = groupMetadataMap.get(groupName);
|
|
7249
|
+
const sortedItems = sortAndSpliceItems(rawItems);
|
|
7250
|
+
compiledGroups.push({
|
|
7251
|
+
id: `group_${groupName.toLowerCase().replace(/\s+/g, "_")}`,
|
|
7252
|
+
name: groupName,
|
|
7253
|
+
slug: meta?.slug || groupName.toLowerCase().replace(/\s+/g, "-"),
|
|
7254
|
+
icon: meta?.icon,
|
|
7255
|
+
defaultExpanded: meta?.defaultExpanded ?? true,
|
|
7256
|
+
order: meta?.order ?? 100,
|
|
7257
|
+
items: sortedItems
|
|
7258
|
+
});
|
|
7259
|
+
}
|
|
7260
|
+
compiledGroups.sort((a, b) => a.order - b.order);
|
|
7261
|
+
return {
|
|
7262
|
+
groups: compiledGroups,
|
|
7263
|
+
ungrouped: sortAndSpliceItems(ungroupedItems)
|
|
7264
|
+
};
|
|
7265
|
+
}
|
|
7266
|
+
function pruneNavigationForUser(tree, user) {
|
|
7267
|
+
const userRoles = /* @__PURE__ */ new Set();
|
|
7268
|
+
if (user?.role) userRoles.add(user.role);
|
|
7269
|
+
if (Array.isArray(user?.roles)) {
|
|
7270
|
+
for (const r of user.roles) userRoles.add(r);
|
|
7271
|
+
}
|
|
7272
|
+
const isAllowed = (item) => {
|
|
7273
|
+
if (!item.access) return true;
|
|
7274
|
+
if (Array.isArray(item.access)) {
|
|
7275
|
+
if (item.access.length === 0) return true;
|
|
7276
|
+
return item.access.some((role) => userRoles.has(role));
|
|
7277
|
+
}
|
|
7278
|
+
return true;
|
|
7279
|
+
};
|
|
7280
|
+
const prunedGroups = [];
|
|
7281
|
+
for (const group of tree.groups) {
|
|
7282
|
+
const visibleItems = group.items.filter(isAllowed);
|
|
7283
|
+
if (visibleItems.length > 0) {
|
|
7284
|
+
prunedGroups.push({
|
|
7285
|
+
...group,
|
|
7286
|
+
items: visibleItems
|
|
7287
|
+
});
|
|
7288
|
+
}
|
|
7289
|
+
}
|
|
7290
|
+
return {
|
|
7291
|
+
groups: prunedGroups,
|
|
7292
|
+
ungrouped: tree.ungrouped.filter(isAllowed)
|
|
7293
|
+
};
|
|
7294
|
+
}
|
|
7295
|
+
|
|
6728
7296
|
// src/index.ts
|
|
6729
7297
|
var import_zod = require("zod");
|
|
6730
7298
|
function defineCollection(config) {
|
|
@@ -6792,8 +7360,10 @@ function defineTab(args) {
|
|
|
6792
7360
|
BASE62_ALPHABET,
|
|
6793
7361
|
BUILTIN_JEXL_HELPERS,
|
|
6794
7362
|
CROCKFORD_BASE32,
|
|
7363
|
+
CURRENT_NAV_PREFERENCES_VERSION,
|
|
6795
7364
|
ConfigValidationError,
|
|
6796
7365
|
ConflictError,
|
|
7366
|
+
DEFAULT_USER_NAV_PREFERENCES,
|
|
6797
7367
|
DuplicateKeyError,
|
|
6798
7368
|
DyrectedAIError,
|
|
6799
7369
|
DyrectedError,
|
|
@@ -6806,6 +7376,7 @@ function defineTab(args) {
|
|
|
6806
7376
|
NON_NEGOTIABLE_CREDENTIAL_FIELDS,
|
|
6807
7377
|
NotFoundError,
|
|
6808
7378
|
PII_REGEX_PATTERNS,
|
|
7379
|
+
RESERVED_NAVIGATION_SLUGS,
|
|
6809
7380
|
ValidationError,
|
|
6810
7381
|
WORKFLOW_HISTORY_COLLECTION,
|
|
6811
7382
|
abs,
|
|
@@ -6816,6 +7387,7 @@ function defineTab(args) {
|
|
|
6816
7387
|
assertValidDeclarativeHookExpression,
|
|
6817
7388
|
assertValidDeclarativeHookResult,
|
|
6818
7389
|
assertValidDeclarativeHooksInConfig,
|
|
7390
|
+
assertValidNavigationSlugs,
|
|
6819
7391
|
assertValidPreviewUrlsInConfig,
|
|
6820
7392
|
availableWorkflowTransitions,
|
|
6821
7393
|
buildSqlOrderBy,
|
|
@@ -6830,6 +7402,7 @@ function defineTab(args) {
|
|
|
6830
7402
|
collectDeclarativeHookValidationIssues,
|
|
6831
7403
|
collectPreviewUrlValidationIssues,
|
|
6832
7404
|
compact,
|
|
7405
|
+
compileNavigation,
|
|
6833
7406
|
count,
|
|
6834
7407
|
createLifecycleEvent,
|
|
6835
7408
|
createWorkflowDocument,
|
|
@@ -6870,6 +7443,7 @@ function defineTab(args) {
|
|
|
6870
7443
|
defineTimeField,
|
|
6871
7444
|
defineUrlField,
|
|
6872
7445
|
defineView,
|
|
7446
|
+
defineWorkspace,
|
|
6873
7447
|
diffDays,
|
|
6874
7448
|
dispatchLifecycleEvent,
|
|
6875
7449
|
dispatchPendingLifecycleEvents,
|
|
@@ -6936,9 +7510,11 @@ function defineTab(args) {
|
|
|
6936
7510
|
parseSqlWhere,
|
|
6937
7511
|
pow,
|
|
6938
7512
|
prefixedId,
|
|
7513
|
+
pruneNavigationForUser,
|
|
6939
7514
|
publishedStateName,
|
|
6940
7515
|
publishingWorkflow,
|
|
6941
7516
|
readingTime,
|
|
7517
|
+
reconcileNavigation,
|
|
6942
7518
|
registerJexlHelpers,
|
|
6943
7519
|
replace,
|
|
6944
7520
|
resolveAdminAuthCollection,
|