@dyrected/core 2.14.0 → 2.16.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/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 BaseDocument, H as HookRequestContext, f as DetailComputedOptions, g as ComputedHandler, h as DetailComputed, i as DetailCustomOptions, j as DetailCustom, k as DetailDividerOptions, l as DetailDivider, m as DisplayFieldOptions, n as DetailField, o as DetailItem, p as DetailGridOptions, q as DetailGrid, r as DetailRepeatOptions, s as DetailRepeat, t as DetailSectionOptions, u as DetailSection, v as DetailTabOptions, w as DetailTab, x as DetailTabsOptions, y as DetailTabs, z as DetailTextOptions, E as DetailText, I as DetailSchema, J as DyrectedContext, K as AIConfig, M as AIPIIConfig, N as ArrayField, O as FieldType, Q as BooleanField, R as AuthConfig, S as AccessPolicyResolver, T as DateField, U as DateTimeField, V as EmailField, X as IconField, Y as ImageField, Z as JoinField, _ as JsonField, $ as MultiSelectField, a0 as NumberField, a1 as ObjectField, a2 as RadioField, a3 as RelationshipField, a4 as RichTextField, a5 as RowField, a6 as SelectField, a7 as TextField, a8 as TextareaField, a9 as TimeField, aa as UrlField } from './app-Cp8RudRI.js';
2
- export { ab as AIAction, ac as AIActionStatus, ad as AIActionType, ae as AIAuditActionType, af as AIAuditRecord, ag as AIChunk, ah as AIMessage, ai as AIPIIPattern, aj as AIRateLimitResult, ak as AIRateLimitStore, al as AIThread, am as AIToolContext, an as AIToolDefinition, ao as AI_ACTIONS_COLLECTION, ap as AI_AUDIT_COLLECTION, aq as AI_CHUNKS_COLLECTION, ar as AI_MESSAGES_COLLECTION, as as AI_THREADS_COLLECTION, at as AccessConfig, au as AccessFunction, av as AccessFunctionArgs, aw as AccessResult, ax as AccessRule, ay as ActionConfig, az as ActionConfigBase, aA as ActionConfigWithHandler, aB as ActionConfigWithMutation, aC as ActionContext, aD as ActionType, aE as AdminAuthAccessResolution, aF as AdminAuthClaimMapping, aG as AdminAuthMember, aH as AdminAuthProvider, aI as AdminAuthProviderMembersConfig, aJ as AdminAuthProvisioningMode, aK as AdminAuthResolveAccessArgs, aL as AdminAuthResolvedIdentity, aM as AdminConfig, aN as AdminDashboardComponentSlots, aO as AdminIconName, aP as AggregateArgs, aQ as AggregateCastType, aR as AggregateCollectionResult, aS as AggregateInput, aT as AggregateOperation, aU as AggregateResult, aV as BaseAdminAuthProvider, aW as BaseFieldAdmin, aX as BlockVariant, aY as BlocksField, aZ as BooleanFieldAdmin, a_ as BooleanFormat, a$ as CharacterLimitFieldAdmin, b0 as CharacterLimitFieldConfig, b1 as CollectionAfterChangeHook, b2 as CollectionAfterDeleteHook, b3 as CollectionAfterReadHook, b4 as CollectionAfterReadHookEntry, b5 as CollectionAfterTransitionHook, b6 as CollectionBeforeChangeHook, b7 as CollectionBeforeChangeHookEntry, b8 as CollectionBeforeDeleteHook, b9 as CollectionBeforeReadHook, ba as CollectionBeforeReadHookEntry, bb as CollectionBeforeTransitionHook, bc as CollectionListComponentSlots, bd as CollectionRAGConfig, be as CollectionSchemaResult, bf as CollectionSummaryResult, bg as CollectionViewComponentSlots, bh as CountOperation, bi as CustomAdminAuthProvider, bj as DatabaseAdapter, bk as DateFieldAdmin, bl as DateFormat, bm as DefaultValueContext, bn as DefineActionOptions, bo as DefineCalendarViewOptions, bp as DefineCardsViewOptions, bq as DefineGanttViewOptions, br as DefineKanbanViewOptions, bs as DefineTableViewOptions, bt as DefineViewBaseOptions, bu as DefineViewOptions, bv as DetailSpan, bw as DisplayTone, bx as DisplayVariant, by as DistinctCountOperation, bz as DistinctValuesOperation, bA as DynamicOptionItem, bB as DynamicOptionsConfig, bC as DynamicOptionsResolver, bD as DynamicOptionsResolverArgs, bE as DyrectedAIContext, bF as DyrectedLoggerConfig, bG as DyrectedObservabilityConfig, bH as EmailFieldAdmin, bI as FieldAdminHooks, bJ as FieldAdminOnChangeHook, bK as FieldAdminOnChangeHookArgs, bL as FieldAdminOptionsHook, bM as FieldAdminOptionsHookArgs, bN as FieldAdminOptionsHookResult, bO as FieldAfterReadHook, bP as FieldAfterReadHookArgs, bQ as FieldBase, bR as FieldBeforeChangeHook, bS as FieldBeforeChangeHookArgs, bT as FieldHook, bU as FieldHooks, bV as FileData, bW as GetDocumentResult, bX as GlobalAfterChangeHook, bY as GlobalAfterReadHook, bZ as GlobalAfterReadHookEntry, b_ as GlobalBeforeChangeHook, b$ as GlobalBeforeChangeHookEntry, c0 as GlobalBeforeReadHook, c1 as GlobalBeforeReadHookEntry, c2 as GlobalRAGConfig, c3 as GlobalSchemaResult, c4 as GlobalSummaryResult, c5 as HeadingLevel, c6 as HookFunction, c7 as IconFieldAdmin, c8 as ImageService, c9 as ImageTransformOptions, ca as InferAggregateResult, cb as JoinFieldAdmin, cc as JsonFieldAdmin, cd as JsonFormat, ce as LIFECYCLE_EVENT_NAMES, cf as LifecycleEventHandler, cg as LinkFormat, ch as MetricColor, ci as MultiSelectFieldAdmin, cj as NamedAccessPolicy, ck as NumberFieldAdmin, cl as NumberFormat, cm as NumberLimitFieldAdmin, cn as NumberLimitFieldConfig, co as NumericOperation, cp as OIDCAdminAuthProvider, cq as OptionFormat, cr as PaginatedResult, cs as PublicAdminAuthProvider, ct as QueryCollectionResult, cu as RAGSearchResult, cv as RadioFieldAdmin, cw as RateLimitConfig, cx as ReadonlyDatabaseAdapter, cy as RichTextFeature, cz as RichTextFieldConfig, cA as SelectFieldAdmin, cB as SqlWhereResult, cC as StorageAdapter, cD as TextFieldAdmin, cE as TextFormat, cF as TextareaFieldAdmin, cG as TrustProxyConfig, cH as TypedField, cI as UploadConfig, cJ as UrlFieldAdmin, cK as UrlLinkValue, cL as ViewActionFeatures, cM as ViewComponentSlots, cN as ViewConfig, cO as ViewLayout, cP as ViewMetric, cQ as ViewSubMetric, cR as WhereClause, cS as WhereOperator, cT as WhereOperatorName, cU as WordLimitFieldAdmin, cV as WordLimitFieldConfig, cW as WorkflowMetadata, cX as WorkflowRole, cY as WorkflowState, cZ as WorkflowTransitionContext, c_ as defineAction, c$ as defineCalendarView, d0 as defineCardsView, d1 as defineGanttView, d2 as defineKanbanView, d3 as defineTableView, d4 as defineView, d5 as isAICollection, d6 as parseMongoWhere, d7 as parseSqlWhere } from './app-Cp8RudRI.js';
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 BaseDocument, H as HookRequestContext, f as DetailActionOptions, g as DetailAction, h as DetailComputedOptions, i as ComputedHandler, j as DetailComputed, k as DetailCustomOptions, l as DetailCustom, m as DetailDividerOptions, n as DetailDivider, o as DisplayFieldOptions, p as DetailField, q as DetailItem, r as DetailGridOptions, s as DetailGrid, t as DetailRepeatOptions, u as DetailRepeat, v as DetailSectionOptions, w as DetailSection, x as DetailTabOptions, y as DetailTab, z as DetailTabsOptions, E as DetailTabs, I as DetailTextOptions, J as DetailText, K as DetailSchema, M as DyrectedContext, N as AIConfig, O as AIPIIConfig, Q as IdStrategy, R as ArrayField, S as FieldType, T as BooleanField, U as AuthConfig, V as AccessPolicyResolver, X as DateField, Y as DateTimeField, Z as EmailField, _ as IconField, $ as ImageField, a0 as JoinField, a1 as JsonField, a2 as MultiSelectField, a3 as NumberField, a4 as ObjectField, a5 as RadioField, a6 as RelationshipField, a7 as RichTextField, a8 as RowField, a9 as SelectField, aa as TextField, ab as TextareaField, ac as TimeField, ad as UrlField } from './app-KSDgfXsw.js';
2
+ export { ae as AIAction, af as AIActionStatus, ag as AIActionType, ah as AIAuditActionType, ai as AIAuditRecord, aj as AIChunk, ak as AIMessage, al as AIPIIPattern, am as AIRateLimitResult, an as AIRateLimitStore, ao as AIThread, ap as AIToolContext, aq as AIToolDefinition, ar as AI_ACTIONS_COLLECTION, as as AI_AUDIT_COLLECTION, at as AI_CHUNKS_COLLECTION, au as AI_MESSAGES_COLLECTION, av as AI_THREADS_COLLECTION, aw as AccessConfig, ax as AccessFunction, ay as AccessFunctionArgs, az as AccessResult, aA as AccessRule, aB as ActionConfig, aC as ActionConfigBase, aD as ActionConfigWithHandler, aE as ActionConfigWithMutation, aF as ActionContext, aG as ActionType, aH as AdminAuthAccessResolution, aI as AdminAuthClaimMapping, aJ as AdminAuthMember, aK as AdminAuthProvider, aL as AdminAuthProviderMembersConfig, aM as AdminAuthProvisioningMode, aN as AdminAuthResolveAccessArgs, aO as AdminAuthResolvedIdentity, aP as AdminConfig, aQ as AdminDashboardComponentSlots, aR as AdminIconName, aS as AggregateArgs, aT as AggregateCastType, aU as AggregateCollectionResult, aV as AggregateInput, aW as AggregateOperation, aX as AggregateResult, aY as BaseAdminAuthProvider, aZ as BaseFieldAdmin, a_ as BlockVariant, a$ as BlocksField, b0 as BooleanFieldAdmin, b1 as BooleanFormat, b2 as CharacterLimitFieldAdmin, b3 as CharacterLimitFieldConfig, b4 as CollectionAfterChangeHook, b5 as CollectionAfterDeleteHook, b6 as CollectionAfterReadHook, b7 as CollectionAfterReadHookEntry, b8 as CollectionAfterTransitionHook, b9 as CollectionBeforeChangeHook, ba as CollectionBeforeChangeHookEntry, bb as CollectionBeforeDeleteHook, bc as CollectionBeforeReadHook, bd as CollectionBeforeReadHookEntry, be as CollectionBeforeTransitionHook, bf as CollectionIndex, bg as CollectionListComponentSlots, bh as CollectionRAGConfig, bi as CollectionSchemaResult, bj as CollectionSummaryResult, bk as CollectionViewComponentSlots, bl as CountOperation, bm as CustomAdminAuthProvider, bn as DatabaseAdapter, bo as DateFieldAdmin, bp as DateFormat, bq as DefaultValueContext, br as DefineActionOptions, bs as DefineCalendarViewOptions, bt as DefineCardsViewOptions, bu as DefineGanttViewOptions, bv as DefineKanbanViewOptions, bw as DefineTableViewOptions, bx as DefineViewBaseOptions, by as DefineViewOptions, bz as DetailSpan, bA as DisplayTone, bB as DisplayVariant, bC as DistinctCountOperation, bD as DistinctValuesOperation, bE as DynamicOptionItem, bF as DynamicOptionsConfig, bG as DynamicOptionsResolver, bH as DynamicOptionsResolverArgs, bI as DyrectedAIContext, bJ as DyrectedLoggerConfig, bK as DyrectedObservabilityConfig, bL as EmailFieldAdmin, bM as FieldAdminHooks, bN as FieldAdminOnChangeHook, bO as FieldAdminOnChangeHookArgs, bP as FieldAdminOptionsHook, bQ as FieldAdminOptionsHookArgs, bR as FieldAdminOptionsHookResult, bS as FieldAfterReadHook, bT as FieldAfterReadHookArgs, bU as FieldBase, bV as FieldBeforeChangeHook, bW as FieldBeforeChangeHookArgs, bX as FieldHook, bY as FieldHooks, bZ as FileData, b_ as GetDocumentResult, b$ as GlobalAfterChangeHook, c0 as GlobalAfterReadHook, c1 as GlobalAfterReadHookEntry, c2 as GlobalBeforeChangeHook, c3 as GlobalBeforeChangeHookEntry, c4 as GlobalBeforeReadHook, c5 as GlobalBeforeReadHookEntry, c6 as GlobalRAGConfig, c7 as GlobalSchemaResult, c8 as GlobalSummaryResult, c9 as HeadingLevel, ca as HookFunction, cb as IconFieldAdmin, cc as ImageService, cd as ImageTransformOptions, ce as InferAggregateResult, cf as JoinFieldAdmin, cg as JsonFieldAdmin, ch as JsonFormat, ci as LIFECYCLE_EVENT_NAMES, cj as LifecycleEventHandler, ck as LinkFormat, cl as MetricColor, cm as MultiSelectFieldAdmin, cn as NamedAccessPolicy, co as NumberFieldAdmin, cp as NumberFormat, cq as NumberLimitFieldAdmin, cr as NumberLimitFieldConfig, cs as NumericOperation, ct as NumericUpdateOperator, cu as OIDCAdminAuthProvider, cv as OptionFormat, cw as PaginatedResult, cx as PublicAdminAuthProvider, cy as QueryCollectionResult, cz as RAGSearchResult, cA as RadioFieldAdmin, cB as RateLimitConfig, cC as ReadonlyDatabaseAdapter, cD as RichTextFeature, cE as RichTextFieldConfig, cF as SelectFieldAdmin, cG as SqlWhereResult, cH as StorageAdapter, cI as TextFieldAdmin, cJ as TextFormat, cK as TextareaFieldAdmin, cL as TrustProxyConfig, cM as TypedField, cN as UploadConfig, cO as UrlFieldAdmin, cP as UrlLinkValue, cQ as ViewActionFeatures, cR as ViewComponentSlots, cS as ViewConfig, cT as ViewLayout, cU as ViewMetric, cV as ViewSubMetric, cW as WhereClause, cX as WhereOperator, cY as WhereOperatorName, cZ as WordLimitFieldAdmin, c_ as WordLimitFieldConfig, c$ as WorkflowMetadata, d0 as WorkflowRole, d1 as WorkflowState, d2 as WorkflowTransitionContext, d3 as defineAction, d4 as defineCalendarView, d5 as defineCardsView, d6 as defineGanttView, d7 as defineKanbanView, d8 as defineTableView, d9 as defineView, da as isAICollection, db as parseMongoWhere, dc as parseSqlWhere } from './app-KSDgfXsw.js';
3
3
  import jexl from 'jexl';
