featuredrop 1.4.0 → 2.2.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.
Files changed (62) hide show
  1. package/README.md +287 -760
  2. package/dist/adapters.cjs +1757 -0
  3. package/dist/adapters.cjs.map +1 -0
  4. package/dist/adapters.d.cts +744 -0
  5. package/dist/adapters.d.ts +744 -0
  6. package/dist/adapters.js +1745 -0
  7. package/dist/adapters.js.map +1 -0
  8. package/dist/admin.cjs +148 -32
  9. package/dist/admin.cjs.map +1 -1
  10. package/dist/admin.d.cts +14 -3
  11. package/dist/admin.d.ts +14 -3
  12. package/dist/admin.js +148 -32
  13. package/dist/admin.js.map +1 -1
  14. package/dist/bridges.cjs +111 -13
  15. package/dist/bridges.cjs.map +1 -1
  16. package/dist/bridges.d.cts +12 -5
  17. package/dist/bridges.d.ts +12 -5
  18. package/dist/bridges.js +111 -13
  19. package/dist/bridges.js.map +1 -1
  20. package/dist/ci.cjs +34 -0
  21. package/dist/ci.cjs.map +1 -1
  22. package/dist/ci.d.cts +5 -1
  23. package/dist/ci.d.ts +5 -1
  24. package/dist/ci.js +34 -1
  25. package/dist/ci.js.map +1 -1
  26. package/dist/cms.cjs +835 -0
  27. package/dist/cms.cjs.map +1 -0
  28. package/dist/cms.d.cts +236 -0
  29. package/dist/cms.d.ts +236 -0
  30. package/dist/cms.js +829 -0
  31. package/dist/cms.js.map +1 -0
  32. package/dist/flags.cjs +27 -7
  33. package/dist/flags.cjs.map +1 -1
  34. package/dist/flags.d.cts +14 -0
  35. package/dist/flags.d.ts +14 -0
  36. package/dist/flags.js +27 -7
  37. package/dist/flags.js.map +1 -1
  38. package/dist/index.cjs +52 -4481
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +1 -1340
  41. package/dist/index.d.ts +1 -1340
  42. package/dist/index.js +53 -4388
  43. package/dist/index.js.map +1 -1
  44. package/dist/markdown.cjs +257 -0
  45. package/dist/markdown.cjs.map +1 -0
  46. package/dist/markdown.d.cts +9 -0
  47. package/dist/markdown.d.ts +9 -0
  48. package/dist/markdown.js +234 -0
  49. package/dist/markdown.js.map +1 -0
  50. package/dist/renderer.cjs +503 -0
  51. package/dist/renderer.cjs.map +1 -0
  52. package/dist/renderer.d.cts +250 -0
  53. package/dist/renderer.d.ts +250 -0
  54. package/dist/renderer.js +501 -0
  55. package/dist/renderer.js.map +1 -0
  56. package/dist/rss.cjs +291 -0
  57. package/dist/rss.cjs.map +1 -0
  58. package/dist/rss.d.cts +158 -0
  59. package/dist/rss.d.ts +158 -0
  60. package/dist/rss.js +268 -0
  61. package/dist/rss.js.map +1 -0
  62. package/package.json +72 -6
package/dist/index.d.cts CHANGED
@@ -1,7 +1,3 @@
1
- import { z } from 'zod';
2
- import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { ReactNode } from 'react';
4
-
5
1
  /** Entry type label — determines default icon/color in UI */
6
2
  type FeatureType = "feature" | "improvement" | "fix" | "breaking";
7
3
  /** Priority level for announcements */
@@ -291,894 +287,6 @@ declare function getFeatureById(manifest: FeatureManifest, id: string): FeatureE
291
287
  */
292
288
  declare function getNewFeaturesByCategory(manifest: FeatureManifest, category: string, storage: StorageAdapter, now?: Date, userContext?: UserContext, matchAudience?: AudienceMatchFn, appVersion?: string): FeatureEntry[];
293
289
 
