@dyrected/core 2.24.2 → 2.25.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-Bg34iyUz.d.cts → app-Ti5woUOq.d.cts} +113 -3
- package/dist/{app-Bg34iyUz.d.ts → app-Ti5woUOq.d.ts} +113 -3
- package/dist/index.cjs +130 -21
- package/dist/index.d.cts +64 -4
- package/dist/index.d.ts +64 -4
- package/dist/index.js +123 -21
- package/dist/server.cjs +215 -51
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +215 -51
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as Field, B as Block, C as CollectionConfig, D as DyrectedConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, G as GlobalConfig, a as DeclarativeHookExpression, W as WorkflowConfig, b as AuthenticatedUser, c as WorkflowTransition, L as LifecycleEventName, d as LifecycleEvent, e as DatabaseAdapter, f as BaseDocument, H as HookRequestContext, T as TaskRunResult, g as TaskConfig, h as DetailActionOptions, i as DetailAction, j as DetailComputedOptions, k as ComputedHandler, l as DetailComputed, m as DetailCustomOptions, n as DetailCustom, o as DetailDividerOptions, p as DetailDivider, q as DisplayFieldOptions, r as DetailField, s as DetailItem, t as DetailGridOptions, u as DetailGrid, v as DetailRepeatOptions, w as DetailRepeat, x as DetailSectionOptions, y as DetailSection, z as DetailTabOptions, E as DetailTab, I as DetailTabsOptions, J as DetailTabs, K as DetailTextOptions, M as DetailText, N as DetailSchema, O as DyrectedContext, Q as AIConfig, R as AIPIIConfig, S as IdStrategy, U as CompiledNavTree, V as CompiledNavItem, X as UserNavigationPreferences, Y as
|
|
2
|
-
export {
|
|
1
|
+
import { F as Field, B as Block, C as CollectionConfig, D as DyrectedConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, G as GlobalConfig, a as DeclarativeHookExpression, W as WorkflowConfig, b as AuthenticatedUser, c as WorkflowTransition, L as LifecycleEventName, d as LifecycleEvent, e as DatabaseAdapter, f as BaseDocument, H as HookRequestContext, T as TaskRunResult, g as TaskConfig, h as DetailActionOptions, i as DetailAction, j as DetailComputedOptions, k as ComputedHandler, l as DetailComputed, m as DetailCustomOptions, n as DetailCustom, o as DetailDividerOptions, p as DetailDivider, q as DisplayFieldOptions, r as DetailField, s as DetailItem, t as DetailGridOptions, u as DetailGrid, v as DetailRepeatOptions, w as DetailRepeat, x as DetailSectionOptions, y as DetailSection, z as DetailTabOptions, E as DetailTab, I as DetailTabsOptions, J as DetailTabs, K as DetailTextOptions, M as DetailText, N as DetailSchema, O as DyrectedContext, Q as AIConfig, R as AIPIIConfig, S as IdStrategy, U as CompiledNavTree, V as CompiledNavItem, X as UserNavigationPreferences, Y as NavigationRolePolicy, Z as DefineWorkspaceOptions, _ as ViewConfig, $ as AdminConfig, a0 as AdminStringKey, a1 as DateTimeField, a2 as RelationshipField, a3 as SelectField, a4 as ArrayField, a5 as FieldType, a6 as BooleanField, a7 as AuthConfig, a8 as AccessPolicyResolver, a9 as DateField, aa as TextField, ab as EmailField, ac as IconField, ad as ImageField, ae as JoinField, af as JsonField, ag as MoneyField, ah as MultiSelectField, ai as NumberField, aj as ObjectField, ak as RadioField, al as RichTextField, am as RowField, an as TextareaField, ao as TimeField, ap as UrlField } from './app-Ti5woUOq.js';
|
|
2
|
+
export { aq as AIAction, ar as AIActionStatus, as as AIActionType, at as AIAuditActionType, au as AIAuditRecord, av as AIChunk, aw as AIMessage, ax as AIPIIPattern, ay as AIRateLimitResult, az as AIRateLimitStore, aA as AIThread, aB as AIToolContext, aC as AIToolDefinition, aD as AI_ACTIONS_COLLECTION, aE as AI_AUDIT_COLLECTION, aF as AI_CHUNKS_COLLECTION, aG as AI_MESSAGES_COLLECTION, aH as AI_THREADS_COLLECTION, aI as AccessConfig, aJ as AccessFunction, aK as AccessFunctionArgs, aL as AccessResult, aM as AccessRule, aN as ActionConfig, aO as ActionConfigBase, aP as ActionConfigWithHandler, aQ as ActionConfigWithMutation, aR as ActionContext, aS as ActionType, aT as AdminAuthAccessResolution, aU as AdminAuthClaimMapping, aV as AdminAuthMember, aW as AdminAuthProvider, aX as AdminAuthProviderMembersConfig, aY as AdminAuthProvisioningMode, aZ as AdminAuthResolveAccessArgs, a_ as AdminAuthResolvedIdentity, a$ as AdminDashboardComponentSlots, b0 as AdminIconName, b1 as AdminStrings, b2 as AggregateArgs, b3 as AggregateCastType, b4 as AggregateCollectionResult, b5 as AggregateInput, b6 as AggregateOperation, b7 as AggregateResult, b8 as AppTrashConfig, b9 as BaseAdminAuthProvider, ba as BaseFieldAdmin, bb as BlockVariant, bc as BlocksField, bd as BooleanFieldAdmin, be as BooleanFormat, bf as CURRENT_NAV_PREFERENCES_VERSION, bg as CUSTOM_VIEW_FETCH_ALL_LIMIT, bh as CalendarViewConfig, bi as CardsViewConfig, bj as CharacterLimitFieldAdmin, bk as CharacterLimitFieldConfig, bl as CollectionAfterChangeHook, bm as CollectionAfterDeleteHook, bn as CollectionAfterReadHook, bo as CollectionAfterReadHookEntry, bp as CollectionAfterRestoreHook, bq as CollectionAfterTransitionHook, br as CollectionAfterTrashHook, bs as CollectionBeforeChangeHook, bt as CollectionBeforeChangeHookEntry, bu as CollectionBeforeCommitHook, bv as CollectionBeforeDeleteHook, bw as CollectionBeforeReadHook, bx as CollectionBeforeReadHookEntry, by as CollectionBeforeRestoreHook, bz as CollectionBeforeTransitionHook, bA as CollectionBeforeTrashHook, bB as CollectionEmailConfig, bC as CollectionIndex, bD as CollectionListComponentSlots, bE as CollectionRAGConfig, bF as CollectionSchemaResult, bG as CollectionSummaryResult, bH as CollectionViewComponentSlots, bI as CompiledNavGroup, bJ as CountOperation, bK as CustomAdminAuthProvider, bL as CustomViewConfig, bM as CustomViewDataConfig, bN as DEFAULT_USER_NAV_PREFERENCES, bO as DateFieldAdmin, bP as DateFormat, bQ as DefaultValueContext, bR as DefineActionOptions, bS as DefineCalendarViewOptions, bT as DefineCardsViewOptions, bU as DefineCustomViewOptions, bV as DefineGanttViewOptions, bW as DefineKanbanViewOptions, bX as DefinePageInput, bY as DefineTableViewOptions, bZ as DefineViewBaseOptions, b_ as DefineViewOptions, b$ as DetailSpan, c0 as DisplayTone, c1 as DisplayVariant, c2 as DistinctCountOperation, c3 as DistinctValuesOperation, c4 as DocumentFormComponentSlots, c5 as DynamicOptionItem, c6 as DynamicOptionsConfig, c7 as DynamicOptionsResolver, c8 as DynamicOptionsResolverArgs, c9 as DyrectedAIContext, ca as DyrectedLoggerConfig, cb as DyrectedObservabilityConfig, cc as EmailFieldAdmin, cd as EmailTemplateArgs, ce as EmailTemplateResult, cf as FORM_SHELLS, cg as FieldAdminHooks, ch as FieldAdminOnChangeHook, ci as FieldAdminOnChangeHookArgs, cj as FieldAdminOptionsHook, ck as FieldAdminOptionsHookArgs, cl as FieldAdminOptionsHookResult, cm as FieldAfterReadHook, cn as FieldAfterReadHookArgs, co as FieldBase, cp as FieldBeforeChangeHook, cq as FieldBeforeChangeHookArgs, cr as FieldHook, cs as FieldHooks, ct as FileData, cu as FormShell, cv as GanttViewConfig, cw as GetDocumentResult, cx as GlobalAfterChangeHook, cy as GlobalAfterReadHook, cz as GlobalAfterReadHookEntry, cA as GlobalBeforeChangeHook, cB as GlobalBeforeChangeHookEntry, cC as GlobalBeforeReadHook, cD as GlobalBeforeReadHookEntry, cE as GlobalFormComponentSlots, cF as GlobalRAGConfig, cG as GlobalSchemaResult, cH as GlobalSummaryResult, cI as HeadingLevel, cJ as HookFunction, cK as IconFieldAdmin, cL as ImageService, cM as ImageTransformOptions, cN as InferAggregateResult, cO as JoinFieldAdmin, cP as JsonFieldAdmin, cQ as JsonFormat, cR as KanbanViewConfig, cS as LIFECYCLE_EVENT_NAMES, cT as LifecycleEventHandler, cU as LinkFormat, cV as MetricColor, cW as MoneyFieldAdmin, cX as MoneyFieldConfig, cY as MultiSelectFieldAdmin, cZ as NAVIGATION_POLICY_KEY, c_ as NamedAccessPolicy, c$ as NavBadgeConfig, d0 as NavGroup, d1 as NumberFieldAdmin, d2 as NumberFormat, d3 as NumberLimitFieldAdmin, d4 as NumberLimitFieldConfig, d5 as NumericOperation, d6 as NumericUpdateOperator, d7 as OIDCAdminAuthProvider, d8 as OptionFormat, d9 as OutboundEmail, da as PageAction, db as PageBreadcrumbItem, dc as PageConfig, dd as PaginatedResult, de as PinnedNavItemRef, df as PublicAdminAuthProvider, dg as QueryCollectionResult, dh as RAGSearchResult, di as RadioFieldAdmin, dj as RateLimitConfig, dk as ReadonlyDatabaseAdapter, dl as RichTextFeature, dm as RichTextFieldConfig, dn as SelectFieldAdmin, dp as SqlWhereResult, dq as StorageAdapter, dr as TableViewConfig, ds as TaskContext, dt as TaskLogger, du as TaskRunStatus, dv as TextFieldAdmin, dw as TextFormat, dx as TextareaFieldAdmin, dy as TrashConfig, dz as TrustProxyConfig, dA as TypedField, dB as UploadConfig, dC as UrlFieldAdmin, dD as UrlLinkValue, dE as ViewActionFeatures, dF as ViewComponentSlots, dG as ViewConfigBase, dH as ViewLayout, dI as ViewMetric, dJ as ViewMetricGroupBy, dK as ViewMetricGroupByConfig, dL as ViewMetricTrendConfig, dM as ViewSubMetric, dN as WhereClause, dO as WhereOperator, dP as WhereOperatorName, dQ as WordLimitFieldAdmin, dR as WordLimitFieldConfig, dS as WorkflowMetadata, dT as WorkflowOnTransitionContext, dU as WorkflowOnTransitionHook, dV as WorkflowRole, dW as WorkflowState, dX as WorkflowTransitionContext, dY as coerceBooleanWhere, dZ as defineAction, d_ as defineCalendarView, d$ as defineCardsView, e0 as defineCustomView, e1 as defineGanttView, e2 as defineKanbanView, e3 as definePage, e4 as defineTableView, e5 as defineView, e6 as defineWorkspace, e7 as isAICollection, e8 as parseMongoWhere, e9 as parseSqlWhere } from './app-Ti5woUOq.js';
|
|
3
3
|
import jexl from 'jexl';
|
|
4
4
|
import { Context } from 'hono';
|
|
5
5
|
export { z } from 'zod';
|
|
@@ -1537,7 +1537,9 @@ interface ReconciledNavTree extends CompiledNavTree {
|
|
|
1537
1537
|
* Reconciles developer-defined navigation tree from code (`baseTree`)
|
|
1538
1538
|
* with operator personal/role preferences (`prefs`), ensuring:
|
|
1539
1539
|
* 1. Sparse delta merging (newly deployed code resources are never dropped).
|
|
1540
|
-
* 2. User-created custom groups and operational workspaces are injected.
|
|
1540
|
+
* 2. User-created custom groups and operational workspaces are injected. Items
|
|
1541
|
+
* already in the server tree keep the server's `access` and `badge`; a
|
|
1542
|
+
* preference can never replace them. Injected items are flagged `userDefined`.
|
|
1541
1543
|
* 3. User visibility overrides (`hidden`) are respected.
|
|
1542
1544
|
* 4. User ordering overrides (`groupOrder`, `itemOrder`) are applied.
|
|
1543
1545
|
* 5. Pinned favorite shortcuts are extracted.
|
|
@@ -1550,12 +1552,46 @@ interface ReconcileNavigationOptions {
|
|
|
1550
1552
|
* If false (default), hidden groups, items, and views are omitted.
|
|
1551
1553
|
*/
|
|
1552
1554
|
includeHidden?: boolean;
|
|
1555
|
+
/**
|
|
1556
|
+
* If false, preferences can only reorder, rename, regroup or hide items that
|
|
1557
|
+
* already exist in the base tree. Items and pins the base tree does not contain
|
|
1558
|
+
* are ignored. Use this when the server has locked the user's menu to a role
|
|
1559
|
+
* policy. Defaults to true.
|
|
1560
|
+
*/
|
|
1561
|
+
allowUserItems?: boolean;
|
|
1553
1562
|
}
|
|
1554
1563
|
declare function reconcileNavigation(baseTree: CompiledNavTree | null | undefined, prefs: UserNavigationPreferences | null | undefined, schemas?: {
|
|
1555
1564
|
collections?: Array<any>;
|
|
1556
1565
|
globals?: Array<any>;
|
|
1557
1566
|
}, options?: ReconcileNavigationOptions): ReconciledNavTree;
|
|
1558
1567
|
|
|
1568
|
+
/**
|
|
1569
|
+
* Reduces a navigation preference to the parts that are safe to share as a
|
|
1570
|
+
* role or global default: ordering, hiding, groups, and regrouped items that
|
|
1571
|
+
* already exist in the server tree. Pinned shortcuts and any item the server
|
|
1572
|
+
* tree does not contain (the publisher's own workspaces) are dropped, so
|
|
1573
|
+
* publishing a layout can never smuggle the publisher's items to other users.
|
|
1574
|
+
*/
|
|
1575
|
+
declare function sanitizeNavigationLayout(prefs: UserNavigationPreferences | null | undefined, tree: CompiledNavTree): UserNavigationPreferences;
|
|
1576
|
+
/**
|
|
1577
|
+
* Validates a stored or submitted role policy and returns a normalised copy,
|
|
1578
|
+
* or `null` when the value is not a policy.
|
|
1579
|
+
*/
|
|
1580
|
+
declare function parseNavigationRolePolicy(value: unknown, tree: CompiledNavTree): NavigationRolePolicy | null;
|
|
1581
|
+
/**
|
|
1582
|
+
* Applies the role menu policies that govern a user to their access-pruned tree.
|
|
1583
|
+
*
|
|
1584
|
+
* `policies` has one entry per role the user holds: the role's policy, or `null`
|
|
1585
|
+
* when the role has none. The menu is locked only if every role has an enforced
|
|
1586
|
+
* policy; a role without one leaves the user unrestricted, because policy narrows
|
|
1587
|
+
* the menu and never grants access. A locked menu is the union of what the
|
|
1588
|
+
* enforced roles allow, arranged by the first policy's layout.
|
|
1589
|
+
*
|
|
1590
|
+
* `access` is applied before this runs, so a policy can never reveal an item the
|
|
1591
|
+
* user cannot access.
|
|
1592
|
+
*/
|
|
1593
|
+
declare function applyNavigationRolePolicies(tree: CompiledNavTree, policies: Array<NavigationRolePolicy | null | undefined>): CompiledNavTree;
|
|
1594
|
+
|
|
1559
1595
|
/**
|
|
1560
1596
|
* System route prefixes reserved by Dyrected.
|
|
1561
1597
|
* Cannot be used as operational workspace slugs.
|
|
@@ -1731,6 +1767,30 @@ declare function getDefaultEmailTemplate(purpose: "invite" | "resetPassword" | "
|
|
|
1731
1767
|
rawHtml: string;
|
|
1732
1768
|
};
|
|
1733
1769
|
|
|
1770
|
+
type BrandingSource = Pick<AdminConfig, "branding" | "meta" | "strings"> | null | undefined;
|
|
1771
|
+
/**
|
|
1772
|
+
* The name of the product as editors should see it.
|
|
1773
|
+
*
|
|
1774
|
+
* Resolution order: `branding.appName`, `branding.logoText`, then the name inside
|
|
1775
|
+
* `meta.titleSuffix` (without its leading `-` or `—`). Returns an empty string when
|
|
1776
|
+
* none is set. It never returns "Dyrected", so white-labelled products do not show
|
|
1777
|
+
* the underlying CMS name; callers decide what neutral wording to use instead.
|
|
1778
|
+
*
|
|
1779
|
+
* @example
|
|
1780
|
+
* resolveAppName({ meta: { titleSuffix: '— Acme Admin' } }) // 'Acme Admin'
|
|
1781
|
+
*/
|
|
1782
|
+
declare function resolveAppName(admin: BrandingSource): string;
|
|
1783
|
+
/**
|
|
1784
|
+
* The text appended to every admin page `<title>`: `meta.titleSuffix` when set,
|
|
1785
|
+
* otherwise `- <app name>`, otherwise an empty string.
|
|
1786
|
+
*/
|
|
1787
|
+
declare function resolveTitleSuffix(admin: BrandingSource): string;
|
|
1788
|
+
/**
|
|
1789
|
+
* Looks up an overridable admin string, replacing `{appName}` with the resolved app name.
|
|
1790
|
+
* Returns `fallback` when the host did not override the key.
|
|
1791
|
+
*/
|
|
1792
|
+
declare function resolveAdminString(admin: BrandingSource, key: AdminStringKey, fallback: string): string;
|
|
1793
|
+
|
|
1734
1794
|
type TopLevelFieldName<TFields extends readonly Field[]> = Extract<TFields[number], {
|
|
1735
1795
|
name: string;
|
|
1736
1796
|
}>["name"];
|
|
@@ -2390,4 +2450,4 @@ declare function defineTab<const T extends readonly Field[]>(args: {
|
|
|
2390
2450
|
fields: T;
|
|
2391
2451
|
}): T;
|
|
2392
2452
|
|
|
2393
|
-
export { AIConfig, type AIErrorCode, AIPIIConfig, type AccessConditions, AccessPolicyResolver, AdminAuthConfig, type AdminComponentsValidationIssue, ArrayField, AuthConfig, type AuthDocFields, AuthenticatedUser, BASE62_ALPHABET, BUILTIN_JEXL_HELPERS, BaseDocument, Block, BooleanField, CROCKFORD_BASE32, CollectionConfig, CompiledNavItem, CompiledNavTree, ComputedHandler, type ConfigDiagnostic, ConfigValidationError, ConflictError, type CreatedAtFieldOptions, type CreatedByFieldOptions, DatabaseAdapter, DateField, DateTimeField, type DeclarativeAccessSurface, type DeclarativeAccessValidationIssue, type DeclarativeAdminSurface, type DeclarativeAdminValidationIssue, DeclarativeHookExpression, type DeclarativeHookSurface, type DeclarativeHookValidationIssue, type DeclarativePreviewSurface, type DeclarativePreviewValidationIssue, DefineWorkspaceOptions, DetailAction, DetailActionOptions, DetailComputed, DetailComputedOptions, DetailCustom, DetailCustomOptions, DetailDivider, DetailDividerOptions, DetailField, DetailGrid, DetailGridOptions, DetailItem, DetailRepeat, DetailRepeatOptions, DetailSchema, DetailSection, DetailSectionOptions, DetailTab, DetailTabOptions, DetailTabs, DetailTabsOptions, DetailText, DetailTextOptions, DisplayFieldOptions, DuplicateKeyError, DyrectedAIError, DyrectedConfig, DyrectedError, EMAIL_TEMPLATES_COLLECTION_CONFIG, EMAIL_TEMPLATES_COLLECTION_SLUG, EmailField, type ExprFunction, type ExtractCollectionSlugs, Field, FieldConditionBuilder, FieldType, ForbiddenError, type GenerateIdOptions, GlobalConfig, HookRequestContext, INTERNAL_SYSTEM_COLLECTIONS, IconField, IdStrategy, ImageField, type InferDocShape, JoinField, JsonField, LIFECYCLE_EVENTS_COLLECTION, type LayoutOptions, LifecycleEvent, LifecycleEventName, MatchBuilder, MoneyField, MultiSelectField, NANOID_ALPHABET, NON_NEGOTIABLE_CREDENTIAL_FIELDS, NotFoundError, NumberField, ObjectField, PII_REGEX_PATTERNS, type Prettify, PublicAdminAuthConfig, type PublishingWorkflowOptions, RESERVED_NAVIGATION_SLUGS, RadioField, type ReconcileNavigationOptions, type ReconciledNavTree, type ReferencedComponentKeys, RelationshipField, type ResolvedTrashConfig, type RestoreDocumentOptions, RichTextField, type RoleOption, type RolesFieldOptions, RowField, type SanitizeDocForAIOptions, SelectField, type SoftDeleteOptions, type SortClause, type SortDirection, type SqlSortDialect, type SystemDocFields, TASK_LOCKS_COLLECTION, TASK_LOCKS_COLLECTION_CONFIG, TRASH_COLLECTION, TRASH_COLLECTION_CONFIG, TaskConfig, TaskRunResult, type TaskRunner, type TemplateBlock, TextField, TextareaField, TimeField, UNASSIGNED_GROUP_KEY, type UpdatedAtFieldOptions, type UpdatedByFieldOptions, type UploadDocFields, UrlField, UserNavigationPreferences, ValidationError, ViewConfig, WORKFLOW_HISTORY_COLLECTION, type WhenFunction, WorkflowConfig, WorkflowTransition, abs, addDays, alertBox, asCollection, assertValidAdminConditionsInConfig, assertValidDeclarativeAccessInConfig, assertValidDeclarativeHookExpression, assertValidDeclarativeHookResult, assertValidDeclarativeHooksInConfig, assertValidNavigationSlugs, assertValidPreviewUrlsInConfig, assertValidTrashInConfig, availableWorkflowTransitions, buildSqlOrderBy, canViewWorkflowDraft, capitalize, ceil, clamp, coalesce, collectAdminComponentsValidationIssues, collectAdminConditionValidationIssues, collectConfigDiagnostics, collectDeclarativeAccessValidationIssues, collectDeclarativeHookValidationIssues, collectPreviewUrlValidationIssues, collectReferencedComponentKeys, compact, compileNavigation, count, createLifecycleEvent, createTaskRunner, createTrashPurgeTask, createWorkflowDocument, ctaButton, defaultValue, defineArrayField, defineBlock, defineBlocksField, defineBooleanField, defineCollection, defineConfig, defineCreatedAtField, defineCreatedByField, defineDateField, defineDateTimeField, defineEmailField, defineField, defineGlobal, defineIconField, defineImageField, defineJoinField, defineJsonField, defineMoneyField, defineMultiSelectField, defineNumberField, defineObjectField, definePublishingWorkflow, defineRadioField, defineRelationshipField, defineRichTextField, defineRoles, defineRolesField, defineRowField, defineSelectField, defineTab, defineTask, defineTextField, defineTextareaField, defineTimeField, defineUpdatedAtField, defineUpdatedByField, defineUrlField, detailBox, diffDays, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, displayAction, displayComputed, displayCustom, displayCustomComponent, displayDivider, displayField, displayGrid, displayRepeat, displaySection, displayTab, displayTabs, displayText, divider, emailTokens, endsWith, escapeHtml, evaluateDetailComputed, evaluateJexl, evaluateJexlSync, eventList, executeFieldAfterRead, executeFieldBeforeChange, expr, first, floor, formatConfigDiagnostics, formatDate, formatJexlValue, generateDefaultDetailSchema, generateDocumentId, generateId, generateOpenApi, get, getAdminAuthCollection, getAdminRoleForCollection, getAllowedSitesForUser, getDefaultEmailTemplate, getPublicAdminAuthConfig, getTrashEntryId, heading, includes, initializeWorkflowDocument, isConfigValidationError, isDetailItemVisible, isEmpty, isFuture, isPast, isSiteAuthorized, isUserAdmin, join, last, layout, length, lower, maskEmail, maskPhone, maskTextPII, materializeWorkflowDocument, max, min, nanoid, nextCronRun, normalizeConfig, normalizeDetailItem, normalizeGroupKey, now, numericFieldNames, paragraph, parseCron, parseSort, pow, prefixedId, pruneNavigationByAccess, pruneNavigationForUser, publishedStateName, publishingWorkflow, readingTime, reconcileNavigation, registerJexlHelpers, replace, resolveAdminAuthCollection, resolveAllCollectionViews, resolveAuthorizedSiteId, resolveBlocks, resolveDocumentTitle, resolveIndexName, resolvePrefix, resolveTrashConfig, restoreDocument, round, row, runCollectionHooks, safeLinkDetailBox, sanitizeDocForAI, saveWorkflowDraft, sectionLabel, simplePublishingWorkflow, slugify, softDeleteDocument, spacer, sqrt, startsWith, sum, table, today, transitionWorkflow, trim, truncate, ulid, unique, upper, uuid, validateAdminConditionExpression, validateDeclarativeAccessExpression, validateDeclarativeHookExpression, validatePreviewUrlExpression, when, wordCount, workflowCapabilities };
|
|
2453
|
+
export { AIConfig, type AIErrorCode, AIPIIConfig, type AccessConditions, AccessPolicyResolver, AdminAuthConfig, type AdminComponentsValidationIssue, AdminConfig, AdminStringKey, ArrayField, AuthConfig, type AuthDocFields, AuthenticatedUser, BASE62_ALPHABET, BUILTIN_JEXL_HELPERS, BaseDocument, Block, BooleanField, CROCKFORD_BASE32, CollectionConfig, CompiledNavItem, CompiledNavTree, ComputedHandler, type ConfigDiagnostic, ConfigValidationError, ConflictError, type CreatedAtFieldOptions, type CreatedByFieldOptions, DatabaseAdapter, DateField, DateTimeField, type DeclarativeAccessSurface, type DeclarativeAccessValidationIssue, type DeclarativeAdminSurface, type DeclarativeAdminValidationIssue, DeclarativeHookExpression, type DeclarativeHookSurface, type DeclarativeHookValidationIssue, type DeclarativePreviewSurface, type DeclarativePreviewValidationIssue, DefineWorkspaceOptions, DetailAction, DetailActionOptions, DetailComputed, DetailComputedOptions, DetailCustom, DetailCustomOptions, DetailDivider, DetailDividerOptions, DetailField, DetailGrid, DetailGridOptions, DetailItem, DetailRepeat, DetailRepeatOptions, DetailSchema, DetailSection, DetailSectionOptions, DetailTab, DetailTabOptions, DetailTabs, DetailTabsOptions, DetailText, DetailTextOptions, DisplayFieldOptions, DuplicateKeyError, DyrectedAIError, DyrectedConfig, DyrectedError, EMAIL_TEMPLATES_COLLECTION_CONFIG, EMAIL_TEMPLATES_COLLECTION_SLUG, EmailField, type ExprFunction, type ExtractCollectionSlugs, Field, FieldConditionBuilder, FieldType, ForbiddenError, type GenerateIdOptions, GlobalConfig, HookRequestContext, INTERNAL_SYSTEM_COLLECTIONS, IconField, IdStrategy, ImageField, type InferDocShape, JoinField, JsonField, LIFECYCLE_EVENTS_COLLECTION, type LayoutOptions, LifecycleEvent, LifecycleEventName, MatchBuilder, MoneyField, MultiSelectField, NANOID_ALPHABET, NON_NEGOTIABLE_CREDENTIAL_FIELDS, NavigationRolePolicy, NotFoundError, NumberField, ObjectField, PII_REGEX_PATTERNS, type Prettify, PublicAdminAuthConfig, type PublishingWorkflowOptions, RESERVED_NAVIGATION_SLUGS, RadioField, type ReconcileNavigationOptions, type ReconciledNavTree, type ReferencedComponentKeys, RelationshipField, type ResolvedTrashConfig, type RestoreDocumentOptions, RichTextField, type RoleOption, type RolesFieldOptions, RowField, type SanitizeDocForAIOptions, SelectField, type SoftDeleteOptions, type SortClause, type SortDirection, type SqlSortDialect, type SystemDocFields, TASK_LOCKS_COLLECTION, TASK_LOCKS_COLLECTION_CONFIG, TRASH_COLLECTION, TRASH_COLLECTION_CONFIG, TaskConfig, TaskRunResult, type TaskRunner, type TemplateBlock, TextField, TextareaField, TimeField, UNASSIGNED_GROUP_KEY, type UpdatedAtFieldOptions, type UpdatedByFieldOptions, type UploadDocFields, UrlField, UserNavigationPreferences, ValidationError, ViewConfig, WORKFLOW_HISTORY_COLLECTION, type WhenFunction, WorkflowConfig, WorkflowTransition, abs, addDays, alertBox, applyNavigationRolePolicies, asCollection, assertValidAdminConditionsInConfig, assertValidDeclarativeAccessInConfig, assertValidDeclarativeHookExpression, assertValidDeclarativeHookResult, assertValidDeclarativeHooksInConfig, assertValidNavigationSlugs, assertValidPreviewUrlsInConfig, assertValidTrashInConfig, availableWorkflowTransitions, buildSqlOrderBy, canViewWorkflowDraft, capitalize, ceil, clamp, coalesce, collectAdminComponentsValidationIssues, collectAdminConditionValidationIssues, collectConfigDiagnostics, collectDeclarativeAccessValidationIssues, collectDeclarativeHookValidationIssues, collectPreviewUrlValidationIssues, collectReferencedComponentKeys, compact, compileNavigation, count, createLifecycleEvent, createTaskRunner, createTrashPurgeTask, createWorkflowDocument, ctaButton, defaultValue, defineArrayField, defineBlock, defineBlocksField, defineBooleanField, defineCollection, defineConfig, defineCreatedAtField, defineCreatedByField, defineDateField, defineDateTimeField, defineEmailField, defineField, defineGlobal, defineIconField, defineImageField, defineJoinField, defineJsonField, defineMoneyField, defineMultiSelectField, defineNumberField, defineObjectField, definePublishingWorkflow, defineRadioField, defineRelationshipField, defineRichTextField, defineRoles, defineRolesField, defineRowField, defineSelectField, defineTab, defineTask, defineTextField, defineTextareaField, defineTimeField, defineUpdatedAtField, defineUpdatedByField, defineUrlField, detailBox, diffDays, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, displayAction, displayComputed, displayCustom, displayCustomComponent, displayDivider, displayField, displayGrid, displayRepeat, displaySection, displayTab, displayTabs, displayText, divider, emailTokens, endsWith, escapeHtml, evaluateDetailComputed, evaluateJexl, evaluateJexlSync, eventList, executeFieldAfterRead, executeFieldBeforeChange, expr, first, floor, formatConfigDiagnostics, formatDate, formatJexlValue, generateDefaultDetailSchema, generateDocumentId, generateId, generateOpenApi, get, getAdminAuthCollection, getAdminRoleForCollection, getAllowedSitesForUser, getDefaultEmailTemplate, getPublicAdminAuthConfig, getTrashEntryId, heading, includes, initializeWorkflowDocument, isConfigValidationError, isDetailItemVisible, isEmpty, isFuture, isPast, isSiteAuthorized, isUserAdmin, join, last, layout, length, lower, maskEmail, maskPhone, maskTextPII, materializeWorkflowDocument, max, min, nanoid, nextCronRun, normalizeConfig, normalizeDetailItem, normalizeGroupKey, now, numericFieldNames, paragraph, parseCron, parseNavigationRolePolicy, parseSort, pow, prefixedId, pruneNavigationByAccess, pruneNavigationForUser, publishedStateName, publishingWorkflow, readingTime, reconcileNavigation, registerJexlHelpers, replace, resolveAdminAuthCollection, resolveAdminString, resolveAllCollectionViews, resolveAppName, resolveAuthorizedSiteId, resolveBlocks, resolveDocumentTitle, resolveIndexName, resolvePrefix, resolveTitleSuffix, resolveTrashConfig, restoreDocument, round, row, runCollectionHooks, safeLinkDetailBox, sanitizeDocForAI, sanitizeNavigationLayout, saveWorkflowDraft, sectionLabel, simplePublishingWorkflow, slugify, softDeleteDocument, spacer, sqrt, startsWith, sum, table, today, transitionWorkflow, trim, truncate, ulid, unique, upper, uuid, validateAdminConditionExpression, validateDeclarativeAccessExpression, validateDeclarativeHookExpression, validatePreviewUrlExpression, when, wordCount, workflowCapabilities };
|
package/dist/index.js
CHANGED
|
@@ -1866,6 +1866,7 @@ var DyrectedAIError = class _DyrectedAIError extends Error {
|
|
|
1866
1866
|
function defineWorkspace(options) {
|
|
1867
1867
|
return options;
|
|
1868
1868
|
}
|
|
1869
|
+
var NAVIGATION_POLICY_KEY = "admin:navigation-policy";
|
|
1869
1870
|
var CURRENT_NAV_PREFERENCES_VERSION = 1;
|
|
1870
1871
|
var DEFAULT_USER_NAV_PREFERENCES = {
|
|
1871
1872
|
_version: CURRENT_NAV_PREFERENCES_VERSION,
|
|
@@ -4207,6 +4208,32 @@ function isUserAdmin(user, collection) {
|
|
|
4207
4208
|
return false;
|
|
4208
4209
|
}
|
|
4209
4210
|
|
|
4211
|
+
// src/utils/app-name.ts
|
|
4212
|
+
var SUFFIX_SEPARATOR = /^[\s\-\u2013\u2014|\u00b7:]+/;
|
|
4213
|
+
function resolveAppName(admin) {
|
|
4214
|
+
const candidates = [
|
|
4215
|
+
admin?.branding?.appName,
|
|
4216
|
+
admin?.branding?.logoText,
|
|
4217
|
+
admin?.meta?.titleSuffix?.replace(SUFFIX_SEPARATOR, "")
|
|
4218
|
+
];
|
|
4219
|
+
for (const candidate of candidates) {
|
|
4220
|
+
const value = typeof candidate === "string" ? candidate.trim() : "";
|
|
4221
|
+
if (value) return value;
|
|
4222
|
+
}
|
|
4223
|
+
return "";
|
|
4224
|
+
}
|
|
4225
|
+
function resolveTitleSuffix(admin) {
|
|
4226
|
+
const explicit = admin?.meta?.titleSuffix;
|
|
4227
|
+
if (typeof explicit === "string") return explicit.trim();
|
|
4228
|
+
const name = resolveAppName(admin);
|
|
4229
|
+
return name ? `- ${name}` : "";
|
|
4230
|
+
}
|
|
4231
|
+
function resolveAdminString(admin, key, fallback) {
|
|
4232
|
+
const override = admin?.strings?.[key];
|
|
4233
|
+
const text = typeof override === "string" && override.trim() ? override : fallback;
|
|
4234
|
+
return text.replace(/\{appName\}/g, resolveAppName(admin));
|
|
4235
|
+
}
|
|
4236
|
+
|
|
4210
4237
|
// src/utils/block-references.ts
|
|
4211
4238
|
function mergeUniqueBlocks(blocks) {
|
|
4212
4239
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -4576,7 +4603,7 @@ function layout({ preheader, title, content, footer, siteName }) {
|
|
|
4576
4603
|
${table(
|
|
4577
4604
|
row(
|
|
4578
4605
|
table(
|
|
4579
|
-
row(" ", `height:5px;background:${emailTokens.colors.accent};font-size:0;line-height:0`) + row(`${sectionLabel(siteName
|
|
4606
|
+
row(" ", `height:5px;background:${emailTokens.colors.accent};font-size:0;line-height:0`) + row(`${siteName?.trim() ? sectionLabel(siteName) : ""}${heading(title)}`, "padding:30px 32px 24px") + row(resolvedContent, "padding:0 32px 32px") + row(
|
|
4580
4607
|
`${divider()}${paragraph(resolvedFooter, "20px 0 6px")}${paragraph("Privacy: this message contains account-related information; please avoid forwarding it.", "10px 0px 0px 0px", "12px")}`,
|
|
4581
4608
|
"padding:0 32px 28px"
|
|
4582
4609
|
),
|
|
@@ -4591,14 +4618,15 @@ function layout({ preheader, title, content, footer, siteName }) {
|
|
|
4591
4618
|
</html>`;
|
|
4592
4619
|
}
|
|
4593
4620
|
function getDefaultEmailTemplate(purpose, options) {
|
|
4594
|
-
const siteName = options?.siteName ?? "
|
|
4621
|
+
const siteName = options?.siteName?.trim() ?? "";
|
|
4622
|
+
const account = siteName ? `${siteName} account` : "account";
|
|
4595
4623
|
switch (purpose) {
|
|
4596
4624
|
case "invite":
|
|
4597
4625
|
return {
|
|
4598
|
-
subject: `You've been invited to ${siteName}
|
|
4626
|
+
subject: siteName ? `You've been invited to ${siteName}` : "You've been invited",
|
|
4599
4627
|
rawHtml: layout({
|
|
4600
4628
|
siteName,
|
|
4601
|
-
preheader: `You've been invited to join ${siteName}
|
|
4629
|
+
preheader: siteName ? `You've been invited to join ${siteName}.` : "You've been invited to join.",
|
|
4602
4630
|
title: "You've been invited",
|
|
4603
4631
|
content: [
|
|
4604
4632
|
paragraph("Use the invitation link below to create your account. The link expires in 7 days."),
|
|
@@ -4615,7 +4643,7 @@ function getDefaultEmailTemplate(purpose, options) {
|
|
|
4615
4643
|
subject: "Reset your password",
|
|
4616
4644
|
rawHtml: layout({
|
|
4617
4645
|
siteName,
|
|
4618
|
-
preheader: `Reset your ${siteName} password
|
|
4646
|
+
preheader: siteName ? `Reset your ${siteName} password.` : "Reset your password.",
|
|
4619
4647
|
title: "Reset your password",
|
|
4620
4648
|
content: [
|
|
4621
4649
|
paragraph("We received a request to reset your password. The reset link expires in 1 hour."),
|
|
@@ -4629,10 +4657,10 @@ function getDefaultEmailTemplate(purpose, options) {
|
|
|
4629
4657
|
};
|
|
4630
4658
|
case "welcome":
|
|
4631
4659
|
return {
|
|
4632
|
-
subject: `Welcome to ${siteName} \u2014 your account is ready
|
|
4660
|
+
subject: siteName ? `Welcome to ${siteName} \u2014 your account is ready` : "Welcome \u2014 your account is ready",
|
|
4633
4661
|
rawHtml: layout({
|
|
4634
4662
|
siteName,
|
|
4635
|
-
preheader: `Your ${
|
|
4663
|
+
preheader: `Your ${account} is ready.`,
|
|
4636
4664
|
title: "Welcome \u2014 your account is ready",
|
|
4637
4665
|
content: [paragraph("Your account has been created. You can now log in with:"), detailBox("{{email}}")],
|
|
4638
4666
|
footer: "If you didn't create this account, you can safely ignore this email."
|
|
@@ -4643,7 +4671,7 @@ function getDefaultEmailTemplate(purpose, options) {
|
|
|
4643
4671
|
subject: "Your password has been changed",
|
|
4644
4672
|
rawHtml: layout({
|
|
4645
4673
|
siteName,
|
|
4646
|
-
preheader: `Your ${siteName} password was changed
|
|
4674
|
+
preheader: siteName ? `Your ${siteName} password was changed.` : "Your password was changed.",
|
|
4647
4675
|
title: "Password changed",
|
|
4648
4676
|
content: [
|
|
4649
4677
|
paragraph("The password for your account has been changed."),
|
|
@@ -4654,12 +4682,12 @@ function getDefaultEmailTemplate(purpose, options) {
|
|
|
4654
4682
|
};
|
|
4655
4683
|
default:
|
|
4656
4684
|
return {
|
|
4657
|
-
subject: `Notification from ${siteName}
|
|
4685
|
+
subject: siteName ? `Notification from ${siteName}` : "Account notification",
|
|
4658
4686
|
rawHtml: layout({
|
|
4659
4687
|
siteName,
|
|
4660
|
-
preheader: `Account notification from ${siteName}
|
|
4688
|
+
preheader: siteName ? `Account notification from ${siteName}.` : "Account notification.",
|
|
4661
4689
|
title: "Account Notification",
|
|
4662
|
-
content: [paragraph(`This is an account notification from ${siteName}.`)],
|
|
4690
|
+
content: [paragraph(siteName ? `This is an account notification from ${siteName}.` : "This is an account notification.")],
|
|
4663
4691
|
footer: "If you have any questions, please reach out to our team."
|
|
4664
4692
|
})
|
|
4665
4693
|
};
|
|
@@ -4895,7 +4923,7 @@ var EMAIL_TEMPLATES_COLLECTION_CONFIG = {
|
|
|
4895
4923
|
beforeChange: [
|
|
4896
4924
|
async ({ data, req }) => {
|
|
4897
4925
|
if (data && data.format === "html") {
|
|
4898
|
-
const siteName = req?.config?.admin
|
|
4926
|
+
const siteName = resolveAppName(req?.config?.admin);
|
|
4899
4927
|
const defaults = getDefaultEmailTemplate(data.purpose || "invite", { siteName });
|
|
4900
4928
|
if (!data.subject) {
|
|
4901
4929
|
data.subject = defaults.subject;
|
|
@@ -5768,12 +5796,13 @@ function getGlobalTag(global) {
|
|
|
5768
5796
|
return `Global: ${global.label || global.slug}`;
|
|
5769
5797
|
}
|
|
5770
5798
|
function generateOpenApi(config) {
|
|
5799
|
+
const appName = resolveAppName(config.admin);
|
|
5771
5800
|
const spec = {
|
|
5772
5801
|
openapi: "3.0.0",
|
|
5773
5802
|
info: {
|
|
5774
|
-
title:
|
|
5803
|
+
title: appName ? `${appName} API` : "API",
|
|
5775
5804
|
version: "1.0.0",
|
|
5776
|
-
description: "Automatically generated OpenAPI specification for
|
|
5805
|
+
description: appName ? `Automatically generated OpenAPI specification for ${appName}.` : "Automatically generated OpenAPI specification for this project."
|
|
5777
5806
|
},
|
|
5778
5807
|
components: {
|
|
5779
5808
|
schemas: {
|
|
@@ -5884,7 +5913,7 @@ function generateOpenApi(config) {
|
|
|
5884
5913
|
spec.paths["/api/schemas"] = {
|
|
5885
5914
|
get: {
|
|
5886
5915
|
tags: ["System"],
|
|
5887
|
-
summary: "Get the serialized
|
|
5916
|
+
summary: "Get the serialized schema",
|
|
5888
5917
|
security: [],
|
|
5889
5918
|
responses: {
|
|
5890
5919
|
200: { description: "Collection and global schema definitions" }
|
|
@@ -7982,6 +8011,7 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
7982
8011
|
};
|
|
7983
8012
|
}
|
|
7984
8013
|
const includeHidden = options?.includeHidden ?? false;
|
|
8014
|
+
const allowUserItems = options?.allowUserItems ?? true;
|
|
7985
8015
|
const effectivePrefs = prefs || DEFAULT_USER_NAV_PREFERENCES;
|
|
7986
8016
|
const hiddenSet = new Set(effectivePrefs.hidden || []);
|
|
7987
8017
|
const knownCollectionSlugs = new Set((schemas?.collections || []).map((c) => c.slug));
|
|
@@ -8013,8 +8043,14 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8013
8043
|
});
|
|
8014
8044
|
}
|
|
8015
8045
|
}
|
|
8046
|
+
const ungroupedKeys = /* @__PURE__ */ new Set();
|
|
8047
|
+
for (const item of baseTree.ungrouped || []) {
|
|
8048
|
+
ungroupedKeys.add(item.id);
|
|
8049
|
+
if (item.slug) ungroupedKeys.add(item.slug);
|
|
8050
|
+
}
|
|
8016
8051
|
for (const itemOpt of effectivePrefs.items || []) {
|
|
8017
8052
|
const itemId = itemOpt.slug ? `workspace_${itemOpt.slug}` : itemOpt.collection ? `collection_${itemOpt.collection}` : `custom_${Math.random()}`;
|
|
8053
|
+
if (ungroupedKeys.has(itemId) || itemOpt.slug && ungroupedKeys.has(itemOpt.slug)) continue;
|
|
8018
8054
|
let existingItem;
|
|
8019
8055
|
let existingParentGroup;
|
|
8020
8056
|
for (const g of groupsList) {
|
|
@@ -8025,6 +8061,7 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8025
8061
|
break;
|
|
8026
8062
|
}
|
|
8027
8063
|
}
|
|
8064
|
+
if (!existingItem && !allowUserItems) continue;
|
|
8028
8065
|
const targetGroup = typeof itemOpt.group === "object" ? itemOpt.group?.name : itemOpt.group || existingParentGroup?.name || "Custom";
|
|
8029
8066
|
const groupKey = targetGroup;
|
|
8030
8067
|
let group = findGroup(groupKey);
|
|
@@ -8054,7 +8091,7 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8054
8091
|
const baseViews = existingItem?.views || [];
|
|
8055
8092
|
const userViews = (itemOpt.views || []).map((uv) => {
|
|
8056
8093
|
const bv = baseViews.find((b) => b.slug === uv.slug);
|
|
8057
|
-
if (!bv) return uv;
|
|
8094
|
+
if (!bv) return { ...uv, access: void 0 };
|
|
8058
8095
|
const metricsScope = uv.metricsScope ?? bv.metricsScope;
|
|
8059
8096
|
let metrics = uv.metrics;
|
|
8060
8097
|
if (Array.isArray(uv.metrics) && Array.isArray(bv.metrics)) {
|
|
@@ -8075,6 +8112,7 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8075
8112
|
return {
|
|
8076
8113
|
...bv,
|
|
8077
8114
|
...uv,
|
|
8115
|
+
access: bv.access,
|
|
8078
8116
|
metricsScope,
|
|
8079
8117
|
metrics
|
|
8080
8118
|
};
|
|
@@ -8111,10 +8149,12 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8111
8149
|
group: group.name,
|
|
8112
8150
|
order: itemOpt.order ?? existingItem?.order ?? 100,
|
|
8113
8151
|
views: mergedViews,
|
|
8114
|
-
collection:
|
|
8115
|
-
global:
|
|
8116
|
-
|
|
8117
|
-
|
|
8152
|
+
collection: existingItem?.collection || itemOpt.collection,
|
|
8153
|
+
global: existingItem?.global || itemOpt.global,
|
|
8154
|
+
// Access and badges are policy/server-computed: only the server tree may set them.
|
|
8155
|
+
badge: existingItem?.badge,
|
|
8156
|
+
access: existingItem?.access,
|
|
8157
|
+
...existingItem ? existingItem.userDefined ? { userDefined: true } : {} : { userDefined: true }
|
|
8118
8158
|
};
|
|
8119
8159
|
if (existingIndex >= 0) {
|
|
8120
8160
|
group.items[existingIndex] = compiledItem;
|
|
@@ -8213,7 +8253,7 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8213
8253
|
label: pin.label || match.label,
|
|
8214
8254
|
icon: pin.icon || match.icon
|
|
8215
8255
|
});
|
|
8216
|
-
} else {
|
|
8256
|
+
} else if (allowUserItems) {
|
|
8217
8257
|
pinnedItems.push({
|
|
8218
8258
|
id: `pin_${pin.slug}`,
|
|
8219
8259
|
type: pin.type,
|
|
@@ -8232,6 +8272,61 @@ function reconcileNavigation(baseTree, prefs, schemas, options) {
|
|
|
8232
8272
|
};
|
|
8233
8273
|
}
|
|
8234
8274
|
|
|
8275
|
+
// src/utils/navigation-policy.ts
|
|
8276
|
+
var isStringArray = (value) => Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
8277
|
+
var itemKeys = (item) => [item.id, ...item.slug ? [item.slug] : []];
|
|
8278
|
+
var allTreeItems = (tree) => [
|
|
8279
|
+
...tree.groups.flatMap((g) => g.items),
|
|
8280
|
+
...tree.ungrouped
|
|
8281
|
+
];
|
|
8282
|
+
function sanitizeNavigationLayout(prefs, tree) {
|
|
8283
|
+
const known = new Set(allTreeItems(tree).flatMap(itemKeys));
|
|
8284
|
+
return {
|
|
8285
|
+
_version: CURRENT_NAV_PREFERENCES_VERSION,
|
|
8286
|
+
hidden: isStringArray(prefs?.hidden) ? prefs.hidden : [],
|
|
8287
|
+
groupOrder: isStringArray(prefs?.groupOrder) ? prefs.groupOrder : [],
|
|
8288
|
+
itemOrder: Object.fromEntries(
|
|
8289
|
+
Object.entries(prefs?.itemOrder ?? {}).filter(([, order]) => isStringArray(order))
|
|
8290
|
+
),
|
|
8291
|
+
groups: Array.isArray(prefs?.groups) ? prefs.groups : [],
|
|
8292
|
+
items: (Array.isArray(prefs?.items) ? prefs.items : []).filter((item) => {
|
|
8293
|
+
if (item.slug) return known.has(item.slug) || known.has(`workspace_${item.slug}`);
|
|
8294
|
+
if (item.collection) return known.has(`collection_${item.collection}`);
|
|
8295
|
+
if (item.global) return known.has(`global_${item.global}`);
|
|
8296
|
+
return false;
|
|
8297
|
+
})
|
|
8298
|
+
};
|
|
8299
|
+
}
|
|
8300
|
+
function parseNavigationRolePolicy(value, tree) {
|
|
8301
|
+
if (!value || typeof value !== "object") return null;
|
|
8302
|
+
const raw = value;
|
|
8303
|
+
if (typeof raw.enforced !== "boolean" || !isStringArray(raw.allowed)) return null;
|
|
8304
|
+
const layout2 = sanitizeNavigationLayout(raw.layout, tree);
|
|
8305
|
+
return {
|
|
8306
|
+
_version: CURRENT_NAV_PREFERENCES_VERSION,
|
|
8307
|
+
enforced: raw.enforced,
|
|
8308
|
+
allowed: raw.allowed,
|
|
8309
|
+
layout: {
|
|
8310
|
+
_version: layout2._version,
|
|
8311
|
+
hidden: layout2.hidden,
|
|
8312
|
+
groupOrder: layout2.groupOrder,
|
|
8313
|
+
itemOrder: layout2.itemOrder,
|
|
8314
|
+
groups: layout2.groups,
|
|
8315
|
+
items: layout2.items
|
|
8316
|
+
}
|
|
8317
|
+
};
|
|
8318
|
+
}
|
|
8319
|
+
function applyNavigationRolePolicies(tree, policies) {
|
|
8320
|
+
const enforced = policies.filter((p) => !!p?.enforced);
|
|
8321
|
+
if (policies.length === 0 || enforced.length !== policies.length) return tree;
|
|
8322
|
+
const allowed = new Set(enforced.flatMap((p) => p.allowed));
|
|
8323
|
+
const isAllowed = (item) => itemKeys(item).some((key) => allowed.has(key));
|
|
8324
|
+
const groups = tree.groups.map((g) => ({ ...g, items: g.items.filter(isAllowed) })).filter((g) => g.items.length > 0);
|
|
8325
|
+
const filtered = { groups, ungrouped: tree.ungrouped.filter(isAllowed) };
|
|
8326
|
+
const reconciled = reconcileNavigation(filtered, enforced[0].layout, void 0, { allowUserItems: false });
|
|
8327
|
+
return { groups: reconciled.groups, ungrouped: reconciled.ungrouped, locked: true };
|
|
8328
|
+
}
|
|
8329
|
+
|
|
8235
8330
|
// src/utils/navigation.ts
|
|
8236
8331
|
var RESERVED_NAVIGATION_SLUGS = /* @__PURE__ */ new Set([
|
|
8237
8332
|
"collections",
|
|
@@ -8879,6 +8974,7 @@ export {
|
|
|
8879
8974
|
LIFECYCLE_EVENT_NAMES,
|
|
8880
8975
|
MatchBuilder,
|
|
8881
8976
|
NANOID_ALPHABET,
|
|
8977
|
+
NAVIGATION_POLICY_KEY,
|
|
8882
8978
|
NON_NEGOTIABLE_CREDENTIAL_FIELDS,
|
|
8883
8979
|
NotFoundError,
|
|
8884
8980
|
PII_REGEX_PATTERNS,
|
|
@@ -8893,6 +8989,7 @@ export {
|
|
|
8893
8989
|
abs,
|
|
8894
8990
|
addDays,
|
|
8895
8991
|
alertBox,
|
|
8992
|
+
applyNavigationRolePolicies,
|
|
8896
8993
|
asCollection,
|
|
8897
8994
|
assertValidAdminConditionsInConfig,
|
|
8898
8995
|
assertValidDeclarativeAccessInConfig,
|
|
@@ -9048,6 +9145,7 @@ export {
|
|
|
9048
9145
|
paragraph,
|
|
9049
9146
|
parseCron,
|
|
9050
9147
|
parseMongoWhere,
|
|
9148
|
+
parseNavigationRolePolicy,
|
|
9051
9149
|
parseSort,
|
|
9052
9150
|
parseSqlWhere,
|
|
9053
9151
|
pow,
|
|
@@ -9061,12 +9159,15 @@ export {
|
|
|
9061
9159
|
registerJexlHelpers,
|
|
9062
9160
|
replace,
|
|
9063
9161
|
resolveAdminAuthCollection,
|
|
9162
|
+
resolveAdminString,
|
|
9064
9163
|
resolveAllCollectionViews,
|
|
9164
|
+
resolveAppName,
|
|
9065
9165
|
resolveAuthorizedSiteId,
|
|
9066
9166
|
resolveBlocks,
|
|
9067
9167
|
resolveDocumentTitle,
|
|
9068
9168
|
resolveIndexName,
|
|
9069
9169
|
resolvePrefix,
|
|
9170
|
+
resolveTitleSuffix,
|
|
9070
9171
|
resolveTrashConfig,
|
|
9071
9172
|
restoreDocument,
|
|
9072
9173
|
round,
|
|
@@ -9074,6 +9175,7 @@ export {
|
|
|
9074
9175
|
runCollectionHooks,
|
|
9075
9176
|
safeLinkDetailBox,
|
|
9076
9177
|
sanitizeDocForAI,
|
|
9178
|
+
sanitizeNavigationLayout,
|
|
9077
9179
|
saveWorkflowDraft,
|
|
9078
9180
|
sectionLabel,
|
|
9079
9181
|
simplePublishingWorkflow,
|