4
4
  import { Context } from 'hono';
5
5
  export { z } from 'zod';
@@ -155,6 +155,57 @@ declare function getAdminRoleForCollection(collection?: CollectionConfig | null)
155
155
  */
156
156
  declare function isUserAdmin(user: any, collection?: CollectionConfig | null): boolean;
157
157
 
158
+ /**
159
+ * User-facing errors for self-hosted server code (action handlers, hooks).
160
+ *
161
+ * Throw these instead of hand-rolling `{ statusCode }` onto a plain `Error`.
162
+ * The action pipeline reads `statusCode` for the HTTP status (defaulting to
163
+ * `500` when absent) and `message` for the response body — which is what the
164
+ * SDK surfaces and the admin shows in its failure toast. Write the message
165
+ * for the editor who will read it.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * import { ValidationError } from "@dyrected/core";
170
+ *
171
+ * handler: async ({ input }) => {
172
+ * if (!input.refundReason) {
173
+ * throw new ValidationError("Enter a refund reason so support can follow up.");
174
+ * }
175
+ * return { status: "refunded" };
176
+ * }
177
+ * ```
178
+ */
179
+ declare class DyrectedError extends Error {
180
+ readonly statusCode: number;
181
+ constructor(message: string, statusCode?: number);
182
+ }
183
+ /** Bad input the editor can fix and retry. Answered with `400`. */
184
+ declare class ValidationError extends DyrectedError {
185
+ constructor(message: string);
186
+ }
187
+ /** The editor is not allowed to do this. Answered with `403`. */
188
+ declare class ForbiddenError extends DyrectedError {
189
+ constructor(message: string);
190
+ }
191
+ /** A referenced record does not exist. Answered with `404`. */
192
+ declare class NotFoundError extends DyrectedError {
193
+ constructor(message: string);
194
+ }
195
+ /** The current state conflicts with the requested change. Answered with `409`. */
196
+ declare class ConflictError extends DyrectedError {
197
+ constructor(message: string);
198
+ }
199
+ /** A unique constraint or unique index was violated on insert/update. Answered with `409`. */
200
+ declare class DuplicateKeyError extends ConflictError {
201
+ readonly field?: string;
202
+ readonly value?: any;
203
+ constructor(message: string, options?: {
204
+ field?: string;
205
+ value?: any;
206
+ });
207
+ }
208
+
158
209
  type SortDirection = 'ASC' | 'DESC';