294
- /**
295
- * Parse a feature description from markdown into sanitized HTML.
296
- * - Uses `marked` when installed (optional peer dep)
297
- * - Falls back to a tiny built-in parser when `marked` is absent
298
- * - Strips script tags, event handlers, and javascript:/data: URLs
299
- */
300
- declare function parseDescription(markdown: string): string;
301
-
302
- interface ChangelogRendererOptions {
303
- manifest: FeatureManifest;
304
- storage: StorageAdapter;
305
- userContext?: UserContext;
306
- matchAudience?: AudienceMatchFn;
307
- appVersion?: string;
308
- flagBridge?: FeatureFlagBridge;
309
- product?: string;
310
- now?: () => Date;
311
- }
312
- interface ChangelogRendererState {
313
- manifest: FeatureManifest;
314
- newFeatures: FeatureEntry[];
315
- newFeaturesSorted: FeatureEntry[];
316
- newCount: number;
317
- watermark: string | null;
318
- dismissedIds: ReadonlySet<string>;
319
- }
320
- interface ChangelogRendererActions {
321
- refresh: () => void;
322
- dismiss: (id: string) => void;
323
- dismissAll: () => Promise<void>;
324
- setManifest: (manifest: FeatureManifest) => void;
325
- setUserContext: (userContext?: UserContext) => void;
326
- setAppVersion: (appVersion?: string) => void;
327
- setAudienceMatcher: (matchAudience?: AudienceMatchFn) => void;
328
- setFlagBridge: (flagBridge?: FeatureFlagBridge) => void;
329
- setProduct: (product?: string) => void;
330
- }
331
- interface ChangelogRendererComputed {
332
- isNew: (sidebarKey: string) => boolean;
333
- getFeature: (sidebarKey: string) => FeatureEntry | undefined;
334
- getFeatureById: (id: string) => FeatureEntry | undefined;
335
- getFeaturesByCategory: (category: string) => FeatureEntry[];
336
- }
337
- interface ChangelogRenderer {
338
- readonly state: ChangelogRendererState;
339
- readonly actions: ChangelogRendererActions;
340
- readonly computed: ChangelogRendererComputed;
341
- subscribe: (listener: (state: ChangelogRendererState) => void) => () => void;
342
- }
343
- declare function createChangelogRenderer({ manifest: initialManifest, storage, userContext: initialUserContext, matchAudience: initialMatchAudience, appVersion: initialAppVersion, flagBridge: initialFlagBridge, product: initialProduct, now, }: ChangelogRendererOptions): ChangelogRenderer;
344
-
345
- interface SlackBridgeOptions {
346
- webhookUrl: string;
347
- username?: string;
348
- iconEmoji?: string;
349
- channel?: string;
350
- formatter?: (feature: FeatureEntry) => Record<string, unknown>;
351
- }
352
- declare const SlackBridge: {
353
- notify(feature: FeatureEntry, options: SlackBridgeOptions): Promise<void>;
354
- };
355
- interface DiscordBridgeOptions {
356
- webhookUrl: string;
357
- username?: string;
358
- avatarUrl?: string;
359
- formatter?: (feature: FeatureEntry) => Record<string, unknown>;
360
- }
361
- declare const DiscordBridge: {
362
- notify(feature: FeatureEntry, options: DiscordBridgeOptions): Promise<void>;
363
- };
364
- interface WebhookBridgeOptions {
365
- url: string;
366
- headers?: Record<string, string>;
367
- event?: string;
368
- body?: Record<string, unknown>;
369
- }
370
- declare const WebhookBridge: {
371
- post(feature: FeatureEntry, options: WebhookBridgeOptions): Promise<void>;
372
- };
373
- interface EmailDigestGeneratorOptions {
374
- title?: string;
375
- intro?: string;
376
- template?: "default" | "minimal";
377
- productName?: string;
378
- }
379
- declare const EmailDigestGenerator: {
380
- generate(features: readonly FeatureEntry[], options?: EmailDigestGeneratorOptions): string;
381
- };
382
- interface RSSFeedGeneratorOptions {
383
- title?: string;
384
- link?: string;
385
- description?: string;
386
- }
387
- declare const RSSFeedGenerator: {
388
- generate(manifest: FeatureManifest, options?: RSSFeedGeneratorOptions): string;
389
- };
390
-
391
- interface ValidationIssue {
392
- path: string;
393
- message: string;
394
- code: "invalid_type" | "missing_required" | "invalid_value" | "invalid_date" | "duplicate_id" | "circular_dependency";
395
- }
396
- interface ValidationResult {
397
- valid: boolean;
398
- errors: ValidationIssue[];
399
- }
400
- declare const featureEntryJsonSchema: {
401
- readonly type: "object";
402
- readonly required: readonly ["id", "label", "releasedAt", "showNewUntil"];
403
- readonly properties: {
404
- readonly id: {
405
- readonly type: "string";
406
- };
407
- readonly label: {
408
- readonly type: "string";
409
- };
410
- readonly description: {
411
- readonly type: "string";
412
- };
413
- readonly releasedAt: {
414
- readonly type: "string";
415
- readonly format: "date-time";
416
- };
417
- readonly showNewUntil: {
418
- readonly type: "string";
419
- readonly format: "date-time";
420
- };
421
- readonly flagKey: {
422
- readonly type: "string";
423
- };
424
- readonly product: {
425
- readonly type: "string";
426
- };
427
- readonly url: {
428
- readonly type: "string";
429
- };
430
- readonly image: {
431
- readonly type: "string";
432
- };
433
- readonly type: {
434
- readonly enum: readonly ["feature", "improvement", "fix", "breaking"];
435
- };
436
- readonly priority: {
437
- readonly enum: readonly ["critical", "normal", "low"];
438
- };
439
- readonly cta: {
440
- readonly type: "object";
441
- readonly properties: {
442
- readonly label: {
443
- readonly type: "string";
444
- };
445
- readonly url: {
446
- readonly type: "string";
447
- };
448
- };
449
- };
450
- readonly meta: {
451
- readonly type: "object";
452
- };
453
- };
454
- };
455
- declare const featureManifestJsonSchema: {
456
- readonly type: "array";
457
- readonly items: {
458
- readonly type: "object";
459
- readonly required: readonly ["id", "label", "releasedAt", "showNewUntil"];
460
- readonly properties: {
461
- readonly id: {
462
- readonly type: "string";
463
- };
464
- readonly label: {
465
- readonly type: "string";
466
- };
467
- readonly description: {
468
- readonly type: "string";
469
- };
470
- readonly releasedAt: {
471
- readonly type: "string";
472
- readonly format: "date-time";
473
- };
474
- readonly showNewUntil: {
475
- readonly type: "string";
476
- readonly format: "date-time";
477
- };
478
- readonly flagKey: {
479
- readonly type: "string";
480
- };
481
- readonly product: {
482
- readonly type: "string";
483
- };
484
- readonly url: {
485
- readonly type: "string";
486
- };
487
- readonly image: {
488
- readonly type: "string";
489
- };
490
- readonly type: {
491
- readonly enum: readonly ["feature", "improvement", "fix", "breaking"];
492
- };
493
- readonly priority: {
494
- readonly enum: readonly ["critical", "normal", "low"];
495
- };
496
- readonly cta: {
497
- readonly type: "object";
498
- readonly properties: {
499
- readonly label: {
500
- readonly type: "string";
501
- };
502
- readonly url: {
503
- readonly type: "string";
504
- };
505
- };
506
- };
507
- readonly meta: {
508
- readonly type: "object";
509
- };
510
- };
511
- };
512
- };
513
- declare const featureEntrySchema: z.ZodObject<{
514
- id: z.ZodString;
515
- label: z.ZodString;
516
- releasedAt: z.ZodEffects<z.ZodString, string, string>;
517
- showNewUntil: z.ZodEffects<z.ZodString, string, string>;
518
- description: z.ZodOptional<z.ZodString>;
519
- flagKey: z.ZodOptional<z.ZodString>;
520
- product: z.ZodOptional<z.ZodString>;
521
- url: z.ZodOptional<z.ZodString>;
522
- image: z.ZodOptional<z.ZodString>;
523
- type: z.ZodOptional<z.ZodEnum<["feature", "improvement", "fix", "breaking"]>>;
524
- priority: z.ZodOptional<z.ZodEnum<["critical", "normal", "low"]>>;
525
- cta: z.ZodOptional<z.ZodObject<{
526
- label: z.ZodString;
527
- url: z.ZodString;
528
- }, "strip", z.ZodTypeAny, {
529
- label: string;
530
- url: string;
531
- }, {
532
- label: string;
533
- url: string;
534
- }>>;
535
- meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
536
- dependsOn: z.ZodOptional<z.ZodObject<{
537
- seen: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
538
- clicked: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
539
- dismissed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
540
- }, "strip", z.ZodTypeAny, {
541
- seen?: string[] | undefined;
542
- clicked?: string[] | undefined;
543
- dismissed?: string[] | undefined;
544
- }, {
545
- seen?: string[] | undefined;
546
- clicked?: string[] | undefined;
547
- dismissed?: string[] | undefined;
548
- }>>;
549
- }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
550
- id: z.ZodString;
551
- label: z.ZodString;
552
- releasedAt: z.ZodEffects<z.ZodString, string, string>;
553
- showNewUntil: z.ZodEffects<z.ZodString, string, string>;
554
- description: z.ZodOptional<z.ZodString>;
555
- flagKey: z.ZodOptional<z.ZodString>;
556
- product: z.ZodOptional<z.ZodString>;
557
- url: z.ZodOptional<z.ZodString>;
558
- image: z.ZodOptional<z.ZodString>;
559
- type: z.ZodOptional<z.ZodEnum<["feature", "improvement", "fix", "breaking"]>>;
560
- priority: z.ZodOptional<z.ZodEnum<["critical", "normal", "low"]>>;
561
- cta: z.ZodOptional<z.ZodObject<{
562
- label: z.ZodString;
563
- url: z.ZodString;
564
- }, "strip", z.ZodTypeAny, {
565
- label: string;
566
- url: string;
567
- }, {
568
- label: string;
569
- url: string;
570
- }>>;
571
- meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
572
- dependsOn: z.ZodOptional<z.ZodObject<{
573
- seen: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
574
- clicked: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
575
- dismissed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
576
- }, "strip", z.ZodTypeAny, {
577
- seen?: string[] | undefined;
578
- clicked?: string[] | undefined;
579
- dismissed?: string[] | undefined;
580
- }, {
581
- seen?: string[] | undefined;
582
- clicked?: string[] | undefined;
583
- dismissed?: string[] | undefined;
584
- }>>;
585
- }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
586
- id: z.ZodString;
587
- label: z.ZodString;
588
- releasedAt: z.ZodEffects<z.ZodString, string, string>;
589
- showNewUntil: z.ZodEffects<z.ZodString, string, string>;
590
- description: z.ZodOptional<z.ZodString>;
591
- flagKey: z.ZodOptional<z.ZodString>;
592
- product: z.ZodOptional<z.ZodString>;
593
- url: z.ZodOptional<z.ZodString>;
594
- image: z.ZodOptional<z.ZodString>;
595
- type: z.ZodOptional<z.ZodEnum<["feature", "improvement", "fix", "breaking"]>>;
596
- priority: z.ZodOptional<z.ZodEnum<["critical", "normal", "low"]>>;
597
- cta: z.ZodOptional<z.ZodObject<{
598
- label: z.ZodString;
599
- url: z.ZodString;
600
- }, "strip", z.ZodTypeAny, {
601
- label: string;
602
- url: string;
603
- }, {
604
- label: string;
605
- url: string;
606
- }>>;
607
- meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
608
- dependsOn: z.ZodOptional<z.ZodObject<{
609
- seen: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
610
- clicked: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
611
- dismissed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
612
- }, "strip", z.ZodTypeAny, {
613
- seen?: string[] | undefined;
614
- clicked?: string[] | undefined;
615
- dismissed?: string[] | undefined;
616
- }, {
617
- seen?: string[] | undefined;
618
- clicked?: string[] | undefined;
619
- dismissed?: string[] | undefined;
620
- }>>;
621
- }, z.ZodTypeAny, "passthrough">>;
622
- declare const featureManifestSchema: z.ZodArray<z.ZodObject<{
623
- id: z.ZodString;
624
- label: z.ZodString;
625
- releasedAt: z.ZodEffects<z.ZodString, string, string>;
626
- showNewUntil: z.ZodEffects<z.ZodString, string, string>;
627
- description: z.ZodOptional<z.ZodString>;
628
- flagKey: z.ZodOptional<z.ZodString>;
629
- product: z.ZodOptional<z.ZodString>;
630
- url: z.ZodOptional<z.ZodString>;
631
- image: z.ZodOptional<z.ZodString>;
632
- type: z.ZodOptional<z.ZodEnum<["feature", "improvement", "fix", "breaking"]>>;
633
- priority: z.ZodOptional<z.ZodEnum<["critical", "normal", "low"]>>;
634
- cta: z.ZodOptional<z.ZodObject<{
635
- label: z.ZodString;
636
- url: z.ZodString;
637
- }, "strip", z.ZodTypeAny, {
638
- label: string;
639
- url: string;
640
- }, {
641
- label: string;
642
- url: string;
643
- }>>;
644
- meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
645
- dependsOn: z.ZodOptional<z.ZodObject<{
646
- seen: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
647
- clicked: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
648
- dismissed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
649
- }, "strip", z.ZodTypeAny, {
650
- seen?: string[] | undefined;
651
- clicked?: string[] | undefined;
652
- dismissed?: string[] | undefined;
653
- }, {
654
- seen?: string[] | undefined;
655
- clicked?: string[] | undefined;
656
- dismissed?: string[] | undefined;
657
- }>>;
658
- }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
659
- id: z.ZodString;
660
- label: z.ZodString;
661
- releasedAt: z.ZodEffects<z.ZodString, string, string>;
662
- showNewUntil: z.ZodEffects<z.ZodString, string, string>;
663
- description: z.ZodOptional<z.ZodString>;
664
- flagKey: z.ZodOptional<z.ZodString>;
665
- product: z.ZodOptional<z.ZodString>;
666
- url: z.ZodOptional<z.ZodString>;
667
- image: z.ZodOptional<z.ZodString>;
668
- type: z.ZodOptional<z.ZodEnum<["feature", "improvement", "fix", "breaking"]>>;
669
- priority: z.ZodOptional<z.ZodEnum<["critical", "normal", "low"]>>;
670
- cta: z.ZodOptional<z.ZodObject<{
671
- label: z.ZodString;
672
- url: z.ZodString;
673
- }, "strip", z.ZodTypeAny, {
674
- label: string;
675
- url: string;
676
- }, {
677
- label: string;
678
- url: string;
679
- }>>;
680
- meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
681
- dependsOn: z.ZodOptional<z.ZodObject<{
682
- seen: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
683
- clicked: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
684
- dismissed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
685
- }, "strip", z.ZodTypeAny, {
686
- seen?: string[] | undefined;
687
- clicked?: string[] | undefined;
688
- dismissed?: string[] | undefined;
689
- }, {
690
- seen?: string[] | undefined;
691
- clicked?: string[] | undefined;
692
- dismissed?: string[] | undefined;
693
- }>>;
694
- }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
695
- id: z.ZodString;
696
- label: z.ZodString;
697
- releasedAt: z.ZodEffects<z.ZodString, string, string>;
698
- showNewUntil: z.ZodEffects<z.ZodString, string, string>;
699
- description: z.ZodOptional<z.ZodString>;
700
- flagKey: z.ZodOptional<z.ZodString>;
701
- product: z.ZodOptional<z.ZodString>;
702
- url: z.ZodOptional<z.ZodString>;
703
- image: z.ZodOptional<z.ZodString>;
704
- type: z.ZodOptional<z.ZodEnum<["feature", "improvement", "fix", "breaking"]>>;
705
- priority: z.ZodOptional<z.ZodEnum<["critical", "normal", "low"]>>;
706
- cta: z.ZodOptional<z.ZodObject<{
707
- label: z.ZodString;
708
- url: z.ZodString;
709
- }, "strip", z.ZodTypeAny, {
710
- label: string;
711
- url: string;
712
- }, {
713
- label: string;
714
- url: string;
715
- }>>;
716
- meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
717
- dependsOn: z.ZodOptional<z.ZodObject<{
718
- seen: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
719
- clicked: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
720
- dismissed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
721
- }, "strip", z.ZodTypeAny, {
722
- seen?: string[] | undefined;
723
- clicked?: string[] | undefined;
724
- dismissed?: string[] | undefined;
725
- }, {
726
- seen?: string[] | undefined;
727
- clicked?: string[] | undefined;
728
- dismissed?: string[] | undefined;
729
- }>>;
730
- }, z.ZodTypeAny, "passthrough">>, "many">;
731
- declare function validateManifest(data: unknown): ValidationResult;
732
-
733
- interface ChangedFeature {
734
- id: string;
735
- before: FeatureEntry;
736
- after: FeatureEntry;
737
- changedFields: string[];
738
- }
739
- interface ManifestDiff {
740
- added: FeatureEntry[];
741
- removed: FeatureEntry[];
742
- changed: ChangedFeature[];
743
- }
744
- declare function diffManifest(before: FeatureManifest, after: FeatureManifest): ManifestDiff;
745
- interface ChangelogDiffOptions {
746
- includeFieldChanges?: boolean;
747
- }
748
- declare function generateChangelogDiff(diff: ManifestDiff, options?: ChangelogDiffOptions): string;
749
- declare function validateManifestForCI(manifest: FeatureManifest): ValidationResult;
750
-
751
- interface CreateFlagBridgeOptions {
752
- isEnabled: (flagKey: string, userContext?: UserContext) => boolean;
753
- }
754
- declare function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge;
755
- interface LaunchDarklyClientLike {
756
- variation: (flagKey: string, user: Record<string, unknown>, defaultValue: boolean) => boolean;
757
- }
758
- interface LaunchDarklyBridgeOptions {
759
- userResolver?: (userContext?: UserContext) => Record<string, unknown>;
760
- defaultValue?: boolean;
761
- }
762
- declare class LaunchDarklyBridge implements FeatureFlagBridge {
763
- private readonly client;
764
- private readonly options;
765
- constructor(client: LaunchDarklyClientLike, options?: LaunchDarklyBridgeOptions);
766
- isEnabled(flagKey: string, userContext?: UserContext): boolean;
767
- }
768
- interface PostHogClientLike {
769
- isFeatureEnabled: (flagKey: string, distinctId?: string, groups?: Record<string, string>, personProperties?: Record<string, unknown>) => boolean;
770
- }
771
- interface PostHogBridgeOptions {
772
- distinctIdResolver?: (userContext?: UserContext) => string | undefined;
773
- groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;
774
- }
775
- declare class PostHogBridge implements FeatureFlagBridge {
776
- private readonly client;
777
- private readonly options;
778
- constructor(client: PostHogClientLike, options?: PostHogBridgeOptions);
779
- isEnabled(flagKey: string, userContext?: UserContext): boolean;
780
- }
781
-
782
- interface ManifestEditorProps {
783
- features: readonly FeatureEntry[];
784
- onSave: (updated: FeatureEntry[]) => Promise<void> | void;
785
- readOnly?: boolean;
786
- children?: ReactNode;
787
- }
788
- declare function ManifestEditor({ features, onSave, readOnly, children, }: ManifestEditorProps): react_jsx_runtime.JSX.Element;
789
- interface ScheduleCalendarProps {
790
- features: readonly FeatureEntry[];
791
- onSchedule: (featureId: string, publishAt: string) => Promise<void> | void;
792
- }
793
- declare function ScheduleCalendar({ features, onSchedule }: ScheduleCalendarProps): react_jsx_runtime.JSX.Element;
794
- interface PreviewPanelProps {
795
- feature?: FeatureEntry | null;
796
- components?: Array<"badge" | "changelog" | "spotlight" | "banner" | "toast">;
797
- }
798
- declare function PreviewPanel({ feature, components }: PreviewPanelProps): react_jsx_runtime.JSX.Element;
799
- interface AudienceBuilderProps {
800
- segments?: string[];
801
- roles?: string[];
802
- regions?: string[];
803
- value?: AudienceRule;
804
- onChange?: (audience: AudienceRule) => void;
805
- onSave?: (audience: AudienceRule) => Promise<void> | void;
806
- }
807
- declare function AudienceBuilder({ segments, roles, regions, value, onChange, onSave, }: AudienceBuilderProps): react_jsx_runtime.JSX.Element;
808
-
809
- type CMSFieldResolver = string | ((record: unknown) => unknown);
810
- interface CMSFieldMapping {
811
- id?: CMSFieldResolver;
812
- label?: CMSFieldResolver;
813
- description?: CMSFieldResolver;
814
- releasedAt?: CMSFieldResolver;
815
- showNewUntil?: CMSFieldResolver;
816
- sidebarKey?: CMSFieldResolver;
817
- category?: CMSFieldResolver;
818
- product?: CMSFieldResolver;
819
- flagKey?: CMSFieldResolver;
820
- url?: CMSFieldResolver;
821
- image?: CMSFieldResolver;
822
- publishAt?: CMSFieldResolver;
823
- type?: CMSFieldResolver;
824
- priority?: CMSFieldResolver;
825
- ctaLabel?: CMSFieldResolver;
826
- ctaUrl?: CMSFieldResolver;
827
- }
828
- interface CMSAdapter {
829
- load: () => Promise<FeatureEntry[]>;
830
- }
831
- interface CMSAdapterBaseOptions {
832
- fieldMapping?: CMSFieldMapping;
833
- /** Throw when mapped entries are invalid. Default false (invalid entries are dropped). */
834
- strictValidation?: boolean;
835
- }
836
- interface ContentfulAdapterOptions extends CMSAdapterBaseOptions {
837
- spaceId: string;
838
- accessToken: string;
839
- contentType: string;
840
- environment?: string;
841
- locale?: string;
842
- limit?: number;
843
- }
844
- interface SanityAdapterOptions extends CMSAdapterBaseOptions {
845
- projectId: string;
846
- dataset: string;
847
- query: string;
848
- token?: string;
849
- apiVersion?: string;
850
- }
851
- interface StrapiAdapterOptions extends CMSAdapterBaseOptions {
852
- baseUrl: string;
853
- endpoint?: string;
854
- token?: string;
855
- query?: string;
856
- }
857
- interface NotionAdapterOptions extends CMSAdapterBaseOptions {
858
- databaseId: string;
859
- token: string;
860
- notionVersion?: string;
861
- filter?: Record<string, unknown>;
862
- sorts?: Array<Record<string, unknown>>;
863
- }
864
- interface MarkdownAdapterFile {
865
- source?: string;
866
- markdown: string;
867
- }
868
- interface MarkdownAdapterOptions extends CMSAdapterBaseOptions {
869
- pattern?: string;
870
- cwd?: string;
871
- entries?: MarkdownAdapterFile[];
872
- }
873
- declare class ContentfulAdapter implements CMSAdapter {
874
- private readonly options;
875
- constructor(options: ContentfulAdapterOptions);
876
- load(): Promise<FeatureEntry[]>;
877
- }
878
- declare class SanityAdapter implements CMSAdapter {
879
- private readonly options;
880
- constructor(options: SanityAdapterOptions);
881
- load(): Promise<FeatureEntry[]>;
882
- }
883
- declare class StrapiAdapter implements CMSAdapter {
884
- private readonly options;
885
- constructor(options: StrapiAdapterOptions);
886
- load(): Promise<FeatureEntry[]>;
887
- }
888
- declare class NotionAdapter implements CMSAdapter {
889
- private readonly options;
890
- constructor(options: NotionAdapterOptions);
891
- load(): Promise<FeatureEntry[]>;
892
- }
893
- declare class MarkdownAdapter implements CMSAdapter {
894
- private readonly options;
895
- constructor(options?: MarkdownAdapterOptions);
896
- load(): Promise<FeatureEntry[]>;
897
- }
898
-
899
- interface FeatureDropTheme {
900
- colors: {
901
- primary: string;
902
- background: string;
903
- text: string;
904
- textMuted: string;
905
- border: string;
906
- success: string;
907
- warning: string;
908
- error: string;
909
- };
910
- fonts: {
911
- family: string;
912
- sizeBase: string;
913
- sizeSm: string;
914
- sizeLg: string;
915
- };
916
- spacing: {
917
- xs: string;
918
- sm: string;
919
- md: string;
920
- lg: string;
921
- xl: string;
922
- };
923
- radii: {
924
- sm: string;
925
- md: string;
926
- lg: string;
927
- full: string;
928
- };
929
- shadows: {
930
- sm: string;
931
- md: string;
932
- lg: string;
933
- };
934
- zIndex: {
935
- base: number;
936
- tooltip: number;
937
- modal: number;
938
- overlay: number;
939
- };
940
- }
941
- type FeatureDropThemePreset = "light" | "dark" | "auto" | "minimal" | "vibrant";
942
- type FeatureDropThemeOverrides = {
943
- [K in keyof FeatureDropTheme]?: Partial<FeatureDropTheme[K]>;
944
- };
945
- type FeatureDropThemeInput = FeatureDropThemePreset | FeatureDropThemeOverrides | FeatureDropTheme;
946
- declare const FEATUREDROP_THEMES: {
947
- readonly light: FeatureDropTheme;
948
- readonly dark: FeatureDropTheme;
949
- readonly minimal: FeatureDropTheme;
950
- readonly vibrant: FeatureDropTheme;
951
- };
952
- declare function createTheme(overrides: FeatureDropThemeOverrides, base?: FeatureDropTheme): FeatureDropTheme;
953
- declare function resolveTheme(input?: FeatureDropThemeInput, options?: {
954
- prefersDark?: boolean;
955
- }): FeatureDropTheme;
956
- declare function themeToCSSVariables(theme: FeatureDropTheme): Record<string, string | number>;
957
-
958
- interface FeatureDropTranslations {
959
- newBadge: string;
960
- whatsNewTitle: string;
961
- markAllRead: string;
962
- allCaughtUp: string;
963
- close: string;
964
- changelogTitle: string;
965
- searchPlaceholder: string;
966
- allCategories: string;
967
- noUpdatesYet: string;
968
- loadMore: string;
969
- share: string;
970
- skipToEntries: string;
971
- newFeatureCount: (count: number) => string;
972
- stepOf: (current: number, total: number) => string;
973
- back: string;
974
- next: string;
975
- skip: string;
976
- finish: string;
977
- gotIt: string;
978
- announcement: string;
979
- feedbackTitle: string;
980
- feedbackTrigger: string;
981
- feedbackSubmitted: string;
982
- submit: string;
983
- cancel: string;
984
- askLater: string;
985
- }
986
- declare function resolveLocale(locale?: string): string;
987
- declare function getLocaleDirection(locale?: string): "ltr" | "rtl";
988
- declare function formatDateForLocale(value: string | number | Date, locale?: string, options?: Intl.DateTimeFormatOptions): string;
989
- declare function formatRelativeTimeForLocale(value: string | number | Date, locale?: string, options?: {
990
- now?: string | number | Date;
991
- numeric?: Intl.RelativeTimeFormatNumeric;
992
- style?: Intl.RelativeTimeFormatStyle;
993
- }): string;
994
- declare function resolveTranslations(locale?: string, overrides?: Partial<FeatureDropTranslations>): FeatureDropTranslations;
995
- declare const FEATUREDROP_TRANSLATIONS: {
996
- readonly en: FeatureDropTranslations;
997
- };
998
-
999
- declare const FEATUREDROP_ANIMATION_PRESETS: readonly ["none", "subtle", "normal", "playful"];
1000
- declare function resolveAnimationPreset(preset?: FeatureDropAnimationPreset, options?: {
1001
- reducedMotion?: boolean;
1002
- }): FeatureDropAnimationPreset;
1003
- type AnimationSurface = "toast" | "panel" | "modal" | "popover";
1004
- type AnimationPhase = "enter" | "exit";
1005
- type PulseSurface = "dot" | "beacon";
1006
- declare function getEnterAnimation(preset: FeatureDropAnimationPreset, surface: AnimationSurface): string | undefined;
1007
- declare function getExitAnimation(preset: FeatureDropAnimationPreset, surface: AnimationSurface): string | undefined;
1008
- declare function getPulseAnimation(preset: FeatureDropAnimationPreset, surface?: PulseSurface): string | undefined;
1009
- declare function getAnimationDurationMs(preset: FeatureDropAnimationPreset, surface: AnimationSurface, phase: AnimationPhase): number;
1010
-
1011
- /**
1012
- * Generate a simple RSS 2.0 feed from a feature manifest.
1013
- * Titles and descriptions are sanitized via `parseDescription`.
1014
- */
1015
- declare function generateRSS(manifest: FeatureManifest, options?: {
1016
- title?: string;
1017
- link?: string;
1018
- description?: string;
1019
- }): string;
1020
-
1021
- interface ThrottleOptions {
1022
- maxSimultaneousBadges?: number;
1023
- maxSimultaneousSpotlights?: number;
1024
- maxToastsPerSession?: number;
1025
- minTimeBetweenModals?: number;
1026
- minTimeBetweenTours?: number;
1027
- sessionCooldown?: number;
1028
- respectDoNotDisturb?: boolean;
1029
- }
1030
- interface ThrottleRuntimeState {
1031
- sessionStartedAt: number;
1032
- quietMode?: boolean;
1033
- }
1034
- interface ThrottleResult {
1035
- visible: FeatureEntry[];
1036
- queued: FeatureEntry[];
1037
- }
1038
- declare function applyAnnouncementThrottle(features: FeatureEntry[], options: ThrottleOptions | undefined, state: ThrottleRuntimeState, now?: number): ThrottleResult;
1039
-
1040
- type AdoptionEventType = "feature_seen" | "feature_clicked" | "feature_dismissed" | "tour_started" | "tour_completed" | "tour_skipped" | "checklist_task_completed" | "checklist_completed" | "survey_submitted" | "feedback_submitted" | "announcement_shown" | "cta_clicked";
1041
- interface AdoptionEvent {
1042
- type: AdoptionEventType;
1043
- featureId?: string;
1044
- tourId?: string;
1045
- variant?: string;
1046
- timestamp: string;
1047
- sessionId?: string;
1048
- userId?: string;
1049
- metadata?: Record<string, unknown>;
1050
- }
1051
- type AdoptionEventInput = Omit<AdoptionEvent, "timestamp"> & {
1052
- timestamp?: string;
1053
- };
1054
- interface AnalyticsAdapter {
1055
- track: (event: AdoptionEvent) => void | Promise<void>;
1056
- trackBatch?: (events: AdoptionEvent[]) => void | Promise<void>;
1057
- }
1058
- interface AnalyticsCollectorOptions {
1059
- adapter: AnalyticsAdapter;
1060
- batchSize?: number;
1061
- flushInterval?: number;
1062
- sampleRate?: number;
1063
- enabled?: boolean;
1064
- sessionId?: string;
1065
- userId?: string;
1066
- now?: () => Date;
1067
- random?: () => number;
1068
- }
1069
- declare class AnalyticsCollector {
1070
- private adapter;
1071
- private queue;
1072
- private batchSize;
1073
- private flushInterval;
1074
- private sampleRate;
1075
- private enabled;
1076
- private now;
1077
- private random;
1078
- private sessionId?;
1079
- private userId?;
1080
- private timer;
1081
- private flushing;
1082
- constructor(options: AnalyticsCollectorOptions);
1083
- setEnabled(enabled: boolean): void;
1084
- setContext(context: {
1085
- sessionId?: string;
1086
- userId?: string;
1087
- }): void;
1088
- getQueueSize(): number;
1089
- track(event: AdoptionEventInput): void;
1090
- flush(): Promise<void>;
1091
- destroy(): Promise<void>;
1092
- private startTimer;
1093
- }
1094
- declare class PostHogAdapter implements AnalyticsAdapter {
1095
- private readonly client;
1096
- constructor(client: {
1097
- capture: (event: string, properties?: Record<string, unknown>) => void;
1098
- });
1099
- track(event: AdoptionEvent): void;
1100
- }
1101
- declare class AmplitudeAdapter implements AnalyticsAdapter {
1102
- private readonly client;
1103
- constructor(client: {
1104
- track: (event: string, properties?: Record<string, unknown>) => void;
1105
- });
1106
- track(event: AdoptionEvent): void;
1107
- }
1108
- declare class MixpanelAdapter implements AnalyticsAdapter {
1109
- private readonly client;
1110
- constructor(client: {
1111
- track: (event: string, properties?: Record<string, unknown>) => void;
1112
- });
1113
- track(event: AdoptionEvent): void;
1114
- }
1115
- declare class SegmentAdapter implements AnalyticsAdapter {
1116
- private readonly client;
1117
- constructor(client: {
1118
- track: (event: string, properties?: Record<string, unknown>) => void;
1119
- });
1120
- track(event: AdoptionEvent): void;
1121
- }
1122
- declare class CustomAdapter implements AnalyticsAdapter {
1123
- private readonly handler;
1124
- constructor(handler: (event: AdoptionEvent) => void | Promise<void>);
1125
- track(event: AdoptionEvent): void | Promise<void>;
1126
- }
1127
- interface FeatureEngagementMetrics {
1128
- seen: number;
1129
- clicked: number;
1130
- dismissed: number;
1131
- }
1132
- interface AdoptionMetrics {
1133
- getAdoptionRate: (featureId: string) => number;
1134
- getTourCompletionRate: (tourId: string) => number;
1135
- getChecklistCompletionRate: (checklistId: string) => number;
1136
- getFeatureEngagement: (featureId: string) => FeatureEngagementMetrics;
1137
- getVariantPerformance: (featureId: string) => Record<string, number>;
1138
- }
1139
- declare function createAdoptionMetrics(events: AdoptionEvent[]): AdoptionMetrics;
1140
-
1141
- declare function resolveDependencyOrder(manifest: FeatureManifest): string[];
1142
- declare function hasDependencyCycle(manifest: FeatureManifest): boolean;
1143
- declare function sortFeaturesByDependencies(features: FeatureEntry[]): FeatureEntry[];
1144
-
1145
- declare function isTriggerMatch(trigger: FeatureTrigger | undefined, context?: TriggerContext): boolean;
1146
- declare class TriggerEngine {
1147
- private context;
1148
- constructor(initial?: TriggerContext);
1149
- setPath(path: string): void;
1150
- trackEvent(event: string): void;
1151
- trackUsage(event: string, delta?: number): void;
1152
- trackMilestone(event: string): void;
1153
- setElapsedMs(elapsedMs: number): void;
1154
- setScrollPercent(scrollPercent: number): void;
1155
- setMetadata(next: Record<string, unknown>): void;
1156
- getContext(): TriggerContext;
1157
- evaluate(trigger: FeatureTrigger | undefined): boolean;
1158
- evaluateFeature(feature: Pick<FeatureEntry, "trigger">): boolean;
1159
- }
1160
-
1161
- declare function getFeatureVariantName(feature: FeatureEntry): string | undefined;
1162
- declare function applyFeatureVariant(feature: FeatureEntry, variantKey: string): FeatureEntry;
1163
- declare function applyFeatureVariants(manifest: FeatureManifest, variantKey: string): FeatureEntry[];
1164
- declare function getOrCreateVariantKey(explicitKey?: string): string;
1165
-
1166
- interface ManifestStats {
1167
- total: number;
1168
- byType: Record<string, number>;
1169
- byCategory: Record<string, number>;
1170
- newestRelease: string | null;
1171
- oldestRelease: string | null;
1172
- }
1173
- declare function computeManifestStats(entries: FeatureEntry[]): ManifestStats;
1174
- declare function generateMarkdownChangelog(entries: FeatureEntry[]): string;
1175
- interface DoctorReport {
1176
- checks: string[];
1177
- warnings: string[];
1178
- errors: string[];
1179
- }
1180
- declare function runDoctor(entries: FeatureEntry[], now?: Date): DoctorReport;
1181
-
1182
290
  interface LocalStorageAdapterOptions {
1183
291
  /** Key prefix for localStorage entries. Default: "featuredrop" */
1184
292
  prefix?: string;
@@ -1209,65 +317,6 @@ declare class LocalStorageAdapter implements StorageAdapter {
1209
317
  dismissAll(now: Date): Promise<void>;
1210
318
  }
1211
319
 
1212
- interface IndexedDBAdapterOptions {
1213
- prefix?: string;
1214
- watermark?: string | null;
1215
- dbName?: string;
1216
- storeName?: string;
1217
- onDismissAll?: (now: Date) => Promise<void>;
1218
- /** Optional remote state fetch for offline-first sync reconciliation. */
1219
- onSyncState?: () => Promise<{
1220
- watermark?: string | null;
1221
- dismissedIds?: string[];
1222
- }>;
1223
- /** Optional remote flush for queued single-dismiss operations. */
1224
- onFlushDismissBatch?: (ids: string[]) => Promise<void>;
1225
- /** Optional remote flush for queued dismiss-all operations. */
1226
- onFlushDismissAll?: (watermark: string) => Promise<void>;
1227
- /** Delay before queued operations are flushed. Default: 500ms. */
1228
- flushDebounceMs?: number;
1229
- /** Attach online/visibility listeners to trigger sync+flush. Default: true in browser. */
1230
- autoSyncOnOnline?: boolean;
1231
- }
1232
- declare class IndexedDBAdapter implements StorageAdapter {
1233
- private readonly prefix;
1234
- private readonly dbName;
1235
- private readonly storeName;
1236
- private readonly onDismissAllCallback?;
1237
- private readonly onSyncStateCallback?;
1238
- private readonly onFlushDismissBatchCallback?;
1239
- private readonly onFlushDismissAllCallback?;
1240
- private readonly flushDebounceMs;
1241
- private readonly autoSyncOnOnline;
1242
- private watermark;
1243
- private dismissed;
1244
- private queue;
1245
- private readonly hydratePromise;
1246
- private flushTimer;
1247
- private flushing;
1248
- private readonly boundOnlineHandler;
1249
- private readonly boundVisibilityHandler;
1250
- constructor(options?: IndexedDBAdapterOptions);
1251
- getWatermark(): string | null;
1252
- getDismissedIds(): ReadonlySet<string>;
1253
- dismiss(id: string): void;
1254
- dismissAll(now: Date): Promise<void>;
1255
- /** Flush queued dismiss operations to optional remote callbacks. */
1256
- flushQueue(): Promise<void>;
1257
- /** Merge local state with optional remote source, then flush queued writes. */
1258
- syncFromRemote(): Promise<void>;
1259
- /** Cleanup optional browser listeners. */
1260
- destroy(): void;
1261
- private persist;
1262
- private hydrateFromIndexedDB;
1263
- private readIndexedDBState;
1264
- private writeIndexedDBState;
1265
- private openDb;
1266
- private scheduleFlush;
1267
- private getLastDismissAll;
1268
- private collectDismissBatch;
1269
- }
1270
-
1271
320
  /**
1272
321
  * In-memory storage adapter.
1273
322
  *
@@ -1288,392 +337,4 @@ declare class MemoryAdapter implements StorageAdapter {
1288
337
  dismissAll(now: Date): Promise<void>;
1289
338
  }
1290
339
 
1291
- interface RemoteAdapterOptions {
1292
- /** Base URL for the feature API (e.g. https://api.example.com/api/features) */
1293
- url: string;
1294
- /** Optional headers applied to all requests */
1295
- headers?: Record<string, string>;
1296
- /** Polling interval in ms for stale-while-revalidate (default: 5 minutes) */
1297
- fetchInterval?: number;
1298
- /** Data format, currently supports 'rest' (default) */
1299
- format?: "rest";
1300
- /** Optional user identifier to pass to state endpoint */
1301
- userId?: string;
1302
- /** Number of retries after the initial request (default: 3) */
1303
- retryAttempts?: number;
1304
- /** Base backoff delay used between retries (default: 250ms) */
1305
- retryBaseDelayMs?: number;
1306
- /** Consecutive failed operations before opening the circuit (default: 5) */
1307
- circuitBreakerThreshold?: number;
1308
- /** Cooldown period while the circuit is open (default: 60s) */
1309
- circuitBreakerCooldownMs?: number;
1310
- /** Optional sleep function override for test environments */
1311
- sleep?: (delayMs: number) => Promise<void>;
1312
- /** Optional timestamp function override for test environments */
1313
- now?: () => number;
1314
- }
1315
- declare class RemoteAdapter implements StorageAdapter {
1316
- private readonly baseUrl;
1317
- private readonly headers;
1318
- private readonly fetchInterval;
1319
- private readonly userId?;
1320
- private dismissedIds;
1321
- private watermark;
1322
- private lastManifest;
1323
- private lastFetchTs;
1324
- private readonly retryAttempts;
1325
- private readonly retryBaseDelayMs;
1326
- private readonly circuitBreakerThreshold;
1327
- private readonly circuitBreakerCooldownMs;
1328
- private readonly sleep;
1329
- private readonly now;
1330
- private consecutiveFailures;
1331
- private circuitOpenUntil;
1332
- constructor(options: RemoteAdapterOptions);
1333
- /** Fetch manifest with stale-while-revalidate */
1334
- fetchManifest(force?: boolean): Promise<FeatureManifest>;
1335
- /** Fetch state (watermark + dismissed IDs) */
1336
- syncState(): Promise<void>;
1337
- getWatermark(): string | null;
1338
- getDismissedIds(): ReadonlySet<string>;
1339
- dismiss(id: string): void;
1340
- dismissAll(now: Date): Promise<void>;
1341
- /** Returns current adapter health; false while circuit breaker is open. */
1342
- isHealthy(): Promise<boolean>;
1343
- private flushDismiss;
1344
- private flushDismissAll;
1345
- private isCircuitOpen;
1346
- private markFailure;
1347
- private markSuccess;
1348
- private withRetry;
1349
- }
1350
-
1351
- interface QueryResultRow {
1352
- watermark?: string | null;
1353
- dismissed_ids?: string[] | null;
1354
- dismissedIds?: string[] | null;
1355
- last_seen?: string | null;
1356
- lastSeen?: string | null;
1357
- }
1358
- interface PostgresQueryResult<T = QueryResultRow> {
1359
- rows: T[];
1360
- rowCount?: number | null;
1361
- }
1362
- type PostgresQueryFn = <T = QueryResultRow>(sql: string, params?: unknown[]) => Promise<PostgresQueryResult<T>>;
1363
- interface PostgresAdapterOptions {
1364
- userId: string;
1365
- query: PostgresQueryFn;
1366
- tableName?: string;
1367
- autoMigrate?: boolean;
1368
- }
1369
- /**
1370
- * Postgres-backed storage adapter.
1371
- *
1372
- * This adapter is dependency-free by design and accepts a user-provided
1373
- * query function, allowing integration with pg, drizzle, prisma, etc.
1374
- */
1375
- declare class PostgresAdapter implements ServerStorageAdapter {
1376
- readonly userId: string;
1377
- private readonly query;
1378
- private readonly tableName;
1379
- private readonly autoMigrate;
1380
- private watermark;
1381
- private dismissedIds;
1382
- private initialized;
1383
- constructor(options: PostgresAdapterOptions);
1384
- getWatermark(): string | null;
1385
- getDismissedIds(): ReadonlySet<string>;
1386
- dismiss(id: string): void;
1387
- dismissAll(now: Date): Promise<void>;
1388
- sync(): Promise<void>;
1389
- dismissBatch(ids: string[]): Promise<void>;
1390
- resetUser(userId: string): Promise<void>;
1391
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1392
- isHealthy(): Promise<boolean>;
1393
- destroy(): Promise<void>;
1394
- private ensureReady;
1395
- }
1396
-
1397
- interface RedisLikePipeline {
1398
- set(key: string, value: string): RedisLikePipeline;
1399
- del(key: string): RedisLikePipeline;
1400
- sadd(key: string, ...members: string[]): RedisLikePipeline;
1401
- exec(): Promise<unknown>;
1402
- }
1403
- interface RedisLikeClient {
1404
- get(key: string): Promise<string | null>;
1405
- set(key: string, value: string): Promise<unknown>;
1406
- del(key: string): Promise<unknown>;
1407
- smembers(key: string): Promise<string[]>;
1408
- sadd(key: string, ...members: string[]): Promise<unknown>;
1409
- ping(): Promise<string>;
1410
- multi(): RedisLikePipeline;
1411
- quit?(): Promise<unknown>;
1412
- disconnect?(): void;
1413
- }
1414
- interface RedisAdapterOptions {
1415
- userId: string;
1416
- client: RedisLikeClient;
1417
- keyPrefix?: string;
1418
- }
1419
- /**
1420
- * Redis-backed storage adapter.
1421
- * Uses simple key + set structures to keep operations predictable.
1422
- */
1423
- declare class RedisAdapter implements ServerStorageAdapter {
1424
- readonly userId: string;
1425
- private readonly client;
1426
- private readonly keyPrefix;
1427
- private watermark;
1428
- private dismissedIds;
1429
- constructor(options: RedisAdapterOptions);
1430
- getWatermark(): string | null;
1431
- getDismissedIds(): ReadonlySet<string>;
1432
- dismiss(id: string): void;
1433
- dismissAll(now: Date): Promise<void>;
1434
- sync(): Promise<void>;
1435
- dismissBatch(ids: string[]): Promise<void>;
1436
- resetUser(userId: string): Promise<void>;
1437
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1438
- isHealthy(): Promise<boolean>;
1439
- destroy(): Promise<void>;
1440
- private watermarkKey;
1441
- private dismissedKey;
1442
- private lastSeenKey;
1443
- }
1444
-
1445
- interface HybridAdapterOptions {
1446
- local: StorageAdapter;
1447
- remote: ServerStorageAdapter;
1448
- /** If true, sync from remote before writes. Default false */
1449
- syncBeforeWrite?: boolean;
1450
- /** Batch window for queued dismiss writes. Default: 500ms */
1451
- dismissBatchWindowMs?: number;
1452
- /** Optional periodic sync interval in ms. Default: disabled (0) */
1453
- syncIntervalMs?: number;
1454
- /** Sync on browser visibility return. Default: true */
1455
- syncOnVisibilityChange?: boolean;
1456
- /** Sync on browser online event. Default: true */
1457
- syncOnOnline?: boolean;
1458
- }
1459
- /**
1460
- * Hybrid adapter that combines local immediacy with remote persistence.
1461
- */
1462
- declare class HybridAdapter implements ServerStorageAdapter {
1463
- readonly userId: string;
1464
- private readonly local;
1465
- private readonly remote;
1466
- private readonly syncBeforeWrite;
1467
- private readonly dismissBatchWindowMs;
1468
- private readonly syncIntervalMs;
1469
- private readonly syncOnVisibilityChange;
1470
- private readonly syncOnOnline;
1471
- private pendingDismissIds;
1472
- private dismissTimer;
1473
- private syncTimer;
1474
- private readonly boundVisibilityHandler;
1475
- private readonly boundOnlineHandler;
1476
- constructor(options: HybridAdapterOptions);
1477
- getWatermark(): string | null;
1478
- getDismissedIds(): ReadonlySet<string>;
1479
- dismiss(id: string): void;
1480
- dismissAll(now: Date): Promise<void>;
1481
- sync(): Promise<void>;
1482
- dismissBatch(ids: string[]): Promise<void>;
1483
- resetUser(userId: string): Promise<void>;
1484
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1485
- isHealthy(): Promise<boolean>;
1486
- destroy(): Promise<void>;
1487
- /** Manually flush queued dismiss operations to the remote adapter. */
1488
- flushPendingDismisses(): Promise<void>;
1489
- private scheduleDismissFlush;
1490
- }
1491
-
1492
- interface MySQLRow {
1493
- user_id?: string;
1494
- watermark?: string | null;
1495
- dismissed_ids?: string[] | string | null;
1496
- dismissedIds?: string[] | string | null;
1497
- last_seen?: string | null;
1498
- lastSeen?: string | null;
1499
- }
1500
- interface MySQLQueryResult<T = MySQLRow> {
1501
- rows: T[];
1502
- }
1503
- type MySQLQueryFn = <T = MySQLRow>(sql: string, params?: unknown[]) => Promise<MySQLQueryResult<T>>;
1504
- interface MySQLAdapterOptions {
1505
- userId: string;
1506
- query: MySQLQueryFn;
1507
- tableName?: string;
1508
- autoMigrate?: boolean;
1509
- }
1510
- declare class MySQLAdapter implements ServerStorageAdapter {
1511
- readonly userId: string;
1512
- private readonly query;
1513
- private readonly tableName;
1514
- private readonly autoMigrate;
1515
- private watermark;
1516
- private dismissedIds;
1517
- private initialized;
1518
- constructor(options: MySQLAdapterOptions);
1519
- getWatermark(): string | null;
1520
- getDismissedIds(): ReadonlySet<string>;
1521
- dismiss(id: string): void;
1522
- dismissAll(now: Date): Promise<void>;
1523
- sync(): Promise<void>;
1524
- dismissBatch(ids: string[]): Promise<void>;
1525
- resetUser(userId: string): Promise<void>;
1526
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1527
- isHealthy(): Promise<boolean>;
1528
- destroy(): Promise<void>;
1529
- private ensureReady;
1530
- }
1531
-
1532
- interface MongoStateDoc {
1533
- userId: string;
1534
- watermark?: string | null;
1535
- dismissedIds?: string[];
1536
- lastSeen?: string;
1537
- }
1538
- interface MongoFindCursor<T> {
1539
- toArray: () => Promise<T[]>;
1540
- }
1541
- interface MongoLikeCollection {
1542
- findOne: (filter: Record<string, unknown>) => Promise<MongoStateDoc | null>;
1543
- updateOne: (filter: Record<string, unknown>, update: Record<string, unknown>, options?: Record<string, unknown>) => Promise<unknown>;
1544
- deleteOne: (filter: Record<string, unknown>) => Promise<unknown>;
1545
- find?: (filter: Record<string, unknown>) => MongoFindCursor<MongoStateDoc>;
1546
- }
1547
- interface MongoAdapterOptions {
1548
- userId: string;
1549
- collection: MongoLikeCollection;
1550
- }
1551
- declare class MongoAdapter implements ServerStorageAdapter {
1552
- readonly userId: string;
1553
- private readonly collection;
1554
- private watermark;
1555
- private dismissedIds;
1556
- constructor(options: MongoAdapterOptions);
1557
- getWatermark(): string | null;
1558
- getDismissedIds(): ReadonlySet<string>;
1559
- dismiss(id: string): void;
1560
- dismissAll(now: Date): Promise<void>;
1561
- sync(): Promise<void>;
1562
- dismissBatch(ids: string[]): Promise<void>;
1563
- resetUser(userId: string): Promise<void>;
1564
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1565
- isHealthy(): Promise<boolean>;
1566
- destroy(): Promise<void>;
1567
- }
1568
-
1569
- interface SQLiteRow {
1570
- user_id?: string;
1571
- watermark?: string | null;
1572
- dismissed_ids?: string[] | string | null;
1573
- dismissedIds?: string[] | string | null;
1574
- last_seen?: string | null;
1575
- lastSeen?: string | null;
1576
- }
1577
- interface SQLiteQueryResult<T = SQLiteRow> {
1578
- rows: T[];
1579
- }
1580
- type SQLiteQueryFn = <T = SQLiteRow>(sql: string, params?: unknown[]) => Promise<SQLiteQueryResult<T>>;
1581
- interface SQLiteAdapterOptions {
1582
- userId: string;
1583
- query: SQLiteQueryFn;
1584
- tableName?: string;
1585
- autoMigrate?: boolean;
1586
- }
1587
- declare class SQLiteAdapter implements ServerStorageAdapter {
1588
- readonly userId: string;
1589
- private readonly query;
1590
- private readonly tableName;
1591
- private readonly autoMigrate;
1592
- private watermark;
1593
- private dismissedIds;
1594
- private initialized;
1595
- constructor(options: SQLiteAdapterOptions);
1596
- getWatermark(): string | null;
1597
- getDismissedIds(): ReadonlySet<string>;
1598
- dismiss(id: string): void;
1599
- dismissAll(now: Date): Promise<void>;
1600
- sync(): Promise<void>;
1601
- dismissBatch(ids: string[]): Promise<void>;
1602
- resetUser(userId: string): Promise<void>;
1603
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1604
- isHealthy(): Promise<boolean>;
1605
- destroy(): Promise<void>;
1606
- private ensureReady;
1607
- }
1608
-
1609
- interface SupabaseErrorLike {
1610
- message?: string;
1611
- }
1612
- interface SupabaseMaybeSingleResult<T> {
1613
- data: T | null;
1614
- error: SupabaseErrorLike | null;
1615
- }
1616
- interface SupabaseMutationResult {
1617
- error: SupabaseErrorLike | null;
1618
- }
1619
- interface SupabaseSelectQuery<T> {
1620
- eq: (column: string, value: unknown) => SupabaseSelectQuery<T>;
1621
- maybeSingle: () => Promise<SupabaseMaybeSingleResult<T>>;
1622
- }
1623
- interface SupabaseMutationQuery {
1624
- eq: (column: string, value: unknown) => Promise<SupabaseMutationResult>;
1625
- }
1626
- interface SupabaseTableClient<T> {
1627
- select: (columns: string) => SupabaseSelectQuery<T>;
1628
- upsert: (value: Record<string, unknown>) => Promise<SupabaseMutationResult>;
1629
- update: (value: Record<string, unknown>) => SupabaseMutationQuery;
1630
- delete: () => SupabaseMutationQuery;
1631
- }
1632
- interface SupabaseRealtimeChannelLike {
1633
- on: (event: "postgres_changes", filter: Record<string, unknown>, callback: () => void) => SupabaseRealtimeChannelLike;
1634
- subscribe: (callback?: (status: string) => void) => SupabaseRealtimeChannelLike;
1635
- }
1636
- interface SupabaseClientLike {
1637
- from: <T = SupabaseStateRow>(table: string) => SupabaseTableClient<T>;
1638
- channel?: (name: string) => SupabaseRealtimeChannelLike;
1639
- removeChannel?: (channel: SupabaseRealtimeChannelLike) => void | Promise<void>;
1640
- }
1641
- interface SupabaseStateRow {
1642
- [key: string]: unknown;
1643
- user_id: string;
1644
- watermark?: string | null;
1645
- dismissed_ids?: string[] | null;
1646
- last_seen?: string | null;
1647
- }
1648
- interface SupabaseAdapterOptions {
1649
- userId: string;
1650
- client: SupabaseClientLike;
1651
- tableName?: string;
1652
- realtime?: boolean;
1653
- }
1654
- declare class SupabaseAdapter implements ServerStorageAdapter {
1655
- readonly userId: string;
1656
- private readonly client;
1657
- private readonly tableName;
1658
- private readonly realtime;
1659
- private watermark;
1660
- private dismissedIds;
1661
- private realtimeChannel;
1662
- private syncing;
1663
- constructor(options: SupabaseAdapterOptions);
1664
- getWatermark(): string | null;
1665
- getDismissedIds(): ReadonlySet<string>;
1666
- dismiss(id: string): void;
1667
- dismissAll(now: Date): Promise<void>;
1668
- sync(): Promise<void>;
1669
- dismissBatch(ids: string[]): Promise<void>;
1670
- resetUser(userId: string): Promise<void>;
1671
- getBulkState(userIds: string[]): Promise<Map<string, DismissalState>>;
1672
- isHealthy(): Promise<boolean>;
1673
- destroy(): Promise<void>;
1674
- private fetchState;
1675
- private upsertState;
1676
- private setupRealtime;
1677
- }
1678
-
1679
- export { type AdoptionEvent, type AdoptionEventInput, type AdoptionEventType, type AdoptionMetrics, AmplitudeAdapter, type AnalyticsAdapter, type AnalyticsCallbacks, AnalyticsCollector, type AnalyticsCollectorOptions, AudienceBuilder, type AudienceBuilderProps, type AudienceMatchFn, type AudienceRule, type CMSAdapter, type CMSFieldMapping, type ChangedFeature, type ChangelogDiffOptions, type ChangelogRenderer, type ChangelogRendererActions, type ChangelogRendererComputed, type ChangelogRendererOptions, type ChangelogRendererState, ContentfulAdapter, type CreateFlagBridgeOptions, CustomAdapter, DiscordBridge, type DiscordBridgeOptions, type DismissalState, EmailDigestGenerator, type EmailDigestGeneratorOptions, FEATUREDROP_ANIMATION_PRESETS, FEATUREDROP_THEMES, FEATUREDROP_TRANSLATIONS, type FeatureCTA, type FeatureDependencies, type FeatureDependencyState, type FeatureDropAnimationPreset, type FeatureDropTheme, type FeatureDropThemeInput, type FeatureDropThemeOverrides, type FeatureDropThemePreset, type FeatureDropTranslations, type FeatureEngagementMetrics, type FeatureEntry, type FeatureFlagBridge, type FeatureManifest, type FeaturePriority, type FeatureTrigger, type FeatureType, type FeatureVariant, HybridAdapter, type HybridAdapterOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LaunchDarklyBridge, type LaunchDarklyBridgeOptions, type LaunchDarklyClientLike, LocalStorageAdapter, type LocalStorageAdapterOptions, type ManifestDiff, ManifestEditor, type ManifestEditorProps, MarkdownAdapter, MemoryAdapter, MixpanelAdapter, MongoAdapter, type MongoAdapterOptions, type MongoLikeCollection, MySQLAdapter, type MySQLAdapterOptions, type MySQLQueryFn, type MySQLQueryResult, NotionAdapter, PostHogAdapter, PostHogBridge, type PostHogBridgeOptions, type PostHogClientLike, PostgresAdapter, type PostgresAdapterOptions, type PostgresQueryFn, type PostgresQueryResult, PreviewPanel, type PreviewPanelProps, RSSFeedGenerator, type RSSFeedGeneratorOptions, RedisAdapter, type RedisAdapterOptions, type RedisLikeClient, type RedisLikePipeline, RemoteAdapter, type RemoteAdapterOptions, SQLiteAdapter, type SQLiteAdapterOptions, type SQLiteQueryFn, type SQLiteQueryResult, SanityAdapter, ScheduleCalendar, type ScheduleCalendarProps, SegmentAdapter, type ServerStorageAdapter, SlackBridge, type SlackBridgeOptions, type StorageAdapter, StrapiAdapter, SupabaseAdapter, type SupabaseAdapterOptions, type SupabaseClientLike, type SupabaseRealtimeChannelLike, type ThrottleOptions, type ThrottleResult, type ThrottleRuntimeState, type TriggerContext, TriggerEngine, type UserContext, type ValidationIssue, type ValidationResult, WebhookBridge, type WebhookBridgeOptions, applyAnnouncementThrottle, applyFeatureVariant, applyFeatureVariants, computeManifestStats, createAdoptionMetrics, createChangelogRenderer, createFlagBridge, createManifest, createTheme, diffManifest, featureEntryJsonSchema, featureEntrySchema, featureManifestJsonSchema, featureManifestSchema, formatDateForLocale, formatRelativeTimeForLocale, generateChangelogDiff, generateMarkdownChangelog, generateRSS, getAnimationDurationMs, getEnterAnimation, getExitAnimation, getFeatureById, getFeatureVariantName, getLocaleDirection, getNewFeatureCount, getNewFeatures, getNewFeaturesByCategory, getNewFeaturesSorted, getOrCreateVariantKey, getPulseAnimation, hasDependencyCycle, hasNewFeature, isNew, isTriggerMatch, matchesAudience, parseDescription, resolveAnimationPreset, resolveDependencyOrder, resolveLocale, resolveTheme, resolveTranslations, runDoctor, sortFeaturesByDependencies, themeToCSSVariables, validateManifest, validateManifestForCI };
340
+ export { type AnalyticsCallbacks, type AudienceMatchFn, type AudienceRule, type DismissalState, type FeatureCTA, type FeatureDependencies, type FeatureDependencyState, type FeatureDropAnimationPreset, type FeatureEntry, type FeatureFlagBridge, type FeatureManifest, type FeaturePriority, type FeatureTrigger, type FeatureType, type FeatureVariant, LocalStorageAdapter, type LocalStorageAdapterOptions, MemoryAdapter, type ServerStorageAdapter, type StorageAdapter, type TriggerContext, type UserContext, createManifest, getFeatureById, getNewFeatureCount, getNewFeatures, getNewFeaturesByCategory, getNewFeaturesSorted, hasNewFeature, isNew, matchesAudience };