@dyrected/core 2.16.0 → 2.18.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-Dd9cBbCs.d.cts} +1460 -1184
- package/dist/{app-KSDgfXsw.d.ts → app-Dd9cBbCs.d.ts} +1460 -1184
- package/dist/index.cjs +988 -6
- package/dist/index.d.cts +155 -4
- package/dist/index.d.ts +155 -4
- package/dist/index.js +969 -6
- package/dist/server.cjs +1079 -40
- package/dist/server.d.cts +20 -4
- package/dist/server.d.ts +20 -4
- package/dist/server.js +1078 -40
- package/package.json +1 -1
|
@@ -446,1356 +446,1529 @@ declare const AI_ACTIONS_COLLECTION = "_dyrected_ai_actions";
|
|
|
446
446
|
declare const AI_AUDIT_COLLECTION = "_dyrected_ai_audit";
|
|
447
447
|
declare function isAICollection(slug: string): boolean;
|
|
448
448
|
|
|
449
|
-
/** A valid icon component name from the Lucide icon set bundled with Dyrected Admin. */
|
|
450
|
-
type AdminIconName = keyof typeof icons;
|
|
451
|
-
/** Ordered custom component keys rendered around the built-in Admin dashboard. */
|
|
452
|
-
interface AdminDashboardComponentSlots {
|
|
453
|
-
beforeDashboard?: string[];
|
|
454
|
-
afterDashboard?: string[];
|
|
455
|
-
}
|
|
456
|
-
/** Ordered custom component keys rendered around an operational view's content. */
|
|
457
|
-
interface CollectionViewComponentSlots {
|
|
458
|
-
beforeViewHeader?: string[];
|
|
459
|
-
afterViewHeader?: string[];
|
|
460
|
-
beforeViewContent?: string[];
|
|
461
|
-
afterViewContent?: string[];
|
|
462
|
-
}
|
|
463
|
-
/** Ordered custom component keys rendered around a collection's list content. */
|
|
464
|
-
interface CollectionListComponentSlots {
|
|
465
|
-
beforeList?: string[];
|
|
466
|
-
beforeListTable?: string[];
|
|
467
|
-
afterListTable?: string[];
|
|
468
|
-
afterList?: string[];
|
|
469
|
-
beforeViewHeader?: string[];
|
|
470
|
-
afterViewHeader?: string[];
|
|
471
|
-
beforeViewContent?: string[];
|
|
472
|
-
afterViewContent?: string[];
|
|
473
|
-
collectionView?: CollectionViewComponentSlots;
|
|
474
|
-
}
|
|
475
449
|
/**
|
|
476
|
-
*
|
|
450
|
+
* The set of type-cast operations supported during aggregation.
|
|
477
451
|
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
* logo: '/logo.svg',
|
|
482
|
-
* primaryColor: '#6366f1',
|
|
483
|
-
* },
|
|
484
|
-
* meta: {
|
|
485
|
-
* titleSuffix: '- My App',
|
|
486
|
-
* },
|
|
487
|
-
* }
|
|
488
|
-
*/
|
|
489
|
-
interface AdminConfig {
|
|
490
|
-
/** Custom component slots around the built-in dashboard. */
|
|
491
|
-
components?: AdminDashboardComponentSlots;
|
|
492
|
-
branding?: {
|
|
493
|
-
/** Full logo image shown in the expanded sidebar. URL or imported image asset. */
|
|
494
|
-
logo?: string;
|
|
495
|
-
/** Compact logo mark used in the collapsed sidebar state. */
|
|
496
|
-
logoMark?: string;
|
|
497
|
-
/** Text alternative or addition to the logo image. */
|
|
498
|
-
logoText?: string;
|
|
499
|
-
/**
|
|
500
|
-
* Brand colour used for committed, filled actions — Save, Create, Upload —
|
|
501
|
-
* and active/selected states. Accepts a hex string, a named colour
|
|
502
|
-
* (`amber`, `lime`, `violet`, `green`, `blue`, `red`, `purple`, `orange`),
|
|
503
|
-
* or a raw HSL triplet (`"217 91% 60%"`). Applied in both light and dark mode.
|
|
504
|
-
*
|
|
505
|
-
* This is one half of the two-colour brand model. Use {@link accentColor}
|
|
506
|
-
* for links and navigation accents. If you only set `primaryColor`, it is
|
|
507
|
-
* reused for accents too, matching the single-brand-colour look.
|
|
508
|
-
* @example '#6366f1'
|
|
509
|
-
* @example 'blue'
|
|
510
|
-
* @example 'hsl(240 50% 60%)'
|
|
511
|
-
*/
|
|
512
|
-
primaryColor?: string;
|
|
513
|
-
/**
|
|
514
|
-
* Brand colour used for links, active navigation details, hover text, and
|
|
515
|
-
* focus rings — the "accent" half of the two-colour brand model, mapped to
|
|
516
|
-
* the admin's `--intelligence` token. Accepts the same formats as
|
|
517
|
-
* {@link primaryColor} and applies in both light and dark mode.
|
|
518
|
-
*
|
|
519
|
-
* Set this when your brand has a distinct link/accent colour separate from
|
|
520
|
-
* your primary action colour. When omitted, accents fall back to
|
|
521
|
-
* `primaryColor` (if set) or the built-in default.
|
|
522
|
-
* @example '#8b5cf6'
|
|
523
|
-
* @example 'violet'
|
|
524
|
-
*/
|
|
525
|
-
accentColor?: string;
|
|
526
|
-
/** Browser tab favicon URL. */
|
|
527
|
-
favicon?: string;
|
|
528
|
-
/** Font family for body and UI text. Must be loaded separately. */
|
|
529
|
-
fontSans?: string;
|
|
530
|
-
/** Font family for headings. Must be loaded separately. */
|
|
531
|
-
fontSerif?: string;
|
|
532
|
-
};
|
|
533
|
-
meta?: {
|
|
534
|
-
/**
|
|
535
|
-
* String appended to every Admin page's `<title>`.
|
|
536
|
-
* @default '- Dyrected'
|
|
537
|
-
*/
|
|
538
|
-
titleSuffix?: string;
|
|
539
|
-
};
|
|
540
|
-
/**
|
|
541
|
-
* The canonical/base URL of the frontend website for links and iframe live previews.
|
|
542
|
-
*/
|
|
543
|
-
siteUrl?: string;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
type DeclarativeHookExpression = string;
|
|
547
|
-
/**
|
|
548
|
-
* @deprecated Use {@link FieldBeforeChangeHook} or `FieldAfterReadHook` instead.
|
|
549
|
-
* This alias remains for backwards compatibility.
|
|
452
|
+
* Each adapter maps these to its own native conversion primitive
|
|
453
|
+
* (e.g. `$toDouble` in MongoDB, `CAST(x AS REAL)` in SQLite).
|
|
454
|
+
* The public API is always database-independent.
|
|
550
455
|
*/
|
|
551
|
-
type
|
|
456
|
+
type AggregateCastType = "number" | "integer" | "float" | "string" | "boolean" | "date";
|
|
552
457
|
/**
|
|
553
|
-
*
|
|
458
|
+
* A `count` aggregate operation.
|
|
554
459
|
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
460
|
+
* - `count: "*"` — count every document matched by `where`.
|
|
461
|
+
* - `cast` is intentionally absent: counting is document-level,
|
|
462
|
+
* not field-value-level, so type conversion has no meaning here.
|
|
557
463
|
*/
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
db: ReadonlyDatabaseAdapter;
|
|
563
|
-
}) => Record<string, unknown> | void | Promise<Record<string, unknown> | void>;
|
|
564
|
-
type CollectionBeforeReadHookEntry = CollectionBeforeReadHook | DeclarativeHookExpression;
|
|
464
|
+
interface CountOperation {
|
|
465
|
+
count: "*";
|
|
466
|
+
where?: Record<string, unknown>;
|
|
467
|
+
}
|
|
565
468
|
/**
|
|
566
|
-
*
|
|
567
|
-
*
|
|
469
|
+
* A `countDistinct` aggregate operation that counts the number of unique
|
|
470
|
+
* non-null values for a specific field.
|
|
568
471
|
*/
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
db: ReadonlyDatabaseAdapter;
|
|
574
|
-
}) => TDoc | Promise<TDoc>;
|
|
575
|
-
type CollectionAfterReadHookEntry<TDoc extends object = Record<string, unknown>> = CollectionAfterReadHook<TDoc> | DeclarativeHookExpression;
|
|
472
|
+
interface DistinctCountOperation {
|
|
473
|
+
countDistinct: string;
|
|
474
|
+
where?: Record<string, unknown>;
|
|
475
|
+
}
|
|
576
476
|
/**
|
|
577
|
-
*
|
|
477
|
+
* A `distinct` aggregate operation that retrieves the unique values
|
|
478
|
+
* (or unique values with item counts) for a specific field.
|
|
578
479
|
*/
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
user?: AuthenticatedUser;
|
|
584
|
-
operation: "create" | "update";
|
|
585
|
-
db: ReadonlyDatabaseAdapter;
|
|
586
|
-
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;
|
|
587
|
-
type CollectionBeforeChangeHookEntry<TDoc extends object = Record<string, unknown>> = CollectionBeforeChangeHook<TDoc> | DeclarativeHookExpression;
|
|
480
|
+
interface DistinctValuesOperation {
|
|
481
|
+
distinct: string;
|
|
482
|
+
where?: Record<string, unknown>;
|
|
483
|
+
}
|
|
588
484
|
/**
|
|
589
|
-
*
|
|
485
|
+
* A `sum`, `avg`, `min`, or `max` aggregate operation on a named field.
|
|
486
|
+
*
|
|
487
|
+
* - `cast` converts stored values before the aggregation runs.
|
|
488
|
+
* Invalid values (e.g. `"unknown"` cast to `number`) become `null`
|
|
489
|
+
* and are ignored by `sum`, `avg`, `min`, and `max`.
|
|
590
490
|
*/
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
}
|
|
491
|
+
interface NumericOperation {
|
|
492
|
+
sum?: string;
|
|
493
|
+
avg?: string;
|
|
494
|
+
min?: string;
|
|
495
|
+
max?: string;
|
|
496
|
+
cast?: AggregateCastType;
|
|
497
|
+
where?: Record<string, unknown>;
|
|
498
|
+
}
|
|
599
499
|
/**
|
|
600
|
-
*
|
|
500
|
+
* A single named aggregate request — either a count, distinct count, distinct values, or numeric operation.
|
|
601
501
|
*/
|
|
602
|
-
type
|
|
603
|
-
id: string;
|
|
604
|
-
doc: TDoc;
|
|
605
|
-
req: HookRequestContext;
|
|
606
|
-
user?: AuthenticatedUser;
|
|
607
|
-
db: ReadonlyDatabaseAdapter;
|
|
608
|
-
}) => void | Promise<void>;
|
|
502
|
+
type AggregateOperation = CountOperation | DistinctCountOperation | DistinctValuesOperation | NumericOperation;
|
|
609
503
|
/**
|
|
610
|
-
*
|
|
504
|
+
* The map of named aggregate operations sent in a single aggregate request.
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* ```ts
|
|
508
|
+
* {
|
|
509
|
+
* totalSubmitted: { count: "*" },
|
|
510
|
+
* uniqueGuests: { countDistinct: "email" },
|
|
511
|
+
* availableSizes: { distinct: "asoebiSize" },
|
|
512
|
+
* totalAsoebiYards: { sum: "asoebiYards", cast: "number", where: { wantsAsoebi: { equals: true } } },
|
|
513
|
+
* }
|
|
514
|
+
* ```
|
|
611
515
|
*/
|
|
612
|
-
type
|
|
613
|
-
id: string;
|
|
614
|
-
doc: TDoc;
|
|
615
|
-
req: HookRequestContext;
|
|
616
|
-
user?: AuthenticatedUser;
|
|
617
|
-
db: DatabaseAdapter;
|
|
618
|
-
}) => void | Promise<void>;
|
|
619
|
-
/** @see {@link CollectionBeforeReadHook} */
|
|
620
|
-
type GlobalBeforeReadHook = CollectionBeforeReadHook;
|
|
621
|
-
type GlobalBeforeReadHookEntry = CollectionBeforeReadHookEntry;
|
|
516
|
+
type AggregateInput = Record<string, AggregateOperation>;
|
|
622
517
|
/**
|
|
623
|
-
*
|
|
518
|
+
* The arguments passed to `DatabaseAdapter.aggregate`.
|
|
624
519
|
*/
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
520
|
+
interface AggregateArgs {
|
|
521
|
+
/** Collection slug. */
|
|
522
|
+
collection: string;
|
|
523
|
+
/** Named aggregate operations to compute. */
|
|
524
|
+
aggregates: AggregateInput;
|
|
525
|
+
/** Optional field to group the aggregates by. */
|
|
526
|
+
groupBy?: string;
|
|
527
|
+
}
|
|
632
528
|
/**
|
|
633
|
-
*
|
|
634
|
-
*
|
|
529
|
+
* The result returned by `DatabaseAdapter.aggregate`.
|
|
530
|
+
*
|
|
531
|
+
* For scalar aggregates, every named key maps to a `number | null` or `any[]` (for distinct).
|
|
532
|
+
* When `groupBy` is used, returns a breakdown per group.
|
|
635
533
|
*/
|
|
636
|
-
type
|
|
637
|
-
data: Partial<TDoc>;
|
|
638
|
-
doc?: TDoc;
|
|
639
|
-
req: HookRequestContext;
|
|
640
|
-
user?: AuthenticatedUser;
|
|
641
|
-
operation: "update";
|
|
642
|
-
db: ReadonlyDatabaseAdapter;
|
|
643
|
-
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;
|
|
644
|
-
type GlobalBeforeChangeHookEntry<TDoc extends object = Record<string, unknown>> = GlobalBeforeChangeHook<TDoc> | DeclarativeHookExpression;
|
|
534
|
+
type AggregateResult = Record<string, any>;
|
|
645
535
|
/**
|
|
646
|
-
*
|
|
536
|
+
* Derives the typed result shape from an `AggregateInput`.
|
|
647
537
|
*/
|
|
648
|
-
type
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
user?: AuthenticatedUser;
|
|
653
|
-
operation: "update";
|
|
654
|
-
db: DatabaseAdapter;
|
|
655
|
-
}) => void | Promise<void>;
|
|
538
|
+
type InferAggregateResult<T extends AggregateInput> = {
|
|
539
|
+
[K in keyof T]: any;
|
|
540
|
+
};
|
|
541
|
+
|
|
656
542
|
/**
|
|
657
|
-
*
|
|
658
|
-
* `CollectionBeforeChangeHook`, `CollectionAfterReadHook`, etc.
|
|
543
|
+
* Dyrected Where Clause DSL — shared query language across all database adapters.
|
|
659
544
|
*
|
|
660
|
-
*
|
|
545
|
+
* Adapters translate this DSL into their native format:
|
|
546
|
+
* - SQL adapters (SQLite, Postgres, MySQL): use parseSqlWhere()
|
|
547
|
+
* - MongoDB adapter: use parseMongoWhere()
|
|
548
|
+
* - Future adapters: implement their own translator against WhereClause
|
|
549
|
+
*
|
|
550
|
+
* Exhaustive operator handling is enforced at compile time via `assertNever`,
|
|
551
|
+
* so adding a new operator without handling it will produce a TypeScript error
|
|
552
|
+
* in every adapter translator.
|
|
661
553
|
*/
|
|
662
|
-
type
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
554
|
+
type WhereOperatorName = 'equals' | 'not_equals' | 'in' | 'not_in' | 'gt' | 'greater_than' | 'gte' | 'greater_than_equal' | 'greater_than_or_equal' | 'lt' | 'less_than' | 'lte' | 'less_than_equal' | 'less_than_or_equal' | 'contains' | 'like' | 'starts_with' | 'exists';
|
|
555
|
+
type WhereOperator = {
|
|
556
|
+
equals: any;
|
|
557
|
+
} | {
|
|
558
|
+
not_equals: any;
|
|
559
|
+
} | {
|
|
560
|
+
in: any[];
|
|
561
|
+
} | {
|
|
562
|
+
not_in: any[];
|
|
563
|
+
} | {
|
|
564
|
+
gt: any;
|
|
565
|
+
} | {
|
|
566
|
+
greater_than: any;
|
|
567
|
+
} | {
|
|
568
|
+
gte: any;
|
|
569
|
+
} | {
|
|
570
|
+
greater_than_equal: any;
|
|
571
|
+
} | {
|
|
572
|
+
greater_than_or_equal: any;
|
|
573
|
+
} | {
|
|
574
|
+
lt: any;
|
|
575
|
+
} | {
|
|
576
|
+
less_than: any;
|
|
577
|
+
} | {
|
|
578
|
+
lte: any;
|
|
579
|
+
} | {
|
|
580
|
+
less_than_equal: any;
|
|
581
|
+
} | {
|
|
582
|
+
less_than_or_equal: any;
|
|
583
|
+
} | {
|
|
584
|
+
contains: string;
|
|
585
|
+
} | {
|
|
586
|
+
like: string;
|
|
587
|
+
} | {
|
|
588
|
+
starts_with: string;
|
|
589
|
+
} | {
|
|
590
|
+
exists: boolean;
|
|
591
|
+
};
|
|
592
|
+
/** Top-level where clause. Fields map to operator objects or shorthand scalar values. */
|
|
593
|
+
type WhereClause = {
|
|
594
|
+
[field: string]: WhereOperator | any;
|
|
595
|
+
OR?: WhereClause[] | readonly WhereClause[];
|
|
596
|
+
or?: WhereClause[] | readonly WhereClause[];
|
|
597
|
+
AND?: WhereClause[] | readonly WhereClause[];
|
|
598
|
+
and?: WhereClause[] | readonly WhereClause[];
|
|
599
|
+
};
|
|
600
|
+
interface SqlWhereResult {
|
|
601
|
+
sql: string;
|
|
602
|
+
params: any[];
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Translates a WhereClause into a parameterized SQL WHERE fragment.
|
|
606
|
+
*
|
|
607
|
+
* @param where The Dyrected where DSL object
|
|
608
|
+
* @param getJsonField Returns the SQL expression for a JSON-stored field (dialect-specific):
|
|
609
|
+
* SQLite: (f) => `json_extract(data, '$.${f}')`
|
|
610
|
+
* Postgres: (f) => `data->>'${f}'`
|
|
611
|
+
* MySQL: (f) => `JSON_UNQUOTE(JSON_EXTRACT(data, '$.${f}'))`
|
|
612
|
+
* @param placeholder '?' for SQLite/MySQL, 'pg' for auto-incrementing Postgres $1/$2/…
|
|
613
|
+
*/
|
|
614
|
+
declare function parseSqlWhere(where: WhereClause, getJsonField: (field: string) => string, placeholder?: '?' | 'pg',
|
|
615
|
+
/**
|
|
616
|
+
* SQL keyword used for `contains`/`starts_with`. Postgres `LIKE` is
|
|
617
|
+
* case-sensitive, so the Postgres adapter defaults to `'ILIKE'` to keep substring
|
|
618
|
+
* matching case-insensitive like SQLite and MySQL.
|
|
619
|
+
*/
|
|
620
|
+
likeOperator?: 'LIKE' | 'ILIKE'): SqlWhereResult;
|
|
621
|
+
/**
|
|
622
|
+
* Translates a WhereClause into a MongoDB filter object.
|
|
623
|
+
* Handles nested OR/AND via $or/$and, and all operators via $eq/$in/$gt etc.
|
|
624
|
+
*/
|
|
625
|
+
declare function parseMongoWhere(where: WhereClause): Record<string, any>;
|
|
626
|
+
/**
|
|
627
|
+
* Turns the strings "true"/"false" into booleans for the fields the schema declares as boolean.
|
|
628
|
+
*
|
|
629
|
+
* Adapters bind booleans natively (1/0, `true`, BSON bool), but a client that sends the string
|
|
630
|
+
* `"true"` would otherwise match nothing on some adapters and the wrong rows on others (Postgres
|
|
631
|
+
* serializes any non-`true` value to `false` for a boolean column). Coercing once, before the
|
|
632
|
+
* where clause is translated, gives every adapter the same behavior. Fields that are not
|
|
633
|
+
* declared boolean are left untouched.
|
|
634
|
+
*/
|
|
635
|
+
declare function coerceBooleanWhere(where: WhereClause, fields: ReadonlyArray<{
|
|
636
|
+
name?: string;
|
|
637
|
+
type?: string;
|
|
638
|
+
}> | undefined): WhereClause;
|
|
671
639
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
640
|
+
/**
|
|
641
|
+
* Custom component slots rendered around an operational view's content.
|
|
642
|
+
*/
|
|
643
|
+
type ViewComponentSlots = CollectionViewComponentSlots;
|
|
644
|
+
/**
|
|
645
|
+
* Supported layout engines for operational views in the Dyrected Admin UI:
|
|
646
|
+
* - `'table'`: The workhorse — column sorting, search, faceted filters, and bulk actions.
|
|
647
|
+
* - `'spreadsheet'`: Inline-editable matrix with batch saving (`Save changes` / `Discard`).
|
|
648
|
+
* - `'kanban'`: Interactive card board grouped by status or category with drag-and-drop.
|
|
649
|
+
* - `'calendar'`: Event schedule grid plotting records across month/week/day views by date.
|
|
650
|
+
* - `'gantt'`: Timeline bars plotted across start and end dates.
|
|
651
|
+
* - `'cards'`: Visual image/thumbnail gallery grid.
|
|
652
|
+
*/
|
|
653
|
+
type ViewLayout = 'table' | 'spreadsheet' | 'kanban' | 'calendar' | 'gantt' | 'cards';
|
|
654
|
+
/**
|
|
655
|
+
* Scope and placement for an operational view action:
|
|
656
|
+
* - `'row'`: Renders as an inline action button on each document/row.
|
|
657
|
+
* - `'bulk'`: Appears in the floating bulk action bar when one or more rows are selected.
|
|
658
|
+
* - `'header'`: Renders as a primary action button in the view header.
|
|
659
|
+
*/
|
|
660
|
+
type ActionType = 'row' | 'bulk' | 'header';
|
|
661
|
+
/**
|
|
662
|
+
* Toggles for the built-in document operations an operational view surfaces.
|
|
663
|
+
* All default to enabled (`true`). Set any to `false` to hide that operation.
|
|
664
|
+
*
|
|
665
|
+
* @example
|
|
666
|
+
* ```ts
|
|
667
|
+
* features: {
|
|
668
|
+
* delete: false, // Prevent deleting records from this view
|
|
669
|
+
* exportSelected: true, // Enable CSV export for checked rows
|
|
670
|
+
* }
|
|
671
|
+
* ```
|
|
672
|
+
*/
|
|
673
|
+
interface ViewActionFeatures {
|
|
674
|
+
/** Enables the "View" preview / read-only drawer button. Defaults to `true`. */
|
|
675
|
+
view?: boolean;
|
|
676
|
+
/** Enables the "Edit" document form link. Defaults to `true`. */
|
|
677
|
+
edit?: boolean;
|
|
678
|
+
/** Enables the "Duplicate" record action. Defaults to `true`. */
|
|
679
|
+
duplicate?: boolean;
|
|
680
|
+
/** Enables the "Delete" record action. Defaults to `true`. */
|
|
681
|
+
delete?: boolean;
|
|
682
|
+
/** Enables the "Export selected" CSV action in the bulk action bar. Defaults to `true`. */
|
|
683
|
+
exportSelected?: boolean;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Color palette options for metric cards:
|
|
687
|
+
* `'purple' | 'emerald' | 'amber' | 'rose' | 'blue' | 'indigo' | 'cyan' | 'orange'`
|
|
688
|
+
*/
|
|
689
|
+
type MetricColor = 'purple' | 'emerald' | 'amber' | 'rose' | 'blue' | 'indigo' | 'cyan' | 'orange' | string;
|
|
690
|
+
/**
|
|
691
|
+
* A sub-metric breakdown item displayed in the compact footer of a metric card.
|
|
692
|
+
*
|
|
693
|
+
* @example
|
|
694
|
+
* ```ts
|
|
695
|
+
* {
|
|
696
|
+
* label: "Pending",
|
|
697
|
+
* aggregates: {
|
|
698
|
+
* checkedIn: { count: "*", where: { checkedIn: { equals: true } } },
|
|
699
|
+
* attending: { count: "*", where: { attending: { equals: true } } },
|
|
700
|
+
* },
|
|
701
|
+
* expression: "aggregates.attending - aggregates.checkedIn",
|
|
702
|
+
* }
|
|
703
|
+
* ```
|
|
704
|
+
*/
|
|
705
|
+
interface ViewSubMetric {
|
|
706
|
+
/** Short label for the sub-metric (e.g. "Pending", "Collected"). */
|
|
678
707
|
label: string;
|
|
679
|
-
/**
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
|
|
708
|
+
/** Single database aggregate operation. */
|
|
709
|
+
aggregate?: AggregateOperation;
|
|
710
|
+
/** Map of named aggregate operations referenced in `expression` as `aggregates.key`. */
|
|
711
|
+
aggregates?: Record<string, AggregateOperation>;
|
|
712
|
+
/** JEXL math formula evaluated over `value` for a single aggregate (e.g. `"value * 100"`). */
|
|
713
|
+
transform?: string;
|
|
714
|
+
/** JEXL math formula evaluated over `aggregates` (e.g. `"aggregates.a - aggregates.b"`). */
|
|
715
|
+
expression?: string;
|
|
716
|
+
/** Display formatter: `'currency' | 'number' | 'percent'`. */
|
|
717
|
+
format?: 'currency' | 'number' | 'percent' | string;
|
|
718
|
+
/** 3-letter currency code (e.g. `"USD"`, `"NGN"`, `"EUR"`) used when `format: "currency"`. */
|
|
719
|
+
currency?: string;
|
|
683
720
|
}
|
|
684
|
-
|
|
685
|
-
|
|
721
|
+
/**
|
|
722
|
+
* Configuration for a KPI summary card rendered at the top of an operational view.
|
|
723
|
+
*
|
|
724
|
+
* All aggregations run directly on the database engine for maximum performance.
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* ```ts
|
|
728
|
+
* {
|
|
729
|
+
* label: "Total Revenue",
|
|
730
|
+
* color: "emerald",
|
|
731
|
+
* aggregate: { sum: "amount", cast: "number", where: { status: "paid" } },
|
|
732
|
+
* format: "currency",
|
|
733
|
+
* currency: "USD",
|
|
734
|
+
* }
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
interface ViewMetric {
|
|
738
|
+
/** Title displayed on the metric card header. */
|
|
739
|
+
label: string;
|
|
740
|
+
/** Accent color for the card's visual indicator. */
|
|
741
|
+
color?: MetricColor;
|
|
742
|
+
/** Unit badge shown alongside the numeric value (e.g. `"Guests"`, `"Orders"`, `"Tables"`). */
|
|
743
|
+
unit?: string;
|
|
744
|
+
/** Single database aggregate operation (`count`, `distinctCount`, `sum`, `avg`, `min`, `max`). */
|
|
745
|
+
aggregate?: AggregateOperation;
|
|
746
|
+
/** Map of named aggregate operations referenced in `expression` as `aggregates.key`. */
|
|
747
|
+
aggregates?: Record<string, AggregateOperation>;
|
|
748
|
+
/** JEXL math formula evaluated over `value` for a single aggregate (e.g. `"value * 25000"`). */
|
|
749
|
+
transform?: string;
|
|
750
|
+
/** JEXL math formula evaluated over `aggregates` (e.g. `"(aggregates.paid / aggregates.total) * 100"`). */
|
|
751
|
+
expression?: string;
|
|
752
|
+
/** Display formatter: `'currency' | 'number' | 'percent'`. */
|
|
753
|
+
format?: 'currency' | 'number' | 'percent' | string;
|
|
754
|
+
/** 3-letter currency code (e.g. `"USD"`, `"NGN"`, `"EUR"`) used when `format: "currency"`. */
|
|
755
|
+
currency?: string;
|
|
756
|
+
/** Optional secondary breakdown items shown in the card footer. */
|
|
757
|
+
subMetrics?: ViewSubMetric[];
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Base configuration shared by all action types.
|
|
761
|
+
*/
|
|
762
|
+
interface ActionConfigBase<TDoc extends Record<string, unknown> = Record<string, unknown>> {
|
|
763
|
+
/** Unique action identifier (e.g. `"checkIn"`, `"markPaid"`). */
|
|
686
764
|
name: string;
|
|
765
|
+
/** Button label displayed in the UI. */
|
|
687
766
|
label: string;
|
|
767
|
+
/** Optional custom label for the modal submit button (defaults to "Run" or "Confirm"). */
|
|
768
|
+
submitLabel?: string;
|
|
769
|
+
/** Lucide icon name for the button (e.g. `"UserCheck"`, `"CheckCircle"`). */
|
|
770
|
+
icon?: string;
|
|
771
|
+
/** Action placement: `'row'` (per-row), `'bulk'` (multi-row selection bar), or `'header'` (view header). Defaults to `'row'`. */
|
|
772
|
+
type?: ActionType;
|
|
773
|
+
/** Optional confirmation prompt shown before executing (e.g. `"Confirm guest check-in at the door?"`). */
|
|
774
|
+
confirm?: string;
|
|
775
|
+
/** Optional interactive modal form fields prompting the user for input before executing. */
|
|
776
|
+
fields?: Field[];
|
|
777
|
+
/** Role-based access rules controlling who can trigger this action. */
|
|
778
|
+
access?: AccessConfig;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* An operational workflow action with declarative data mutation.
|
|
782
|
+
*/
|
|
783
|
+
interface ActionConfigWithMutation<TDoc extends Record<string, unknown> = Record<string, unknown>> extends ActionConfigBase<TDoc> {
|
|
784
|
+
/** Declarative database mutation applied to targeted documents (e.g. `{ checkedIn: true, checkedInAt: "now()" }`). */
|
|
785
|
+
mutation: Partial<TDoc> | Record<string, unknown>;
|
|
786
|
+
/** Optional server handler for additional logic. */
|
|
787
|
+
handler?: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* An operational workflow action with server handler.
|
|
791
|
+
*/
|
|
792
|
+
interface ActionConfigWithHandler<TDoc extends Record<string, unknown> = Record<string, unknown>> extends ActionConfigBase<TDoc> {
|
|
793
|
+
/** Self-hosted server handler function executed when the action is triggered (required when mutation is not provided). */
|
|
794
|
+
handler: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
795
|
+
/** Optional declarative mutation. */
|
|
796
|
+
mutation?: Partial<TDoc> | Record<string, unknown>;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* An operational workflow action that can mutate data or trigger server logic.
|
|
800
|
+
* Requires either `mutation` or `handler` (or both).
|
|
801
|
+
*/
|
|
802
|
+
type ActionConfig<TDoc extends Record<string, unknown> = Record<string, unknown>> = ActionConfigWithMutation<TDoc> | ActionConfigWithHandler<TDoc>;
|
|
803
|
+
/**
|
|
804
|
+
* Context passed to an action's server handler function.
|
|
805
|
+
*/
|
|
806
|
+
interface ActionContext<TDoc extends Record<string, unknown> = Record<string, unknown>> {
|
|
807
|
+
/** The target document (for row actions), or null for header actions. */
|
|
808
|
+
doc: TDoc | null;
|
|
809
|
+
/** All targeted documents (for bulk actions). Empty array for header actions. */
|
|
810
|
+
docs: TDoc[];
|
|
811
|
+
/** The authenticated acting user, if available. */
|
|
812
|
+
user: Record<string, unknown> | null;
|
|
813
|
+
/** User inputs submitted via the action's modal form fields. */
|
|
814
|
+
input: Record<string, unknown>;
|
|
815
|
+
/** The collection configuration object. */
|
|
816
|
+
collection: Record<string, unknown>;
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Role-based access control rules for a view or action.
|
|
820
|
+
*/
|
|
821
|
+
interface AccessConfig {
|
|
822
|
+
read?: AccessRule<any>;
|
|
823
|
+
create?: AccessRule<any>;
|
|
824
|
+
update?: AccessRule<any>;
|
|
825
|
+
delete?: AccessRule<any>;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Base options shared by all operational view configurations.
|
|
829
|
+
*/
|
|
830
|
+
interface ViewConfigBase {
|
|
831
|
+
/** Stable URL slug for the view (`/collections/:slug/views/:viewSlug` or `/:workspaceSlug/:viewSlug`). */
|
|
832
|
+
slug: string;
|
|
833
|
+
/** Human-readable title displayed in the sidebar navigation and view header. */
|
|
834
|
+
label: string;
|
|
835
|
+
/** Lucide icon name (e.g. `"UserCheck"`, `"Calendar"`, `"Shirt"`, `"TableProperties"`). */
|
|
836
|
+
icon?: string;
|
|
837
|
+
/** Optional target collection slug for views defined inside standalone operational workspaces. */
|
|
838
|
+
collection?: string;
|
|
839
|
+
/** Base query filter applied before user toolbar filters (e.g. `{ attending: { equals: true } }` or JEXL string). */
|
|
840
|
+
filter?: WhereClause | Record<string, any> | string;
|
|
841
|
+
/** Field names to show in this view, in order. If omitted, Dyrected infers default display fields. */
|
|
842
|
+
columns?: string[];
|
|
843
|
+
/** Default sorting rule when entering the view. */
|
|
844
|
+
sort?: {
|
|
845
|
+
field: string;
|
|
846
|
+
direction: 'asc' | 'desc';
|
|
847
|
+
};
|
|
848
|
+
/** Custom workflow actions available in this view. */
|
|
849
|
+
actions?: ActionConfig[];
|
|
850
|
+
/** Toggles built-in operations (view/edit/duplicate/delete/export). */
|
|
851
|
+
features?: ViewActionFeatures;
|
|
688
852
|
/**
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*/
|
|
692
|
-
from: string | string[];
|
|
693
|
-
/**
|
|
694
|
-
* Target state this transition leads to.
|
|
695
|
-
* Must match a name in the workflow's `states` array.
|
|
853
|
+
* Explicit display order for action buttons — mixing custom action names and built-in names
|
|
854
|
+
* (`"view"`, `"edit"`, `"duplicate"`, `"delete"`). Unlisted actions append in default order.
|
|
696
855
|
*/
|
|
697
|
-
|
|
698
|
-
/**
|
|
699
|
-
|
|
700
|
-
/**
|
|
701
|
-
|
|
702
|
-
/**
|
|
703
|
-
|
|
856
|
+
actionOrder?: string[];
|
|
857
|
+
/** KPI summary cards rendered in the hero row above the view. */
|
|
858
|
+
metrics?: ViewMetric[];
|
|
859
|
+
/** Optional real-time counter badge or status indicator displayed on this view in navigation and tabs. */
|
|
860
|
+
badge?: NavBadgeConfig | string;
|
|
861
|
+
/** Custom component slots rendered around this operational view. */
|
|
862
|
+
components?: ViewComponentSlots;
|
|
863
|
+
/** Role-based access rules controlling who can see or use this view. */
|
|
864
|
+
access?: AccessConfig;
|
|
704
865
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
866
|
+
/** Table view — requires no special fields. */
|
|
867
|
+
interface TableViewConfig extends ViewConfigBase {
|
|
868
|
+
layout?: 'table' | 'spreadsheet';
|
|
869
|
+
/** Field name used to organize records into kanban columns or collapsible grouped sections in table, cards, and spreadsheet. */
|
|
870
|
+
groupBy?: string;
|
|
709
871
|
}
|
|
710
|
-
/**
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
*/
|
|
716
|
-
interface WorkflowConfig<TDoc extends object = Record<string, unknown>> {
|
|
717
|
-
/** The state every new document starts in, e.g. `"draft"`. */
|
|
718
|
-
initialState: string;
|
|
719
|
-
/** State used for a new working revision created from published content. */
|
|
720
|
-
draftState?: string;
|
|
721
|
-
/** All states a document can occupy. Exactly one should be marked `published`. */
|
|
722
|
-
states: WorkflowState[];
|
|
723
|
-
/** The allowed moves between states, each with its own capability and comment rules. */
|
|
724
|
-
transitions: WorkflowTransition[];
|
|
725
|
-
/** Maps values in `user.roles` to workflow capabilities. */
|
|
726
|
-
roles?: WorkflowRole[];
|
|
727
|
-
/** Server-side hooks that run around every transition. */
|
|
728
|
-
hooks?: {
|
|
729
|
-
/** Runs before a transition commits — throw to validate or block the move. */
|
|
730
|
-
beforeTransition?: CollectionBeforeTransitionHook<TDoc>[];
|
|
731
|
-
/** Runs after a transition commits — trigger notifications or downstream work. */
|
|
732
|
-
afterTransition?: CollectionAfterTransitionHook<TDoc>[];
|
|
733
|
-
};
|
|
872
|
+
/** Kanban view — requires `groupBy` to organize into columns. */
|
|
873
|
+
interface KanbanViewConfig extends ViewConfigBase {
|
|
874
|
+
layout: 'kanban';
|
|
875
|
+
/** Field name to organize records into kanban columns. */
|
|
876
|
+
groupBy: string;
|
|
734
877
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
/**
|
|
739
|
-
|
|
740
|
-
/** Revision number currently exposed as the public snapshot, once published. */
|
|
741
|
-
publishedRevision?: number;
|
|
742
|
-
/** ISO timestamp of the most recent publish. */
|
|
743
|
-
publishedAt?: string;
|
|
744
|
-
/** Id of the user who last published this document. */
|
|
745
|
-
publishedBy?: string;
|
|
746
|
-
/** Transitions currently allowed for the requesting user. Response-only. */
|
|
747
|
-
availableTransitions?: string[];
|
|
878
|
+
/** Calendar view — requires `dateField` to place records on the calendar. */
|
|
879
|
+
interface CalendarViewConfig extends ViewConfigBase {
|
|
880
|
+
layout: 'calendar';
|
|
881
|
+
/** Field name containing the ISO date string for calendar placement. */
|
|
882
|
+
dateField: string;
|
|
748
883
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
/**
|
|
753
|
-
|
|
754
|
-
/**
|
|
755
|
-
|
|
756
|
-
/** The document as it stands before the transition commits. */
|
|
757
|
-
doc: TDoc;
|
|
758
|
-
/** The user performing the transition, when the request is authenticated. */
|
|
759
|
-
user?: AuthenticatedUser;
|
|
760
|
-
/** Comment supplied with the transition; required when `requireComment` is set. */
|
|
761
|
-
comment?: string;
|
|
762
|
-
/** Request context for the transition. */
|
|
763
|
-
req: HookRequestContext;
|
|
764
|
-
/** Transaction-scoped database adapter for reads and writes inside the hook. */
|
|
765
|
-
db: DatabaseAdapter;
|
|
884
|
+
/** Gantt view — requires both `startDateField` and `endDateField`. */
|
|
885
|
+
interface GanttViewConfig extends ViewConfigBase {
|
|
886
|
+
layout: 'gantt';
|
|
887
|
+
/** Field name for the start date in the gantt timeline. */
|
|
888
|
+
startDateField: string;
|
|
889
|
+
/** Field name for the end date in the gantt timeline. */
|
|
890
|
+
endDateField: string;
|
|
766
891
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
/** Unique id for this event. */
|
|
773
|
-
id: string;
|
|
774
|
-
/** The lifecycle event name, e.g. `"workflow.transitioned"` or `"entry.published"`. */
|
|
775
|
-
name: LifecycleEventName;
|
|
776
|
-
/** Slug of the collection the event is about. */
|
|
777
|
-
collection: string;
|
|
778
|
-
/** Id of the document the event is about. */
|
|
779
|
-
documentId: string;
|
|
780
|
-
/** ISO timestamp of when the event occurred. */
|
|
781
|
-
occurredAt: string;
|
|
782
|
-
/** Id of the user who triggered the event, when known. */
|
|
783
|
-
actorId?: string;
|
|
784
|
-
/** Event-specific data, such as the transition name and affected revision. */
|
|
785
|
-
payload: TPayload;
|
|
786
|
-
/** Number of delivery attempts made so far. */
|
|
787
|
-
attempts: number;
|
|
788
|
-
/** Current delivery status as the dispatcher works through the queue. */
|
|
789
|
-
status: "pending" | "processing" | "delivered" | "failed";
|
|
790
|
-
/** ISO timestamp of the next delivery retry, while pending. */
|
|
791
|
-
nextAttemptAt?: string;
|
|
792
|
-
/** ISO timestamp of successful delivery. */
|
|
793
|
-
deliveredAt?: string;
|
|
794
|
-
/** Message from the most recent failed delivery attempt. */
|
|
795
|
-
lastError?: string;
|
|
892
|
+
/** Cards view — shows records as image/thumbnail gallery. */
|
|
893
|
+
interface CardsViewConfig extends ViewConfigBase {
|
|
894
|
+
layout: 'cards';
|
|
895
|
+
/** Field name used to organize records into groups. */
|
|
896
|
+
groupBy?: string;
|
|
796
897
|
}
|
|
797
|
-
type LifecycleEventHandler = (event: LifecycleEvent) => void | Promise<void>;
|
|
798
|
-
|
|
799
|
-
/** Column span in the 12-column Detail View layout grid (1 to 12). */
|
|
800
|
-
type DetailSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
801
898
|
/**
|
|
802
|
-
*
|
|
899
|
+
* Complete configuration for a tailored operational view.
|
|
803
900
|
*/
|
|
804
|
-
type
|
|
901
|
+
type ViewConfig = TableViewConfig | KanbanViewConfig | CalendarViewConfig | GanttViewConfig | CardsViewConfig;
|
|
805
902
|
/**
|
|
806
|
-
*
|
|
903
|
+
* Backwards-compatible aliases for builder types.
|
|
807
904
|
*/
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
/**
|
|
832
|
-
|
|
833
|
-
/**
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
/**
|
|
848
|
-
|
|
849
|
-
/** CSS object-fit behavior for media ('cover', 'contain', 'fill', 'scale-down'). */
|
|
850
|
-
objectFit?: "cover" | "contain" | "fill" | "scale-down";
|
|
851
|
-
/** Media alignment ('left', 'center', 'right'). */
|
|
852
|
-
align?: "left" | "center" | "right";
|
|
853
|
-
/** Fixed pixel width or CSS dimension for media preview. */
|
|
854
|
-
width?: string | number;
|
|
855
|
-
/** Fixed pixel height or CSS dimension for media preview. */
|
|
856
|
-
height?: string | number;
|
|
905
|
+
type DefineViewBaseOptions = ViewConfigBase;
|
|
906
|
+
type DefineTableViewOptions = TableViewConfig;
|
|
907
|
+
type DefineKanbanViewOptions = KanbanViewConfig;
|
|
908
|
+
type DefineCalendarViewOptions = CalendarViewConfig;
|
|
909
|
+
type DefineGanttViewOptions = GanttViewConfig;
|
|
910
|
+
type DefineCardsViewOptions = CardsViewConfig;
|
|
911
|
+
type DefineViewOptions = ViewConfig;
|
|
912
|
+
/**
|
|
913
|
+
* Options for defining a custom workflow action with `defineAction`.
|
|
914
|
+
*
|
|
915
|
+
* @example
|
|
916
|
+
* ```ts
|
|
917
|
+
* export const checkInAction = defineAction({
|
|
918
|
+
* name: "checkIn",
|
|
919
|
+
* label: "Check In",
|
|
920
|
+
* icon: "UserCheck",
|
|
921
|
+
* type: "row",
|
|
922
|
+
* confirm: "Confirm guest check-in at the door?",
|
|
923
|
+
* mutation: { checkedIn: true, checkedInAt: "now()" },
|
|
924
|
+
* });
|
|
925
|
+
* ```
|
|
926
|
+
*/
|
|
927
|
+
interface DefineActionOptions<TDoc extends Record<string, unknown> = Record<string, unknown>> {
|
|
928
|
+
/** Unique action identifier (e.g. `"checkIn"`, `"markPaid"`). */
|
|
929
|
+
name: string;
|
|
930
|
+
/** Button label displayed in the UI. */
|
|
931
|
+
label: string;
|
|
932
|
+
/** Lucide icon name for the button (e.g. `"UserCheck"`, `"CheckCircle"`). */
|
|
933
|
+
icon?: string;
|
|
934
|
+
/** Action placement: `'row'` (per-row), `'bulk'` (multi-row selection bar), or `'header'` (view header). Defaults to `'row'`. */
|
|
935
|
+
type?: ActionType;
|
|
936
|
+
/** Optional confirmation prompt shown before executing (e.g. `"Confirm guest check-in at the door?"`). */
|
|
937
|
+
confirm?: string;
|
|
938
|
+
/** Optional interactive modal form fields prompting the user for input before executing. */
|
|
939
|
+
fields?: Field[];
|
|
940
|
+
/** Declarative database mutation applied to targeted documents (e.g. `{ checkedIn: true, checkedInAt: "now()" }`). */
|
|
941
|
+
mutation?: Partial<TDoc> | Record<string, unknown>;
|
|
942
|
+
/** Self-hosted server handler function executed when the action is triggered. */
|
|
943
|
+
handler?: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
944
|
+
/** Role-based access rules controlling who can trigger this action. */
|
|
945
|
+
access?: AccessConfig;
|
|
857
946
|
}
|
|
858
947
|
/**
|
|
859
|
-
*
|
|
948
|
+
* Defines a typed operational view for a collection.
|
|
949
|
+
* Layout-specific overloads enforce required fields for each view type.
|
|
950
|
+
*
|
|
951
|
+
* @example
|
|
952
|
+
* ```ts
|
|
953
|
+
* // Table view (no special requirements)
|
|
954
|
+
* export const allGuests = defineView({
|
|
955
|
+
* slug: "all-guests",
|
|
956
|
+
* label: "All Guests",
|
|
957
|
+
* layout: "table", // or omit for default
|
|
958
|
+
* });
|
|
959
|
+
*
|
|
960
|
+
* // Kanban view (requires groupBy)
|
|
961
|
+
* export const guestsByTable = defineView({
|
|
962
|
+
* slug: "by-table",
|
|
963
|
+
* label: "Guests by Table",
|
|
964
|
+
* layout: "kanban",
|
|
965
|
+
* groupBy: "tableNumber", // required!
|
|
966
|
+
* });
|
|
967
|
+
*
|
|
968
|
+
* // Calendar view (requires dateField)
|
|
969
|
+
* export const eventCalendar = defineView({
|
|
970
|
+
* slug: "event-calendar",
|
|
971
|
+
* label: "Event Calendar",
|
|
972
|
+
* layout: "calendar",
|
|
973
|
+
* dateField: "eventDate", // required!
|
|
974
|
+
* });
|
|
975
|
+
*
|
|
976
|
+
* // Gantt view (requires startDateField and endDateField)
|
|
977
|
+
* export const projectTimeline = defineView({
|
|
978
|
+
* slug: "timeline",
|
|
979
|
+
* label: "Project Timeline",
|
|
980
|
+
* layout: "gantt",
|
|
981
|
+
* startDateField: "startDate", // required!
|
|
982
|
+
* endDateField: "endDate", // required!
|
|
983
|
+
* });
|
|
984
|
+
* ```
|
|
985
|
+
*/
|
|
986
|
+
declare function defineView(config: DefineTableViewOptions): DefineTableViewOptions;
|
|
987
|
+
declare function defineView(config: DefineKanbanViewOptions): DefineKanbanViewOptions;
|
|
988
|
+
declare function defineView(config: DefineCalendarViewOptions): DefineCalendarViewOptions;
|
|
989
|
+
declare function defineView(config: DefineGanttViewOptions): DefineGanttViewOptions;
|
|
990
|
+
declare function defineView(config: DefineCardsViewOptions): DefineCardsViewOptions;
|
|
991
|
+
declare function defineView<const T extends DefineViewOptions>(config: T): T;
|
|
992
|
+
/** Convenience helper for table views. Enforces no view-specific required fields. */
|
|
993
|
+
declare function defineTableView(config: DefineTableViewOptions): DefineTableViewOptions;
|
|
994
|
+
/** Convenience helper for kanban views. Enforces `groupBy` is provided. */
|
|
995
|
+
declare function defineKanbanView(config: DefineKanbanViewOptions): DefineKanbanViewOptions;
|
|
996
|
+
/** Convenience helper for calendar views. Enforces `dateField` is provided. */
|
|
997
|
+
declare function defineCalendarView(config: DefineCalendarViewOptions): DefineCalendarViewOptions;
|
|
998
|
+
/** Convenience helper for gantt views. Enforces `startDateField` and `endDateField` are provided. */
|
|
999
|
+
declare function defineGanttView(config: DefineGanttViewOptions): DefineGanttViewOptions;
|
|
1000
|
+
/** Convenience helper for cards views. Optional `groupBy`. */
|
|
1001
|
+
declare function defineCardsView(config: DefineCardsViewOptions): DefineCardsViewOptions;
|
|
1002
|
+
/**
|
|
1003
|
+
* Defines a custom workflow action for an operational view.
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* ```ts
|
|
1007
|
+
* export const markPaidAction = defineAction({
|
|
1008
|
+
* name: "markPaid",
|
|
1009
|
+
* label: "Mark Paid",
|
|
1010
|
+
* icon: "DollarSign",
|
|
1011
|
+
* type: "bulk",
|
|
1012
|
+
* confirm: "Mark selected orders as paid?",
|
|
1013
|
+
* mutation: { status: "paid" },
|
|
1014
|
+
* });
|
|
1015
|
+
* ```
|
|
860
1016
|
*/
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
type: "field";
|
|
864
|
-
/** Field name or nested path in the document. */
|
|
865
|
-
field: string;
|
|
866
|
-
/** Display options for this field. */
|
|
867
|
-
options?: DisplayFieldOptions;
|
|
868
|
-
}
|
|
1017
|
+
declare function defineAction<const T extends DefineActionOptions>(config: T): T;
|
|
1018
|
+
|
|
869
1019
|
/**
|
|
870
|
-
*
|
|
1020
|
+
* Definition of a navigation group in the Dyrected admin sidebar.
|
|
871
1021
|
*/
|
|
872
|
-
interface
|
|
873
|
-
/**
|
|
874
|
-
|
|
875
|
-
/**
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
|
|
879
|
-
/**
|
|
880
|
-
|
|
881
|
-
/**
|
|
882
|
-
|
|
883
|
-
/** Internal grid column count for child items. */
|
|
884
|
-
columns?: number;
|
|
885
|
-
/** When true, allows editors to collapse and expand the section. */
|
|
886
|
-
collapsible?: boolean;
|
|
887
|
-
/** Starts the section in collapsed state when collapsible is enabled. */
|
|
888
|
-
collapsedByDefault?: boolean;
|
|
889
|
-
/**
|
|
890
|
-
* Visibility condition for this section.
|
|
891
|
-
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
892
|
-
*
|
|
893
|
-
* @example `visible: "user.roles != null and 'admin' in user.roles"`
|
|
894
|
-
*/
|
|
895
|
-
visible?: string | boolean;
|
|
1022
|
+
interface NavGroup {
|
|
1023
|
+
/** Display title for the group in the sidebar. */
|
|
1024
|
+
name: string;
|
|
1025
|
+
/** Optional stable identifier/slug for the group. */
|
|
1026
|
+
slug?: string;
|
|
1027
|
+
/** Lucide icon name for the group accordion header. */
|
|
1028
|
+
icon?: AdminIconName | string;
|
|
1029
|
+
/** Whether the group is expanded by default in the sidebar. */
|
|
1030
|
+
defaultExpanded?: boolean;
|
|
1031
|
+
/** Sort order weight for the group section in the sidebar (lower numbers appear first). */
|
|
1032
|
+
order?: number;
|
|
896
1033
|
}
|
|
897
1034
|
/**
|
|
898
|
-
*
|
|
1035
|
+
* Configuration for real-time count badges on navigation items.
|
|
899
1036
|
*/
|
|
900
|
-
interface
|
|
901
|
-
/**
|
|
902
|
-
|
|
903
|
-
/**
|
|
904
|
-
|
|
905
|
-
/**
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1037
|
+
interface NavBadgeConfig {
|
|
1038
|
+
/** If true, automatically calculates a count based on the primary view's filter. */
|
|
1039
|
+
count?: boolean;
|
|
1040
|
+
/** Static text override for the badge (e.g. "Live", "New", "Urgent"). */
|
|
1041
|
+
text?: string;
|
|
1042
|
+
/** Custom aggregate filter evaluated on the database. */
|
|
1043
|
+
aggregate?: {
|
|
1044
|
+
collection: string;
|
|
1045
|
+
where?: Record<string, unknown>;
|
|
1046
|
+
};
|
|
1047
|
+
/** Visual badge color variant. */
|
|
1048
|
+
variant?: "default" | "warning" | "destructive" | "info" | "success";
|
|
909
1049
|
}
|
|
910
1050
|
/**
|
|
911
|
-
*
|
|
1051
|
+
* Options for defining an operational workspace, or customizing placement of collections/globals, with `defineWorkspace`.
|
|
912
1052
|
*/
|
|
913
|
-
interface
|
|
914
|
-
/**
|
|
915
|
-
|
|
916
|
-
/**
|
|
917
|
-
|
|
918
|
-
/**
|
|
919
|
-
|
|
920
|
-
/**
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1053
|
+
interface DefineWorkspaceOptions {
|
|
1054
|
+
/** If provided, injects views into an existing collection submenu. If omitted, item stands alone. */
|
|
1055
|
+
addToCollection?: string;
|
|
1056
|
+
/** References an existing collection to position it in navigation. */
|
|
1057
|
+
collection?: string;
|
|
1058
|
+
/** References an existing global to position it in navigation. */
|
|
1059
|
+
global?: string;
|
|
1060
|
+
/** Designates this item as the dashboard link. */
|
|
1061
|
+
dashboard?: boolean;
|
|
1062
|
+
/** Stable URL slug for standalone operational workspaces (`/:slug`). */
|
|
1063
|
+
slug?: string;
|
|
1064
|
+
/** Display label in the sidebar (defaults to collection/global label when applicable). */
|
|
1065
|
+
label?: string;
|
|
1066
|
+
/** Lucide icon name (e.g. "ShieldAlert", "Users", "Briefcase"). */
|
|
1067
|
+
icon?: AdminIconName | string;
|
|
1068
|
+
/** Section group name (string) or group object with icon and default expanded state. */
|
|
1069
|
+
group?: string | NavGroup;
|
|
1070
|
+
/** Relative position: insert immediately after this collection or nav item slug. */
|
|
1071
|
+
after?: string;
|
|
1072
|
+
/** Relative position: insert immediately before this collection or nav item slug. */
|
|
1073
|
+
before?: string;
|
|
1074
|
+
/** Numeric sort weight within its group (lower numbers first, default 100). */
|
|
1075
|
+
order?: number;
|
|
1076
|
+
/** Fast shortcut to pin item to start or end of its group: 'first' | 'last'. */
|
|
1077
|
+
position?: "first" | "last";
|
|
1078
|
+
/** Real-time counter badge (auto-computed from primary view or custom aggregate). */
|
|
1079
|
+
badge?: NavBadgeConfig | string;
|
|
1080
|
+
/** Role-based access rules controlling who can see this navigation item. */
|
|
1081
|
+
access?: string[] | AccessRule;
|
|
1082
|
+
/** Custom internal route or external URL. */
|
|
1083
|
+
href?: string;
|
|
1084
|
+
/** Views belonging to this item. The first view is automatically the default. */
|
|
1085
|
+
views?: ViewConfig[];
|
|
925
1086
|
}
|
|
926
1087
|
/**
|
|
927
|
-
*
|
|
1088
|
+
* Helper to define an operational workspace or customize placement of collections/globals.
|
|
1089
|
+
*
|
|
1090
|
+
* @example
|
|
1091
|
+
* ```ts
|
|
1092
|
+
* export const kycQueue = defineWorkspace({
|
|
1093
|
+
* slug: "kyc-review",
|
|
1094
|
+
* label: "KYC Review",
|
|
1095
|
+
* icon: "ShieldAlert",
|
|
1096
|
+
* group: "Compliance",
|
|
1097
|
+
* views: [
|
|
1098
|
+
* defineView({ collection: "investors", slug: "pending", label: "Pending" }),
|
|
1099
|
+
* ],
|
|
1100
|
+
* });
|
|
1101
|
+
* ```
|
|
928
1102
|
*/
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1103
|
+
declare function defineWorkspace(options: DefineWorkspaceOptions): DefineWorkspaceOptions;
|
|
1104
|
+
/**
|
|
1105
|
+
* Runtime compiled representation of a single navigation item.
|
|
1106
|
+
*/
|
|
1107
|
+
interface CompiledNavItem {
|
|
1108
|
+
id: string;
|
|
1109
|
+
type: "workspace" | "collection" | "global" | "dashboard" | "link";
|
|
1110
|
+
slug: string;
|
|
933
1111
|
label: string;
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1112
|
+
icon?: string;
|
|
1113
|
+
group?: string;
|
|
1114
|
+
href?: string;
|
|
1115
|
+
badge?: NavBadgeConfig | string;
|
|
1116
|
+
access?: string[] | AccessRule;
|
|
1117
|
+
order: number;
|
|
1118
|
+
collection?: string;
|
|
1119
|
+
global?: string;
|
|
1120
|
+
views: ViewConfig[];
|
|
938
1121
|
}
|
|
939
1122
|
/**
|
|
940
|
-
*
|
|
1123
|
+
* Runtime compiled representation of a navigation group containing items.
|
|
941
1124
|
*/
|
|
942
|
-
interface
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
*/
|
|
951
|
-
visible?: string | boolean;
|
|
1125
|
+
interface CompiledNavGroup {
|
|
1126
|
+
id: string;
|
|
1127
|
+
name: string;
|
|
1128
|
+
slug: string;
|
|
1129
|
+
icon?: string;
|
|
1130
|
+
defaultExpanded?: boolean;
|
|
1131
|
+
order: number;
|
|
1132
|
+
items: CompiledNavItem[];
|
|
952
1133
|
}
|
|
953
1134
|
/**
|
|
954
|
-
*
|
|
1135
|
+
* Complete runtime compiled navigation tree.
|
|
955
1136
|
*/
|
|
956
|
-
interface
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1137
|
+
interface CompiledNavTree {
|
|
1138
|
+
groups: CompiledNavGroup[];
|
|
1139
|
+
ungrouped: CompiledNavItem[];
|
|
1140
|
+
}
|
|
1141
|
+
interface PinnedNavItemRef {
|
|
1142
|
+
type: "workspace" | "collection" | "global" | "link" | "dashboard";
|
|
1143
|
+
slug: string;
|
|
1144
|
+
view?: string;
|
|
1145
|
+
label?: string;
|
|
1146
|
+
icon?: string;
|
|
1147
|
+
}
|
|
1148
|
+
interface UserNavigationPreferences {
|
|
1149
|
+
_version: number;
|
|
1150
|
+
pinned?: PinnedNavItemRef[];
|
|
1151
|
+
hidden?: string[];
|
|
1152
|
+
groupOrder?: string[];
|
|
1153
|
+
itemOrder?: Record<string, string[]>;
|
|
1154
|
+
groups?: NavGroup[];
|
|
1155
|
+
items?: DefineWorkspaceOptions[];
|
|
1156
|
+
}
|
|
1157
|
+
declare const CURRENT_NAV_PREFERENCES_VERSION = 1;
|
|
1158
|
+
declare const DEFAULT_USER_NAV_PREFERENCES: UserNavigationPreferences;
|
|
1159
|
+
|
|
1160
|
+
/** A valid icon component name from the Lucide icon set bundled with Dyrected Admin. */
|
|
1161
|
+
type AdminIconName = keyof typeof icons;
|
|
1162
|
+
/** Ordered custom component keys rendered around the built-in Admin dashboard. */
|
|
1163
|
+
interface AdminDashboardComponentSlots {
|
|
1164
|
+
beforeDashboard?: string[];
|
|
1165
|
+
afterDashboard?: string[];
|
|
1166
|
+
}
|
|
1167
|
+
/** Ordered custom component keys rendered around an operational view's content. */
|
|
1168
|
+
interface CollectionViewComponentSlots {
|
|
1169
|
+
beforeViewHeader?: string[];
|
|
1170
|
+
afterViewHeader?: string[];
|
|
1171
|
+
beforeViewContent?: string[];
|
|
1172
|
+
afterViewContent?: string[];
|
|
1173
|
+
}
|
|
1174
|
+
/** Ordered custom component keys rendered around a collection's list content. */
|
|
1175
|
+
interface CollectionListComponentSlots {
|
|
1176
|
+
beforeList?: string[];
|
|
1177
|
+
beforeListTable?: string[];
|
|
1178
|
+
afterListTable?: string[];
|
|
1179
|
+
afterList?: string[];
|
|
1180
|
+
beforeViewHeader?: string[];
|
|
1181
|
+
afterViewHeader?: string[];
|
|
1182
|
+
beforeViewContent?: string[];
|
|
1183
|
+
afterViewContent?: string[];
|
|
1184
|
+
collectionView?: CollectionViewComponentSlots;
|
|
963
1185
|
}
|
|
964
1186
|
/**
|
|
965
|
-
*
|
|
1187
|
+
* Branding and metadata options for the Dyrected Admin UI.
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* admin: {
|
|
1191
|
+
* branding: {
|
|
1192
|
+
* logo: '/logo.svg',
|
|
1193
|
+
* primaryColor: '#6366f1',
|
|
1194
|
+
* },
|
|
1195
|
+
* meta: {
|
|
1196
|
+
* titleSuffix: '- My App',
|
|
1197
|
+
* },
|
|
1198
|
+
* }
|
|
966
1199
|
*/
|
|
967
|
-
interface
|
|
968
|
-
/** Grid width of the sub-grid container in the surrounding layout. */
|
|
969
|
-
span?: DetailSpan;
|
|
1200
|
+
interface AdminConfig {
|
|
970
1201
|
/**
|
|
971
|
-
*
|
|
972
|
-
*
|
|
1202
|
+
* Custom navigation layout for the admin sidebar.
|
|
1203
|
+
* If omitted, all collections and globals appear in default sections.
|
|
973
1204
|
*/
|
|
974
|
-
|
|
1205
|
+
navigation?: DefineWorkspaceOptions[];
|
|
1206
|
+
/** Custom component slots around the built-in dashboard. */
|
|
1207
|
+
components?: AdminDashboardComponentSlots;
|
|
1208
|
+
branding?: {
|
|
1209
|
+
/** Full logo image shown in the expanded sidebar. URL or imported image asset. */
|
|
1210
|
+
logo?: string;
|
|
1211
|
+
/** Compact logo mark used in the collapsed sidebar state. */
|
|
1212
|
+
logoMark?: string;
|
|
1213
|
+
/** Text alternative or addition to the logo image. */
|
|
1214
|
+
logoText?: string;
|
|
1215
|
+
/**
|
|
1216
|
+
* Brand colour used for committed, filled actions — Save, Create, Upload —
|
|
1217
|
+
* and active/selected states. Accepts a hex string, a named colour
|
|
1218
|
+
* (`amber`, `lime`, `violet`, `green`, `blue`, `red`, `purple`, `orange`),
|
|
1219
|
+
* or a raw HSL triplet (`"217 91% 60%"`). Applied in both light and dark mode.
|
|
1220
|
+
*
|
|
1221
|
+
* This is one half of the two-colour brand model. Use {@link accentColor}
|
|
1222
|
+
* for links and navigation accents. If you only set `primaryColor`, it is
|
|
1223
|
+
* reused for accents too, matching the single-brand-colour look.
|
|
1224
|
+
* @example '#6366f1'
|
|
1225
|
+
* @example 'blue'
|
|
1226
|
+
* @example 'hsl(240 50% 60%)'
|
|
1227
|
+
*/
|
|
1228
|
+
primaryColor?: string;
|
|
1229
|
+
/**
|
|
1230
|
+
* Brand colour used for links, active navigation details, hover text, and
|
|
1231
|
+
* focus rings — the "accent" half of the two-colour brand model, mapped to
|
|
1232
|
+
* the admin's `--intelligence` token. Accepts the same formats as
|
|
1233
|
+
* {@link primaryColor} and applies in both light and dark mode.
|
|
1234
|
+
*
|
|
1235
|
+
* Set this when your brand has a distinct link/accent colour separate from
|
|
1236
|
+
* your primary action colour. When omitted, accents fall back to
|
|
1237
|
+
* `primaryColor` (if set) or the built-in default.
|
|
1238
|
+
* @example '#8b5cf6'
|
|
1239
|
+
* @example 'violet'
|
|
1240
|
+
*/
|
|
1241
|
+
accentColor?: string;
|
|
1242
|
+
/** Browser tab favicon URL. */
|
|
1243
|
+
favicon?: string;
|
|
1244
|
+
/** Font family for body and UI text. Must be loaded separately. */
|
|
1245
|
+
fontSans?: string;
|
|
1246
|
+
/** Font family for headings. Must be loaded separately. */
|
|
1247
|
+
fontSerif?: string;
|
|
1248
|
+
};
|
|
1249
|
+
meta?: {
|
|
1250
|
+
/**
|
|
1251
|
+
* String appended to every Admin page's `<title>`.
|
|
1252
|
+
* @default '- Dyrected'
|
|
1253
|
+
*/
|
|
1254
|
+
titleSuffix?: string;
|
|
1255
|
+
};
|
|
1256
|
+
/**
|
|
1257
|
+
* The canonical/base URL of the frontend website for links and iframe live previews.
|
|
1258
|
+
*/
|
|
1259
|
+
siteUrl?: string;
|
|
1260
|
+
/**
|
|
1261
|
+
* Public URL of the Admin UI, used for links in invite and password-reset emails.
|
|
1262
|
+
* Falls back to the `DYRECTED_ADMIN_URL` env var, then the page the admin is running on,
|
|
1263
|
+
* then `/admin` (resolved against the request origin).
|
|
1264
|
+
*/
|
|
1265
|
+
adminUrl?: string;
|
|
975
1266
|
}
|
|
1267
|
+
|
|
1268
|
+
type DeclarativeHookExpression = string;
|
|
1269
|
+
/**
|
|
1270
|
+
* @deprecated Use {@link FieldBeforeChangeHook} or `FieldAfterReadHook` instead.
|
|
1271
|
+
* This alias remains for backwards compatibility.
|
|
1272
|
+
*/
|
|
1273
|
+
type FieldHook<TDoc extends object = Record<string, unknown>, TValue = unknown> = FieldBeforeChangeHook<TValue, TDoc>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Runs before Dyrected queries the database for a list or single-document fetch.
|
|
1276
|
+
*
|
|
1277
|
+
* Return a new `where` query object to override or extend the current filter.
|
|
1278
|
+
* Return `undefined` (or nothing) to leave the query unchanged.
|
|
1279
|
+
*/
|
|
1280
|
+
type CollectionBeforeReadHook = (args: {
|
|
1281
|
+
req: HookRequestContext;
|
|
1282
|
+
query?: Record<string, unknown>;
|
|
1283
|
+
user?: AuthenticatedUser;
|
|
1284
|
+
db: ReadonlyDatabaseAdapter;
|
|
1285
|
+
}) => Record<string, unknown> | void | Promise<Record<string, unknown> | void>;
|
|
1286
|
+
type CollectionBeforeReadHookEntry = CollectionBeforeReadHook | DeclarativeHookExpression;
|
|
1287
|
+
/**
|
|
1288
|
+
* Runs after a document (or list of documents) is fetched from the database,
|
|
1289
|
+
* before the response is sent to the client.
|
|
1290
|
+
*/
|
|
1291
|
+
type CollectionAfterReadHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1292
|
+
doc: TDoc;
|
|
1293
|
+
req: HookRequestContext;
|
|
1294
|
+
user?: AuthenticatedUser;
|
|
1295
|
+
db: ReadonlyDatabaseAdapter;
|
|
1296
|
+
}) => TDoc | Promise<TDoc>;
|
|
1297
|
+
type CollectionAfterReadHookEntry<TDoc extends object = Record<string, unknown>> = CollectionAfterReadHook<TDoc> | DeclarativeHookExpression;
|
|
976
1298
|
/**
|
|
977
|
-
*
|
|
1299
|
+
* Runs **before** a document is created or updated in the database.
|
|
978
1300
|
*/
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
}
|
|
1301
|
+
type CollectionBeforeChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1302
|
+
data: Partial<TDoc>;
|
|
1303
|
+
doc?: TDoc;
|
|
1304
|
+
req: HookRequestContext;
|
|
1305
|
+
user?: AuthenticatedUser;
|
|
1306
|
+
operation: "create" | "update";
|
|
1307
|
+
db: ReadonlyDatabaseAdapter;
|
|
1308
|
+
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;
|
|
1309
|
+
type CollectionBeforeChangeHookEntry<TDoc extends object = Record<string, unknown>> = CollectionBeforeChangeHook<TDoc> | DeclarativeHookExpression;
|
|
989
1310
|
/**
|
|
990
|
-
*
|
|
1311
|
+
* Runs **after** a document is created or updated in the database.
|
|
991
1312
|
*/
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
* Visibility condition for this repeat container.
|
|
1001
|
-
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1002
|
-
*/
|
|
1003
|
-
visible?: string | boolean;
|
|
1004
|
-
/** Field name in each row to use as the card header title (e.g. 'title', 'key', 'name'). */
|
|
1005
|
-
useAsTitle?: string;
|
|
1006
|
-
/** Field name in each row to use as the card header title (alias for useAsTitle). */
|
|
1007
|
-
titleField?: string;
|
|
1008
|
-
/** Static card title prefix or template (e.g. 'Category' or 'Card #{index}'). */
|
|
1009
|
-
title?: string;
|
|
1010
|
-
/** Optional icon name for card header. */
|
|
1011
|
-
icon?: string;
|
|
1012
|
-
/** Number of grid columns for cards layout (1, 2, 3, or 4; defaults to 3). */
|
|
1013
|
-
columns?: 1 | 2 | 3 | 4;
|
|
1014
|
-
}
|
|
1313
|
+
type CollectionAfterChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1314
|
+
doc: TDoc;
|
|
1315
|
+
previousDoc?: TDoc;
|
|
1316
|
+
req: HookRequestContext;
|
|
1317
|
+
user?: AuthenticatedUser;
|
|
1318
|
+
operation: "create" | "update";
|
|
1319
|
+
db: DatabaseAdapter;
|
|
1320
|
+
}) => void | Promise<void>;
|
|
1015
1321
|
/**
|
|
1016
|
-
*
|
|
1322
|
+
* Runs **inside** the database transaction that persists a create or update,
|
|
1323
|
+
* after the document is written and before the transaction commits.
|
|
1324
|
+
*
|
|
1325
|
+
* `tx` is a writable, transaction-scoped adapter: anything written through it
|
|
1326
|
+
* commits or rolls back together with the document. Throw to abort the whole
|
|
1327
|
+
* operation, including the primary write. Use it for invariants that must hold
|
|
1328
|
+
* atomically, such as writing a ledger row alongside a payment.
|
|
1329
|
+
*
|
|
1330
|
+
* Requires a database adapter that supports transactions.
|
|
1017
1331
|
*/
|
|
1018
|
-
|
|
1019
|
-
/**
|
|
1020
|
-
|
|
1021
|
-
/**
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1332
|
+
type CollectionBeforeCommitHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1333
|
+
/** The document as persisted by this operation. */
|
|
1334
|
+
doc: TDoc;
|
|
1335
|
+
/** The document before the update. Absent on create. */
|
|
1336
|
+
previousDoc?: TDoc;
|
|
1337
|
+
req: HookRequestContext;
|
|
1338
|
+
user?: AuthenticatedUser;
|
|
1339
|
+
operation: "create" | "update";
|
|
1340
|
+
/** Writable, transaction-scoped database adapter. */
|
|
1341
|
+
tx: DatabaseAdapter;
|
|
1342
|
+
}) => void | Promise<void>;
|
|
1028
1343
|
/**
|
|
1029
|
-
*
|
|
1344
|
+
* Runs **before** a document is deleted from the database.
|
|
1030
1345
|
*/
|
|
1031
|
-
type
|
|
1346
|
+
type CollectionBeforeDeleteHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1347
|
+
id: string;
|
|
1032
1348
|
doc: TDoc;
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1349
|
+
req: HookRequestContext;
|
|
1350
|
+
user?: AuthenticatedUser;
|
|
1351
|
+
db: ReadonlyDatabaseAdapter;
|
|
1352
|
+
}) => void | Promise<void>;
|
|
1036
1353
|
/**
|
|
1037
|
-
*
|
|
1354
|
+
* Runs **after** a document has been deleted from the database.
|
|
1038
1355
|
*/
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
format?: string;
|
|
1050
|
-
/** Currency code when format is 'currency'. */
|
|
1051
|
-
currency?: string;
|
|
1052
|
-
/**
|
|
1053
|
-
* Visibility condition for this computed card.
|
|
1054
|
-
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1055
|
-
*/
|
|
1056
|
-
visible?: string | boolean;
|
|
1057
|
-
}
|
|
1356
|
+
type CollectionAfterDeleteHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1357
|
+
id: string;
|
|
1358
|
+
doc: TDoc;
|
|
1359
|
+
req: HookRequestContext;
|
|
1360
|
+
user?: AuthenticatedUser;
|
|
1361
|
+
db: DatabaseAdapter;
|
|
1362
|
+
}) => void | Promise<void>;
|
|
1363
|
+
/** @see {@link CollectionBeforeReadHook} */
|
|
1364
|
+
type GlobalBeforeReadHook = CollectionBeforeReadHook;
|
|
1365
|
+
type GlobalBeforeReadHookEntry = CollectionBeforeReadHookEntry;
|
|
1058
1366
|
/**
|
|
1059
|
-
*
|
|
1367
|
+
* Runs after the global document is fetched, before the response is sent.
|
|
1060
1368
|
*/
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
/** JEXL evaluation string. */
|
|
1069
|
-
expression?: string;
|
|
1070
|
-
/** Computed function handler. */
|
|
1071
|
-
handler?: ComputedHandler<TDoc>;
|
|
1072
|
-
/** Computed options. */
|
|
1073
|
-
options?: DetailComputedOptions<TDoc>;
|
|
1074
|
-
}
|
|
1369
|
+
type GlobalAfterReadHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1370
|
+
doc: TDoc;
|
|
1371
|
+
req: HookRequestContext;
|
|
1372
|
+
user?: AuthenticatedUser;
|
|
1373
|
+
db: ReadonlyDatabaseAdapter;
|
|
1374
|
+
}) => TDoc | Promise<TDoc>;
|
|
1375
|
+
type GlobalAfterReadHookEntry<TDoc extends object = Record<string, unknown>> = GlobalAfterReadHook<TDoc> | DeclarativeHookExpression;
|
|
1075
1376
|
/**
|
|
1076
|
-
*
|
|
1377
|
+
* Runs before the global document is updated.
|
|
1378
|
+
* Operation is always `'update'` (globals cannot be created or deleted).
|
|
1077
1379
|
*/
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
spacing?: "sm" | "md" | "lg" | "none";
|
|
1088
|
-
}
|
|
1380
|
+
type GlobalBeforeChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1381
|
+
data: Partial<TDoc>;
|
|
1382
|
+
doc?: TDoc;
|
|
1383
|
+
req: HookRequestContext;
|
|
1384
|
+
user?: AuthenticatedUser;
|
|
1385
|
+
operation: "update";
|
|
1386
|
+
db: ReadonlyDatabaseAdapter;
|
|
1387
|
+
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;
|
|
1388
|
+
type GlobalBeforeChangeHookEntry<TDoc extends object = Record<string, unknown>> = GlobalBeforeChangeHook<TDoc> | DeclarativeHookExpression;
|
|
1089
1389
|
/**
|
|
1090
|
-
*
|
|
1390
|
+
* Runs after the global document is updated. Side-effects only.
|
|
1091
1391
|
*/
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1392
|
+
type GlobalAfterChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1393
|
+
doc: TDoc;
|
|
1394
|
+
previousDoc?: TDoc;
|
|
1395
|
+
req: HookRequestContext;
|
|
1396
|
+
user?: AuthenticatedUser;
|
|
1397
|
+
operation: "update";
|
|
1398
|
+
db: DatabaseAdapter;
|
|
1399
|
+
}) => void | Promise<void>;
|
|
1098
1400
|
/**
|
|
1099
|
-
*
|
|
1401
|
+
* @deprecated Use the specific hook types instead:
|
|
1402
|
+
* `CollectionBeforeChangeHook`, `CollectionAfterReadHook`, etc.
|
|
1403
|
+
*
|
|
1404
|
+
* This broad type remains for backwards compatibility with the internal hook runner.
|
|
1100
1405
|
*/
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1406
|
+
type HookFunction<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1407
|
+
data?: Partial<TDoc>;
|
|
1408
|
+
doc?: TDoc;
|
|
1409
|
+
user?: AuthenticatedUser;
|
|
1410
|
+
req?: HookRequestContext;
|
|
1411
|
+
operation?: "create" | "update" | "delete";
|
|
1412
|
+
db?: DatabaseAdapter;
|
|
1413
|
+
[key: string]: unknown;
|
|
1414
|
+
}) => unknown | Promise<unknown>;
|
|
1415
|
+
|
|
1416
|
+
declare const LIFECYCLE_EVENT_NAMES: readonly ["revision.created", "workflow.transitioned", "entry.published", "entry.unpublished"];
|
|
1417
|
+
type LifecycleEventName = (typeof LIFECYCLE_EVENT_NAMES)[number];
|
|
1418
|
+
interface WorkflowState {
|
|
1419
|
+
/** Stable machine-readable state key. */
|
|
1420
|
+
name: string;
|
|
1421
|
+
/** Label rendered in the Admin UI. */
|
|
1422
|
+
label: string;
|
|
1423
|
+
/** Marks the state whose revision is visible to public readers. */
|
|
1424
|
+
published?: boolean;
|
|
1425
|
+
/** Optional visual tone used by the Admin UI. */
|
|
1426
|
+
color?: "neutral" | "warning" | "success" | "danger" | "info";
|
|
1427
|
+
}
|
|
1428
|
+
interface WorkflowTransition {
|
|
1429
|
+
/** Stable transition key used by the REST and SDK APIs. */
|
|
1430
|
+
name: string;
|
|
1431
|
+
label: string;
|
|
1104
1432
|
/**
|
|
1105
|
-
*
|
|
1106
|
-
*
|
|
1433
|
+
* Source state(s) this transition originates from.
|
|
1434
|
+
* Must match names in the workflow's `states` array.
|
|
1107
1435
|
*/
|
|
1108
|
-
|
|
1109
|
-
/**
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1436
|
+
from: string | string[];
|
|
1437
|
+
/**
|
|
1438
|
+
* Target state this transition leads to.
|
|
1439
|
+
* Must match a name in the workflow's `states` array.
|
|
1440
|
+
*/
|
|
1441
|
+
to: string;
|
|
1442
|
+
/** Every listed capability is required. */
|
|
1443
|
+
requiredCapabilities?: string[];
|
|
1444
|
+
/** Require a non-empty comment when performing the transition. */
|
|
1445
|
+
requireComment?: boolean;
|
|
1446
|
+
/** Remove the public snapshot after this transition commits. */
|
|
1447
|
+
unpublish?: boolean;
|
|
1448
|
+
/**
|
|
1449
|
+
* Runs inside the transition's database transaction, after the workflow state
|
|
1450
|
+
* is written and before it commits. Writes made through `tx` commit or roll
|
|
1451
|
+
* back together with the state change; throw to abort the transition and
|
|
1452
|
+
* leave the document in its original state.
|
|
1453
|
+
*/
|
|
1454
|
+
onTransition?: WorkflowOnTransitionHook;
|
|
1455
|
+
}
|
|
1456
|
+
interface WorkflowOnTransitionContext<TDoc extends object = Record<string, unknown>> {
|
|
1457
|
+
/** The transition being performed. */
|
|
1458
|
+
transition: WorkflowTransition;
|
|
1459
|
+
/** State the document is moving out of. */
|
|
1460
|
+
from: string;
|
|
1461
|
+
/** State the document is moving into. */
|
|
1462
|
+
to: string;
|
|
1463
|
+
/** The document as locked inside the transaction, before the transition is applied. */
|
|
1464
|
+
doc: TDoc;
|
|
1465
|
+
/** Extra payload supplied by the caller alongside the transition request. */
|
|
1466
|
+
input?: Record<string, unknown>;
|
|
1467
|
+
/** Comment supplied with the transition. */
|
|
1468
|
+
comment?: string;
|
|
1469
|
+
/** The user performing the transition, when the request is authenticated. */
|
|
1470
|
+
user?: AuthenticatedUser;
|
|
1471
|
+
/** Request context for the transition. */
|
|
1472
|
+
req: HookRequestContext;
|
|
1473
|
+
/** Writable, transaction-scoped database adapter. */
|
|
1474
|
+
tx: DatabaseAdapter;
|
|
1475
|
+
}
|
|
1476
|
+
type WorkflowOnTransitionHook<TDoc extends object = Record<string, unknown>> = (args: WorkflowOnTransitionContext<TDoc>) => void | Promise<void>;
|
|
1477
|
+
interface WorkflowRole {
|
|
1478
|
+
/** Existing user role value, for example `editor` or `publisher`. */
|
|
1479
|
+
role: string;
|
|
1480
|
+
capabilities: string[];
|
|
1113
1481
|
}
|
|
1114
1482
|
/**
|
|
1115
|
-
*
|
|
1483
|
+
* Configuration for a collection's editorial workflow: the states a document
|
|
1484
|
+
* can be in, the transitions between them, and the roles allowed to perform
|
|
1485
|
+
* each. Attach it to a collection's `workflow`, or build one with
|
|
1486
|
+
* `definePublishingWorkflow`.
|
|
1116
1487
|
*/
|
|
1117
|
-
interface
|
|
1118
|
-
/**
|
|
1119
|
-
|
|
1120
|
-
/**
|
|
1121
|
-
|
|
1122
|
-
/**
|
|
1123
|
-
|
|
1488
|
+
interface WorkflowConfig<TDoc extends object = Record<string, unknown>> {
|
|
1489
|
+
/** The state every new document starts in, e.g. `"draft"`. */
|
|
1490
|
+
initialState: string;
|
|
1491
|
+
/** State used for a new working revision created from published content. */
|
|
1492
|
+
draftState?: string;
|
|
1493
|
+
/** All states a document can occupy. Exactly one should be marked `published`. */
|
|
1494
|
+
states: WorkflowState[];
|
|
1495
|
+
/** The allowed moves between states, each with its own capability and comment rules. */
|
|
1496
|
+
transitions: WorkflowTransition[];
|
|
1497
|
+
/** Maps values in `user.roles` to workflow capabilities. */
|
|
1498
|
+
roles?: WorkflowRole[];
|
|
1499
|
+
/** Server-side hooks that run around every transition. */
|
|
1500
|
+
hooks?: {
|
|
1501
|
+
/** Runs before a transition commits — throw to validate or block the move. */
|
|
1502
|
+
beforeTransition?: CollectionBeforeTransitionHook<TDoc>[];
|
|
1503
|
+
/** Runs after a transition commits — trigger notifications or downstream work. */
|
|
1504
|
+
afterTransition?: CollectionAfterTransitionHook<TDoc>[];
|
|
1505
|
+
};
|
|
1124
1506
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
/**
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1507
|
+
interface WorkflowMetadata {
|
|
1508
|
+
/** The document's current workflow state, e.g. `"draft"` or `"published"`. */
|
|
1509
|
+
state: string;
|
|
1510
|
+
/** Revision counter, incremented on every committed transition. */
|
|
1511
|
+
revision: number;
|
|
1512
|
+
/** Revision number currently exposed as the public snapshot, once published. */
|
|
1513
|
+
publishedRevision?: number;
|
|
1514
|
+
/** ISO timestamp of the most recent publish. */
|
|
1515
|
+
publishedAt?: string;
|
|
1516
|
+
/** Id of the user who last published this document. */
|
|
1517
|
+
publishedBy?: string;
|
|
1518
|
+
/** Transitions currently allowed for the requesting user. Response-only. */
|
|
1519
|
+
availableTransitions?: string[];
|
|
1520
|
+
}
|
|
1521
|
+
interface WorkflowTransitionContext<TDoc extends object = Record<string, unknown>> {
|
|
1522
|
+
/** The transition being performed. */
|
|
1523
|
+
transition: WorkflowTransition;
|
|
1524
|
+
/** State the document is moving out of. */
|
|
1525
|
+
from: string;
|
|
1526
|
+
/** State the document is moving into. */
|
|
1527
|
+
to: string;
|
|
1528
|
+
/** The document as it stands before the transition commits. */
|
|
1529
|
+
doc: TDoc;
|
|
1530
|
+
/** The user performing the transition, when the request is authenticated. */
|
|
1531
|
+
user?: AuthenticatedUser;
|
|
1532
|
+
/** Comment supplied with the transition; required when `requireComment` is set. */
|
|
1533
|
+
comment?: string;
|
|
1534
|
+
/** Extra payload supplied by the caller alongside the transition request. */
|
|
1535
|
+
input?: Record<string, unknown>;
|
|
1536
|
+
/** Request context for the transition. */
|
|
1537
|
+
req: HookRequestContext;
|
|
1538
|
+
/** Transaction-scoped database adapter for reads and writes inside the hook. */
|
|
1539
|
+
db: DatabaseAdapter;
|
|
1540
|
+
}
|
|
1541
|
+
type CollectionBeforeTransitionHook<TDoc extends object = Record<string, unknown>> = (args: WorkflowTransitionContext<TDoc>) => void | Promise<void>;
|
|
1542
|
+
type CollectionAfterTransitionHook<TDoc extends object = Record<string, unknown>> = (args: WorkflowTransitionContext<TDoc> & {
|
|
1543
|
+
event: LifecycleEvent;
|
|
1544
|
+
}) => void | Promise<void>;
|
|
1545
|
+
interface LifecycleEvent<TPayload = Record<string, unknown>> {
|
|
1546
|
+
/** Unique id for this event. */
|
|
1547
|
+
id: string;
|
|
1548
|
+
/** The lifecycle event name, e.g. `"workflow.transitioned"` or `"entry.published"`. */
|
|
1549
|
+
name: LifecycleEventName;
|
|
1550
|
+
/** Slug of the collection the event is about. */
|
|
1551
|
+
collection: string;
|
|
1552
|
+
/** Id of the document the event is about. */
|
|
1553
|
+
documentId: string;
|
|
1554
|
+
/** ISO timestamp of when the event occurred. */
|
|
1555
|
+
occurredAt: string;
|
|
1556
|
+
/** Id of the user who triggered the event, when known. */
|
|
1557
|
+
actorId?: string;
|
|
1558
|
+
/** Event-specific data, such as the transition name and affected revision. */
|
|
1559
|
+
payload: TPayload;
|
|
1560
|
+
/** Number of delivery attempts made so far. */
|
|
1561
|
+
attempts: number;
|
|
1562
|
+
/** Current delivery status as the dispatcher works through the queue. */
|
|
1563
|
+
status: "pending" | "processing" | "delivered" | "failed";
|
|
1564
|
+
/** ISO timestamp of the next delivery retry, while pending. */
|
|
1565
|
+
nextAttemptAt?: string;
|
|
1566
|
+
/** ISO timestamp of successful delivery. */
|
|
1567
|
+
deliveredAt?: string;
|
|
1568
|
+
/** Message from the most recent failed delivery attempt. */
|
|
1569
|
+
lastError?: string;
|
|
1144
1570
|
}
|
|
1571
|
+
type LifecycleEventHandler = (event: LifecycleEvent) => void | Promise<void>;
|
|
1572
|
+
|
|
1573
|
+
/** Column span in the 12-column Detail View layout grid (1 to 12). */
|
|
1574
|
+
type DetailSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
1145
1575
|
/**
|
|
1146
|
-
*
|
|
1576
|
+
* Visual display variants supported by DetailFieldRenderer.
|
|
1147
1577
|
*/
|
|
1148
|
-
|
|
1149
|
-
/** Identifies this item as a custom component. */
|
|
1150
|
-
type: "custom";
|
|
1151
|
-
/** Registered custom component name. */
|
|
1152
|
-
name: string;
|
|
1153
|
-
/** Custom component options. */
|
|
1154
|
-
options?: DetailCustomOptions<TDoc>;
|
|
1155
|
-
}
|
|
1578
|
+
type DisplayVariant = "text" | "badge" | "code-badge" | "code" | "copyable" | "link" | "url" | "email" | "phone" | "currency" | "percent" | "progress" | "star" | "star-rating" | "boolean" | "date" | "datetime" | "time" | "relative" | "image" | "avatar" | "color" | "color-swatches" | "icon" | "key-value" | "table" | "tags" | "badges" | "json";
|
|
1156
1579
|
/**
|
|
1157
|
-
* Configuration options for rendering
|
|
1580
|
+
* Configuration options for rendering a field in a Detail View.
|
|
1158
1581
|
*/
|
|
1159
|
-
interface
|
|
1582
|
+
interface DisplayFieldOptions {
|
|
1583
|
+
/** Custom label overriding the field's schema label. */
|
|
1584
|
+
label?: string;
|
|
1585
|
+
/** When true, hides the field label entirely and renders only the value. */
|
|
1586
|
+
hideLabel?: boolean;
|
|
1587
|
+
/** Informational tooltip shown next to the label. */
|
|
1588
|
+
tooltip?: string;
|
|
1160
1589
|
/** Grid column span across the 12-column grid. */
|
|
1161
1590
|
span?: DetailSpan;
|
|
1162
|
-
/**
|
|
1163
|
-
|
|
1164
|
-
/**
|
|
1165
|
-
|
|
1166
|
-
/**
|
|
1167
|
-
|
|
1591
|
+
/** Specific visual representation variant (e.g. 'badge', 'currency', 'star', 'copyable'). */
|
|
1592
|
+
display?: DisplayVariant;
|
|
1593
|
+
/** Preset format for numbers, dates, and currencies ('currency', 'date', 'datetime', 'relative', 'number', 'percent'). */
|
|
1594
|
+
format?: "currency" | "date" | "datetime" | "relative" | "number" | "percent" | string;
|
|
1595
|
+
/** ISO currency code (e.g. 'USD', 'EUR') when display or format is 'currency'. */
|
|
1596
|
+
currency?: string;
|
|
1597
|
+
/** Color mapping for badge and tag values (named palette, hex color, Tailwind class, or wildcard). */
|
|
1598
|
+
badgeColors?: Record<string, string>;
|
|
1599
|
+
/** Column header for object keys when display is 'key-value'. */
|
|
1600
|
+
keyLabel?: string;
|
|
1601
|
+
/** Column header for object values when display is 'key-value'. */
|
|
1602
|
+
valueLabel?: string;
|
|
1603
|
+
/** Custom placeholder text when the field value is null, undefined, or empty. */
|
|
1604
|
+
emptyText?: string;
|
|
1605
|
+
/** When true, hides this entire field item if the value is null or empty. */
|
|
1606
|
+
hideIfEmpty?: boolean;
|
|
1168
1607
|
/**
|
|
1169
|
-
*
|
|
1608
|
+
* When true, allows inline editing of this field in the Detail View
|
|
1609
|
+
* via an interactive toggle.
|
|
1610
|
+
*/
|
|
1611
|
+
editable?: boolean;
|
|
1612
|
+
/**
|
|
1613
|
+
* Visibility condition for this field item.
|
|
1170
1614
|
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1615
|
+
* When false or evaluating to falsy, this item is hidden in the Detail View.
|
|
1616
|
+
*
|
|
1617
|
+
* @example `visible: "doc.status == 'published'"`
|
|
1618
|
+
* @example `visible: false`
|
|
1171
1619
|
*/
|
|
1172
1620
|
visible?: string | boolean;
|
|
1621
|
+
/** Specific aspect ratio constraint for media (e.g., "16/9", "4/3", "1/1", "auto"). */
|
|
1622
|
+
aspectRatio?: string;
|
|
1623
|
+
/** CSS object-fit behavior for media ('cover', 'contain', 'fill', 'scale-down'). */
|
|
1624
|
+
objectFit?: "cover" | "contain" | "fill" | "scale-down";
|
|
1625
|
+
/** Media alignment ('left', 'center', 'right'). */
|
|
1626
|
+
align?: "left" | "center" | "right";
|
|
1627
|
+
/** Fixed pixel width or CSS dimension for media preview. */
|
|
1628
|
+
width?: string | number;
|
|
1629
|
+
/** Fixed pixel height or CSS dimension for media preview. */
|
|
1630
|
+
height?: string | number;
|
|
1173
1631
|
}
|
|
1174
1632
|
/**
|
|
1175
|
-
*
|
|
1176
|
-
* position in a Detail View. The same action (and its confirm dialog, modal
|
|
1177
|
-
* fields, and execution) can also render automatically in the Detail View's
|
|
1178
|
-
* header toolbar when the action's `type` is `'header'` — placing it here
|
|
1179
|
-
* too does not duplicate that config, it just adds another entry point to
|
|
1180
|
-
* the same action.
|
|
1181
|
-
*/
|
|
1182
|
-
interface DetailAction {
|
|
1183
|
-
/** Identifies this item as an action button. */
|
|
1184
|
-
type: "action";
|
|
1185
|
-
/** Name of the action, matching an entry in `collection.actions`. */
|
|
1186
|
-
name: string;
|
|
1187
|
-
/** Display and visibility options for this placement. */
|
|
1188
|
-
options?: DetailActionOptions;
|
|
1189
|
-
}
|
|
1190
|
-
/**
|
|
1191
|
-
* Union of all valid item types in a Detail View schema.
|
|
1192
|
-
*/
|
|
1193
|
-
type DetailItem<TDoc = any> = DetailSection | DetailTabs | DetailGrid | DetailField | DetailRepeat | DetailComputed<TDoc> | DetailDivider | DetailText | DetailCustom<TDoc> | DetailAction | string;
|
|
1194
|
-
/**
|
|
1195
|
-
* Detail View layout schema definition for a collection or global.
|
|
1196
|
-
*/
|
|
1197
|
-
type DetailSchema<TDoc = any> = DetailItem<TDoc>[];
|
|
1198
|
-
|
|
1199
|
-
/**
|
|
1200
|
-
* The set of type-cast operations supported during aggregation.
|
|
1201
|
-
*
|
|
1202
|
-
* Each adapter maps these to its own native conversion primitive
|
|
1203
|
-
* (e.g. `$toDouble` in MongoDB, `CAST(x AS REAL)` in SQLite).
|
|
1204
|
-
* The public API is always database-independent.
|
|
1205
|
-
*/
|
|
1206
|
-
type AggregateCastType = "number" | "integer" | "float" | "string" | "boolean" | "date";
|
|
1207
|
-
/**
|
|
1208
|
-
* A `count` aggregate operation.
|
|
1209
|
-
*
|
|
1210
|
-
* - `count: "*"` — count every document matched by `where`.
|
|
1211
|
-
* - `cast` is intentionally absent: counting is document-level,
|
|
1212
|
-
* not field-value-level, so type conversion has no meaning here.
|
|
1213
|
-
*/
|
|
1214
|
-
interface CountOperation {
|
|
1215
|
-
count: "*";
|
|
1216
|
-
where?: Record<string, unknown>;
|
|
1217
|
-
}
|
|
1218
|
-
/**
|
|
1219
|
-
* A `countDistinct` aggregate operation that counts the number of unique
|
|
1220
|
-
* non-null values for a specific field.
|
|
1221
|
-
*/
|
|
1222
|
-
interface DistinctCountOperation {
|
|
1223
|
-
countDistinct: string;
|
|
1224
|
-
where?: Record<string, unknown>;
|
|
1225
|
-
}
|
|
1226
|
-
/**
|
|
1227
|
-
* A `distinct` aggregate operation that retrieves the unique values
|
|
1228
|
-
* (or unique values with item counts) for a specific field.
|
|
1229
|
-
*/
|
|
1230
|
-
interface DistinctValuesOperation {
|
|
1231
|
-
distinct: string;
|
|
1232
|
-
where?: Record<string, unknown>;
|
|
1233
|
-
}
|
|
1234
|
-
/**
|
|
1235
|
-
* A `sum`, `avg`, `min`, or `max` aggregate operation on a named field.
|
|
1236
|
-
*
|
|
1237
|
-
* - `cast` converts stored values before the aggregation runs.
|
|
1238
|
-
* Invalid values (e.g. `"unknown"` cast to `number`) become `null`
|
|
1239
|
-
* and are ignored by `sum`, `avg`, `min`, and `max`.
|
|
1240
|
-
*/
|
|
1241
|
-
interface NumericOperation {
|
|
1242
|
-
sum?: string;
|
|
1243
|
-
avg?: string;
|
|
1244
|
-
min?: string;
|
|
1245
|
-
max?: string;
|
|
1246
|
-
cast?: AggregateCastType;
|
|
1247
|
-
where?: Record<string, unknown>;
|
|
1248
|
-
}
|
|
1249
|
-
/**
|
|
1250
|
-
* A single named aggregate request — either a count, distinct count, distinct values, or numeric operation.
|
|
1251
|
-
*/
|
|
1252
|
-
type AggregateOperation = CountOperation | DistinctCountOperation | DistinctValuesOperation | NumericOperation;
|
|
1253
|
-
/**
|
|
1254
|
-
* The map of named aggregate operations sent in a single aggregate request.
|
|
1255
|
-
*
|
|
1256
|
-
* @example
|
|
1257
|
-
* ```ts
|
|
1258
|
-
* {
|
|
1259
|
-
* totalSubmitted: { count: "*" },
|
|
1260
|
-
* uniqueGuests: { countDistinct: "email" },
|
|
1261
|
-
* availableSizes: { distinct: "asoebiSize" },
|
|
1262
|
-
* totalAsoebiYards: { sum: "asoebiYards", cast: "number", where: { wantsAsoebi: { equals: true } } },
|
|
1263
|
-
* }
|
|
1264
|
-
* ```
|
|
1265
|
-
*/
|
|
1266
|
-
type AggregateInput = Record<string, AggregateOperation>;
|
|
1267
|
-
/**
|
|
1268
|
-
* The arguments passed to `DatabaseAdapter.aggregate`.
|
|
1633
|
+
* Declared field item in a Detail View.
|
|
1269
1634
|
*/
|
|
1270
|
-
interface
|
|
1271
|
-
/**
|
|
1272
|
-
|
|
1273
|
-
/**
|
|
1274
|
-
|
|
1275
|
-
/**
|
|
1276
|
-
|
|
1635
|
+
interface DetailField {
|
|
1636
|
+
/** Identifies this item as a field. */
|
|
1637
|
+
type: "field";
|
|
1638
|
+
/** Field name or nested path in the document. */
|
|
1639
|
+
field: string;
|
|
1640
|
+
/** Display options for this field. */
|
|
1641
|
+
options?: DisplayFieldOptions;
|
|
1277
1642
|
}
|
|
1278
1643
|
/**
|
|
1279
|
-
*
|
|
1280
|
-
*
|
|
1281
|
-
* For scalar aggregates, every named key maps to a `number | null` or `any[]` (for distinct).
|
|
1282
|
-
* When `groupBy` is used, returns a breakdown per group.
|
|
1283
|
-
*/
|
|
1284
|
-
type AggregateResult = Record<string, any>;
|
|
1285
|
-
/**
|
|
1286
|
-
* Derives the typed result shape from an `AggregateInput`.
|
|
1287
|
-
*/
|
|
1288
|
-
type InferAggregateResult<T extends AggregateInput> = {
|
|
1289
|
-
[K in keyof T]: any;
|
|
1290
|
-
};
|
|
1291
|
-
|
|
1292
|
-
/**
|
|
1293
|
-
* Dyrected Where Clause DSL — shared query language across all database adapters.
|
|
1294
|
-
*
|
|
1295
|
-
* Adapters translate this DSL into their native format:
|
|
1296
|
-
* - SQL adapters (SQLite, Postgres, MySQL): use parseSqlWhere()
|
|
1297
|
-
* - MongoDB adapter: use parseMongoWhere()
|
|
1298
|
-
* - Future adapters: implement their own translator against WhereClause
|
|
1299
|
-
*
|
|
1300
|
-
* Exhaustive operator handling is enforced at compile time via `assertNever`,
|
|
1301
|
-
* so adding a new operator without handling it will produce a TypeScript error
|
|
1302
|
-
* in every adapter translator.
|
|
1644
|
+
* Configuration options for a Detail View section container.
|
|
1303
1645
|
*/
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
lte: any;
|
|
1329
|
-
} | {
|
|
1330
|
-
less_than_equal: any;
|
|
1331
|
-
} | {
|
|
1332
|
-
less_than_or_equal: any;
|
|
1333
|
-
} | {
|
|
1334
|
-
contains: string;
|
|
1335
|
-
} | {
|
|
1336
|
-
like: string;
|
|
1337
|
-
} | {
|
|
1338
|
-
starts_with: string;
|
|
1339
|
-
} | {
|
|
1340
|
-
exists: boolean;
|
|
1341
|
-
};
|
|
1342
|
-
/** Top-level where clause. Fields map to operator objects or shorthand scalar values. */
|
|
1343
|
-
type WhereClause = {
|
|
1344
|
-
[field: string]: WhereOperator | any;
|
|
1345
|
-
OR?: WhereClause[] | readonly WhereClause[];
|
|
1346
|
-
or?: WhereClause[] | readonly WhereClause[];
|
|
1347
|
-
AND?: WhereClause[] | readonly WhereClause[];
|
|
1348
|
-
and?: WhereClause[] | readonly WhereClause[];
|
|
1349
|
-
};
|
|
1350
|
-
interface SqlWhereResult {
|
|
1351
|
-
sql: string;
|
|
1352
|
-
params: any[];
|
|
1646
|
+
interface DetailSectionOptions {
|
|
1647
|
+
/** Lucide icon name displayed in the section header. */
|
|
1648
|
+
icon?: string;
|
|
1649
|
+
/** Status or counter badge displayed beside the section title. */
|
|
1650
|
+
badge?: string;
|
|
1651
|
+
/** Color palette name or hex code for the section badge. */
|
|
1652
|
+
badgeColor?: string;
|
|
1653
|
+
/** Subtitle description displayed beneath the section title. */
|
|
1654
|
+
description?: string;
|
|
1655
|
+
/** Grid width of the section on the main 12-column layout. */
|
|
1656
|
+
span?: DetailSpan;
|
|
1657
|
+
/** Internal grid column count for child items. */
|
|
1658
|
+
columns?: number;
|
|
1659
|
+
/** When true, allows editors to collapse and expand the section. */
|
|
1660
|
+
collapsible?: boolean;
|
|
1661
|
+
/** Starts the section in collapsed state when collapsible is enabled. */
|
|
1662
|
+
collapsedByDefault?: boolean;
|
|
1663
|
+
/**
|
|
1664
|
+
* Visibility condition for this section.
|
|
1665
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1666
|
+
*
|
|
1667
|
+
* @example `visible: "user.roles != null and 'admin' in user.roles"`
|
|
1668
|
+
*/
|
|
1669
|
+
visible?: string | boolean;
|
|
1353
1670
|
}
|
|
1354
1671
|
/**
|
|
1355
|
-
*
|
|
1356
|
-
*
|
|
1357
|
-
* @param where The Dyrected where DSL object
|
|
1358
|
-
* @param getJsonField Returns the SQL expression for a JSON-stored field (dialect-specific):
|
|
1359
|
-
* SQLite: (f) => `json_extract(data, '$.${f}')`
|
|
1360
|
-
* Postgres: (f) => `data->>'${f}'`
|
|
1361
|
-
* MySQL: (f) => `JSON_UNQUOTE(JSON_EXTRACT(data, '$.${f}'))`
|
|
1362
|
-
* @param placeholder '?' for SQLite/MySQL, 'pg' for auto-incrementing Postgres $1/$2/…
|
|
1672
|
+
* Section container grouping fields and components in a Detail View.
|
|
1363
1673
|
*/
|
|
1364
|
-
|
|
1674
|
+
interface DetailSection {
|
|
1675
|
+
/** Identifies this item as a section. */
|
|
1676
|
+
type: "section";
|
|
1677
|
+
/** Section heading title. */
|
|
1678
|
+
title: string;
|
|
1679
|
+
/** Child items rendered inside this section. */
|
|
1680
|
+
items: DetailItem[];
|
|
1681
|
+
/** Section container options. */
|
|
1682
|
+
options?: DetailSectionOptions;
|
|
1683
|
+
}
|
|
1365
1684
|
/**
|
|
1366
|
-
*
|
|
1367
|
-
* case-sensitive, so the Postgres adapter defaults to `'ILIKE'` to keep substring
|
|
1368
|
-
* matching case-insensitive like SQLite and MySQL.
|
|
1685
|
+
* Configuration options for an individual tab in `displayTabs()`.
|
|
1369
1686
|
*/
|
|
1370
|
-
|
|
1687
|
+
interface DetailTabOptions {
|
|
1688
|
+
/** Lucide icon name displayed inside the tab trigger. */
|
|
1689
|
+
icon?: string;
|
|
1690
|
+
/** Counter or status badge rendered next to the tab label. */
|
|
1691
|
+
badge?: string;
|
|
1692
|
+
/** Color palette name or hex code for the tab badge. */
|
|
1693
|
+
badgeColor?: string;
|
|
1694
|
+
/**
|
|
1695
|
+
* Visibility condition for this individual tab.
|
|
1696
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1697
|
+
*/
|
|
1698
|
+
visible?: string | boolean;
|
|
1699
|
+
}
|
|
1371
1700
|
/**
|
|
1372
|
-
*
|
|
1373
|
-
* Handles nested OR/AND via $or/$and, and all operators via $eq/$in/$gt etc.
|
|
1701
|
+
* Single tab entry inside a tabbed container.
|
|
1374
1702
|
*/
|
|
1375
|
-
|
|
1376
|
-
|
|
1703
|
+
interface DetailTab {
|
|
1704
|
+
/** Identifies this item as a tab. */
|
|
1705
|
+
type: "tab";
|
|
1706
|
+
/** Tab label shown in the tab bar. */
|
|
1707
|
+
label: string;
|
|
1708
|
+
/** Child items rendered when this tab is active. */
|
|
1709
|
+
items: DetailItem[];
|
|
1710
|
+
/** Tab options. */
|
|
1711
|
+
options?: DetailTabOptions;
|
|
1712
|
+
}
|
|
1377
1713
|
/**
|
|
1378
|
-
*
|
|
1714
|
+
* Configuration options for a tabbed container.
|
|
1379
1715
|
*/
|
|
1380
|
-
|
|
1716
|
+
interface DetailTabsOptions {
|
|
1717
|
+
/** Grid width of the tabs container on the main layout. */
|
|
1718
|
+
span?: DetailSpan;
|
|
1719
|
+
/** Label of the tab that should be active on initial render. */
|
|
1720
|
+
defaultTab?: string;
|
|
1721
|
+
/**
|
|
1722
|
+
* Visibility condition for this tab container.
|
|
1723
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1724
|
+
*/
|
|
1725
|
+
visible?: string | boolean;
|
|
1726
|
+
}
|
|
1381
1727
|
/**
|
|
1382
|
-
*
|
|
1383
|
-
* - `'table'`: The workhorse — column sorting, search, faceted filters, and bulk actions.
|
|
1384
|
-
* - `'spreadsheet'`: Inline-editable matrix with batch saving (`Save changes` / `Discard`).
|
|
1385
|
-
* - `'kanban'`: Interactive card board grouped by status or category with drag-and-drop.
|
|
1386
|
-
* - `'calendar'`: Event schedule grid plotting records across month/week/day views by date.
|
|
1387
|
-
* - `'gantt'`: Timeline bars plotted across start and end dates.
|
|
1388
|
-
* - `'cards'`: Visual image/thumbnail gallery grid.
|
|
1728
|
+
* Tabbed navigation container in a Detail View layout.
|
|
1389
1729
|
*/
|
|
1390
|
-
|
|
1730
|
+
interface DetailTabs {
|
|
1731
|
+
/** Identifies this item as a tab container. */
|
|
1732
|
+
type: "tabs";
|
|
1733
|
+
/** List of tabs in this container. */
|
|
1734
|
+
tabs: DetailTab[];
|
|
1735
|
+
/** Tab container options. */
|
|
1736
|
+
options?: DetailTabsOptions;
|
|
1737
|
+
}
|
|
1391
1738
|
/**
|
|
1392
|
-
*
|
|
1393
|
-
* - `'row'`: Renders as an inline action button on each document/row.
|
|
1394
|
-
* - `'bulk'`: Appears in the floating bulk action bar when one or more rows are selected.
|
|
1395
|
-
* - `'header'`: Renders as a primary action button in the view header.
|
|
1739
|
+
* Configuration options for a sub-grid container.
|
|
1396
1740
|
*/
|
|
1397
|
-
|
|
1741
|
+
interface DetailGridOptions {
|
|
1742
|
+
/** Grid width of the sub-grid container in the surrounding layout. */
|
|
1743
|
+
span?: DetailSpan;
|
|
1744
|
+
/**
|
|
1745
|
+
* Visibility condition for this grid container.
|
|
1746
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1747
|
+
*/
|
|
1748
|
+
visible?: string | boolean;
|
|
1749
|
+
}
|
|
1398
1750
|
/**
|
|
1399
|
-
*
|
|
1400
|
-
* All default to enabled (`true`). Set any to `false` to hide that operation.
|
|
1401
|
-
*
|
|
1402
|
-
* @example
|
|
1403
|
-
* ```ts
|
|
1404
|
-
* features: {
|
|
1405
|
-
* delete: false, // Prevent deleting records from this view
|
|
1406
|
-
* exportSelected: true, // Enable CSV export for checked rows
|
|
1407
|
-
* }
|
|
1408
|
-
* ```
|
|
1751
|
+
* Multi-column sub-grid layout inside a section or tab.
|
|
1409
1752
|
*/
|
|
1410
|
-
interface
|
|
1411
|
-
/**
|
|
1412
|
-
|
|
1413
|
-
/**
|
|
1414
|
-
|
|
1415
|
-
/**
|
|
1416
|
-
|
|
1417
|
-
/**
|
|
1418
|
-
|
|
1419
|
-
/** Enables the "Export selected" CSV action in the bulk action bar. Defaults to `true`. */
|
|
1420
|
-
exportSelected?: boolean;
|
|
1753
|
+
interface DetailGrid {
|
|
1754
|
+
/** Identifies this item as a grid. */
|
|
1755
|
+
type: "grid";
|
|
1756
|
+
/** Number of balanced columns in this grid. */
|
|
1757
|
+
columns: number;
|
|
1758
|
+
/** Child items rendered across the grid columns. */
|
|
1759
|
+
items: DetailItem[];
|
|
1760
|
+
/** Grid container options. */
|
|
1761
|
+
options?: DetailGridOptions;
|
|
1421
1762
|
}
|
|
1422
1763
|
/**
|
|
1423
|
-
*
|
|
1424
|
-
* `'purple' | 'emerald' | 'amber' | 'rose' | 'blue' | 'indigo' | 'cyan' | 'orange'`
|
|
1764
|
+
* Configuration options for a repeated array field.
|
|
1425
1765
|
*/
|
|
1426
|
-
|
|
1766
|
+
interface DetailRepeatOptions {
|
|
1767
|
+
/** Layout style for repeated items: 'table', 'cards', or 'list'. */
|
|
1768
|
+
layout?: "table" | "cards" | "list";
|
|
1769
|
+
/** Message shown when the repeated array is empty. */
|
|
1770
|
+
emptyText?: string;
|
|
1771
|
+
/** Grid width of the repeated container. */
|
|
1772
|
+
span?: DetailSpan;
|
|
1773
|
+
/**
|
|
1774
|
+
* Visibility condition for this repeat container.
|
|
1775
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1776
|
+
*/
|
|
1777
|
+
visible?: string | boolean;
|
|
1778
|
+
/** Field name in each row to use as the card header title (e.g. 'title', 'key', 'name'). */
|
|
1779
|
+
useAsTitle?: string;
|
|
1780
|
+
/** Field name in each row to use as the card header title (alias for useAsTitle). */
|
|
1781
|
+
titleField?: string;
|
|
1782
|
+
/** Static card title prefix or template (e.g. 'Category' or 'Card #{index}'). */
|
|
1783
|
+
title?: string;
|
|
1784
|
+
/** Optional icon name for card header. */
|
|
1785
|
+
icon?: string;
|
|
1786
|
+
/** Number of grid columns for cards layout (1, 2, 3, or 4; defaults to 3). */
|
|
1787
|
+
columns?: 1 | 2 | 3 | 4;
|
|
1788
|
+
}
|
|
1427
1789
|
/**
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
* @example
|
|
1431
|
-
* ```ts
|
|
1432
|
-
* {
|
|
1433
|
-
* label: "Pending",
|
|
1434
|
-
* aggregates: {
|
|
1435
|
-
* checkedIn: { count: "*", where: { checkedIn: { equals: true } } },
|
|
1436
|
-
* attending: { count: "*", where: { attending: { equals: true } } },
|
|
1437
|
-
* },
|
|
1438
|
-
* expression: "aggregates.attending - aggregates.checkedIn",
|
|
1439
|
-
* }
|
|
1440
|
-
* ```
|
|
1790
|
+
* Delegated repeated array field item in a Detail View.
|
|
1441
1791
|
*/
|
|
1442
|
-
interface
|
|
1443
|
-
/**
|
|
1444
|
-
|
|
1445
|
-
/**
|
|
1446
|
-
|
|
1447
|
-
/**
|
|
1448
|
-
|
|
1449
|
-
/**
|
|
1450
|
-
|
|
1451
|
-
/** JEXL math formula evaluated over `aggregates` (e.g. `"aggregates.a - aggregates.b"`). */
|
|
1452
|
-
expression?: string;
|
|
1453
|
-
/** Display formatter: `'currency' | 'number' | 'percent'`. */
|
|
1454
|
-
format?: 'currency' | 'number' | 'percent' | string;
|
|
1455
|
-
/** 3-letter currency code (e.g. `"USD"`, `"NGN"`, `"EUR"`) used when `format: "currency"`. */
|
|
1456
|
-
currency?: string;
|
|
1792
|
+
interface DetailRepeat {
|
|
1793
|
+
/** Identifies this item as a repeat container. */
|
|
1794
|
+
type: "repeat";
|
|
1795
|
+
/** Array field name in the document. */
|
|
1796
|
+
field: string;
|
|
1797
|
+
/** Item template schemas rendered for each element in the array. */
|
|
1798
|
+
items: DetailItem[];
|
|
1799
|
+
/** Repeat options. */
|
|
1800
|
+
options?: DetailRepeatOptions;
|
|
1457
1801
|
}
|
|
1458
1802
|
/**
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1461
|
-
* All aggregations run directly on the database engine for maximum performance.
|
|
1462
|
-
*
|
|
1463
|
-
* @example
|
|
1464
|
-
* ```ts
|
|
1465
|
-
* {
|
|
1466
|
-
* label: "Total Revenue",
|
|
1467
|
-
* color: "emerald",
|
|
1468
|
-
* aggregate: { sum: "amount", cast: "number", where: { status: "paid" } },
|
|
1469
|
-
* format: "currency",
|
|
1470
|
-
* currency: "USD",
|
|
1471
|
-
* }
|
|
1472
|
-
* ```
|
|
1803
|
+
* Async or synchronous handler function calculating a computed metric.
|
|
1473
1804
|
*/
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
/** Unit badge shown alongside the numeric value (e.g. `"Guests"`, `"Orders"`, `"Tables"`). */
|
|
1480
|
-
unit?: string;
|
|
1481
|
-
/** Single database aggregate operation (`count`, `distinctCount`, `sum`, `avg`, `min`, `max`). */
|
|
1482
|
-
aggregate?: AggregateOperation;
|
|
1483
|
-
/** Map of named aggregate operations referenced in `expression` as `aggregates.key`. */
|
|
1484
|
-
aggregates?: Record<string, AggregateOperation>;
|
|
1485
|
-
/** JEXL math formula evaluated over `value` for a single aggregate (e.g. `"value * 25000"`). */
|
|
1486
|
-
transform?: string;
|
|
1487
|
-
/** JEXL math formula evaluated over `aggregates` (e.g. `"(aggregates.paid / aggregates.total) * 100"`). */
|
|
1488
|
-
expression?: string;
|
|
1489
|
-
/** Display formatter: `'currency' | 'number' | 'percent'`. */
|
|
1490
|
-
format?: 'currency' | 'number' | 'percent' | string;
|
|
1491
|
-
/** 3-letter currency code (e.g. `"USD"`, `"NGN"`, `"EUR"`) used when `format: "currency"`. */
|
|
1492
|
-
currency?: string;
|
|
1493
|
-
/** Optional secondary breakdown items shown in the card footer. */
|
|
1494
|
-
subMetrics?: ViewSubMetric[];
|
|
1495
|
-
}
|
|
1805
|
+
type ComputedHandler<TDoc = any> = (context: {
|
|
1806
|
+
doc: TDoc;
|
|
1807
|
+
user?: any;
|
|
1808
|
+
db?: any;
|
|
1809
|
+
}) => any | Promise<any>;
|
|
1496
1810
|
/**
|
|
1497
|
-
*
|
|
1811
|
+
* Configuration options for a computed value card.
|
|
1498
1812
|
*/
|
|
1499
|
-
interface
|
|
1500
|
-
/**
|
|
1501
|
-
|
|
1502
|
-
/**
|
|
1503
|
-
|
|
1504
|
-
/**
|
|
1505
|
-
|
|
1506
|
-
/**
|
|
1507
|
-
|
|
1508
|
-
/**
|
|
1509
|
-
|
|
1510
|
-
/**
|
|
1511
|
-
|
|
1512
|
-
/** Field name containing the ISO date string for calendar placement. Required when `layout: 'calendar'`. */
|
|
1513
|
-
dateField?: string;
|
|
1514
|
-
/** Field name for the start date in timeline/gantt views. Required when `layout: 'gantt'`. */
|
|
1515
|
-
startDateField?: string;
|
|
1516
|
-
/** Field name for the end date in timeline/gantt views. Required when `layout: 'gantt'`. */
|
|
1517
|
-
endDateField?: string;
|
|
1518
|
-
/** Field names to show in this view, in order. If omitted, Dyrected infers default display fields. */
|
|
1519
|
-
columns?: string[];
|
|
1520
|
-
/** Default sorting rule when entering the view. */
|
|
1521
|
-
sort?: {
|
|
1522
|
-
field: string;
|
|
1523
|
-
direction: 'asc' | 'desc';
|
|
1524
|
-
};
|
|
1525
|
-
/** Custom workflow actions available in this view. */
|
|
1526
|
-
actions?: ActionConfig[];
|
|
1527
|
-
/** Toggles built-in operations (view/edit/duplicate/delete/export). */
|
|
1528
|
-
features?: ViewActionFeatures;
|
|
1813
|
+
interface DetailComputedOptions<TDoc = any> {
|
|
1814
|
+
/** Unique identifier for the computed metric. */
|
|
1815
|
+
id?: string;
|
|
1816
|
+
/** JEXL expression string evaluated against `{ doc, user }`. */
|
|
1817
|
+
expression?: string;
|
|
1818
|
+
/** Async or sync function receiving `{ doc, user, db }` returning the computed value. */
|
|
1819
|
+
handler?: ComputedHandler<TDoc>;
|
|
1820
|
+
/** Grid width for the computed card. */
|
|
1821
|
+
span?: DetailSpan;
|
|
1822
|
+
/** Formatting preset for the computed value ('currency', 'percent', 'number', 'date'). */
|
|
1823
|
+
format?: string;
|
|
1824
|
+
/** Currency code when format is 'currency'. */
|
|
1825
|
+
currency?: string;
|
|
1529
1826
|
/**
|
|
1530
|
-
*
|
|
1531
|
-
*
|
|
1827
|
+
* Visibility condition for this computed card.
|
|
1828
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1532
1829
|
*/
|
|
1533
|
-
|
|
1534
|
-
/** KPI summary cards rendered in the hero row above the view. */
|
|
1535
|
-
metrics?: ViewMetric[];
|
|
1536
|
-
/** Role-based access rules controlling who can see or use this view. */
|
|
1537
|
-
access?: AccessConfig;
|
|
1830
|
+
visible?: string | boolean;
|
|
1538
1831
|
}
|
|
1539
1832
|
/**
|
|
1540
|
-
*
|
|
1833
|
+
* Computed KPI or metric card in a Detail View.
|
|
1541
1834
|
*/
|
|
1542
|
-
interface
|
|
1543
|
-
/**
|
|
1544
|
-
|
|
1545
|
-
/**
|
|
1835
|
+
interface DetailComputed<TDoc = any> {
|
|
1836
|
+
/** Identifies this item as a computed value. */
|
|
1837
|
+
type: "computed";
|
|
1838
|
+
/** Unique computed identifier. */
|
|
1839
|
+
id?: string;
|
|
1840
|
+
/** Human-readable card label. */
|
|
1546
1841
|
label: string;
|
|
1547
|
-
/**
|
|
1548
|
-
|
|
1549
|
-
/**
|
|
1550
|
-
|
|
1551
|
-
/**
|
|
1552
|
-
|
|
1553
|
-
/** Optional confirmation prompt shown before executing (e.g. `"Confirm guest check-in at the door?"`). */
|
|
1554
|
-
confirm?: string;
|
|
1555
|
-
/** Optional interactive modal form fields prompting the user for input before executing. */
|
|
1556
|
-
fields?: Field[];
|
|
1557
|
-
/** Role-based access rules controlling who can trigger this action. */
|
|
1558
|
-
access?: AccessConfig;
|
|
1842
|
+
/** JEXL evaluation string. */
|
|
1843
|
+
expression?: string;
|
|
1844
|
+
/** Computed function handler. */
|
|
1845
|
+
handler?: ComputedHandler<TDoc>;
|
|
1846
|
+
/** Computed options. */
|
|
1847
|
+
options?: DetailComputedOptions<TDoc>;
|
|
1559
1848
|
}
|
|
1560
1849
|
/**
|
|
1561
|
-
*
|
|
1850
|
+
* Configuration options for a horizontal divider line.
|
|
1562
1851
|
*/
|
|
1563
|
-
interface
|
|
1564
|
-
/**
|
|
1565
|
-
|
|
1566
|
-
/**
|
|
1567
|
-
|
|
1852
|
+
interface DetailDividerOptions {
|
|
1853
|
+
/** Grid span in the surrounding layout. */
|
|
1854
|
+
span?: DetailSpan;
|
|
1855
|
+
/**
|
|
1856
|
+
* Visibility condition for this divider.
|
|
1857
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1858
|
+
*/
|
|
1859
|
+
visible?: string | boolean;
|
|
1860
|
+
/** Vertical margin spacing around the divider line. */
|
|
1861
|
+
spacing?: "sm" | "md" | "lg" | "none";
|
|
1568
1862
|
}
|
|
1569
1863
|
/**
|
|
1570
|
-
*
|
|
1864
|
+
* Horizontal divider line in a Detail View layout.
|
|
1571
1865
|
*/
|
|
1572
|
-
interface
|
|
1573
|
-
/**
|
|
1574
|
-
|
|
1575
|
-
/**
|
|
1576
|
-
|
|
1866
|
+
interface DetailDivider {
|
|
1867
|
+
/** Identifies this item as a divider. */
|
|
1868
|
+
type: "divider";
|
|
1869
|
+
/** Divider options. */
|
|
1870
|
+
options?: DetailDividerOptions;
|
|
1577
1871
|
}
|
|
1578
1872
|
/**
|
|
1579
|
-
*
|
|
1580
|
-
* Requires either `mutation` or `handler` (or both).
|
|
1581
|
-
*/
|
|
1582
|
-
type ActionConfig<TDoc extends Record<string, unknown> = Record<string, unknown>> = ActionConfigWithMutation<TDoc> | ActionConfigWithHandler<TDoc>;
|
|
1583
|
-
/**
|
|
1584
|
-
* Context passed to an action's server handler function.
|
|
1873
|
+
* Configuration options for a static text or callout block.
|
|
1585
1874
|
*/
|
|
1586
|
-
interface
|
|
1587
|
-
/**
|
|
1588
|
-
|
|
1589
|
-
/**
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1875
|
+
interface DetailTextOptions {
|
|
1876
|
+
/** Grid width in the 12-column layout. */
|
|
1877
|
+
span?: DetailSpan;
|
|
1878
|
+
/**
|
|
1879
|
+
* Visibility condition for this text block.
|
|
1880
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1881
|
+
*/
|
|
1882
|
+
visible?: string | boolean;
|
|
1883
|
+
/** Typography and alert styling variant ('body', 'heading', 'subheading', 'muted', 'caption', 'callout', 'info', 'warning'). */
|
|
1884
|
+
variant?: "body" | "heading" | "subheading" | "muted" | "caption" | "callout" | "info" | "warning";
|
|
1885
|
+
/** Custom CSS or Tailwind classes applied to the text wrapper. */
|
|
1886
|
+
className?: string;
|
|
1597
1887
|
}
|
|
1598
1888
|
/**
|
|
1599
|
-
*
|
|
1889
|
+
* Static text, heading, callout, or notice block in a Detail View.
|
|
1600
1890
|
*/
|
|
1601
|
-
interface
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1891
|
+
interface DetailText {
|
|
1892
|
+
/** Identifies this item as a text block. */
|
|
1893
|
+
type: "text";
|
|
1894
|
+
/** Text or markdown content. */
|
|
1895
|
+
content: string;
|
|
1896
|
+
/** Text options. */
|
|
1897
|
+
options?: DetailTextOptions;
|
|
1606
1898
|
}
|
|
1607
1899
|
/**
|
|
1608
|
-
*
|
|
1900
|
+
* Configuration options for a custom React component slot.
|
|
1609
1901
|
*/
|
|
1610
|
-
interface
|
|
1611
|
-
/**
|
|
1612
|
-
|
|
1613
|
-
/** Human-readable title displayed in the sidebar navigation and view header. */
|
|
1614
|
-
label: string;
|
|
1615
|
-
/** Lucide icon name (e.g. `"UserCheck"`, `"Calendar"`, `"Shirt"`, `"TableProperties"`). */
|
|
1616
|
-
icon?: string;
|
|
1617
|
-
/** Base query filter applied before user toolbar filters (e.g. `{ attending: { equals: true } }` or JEXL string). */
|
|
1618
|
-
filter?: Record<string, any> | string;
|
|
1619
|
-
/** Field names to show in this view, in order. If omitted, Dyrected infers default display fields. */
|
|
1620
|
-
columns?: string[];
|
|
1621
|
-
/** Default sorting rule when entering the view. */
|
|
1622
|
-
sort?: {
|
|
1623
|
-
field: string;
|
|
1624
|
-
direction: 'asc' | 'desc';
|
|
1625
|
-
};
|
|
1626
|
-
/** Custom workflow actions available in this view. */
|
|
1627
|
-
actions?: ActionConfig[];
|
|
1628
|
-
/** Toggles built-in operations (view/edit/duplicate/delete/export). */
|
|
1629
|
-
features?: ViewActionFeatures;
|
|
1902
|
+
interface DetailCustomOptions<TDoc = any> {
|
|
1903
|
+
/** Grid span in the 12-column layout. */
|
|
1904
|
+
span?: DetailSpan;
|
|
1630
1905
|
/**
|
|
1631
|
-
*
|
|
1632
|
-
*
|
|
1906
|
+
* Visibility condition for this custom component.
|
|
1907
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1633
1908
|
*/
|
|
1634
|
-
|
|
1635
|
-
/**
|
|
1636
|
-
|
|
1637
|
-
/**
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
interface DefineTableViewOptions extends DefineViewBaseOptions {
|
|
1644
|
-
layout?: 'table' | 'spreadsheet';
|
|
1645
|
-
/** Field name used to organize records into kanban columns or collapsible grouped sections in table, cards, and spreadsheet. */
|
|
1646
|
-
groupBy?: string;
|
|
1647
|
-
}
|
|
1648
|
-
/** Kanban view — requires `groupBy` to organize into columns. */
|
|
1649
|
-
interface DefineKanbanViewOptions extends DefineViewBaseOptions {
|
|
1650
|
-
layout: 'kanban';
|
|
1651
|
-
/** Field name to organize records into kanban columns. */
|
|
1652
|
-
groupBy: string;
|
|
1653
|
-
}
|
|
1654
|
-
/** Calendar view — requires `dateField` to place records on the calendar. */
|
|
1655
|
-
interface DefineCalendarViewOptions extends DefineViewBaseOptions {
|
|
1656
|
-
layout: 'calendar';
|
|
1657
|
-
/** Field name containing the ISO date string for calendar placement. */
|
|
1658
|
-
dateField: string;
|
|
1659
|
-
}
|
|
1660
|
-
/** Gantt view — requires both `startDateField` and `endDateField`. */
|
|
1661
|
-
interface DefineGanttViewOptions extends DefineViewBaseOptions {
|
|
1662
|
-
layout: 'gantt';
|
|
1663
|
-
/** Field name for the start date in the gantt timeline. */
|
|
1664
|
-
startDateField: string;
|
|
1665
|
-
/** Field name for the end date in the gantt timeline. */
|
|
1666
|
-
endDateField: string;
|
|
1909
|
+
visible?: string | boolean;
|
|
1910
|
+
/** Static or initial props passed into the custom component. */
|
|
1911
|
+
props?: Record<string, any>;
|
|
1912
|
+
/** Inline render function receiving `{ doc, user }` (Self-hosted React runtimes). */
|
|
1913
|
+
render?: (context: {
|
|
1914
|
+
doc: TDoc;
|
|
1915
|
+
user?: any;
|
|
1916
|
+
[key: string]: any;
|
|
1917
|
+
}) => any;
|
|
1667
1918
|
}
|
|
1668
|
-
/**
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1919
|
+
/**
|
|
1920
|
+
* Custom React component slot mounted in a Detail View.
|
|
1921
|
+
*/
|
|
1922
|
+
interface DetailCustom<TDoc = any> {
|
|
1923
|
+
/** Identifies this item as a custom component. */
|
|
1924
|
+
type: "custom";
|
|
1925
|
+
/** Registered custom component name. */
|
|
1926
|
+
name: string;
|
|
1927
|
+
/** Custom component options. */
|
|
1928
|
+
options?: DetailCustomOptions<TDoc>;
|
|
1673
1929
|
}
|
|
1674
1930
|
/**
|
|
1675
|
-
*
|
|
1676
|
-
* Use layout-specific overloads to ensure required fields are provided.
|
|
1677
|
-
*
|
|
1678
|
-
* @example
|
|
1679
|
-
* ```ts
|
|
1680
|
-
* export const attendingGuests = defineView({
|
|
1681
|
-
* slug: "attending-guests",
|
|
1682
|
-
* label: "Attending Guests",
|
|
1683
|
-
* icon: "UserCheck",
|
|
1684
|
-
* layout: "table",
|
|
1685
|
-
* groupBy: "tableNumber",
|
|
1686
|
-
* filter: { attending: { equals: true } },
|
|
1687
|
-
* columns: ["name", "email", "guestCount", "checkedIn"],
|
|
1688
|
-
* sort: { field: "name", direction: "asc" },
|
|
1689
|
-
* });
|
|
1690
|
-
* ```
|
|
1931
|
+
* Configuration options for rendering an action button in a Detail View.
|
|
1691
1932
|
*/
|
|
1692
|
-
|
|
1933
|
+
interface DetailActionOptions {
|
|
1934
|
+
/** Grid column span across the 12-column grid. */
|
|
1935
|
+
span?: DetailSpan;
|
|
1936
|
+
/** Button visual style. Defaults to `'outline'`. */
|
|
1937
|
+
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive";
|
|
1938
|
+
/** Button size. Defaults to `'sm'`. */
|
|
1939
|
+
size?: "sm" | "default";
|
|
1940
|
+
/** Overrides the action's own `label` for this placement. */
|
|
1941
|
+
label?: string;
|
|
1942
|
+
/**
|
|
1943
|
+
* Visibility condition for this action item.
|
|
1944
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1945
|
+
*/
|
|
1946
|
+
visible?: string | boolean;
|
|
1947
|
+
}
|
|
1693
1948
|
/**
|
|
1694
|
-
*
|
|
1695
|
-
*
|
|
1696
|
-
*
|
|
1697
|
-
*
|
|
1698
|
-
*
|
|
1699
|
-
*
|
|
1700
|
-
* label: "Check In",
|
|
1701
|
-
* icon: "UserCheck",
|
|
1702
|
-
* type: "row",
|
|
1703
|
-
* confirm: "Confirm guest check-in at the door?",
|
|
1704
|
-
* mutation: { checkedIn: true, checkedInAt: "now()" },
|
|
1705
|
-
* });
|
|
1706
|
-
* ```
|
|
1949
|
+
* Renders a button for a named action from `collection.actions` at this
|
|
1950
|
+
* position in a Detail View. The same action (and its confirm dialog, modal
|
|
1951
|
+
* fields, and execution) can also render automatically in the Detail View's
|
|
1952
|
+
* header toolbar when the action's `type` is `'header'` — placing it here
|
|
1953
|
+
* too does not duplicate that config, it just adds another entry point to
|
|
1954
|
+
* the same action.
|
|
1707
1955
|
*/
|
|
1708
|
-
interface
|
|
1709
|
-
/**
|
|
1956
|
+
interface DetailAction {
|
|
1957
|
+
/** Identifies this item as an action button. */
|
|
1958
|
+
type: "action";
|
|
1959
|
+
/** Name of the action, matching an entry in `collection.actions`. */
|
|
1710
1960
|
name: string;
|
|
1711
|
-
/**
|
|
1712
|
-
|
|
1713
|
-
/** Lucide icon name for the button (e.g. `"UserCheck"`, `"CheckCircle"`). */
|
|
1714
|
-
icon?: string;
|
|
1715
|
-
/** Action placement: `'row'` (per-row), `'bulk'` (multi-row selection bar), or `'header'` (view header). Defaults to `'row'`. */
|
|
1716
|
-
type?: ActionType;
|
|
1717
|
-
/** Optional confirmation prompt shown before executing (e.g. `"Confirm guest check-in at the door?"`). */
|
|
1718
|
-
confirm?: string;
|
|
1719
|
-
/** Optional interactive modal form fields prompting the user for input before executing. */
|
|
1720
|
-
fields?: Field[];
|
|
1721
|
-
/** Declarative database mutation applied to targeted documents (e.g. `{ checkedIn: true, checkedInAt: "now()" }`). */
|
|
1722
|
-
mutation?: Partial<TDoc> | Record<string, unknown>;
|
|
1723
|
-
/** Self-hosted server handler function executed when the action is triggered. */
|
|
1724
|
-
handler?: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
1725
|
-
/** Role-based access rules controlling who can trigger this action. */
|
|
1726
|
-
access?: AccessConfig;
|
|
1961
|
+
/** Display and visibility options for this placement. */
|
|
1962
|
+
options?: DetailActionOptions;
|
|
1727
1963
|
}
|
|
1728
1964
|
/**
|
|
1729
|
-
*
|
|
1730
|
-
* Layout-specific overloads enforce required fields for each view type.
|
|
1731
|
-
*
|
|
1732
|
-
* @example
|
|
1733
|
-
* ```ts
|
|
1734
|
-
* // Table view (no special requirements)
|
|
1735
|
-
* export const allGuests = defineView({
|
|
1736
|
-
* slug: "all-guests",
|
|
1737
|
-
* label: "All Guests",
|
|
1738
|
-
* layout: "table", // or omit for default
|
|
1739
|
-
* });
|
|
1740
|
-
*
|
|
1741
|
-
* // Kanban view (requires groupBy)
|
|
1742
|
-
* export const guestsByTable = defineView({
|
|
1743
|
-
* slug: "by-table",
|
|
1744
|
-
* label: "Guests by Table",
|
|
1745
|
-
* layout: "kanban",
|
|
1746
|
-
* groupBy: "tableNumber", // required!
|
|
1747
|
-
* });
|
|
1748
|
-
*
|
|
1749
|
-
* // Calendar view (requires dateField)
|
|
1750
|
-
* export const eventCalendar = defineView({
|
|
1751
|
-
* slug: "event-calendar",
|
|
1752
|
-
* label: "Event Calendar",
|
|
1753
|
-
* layout: "calendar",
|
|
1754
|
-
* dateField: "eventDate", // required!
|
|
1755
|
-
* });
|
|
1756
|
-
*
|
|
1757
|
-
* // Gantt view (requires startDateField and endDateField)
|
|
1758
|
-
* export const projectTimeline = defineView({
|
|
1759
|
-
* slug: "timeline",
|
|
1760
|
-
* label: "Project Timeline",
|
|
1761
|
-
* layout: "gantt",
|
|
1762
|
-
* startDateField: "startDate", // required!
|
|
1763
|
-
* endDateField: "endDate", // required!
|
|
1764
|
-
* });
|
|
1765
|
-
* ```
|
|
1965
|
+
* Union of all valid item types in a Detail View schema.
|
|
1766
1966
|
*/
|
|
1767
|
-
|
|
1768
|
-
declare function defineView(config: DefineKanbanViewOptions): DefineKanbanViewOptions;
|
|
1769
|
-
declare function defineView(config: DefineCalendarViewOptions): DefineCalendarViewOptions;
|
|
1770
|
-
declare function defineView(config: DefineGanttViewOptions): DefineGanttViewOptions;
|
|
1771
|
-
declare function defineView(config: DefineCardsViewOptions): DefineCardsViewOptions;
|
|
1772
|
-
declare function defineView<const T extends DefineViewOptions>(config: T): T;
|
|
1773
|
-
/** Convenience helper for table views. Enforces no view-specific required fields. */
|
|
1774
|
-
declare function defineTableView(config: DefineTableViewOptions): DefineTableViewOptions;
|
|
1775
|
-
/** Convenience helper for kanban views. Enforces `groupBy` is provided. */
|
|
1776
|
-
declare function defineKanbanView(config: DefineKanbanViewOptions): DefineKanbanViewOptions;
|
|
1777
|
-
/** Convenience helper for calendar views. Enforces `dateField` is provided. */
|
|
1778
|
-
declare function defineCalendarView(config: DefineCalendarViewOptions): DefineCalendarViewOptions;
|
|
1779
|
-
/** Convenience helper for gantt views. Enforces `startDateField` and `endDateField` are provided. */
|
|
1780
|
-
declare function defineGanttView(config: DefineGanttViewOptions): DefineGanttViewOptions;
|
|
1781
|
-
/** Convenience helper for cards views. Optional `groupBy`. */
|
|
1782
|
-
declare function defineCardsView(config: DefineCardsViewOptions): DefineCardsViewOptions;
|
|
1967
|
+
type DetailItem<TDoc = any> = DetailSection | DetailTabs | DetailGrid | DetailField | DetailRepeat | DetailComputed<TDoc> | DetailDivider | DetailText | DetailCustom<TDoc> | DetailAction | string;
|
|
1783
1968
|
/**
|
|
1784
|
-
*
|
|
1785
|
-
*
|
|
1786
|
-
* @example
|
|
1787
|
-
* ```ts
|
|
1788
|
-
* export const markPaidAction = defineAction({
|
|
1789
|
-
* name: "markPaid",
|
|
1790
|
-
* label: "Mark Paid",
|
|
1791
|
-
* icon: "DollarSign",
|
|
1792
|
-
* type: "bulk",
|
|
1793
|
-
* confirm: "Mark selected orders as paid?",
|
|
1794
|
-
* mutation: { status: "paid" },
|
|
1795
|
-
* });
|
|
1796
|
-
* ```
|
|
1969
|
+
* Detail View layout schema definition for a collection or global.
|
|
1797
1970
|
*/
|
|
1798
|
-
|
|
1971
|
+
type DetailSchema<TDoc = any> = DetailItem<TDoc>[];
|
|
1799
1972
|
|
|
1800
1973
|
/**
|
|
1801
1974
|
* Configures account lockout behavior for an auth-enabled collection.
|
|
@@ -2117,6 +2290,13 @@ interface CollectionConfig<TDoc extends object = Record<string, unknown>> {
|
|
|
2117
2290
|
* See `CollectionAfterChangeHook` for await-vs-fire-and-forget guidance.
|
|
2118
2291
|
*/
|
|
2119
2292
|
afterChange?: CollectionAfterChangeHook<TDoc>[];
|
|
2293
|
+
/**
|
|
2294
|
+
* Runs inside the database transaction that persists a create or update,
|
|
2295
|
+
* before it commits. `tx` is writable, so secondary writes commit or roll
|
|
2296
|
+
* back atomically with the document. Throw to abort the whole operation.
|
|
2297
|
+
* Requires a transactional database adapter.
|
|
2298
|
+
*/
|
|
2299
|
+
beforeCommit?: CollectionBeforeCommitHook<TDoc>[];
|
|
2120
2300
|
/** Runs before a document is deleted. Throw to cancel the deletion. */
|
|
2121
2301
|
beforeDelete?: CollectionBeforeDeleteHook<TDoc>[];
|
|
2122
2302
|
/**
|
|
@@ -2162,6 +2342,10 @@ interface CollectionConfig<TDoc extends object = Record<string, unknown>> {
|
|
|
2162
2342
|
* Collections with the same `group` are visually grouped together.
|
|
2163
2343
|
*/
|
|
2164
2344
|
group?: string;
|
|
2345
|
+
/**
|
|
2346
|
+
* Numeric sort order within navigation or sidebar group (lower numbers appear first).
|
|
2347
|
+
*/
|
|
2348
|
+
order?: number;
|
|
2165
2349
|
/**
|
|
2166
2350
|
* Slug of the view to render by default when navigating to `/collections/:slug`.
|
|
2167
2351
|
* If not specified, defaults to the view with `default: true` or the all-records table view.
|
|
@@ -2425,6 +2609,10 @@ interface GlobalConfig<TDoc extends object = Record<string, unknown>> {
|
|
|
2425
2609
|
icon?: AdminIconName;
|
|
2426
2610
|
/** Groups this global under a named section in the Admin sidebar. */
|
|
2427
2611
|
group?: string;
|
|
2612
|
+
/**
|
|
2613
|
+
* Numeric sort order within navigation or sidebar group (lower numbers appear first).
|
|
2614
|
+
*/
|
|
2615
|
+
order?: number;
|
|
2428
2616
|
/** If `true`, this global is not shown in the Admin UI sidebar. */
|
|
2429
2617
|
hidden?: boolean;
|
|
2430
2618
|
};
|
|
@@ -2476,10 +2664,14 @@ interface DatabaseAdapter {
|
|
|
2476
2664
|
/** Row-level locking strategy (e.g. SELECT ... FOR UPDATE in transactions). */
|
|
2477
2665
|
lock?: "for-update";
|
|
2478
2666
|
}): Promise<PaginatedResult>;
|
|
2479
|
-
/**
|
|
2667
|
+
/**
|
|
2668
|
+
* Find a single document by its ID or by a `where` filter (the first match
|
|
2669
|
+
* is returned). Returns `null` if not found. Provide `id` or `where`.
|
|
2670
|
+
*/
|
|
2480
2671
|
findOne(args: {
|
|
2481
2672
|
collection: string;
|
|
2482
|
-
id
|
|
2673
|
+
id?: string;
|
|
2674
|
+
where?: Record<string, unknown>;
|
|
2483
2675
|
/** Row-level locking strategy (e.g. SELECT ... FOR UPDATE in transactions). */
|
|
2484
2676
|
lock?: "for-update";
|
|
2485
2677
|
}): Promise<BaseDocument | null>;
|
|
@@ -2655,7 +2847,7 @@ interface ImageService {
|
|
|
2655
2847
|
}>;
|
|
2656
2848
|
}
|
|
2657
2849
|
|
|
2658
|
-
type FieldType = "text" | "textarea" | "richText" | "number" | "boolean" | "date" | "datetime" | "time" | "select" | "multiSelect" | "radio" | "relationship" | "array" | "object" | "json" | "blocks" | "image" | "email" | "url" | "icon" | "join" | "row";
|
|
2850
|
+
type FieldType = "text" | "textarea" | "richText" | "number" | "money" | "boolean" | "date" | "datetime" | "time" | "select" | "multiSelect" | "radio" | "relationship" | "array" | "object" | "json" | "blocks" | "image" | "email" | "url" | "icon" | "join" | "row";
|
|
2659
2851
|
interface DynamicOptionsResolverArgs {
|
|
2660
2852
|
/** Database adapter available to server-side option resolvers. */
|
|
2661
2853
|
db?: DatabaseAdapter;
|
|
@@ -2737,6 +2929,12 @@ interface FieldBase {
|
|
|
2737
2929
|
required?: boolean;
|
|
2738
2930
|
/** Whether values for this field must be unique across the collection. */
|
|
2739
2931
|
unique?: boolean;
|
|
2932
|
+
/**
|
|
2933
|
+
* Whether the value can only be set when the document is created. Any update
|
|
2934
|
+
* that tries to change it is rejected with a validation error. Re-sending the
|
|
2935
|
+
* unchanged value is allowed.
|
|
2936
|
+
*/
|
|
2937
|
+
immutable?: boolean;
|
|
2740
2938
|
/** Default value: literal value or function computed from context. */
|
|
2741
2939
|
defaultValue?: unknown;
|
|
2742
2940
|
/** Static or dynamic option source for supported selection fields. */
|
|
@@ -3197,6 +3395,13 @@ type NumberFieldAdmin = NumberLimitFieldAdmin & {
|
|
|
3197
3395
|
/** How the value is displayed in read-only Admin surfaces (list cells, read-only inputs). Does not affect storage or editing. */
|
|
3198
3396
|
format?: NumberFormat;
|
|
3199
3397
|
};
|
|
3398
|
+
type MoneyFieldAdmin = {
|
|
3399
|
+
/**
|
|
3400
|
+
* Show the stored minor units as a major-unit amount (for example `5250000`
|
|
3401
|
+
* as `52,500.00`) in the Admin. Defaults to `true`. Does not affect storage or the API.
|
|
3402
|
+
*/
|
|
3403
|
+
displayMinorAsMajor?: boolean;
|
|
3404
|
+
};
|
|
3200
3405
|
type DateFieldAdmin = {
|
|
3201
3406
|
/** How the value is displayed in read-only Admin surfaces (list cells, read-only inputs). Does not affect storage or editing. */
|
|
3202
3407
|
format?: DateFormat;
|
|
@@ -3274,6 +3479,22 @@ type SelectField = TypedField<"select", string, SelectFieldAdmin>;
|
|
|
3274
3479
|
type RadioField = TypedField<"radio", string, RadioFieldAdmin>;
|
|
3275
3480
|
/** A numeric value. Optional advisory `min`/`max` guide editors without enforcing server-side validation. */
|
|
3276
3481
|
type NumberField = TypedField<"number", number, NumberFieldAdmin> & NumberLimitFieldConfig;
|
|
3482
|
+
/** Currency settings for a `money` field. */
|
|
3483
|
+
interface MoneyFieldConfig {
|
|
3484
|
+
/** Fixed ISO 4217 currency code for every value, for example `"NGN"`. */
|
|
3485
|
+
currency?: string;
|
|
3486
|
+
/** Name of a sibling field holding the ISO 4217 currency code for each document. Overrides `currency`. */
|
|
3487
|
+
currencyField?: string;
|
|
3488
|
+
/** Digits after the decimal point in the major unit. Defaults to `2` (kobo, cents). */
|
|
3489
|
+
decimals?: number;
|
|
3490
|
+
}
|
|
3491
|
+
/**
|
|
3492
|
+
* A monetary amount stored as an integer count of minor units (kobo, cents),
|
|
3493
|
+
* so arithmetic never suffers floating-point drift. The API reads and writes
|
|
3494
|
+
* the integer; only the Admin formats it as a major-unit amount. Values must be
|
|
3495
|
+
* safe integers, and integer strings are accepted and converted.
|
|
3496
|
+
*/
|
|
3497
|
+
type MoneyField = TypedField<"money", number, MoneyFieldAdmin> & MoneyFieldConfig;
|
|
3277
3498
|
/** A `true`/`false` value, shown to editors as a checkbox or switch. */
|
|
3278
3499
|
type BooleanField = TypedField<"boolean", boolean, BooleanFieldAdmin>;
|
|
3279
3500
|
/**
|
|
@@ -3343,7 +3564,7 @@ type JoinField = TypedField<"join", unknown, JoinFieldAdmin> & {
|
|
|
3343
3564
|
};
|
|
3344
3565
|
/** A layout-only container that arranges its child `fields` horizontally in the admin UI. Stores no value of its own. */
|
|
3345
3566
|
type RowField = TypedField<"row", unknown>;
|
|
3346
|
-
type Field = TextField | TextareaField | EmailField | UrlField | IconField | DateField | DateTimeField | TimeField | SelectField | RadioField | NumberField | BooleanField | MultiSelectField | RelationshipField | ImageField | RichTextField | JsonField | ObjectField | ArrayField | BlocksField | JoinField | RowField;
|
|
3567
|
+
type Field = TextField | TextareaField | EmailField | UrlField | IconField | DateField | DateTimeField | TimeField | SelectField | RadioField | NumberField | MoneyField | BooleanField | MultiSelectField | RelationshipField | ImageField | RichTextField | JsonField | ObjectField | ArrayField | BlocksField | JoinField | RowField;
|
|
3347
3568
|
interface UploadConfig {
|
|
3348
3569
|
/** Allowed MIME types for uploaded files. */
|
|
3349
3570
|
allowedMimeTypes?: string[];
|
|
@@ -3504,6 +3725,56 @@ interface AdminAuthConfig {
|
|
|
3504
3725
|
resolveAccess?: (args: AdminAuthResolveAccessArgs) => Promise<AdminAuthAccessResolution> | AdminAuthAccessResolution;
|
|
3505
3726
|
}
|
|
3506
3727
|
|
|
3728
|
+
/** Minimal structural logger handed to task handlers (a pino logger satisfies it). */
|
|
3729
|
+
interface TaskLogger {
|
|
3730
|
+
info(obj: unknown, msg?: string): void;
|
|
3731
|
+
warn(obj: unknown, msg?: string): void;
|
|
3732
|
+
error(obj: unknown, msg?: string): void;
|
|
3733
|
+
}
|
|
3734
|
+
interface TaskContext {
|
|
3735
|
+
/** The database adapter. */
|
|
3736
|
+
db: DatabaseAdapter;
|
|
3737
|
+
/** Logger scoped to this task. */
|
|
3738
|
+
logger: TaskLogger;
|
|
3739
|
+
/**
|
|
3740
|
+
* Aborted when the run exceeds `lockTimeout`. Pass it to `fetch` or check it
|
|
3741
|
+
* in long loops so an overrunning task stops touching data after its lock lapses.
|
|
3742
|
+
*/
|
|
3743
|
+
signal: AbortSignal;
|
|
3744
|
+
/** The cron slot this run was started for, or `undefined` for a manual run. */
|
|
3745
|
+
scheduledFor?: Date;
|
|
3746
|
+
}
|
|
3747
|
+
/**
|
|
3748
|
+
* A named background job. Define it with `defineTask` and list it under
|
|
3749
|
+
* `tasks` in your config, then run it with `createTaskRunner`.
|
|
3750
|
+
*/
|
|
3751
|
+
interface TaskConfig {
|
|
3752
|
+
/** Unique, stable name, for example `wallet:ledger-drift`. Also the lock key. */
|
|
3753
|
+
name: string;
|
|
3754
|
+
/**
|
|
3755
|
+
* Standard five-field cron expression (`minute hour day-of-month month day-of-week`),
|
|
3756
|
+
* evaluated in UTC. Omit for a task that only runs when you call `runTask`.
|
|
3757
|
+
*/
|
|
3758
|
+
cron?: string;
|
|
3759
|
+
/**
|
|
3760
|
+
* Seconds a run may hold its lock before another instance may take over,
|
|
3761
|
+
* and before its `signal` is aborted. Defaults to 300.
|
|
3762
|
+
*/
|
|
3763
|
+
lockTimeout?: number;
|
|
3764
|
+
/** The work to do. Throw to record the run as failed. */
|
|
3765
|
+
run: (context: TaskContext) => void | Promise<void>;
|
|
3766
|
+
}
|
|
3767
|
+
type TaskRunStatus = "completed" | "failed" | "skipped";
|
|
3768
|
+
interface TaskRunResult {
|
|
3769
|
+
name: string;
|
|
3770
|
+
status: TaskRunStatus;
|
|
3771
|
+
/** Why a run was skipped. */
|
|
3772
|
+
reason?: "locked" | "not-due";
|
|
3773
|
+
/** Failure message when `status` is `"failed"`. */
|
|
3774
|
+
error?: string;
|
|
3775
|
+
durationMs: number;
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3507
3778
|
type DyrectedLoggerConfig = {
|
|
3508
3779
|
options: LoggerOptions;
|
|
3509
3780
|
destination?: DestinationStream;
|
|
@@ -3742,6 +4013,11 @@ interface DyrectedConfig<TUser extends AuthenticatedUser = AuthenticatedUser> {
|
|
|
3742
4013
|
redis?: {
|
|
3743
4014
|
url: string;
|
|
3744
4015
|
};
|
|
4016
|
+
/**
|
|
4017
|
+
* Background tasks. Define each with `defineTask`, then run them with
|
|
4018
|
+
* `createTaskRunner(config)`.
|
|
4019
|
+
*/
|
|
4020
|
+
tasks?: TaskConfig[];
|
|
3745
4021
|
/** Durable lifecycle-event delivery configuration. */
|
|
3746
4022
|
events?: {
|
|
3747
4023
|
handlers: LifecycleEventHandler[];
|
|
@@ -3954,4 +4230,4 @@ interface DyrectedContext {
|
|
|
3954
4230
|
*/
|
|
3955
4231
|
declare function createDyrectedApp(rawConfig: DyrectedConfig | any): Promise<Hono<DyrectedContext, hono_types.BlankSchema, "/">>;
|
|
3956
4232
|
|
|
3957
|
-
export { type
|
|
4233
|
+
export { type BooleanField as $, type AdminAuthConfig as A, type Block as B, type CollectionConfig as C, type DyrectedConfig as D, type DetailTab as E, type Field as F, type GlobalConfig as G, type HookRequestContext as H, type DetailTabsOptions as I, type DetailTabs as J, type DetailTextOptions as K, type LifecycleEventName as L, type DetailText as M, type DetailSchema as N, type DyrectedContext as O, type PublicAdminAuthConfig as P, type AIConfig as Q, type AIPIIConfig as R, type IdStrategy as S, type TaskRunResult as T, type CompiledNavTree as U, type CompiledNavItem as V, type WorkflowConfig as W, type UserNavigationPreferences as X, type DefineWorkspaceOptions as Y, type ArrayField as Z, type FieldType as _, type DeclarativeHookExpression as a, type AggregateCastType as a$, type AuthConfig as a0, type AccessPolicyResolver as a1, type DateField as a2, type DateTimeField as a3, type EmailField as a4, type IconField as a5, type ImageField as a6, type JoinField as a7, type JsonField as a8, type MoneyField as a9, AI_AUDIT_COLLECTION as aA, AI_CHUNKS_COLLECTION as aB, AI_MESSAGES_COLLECTION as aC, AI_THREADS_COLLECTION as aD, type AccessConfig as aE, type AccessFunction as aF, type AccessFunctionArgs as aG, type AccessResult as aH, type AccessRule as aI, type ActionConfig as aJ, type ActionConfigBase as aK, type ActionConfigWithHandler as aL, type ActionConfigWithMutation as aM, type ActionContext as aN, type ActionType as aO, type AdminAuthAccessResolution as aP, type AdminAuthClaimMapping as aQ, type AdminAuthMember as aR, type AdminAuthProvider as aS, type AdminAuthProviderMembersConfig as aT, type AdminAuthProvisioningMode as aU, type AdminAuthResolveAccessArgs as aV, type AdminAuthResolvedIdentity as aW, type AdminConfig as aX, type AdminDashboardComponentSlots as aY, type AdminIconName as aZ, type AggregateArgs as a_, type MultiSelectField as aa, type NumberField as ab, type ObjectField as ac, type RadioField as ad, type RelationshipField as ae, type RichTextField as af, type RowField as ag, type SelectField as ah, type TextField as ai, type TextareaField as aj, type TimeField as ak, type UrlField as al, type AIAction as am, type AIActionStatus as an, type AIActionType as ao, type AIAuditActionType as ap, type AIAuditRecord as aq, type AIChunk as ar, type AIMessage as as, type AIPIIPattern as at, type AIRateLimitResult as au, type AIRateLimitStore as av, type AIThread as aw, type AIToolContext as ax, type AIToolDefinition as ay, AI_ACTIONS_COLLECTION as az, type AuthenticatedUser as b, type FieldAdminOnChangeHookArgs as b$, type AggregateCollectionResult as b0, type AggregateInput as b1, type AggregateOperation as b2, type AggregateResult as b3, type BaseAdminAuthProvider as b4, type BaseFieldAdmin as b5, type BlockVariant as b6, type BlocksField as b7, type BooleanFieldAdmin as b8, type BooleanFormat as b9, DEFAULT_USER_NAV_PREFERENCES as bA, type DateFieldAdmin as bB, type DateFormat as bC, type DefaultValueContext as bD, type DefineActionOptions as bE, type DefineCalendarViewOptions as bF, type DefineCardsViewOptions as bG, type DefineGanttViewOptions as bH, type DefineKanbanViewOptions as bI, type DefineTableViewOptions as bJ, type DefineViewBaseOptions as bK, type DefineViewOptions as bL, type DetailSpan as bM, type DisplayTone as bN, type DisplayVariant as bO, type DistinctCountOperation as bP, type DistinctValuesOperation as bQ, type DynamicOptionItem as bR, type DynamicOptionsConfig as bS, type DynamicOptionsResolver as bT, type DynamicOptionsResolverArgs as bU, type DyrectedAIContext as bV, type DyrectedLoggerConfig as bW, type DyrectedObservabilityConfig as bX, type EmailFieldAdmin as bY, type FieldAdminHooks as bZ, type FieldAdminOnChangeHook as b_, CURRENT_NAV_PREFERENCES_VERSION as ba, type CalendarViewConfig as bb, type CardsViewConfig as bc, type CharacterLimitFieldAdmin as bd, type CharacterLimitFieldConfig as be, type CollectionAfterChangeHook as bf, type CollectionAfterDeleteHook as bg, type CollectionAfterReadHook as bh, type CollectionAfterReadHookEntry as bi, type CollectionAfterTransitionHook as bj, type CollectionBeforeChangeHook as bk, type CollectionBeforeChangeHookEntry as bl, type CollectionBeforeCommitHook as bm, type CollectionBeforeDeleteHook as bn, type CollectionBeforeReadHook as bo, type CollectionBeforeReadHookEntry as bp, type CollectionBeforeTransitionHook as bq, type CollectionIndex as br, type CollectionListComponentSlots as bs, type CollectionRAGConfig as bt, type CollectionSchemaResult as bu, type CollectionSummaryResult as bv, type CollectionViewComponentSlots as bw, type CompiledNavGroup as bx, type CountOperation as by, type CustomAdminAuthProvider as bz, type WorkflowTransition as c, type StorageAdapter as c$, type FieldAdminOptionsHook as c0, type FieldAdminOptionsHookArgs as c1, type FieldAdminOptionsHookResult as c2, type FieldAfterReadHook as c3, type FieldAfterReadHookArgs as c4, type FieldBase as c5, type FieldBeforeChangeHook as c6, type FieldBeforeChangeHookArgs as c7, type FieldHook as c8, type FieldHooks as c9, type MetricColor as cA, type MoneyFieldAdmin as cB, type MoneyFieldConfig as cC, type MultiSelectFieldAdmin as cD, type NamedAccessPolicy as cE, type NavBadgeConfig as cF, type NavGroup as cG, type NumberFieldAdmin as cH, type NumberFormat as cI, type NumberLimitFieldAdmin as cJ, type NumberLimitFieldConfig as cK, type NumericOperation as cL, type NumericUpdateOperator as cM, type OIDCAdminAuthProvider as cN, type OptionFormat as cO, type PaginatedResult as cP, type PinnedNavItemRef as cQ, type PublicAdminAuthProvider as cR, type QueryCollectionResult as cS, type RAGSearchResult as cT, type RadioFieldAdmin as cU, type RateLimitConfig as cV, type ReadonlyDatabaseAdapter as cW, type RichTextFeature as cX, type RichTextFieldConfig as cY, type SelectFieldAdmin as cZ, type SqlWhereResult as c_, type FileData as ca, type GanttViewConfig as cb, type GetDocumentResult as cc, type GlobalAfterChangeHook as cd, type GlobalAfterReadHook as ce, type GlobalAfterReadHookEntry as cf, type GlobalBeforeChangeHook as cg, type GlobalBeforeChangeHookEntry as ch, type GlobalBeforeReadHook as ci, type GlobalBeforeReadHookEntry as cj, type GlobalRAGConfig as ck, type GlobalSchemaResult as cl, type GlobalSummaryResult as cm, type HeadingLevel as cn, type HookFunction as co, type IconFieldAdmin as cp, type ImageService as cq, type ImageTransformOptions as cr, type InferAggregateResult as cs, type JoinFieldAdmin as ct, type JsonFieldAdmin as cu, type JsonFormat as cv, type KanbanViewConfig as cw, LIFECYCLE_EVENT_NAMES as cx, type LifecycleEventHandler as cy, type LinkFormat as cz, type LifecycleEvent as d, renderPrometheusMetrics as d$, type TableViewConfig as d0, type TaskContext as d1, type TaskLogger as d2, type TaskRunStatus as d3, type TextFieldAdmin as d4, type TextFormat as d5, type TextareaFieldAdmin as d6, type TrustProxyConfig as d7, type TypedField as d8, type UploadConfig as d9, defineKanbanView as dA, defineTableView as dB, defineView as dC, defineWorkspace as dD, isAICollection as dE, parseMongoWhere as dF, parseSqlWhere as dG, type CollectionTokenPayload as dH, DEFAULT_SESSION_EXPIRY as dI, type DyrectedObservabilityRuntime as dJ, type RequestBodyCapture as dK, type RequestTraceContext as dL, type ResolvedObservabilityConfig as dM, attachRequestMetrics as dN, bindObservabilityRuntime as dO, buildRequestLogger as dP, captureRequestBody as dQ, createDyrectedApp as dR, createObservabilityRuntime as dS, createRequestSpan as dT, decodeCollectionToken as dU, endRequestSpan as dV, getConfigLogger as dW, getObservabilityRuntime as dX, getRequestLogger as dY, redactBody as dZ, redactHeaders as d_, type UrlFieldAdmin as da, type UrlLinkValue as db, type ViewActionFeatures as dc, type ViewComponentSlots as dd, type ViewConfig as de, type ViewConfigBase as df, type ViewLayout as dg, type ViewMetric as dh, type ViewSubMetric as di, type WhereClause as dj, type WhereOperator as dk, type WhereOperatorName as dl, type WordLimitFieldAdmin as dm, type WordLimitFieldConfig as dn, type WorkflowMetadata as dp, type WorkflowOnTransitionContext as dq, type WorkflowOnTransitionHook as dr, type WorkflowRole as ds, type WorkflowState as dt, type WorkflowTransitionContext as du, coerceBooleanWhere as dv, defineAction as dw, defineCalendarView as dx, defineCardsView as dy, defineGanttView as dz, type DatabaseAdapter as e, resolveObservabilityConfig as e0, resolveSessionTokenExpiry as e1, shouldSampleRequest as e2, signCollectionToken as e3, verifyCollectionToken as e4, type BaseDocument as f, type TaskConfig as g, type DetailActionOptions as h, type DetailAction as i, type DetailComputedOptions as j, type ComputedHandler as k, type DetailComputed as l, type DetailCustomOptions as m, type DetailCustom as n, type DetailDividerOptions as o, type DetailDivider as p, type DisplayFieldOptions as q, type DetailField as r, type DetailItem as s, type DetailGridOptions as t, type DetailGrid as u, type DetailRepeatOptions as v, type DetailRepeat as w, type DetailSectionOptions as x, type DetailSection as y, type DetailTabOptions as z };
|