159
210
  interface SortClause {
160
211
  field: string;
@@ -725,6 +776,17 @@ declare function displayCustom<TDoc = any>(name: string, options?: DetailCustomO
725
776
  * Alias for `displayCustom` to render a custom component in a Detail View layout.
726
777
  */
727
778
  declare function displayCustomComponent<TDoc = any>(name: string, options?: DetailCustomOptions<TDoc>): DetailCustom<TDoc>;
779
+ /**
780
+ * Renders a button for a named action (defined in `collection.actions`) at this
781
+ * position in a Detail View — the same action, dialog, and execution as the
782
+ * header toolbar, just placed inline.
783
+ *
784
+ * @example
785
+ * ```ts
786
+ * displayAction('markShipped', { variant: 'default', span: 4 })
787
+ * ```
788
+ */
789
+ declare function displayAction(name: string, options?: DetailActionOptions): DetailAction;
728
790
  /**
729
791
  * Evaluates server-side computed functions and JEXL expressions from a detail schema
730
792
  * and attaches them to `doc._meta.computed`.
@@ -1267,6 +1329,70 @@ interface SanitizeDocForAIOptions {
1267
1329
  */
1268
1330
  declare function sanitizeDocForAI(options: SanitizeDocForAIOptions): Record<string, unknown>;
1269
1331
 
1332
+ declare const NANOID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
1333
+ declare const BASE62_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1334
+ declare const CROCKFORD_BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
1335
+ /**
1336
+ * Generates an unbiased cryptographically secure NanoID string.
1337
+ *
1338
+ * @param size Number of characters to generate (default: 21)
1339
+ * @param alphabet Characters to draw from (default: URL-safe Base64 alphanumeric)
1340
+ */
1341
+ declare function nanoid(size?: number, alphabet?: string): string;
1342
+ /**
1343
+ * Generates a 26-character time-sortable ULID (Universally Unique Lexicographically Sortable Identifier).
1344
+ *
1345
+ * The first 10 characters encode the millisecond timestamp, followed by 16 cryptographically secure
1346
+ * random Crockford Base32 characters. ULIDs sort in chronological order, making them optimal
1347
+ * for B-tree index locality in relational databases.
1348
+ *
1349
+ * @param seedTime Optional millisecond timestamp (default: Date.now())
1350
+ */
1351
+ declare function ulid(seedTime?: number): string;
1352
+ /**
1353
+ * Standard RFC 4122 UUIDv4 generator wrapper.
1354
+ */
1355
+ declare function uuid(): string;
1356
+ /**
1357
+ * Resolves a clean 3-4 character prefix for a collection slug or explicit prefix.
1358
+ *
1359
+ * @example
1360
+ * resolvePrefix('cob-daily-reports') // 'cob'
1361
+ * resolvePrefix('ipo-reservations') // 'ipo'
1362
+ * resolvePrefix('users') // 'usr'
1363
+ * resolvePrefix('applications') // 'app'
1364
+ * resolvePrefix('anything', 'custom') // 'custom'
1365
+ */
1366
+ declare function resolvePrefix(slug?: string, explicitPrefix?: string): string;
1367
+ /**
1368
+ * Generates a Stripe-style prefixed NanoID (e.g. `col_k9pQ2mZwRtx89aB1`).
1369
+ *
1370
+ * Uses Base62 for the random suffix to prevent extra underscores and hyphens in the ID body.
1371
+ *
1372
+ * @param prefix Collection prefix (e.g. 'usr', 'cob', 'app', 'col')
1373
+ * @param size Length of the random suffix (default: 16)
1374
+ */
1375
+ declare function prefixedId(prefix?: string, size?: number): string;
1376
+
1377
+ interface GenerateIdOptions {
1378
+ prefix?: string;
1379
+ type?: IdStrategy;
1380
+ size?: number;
1381
+ }
1382
+ /**
1383
+ * Generates an ID according to the specified options. Defaults to Stripe-style prefixed NanoID.
1384
+ */
1385
+ declare function generateId(options?: GenerateIdOptions | string): string;
1386
+ /**
1387
+ * Generates a document ID based on collection configuration or slug.
1388
+ */
1389
+ declare function generateDocumentId(collectionOrSlug?: string | {
1390
+ slug: string;
1391
+ idPrefix?: string;
1392
+ idType?: IdStrategy;
1393
+ idGenerator?: (slug: string) => string;
1394
+ }): string;
1395
+
1270
1396
  type TopLevelFieldName<TFields extends readonly Field[]> = Extract<TFields[number], {
1271
1397
  name: string;
1272
1398
  }>["name"];
@@ -1763,4 +1889,4 @@ declare function defineTab<const T extends readonly Field[]>(args: {
1763
1889
  fields: T;
1764
1890
  }): T;
1765
1891
 
1766
- export { AIConfig, type AIErrorCode, AIPIIConfig, type AccessConditions, AccessPolicyResolver, AdminAuthConfig, ArrayField, AuthConfig, type AuthDocFields, AuthenticatedUser, BUILTIN_JEXL_HELPERS, BaseDocument, Block, BooleanField, CollectionConfig, ComputedHandler, type ConfigDiagnostic, ConfigValidationError, DateField, DateTimeField, type DeclarativeAccessSurface, type DeclarativeAccessValidationIssue, type DeclarativeAdminSurface, type DeclarativeAdminValidationIssue, DeclarativeHookExpression, type DeclarativeHookSurface, type DeclarativeHookValidationIssue, type DeclarativePreviewSurface, type DeclarativePreviewValidationIssue, DetailComputed, DetailComputedOptions, DetailCustom, DetailCustomOptions, DetailDivider, DetailDividerOptions, DetailField, DetailGrid, DetailGridOptions, DetailItem, DetailRepeat, DetailRepeatOptions, DetailSchema, DetailSection, DetailSectionOptions, DetailTab, DetailTabOptions, DetailTabs, DetailTabsOptions, DetailText, DetailTextOptions, DisplayFieldOptions, DyrectedAIError, DyrectedConfig, EmailField, type ExprFunction, type ExtractCollectionSlugs, Field, FieldConditionBuilder, FieldType, GlobalConfig, HookRequestContext, IconField, ImageField, type InferDocShape, JoinField, JsonField, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, MatchBuilder, MultiSelectField, NON_NEGOTIABLE_CREDENTIAL_FIELDS, NumberField, ObjectField, PII_REGEX_PATTERNS, type Prettify, PublicAdminAuthConfig, type PublishingWorkflowOptions, RadioField, RelationshipField, RichTextField, RowField, type SanitizeDocForAIOptions, SelectField, type SortClause, type SortDirection, type SqlSortDialect, type SystemDocFields, TextField, TextareaField, TimeField, type UploadDocFields, UrlField, WORKFLOW_HISTORY_COLLECTION, type WhenFunction, WorkflowConfig, WorkflowTransition, abs, addDays, asCollection, assertValidAdminConditionsInConfig, assertValidDeclarativeAccessInConfig, assertValidDeclarativeHookExpression, assertValidDeclarativeHookResult, assertValidDeclarativeHooksInConfig, assertValidPreviewUrlsInConfig, availableWorkflowTransitions, buildSqlOrderBy, canViewWorkflowDraft, capitalize, ceil, clamp, coalesce, collectAdminConditionValidationIssues, collectConfigDiagnostics, collectDeclarativeAccessValidationIssues, collectDeclarativeHookValidationIssues, collectPreviewUrlValidationIssues, compact, count, createLifecycleEvent, createWorkflowDocument, defaultValue, defineArrayField, defineBlock, defineBlocksField, defineBooleanField, defineCollection, defineConfig, defineDateField, defineDateTimeField, defineEmailField, defineField, defineGlobal, defineIconField, defineImageField, defineJoinField, defineJsonField, defineMultiSelectField, defineNumberField, defineObjectField, definePublishingWorkflow, defineRadioField, defineRelationshipField, defineRichTextField, defineRowField, defineSelectField, defineTab, defineTextField, defineTextareaField, defineTimeField, defineUrlField, diffDays, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, displayComputed, displayCustom, displayCustomComponent, displayDivider, displayField, displayGrid, displayRepeat, displaySection, displayTab, displayTabs, displayText, endsWith, evaluateDetailComputed, evaluateJexl, evaluateJexlSync, executeFieldAfterRead, executeFieldBeforeChange, expr, first, floor, formatConfigDiagnostics, formatDate, formatJexlValue, generateDefaultDetailSchema, generateOpenApi, get, getAdminAuthCollection, getAdminRoleForCollection, getAllowedSitesForUser, getPublicAdminAuthConfig, includes, initializeWorkflowDocument, isConfigValidationError, isDetailItemVisible, isEmpty, isFuture, isPast, isSiteAuthorized, isUserAdmin, join, last, length, lower, maskEmail, maskPhone, maskTextPII, materializeWorkflowDocument, max, min, normalizeConfig, normalizeDetailItem, now, numericFieldNames, parseSort, pow, publishedStateName, publishingWorkflow, readingTime, registerJexlHelpers, replace, resolveAdminAuthCollection, resolveAuthorizedSiteId, round, runCollectionHooks, sanitizeDocForAI, saveWorkflowDraft, simplePublishingWorkflow, slugify, sqrt, startsWith, sum, today, transitionWorkflow, trim, truncate, unique, upper, validateAdminConditionExpression, validateDeclarativeAccessExpression, validateDeclarativeHookExpression, validatePreviewUrlExpression, when, wordCount, workflowCapabilities };
1892
+ export { AIConfig, type AIErrorCode, AIPIIConfig, type AccessConditions, AccessPolicyResolver, AdminAuthConfig, ArrayField, AuthConfig, type AuthDocFields, AuthenticatedUser, BASE62_ALPHABET, BUILTIN_JEXL_HELPERS, BaseDocument, Block, BooleanField, CROCKFORD_BASE32, CollectionConfig, ComputedHandler, type ConfigDiagnostic, ConfigValidationError, ConflictError, DateField, DateTimeField, type DeclarativeAccessSurface, type DeclarativeAccessValidationIssue, type DeclarativeAdminSurface, type DeclarativeAdminValidationIssue, DeclarativeHookExpression, type DeclarativeHookSurface, type DeclarativeHookValidationIssue, type DeclarativePreviewSurface, type DeclarativePreviewValidationIssue, 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, EmailField, type ExprFunction, type ExtractCollectionSlugs, Field, FieldConditionBuilder, FieldType, ForbiddenError, type GenerateIdOptions, GlobalConfig, HookRequestContext, IconField, IdStrategy, ImageField, type InferDocShape, JoinField, JsonField, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, MatchBuilder, MultiSelectField, NANOID_ALPHABET, NON_NEGOTIABLE_CREDENTIAL_FIELDS, NotFoundError, NumberField, ObjectField, PII_REGEX_PATTERNS, type Prettify, PublicAdminAuthConfig, type PublishingWorkflowOptions, RadioField, RelationshipField, RichTextField, RowField, type SanitizeDocForAIOptions, SelectField, type SortClause, type SortDirection, type SqlSortDialect, type SystemDocFields, TextField, TextareaField, TimeField, type UploadDocFields, UrlField, ValidationError, WORKFLOW_HISTORY_COLLECTION, type WhenFunction, WorkflowConfig, WorkflowTransition, abs, addDays, asCollection, assertValidAdminConditionsInConfig, assertValidDeclarativeAccessInConfig, assertValidDeclarativeHookExpression, assertValidDeclarativeHookResult, assertValidDeclarativeHooksInConfig, assertValidPreviewUrlsInConfig, availableWorkflowTransitions, buildSqlOrderBy, canViewWorkflowDraft, capitalize, ceil, clamp, coalesce, collectAdminConditionValidationIssues, collectConfigDiagnostics, collectDeclarativeAccessValidationIssues, collectDeclarativeHookValidationIssues, collectPreviewUrlValidationIssues, compact, count, createLifecycleEvent, createWorkflowDocument, defaultValue, defineArrayField, defineBlock, defineBlocksField, defineBooleanField, defineCollection, defineConfig, defineDateField, defineDateTimeField, defineEmailField, defineField, defineGlobal, defineIconField, defineImageField, defineJoinField, defineJsonField, defineMultiSelectField, defineNumberField, defineObjectField, definePublishingWorkflow, defineRadioField, defineRelationshipField, defineRichTextField, defineRowField, defineSelectField, defineTab, defineTextField, defineTextareaField, defineTimeField, defineUrlField, diffDays, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, displayAction, displayComputed, displayCustom, displayCustomComponent, displayDivider, displayField, displayGrid, displayRepeat, displaySection, displayTab, displayTabs, displayText, endsWith, evaluateDetailComputed, evaluateJexl, evaluateJexlSync, executeFieldAfterRead, executeFieldBeforeChange, expr, first, floor, formatConfigDiagnostics, formatDate, formatJexlValue, generateDefaultDetailSchema, generateDocumentId, generateId, generateOpenApi, get, getAdminAuthCollection, getAdminRoleForCollection, getAllowedSitesForUser, getPublicAdminAuthConfig, includes, initializeWorkflowDocument, isConfigValidationError, isDetailItemVisible, isEmpty, isFuture, isPast, isSiteAuthorized, isUserAdmin, join, last, length, lower, maskEmail, maskPhone, maskTextPII, materializeWorkflowDocument, max, min, nanoid, normalizeConfig, normalizeDetailItem, now, numericFieldNames, parseSort, pow, prefixedId, publishedStateName, publishingWorkflow, readingTime, registerJexlHelpers, replace, resolveAdminAuthCollection, resolveAuthorizedSiteId, resolvePrefix, round, runCollectionHooks, sanitizeDocForAI, saveWorkflowDraft, simplePublishingWorkflow, slugify, sqrt, startsWith, sum, today, transitionWorkflow, trim, truncate, ulid, unique, upper, uuid, validateAdminConditionExpression, validateDeclarativeAccessExpression, validateDeclarativeHookExpression, validatePreviewUrlExpression, when, wordCount, workflowCapabilities };
package/dist/index.js CHANGED
@@ -3363,6 +3363,134 @@ function assertValidDeclarativeAccessInConfig(config, source = "config") {
3363
3363
  throw new ConfigValidationError(source, diagnostics);
3364
3364
  }
3365
3365
 
3366
+ // src/utils/id.ts
3367
+ import { randomBytes, randomUUID } from "crypto";
3368
+ var NANOID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
3369
+ var BASE62_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
3370
+ var CROCKFORD_BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
3371
+ var COMMON_SLUG_PREFIXES = {
3372
+ users: "usr",
3373
+ members: "mem",
3374
+ accounts: "acc",
3375
+ applications: "app",
3376
+ customers: "cus",
3377
+ products: "prd",
3378
+ orders: "ord",
3379
+ reports: "rpt",
3380
+ sessions: "ses",
3381
+ transactions: "txn",
3382
+ wallets: "wal",
3383
+ media: "med",
3384
+ files: "fil",
3385
+ posts: "post",
3386
+ pages: "page",
3387
+ tags: "tag",
3388
+ categories: "cat",
3389
+ comments: "com"
3390
+ };
3391
+ function nanoid(size = 21, alphabet = NANOID_ALPHABET) {
3392
+ const mask = (2 << 31 - Math.clz32(alphabet.length - 1 | 1)) - 1;
3393
+ const step = Math.ceil(1.6 * mask * size / alphabet.length);
3394
+ let id = "";
3395
+ while (true) {
3396
+ const bytes = randomBytes(step);
3397
+ for (let i = 0; i < step; i++) {
3398
+ const byte = bytes[i] & mask;
3399
+ if (alphabet[byte]) {
3400
+ id += alphabet[byte];
3401
+ if (id.length === size) return id;
3402
+ }
3403
+ }
3404
+ }
3405
+ }
3406
+ function encodeUlidTime(now2, len = 10) {
3407
+ let str = "";
3408
+ let time = Math.floor(now2);
3409
+ for (let i = len - 1; i >= 0; i--) {
3410
+ const mod = time % 32;
3411
+ str = CROCKFORD_BASE32[mod] + str;
3412
+ time = (time - mod) / 32;
3413
+ }
3414
+ return str;
3415
+ }
3416
+ function encodeUlidRandom(bytes) {
3417
+ let str = "";
3418
+ let bitBuffer = 0;
3419
+ let bitsInBuffer = 0;
3420
+ for (let i = 0; i < bytes.length; i++) {
3421
+ bitBuffer = bitBuffer << 8 | bytes[i];
3422
+ bitsInBuffer += 8;
3423
+ while (bitsInBuffer >= 5) {
3424
+ bitsInBuffer -= 5;
3425
+ const index = bitBuffer >> bitsInBuffer & 31;
3426
+ str += CROCKFORD_BASE32[index];
3427
+ }
3428
+ }
3429
+ return str;
3430
+ }
3431
+ function ulid(seedTime = Date.now()) {
3432
+ const timePart = encodeUlidTime(seedTime);
3433
+ const randPart = encodeUlidRandom(randomBytes(10));
3434
+ return timePart + randPart;
3435
+ }
3436
+ function uuid() {
3437
+ return randomUUID();
3438
+ }
3439
+ function resolvePrefix(slug, explicitPrefix) {
3440
+ if (explicitPrefix && typeof explicitPrefix === "string" && explicitPrefix.trim().length > 0) {
3441
+ const cleaned = explicitPrefix.trim().toLowerCase().replace(/[^a-z0-9_]/g, "");
3442
+ if (cleaned.length > 0) return cleaned;
3443
+ }
3444
+ if (!slug || typeof slug !== "string") return "col";
3445
+ const s = slug.trim().toLowerCase();
3446
+ if (COMMON_SLUG_PREFIXES[s]) return COMMON_SLUG_PREFIXES[s];
3447
+ const pieces = s.split(/[-_]/).filter(Boolean);
3448
+ if (pieces.length > 1 && pieces[0].length >= 2) {
3449
+ const first2 = pieces[0].replace(/[^a-z0-9]/g, "");
3450
+ if (first2.length >= 2) return first2.slice(0, 4);
3451
+ }
3452
+ const cleanWord = s.replace(/[^a-z0-9]/g, "");
3453
+ if (cleanWord.length <= 4) return cleanWord || "col";
3454
+ return cleanWord.slice(0, 3) || "col";
3455
+ }
3456
+ function prefixedId(prefix = "col", size = 16) {
3457
+ const cleanPrefix = (prefix || "col").toLowerCase().replace(/[^a-z0-9_]/g, "") || "col";
3458
+ return `${cleanPrefix}_${nanoid(size, BASE62_ALPHABET)}`;
3459
+ }
3460
+ function generateId(options) {
3461
+ if (typeof options === "string") {
3462
+ return prefixedId(resolvePrefix(options));
3463
+ }
3464
+ const opts = options || {};
3465
+ const type = opts.type || "prefixed-nanoid";
3466
+ switch (type) {
3467
+ case "uuid":
3468
+ return uuid();
3469
+ case "ulid":
3470
+ return ulid();
3471
+ case "nanoid":
3472
+ return nanoid(opts.size || 21);
3473
+ case "prefixed-nanoid":
3474
+ default:
3475
+ return prefixedId(opts.prefix || "col", opts.size || 16);
3476
+ }
3477
+ }
3478
+ function generateDocumentId(collectionOrSlug) {
3479
+ if (!collectionOrSlug) {
3480
+ return prefixedId("col");
3481
+ }
3482
+ if (typeof collectionOrSlug === "string") {
3483
+ const prefix2 = resolvePrefix(collectionOrSlug);
3484
+ return prefixedId(prefix2);
3485
+ }
3486
+ if (typeof collectionOrSlug.idGenerator === "function") {
3487
+ return collectionOrSlug.idGenerator(collectionOrSlug.slug);
3488
+ }
3489
+ const type = collectionOrSlug.idType || "prefixed-nanoid";
3490
+ const prefix = resolvePrefix(collectionOrSlug.slug, collectionOrSlug.idPrefix);
3491
+ return generateId({ prefix, type });
3492
+ }
3493
+
3366
3494
  // src/utils/config.ts
3367
3495
  var AUDIT_COLLECTION_SLUG = "__audit";
3368
3496
  var SYSTEM_FIELDS = [
@@ -3684,11 +3812,31 @@ function normalizeConfig(config) {
3684
3812
  }
3685
3813
  const updatedFieldNames = new Set(fields.map((f) => f.name));
3686
3814
  const fieldsToInject = SYSTEM_FIELDS.filter((f) => !updatedFieldNames.has(f.name));
3815
+ const indexedFieldNames = /* @__PURE__ */ new Set();
3816
+ if (col.indexes) {
3817
+ for (const idx of col.indexes) {
3818
+ if (Array.isArray(idx.fields)) {
3819
+ for (const f of idx.fields) {
3820
+ indexedFieldNames.add(f);
3821
+ }
3822
+ }
3823
+ }
3824
+ }
3825
+ const allFields = [...fields, ...fieldsToInject].map((field) => {
3826
+ if (field.unique || field.name && indexedFieldNames.has(field.name)) {
3827
+ return { ...field, promoted: true };
3828
+ }
3829
+ return field;
3830
+ });
3687
3831
  const workflow = col.workflow || (col.drafts ? simplePublishingWorkflow() : void 0);
3832
+ const idPrefix = col.idPrefix || resolvePrefix(col.slug);
3833
+ const idType = col.idType || "prefixed-nanoid";
3688
3834
  return {
3689
3835
  ...col,
3836
+ idPrefix,
3837
+ idType,
3690
3838
  workflow,
3691
- fields: [...fields, ...fieldsToInject]
3839
+ fields: allFields
3692
3840
  };
3693
3841
  });
3694
3842
  const hasAuditCollection = normalizedCollections.some((col) => col.slug === AUDIT_COLLECTION_SLUG);
@@ -3710,6 +3858,56 @@ function normalizeConfig(config) {
3710
3858
  };
3711
3859
  }
