@dyrected/core 2.15.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{app-Cmp5lFLJ.d.cts → app-CLdT_0se.d.cts} +1342 -1178
- package/dist/{app-Cmp5lFLJ.d.ts → app-CLdT_0se.d.ts} +1342 -1178
- package/dist/index.cjs +758 -1
- package/dist/index.d.cts +133 -3
- package/dist/index.d.ts +133 -3
- package/dist/index.js +739 -1
- package/dist/server.cjs +1052 -24
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1052 -24
- package/package.json +1 -1
|
@@ -446,1356 +446,1458 @@ 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
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
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[];
|
|
709
603
|
}
|
|
710
604
|
/**
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
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/…
|
|
715
613
|
*/
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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
|
+
/**
|
|
628
|
+
* Custom component slots rendered around an operational view's content.
|
|
629
|
+
*/
|
|
630
|
+
type ViewComponentSlots = CollectionViewComponentSlots;
|
|
631
|
+
/**
|
|
632
|
+
* Supported layout engines for operational views in the Dyrected Admin UI:
|
|
633
|
+
* - `'table'`: The workhorse — column sorting, search, faceted filters, and bulk actions.
|
|
634
|
+
* - `'spreadsheet'`: Inline-editable matrix with batch saving (`Save changes` / `Discard`).
|
|
635
|
+
* - `'kanban'`: Interactive card board grouped by status or category with drag-and-drop.
|
|
636
|
+
* - `'calendar'`: Event schedule grid plotting records across month/week/day views by date.
|
|
637
|
+
* - `'gantt'`: Timeline bars plotted across start and end dates.
|
|
638
|
+
* - `'cards'`: Visual image/thumbnail gallery grid.
|
|
639
|
+
*/
|
|
640
|
+
type ViewLayout = 'table' | 'spreadsheet' | 'kanban' | 'calendar' | 'gantt' | 'cards';
|
|
641
|
+
/**
|
|
642
|
+
* Scope and placement for an operational view action:
|
|
643
|
+
* - `'row'`: Renders as an inline action button on each document/row.
|
|
644
|
+
* - `'bulk'`: Appears in the floating bulk action bar when one or more rows are selected.
|
|
645
|
+
* - `'header'`: Renders as a primary action button in the view header.
|
|
646
|
+
*/
|
|
647
|
+
type ActionType = 'row' | 'bulk' | 'header';
|
|
648
|
+
/**
|
|
649
|
+
* Toggles for the built-in document operations an operational view surfaces.
|
|
650
|
+
* All default to enabled (`true`). Set any to `false` to hide that operation.
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```ts
|
|
654
|
+
* features: {
|
|
655
|
+
* delete: false, // Prevent deleting records from this view
|
|
656
|
+
* exportSelected: true, // Enable CSV export for checked rows
|
|
657
|
+
* }
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
interface ViewActionFeatures {
|
|
661
|
+
/** Enables the "View" preview / read-only drawer button. Defaults to `true`. */
|
|
662
|
+
view?: boolean;
|
|
663
|
+
/** Enables the "Edit" document form link. Defaults to `true`. */
|
|
664
|
+
edit?: boolean;
|
|
665
|
+
/** Enables the "Duplicate" record action. Defaults to `true`. */
|
|
666
|
+
duplicate?: boolean;
|
|
667
|
+
/** Enables the "Delete" record action. Defaults to `true`. */
|
|
668
|
+
delete?: boolean;
|
|
669
|
+
/** Enables the "Export selected" CSV action in the bulk action bar. Defaults to `true`. */
|
|
670
|
+
exportSelected?: boolean;
|
|
766
671
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
/**
|
|
789
|
-
|
|
790
|
-
/**
|
|
791
|
-
|
|
792
|
-
/**
|
|
793
|
-
|
|
794
|
-
/**
|
|
795
|
-
|
|
672
|
+
/**
|
|
673
|
+
* Color palette options for metric cards:
|
|
674
|
+
* `'purple' | 'emerald' | 'amber' | 'rose' | 'blue' | 'indigo' | 'cyan' | 'orange'`
|
|
675
|
+
*/
|
|
676
|
+
type MetricColor = 'purple' | 'emerald' | 'amber' | 'rose' | 'blue' | 'indigo' | 'cyan' | 'orange' | string;
|
|
677
|
+
/**
|
|
678
|
+
* A sub-metric breakdown item displayed in the compact footer of a metric card.
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* ```ts
|
|
682
|
+
* {
|
|
683
|
+
* label: "Pending",
|
|
684
|
+
* aggregates: {
|
|
685
|
+
* checkedIn: { count: "*", where: { checkedIn: { equals: true } } },
|
|
686
|
+
* attending: { count: "*", where: { attending: { equals: true } } },
|
|
687
|
+
* },
|
|
688
|
+
* expression: "aggregates.attending - aggregates.checkedIn",
|
|
689
|
+
* }
|
|
690
|
+
* ```
|
|
691
|
+
*/
|
|
692
|
+
interface ViewSubMetric {
|
|
693
|
+
/** Short label for the sub-metric (e.g. "Pending", "Collected"). */
|
|
694
|
+
label: string;
|
|
695
|
+
/** Single database aggregate operation. */
|
|
696
|
+
aggregate?: AggregateOperation;
|
|
697
|
+
/** Map of named aggregate operations referenced in `expression` as `aggregates.key`. */
|
|
698
|
+
aggregates?: Record<string, AggregateOperation>;
|
|
699
|
+
/** JEXL math formula evaluated over `value` for a single aggregate (e.g. `"value * 100"`). */
|
|
700
|
+
transform?: string;
|
|
701
|
+
/** JEXL math formula evaluated over `aggregates` (e.g. `"aggregates.a - aggregates.b"`). */
|
|
702
|
+
expression?: string;
|
|
703
|
+
/** Display formatter: `'currency' | 'number' | 'percent'`. */
|
|
704
|
+
format?: 'currency' | 'number' | 'percent' | string;
|
|
705
|
+
/** 3-letter currency code (e.g. `"USD"`, `"NGN"`, `"EUR"`) used when `format: "currency"`. */
|
|
706
|
+
currency?: string;
|
|
796
707
|
}
|
|
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
708
|
/**
|
|
802
|
-
*
|
|
709
|
+
* Configuration for a KPI summary card rendered at the top of an operational view.
|
|
710
|
+
*
|
|
711
|
+
* All aggregations run directly on the database engine for maximum performance.
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* {
|
|
716
|
+
* label: "Total Revenue",
|
|
717
|
+
* color: "emerald",
|
|
718
|
+
* aggregate: { sum: "amount", cast: "number", where: { status: "paid" } },
|
|
719
|
+
* format: "currency",
|
|
720
|
+
* currency: "USD",
|
|
721
|
+
* }
|
|
722
|
+
* ```
|
|
803
723
|
*/
|
|
804
|
-
|
|
724
|
+
interface ViewMetric {
|
|
725
|
+
/** Title displayed on the metric card header. */
|
|
726
|
+
label: string;
|
|
727
|
+
/** Accent color for the card's visual indicator. */
|
|
728
|
+
color?: MetricColor;
|
|
729
|
+
/** Unit badge shown alongside the numeric value (e.g. `"Guests"`, `"Orders"`, `"Tables"`). */
|
|
730
|
+
unit?: string;
|
|
731
|
+
/** Single database aggregate operation (`count`, `distinctCount`, `sum`, `avg`, `min`, `max`). */
|
|
732
|
+
aggregate?: AggregateOperation;
|
|
733
|
+
/** Map of named aggregate operations referenced in `expression` as `aggregates.key`. */
|
|
734
|
+
aggregates?: Record<string, AggregateOperation>;
|
|
735
|
+
/** JEXL math formula evaluated over `value` for a single aggregate (e.g. `"value * 25000"`). */
|
|
736
|
+
transform?: string;
|
|
737
|
+
/** JEXL math formula evaluated over `aggregates` (e.g. `"(aggregates.paid / aggregates.total) * 100"`). */
|
|
738
|
+
expression?: string;
|
|
739
|
+
/** Display formatter: `'currency' | 'number' | 'percent'`. */
|
|
740
|
+
format?: 'currency' | 'number' | 'percent' | string;
|
|
741
|
+
/** 3-letter currency code (e.g. `"USD"`, `"NGN"`, `"EUR"`) used when `format: "currency"`. */
|
|
742
|
+
currency?: string;
|
|
743
|
+
/** Optional secondary breakdown items shown in the card footer. */
|
|
744
|
+
subMetrics?: ViewSubMetric[];
|
|
745
|
+
}
|
|
805
746
|
/**
|
|
806
|
-
*
|
|
747
|
+
* Base configuration shared by all action types.
|
|
807
748
|
*/
|
|
808
|
-
interface
|
|
809
|
-
/**
|
|
810
|
-
|
|
811
|
-
/**
|
|
812
|
-
|
|
813
|
-
/**
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
|
|
817
|
-
/**
|
|
818
|
-
|
|
819
|
-
/**
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
|
|
823
|
-
/**
|
|
824
|
-
|
|
825
|
-
/** Column header for object keys when display is 'key-value'. */
|
|
826
|
-
keyLabel?: string;
|
|
827
|
-
/** Column header for object values when display is 'key-value'. */
|
|
828
|
-
valueLabel?: string;
|
|
829
|
-
/** Custom placeholder text when the field value is null, undefined, or empty. */
|
|
830
|
-
emptyText?: string;
|
|
831
|
-
/** When true, hides this entire field item if the value is null or empty. */
|
|
832
|
-
hideIfEmpty?: boolean;
|
|
833
|
-
/**
|
|
834
|
-
* When true, allows inline editing of this field in the Detail View
|
|
835
|
-
* via an interactive toggle.
|
|
836
|
-
*/
|
|
837
|
-
editable?: boolean;
|
|
838
|
-
/**
|
|
839
|
-
* Visibility condition for this field item.
|
|
840
|
-
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
841
|
-
* When false or evaluating to falsy, this item is hidden in the Detail View.
|
|
842
|
-
*
|
|
843
|
-
* @example `visible: "doc.status == 'published'"`
|
|
844
|
-
* @example `visible: false`
|
|
845
|
-
*/
|
|
846
|
-
visible?: string | boolean;
|
|
847
|
-
/** Specific aspect ratio constraint for media (e.g., "16/9", "4/3", "1/1", "auto"). */
|
|
848
|
-
aspectRatio?: string;
|
|
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;
|
|
749
|
+
interface ActionConfigBase<TDoc extends Record<string, unknown> = Record<string, unknown>> {
|
|
750
|
+
/** Unique action identifier (e.g. `"checkIn"`, `"markPaid"`). */
|
|
751
|
+
name: string;
|
|
752
|
+
/** Button label displayed in the UI. */
|
|
753
|
+
label: string;
|
|
754
|
+
/** Optional custom label for the modal submit button (defaults to "Run" or "Confirm"). */
|
|
755
|
+
submitLabel?: string;
|
|
756
|
+
/** Lucide icon name for the button (e.g. `"UserCheck"`, `"CheckCircle"`). */
|
|
757
|
+
icon?: string;
|
|
758
|
+
/** Action placement: `'row'` (per-row), `'bulk'` (multi-row selection bar), or `'header'` (view header). Defaults to `'row'`. */
|
|
759
|
+
type?: ActionType;
|
|
760
|
+
/** Optional confirmation prompt shown before executing (e.g. `"Confirm guest check-in at the door?"`). */
|
|
761
|
+
confirm?: string;
|
|
762
|
+
/** Optional interactive modal form fields prompting the user for input before executing. */
|
|
763
|
+
fields?: Field[];
|
|
764
|
+
/** Role-based access rules controlling who can trigger this action. */
|
|
765
|
+
access?: AccessConfig;
|
|
857
766
|
}
|
|
858
767
|
/**
|
|
859
|
-
*
|
|
768
|
+
* An operational workflow action with declarative data mutation.
|
|
860
769
|
*/
|
|
861
|
-
interface
|
|
862
|
-
/**
|
|
863
|
-
|
|
864
|
-
/**
|
|
865
|
-
|
|
866
|
-
/** Display options for this field. */
|
|
867
|
-
options?: DisplayFieldOptions;
|
|
770
|
+
interface ActionConfigWithMutation<TDoc extends Record<string, unknown> = Record<string, unknown>> extends ActionConfigBase<TDoc> {
|
|
771
|
+
/** Declarative database mutation applied to targeted documents (e.g. `{ checkedIn: true, checkedInAt: "now()" }`). */
|
|
772
|
+
mutation: Partial<TDoc> | Record<string, unknown>;
|
|
773
|
+
/** Optional server handler for additional logic. */
|
|
774
|
+
handler?: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
868
775
|
}
|
|
869
776
|
/**
|
|
870
|
-
*
|
|
777
|
+
* An operational workflow action with server handler.
|
|
871
778
|
*/
|
|
872
|
-
interface
|
|
873
|
-
/**
|
|
874
|
-
|
|
875
|
-
/**
|
|
876
|
-
|
|
877
|
-
/** Color palette name or hex code for the section badge. */
|
|
878
|
-
badgeColor?: string;
|
|
879
|
-
/** Subtitle description displayed beneath the section title. */
|
|
880
|
-
description?: string;
|
|
881
|
-
/** Grid width of the section on the main 12-column layout. */
|
|
882
|
-
span?: DetailSpan;
|
|
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;
|
|
779
|
+
interface ActionConfigWithHandler<TDoc extends Record<string, unknown> = Record<string, unknown>> extends ActionConfigBase<TDoc> {
|
|
780
|
+
/** Self-hosted server handler function executed when the action is triggered (required when mutation is not provided). */
|
|
781
|
+
handler: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
782
|
+
/** Optional declarative mutation. */
|
|
783
|
+
mutation?: Partial<TDoc> | Record<string, unknown>;
|
|
896
784
|
}
|
|
897
785
|
/**
|
|
898
|
-
*
|
|
786
|
+
* An operational workflow action that can mutate data or trigger server logic.
|
|
787
|
+
* Requires either `mutation` or `handler` (or both).
|
|
899
788
|
*/
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
/**
|
|
906
|
-
|
|
907
|
-
/**
|
|
908
|
-
|
|
789
|
+
type ActionConfig<TDoc extends Record<string, unknown> = Record<string, unknown>> = ActionConfigWithMutation<TDoc> | ActionConfigWithHandler<TDoc>;
|
|
790
|
+
/**
|
|
791
|
+
* Context passed to an action's server handler function.
|
|
792
|
+
*/
|
|
793
|
+
interface ActionContext<TDoc extends Record<string, unknown> = Record<string, unknown>> {
|
|
794
|
+
/** The target document (for row actions), or null for header actions. */
|
|
795
|
+
doc: TDoc | null;
|
|
796
|
+
/** All targeted documents (for bulk actions). Empty array for header actions. */
|
|
797
|
+
docs: TDoc[];
|
|
798
|
+
/** The authenticated acting user, if available. */
|
|
799
|
+
user: Record<string, unknown> | null;
|
|
800
|
+
/** User inputs submitted via the action's modal form fields. */
|
|
801
|
+
input: Record<string, unknown>;
|
|
802
|
+
/** The collection configuration object. */
|
|
803
|
+
collection: Record<string, unknown>;
|
|
909
804
|
}
|
|
910
805
|
/**
|
|
911
|
-
*
|
|
806
|
+
* Role-based access control rules for a view or action.
|
|
912
807
|
*/
|
|
913
|
-
interface
|
|
914
|
-
|
|
808
|
+
interface AccessConfig {
|
|
809
|
+
read?: AccessRule<any>;
|
|
810
|
+
create?: AccessRule<any>;
|
|
811
|
+
update?: AccessRule<any>;
|
|
812
|
+
delete?: AccessRule<any>;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Base options shared by all operational view configurations.
|
|
816
|
+
*/
|
|
817
|
+
interface ViewConfigBase {
|
|
818
|
+
/** Stable URL slug for the view (`/collections/:slug/views/:viewSlug` or `/:workspaceSlug/:viewSlug`). */
|
|
819
|
+
slug: string;
|
|
820
|
+
/** Human-readable title displayed in the sidebar navigation and view header. */
|
|
821
|
+
label: string;
|
|
822
|
+
/** Lucide icon name (e.g. `"UserCheck"`, `"Calendar"`, `"Shirt"`, `"TableProperties"`). */
|
|
915
823
|
icon?: string;
|
|
916
|
-
/**
|
|
917
|
-
|
|
918
|
-
/**
|
|
919
|
-
|
|
824
|
+
/** Optional target collection slug for views defined inside standalone operational workspaces. */
|
|
825
|
+
collection?: string;
|
|
826
|
+
/** Base query filter applied before user toolbar filters (e.g. `{ attending: { equals: true } }` or JEXL string). */
|
|
827
|
+
filter?: WhereClause | Record<string, any> | string;
|
|
828
|
+
/** Field names to show in this view, in order. If omitted, Dyrected infers default display fields. */
|
|
829
|
+
columns?: string[];
|
|
830
|
+
/** Default sorting rule when entering the view. */
|
|
831
|
+
sort?: {
|
|
832
|
+
field: string;
|
|
833
|
+
direction: 'asc' | 'desc';
|
|
834
|
+
};
|
|
835
|
+
/** Custom workflow actions available in this view. */
|
|
836
|
+
actions?: ActionConfig[];
|
|
837
|
+
/** Toggles built-in operations (view/edit/duplicate/delete/export). */
|
|
838
|
+
features?: ViewActionFeatures;
|
|
920
839
|
/**
|
|
921
|
-
*
|
|
922
|
-
*
|
|
840
|
+
* Explicit display order for action buttons — mixing custom action names and built-in names
|
|
841
|
+
* (`"view"`, `"edit"`, `"duplicate"`, `"delete"`). Unlisted actions append in default order.
|
|
923
842
|
*/
|
|
924
|
-
|
|
843
|
+
actionOrder?: string[];
|
|
844
|
+
/** KPI summary cards rendered in the hero row above the view. */
|
|
845
|
+
metrics?: ViewMetric[];
|
|
846
|
+
/** Optional real-time counter badge or status indicator displayed on this view in navigation and tabs. */
|
|
847
|
+
badge?: NavBadgeConfig | string;
|
|
848
|
+
/** Custom component slots rendered around this operational view. */
|
|
849
|
+
components?: ViewComponentSlots;
|
|
850
|
+
/** Role-based access rules controlling who can see or use this view. */
|
|
851
|
+
access?: AccessConfig;
|
|
852
|
+
}
|
|
853
|
+
/** Table view — requires no special fields. */
|
|
854
|
+
interface TableViewConfig extends ViewConfigBase {
|
|
855
|
+
layout?: 'table' | 'spreadsheet';
|
|
856
|
+
/** Field name used to organize records into kanban columns or collapsible grouped sections in table, cards, and spreadsheet. */
|
|
857
|
+
groupBy?: string;
|
|
858
|
+
}
|
|
859
|
+
/** Kanban view — requires `groupBy` to organize into columns. */
|
|
860
|
+
interface KanbanViewConfig extends ViewConfigBase {
|
|
861
|
+
layout: 'kanban';
|
|
862
|
+
/** Field name to organize records into kanban columns. */
|
|
863
|
+
groupBy: string;
|
|
864
|
+
}
|
|
865
|
+
/** Calendar view — requires `dateField` to place records on the calendar. */
|
|
866
|
+
interface CalendarViewConfig extends ViewConfigBase {
|
|
867
|
+
layout: 'calendar';
|
|
868
|
+
/** Field name containing the ISO date string for calendar placement. */
|
|
869
|
+
dateField: string;
|
|
925
870
|
}
|
|
926
|
-
/**
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
871
|
+
/** Gantt view — requires both `startDateField` and `endDateField`. */
|
|
872
|
+
interface GanttViewConfig extends ViewConfigBase {
|
|
873
|
+
layout: 'gantt';
|
|
874
|
+
/** Field name for the start date in the gantt timeline. */
|
|
875
|
+
startDateField: string;
|
|
876
|
+
/** Field name for the end date in the gantt timeline. */
|
|
877
|
+
endDateField: string;
|
|
878
|
+
}
|
|
879
|
+
/** Cards view — shows records as image/thumbnail gallery. */
|
|
880
|
+
interface CardsViewConfig extends ViewConfigBase {
|
|
881
|
+
layout: 'cards';
|
|
882
|
+
/** Field name used to organize records into groups. */
|
|
883
|
+
groupBy?: string;
|
|
938
884
|
}
|
|
939
885
|
/**
|
|
940
|
-
*
|
|
886
|
+
* Complete configuration for a tailored operational view.
|
|
941
887
|
*/
|
|
942
|
-
|
|
943
|
-
/** Grid width of the tabs container on the main layout. */
|
|
944
|
-
span?: DetailSpan;
|
|
945
|
-
/** Label of the tab that should be active on initial render. */
|
|
946
|
-
defaultTab?: string;
|
|
947
|
-
/**
|
|
948
|
-
* Visibility condition for this tab container.
|
|
949
|
-
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
950
|
-
*/
|
|
951
|
-
visible?: string | boolean;
|
|
952
|
-
}
|
|
888
|
+
type ViewConfig = TableViewConfig | KanbanViewConfig | CalendarViewConfig | GanttViewConfig | CardsViewConfig;
|
|
953
889
|
/**
|
|
954
|
-
*
|
|
890
|
+
* Backwards-compatible aliases for builder types.
|
|
955
891
|
*/
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
}
|
|
892
|
+
type DefineViewBaseOptions = ViewConfigBase;
|
|
893
|
+
type DefineTableViewOptions = TableViewConfig;
|
|
894
|
+
type DefineKanbanViewOptions = KanbanViewConfig;
|
|
895
|
+
type DefineCalendarViewOptions = CalendarViewConfig;
|
|
896
|
+
type DefineGanttViewOptions = GanttViewConfig;
|
|
897
|
+
type DefineCardsViewOptions = CardsViewConfig;
|
|
898
|
+
type DefineViewOptions = ViewConfig;
|
|
964
899
|
/**
|
|
965
|
-
*
|
|
900
|
+
* Options for defining a custom workflow action with `defineAction`.
|
|
901
|
+
*
|
|
902
|
+
* @example
|
|
903
|
+
* ```ts
|
|
904
|
+
* export const checkInAction = defineAction({
|
|
905
|
+
* name: "checkIn",
|
|
906
|
+
* label: "Check In",
|
|
907
|
+
* icon: "UserCheck",
|
|
908
|
+
* type: "row",
|
|
909
|
+
* confirm: "Confirm guest check-in at the door?",
|
|
910
|
+
* mutation: { checkedIn: true, checkedInAt: "now()" },
|
|
911
|
+
* });
|
|
912
|
+
* ```
|
|
966
913
|
*/
|
|
967
|
-
interface
|
|
968
|
-
/**
|
|
969
|
-
|
|
970
|
-
/**
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
914
|
+
interface DefineActionOptions<TDoc extends Record<string, unknown> = Record<string, unknown>> {
|
|
915
|
+
/** Unique action identifier (e.g. `"checkIn"`, `"markPaid"`). */
|
|
916
|
+
name: string;
|
|
917
|
+
/** Button label displayed in the UI. */
|
|
918
|
+
label: string;
|
|
919
|
+
/** Lucide icon name for the button (e.g. `"UserCheck"`, `"CheckCircle"`). */
|
|
920
|
+
icon?: string;
|
|
921
|
+
/** Action placement: `'row'` (per-row), `'bulk'` (multi-row selection bar), or `'header'` (view header). Defaults to `'row'`. */
|
|
922
|
+
type?: ActionType;
|
|
923
|
+
/** Optional confirmation prompt shown before executing (e.g. `"Confirm guest check-in at the door?"`). */
|
|
924
|
+
confirm?: string;
|
|
925
|
+
/** Optional interactive modal form fields prompting the user for input before executing. */
|
|
926
|
+
fields?: Field[];
|
|
927
|
+
/** Declarative database mutation applied to targeted documents (e.g. `{ checkedIn: true, checkedInAt: "now()" }`). */
|
|
928
|
+
mutation?: Partial<TDoc> | Record<string, unknown>;
|
|
929
|
+
/** Self-hosted server handler function executed when the action is triggered. */
|
|
930
|
+
handler?: (context: ActionContext<TDoc>) => Promise<unknown> | unknown;
|
|
931
|
+
/** Role-based access rules controlling who can trigger this action. */
|
|
932
|
+
access?: AccessConfig;
|
|
975
933
|
}
|
|
976
934
|
/**
|
|
977
|
-
*
|
|
935
|
+
* Defines a typed operational view for a collection.
|
|
936
|
+
* Layout-specific overloads enforce required fields for each view type.
|
|
937
|
+
*
|
|
938
|
+
* @example
|
|
939
|
+
* ```ts
|
|
940
|
+
* // Table view (no special requirements)
|
|
941
|
+
* export const allGuests = defineView({
|
|
942
|
+
* slug: "all-guests",
|
|
943
|
+
* label: "All Guests",
|
|
944
|
+
* layout: "table", // or omit for default
|
|
945
|
+
* });
|
|
946
|
+
*
|
|
947
|
+
* // Kanban view (requires groupBy)
|
|
948
|
+
* export const guestsByTable = defineView({
|
|
949
|
+
* slug: "by-table",
|
|
950
|
+
* label: "Guests by Table",
|
|
951
|
+
* layout: "kanban",
|
|
952
|
+
* groupBy: "tableNumber", // required!
|
|
953
|
+
* });
|
|
954
|
+
*
|
|
955
|
+
* // Calendar view (requires dateField)
|
|
956
|
+
* export const eventCalendar = defineView({
|
|
957
|
+
* slug: "event-calendar",
|
|
958
|
+
* label: "Event Calendar",
|
|
959
|
+
* layout: "calendar",
|
|
960
|
+
* dateField: "eventDate", // required!
|
|
961
|
+
* });
|
|
962
|
+
*
|
|
963
|
+
* // Gantt view (requires startDateField and endDateField)
|
|
964
|
+
* export const projectTimeline = defineView({
|
|
965
|
+
* slug: "timeline",
|
|
966
|
+
* label: "Project Timeline",
|
|
967
|
+
* layout: "gantt",
|
|
968
|
+
* startDateField: "startDate", // required!
|
|
969
|
+
* endDateField: "endDate", // required!
|
|
970
|
+
* });
|
|
971
|
+
* ```
|
|
978
972
|
*/
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
973
|
+
declare function defineView(config: DefineTableViewOptions): DefineTableViewOptions;
|
|
974
|
+
declare function defineView(config: DefineKanbanViewOptions): DefineKanbanViewOptions;
|
|
975
|
+
declare function defineView(config: DefineCalendarViewOptions): DefineCalendarViewOptions;
|
|
976
|
+
declare function defineView(config: DefineGanttViewOptions): DefineGanttViewOptions;
|
|
977
|
+
declare function defineView(config: DefineCardsViewOptions): DefineCardsViewOptions;
|
|
978
|
+
declare function defineView<const T extends DefineViewOptions>(config: T): T;
|
|
979
|
+
/** Convenience helper for table views. Enforces no view-specific required fields. */
|
|
980
|
+
declare function defineTableView(config: DefineTableViewOptions): DefineTableViewOptions;
|
|
981
|
+
/** Convenience helper for kanban views. Enforces `groupBy` is provided. */
|
|
982
|
+
declare function defineKanbanView(config: DefineKanbanViewOptions): DefineKanbanViewOptions;
|
|
983
|
+
/** Convenience helper for calendar views. Enforces `dateField` is provided. */
|
|
984
|
+
declare function defineCalendarView(config: DefineCalendarViewOptions): DefineCalendarViewOptions;
|
|
985
|
+
/** Convenience helper for gantt views. Enforces `startDateField` and `endDateField` are provided. */
|
|
986
|
+
declare function defineGanttView(config: DefineGanttViewOptions): DefineGanttViewOptions;
|
|
987
|
+
/** Convenience helper for cards views. Optional `groupBy`. */
|
|
988
|
+
declare function defineCardsView(config: DefineCardsViewOptions): DefineCardsViewOptions;
|
|
989
989
|
/**
|
|
990
|
-
*
|
|
990
|
+
* Defines a custom workflow action for an operational view.
|
|
991
|
+
*
|
|
992
|
+
* @example
|
|
993
|
+
* ```ts
|
|
994
|
+
* export const markPaidAction = defineAction({
|
|
995
|
+
* name: "markPaid",
|
|
996
|
+
* label: "Mark Paid",
|
|
997
|
+
* icon: "DollarSign",
|
|
998
|
+
* type: "bulk",
|
|
999
|
+
* confirm: "Mark selected orders as paid?",
|
|
1000
|
+
* mutation: { status: "paid" },
|
|
1001
|
+
* });
|
|
1002
|
+
* ```
|
|
991
1003
|
*/
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
layout?: "table" | "cards" | "list";
|
|
995
|
-
/** Message shown when the repeated array is empty. */
|
|
996
|
-
emptyText?: string;
|
|
997
|
-
/** Grid width of the repeated container. */
|
|
998
|
-
span?: DetailSpan;
|
|
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
|
-
}
|
|
1004
|
+
declare function defineAction<const T extends DefineActionOptions>(config: T): T;
|
|
1005
|
+
|
|
1015
1006
|
/**
|
|
1016
|
-
*
|
|
1007
|
+
* Definition of a navigation group in the Dyrected admin sidebar.
|
|
1017
1008
|
*/
|
|
1018
|
-
interface
|
|
1019
|
-
/**
|
|
1020
|
-
|
|
1021
|
-
/**
|
|
1022
|
-
|
|
1023
|
-
/**
|
|
1024
|
-
|
|
1025
|
-
/**
|
|
1026
|
-
|
|
1009
|
+
interface NavGroup {
|
|
1010
|
+
/** Display title for the group in the sidebar. */
|
|
1011
|
+
name: string;
|
|
1012
|
+
/** Optional stable identifier/slug for the group. */
|
|
1013
|
+
slug?: string;
|
|
1014
|
+
/** Lucide icon name for the group accordion header. */
|
|
1015
|
+
icon?: AdminIconName | string;
|
|
1016
|
+
/** Whether the group is expanded by default in the sidebar. */
|
|
1017
|
+
defaultExpanded?: boolean;
|
|
1018
|
+
/** Sort order weight for the group section in the sidebar (lower numbers appear first). */
|
|
1019
|
+
order?: number;
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Configuration for real-time count badges on navigation items.
|
|
1023
|
+
*/
|
|
1024
|
+
interface NavBadgeConfig {
|
|
1025
|
+
/** If true, automatically calculates a count based on the primary view's filter. */
|
|
1026
|
+
count?: boolean;
|
|
1027
|
+
/** Static text override for the badge (e.g. "Live", "New", "Urgent"). */
|
|
1028
|
+
text?: string;
|
|
1029
|
+
/** Custom aggregate filter evaluated on the database. */
|
|
1030
|
+
aggregate?: {
|
|
1031
|
+
collection: string;
|
|
1032
|
+
where?: Record<string, unknown>;
|
|
1033
|
+
};
|
|
1034
|
+
/** Visual badge color variant. */
|
|
1035
|
+
variant?: "default" | "warning" | "destructive" | "info" | "success";
|
|
1027
1036
|
}
|
|
1028
1037
|
/**
|
|
1029
|
-
*
|
|
1038
|
+
* Options for defining an operational workspace, or customizing placement of collections/globals, with `defineWorkspace`.
|
|
1030
1039
|
*/
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1040
|
+
interface DefineWorkspaceOptions {
|
|
1041
|
+
/** If provided, injects views into an existing collection submenu. If omitted, item stands alone. */
|
|
1042
|
+
addToCollection?: string;
|
|
1043
|
+
/** References an existing collection to position it in navigation. */
|
|
1044
|
+
collection?: string;
|
|
1045
|
+
/** References an existing global to position it in navigation. */
|
|
1046
|
+
global?: string;
|
|
1047
|
+
/** Designates this item as the dashboard link. */
|
|
1048
|
+
dashboard?: boolean;
|
|
1049
|
+
/** Stable URL slug for standalone operational workspaces (`/:slug`). */
|
|
1050
|
+
slug?: string;
|
|
1051
|
+
/** Display label in the sidebar (defaults to collection/global label when applicable). */
|
|
1052
|
+
label?: string;
|
|
1053
|
+
/** Lucide icon name (e.g. "ShieldAlert", "Users", "Briefcase"). */
|
|
1054
|
+
icon?: AdminIconName | string;
|
|
1055
|
+
/** Section group name (string) or group object with icon and default expanded state. */
|
|
1056
|
+
group?: string | NavGroup;
|
|
1057
|
+
/** Relative position: insert immediately after this collection or nav item slug. */
|
|
1058
|
+
after?: string;
|
|
1059
|
+
/** Relative position: insert immediately before this collection or nav item slug. */
|
|
1060
|
+
before?: string;
|
|
1061
|
+
/** Numeric sort weight within its group (lower numbers first, default 100). */
|
|
1062
|
+
order?: number;
|
|
1063
|
+
/** Fast shortcut to pin item to start or end of its group: 'first' | 'last'. */
|
|
1064
|
+
position?: "first" | "last";
|
|
1065
|
+
/** Real-time counter badge (auto-computed from primary view or custom aggregate). */
|
|
1066
|
+
badge?: NavBadgeConfig | string;
|
|
1067
|
+
/** Role-based access rules controlling who can see this navigation item. */
|
|
1068
|
+
access?: string[] | AccessRule;
|
|
1069
|
+
/** Custom internal route or external URL. */
|
|
1070
|
+
href?: string;
|
|
1071
|
+
/** Views belonging to this item. The first view is automatically the default. */
|
|
1072
|
+
views?: ViewConfig[];
|
|
1073
|
+
}
|
|
1036
1074
|
/**
|
|
1037
|
-
*
|
|
1075
|
+
* Helper to define an operational workspace or customize placement of collections/globals.
|
|
1076
|
+
*
|
|
1077
|
+
* @example
|
|
1078
|
+
* ```ts
|
|
1079
|
+
* export const kycQueue = defineWorkspace({
|
|
1080
|
+
* slug: "kyc-review",
|
|
1081
|
+
* label: "KYC Review",
|
|
1082
|
+
* icon: "ShieldAlert",
|
|
1083
|
+
* group: "Compliance",
|
|
1084
|
+
* views: [
|
|
1085
|
+
* defineView({ collection: "investors", slug: "pending", label: "Pending" }),
|
|
1086
|
+
* ],
|
|
1087
|
+
* });
|
|
1088
|
+
* ```
|
|
1038
1089
|
*/
|
|
1039
|
-
|
|
1040
|
-
/** Unique identifier for the computed metric. */
|
|
1041
|
-
id?: string;
|
|
1042
|
-
/** JEXL expression string evaluated against `{ doc, user }`. */
|
|
1043
|
-
expression?: string;
|
|
1044
|
-
/** Async or sync function receiving `{ doc, user, db }` returning the computed value. */
|
|
1045
|
-
handler?: ComputedHandler<TDoc>;
|
|
1046
|
-
/** Grid width for the computed card. */
|
|
1047
|
-
span?: DetailSpan;
|
|
1048
|
-
/** Formatting preset for the computed value ('currency', 'percent', 'number', 'date'). */
|
|
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
|
-
}
|
|
1090
|
+
declare function defineWorkspace(options: DefineWorkspaceOptions): DefineWorkspaceOptions;
|
|
1058
1091
|
/**
|
|
1059
|
-
*
|
|
1092
|
+
* Runtime compiled representation of a single navigation item.
|
|
1060
1093
|
*/
|
|
1061
|
-
interface
|
|
1062
|
-
|
|
1063
|
-
type: "
|
|
1064
|
-
|
|
1065
|
-
id?: string;
|
|
1066
|
-
/** Human-readable card label. */
|
|
1094
|
+
interface CompiledNavItem {
|
|
1095
|
+
id: string;
|
|
1096
|
+
type: "workspace" | "collection" | "global" | "dashboard" | "link";
|
|
1097
|
+
slug: string;
|
|
1067
1098
|
label: string;
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1099
|
+
icon?: string;
|
|
1100
|
+
group?: string;
|
|
1101
|
+
href?: string;
|
|
1102
|
+
badge?: NavBadgeConfig | string;
|
|
1103
|
+
access?: string[] | AccessRule;
|
|
1104
|
+
order: number;
|
|
1105
|
+
collection?: string;
|
|
1106
|
+
global?: string;
|
|
1107
|
+
views: ViewConfig[];
|
|
1074
1108
|
}
|
|
1075
1109
|
/**
|
|
1076
|
-
*
|
|
1110
|
+
* Runtime compiled representation of a navigation group containing items.
|
|
1077
1111
|
*/
|
|
1078
|
-
interface
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
/** Vertical margin spacing around the divider line. */
|
|
1087
|
-
spacing?: "sm" | "md" | "lg" | "none";
|
|
1112
|
+
interface CompiledNavGroup {
|
|
1113
|
+
id: string;
|
|
1114
|
+
name: string;
|
|
1115
|
+
slug: string;
|
|
1116
|
+
icon?: string;
|
|
1117
|
+
defaultExpanded?: boolean;
|
|
1118
|
+
order: number;
|
|
1119
|
+
items: CompiledNavItem[];
|
|
1088
1120
|
}
|
|
1089
1121
|
/**
|
|
1090
|
-
*
|
|
1122
|
+
* Complete runtime compiled navigation tree.
|
|
1091
1123
|
*/
|
|
1092
|
-
interface
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1124
|
+
interface CompiledNavTree {
|
|
1125
|
+
groups: CompiledNavGroup[];
|
|
1126
|
+
ungrouped: CompiledNavItem[];
|
|
1127
|
+
}
|
|
1128
|
+
interface PinnedNavItemRef {
|
|
1129
|
+
type: "workspace" | "collection" | "global" | "link" | "dashboard";
|
|
1130
|
+
slug: string;
|
|
1131
|
+
view?: string;
|
|
1132
|
+
label?: string;
|
|
1133
|
+
icon?: string;
|
|
1134
|
+
}
|
|
1135
|
+
interface UserNavigationPreferences {
|
|
1136
|
+
_version: number;
|
|
1137
|
+
pinned?: PinnedNavItemRef[];
|
|
1138
|
+
hidden?: string[];
|
|
1139
|
+
groupOrder?: string[];
|
|
1140
|
+
itemOrder?: Record<string, string[]>;
|
|
1141
|
+
groups?: NavGroup[];
|
|
1142
|
+
items?: DefineWorkspaceOptions[];
|
|
1143
|
+
}
|
|
1144
|
+
declare const CURRENT_NAV_PREFERENCES_VERSION = 1;
|
|
1145
|
+
declare const DEFAULT_USER_NAV_PREFERENCES: UserNavigationPreferences;
|
|
1146
|
+
|
|
1147
|
+
/** A valid icon component name from the Lucide icon set bundled with Dyrected Admin. */
|
|
1148
|
+
type AdminIconName = keyof typeof icons;
|
|
1149
|
+
/** Ordered custom component keys rendered around the built-in Admin dashboard. */
|
|
1150
|
+
interface AdminDashboardComponentSlots {
|
|
1151
|
+
beforeDashboard?: string[];
|
|
1152
|
+
afterDashboard?: string[];
|
|
1153
|
+
}
|
|
1154
|
+
/** Ordered custom component keys rendered around an operational view's content. */
|
|
1155
|
+
interface CollectionViewComponentSlots {
|
|
1156
|
+
beforeViewHeader?: string[];
|
|
1157
|
+
afterViewHeader?: string[];
|
|
1158
|
+
beforeViewContent?: string[];
|
|
1159
|
+
afterViewContent?: string[];
|
|
1160
|
+
}
|
|
1161
|
+
/** Ordered custom component keys rendered around a collection's list content. */
|
|
1162
|
+
interface CollectionListComponentSlots {
|
|
1163
|
+
beforeList?: string[];
|
|
1164
|
+
beforeListTable?: string[];
|
|
1165
|
+
afterListTable?: string[];
|
|
1166
|
+
afterList?: string[];
|
|
1167
|
+
beforeViewHeader?: string[];
|
|
1168
|
+
afterViewHeader?: string[];
|
|
1169
|
+
beforeViewContent?: string[];
|
|
1170
|
+
afterViewContent?: string[];
|
|
1171
|
+
collectionView?: CollectionViewComponentSlots;
|
|
1097
1172
|
}
|
|
1098
1173
|
/**
|
|
1099
|
-
*
|
|
1174
|
+
* Branding and metadata options for the Dyrected Admin UI.
|
|
1175
|
+
*
|
|
1176
|
+
* @example
|
|
1177
|
+
* admin: {
|
|
1178
|
+
* branding: {
|
|
1179
|
+
* logo: '/logo.svg',
|
|
1180
|
+
* primaryColor: '#6366f1',
|
|
1181
|
+
* },
|
|
1182
|
+
* meta: {
|
|
1183
|
+
* titleSuffix: '- My App',
|
|
1184
|
+
* },
|
|
1185
|
+
* }
|
|
1100
1186
|
*/
|
|
1101
|
-
interface
|
|
1102
|
-
/** Grid width in the 12-column layout. */
|
|
1103
|
-
span?: DetailSpan;
|
|
1187
|
+
interface AdminConfig {
|
|
1104
1188
|
/**
|
|
1105
|
-
*
|
|
1106
|
-
*
|
|
1189
|
+
* Custom navigation layout for the admin sidebar.
|
|
1190
|
+
* If omitted, all collections and globals appear in default sections.
|
|
1107
1191
|
*/
|
|
1108
|
-
|
|
1109
|
-
/**
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1192
|
+
navigation?: DefineWorkspaceOptions[];
|
|
1193
|
+
/** Custom component slots around the built-in dashboard. */
|
|
1194
|
+
components?: AdminDashboardComponentSlots;
|
|
1195
|
+
branding?: {
|
|
1196
|
+
/** Full logo image shown in the expanded sidebar. URL or imported image asset. */
|
|
1197
|
+
logo?: string;
|
|
1198
|
+
/** Compact logo mark used in the collapsed sidebar state. */
|
|
1199
|
+
logoMark?: string;
|
|
1200
|
+
/** Text alternative or addition to the logo image. */
|
|
1201
|
+
logoText?: string;
|
|
1202
|
+
/**
|
|
1203
|
+
* Brand colour used for committed, filled actions — Save, Create, Upload —
|
|
1204
|
+
* and active/selected states. Accepts a hex string, a named colour
|
|
1205
|
+
* (`amber`, `lime`, `violet`, `green`, `blue`, `red`, `purple`, `orange`),
|
|
1206
|
+
* or a raw HSL triplet (`"217 91% 60%"`). Applied in both light and dark mode.
|
|
1207
|
+
*
|
|
1208
|
+
* This is one half of the two-colour brand model. Use {@link accentColor}
|
|
1209
|
+
* for links and navigation accents. If you only set `primaryColor`, it is
|
|
1210
|
+
* reused for accents too, matching the single-brand-colour look.
|
|
1211
|
+
* @example '#6366f1'
|
|
1212
|
+
* @example 'blue'
|
|
1213
|
+
* @example 'hsl(240 50% 60%)'
|
|
1214
|
+
*/
|
|
1215
|
+
primaryColor?: string;
|
|
1216
|
+
/**
|
|
1217
|
+
* Brand colour used for links, active navigation details, hover text, and
|
|
1218
|
+
* focus rings — the "accent" half of the two-colour brand model, mapped to
|
|
1219
|
+
* the admin's `--intelligence` token. Accepts the same formats as
|
|
1220
|
+
* {@link primaryColor} and applies in both light and dark mode.
|
|
1221
|
+
*
|
|
1222
|
+
* Set this when your brand has a distinct link/accent colour separate from
|
|
1223
|
+
* your primary action colour. When omitted, accents fall back to
|
|
1224
|
+
* `primaryColor` (if set) or the built-in default.
|
|
1225
|
+
* @example '#8b5cf6'
|
|
1226
|
+
* @example 'violet'
|
|
1227
|
+
*/
|
|
1228
|
+
accentColor?: string;
|
|
1229
|
+
/** Browser tab favicon URL. */
|
|
1230
|
+
favicon?: string;
|
|
1231
|
+
/** Font family for body and UI text. Must be loaded separately. */
|
|
1232
|
+
fontSans?: string;
|
|
1233
|
+
/** Font family for headings. Must be loaded separately. */
|
|
1234
|
+
fontSerif?: string;
|
|
1235
|
+
};
|
|
1236
|
+
meta?: {
|
|
1237
|
+
/**
|
|
1238
|
+
* String appended to every Admin page's `<title>`.
|
|
1239
|
+
* @default '- Dyrected'
|
|
1240
|
+
*/
|
|
1241
|
+
titleSuffix?: string;
|
|
1242
|
+
};
|
|
1243
|
+
/**
|
|
1244
|
+
* The canonical/base URL of the frontend website for links and iframe live previews.
|
|
1245
|
+
*/
|
|
1246
|
+
siteUrl?: string;
|
|
1113
1247
|
}
|
|
1248
|
+
|
|
1249
|
+
type DeclarativeHookExpression = string;
|
|
1114
1250
|
/**
|
|
1115
|
-
*
|
|
1251
|
+
* @deprecated Use {@link FieldBeforeChangeHook} or `FieldAfterReadHook` instead.
|
|
1252
|
+
* This alias remains for backwards compatibility.
|
|
1116
1253
|
*/
|
|
1117
|
-
|
|
1118
|
-
/** Identifies this item as a text block. */
|
|
1119
|
-
type: "text";
|
|
1120
|
-
/** Text or markdown content. */
|
|
1121
|
-
content: string;
|
|
1122
|
-
/** Text options. */
|
|
1123
|
-
options?: DetailTextOptions;
|
|
1124
|
-
}
|
|
1254
|
+
type FieldHook<TDoc extends object = Record<string, unknown>, TValue = unknown> = FieldBeforeChangeHook<TValue, TDoc>;
|
|
1125
1255
|
/**
|
|
1126
|
-
*
|
|
1256
|
+
* Runs before Dyrected queries the database for a list or single-document fetch.
|
|
1257
|
+
*
|
|
1258
|
+
* Return a new `where` query object to override or extend the current filter.
|
|
1259
|
+
* Return `undefined` (or nothing) to leave the query unchanged.
|
|
1127
1260
|
*/
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
visible?: string | boolean;
|
|
1136
|
-
/** Static or initial props passed into the custom component. */
|
|
1137
|
-
props?: Record<string, any>;
|
|
1138
|
-
/** Inline render function receiving `{ doc, user }` (Self-hosted React runtimes). */
|
|
1139
|
-
render?: (context: {
|
|
1140
|
-
doc: TDoc;
|
|
1141
|
-
user?: any;
|
|
1142
|
-
[key: string]: any;
|
|
1143
|
-
}) => any;
|
|
1144
|
-
}
|
|
1261
|
+
type CollectionBeforeReadHook = (args: {
|
|
1262
|
+
req: HookRequestContext;
|
|
1263
|
+
query?: Record<string, unknown>;
|
|
1264
|
+
user?: AuthenticatedUser;
|
|
1265
|
+
db: ReadonlyDatabaseAdapter;
|
|
1266
|
+
}) => Record<string, unknown> | void | Promise<Record<string, unknown> | void>;
|
|
1267
|
+
type CollectionBeforeReadHookEntry = CollectionBeforeReadHook | DeclarativeHookExpression;
|
|
1145
1268
|
/**
|
|
1146
|
-
*
|
|
1269
|
+
* Runs after a document (or list of documents) is fetched from the database,
|
|
1270
|
+
* before the response is sent to the client.
|
|
1147
1271
|
*/
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
}
|
|
1272
|
+
type CollectionAfterReadHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1273
|
+
doc: TDoc;
|
|
1274
|
+
req: HookRequestContext;
|
|
1275
|
+
user?: AuthenticatedUser;
|
|
1276
|
+
db: ReadonlyDatabaseAdapter;
|
|
1277
|
+
}) => TDoc | Promise<TDoc>;
|
|
1278
|
+
type CollectionAfterReadHookEntry<TDoc extends object = Record<string, unknown>> = CollectionAfterReadHook<TDoc> | DeclarativeHookExpression;
|
|
1156
1279
|
/**
|
|
1157
|
-
*
|
|
1280
|
+
* Runs **before** a document is created or updated in the database.
|
|
1158
1281
|
*/
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
/**
|
|
1169
|
-
* Visibility condition for this action item.
|
|
1170
|
-
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1171
|
-
*/
|
|
1172
|
-
visible?: string | boolean;
|
|
1173
|
-
}
|
|
1282
|
+
type CollectionBeforeChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1283
|
+
data: Partial<TDoc>;
|
|
1284
|
+
doc?: TDoc;
|
|
1285
|
+
req: HookRequestContext;
|
|
1286
|
+
user?: AuthenticatedUser;
|
|
1287
|
+
operation: "create" | "update";
|
|
1288
|
+
db: ReadonlyDatabaseAdapter;
|
|
1289
|
+
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;
|
|
1290
|
+
type CollectionBeforeChangeHookEntry<TDoc extends object = Record<string, unknown>> = CollectionBeforeChangeHook<TDoc> | DeclarativeHookExpression;
|
|
1174
1291
|
/**
|
|
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.
|
|
1292
|
+
* Runs **after** a document is created or updated in the database.
|
|
1181
1293
|
*/
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
}
|
|
1294
|
+
type CollectionAfterChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1295
|
+
doc: TDoc;
|
|
1296
|
+
previousDoc?: TDoc;
|
|
1297
|
+
req: HookRequestContext;
|
|
1298
|
+
user?: AuthenticatedUser;
|
|
1299
|
+
operation: "create" | "update";
|
|
1300
|
+
db: DatabaseAdapter;
|
|
1301
|
+
}) => void | Promise<void>;
|
|
1302
|
+
/**
|
|
1303
|
+
* Runs **before** a document is deleted from the database.
|
|
1304
|
+
*/
|
|
1305
|
+
type CollectionBeforeDeleteHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1306
|
+
id: string;
|
|
1307
|
+
doc: TDoc;
|
|
1308
|
+
req: HookRequestContext;
|
|
1309
|
+
user?: AuthenticatedUser;
|
|
1310
|
+
db: ReadonlyDatabaseAdapter;
|
|
1311
|
+
}) => void | Promise<void>;
|
|
1312
|
+
/**
|
|
1313
|
+
* Runs **after** a document has been deleted from the database.
|
|
1314
|
+
*/
|
|
1315
|
+
type CollectionAfterDeleteHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1316
|
+
id: string;
|
|
1317
|
+
doc: TDoc;
|
|
1318
|
+
req: HookRequestContext;
|
|
1319
|
+
user?: AuthenticatedUser;
|
|
1320
|
+
db: DatabaseAdapter;
|
|
1321
|
+
}) => void | Promise<void>;
|
|
1322
|
+
/** @see {@link CollectionBeforeReadHook} */
|
|
1323
|
+
type GlobalBeforeReadHook = CollectionBeforeReadHook;
|
|
1324
|
+
type GlobalBeforeReadHookEntry = CollectionBeforeReadHookEntry;
|
|
1190
1325
|
/**
|
|
1191
|
-
*
|
|
1326
|
+
* Runs after the global document is fetched, before the response is sent.
|
|
1192
1327
|
*/
|
|
1193
|
-
type
|
|
1328
|
+
type GlobalAfterReadHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1329
|
+
doc: TDoc;
|
|
1330
|
+
req: HookRequestContext;
|
|
1331
|
+
user?: AuthenticatedUser;
|
|
1332
|
+
db: ReadonlyDatabaseAdapter;
|
|
1333
|
+
}) => TDoc | Promise<TDoc>;
|
|
1334
|
+
type GlobalAfterReadHookEntry<TDoc extends object = Record<string, unknown>> = GlobalAfterReadHook<TDoc> | DeclarativeHookExpression;
|
|
1194
1335
|
/**
|
|
1195
|
-
*
|
|
1336
|
+
* Runs before the global document is updated.
|
|
1337
|
+
* Operation is always `'update'` (globals cannot be created or deleted).
|
|
1196
1338
|
*/
|
|
1197
|
-
type
|
|
1198
|
-
|
|
1339
|
+
type GlobalBeforeChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1340
|
+
data: Partial<TDoc>;
|
|
1341
|
+
doc?: TDoc;
|
|
1342
|
+
req: HookRequestContext;
|
|
1343
|
+
user?: AuthenticatedUser;
|
|
1344
|
+
operation: "update";
|
|
1345
|
+
db: ReadonlyDatabaseAdapter;
|
|
1346
|
+
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;
|
|
1347
|
+
type GlobalBeforeChangeHookEntry<TDoc extends object = Record<string, unknown>> = GlobalBeforeChangeHook<TDoc> | DeclarativeHookExpression;
|
|
1199
1348
|
/**
|
|
1200
|
-
*
|
|
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.
|
|
1349
|
+
* Runs after the global document is updated. Side-effects only.
|
|
1205
1350
|
*/
|
|
1206
|
-
type
|
|
1351
|
+
type GlobalAfterChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1352
|
+
doc: TDoc;
|
|
1353
|
+
previousDoc?: TDoc;
|
|
1354
|
+
req: HookRequestContext;
|
|
1355
|
+
user?: AuthenticatedUser;
|
|
1356
|
+
operation: "update";
|
|
1357
|
+
db: DatabaseAdapter;
|
|
1358
|
+
}) => void | Promise<void>;
|
|
1207
1359
|
/**
|
|
1208
|
-
*
|
|
1360
|
+
* @deprecated Use the specific hook types instead:
|
|
1361
|
+
* `CollectionBeforeChangeHook`, `CollectionAfterReadHook`, etc.
|
|
1209
1362
|
*
|
|
1210
|
-
*
|
|
1211
|
-
* - `cast` is intentionally absent: counting is document-level,
|
|
1212
|
-
* not field-value-level, so type conversion has no meaning here.
|
|
1363
|
+
* This broad type remains for backwards compatibility with the internal hook runner.
|
|
1213
1364
|
*/
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1365
|
+
type HookFunction<TDoc extends object = Record<string, unknown>> = (args: {
|
|
1366
|
+
data?: Partial<TDoc>;
|
|
1367
|
+
doc?: TDoc;
|
|
1368
|
+
user?: AuthenticatedUser;
|
|
1369
|
+
req?: HookRequestContext;
|
|
1370
|
+
operation?: "create" | "update" | "delete";
|
|
1371
|
+
db?: DatabaseAdapter;
|
|
1372
|
+
[key: string]: unknown;
|
|
1373
|
+
}) => unknown | Promise<unknown>;
|
|
1374
|
+
|
|
1375
|
+
declare const LIFECYCLE_EVENT_NAMES: readonly ["revision.created", "workflow.transitioned", "entry.published", "entry.unpublished"];
|
|
1376
|
+
type LifecycleEventName = (typeof LIFECYCLE_EVENT_NAMES)[number];
|
|
1377
|
+
interface WorkflowState {
|
|
1378
|
+
/** Stable machine-readable state key. */
|
|
1379
|
+
name: string;
|
|
1380
|
+
/** Label rendered in the Admin UI. */
|
|
1381
|
+
label: string;
|
|
1382
|
+
/** Marks the state whose revision is visible to public readers. */
|
|
1383
|
+
published?: boolean;
|
|
1384
|
+
/** Optional visual tone used by the Admin UI. */
|
|
1385
|
+
color?: "neutral" | "warning" | "success" | "danger" | "info";
|
|
1386
|
+
}
|
|
1387
|
+
interface WorkflowTransition {
|
|
1388
|
+
/** Stable transition key used by the REST and SDK APIs. */
|
|
1389
|
+
name: string;
|
|
1390
|
+
label: string;
|
|
1391
|
+
/**
|
|
1392
|
+
* Source state(s) this transition originates from.
|
|
1393
|
+
* Must match names in the workflow's `states` array.
|
|
1394
|
+
*/
|
|
1395
|
+
from: string | string[];
|
|
1396
|
+
/**
|
|
1397
|
+
* Target state this transition leads to.
|
|
1398
|
+
* Must match a name in the workflow's `states` array.
|
|
1399
|
+
*/
|
|
1400
|
+
to: string;
|
|
1401
|
+
/** Every listed capability is required. */
|
|
1402
|
+
requiredCapabilities?: string[];
|
|
1403
|
+
/** Require a non-empty comment when performing the transition. */
|
|
1404
|
+
requireComment?: boolean;
|
|
1405
|
+
/** Remove the public snapshot after this transition commits. */
|
|
1406
|
+
unpublish?: boolean;
|
|
1407
|
+
}
|
|
1408
|
+
interface WorkflowRole {
|
|
1409
|
+
/** Existing user role value, for example `editor` or `publisher`. */
|
|
1410
|
+
role: string;
|
|
1411
|
+
capabilities: string[];
|
|
1217
1412
|
}
|
|
1218
1413
|
/**
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
1414
|
+
* Configuration for a collection's editorial workflow: the states a document
|
|
1415
|
+
* can be in, the transitions between them, and the roles allowed to perform
|
|
1416
|
+
* each. Attach it to a collection's `workflow`, or build one with
|
|
1417
|
+
* `definePublishingWorkflow`.
|
|
1221
1418
|
*/
|
|
1222
|
-
interface
|
|
1223
|
-
|
|
1224
|
-
|
|
1419
|
+
interface WorkflowConfig<TDoc extends object = Record<string, unknown>> {
|
|
1420
|
+
/** The state every new document starts in, e.g. `"draft"`. */
|
|
1421
|
+
initialState: string;
|
|
1422
|
+
/** State used for a new working revision created from published content. */
|
|
1423
|
+
draftState?: string;
|
|
1424
|
+
/** All states a document can occupy. Exactly one should be marked `published`. */
|
|
1425
|
+
states: WorkflowState[];
|
|
1426
|
+
/** The allowed moves between states, each with its own capability and comment rules. */
|
|
1427
|
+
transitions: WorkflowTransition[];
|
|
1428
|
+
/** Maps values in `user.roles` to workflow capabilities. */
|
|
1429
|
+
roles?: WorkflowRole[];
|
|
1430
|
+
/** Server-side hooks that run around every transition. */
|
|
1431
|
+
hooks?: {
|
|
1432
|
+
/** Runs before a transition commits — throw to validate or block the move. */
|
|
1433
|
+
beforeTransition?: CollectionBeforeTransitionHook<TDoc>[];
|
|
1434
|
+
/** Runs after a transition commits — trigger notifications or downstream work. */
|
|
1435
|
+
afterTransition?: CollectionAfterTransitionHook<TDoc>[];
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
interface WorkflowMetadata {
|
|
1439
|
+
/** The document's current workflow state, e.g. `"draft"` or `"published"`. */
|
|
1440
|
+
state: string;
|
|
1441
|
+
/** Revision counter, incremented on every committed transition. */
|
|
1442
|
+
revision: number;
|
|
1443
|
+
/** Revision number currently exposed as the public snapshot, once published. */
|
|
1444
|
+
publishedRevision?: number;
|
|
1445
|
+
/** ISO timestamp of the most recent publish. */
|
|
1446
|
+
publishedAt?: string;
|
|
1447
|
+
/** Id of the user who last published this document. */
|
|
1448
|
+
publishedBy?: string;
|
|
1449
|
+
/** Transitions currently allowed for the requesting user. Response-only. */
|
|
1450
|
+
availableTransitions?: string[];
|
|
1451
|
+
}
|
|
1452
|
+
interface WorkflowTransitionContext<TDoc extends object = Record<string, unknown>> {
|
|
1453
|
+
/** The transition being performed. */
|
|
1454
|
+
transition: WorkflowTransition;
|
|
1455
|
+
/** State the document is moving out of. */
|
|
1456
|
+
from: string;
|
|
1457
|
+
/** State the document is moving into. */
|
|
1458
|
+
to: string;
|
|
1459
|
+
/** The document as it stands before the transition commits. */
|
|
1460
|
+
doc: TDoc;
|
|
1461
|
+
/** The user performing the transition, when the request is authenticated. */
|
|
1462
|
+
user?: AuthenticatedUser;
|
|
1463
|
+
/** Comment supplied with the transition; required when `requireComment` is set. */
|
|
1464
|
+
comment?: string;
|
|
1465
|
+
/** Request context for the transition. */
|
|
1466
|
+
req: HookRequestContext;
|
|
1467
|
+
/** Transaction-scoped database adapter for reads and writes inside the hook. */
|
|
1468
|
+
db: DatabaseAdapter;
|
|
1469
|
+
}
|
|
1470
|
+
type CollectionBeforeTransitionHook<TDoc extends object = Record<string, unknown>> = (args: WorkflowTransitionContext<TDoc>) => void | Promise<void>;
|
|
1471
|
+
type CollectionAfterTransitionHook<TDoc extends object = Record<string, unknown>> = (args: WorkflowTransitionContext<TDoc> & {
|
|
1472
|
+
event: LifecycleEvent;
|
|
1473
|
+
}) => void | Promise<void>;
|
|
1474
|
+
interface LifecycleEvent<TPayload = Record<string, unknown>> {
|
|
1475
|
+
/** Unique id for this event. */
|
|
1476
|
+
id: string;
|
|
1477
|
+
/** The lifecycle event name, e.g. `"workflow.transitioned"` or `"entry.published"`. */
|
|
1478
|
+
name: LifecycleEventName;
|
|
1479
|
+
/** Slug of the collection the event is about. */
|
|
1480
|
+
collection: string;
|
|
1481
|
+
/** Id of the document the event is about. */
|
|
1482
|
+
documentId: string;
|
|
1483
|
+
/** ISO timestamp of when the event occurred. */
|
|
1484
|
+
occurredAt: string;
|
|
1485
|
+
/** Id of the user who triggered the event, when known. */
|
|
1486
|
+
actorId?: string;
|
|
1487
|
+
/** Event-specific data, such as the transition name and affected revision. */
|
|
1488
|
+
payload: TPayload;
|
|
1489
|
+
/** Number of delivery attempts made so far. */
|
|
1490
|
+
attempts: number;
|
|
1491
|
+
/** Current delivery status as the dispatcher works through the queue. */
|
|
1492
|
+
status: "pending" | "processing" | "delivered" | "failed";
|
|
1493
|
+
/** ISO timestamp of the next delivery retry, while pending. */
|
|
1494
|
+
nextAttemptAt?: string;
|
|
1495
|
+
/** ISO timestamp of successful delivery. */
|
|
1496
|
+
deliveredAt?: string;
|
|
1497
|
+
/** Message from the most recent failed delivery attempt. */
|
|
1498
|
+
lastError?: string;
|
|
1225
1499
|
}
|
|
1500
|
+
type LifecycleEventHandler = (event: LifecycleEvent) => void | Promise<void>;
|
|
1501
|
+
|
|
1502
|
+
/** Column span in the 12-column Detail View layout grid (1 to 12). */
|
|
1503
|
+
type DetailSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
1226
1504
|
/**
|
|
1227
|
-
*
|
|
1228
|
-
* (or unique values with item counts) for a specific field.
|
|
1505
|
+
* Visual display variants supported by DetailFieldRenderer.
|
|
1229
1506
|
*/
|
|
1230
|
-
|
|
1231
|
-
distinct: string;
|
|
1232
|
-
where?: Record<string, unknown>;
|
|
1233
|
-
}
|
|
1507
|
+
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";
|
|
1234
1508
|
/**
|
|
1235
|
-
*
|
|
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`.
|
|
1509
|
+
* Configuration options for rendering a field in a Detail View.
|
|
1240
1510
|
*/
|
|
1241
|
-
interface
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1511
|
+
interface DisplayFieldOptions {
|
|
1512
|
+
/** Custom label overriding the field's schema label. */
|
|
1513
|
+
label?: string;
|
|
1514
|
+
/** When true, hides the field label entirely and renders only the value. */
|
|
1515
|
+
hideLabel?: boolean;
|
|
1516
|
+
/** Informational tooltip shown next to the label. */
|
|
1517
|
+
tooltip?: string;
|
|
1518
|
+
/** Grid column span across the 12-column grid. */
|
|
1519
|
+
span?: DetailSpan;
|
|
1520
|
+
/** Specific visual representation variant (e.g. 'badge', 'currency', 'star', 'copyable'). */
|
|
1521
|
+
display?: DisplayVariant;
|
|
1522
|
+
/** Preset format for numbers, dates, and currencies ('currency', 'date', 'datetime', 'relative', 'number', 'percent'). */
|
|
1523
|
+
format?: "currency" | "date" | "datetime" | "relative" | "number" | "percent" | string;
|
|
1524
|
+
/** ISO currency code (e.g. 'USD', 'EUR') when display or format is 'currency'. */
|
|
1525
|
+
currency?: string;
|
|
1526
|
+
/** Color mapping for badge and tag values (named palette, hex color, Tailwind class, or wildcard). */
|
|
1527
|
+
badgeColors?: Record<string, string>;
|
|
1528
|
+
/** Column header for object keys when display is 'key-value'. */
|
|
1529
|
+
keyLabel?: string;
|
|
1530
|
+
/** Column header for object values when display is 'key-value'. */
|
|
1531
|
+
valueLabel?: string;
|
|
1532
|
+
/** Custom placeholder text when the field value is null, undefined, or empty. */
|
|
1533
|
+
emptyText?: string;
|
|
1534
|
+
/** When true, hides this entire field item if the value is null or empty. */
|
|
1535
|
+
hideIfEmpty?: boolean;
|
|
1536
|
+
/**
|
|
1537
|
+
* When true, allows inline editing of this field in the Detail View
|
|
1538
|
+
* via an interactive toggle.
|
|
1539
|
+
*/
|
|
1540
|
+
editable?: boolean;
|
|
1541
|
+
/**
|
|
1542
|
+
* Visibility condition for this field item.
|
|
1543
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1544
|
+
* When false or evaluating to falsy, this item is hidden in the Detail View.
|
|
1545
|
+
*
|
|
1546
|
+
* @example `visible: "doc.status == 'published'"`
|
|
1547
|
+
* @example `visible: false`
|
|
1548
|
+
*/
|
|
1549
|
+
visible?: string | boolean;
|
|
1550
|
+
/** Specific aspect ratio constraint for media (e.g., "16/9", "4/3", "1/1", "auto"). */
|
|
1551
|
+
aspectRatio?: string;
|
|
1552
|
+
/** CSS object-fit behavior for media ('cover', 'contain', 'fill', 'scale-down'). */
|
|
1553
|
+
objectFit?: "cover" | "contain" | "fill" | "scale-down";
|
|
1554
|
+
/** Media alignment ('left', 'center', 'right'). */
|
|
1555
|
+
align?: "left" | "center" | "right";
|
|
1556
|
+
/** Fixed pixel width or CSS dimension for media preview. */
|
|
1557
|
+
width?: string | number;
|
|
1558
|
+
/** Fixed pixel height or CSS dimension for media preview. */
|
|
1559
|
+
height?: string | number;
|
|
1248
1560
|
}
|
|
1249
1561
|
/**
|
|
1250
|
-
*
|
|
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`.
|
|
1562
|
+
* Declared field item in a Detail View.
|
|
1269
1563
|
*/
|
|
1270
|
-
interface
|
|
1271
|
-
/**
|
|
1272
|
-
|
|
1273
|
-
/**
|
|
1274
|
-
|
|
1275
|
-
/**
|
|
1276
|
-
|
|
1564
|
+
interface DetailField {
|
|
1565
|
+
/** Identifies this item as a field. */
|
|
1566
|
+
type: "field";
|
|
1567
|
+
/** Field name or nested path in the document. */
|
|
1568
|
+
field: string;
|
|
1569
|
+
/** Display options for this field. */
|
|
1570
|
+
options?: DisplayFieldOptions;
|
|
1277
1571
|
}
|
|
1278
1572
|
/**
|
|
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.
|
|
1573
|
+
* Configuration options for a Detail View section container.
|
|
1303
1574
|
*/
|
|
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[];
|
|
1575
|
+
interface DetailSectionOptions {
|
|
1576
|
+
/** Lucide icon name displayed in the section header. */
|
|
1577
|
+
icon?: string;
|
|
1578
|
+
/** Status or counter badge displayed beside the section title. */
|
|
1579
|
+
badge?: string;
|
|
1580
|
+
/** Color palette name or hex code for the section badge. */
|
|
1581
|
+
badgeColor?: string;
|
|
1582
|
+
/** Subtitle description displayed beneath the section title. */
|
|
1583
|
+
description?: string;
|
|
1584
|
+
/** Grid width of the section on the main 12-column layout. */
|
|
1585
|
+
span?: DetailSpan;
|
|
1586
|
+
/** Internal grid column count for child items. */
|
|
1587
|
+
columns?: number;
|
|
1588
|
+
/** When true, allows editors to collapse and expand the section. */
|
|
1589
|
+
collapsible?: boolean;
|
|
1590
|
+
/** Starts the section in collapsed state when collapsible is enabled. */
|
|
1591
|
+
collapsedByDefault?: boolean;
|
|
1592
|
+
/**
|
|
1593
|
+
* Visibility condition for this section.
|
|
1594
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1595
|
+
*
|
|
1596
|
+
* @example `visible: "user.roles != null and 'admin' in user.roles"`
|
|
1597
|
+
*/
|
|
1598
|
+
visible?: string | boolean;
|
|
1353
1599
|
}
|
|
1354
1600
|
/**
|
|
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/…
|
|
1363
|
-
*/
|
|
1364
|
-
declare function parseSqlWhere(where: WhereClause, getJsonField: (field: string) => string, placeholder?: '?' | 'pg',
|
|
1365
|
-
/**
|
|
1366
|
-
* SQL keyword used for `contains`/`starts_with`. Postgres `LIKE` is
|
|
1367
|
-
* case-sensitive, so the Postgres adapter defaults to `'ILIKE'` to keep substring
|
|
1368
|
-
* matching case-insensitive like SQLite and MySQL.
|
|
1601
|
+
* Section container grouping fields and components in a Detail View.
|
|
1369
1602
|
*/
|
|
1370
|
-
|
|
1603
|
+
interface DetailSection {
|
|
1604
|
+
/** Identifies this item as a section. */
|
|
1605
|
+
type: "section";
|
|
1606
|
+
/** Section heading title. */
|
|
1607
|
+
title: string;
|
|
1608
|
+
/** Child items rendered inside this section. */
|
|
1609
|
+
items: DetailItem[];
|
|
1610
|
+
/** Section container options. */
|
|
1611
|
+
options?: DetailSectionOptions;
|
|
1612
|
+
}
|
|
1371
1613
|
/**
|
|
1372
|
-
*
|
|
1373
|
-
* Handles nested OR/AND via $or/$and, and all operators via $eq/$in/$gt etc.
|
|
1614
|
+
* Configuration options for an individual tab in `displayTabs()`.
|
|
1374
1615
|
*/
|
|
1375
|
-
|
|
1376
|
-
|
|
1616
|
+
interface DetailTabOptions {
|
|
1617
|
+
/** Lucide icon name displayed inside the tab trigger. */
|
|
1618
|
+
icon?: string;
|
|
1619
|
+
/** Counter or status badge rendered next to the tab label. */
|
|
1620
|
+
badge?: string;
|
|
1621
|
+
/** Color palette name or hex code for the tab badge. */
|
|
1622
|
+
badgeColor?: string;
|
|
1623
|
+
/**
|
|
1624
|
+
* Visibility condition for this individual tab.
|
|
1625
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1626
|
+
*/
|
|
1627
|
+
visible?: string | boolean;
|
|
1628
|
+
}
|
|
1377
1629
|
/**
|
|
1378
|
-
*
|
|
1630
|
+
* Single tab entry inside a tabbed container.
|
|
1379
1631
|
*/
|
|
1380
|
-
|
|
1632
|
+
interface DetailTab {
|
|
1633
|
+
/** Identifies this item as a tab. */
|
|
1634
|
+
type: "tab";
|
|
1635
|
+
/** Tab label shown in the tab bar. */
|
|
1636
|
+
label: string;
|
|
1637
|
+
/** Child items rendered when this tab is active. */
|
|
1638
|
+
items: DetailItem[];
|
|
1639
|
+
/** Tab options. */
|
|
1640
|
+
options?: DetailTabOptions;
|
|
1641
|
+
}
|
|
1381
1642
|
/**
|
|
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.
|
|
1643
|
+
* Configuration options for a tabbed container.
|
|
1389
1644
|
*/
|
|
1390
|
-
|
|
1645
|
+
interface DetailTabsOptions {
|
|
1646
|
+
/** Grid width of the tabs container on the main layout. */
|
|
1647
|
+
span?: DetailSpan;
|
|
1648
|
+
/** Label of the tab that should be active on initial render. */
|
|
1649
|
+
defaultTab?: string;
|
|
1650
|
+
/**
|
|
1651
|
+
* Visibility condition for this tab container.
|
|
1652
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1653
|
+
*/
|
|
1654
|
+
visible?: string | boolean;
|
|
1655
|
+
}
|
|
1391
1656
|
/**
|
|
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.
|
|
1657
|
+
* Tabbed navigation container in a Detail View layout.
|
|
1396
1658
|
*/
|
|
1397
|
-
|
|
1659
|
+
interface DetailTabs {
|
|
1660
|
+
/** Identifies this item as a tab container. */
|
|
1661
|
+
type: "tabs";
|
|
1662
|
+
/** List of tabs in this container. */
|
|
1663
|
+
tabs: DetailTab[];
|
|
1664
|
+
/** Tab container options. */
|
|
1665
|
+
options?: DetailTabsOptions;
|
|
1666
|
+
}
|
|
1398
1667
|
/**
|
|
1399
|
-
*
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
*/
|
|
1410
|
-
interface ViewActionFeatures {
|
|
1411
|
-
/** Enables the "View" preview / read-only drawer button. Defaults to `true`. */
|
|
1412
|
-
view?: boolean;
|
|
1413
|
-
/** Enables the "Edit" document form link. Defaults to `true`. */
|
|
1414
|
-
edit?: boolean;
|
|
1415
|
-
/** Enables the "Duplicate" record action. Defaults to `true`. */
|
|
1416
|
-
duplicate?: boolean;
|
|
1417
|
-
/** Enables the "Delete" record action. Defaults to `true`. */
|
|
1418
|
-
delete?: boolean;
|
|
1419
|
-
/** Enables the "Export selected" CSV action in the bulk action bar. Defaults to `true`. */
|
|
1420
|
-
exportSelected?: boolean;
|
|
1668
|
+
* Configuration options for a sub-grid container.
|
|
1669
|
+
*/
|
|
1670
|
+
interface DetailGridOptions {
|
|
1671
|
+
/** Grid width of the sub-grid container in the surrounding layout. */
|
|
1672
|
+
span?: DetailSpan;
|
|
1673
|
+
/**
|
|
1674
|
+
* Visibility condition for this grid container.
|
|
1675
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1676
|
+
*/
|
|
1677
|
+
visible?: string | boolean;
|
|
1421
1678
|
}
|
|
1422
1679
|
/**
|
|
1423
|
-
*
|
|
1424
|
-
* `'purple' | 'emerald' | 'amber' | 'rose' | 'blue' | 'indigo' | 'cyan' | 'orange'`
|
|
1680
|
+
* Multi-column sub-grid layout inside a section or tab.
|
|
1425
1681
|
*/
|
|
1426
|
-
|
|
1682
|
+
interface DetailGrid {
|
|
1683
|
+
/** Identifies this item as a grid. */
|
|
1684
|
+
type: "grid";
|
|
1685
|
+
/** Number of balanced columns in this grid. */
|
|
1686
|
+
columns: number;
|
|
1687
|
+
/** Child items rendered across the grid columns. */
|
|
1688
|
+
items: DetailItem[];
|
|
1689
|
+
/** Grid container options. */
|
|
1690
|
+
options?: DetailGridOptions;
|
|
1691
|
+
}
|
|
1427
1692
|
/**
|
|
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
|
-
* ```
|
|
1693
|
+
* Configuration options for a repeated array field.
|
|
1441
1694
|
*/
|
|
1442
|
-
interface
|
|
1443
|
-
/**
|
|
1444
|
-
|
|
1445
|
-
/**
|
|
1446
|
-
|
|
1447
|
-
/**
|
|
1448
|
-
|
|
1449
|
-
/**
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1695
|
+
interface DetailRepeatOptions {
|
|
1696
|
+
/** Layout style for repeated items: 'table', 'cards', or 'list'. */
|
|
1697
|
+
layout?: "table" | "cards" | "list";
|
|
1698
|
+
/** Message shown when the repeated array is empty. */
|
|
1699
|
+
emptyText?: string;
|
|
1700
|
+
/** Grid width of the repeated container. */
|
|
1701
|
+
span?: DetailSpan;
|
|
1702
|
+
/**
|
|
1703
|
+
* Visibility condition for this repeat container.
|
|
1704
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1705
|
+
*/
|
|
1706
|
+
visible?: string | boolean;
|
|
1707
|
+
/** Field name in each row to use as the card header title (e.g. 'title', 'key', 'name'). */
|
|
1708
|
+
useAsTitle?: string;
|
|
1709
|
+
/** Field name in each row to use as the card header title (alias for useAsTitle). */
|
|
1710
|
+
titleField?: string;
|
|
1711
|
+
/** Static card title prefix or template (e.g. 'Category' or 'Card #{index}'). */
|
|
1712
|
+
title?: string;
|
|
1713
|
+
/** Optional icon name for card header. */
|
|
1714
|
+
icon?: string;
|
|
1715
|
+
/** Number of grid columns for cards layout (1, 2, 3, or 4; defaults to 3). */
|
|
1716
|
+
columns?: 1 | 2 | 3 | 4;
|
|
1457
1717
|
}
|
|
1458
1718
|
/**
|
|
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
|
-
* ```
|
|
1719
|
+
* Delegated repeated array field item in a Detail View.
|
|
1473
1720
|
*/
|
|
1474
|
-
interface
|
|
1475
|
-
/**
|
|
1476
|
-
|
|
1477
|
-
/**
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
|
|
1481
|
-
/**
|
|
1482
|
-
|
|
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[];
|
|
1721
|
+
interface DetailRepeat {
|
|
1722
|
+
/** Identifies this item as a repeat container. */
|
|
1723
|
+
type: "repeat";
|
|
1724
|
+
/** Array field name in the document. */
|
|
1725
|
+
field: string;
|
|
1726
|
+
/** Item template schemas rendered for each element in the array. */
|
|
1727
|
+
items: DetailItem[];
|
|
1728
|
+
/** Repeat options. */
|
|
1729
|
+
options?: DetailRepeatOptions;
|
|
1495
1730
|
}
|
|
1496
1731
|
/**
|
|
1497
|
-
*
|
|
1732
|
+
* Async or synchronous handler function calculating a computed metric.
|
|
1498
1733
|
*/
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
/**
|
|
1509
|
-
|
|
1510
|
-
/**
|
|
1511
|
-
|
|
1512
|
-
/**
|
|
1513
|
-
|
|
1514
|
-
/**
|
|
1515
|
-
|
|
1516
|
-
/**
|
|
1517
|
-
|
|
1518
|
-
/**
|
|
1519
|
-
|
|
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;
|
|
1734
|
+
type ComputedHandler<TDoc = any> = (context: {
|
|
1735
|
+
doc: TDoc;
|
|
1736
|
+
user?: any;
|
|
1737
|
+
db?: any;
|
|
1738
|
+
}) => any | Promise<any>;
|
|
1739
|
+
/**
|
|
1740
|
+
* Configuration options for a computed value card.
|
|
1741
|
+
*/
|
|
1742
|
+
interface DetailComputedOptions<TDoc = any> {
|
|
1743
|
+
/** Unique identifier for the computed metric. */
|
|
1744
|
+
id?: string;
|
|
1745
|
+
/** JEXL expression string evaluated against `{ doc, user }`. */
|
|
1746
|
+
expression?: string;
|
|
1747
|
+
/** Async or sync function receiving `{ doc, user, db }` returning the computed value. */
|
|
1748
|
+
handler?: ComputedHandler<TDoc>;
|
|
1749
|
+
/** Grid width for the computed card. */
|
|
1750
|
+
span?: DetailSpan;
|
|
1751
|
+
/** Formatting preset for the computed value ('currency', 'percent', 'number', 'date'). */
|
|
1752
|
+
format?: string;
|
|
1753
|
+
/** Currency code when format is 'currency'. */
|
|
1754
|
+
currency?: string;
|
|
1529
1755
|
/**
|
|
1530
|
-
*
|
|
1531
|
-
*
|
|
1756
|
+
* Visibility condition for this computed card.
|
|
1757
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1532
1758
|
*/
|
|
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;
|
|
1759
|
+
visible?: string | boolean;
|
|
1538
1760
|
}
|
|
1539
1761
|
/**
|
|
1540
|
-
*
|
|
1762
|
+
* Computed KPI or metric card in a Detail View.
|
|
1541
1763
|
*/
|
|
1542
|
-
interface
|
|
1543
|
-
/**
|
|
1544
|
-
|
|
1545
|
-
/**
|
|
1764
|
+
interface DetailComputed<TDoc = any> {
|
|
1765
|
+
/** Identifies this item as a computed value. */
|
|
1766
|
+
type: "computed";
|
|
1767
|
+
/** Unique computed identifier. */
|
|
1768
|
+
id?: string;
|
|
1769
|
+
/** Human-readable card label. */
|
|
1546
1770
|
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;
|
|
1771
|
+
/** JEXL evaluation string. */
|
|
1772
|
+
expression?: string;
|
|
1773
|
+
/** Computed function handler. */
|
|
1774
|
+
handler?: ComputedHandler<TDoc>;
|
|
1775
|
+
/** Computed options. */
|
|
1776
|
+
options?: DetailComputedOptions<TDoc>;
|
|
1559
1777
|
}
|
|
1560
1778
|
/**
|
|
1561
|
-
*
|
|
1779
|
+
* Configuration options for a horizontal divider line.
|
|
1562
1780
|
*/
|
|
1563
|
-
interface
|
|
1564
|
-
/**
|
|
1565
|
-
|
|
1566
|
-
/**
|
|
1567
|
-
|
|
1781
|
+
interface DetailDividerOptions {
|
|
1782
|
+
/** Grid span in the surrounding layout. */
|
|
1783
|
+
span?: DetailSpan;
|
|
1784
|
+
/**
|
|
1785
|
+
* Visibility condition for this divider.
|
|
1786
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1787
|
+
*/
|
|
1788
|
+
visible?: string | boolean;
|
|
1789
|
+
/** Vertical margin spacing around the divider line. */
|
|
1790
|
+
spacing?: "sm" | "md" | "lg" | "none";
|
|
1568
1791
|
}
|
|
1569
1792
|
/**
|
|
1570
|
-
*
|
|
1793
|
+
* Horizontal divider line in a Detail View layout.
|
|
1571
1794
|
*/
|
|
1572
|
-
interface
|
|
1573
|
-
/**
|
|
1574
|
-
|
|
1575
|
-
/**
|
|
1576
|
-
|
|
1795
|
+
interface DetailDivider {
|
|
1796
|
+
/** Identifies this item as a divider. */
|
|
1797
|
+
type: "divider";
|
|
1798
|
+
/** Divider options. */
|
|
1799
|
+
options?: DetailDividerOptions;
|
|
1577
1800
|
}
|
|
1578
1801
|
/**
|
|
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.
|
|
1802
|
+
* Configuration options for a static text or callout block.
|
|
1585
1803
|
*/
|
|
1586
|
-
interface
|
|
1587
|
-
/**
|
|
1588
|
-
|
|
1589
|
-
/**
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1804
|
+
interface DetailTextOptions {
|
|
1805
|
+
/** Grid width in the 12-column layout. */
|
|
1806
|
+
span?: DetailSpan;
|
|
1807
|
+
/**
|
|
1808
|
+
* Visibility condition for this text block.
|
|
1809
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1810
|
+
*/
|
|
1811
|
+
visible?: string | boolean;
|
|
1812
|
+
/** Typography and alert styling variant ('body', 'heading', 'subheading', 'muted', 'caption', 'callout', 'info', 'warning'). */
|
|
1813
|
+
variant?: "body" | "heading" | "subheading" | "muted" | "caption" | "callout" | "info" | "warning";
|
|
1814
|
+
/** Custom CSS or Tailwind classes applied to the text wrapper. */
|
|
1815
|
+
className?: string;
|
|
1597
1816
|
}
|
|
1598
1817
|
/**
|
|
1599
|
-
*
|
|
1818
|
+
* Static text, heading, callout, or notice block in a Detail View.
|
|
1600
1819
|
*/
|
|
1601
|
-
interface
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1820
|
+
interface DetailText {
|
|
1821
|
+
/** Identifies this item as a text block. */
|
|
1822
|
+
type: "text";
|
|
1823
|
+
/** Text or markdown content. */
|
|
1824
|
+
content: string;
|
|
1825
|
+
/** Text options. */
|
|
1826
|
+
options?: DetailTextOptions;
|
|
1606
1827
|
}
|
|
1607
1828
|
/**
|
|
1608
|
-
*
|
|
1829
|
+
* Configuration options for a custom React component slot.
|
|
1609
1830
|
*/
|
|
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;
|
|
1831
|
+
interface DetailCustomOptions<TDoc = any> {
|
|
1832
|
+
/** Grid span in the 12-column layout. */
|
|
1833
|
+
span?: DetailSpan;
|
|
1630
1834
|
/**
|
|
1631
|
-
*
|
|
1632
|
-
*
|
|
1835
|
+
* Visibility condition for this custom component.
|
|
1836
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1633
1837
|
*/
|
|
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;
|
|
1838
|
+
visible?: string | boolean;
|
|
1839
|
+
/** Static or initial props passed into the custom component. */
|
|
1840
|
+
props?: Record<string, any>;
|
|
1841
|
+
/** Inline render function receiving `{ doc, user }` (Self-hosted React runtimes). */
|
|
1842
|
+
render?: (context: {
|
|
1843
|
+
doc: TDoc;
|
|
1844
|
+
user?: any;
|
|
1845
|
+
[key: string]: any;
|
|
1846
|
+
}) => any;
|
|
1667
1847
|
}
|
|
1668
|
-
/**
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1848
|
+
/**
|
|
1849
|
+
* Custom React component slot mounted in a Detail View.
|
|
1850
|
+
*/
|
|
1851
|
+
interface DetailCustom<TDoc = any> {
|
|
1852
|
+
/** Identifies this item as a custom component. */
|
|
1853
|
+
type: "custom";
|
|
1854
|
+
/** Registered custom component name. */
|
|
1855
|
+
name: string;
|
|
1856
|
+
/** Custom component options. */
|
|
1857
|
+
options?: DetailCustomOptions<TDoc>;
|
|
1673
1858
|
}
|
|
1674
1859
|
/**
|
|
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
|
-
* ```
|
|
1860
|
+
* Configuration options for rendering an action button in a Detail View.
|
|
1691
1861
|
*/
|
|
1692
|
-
|
|
1862
|
+
interface DetailActionOptions {
|
|
1863
|
+
/** Grid column span across the 12-column grid. */
|
|
1864
|
+
span?: DetailSpan;
|
|
1865
|
+
/** Button visual style. Defaults to `'outline'`. */
|
|
1866
|
+
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive";
|
|
1867
|
+
/** Button size. Defaults to `'sm'`. */
|
|
1868
|
+
size?: "sm" | "default";
|
|
1869
|
+
/** Overrides the action's own `label` for this placement. */
|
|
1870
|
+
label?: string;
|
|
1871
|
+
/**
|
|
1872
|
+
* Visibility condition for this action item.
|
|
1873
|
+
* Can be a boolean or a JEXL expression evaluated against `{ doc, user }`.
|
|
1874
|
+
*/
|
|
1875
|
+
visible?: string | boolean;
|
|
1876
|
+
}
|
|
1693
1877
|
/**
|
|
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
|
-
* ```
|
|
1878
|
+
* Renders a button for a named action from `collection.actions` at this
|
|
1879
|
+
* position in a Detail View. The same action (and its confirm dialog, modal
|
|
1880
|
+
* fields, and execution) can also render automatically in the Detail View's
|
|
1881
|
+
* header toolbar when the action's `type` is `'header'` — placing it here
|
|
1882
|
+
* too does not duplicate that config, it just adds another entry point to
|
|
1883
|
+
* the same action.
|
|
1707
1884
|
*/
|
|
1708
|
-
interface
|
|
1709
|
-
/**
|
|
1885
|
+
interface DetailAction {
|
|
1886
|
+
/** Identifies this item as an action button. */
|
|
1887
|
+
type: "action";
|
|
1888
|
+
/** Name of the action, matching an entry in `collection.actions`. */
|
|
1710
1889
|
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;
|
|
1890
|
+
/** Display and visibility options for this placement. */
|
|
1891
|
+
options?: DetailActionOptions;
|
|
1727
1892
|
}
|
|
1728
1893
|
/**
|
|
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
|
-
* ```
|
|
1894
|
+
* Union of all valid item types in a Detail View schema.
|
|
1766
1895
|
*/
|
|
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;
|
|
1896
|
+
type DetailItem<TDoc = any> = DetailSection | DetailTabs | DetailGrid | DetailField | DetailRepeat | DetailComputed<TDoc> | DetailDivider | DetailText | DetailCustom<TDoc> | DetailAction | string;
|
|
1783
1897
|
/**
|
|
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
|
-
* ```
|
|
1898
|
+
* Detail View layout schema definition for a collection or global.
|
|
1797
1899
|
*/
|
|
1798
|
-
|
|
1900
|
+
type DetailSchema<TDoc = any> = DetailItem<TDoc>[];
|
|
1799
1901
|
|
|
1800
1902
|
/**
|
|
1801
1903
|
* Configures account lockout behavior for an auth-enabled collection.
|
|
@@ -1835,6 +1937,30 @@ interface AuthConfig {
|
|
|
1835
1937
|
*/
|
|
1836
1938
|
adminRole?: string;
|
|
1837
1939
|
}
|
|
1940
|
+
/**
|
|
1941
|
+
* Physical database index specification for a collection.
|
|
1942
|
+
*/
|
|
1943
|
+
interface CollectionIndex {
|
|
1944
|
+
/** Optional custom index name. If omitted, adapter auto-generates one. */
|
|
1945
|
+
name?: string;
|
|
1946
|
+
/** Field names participating in the index. */
|
|
1947
|
+
fields: string[];
|
|
1948
|
+
/** Whether the index enforces database-level uniqueness. Defaults to false. */
|
|
1949
|
+
unique?: boolean;
|
|
1950
|
+
/** Whether to only index non-null rows where supported. */
|
|
1951
|
+
sparse?: boolean;
|
|
1952
|
+
}
|
|
1953
|
+
/**
|
|
1954
|
+
* Atomic numeric update operators for database mutation payloads.
|
|
1955
|
+
*/
|
|
1956
|
+
interface NumericUpdateOperator {
|
|
1957
|
+
increment?: number;
|
|
1958
|
+
decrement?: number;
|
|
1959
|
+
}
|
|
1960
|
+
/**
|
|
1961
|
+
* Strategy for generating document IDs.
|
|
1962
|
+
*/
|
|
1963
|
+
type IdStrategy = "prefixed-nanoid" | "nanoid" | "ulid" | "uuid";
|
|
1838
1964
|
/**
|
|
1839
1965
|
* Use this contract when you want the exact shape of a collection config.
|
|
1840
1966
|
*
|
|
@@ -1960,6 +2086,31 @@ interface CollectionConfig<TDoc extends object = Record<string, unknown>> {
|
|
|
1960
2086
|
* @see {@link https://dyrected.com/docs/model-content/fields/blocks Blocks and page sections}
|
|
1961
2087
|
*/
|
|
1962
2088
|
fields: Field[];
|
|
2089
|
+
/**
|
|
2090
|
+
* Database indexes to create on this collection.
|
|
2091
|
+
*
|
|
2092
|
+
* Fields participating in indexes are automatically promoted to physical columns.
|
|
2093
|
+
*/
|
|
2094
|
+
indexes?: CollectionIndex[];
|
|
2095
|
+
/**
|
|
2096
|
+
* Optional custom prefix for auto-generated document IDs (e.g. `'usr'`, `'cob'`, `'sub'`).
|
|
2097
|
+
* When using the default prefixed ID generator, IDs will follow the format `${idPrefix}_${random}`.
|
|
2098
|
+
*/
|
|
2099
|
+
idPrefix?: string;
|
|
2100
|
+
/**
|
|
2101
|
+
* Strategy for generating document IDs when not explicitly provided.
|
|
2102
|
+
* - `'prefixed-nanoid'`: Stripe-style prefixed NanoID (default), e.g. `cob_8xK2p9LmQwRt9a`
|
|
2103
|
+
* - `'nanoid'`: Compact URL-friendly random ID, e.g. `V1StGXR8_Z5jdHi6B-myT`
|
|
2104
|
+
* - `'ulid'`: 26-character Crockford Base32 time-sortable ID, e.g. `01J8K3R4Q7V9N2M1P6W0XYZA3C`
|
|
2105
|
+
* - `'uuid'`: 36-character RFC 4122 UUIDv4, e.g. `f47ac10b-58cc-4372-a567-0e02b2c3d479`
|
|
2106
|
+
*
|
|
2107
|
+
* Defaults to `'prefixed-nanoid'`.
|
|
2108
|
+
*/
|
|
2109
|
+
idType?: IdStrategy;
|
|
2110
|
+
/**
|
|
2111
|
+
* Custom function to generate document IDs. Overrides `idType` and `idPrefix`.
|
|
2112
|
+
*/
|
|
2113
|
+
idGenerator?: (slug: string) => string;
|
|
1963
2114
|
/**
|
|
1964
2115
|
* If `true`, Dyrected automatically adds the built-in system fields
|
|
1965
2116
|
* `createdAt`, `updatedAt`, `createdBy`, and `updatedBy` to every document.
|
|
@@ -2113,6 +2264,10 @@ interface CollectionConfig<TDoc extends object = Record<string, unknown>> {
|
|
|
2113
2264
|
* Collections with the same `group` are visually grouped together.
|
|
2114
2265
|
*/
|
|
2115
2266
|
group?: string;
|
|
2267
|
+
/**
|
|
2268
|
+
* Numeric sort order within navigation or sidebar group (lower numbers appear first).
|
|
2269
|
+
*/
|
|
2270
|
+
order?: number;
|
|
2116
2271
|
/**
|
|
2117
2272
|
* Slug of the view to render by default when navigating to `/collections/:slug`.
|
|
2118
2273
|
* If not specified, defaults to the view with `default: true` or the all-records table view.
|
|
@@ -2376,6 +2531,10 @@ interface GlobalConfig<TDoc extends object = Record<string, unknown>> {
|
|
|
2376
2531
|
icon?: AdminIconName;
|
|
2377
2532
|
/** Groups this global under a named section in the Admin sidebar. */
|
|
2378
2533
|
group?: string;
|
|
2534
|
+
/**
|
|
2535
|
+
* Numeric sort order within navigation or sidebar group (lower numbers appear first).
|
|
2536
|
+
*/
|
|
2537
|
+
order?: number;
|
|
2379
2538
|
/** If `true`, this global is not shown in the Admin UI sidebar. */
|
|
2380
2539
|
hidden?: boolean;
|
|
2381
2540
|
};
|
|
@@ -2424,21 +2583,26 @@ interface DatabaseAdapter {
|
|
|
2424
2583
|
* ignore it; SQL adapters use it to sort numeric fields by magnitude.
|
|
2425
2584
|
*/
|
|
2426
2585
|
fields?: Field[];
|
|
2586
|
+
/** Row-level locking strategy (e.g. SELECT ... FOR UPDATE in transactions). */
|
|
2587
|
+
lock?: "for-update";
|
|
2427
2588
|
}): Promise<PaginatedResult>;
|
|
2428
2589
|
/** Find a single document by its ID. Returns `null` if not found. */
|
|
2429
2590
|
findOne(args: {
|
|
2430
2591
|
collection: string;
|
|
2431
2592
|
id: string;
|
|
2593
|
+
/** Row-level locking strategy (e.g. SELECT ... FOR UPDATE in transactions). */
|
|
2594
|
+
lock?: "for-update";
|
|
2432
2595
|
}): Promise<BaseDocument | null>;
|
|
2433
2596
|
/** Insert a new document and return it with its generated `id`. */
|
|
2434
2597
|
create(args: {
|
|
2435
2598
|
collection: string;
|
|
2436
2599
|
data: Record<string, unknown>;
|
|
2437
2600
|
}): Promise<BaseDocument>;
|
|
2438
|
-
/** Update a document by ID and return the updated document. */
|
|
2601
|
+
/** Update a document by ID or conditional filter and return the updated document. */
|
|
2439
2602
|
update(args: {
|
|
2440
2603
|
collection: string;
|
|
2441
|
-
id
|
|
2604
|
+
id?: string;
|
|
2605
|
+
where?: Record<string, unknown>;
|
|
2442
2606
|
data: Record<string, unknown>;
|
|
2443
2607
|
}): Promise<BaseDocument>;
|
|
2444
2608
|
/** Delete a document by ID. Return value is intentionally untyped — callers do not use it. */
|
|
@@ -3900,4 +4064,4 @@ interface DyrectedContext {
|
|
|
3900
4064
|
*/
|
|
3901
4065
|
declare function createDyrectedApp(rawConfig: DyrectedConfig | any): Promise<Hono<DyrectedContext, hono_types.BlankSchema, "/">>;
|
|
3902
4066
|
|
|
3903
|
-
export { type
|
|
4067
|
+
export { type DateField as $, type AdminAuthConfig as A, type Block as B, type CollectionConfig as C, type DyrectedConfig as D, type DetailTabs as E, type Field as F, type GlobalConfig as G, type HookRequestContext as H, type DetailTextOptions as I, type DetailText as J, type DetailSchema as K, type LifecycleEventName as L, type DyrectedContext as M, type AIConfig as N, type AIPIIConfig as O, type PublicAdminAuthConfig as P, type IdStrategy as Q, type CompiledNavTree as R, type CompiledNavItem as S, type DefineWorkspaceOptions as T, type UserNavigationPreferences as U, type ArrayField as V, type WorkflowConfig as W, type FieldType as X, type BooleanField as Y, type AuthConfig as Z, type AccessPolicyResolver as _, type DeclarativeHookExpression as a, type AggregateResult as a$, type DateTimeField as a0, type EmailField as a1, type IconField as a2, type ImageField as a3, type JoinField as a4, type JsonField as a5, type MultiSelectField as a6, type NumberField as a7, type ObjectField as a8, type RadioField as a9, type AccessConfig as aA, type AccessFunction as aB, type AccessFunctionArgs as aC, type AccessResult as aD, type AccessRule as aE, type ActionConfig as aF, type ActionConfigBase as aG, type ActionConfigWithHandler as aH, type ActionConfigWithMutation as aI, type ActionContext as aJ, type ActionType as aK, type AdminAuthAccessResolution as aL, type AdminAuthClaimMapping as aM, type AdminAuthMember as aN, type AdminAuthProvider as aO, type AdminAuthProviderMembersConfig as aP, type AdminAuthProvisioningMode as aQ, type AdminAuthResolveAccessArgs as aR, type AdminAuthResolvedIdentity as aS, type AdminConfig as aT, type AdminDashboardComponentSlots as aU, type AdminIconName as aV, type AggregateArgs as aW, type AggregateCastType as aX, type AggregateCollectionResult as aY, type AggregateInput as aZ, type AggregateOperation as a_, type RelationshipField as aa, type RichTextField as ab, type RowField as ac, type SelectField as ad, type TextField as ae, type TextareaField as af, type TimeField as ag, type UrlField as ah, type AIAction as ai, type AIActionStatus as aj, type AIActionType as ak, type AIAuditActionType as al, type AIAuditRecord as am, type AIChunk as an, type AIMessage as ao, type AIPIIPattern as ap, type AIRateLimitResult as aq, type AIRateLimitStore as ar, type AIThread as as, type AIToolContext as at, type AIToolDefinition as au, AI_ACTIONS_COLLECTION as av, AI_AUDIT_COLLECTION as aw, AI_CHUNKS_COLLECTION as ax, AI_MESSAGES_COLLECTION as ay, AI_THREADS_COLLECTION as az, type AuthenticatedUser as b, type FieldAfterReadHook as b$, type BaseAdminAuthProvider as b0, type BaseFieldAdmin as b1, type BlockVariant as b2, type BlocksField as b3, type BooleanFieldAdmin as b4, type BooleanFormat as b5, CURRENT_NAV_PREFERENCES_VERSION as b6, type CalendarViewConfig as b7, type CardsViewConfig as b8, type CharacterLimitFieldAdmin as b9, type DefineActionOptions as bA, type DefineCalendarViewOptions as bB, type DefineCardsViewOptions as bC, type DefineGanttViewOptions as bD, type DefineKanbanViewOptions as bE, type DefineTableViewOptions as bF, type DefineViewBaseOptions as bG, type DefineViewOptions as bH, type DetailSpan as bI, type DisplayTone as bJ, type DisplayVariant as bK, type DistinctCountOperation as bL, type DistinctValuesOperation as bM, type DynamicOptionItem as bN, type DynamicOptionsConfig as bO, type DynamicOptionsResolver as bP, type DynamicOptionsResolverArgs as bQ, type DyrectedAIContext as bR, type DyrectedLoggerConfig as bS, type DyrectedObservabilityConfig as bT, type EmailFieldAdmin as bU, type FieldAdminHooks as bV, type FieldAdminOnChangeHook as bW, type FieldAdminOnChangeHookArgs as bX, type FieldAdminOptionsHook as bY, type FieldAdminOptionsHookArgs as bZ, type FieldAdminOptionsHookResult as b_, type CharacterLimitFieldConfig as ba, type CollectionAfterChangeHook as bb, type CollectionAfterDeleteHook as bc, type CollectionAfterReadHook as bd, type CollectionAfterReadHookEntry as be, type CollectionAfterTransitionHook as bf, type CollectionBeforeChangeHook as bg, type CollectionBeforeChangeHookEntry as bh, type CollectionBeforeDeleteHook as bi, type CollectionBeforeReadHook as bj, type CollectionBeforeReadHookEntry as bk, type CollectionBeforeTransitionHook as bl, type CollectionIndex as bm, type CollectionListComponentSlots as bn, type CollectionRAGConfig as bo, type CollectionSchemaResult as bp, type CollectionSummaryResult as bq, type CollectionViewComponentSlots as br, type CompiledNavGroup as bs, type CountOperation as bt, type CustomAdminAuthProvider as bu, DEFAULT_USER_NAV_PREFERENCES as bv, type DatabaseAdapter as bw, type DateFieldAdmin as bx, type DateFormat as by, type DefaultValueContext as bz, type WorkflowTransition as c, type TypedField as c$, type FieldAfterReadHookArgs as c0, type FieldBase as c1, type FieldBeforeChangeHook as c2, type FieldBeforeChangeHookArgs as c3, type FieldHook as c4, type FieldHooks as c5, type FileData as c6, type GanttViewConfig as c7, type GetDocumentResult as c8, type GlobalAfterChangeHook as c9, type NavGroup as cA, type NumberFieldAdmin as cB, type NumberFormat as cC, type NumberLimitFieldAdmin as cD, type NumberLimitFieldConfig as cE, type NumericOperation as cF, type NumericUpdateOperator as cG, type OIDCAdminAuthProvider as cH, type OptionFormat as cI, type PaginatedResult as cJ, type PinnedNavItemRef as cK, type PublicAdminAuthProvider as cL, type QueryCollectionResult as cM, type RAGSearchResult as cN, type RadioFieldAdmin as cO, type RateLimitConfig as cP, type ReadonlyDatabaseAdapter as cQ, type RichTextFeature as cR, type RichTextFieldConfig as cS, type SelectFieldAdmin as cT, type SqlWhereResult as cU, type StorageAdapter as cV, type TableViewConfig as cW, type TextFieldAdmin as cX, type TextFormat as cY, type TextareaFieldAdmin as cZ, type TrustProxyConfig as c_, type GlobalAfterReadHook as ca, type GlobalAfterReadHookEntry as cb, type GlobalBeforeChangeHook as cc, type GlobalBeforeChangeHookEntry as cd, type GlobalBeforeReadHook as ce, type GlobalBeforeReadHookEntry as cf, type GlobalRAGConfig as cg, type GlobalSchemaResult as ch, type GlobalSummaryResult as ci, type HeadingLevel as cj, type HookFunction as ck, type IconFieldAdmin as cl, type ImageService as cm, type ImageTransformOptions as cn, type InferAggregateResult as co, type JoinFieldAdmin as cp, type JsonFieldAdmin as cq, type JsonFormat as cr, type KanbanViewConfig as cs, LIFECYCLE_EVENT_NAMES as ct, type LifecycleEventHandler as cu, type LinkFormat as cv, type MetricColor as cw, type MultiSelectFieldAdmin as cx, type NamedAccessPolicy as cy, type NavBadgeConfig as cz, type LifecycleEvent as d, type UploadConfig as d0, type UrlFieldAdmin as d1, type UrlLinkValue as d2, type ViewActionFeatures as d3, type ViewComponentSlots as d4, type ViewConfig as d5, type ViewConfigBase as d6, type ViewLayout as d7, type ViewMetric as d8, type ViewSubMetric as d9, type ResolvedObservabilityConfig as dA, attachRequestMetrics as dB, bindObservabilityRuntime as dC, buildRequestLogger as dD, captureRequestBody as dE, createDyrectedApp as dF, createObservabilityRuntime as dG, createRequestSpan as dH, decodeCollectionToken as dI, endRequestSpan as dJ, getConfigLogger as dK, getObservabilityRuntime as dL, getRequestLogger as dM, redactBody as dN, redactHeaders as dO, renderPrometheusMetrics as dP, resolveObservabilityConfig as dQ, resolveSessionTokenExpiry as dR, shouldSampleRequest as dS, signCollectionToken as dT, verifyCollectionToken as dU, type WhereClause as da, type WhereOperator as db, type WhereOperatorName as dc, type WordLimitFieldAdmin as dd, type WordLimitFieldConfig as de, type WorkflowMetadata as df, type WorkflowRole as dg, type WorkflowState as dh, type WorkflowTransitionContext as di, defineAction as dj, defineCalendarView as dk, defineCardsView as dl, defineGanttView as dm, defineKanbanView as dn, defineTableView as dp, defineView as dq, defineWorkspace as dr, isAICollection as ds, parseMongoWhere as dt, parseSqlWhere as du, type CollectionTokenPayload as dv, DEFAULT_SESSION_EXPIRY as dw, type DyrectedObservabilityRuntime as dx, type RequestBodyCapture as dy, type RequestTraceContext as dz, type BaseDocument as e, type DetailActionOptions as f, type DetailAction as g, type DetailComputedOptions as h, type ComputedHandler as i, type DetailComputed as j, type DetailCustomOptions as k, type DetailCustom as l, type DetailDividerOptions as m, type DetailDivider as n, type DisplayFieldOptions as o, type DetailField as p, type DetailItem as q, type DetailGridOptions as r, type DetailGrid as s, type DetailRepeatOptions as t, type DetailRepeat as u, type DetailSectionOptions as v, type DetailSection as w, type DetailTabOptions as x, type DetailTab as y, type DetailTabsOptions as z };
|