3712
3860
 
3861
+ // src/utils/errors.ts
3862
+ var DyrectedError = class _DyrectedError extends Error {
3863
+ statusCode;
3864
+ constructor(message, statusCode = 500) {
3865
+ super(message);
3866
+ this.name = "DyrectedError";
3867
+ this.statusCode = statusCode;
3868
+ Object.setPrototypeOf(this, _DyrectedError.prototype);
3869
+ }
3870
+ };
3871
+ var ValidationError = class _ValidationError extends DyrectedError {
3872
+ constructor(message) {
3873
+ super(message, 400);
3874
+ this.name = "ValidationError";
3875
+ Object.setPrototypeOf(this, _ValidationError.prototype);
3876
+ }
3877
+ };
3878
+ var ForbiddenError = class _ForbiddenError extends DyrectedError {
3879
+ constructor(message) {
3880
+ super(message, 403);
3881
+ this.name = "ForbiddenError";
3882
+ Object.setPrototypeOf(this, _ForbiddenError.prototype);
3883
+ }
3884
+ };
3885
+ var NotFoundError = class _NotFoundError extends DyrectedError {
3886
+ constructor(message) {
3887
+ super(message, 404);
3888
+ this.name = "NotFoundError";
3889
+ Object.setPrototypeOf(this, _NotFoundError.prototype);
3890
+ }
3891
+ };
3892
+ var ConflictError = class _ConflictError extends DyrectedError {
3893
+ constructor(message) {
3894
+ super(message, 409);
3895
+ this.name = "ConflictError";
3896
+ Object.setPrototypeOf(this, _ConflictError.prototype);
3897
+ }
3898
+ };
3899
+ var DuplicateKeyError = class _DuplicateKeyError extends ConflictError {
3900
+ field;
3901
+ value;
3902
+ constructor(message, options) {
3903
+ super(message);
3904
+ this.name = "DuplicateKeyError";
3905
+ this.field = options?.field;
3906
+ this.value = options?.value;
3907
+ Object.setPrototypeOf(this, _DuplicateKeyError.prototype);
3908
+ }
3909
+ };
3910
+
3713
3911
  // src/utils/parse-where.ts
3714
3912
  function assertNever(op, context) {
3715
3913
  throw new Error(`[dyrected/core] Unhandled where operator "${op}" in ${context}`);
@@ -5569,6 +5767,13 @@ function displayCustom(name, options) {
5569
5767
  function displayCustomComponent(name, options) {
5570
5768
  return displayCustom(name, options);
5571
5769
  }
5770
+ function displayAction(name, options) {
5771
+ return {
5772
+ type: "action",
5773
+ name,
5774
+ options
5775
+ };
5776
+ }
5572
5777
  async function evaluateDetailComputed(detail, doc, user, db) {
5573
5778
  if (!doc || !detail || !Array.isArray(detail)) {
5574
5779
  return doc;
@@ -5641,6 +5846,12 @@ function generateDefaultDetailSchema(schema) {
5641
5846
  if (SENSITIVE_DETAIL_FIELDS.has(field.name)) continue;
5642
5847
  if (field.hidden) continue;
5643
5848
  if (field.admin?.hidden) continue;
5849
+ if (field.type === "join") {
5850
+ const joinColumns = field.admin?.columns;
5851
+ const repeatItems = Array.isArray(joinColumns) && joinColumns.length > 0 ? joinColumns.map((col) => displayField(col, { span: 12 })) : [displayComputed("Item", "doc.title || doc.name || doc.label || doc.slug || doc.id")];
5852
+ mainFields.push(displayRepeat(field.name, repeatItems, { span: 12, layout: "table" }));
5853
+ continue;
5854
+ }
5644
5855
  const isSidebar = sidebarFieldTypes.has(field.type) && field.type !== "relationship" && !field.hasMany;
5645
5856
  if (isSidebar && sidebarFields.length < 5) {
5646
5857
  sidebarFields.push(
@@ -6380,15 +6591,24 @@ export {
6380
6591
  AI_CHUNKS_COLLECTION,
6381
6592
  AI_MESSAGES_COLLECTION,
6382
6593
  AI_THREADS_COLLECTION,
6594
+ BASE62_ALPHABET,
6383
6595
  BUILTIN_JEXL_HELPERS,
6596
+ CROCKFORD_BASE32,
6384
6597
  ConfigValidationError,
6598
+ ConflictError,
6599
+ DuplicateKeyError,
6385
6600
  DyrectedAIError,
6601
+ DyrectedError,
6386
6602
  FieldConditionBuilder,
6603
+ ForbiddenError,
6387
6604
  LIFECYCLE_EVENTS_COLLECTION,
6388
6605
  LIFECYCLE_EVENT_NAMES,
6389
6606
  MatchBuilder,
6607
+ NANOID_ALPHABET,
6390
6608
  NON_NEGOTIABLE_CREDENTIAL_FIELDS,
6609
+ NotFoundError,
6391
6610
  PII_REGEX_PATTERNS,
6611
+ ValidationError,
6392
6612
  WORKFLOW_HISTORY_COLLECTION,
6393
6613
  abs,
6394
6614
  addDays,
@@ -6455,6 +6675,7 @@ export {
6455
6675
  diffDays,
6456
6676
  dispatchLifecycleEvent,
6457
6677
  dispatchPendingLifecycleEvents,
6678
+ displayAction,
6458
6679
  displayComputed,
6459
6680
  displayCustom,
6460
6681
  displayCustomComponent,
@@ -6479,6 +6700,8 @@ export {
6479
6700
  formatDate,
6480
6701
  formatJexlValue,
6481
6702
  generateDefaultDetailSchema,
6703
+ generateDocumentId,
6704
+ generateId,
6482
6705
  generateOpenApi,
6483
6706
  get,
6484
6707
  getAdminAuthCollection,
@@ -6505,6 +6728,7 @@ export {
6505
6728
  materializeWorkflowDocument,
6506
6729
  max,
6507
6730
  min,
6731
+ nanoid,
6508
6732
  normalizeConfig,
6509
6733
  normalizeDetailItem,
6510
6734
  now,
@@ -6513,6 +6737,7 @@ export {
6513
6737
  parseSort,
6514
6738
  parseSqlWhere,
6515
6739
  pow,
6740
+ prefixedId,
6516
6741
  publishedStateName,
6517
6742
  publishingWorkflow,
6518
6743
  readingTime,
@@ -6520,6 +6745,7 @@ export {
6520
6745
  replace,
6521
6746
  resolveAdminAuthCollection,
6522
6747
  resolveAuthorizedSiteId,
6748
+ resolvePrefix,
6523
6749
  round,
6524
6750
  runCollectionHooks,
6525
6751
  sanitizeDocForAI,
@@ -6533,8 +6759,10 @@ export {
6533
6759
  transitionWorkflow,
6534
6760
  trim,
6535
6761
  truncate,
6762
+ ulid,
6536
6763
  unique,
6537
6764
  upper,
6765
+ uuid,
6538
6766
  validateAdminConditionExpression,
6539
6767
  validateDeclarativeAccessExpression,
6540
6768
  validateDeclarativeHookExpression,