@contentful/optimization-core 0.1.0-alpha

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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -0
  3. package/dist/Consent.d.ts +44 -0
  4. package/dist/Consent.d.ts.map +1 -0
  5. package/dist/Consent.js +2 -0
  6. package/dist/Consent.js.map +1 -0
  7. package/dist/CoreBase.d.ts +161 -0
  8. package/dist/CoreBase.d.ts.map +1 -0
  9. package/dist/CoreBase.js +151 -0
  10. package/dist/CoreBase.js.map +1 -0
  11. package/dist/CoreStateful.d.ts +142 -0
  12. package/dist/CoreStateful.d.ts.map +1 -0
  13. package/dist/CoreStateful.js +137 -0
  14. package/dist/CoreStateful.js.map +1 -0
  15. package/dist/CoreStateless.d.ts +53 -0
  16. package/dist/CoreStateless.d.ts.map +1 -0
  17. package/dist/CoreStateless.js +43 -0
  18. package/dist/CoreStateless.js.map +1 -0
  19. package/dist/ProductBase.d.ts +83 -0
  20. package/dist/ProductBase.d.ts.map +1 -0
  21. package/dist/ProductBase.js +50 -0
  22. package/dist/ProductBase.js.map +1 -0
  23. package/dist/analytics/AnalyticsBase.d.ts +35 -0
  24. package/dist/analytics/AnalyticsBase.d.ts.map +1 -0
  25. package/dist/analytics/AnalyticsBase.js +13 -0
  26. package/dist/analytics/AnalyticsBase.js.map +1 -0
  27. package/dist/analytics/AnalyticsStateful.d.ts +138 -0
  28. package/dist/analytics/AnalyticsStateful.d.ts.map +1 -0
  29. package/dist/analytics/AnalyticsStateful.js +179 -0
  30. package/dist/analytics/AnalyticsStateful.js.map +1 -0
  31. package/dist/analytics/AnalyticsStateless.d.ts +48 -0
  32. package/dist/analytics/AnalyticsStateless.d.ts.map +1 -0
  33. package/dist/analytics/AnalyticsStateless.js +61 -0
  34. package/dist/analytics/AnalyticsStateless.js.map +1 -0
  35. package/dist/analytics/index.d.ts +5 -0
  36. package/dist/analytics/index.d.ts.map +1 -0
  37. package/dist/analytics/index.js +5 -0
  38. package/dist/analytics/index.js.map +1 -0
  39. package/dist/global-constants.d.ts +18 -0
  40. package/dist/global-constants.d.ts.map +1 -0
  41. package/dist/global-constants.js +18 -0
  42. package/dist/global-constants.js.map +1 -0
  43. package/dist/index.cjs +1808 -0
  44. package/dist/index.cjs.map +1 -0
  45. package/dist/index.d.ts +15 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +15 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/index.mjs +1535 -0
  50. package/dist/index.mjs.map +1 -0
  51. package/dist/lib/decorators/guardedBy.d.ts +113 -0
  52. package/dist/lib/decorators/guardedBy.d.ts.map +1 -0
  53. package/dist/lib/decorators/guardedBy.js +143 -0
  54. package/dist/lib/decorators/guardedBy.js.map +1 -0
  55. package/dist/lib/decorators/index.d.ts +2 -0
  56. package/dist/lib/decorators/index.d.ts.map +1 -0
  57. package/dist/lib/decorators/index.js +2 -0
  58. package/dist/lib/decorators/index.js.map +1 -0
  59. package/dist/lib/interceptor/InterceptorManager.d.ts +127 -0
  60. package/dist/lib/interceptor/InterceptorManager.d.ts.map +1 -0
  61. package/dist/lib/interceptor/InterceptorManager.js +125 -0
  62. package/dist/lib/interceptor/InterceptorManager.js.map +1 -0
  63. package/dist/lib/interceptor/index.d.ts +2 -0
  64. package/dist/lib/interceptor/index.d.ts.map +1 -0
  65. package/dist/lib/interceptor/index.js +2 -0
  66. package/dist/lib/interceptor/index.js.map +1 -0
  67. package/dist/lib/value-presence/ValuePresence.d.ts +123 -0
  68. package/dist/lib/value-presence/ValuePresence.d.ts.map +1 -0
  69. package/dist/lib/value-presence/ValuePresence.js +141 -0
  70. package/dist/lib/value-presence/ValuePresence.js.map +1 -0
  71. package/dist/lib/value-presence/index.d.ts +2 -0
  72. package/dist/lib/value-presence/index.d.ts.map +1 -0
  73. package/dist/lib/value-presence/index.js +2 -0
  74. package/dist/lib/value-presence/index.js.map +1 -0
  75. package/dist/personalization/PersonalizationBase.d.ts +184 -0
  76. package/dist/personalization/PersonalizationBase.d.ts.map +1 -0
  77. package/dist/personalization/PersonalizationBase.js +76 -0
  78. package/dist/personalization/PersonalizationBase.js.map +1 -0
  79. package/dist/personalization/PersonalizationStateful.d.ts +226 -0
  80. package/dist/personalization/PersonalizationStateful.d.ts.map +1 -0
  81. package/dist/personalization/PersonalizationStateful.js +297 -0
  82. package/dist/personalization/PersonalizationStateful.js.map +1 -0
  83. package/dist/personalization/PersonalizationStateless.d.ts +74 -0
  84. package/dist/personalization/PersonalizationStateless.d.ts.map +1 -0
  85. package/dist/personalization/PersonalizationStateless.js +98 -0
  86. package/dist/personalization/PersonalizationStateless.js.map +1 -0
  87. package/dist/personalization/index.d.ts +6 -0
  88. package/dist/personalization/index.d.ts.map +1 -0
  89. package/dist/personalization/index.js +6 -0
  90. package/dist/personalization/index.js.map +1 -0
  91. package/dist/personalization/resolvers/FlagsResolver.d.ts +35 -0
  92. package/dist/personalization/resolvers/FlagsResolver.d.ts.map +1 -0
  93. package/dist/personalization/resolvers/FlagsResolver.js +47 -0
  94. package/dist/personalization/resolvers/FlagsResolver.js.map +1 -0
  95. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts +74 -0
  96. package/dist/personalization/resolvers/MergeTagValueResolver.d.ts.map +1 -0
  97. package/dist/personalization/resolvers/MergeTagValueResolver.js +109 -0
  98. package/dist/personalization/resolvers/MergeTagValueResolver.js.map +1 -0
  99. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts +142 -0
  100. package/dist/personalization/resolvers/PersonalizedEntryResolver.d.ts.map +1 -0
  101. package/dist/personalization/resolvers/PersonalizedEntryResolver.js +196 -0
  102. package/dist/personalization/resolvers/PersonalizedEntryResolver.js.map +1 -0
  103. package/dist/personalization/resolvers/index.d.ts +7 -0
  104. package/dist/personalization/resolvers/index.d.ts.map +1 -0
  105. package/dist/personalization/resolvers/index.js +7 -0
  106. package/dist/personalization/resolvers/index.js.map +1 -0
  107. package/dist/signals.d.ts +35 -0
  108. package/dist/signals.d.ts.map +1 -0
  109. package/dist/signals.js +30 -0
  110. package/dist/signals.js.map +1 -0
  111. package/package.json +29 -0
@@ -0,0 +1,74 @@
1
+ import { MergeTagEntry, Profile } from '@contentful/optimization-api-client';
2
+ /**
3
+ * Resolves merge tag values from a {@link Profile}.
4
+ *
5
+ * @public
6
+ * @remarks
7
+ * *Merge tags* are references to user profile data that may be embedded in content
8
+ * and expanded at runtime. This resolver normalizes the merge-tag identifier into
9
+ * a set of candidate selectors and searches the profile for a matching value.
10
+ * Result values are returned as strings; numeric/boolean primitives are stringified.
11
+ */
12
+ declare const MergeTagValueResolver: {
13
+ /**
14
+ * Type guard to ensure the input is a {@link MergeTagEntry}.
15
+ *
16
+ * @param embeddedEntryNodeTarget - Unknown value to validate.
17
+ * @returns `true` if the input is a valid merge-tag entry.
18
+ * @example
19
+ * ```ts
20
+ * if (MergeTagValueResolver.isMergeTagEntry(node)) {
21
+ * // safe to read fields
22
+ * }
23
+ * ```
24
+ */
25
+ isMergeTagEntry(embeddedEntryNodeTarget: unknown): embeddedEntryNodeTarget is MergeTagEntry;
26
+ /**
27
+ * Generate a list of candidate selectors for a merge-tag ID.
28
+ *
29
+ * @param id - Merge-tag identifier (segments separated by `_`).
30
+ * @returns Array of dot-path selectors to try against a profile.
31
+ * @example
32
+ * ```ts
33
+ * // "profile_name_first" -> [
34
+ * // 'profile',
35
+ * // 'profile.name',
36
+ * // 'profile.name.first'
37
+ * // ]
38
+ * const selectors = MergeTagValueResolver.normalizeSelectors('profile_name_first')
39
+ * ```
40
+ */
41
+ normalizeSelectors(id: string): string[];
42
+ /**
43
+ * Look up a merge-tag value from a profile using normalized selectors.
44
+ *
45
+ * @param id - Merge-tag identifier.
46
+ * @param profile - Profile from which to resolve the value.
47
+ * @returns A stringified primitive if found; otherwise `undefined`.
48
+ * @example
49
+ * ```ts
50
+ * const value = MergeTagValueResolver.getValueFromProfile('user_email', profile)
51
+ * if (value) sendEmailTo(value)
52
+ * ```
53
+ * @remarks
54
+ * Only string/number/boolean primitives are returned; objects/arrays are ignored.
55
+ */
56
+ getValueFromProfile(id: string, profile?: Profile): string | undefined;
57
+ /**
58
+ * Resolve the display value for a merge-tag entry using the provided profile,
59
+ * falling back to the entry's configured `nt_fallback` when necessary.
60
+ *
61
+ * @param mergeTagEntry - The merge-tag entry to resolve.
62
+ * @param profile - Optional profile used for lookup.
63
+ * @returns The resolved string, or `undefined` if the entry is invalid and no
64
+ * fallback is available.
65
+ * @example
66
+ * ```ts
67
+ * const text = MergeTagValueResolver.resolve(entry, profile)
68
+ * render(text ?? 'Guest')
69
+ * ```
70
+ */
71
+ resolve(mergeTagEntry: MergeTagEntry | undefined, profile?: Profile): string | undefined;
72
+ };
73
+ export default MergeTagValueResolver;
74
+ //# sourceMappingURL=MergeTagValueResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MergeTagValueResolver.d.ts","sourceRoot":"","sources":["../../../src/personalization/resolvers/MergeTagValueResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAA;AAS5E;;;;;;;;;GASG;AACH,QAAA,MAAM,qBAAqB;IACzB;;;;;;;;;;;OAWG;6CACsC,OAAO,GAAG,uBAAuB,IAAI,aAAa;IAI3F;;;;;;;;;;;;;;OAcG;2BACoB,MAAM,GAAG,MAAM,EAAE;IASxC;;;;;;;;;;;;;OAaG;4BACqB,MAAM,YAAY,OAAO,GAAG,MAAM,GAAG,SAAS;IAiBtE;;;;;;;;;;;;;OAaG;2BACoB,aAAa,GAAG,SAAS,YAAY,OAAO,GAAG,MAAM,GAAG,SAAS;CAoBzF,CAAA;AAED,eAAe,qBAAqB,CAAA"}
@@ -0,0 +1,109 @@
1
+ import { MergeTagEntry, Profile } from '@contentful/optimization-api-client';
2
+ import { get } from 'es-toolkit/compat';
3
+ import { createScopedLogger } from 'logger';
4
+ const logger = createScopedLogger('Personalization');
5
+ /** Base string for log messages when merge-tag resolution fails. */
6
+ const RESOLUTION_WARNING_BASE = 'Could not resolve Merge Tag value:';
7
+ /**
8
+ * Resolves merge tag values from a {@link Profile}.
9
+ *
10
+ * @public
11
+ * @remarks
12
+ * *Merge tags* are references to user profile data that may be embedded in content
13
+ * and expanded at runtime. This resolver normalizes the merge-tag identifier into
14
+ * a set of candidate selectors and searches the profile for a matching value.
15
+ * Result values are returned as strings; numeric/boolean primitives are stringified.
16
+ */
17
+ const MergeTagValueResolver = {
18
+ /**
19
+ * Type guard to ensure the input is a {@link MergeTagEntry}.
20
+ *
21
+ * @param embeddedEntryNodeTarget - Unknown value to validate.
22
+ * @returns `true` if the input is a valid merge-tag entry.
23
+ * @example
24
+ * ```ts
25
+ * if (MergeTagValueResolver.isMergeTagEntry(node)) {
26
+ * // safe to read fields
27
+ * }
28
+ * ```
29
+ */
30
+ isMergeTagEntry(embeddedEntryNodeTarget) {
31
+ return MergeTagEntry.safeParse(embeddedEntryNodeTarget).success;
32
+ },
33
+ /**
34
+ * Generate a list of candidate selectors for a merge-tag ID.
35
+ *
36
+ * @param id - Merge-tag identifier (segments separated by `_`).
37
+ * @returns Array of dot-path selectors to try against a profile.
38
+ * @example
39
+ * ```ts
40
+ * // "profile_name_first" -> [
41
+ * // 'profile',
42
+ * // 'profile.name',
43
+ * // 'profile.name.first'
44
+ * // ]
45
+ * const selectors = MergeTagValueResolver.normalizeSelectors('profile_name_first')
46
+ * ```
47
+ */
48
+ normalizeSelectors(id) {
49
+ return id.split('_').map((_path, index, paths) => {
50
+ const dotPath = paths.slice(0, index).join('.');
51
+ const underScorePath = paths.slice(index).join('_');
52
+ return [dotPath, underScorePath].filter((path) => path !== '').join('.');
53
+ });
54
+ },
55
+ /**
56
+ * Look up a merge-tag value from a profile using normalized selectors.
57
+ *
58
+ * @param id - Merge-tag identifier.
59
+ * @param profile - Profile from which to resolve the value.
60
+ * @returns A stringified primitive if found; otherwise `undefined`.
61
+ * @example
62
+ * ```ts
63
+ * const value = MergeTagValueResolver.getValueFromProfile('user_email', profile)
64
+ * if (value) sendEmailTo(value)
65
+ * ```
66
+ * @remarks
67
+ * Only string/number/boolean primitives are returned; objects/arrays are ignored.
68
+ */
69
+ getValueFromProfile(id, profile) {
70
+ const selectors = MergeTagValueResolver.normalizeSelectors(id);
71
+ const matchingSelector = selectors.find((selector) => get(profile, selector));
72
+ if (!matchingSelector)
73
+ return undefined;
74
+ const value = get(profile, matchingSelector);
75
+ if (!value ||
76
+ (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean'))
77
+ return undefined;
78
+ return `${value}`;
79
+ },
80
+ /**
81
+ * Resolve the display value for a merge-tag entry using the provided profile,
82
+ * falling back to the entry's configured `nt_fallback` when necessary.
83
+ *
84
+ * @param mergeTagEntry - The merge-tag entry to resolve.
85
+ * @param profile - Optional profile used for lookup.
86
+ * @returns The resolved string, or `undefined` if the entry is invalid and no
87
+ * fallback is available.
88
+ * @example
89
+ * ```ts
90
+ * const text = MergeTagValueResolver.resolve(entry, profile)
91
+ * render(text ?? 'Guest')
92
+ * ```
93
+ */
94
+ resolve(mergeTagEntry, profile) {
95
+ if (!MergeTagValueResolver.isMergeTagEntry(mergeTagEntry)) {
96
+ logger.warn(`${RESOLUTION_WARNING_BASE} supplied entry is not a Merge Tag entry`);
97
+ return;
98
+ }
99
+ const { fields: { nt_fallback: fallback }, } = mergeTagEntry;
100
+ if (!Profile.safeParse(profile).success) {
101
+ logger.warn(`${RESOLUTION_WARNING_BASE} no valid profile`);
102
+ return fallback;
103
+ }
104
+ return (MergeTagValueResolver.getValueFromProfile(mergeTagEntry.fields.nt_mergetag_id, profile) ??
105
+ fallback);
106
+ },
107
+ };
108
+ export default MergeTagValueResolver;
109
+ //# sourceMappingURL=MergeTagValueResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MergeTagValueResolver.js","sourceRoot":"","sources":["../../../src/personalization/resolvers/MergeTagValueResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAA;AAC5E,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAE3C,MAAM,MAAM,GAAG,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;AAEpD,oEAAoE;AACpE,MAAM,uBAAuB,GAAG,oCAAoC,CAAA;AAEpE;;;;;;;;;GASG;AACH,MAAM,qBAAqB,GAAG;IAC5B;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,uBAAgC;QAC9C,OAAO,aAAa,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC,OAAO,CAAA;IACjE,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,kBAAkB,CAAC,EAAU;QAC3B,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC/C,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAEnD,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1E,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,EAAU,EAAE,OAAiB;QAC/C,MAAM,SAAS,GAAG,qBAAqB,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAA;QAC9D,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAA;QAE7E,IAAI,CAAC,gBAAgB;YAAE,OAAO,SAAS,CAAA;QAEvC,MAAM,KAAK,GAAY,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA;QAErD,IACE,CAAC,KAAK;YACN,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,CAAC;YAEtF,OAAO,SAAS,CAAA;QAElB,OAAO,GAAG,KAAK,EAAE,CAAA;IACnB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,aAAwC,EAAE,OAAiB;QACjE,IAAI,CAAC,qBAAqB,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC,GAAG,uBAAuB,0CAA0C,CAAC,CAAA;YACjF,OAAM;QACR,CAAC;QAED,MAAM,EACJ,MAAM,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,GAClC,GAAG,aAAa,CAAA;QAEjB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,GAAG,uBAAuB,mBAAmB,CAAC,CAAA;YAC1D,OAAO,QAAQ,CAAA;QACjB,CAAC;QAED,OAAO,CACL,qBAAqB,CAAC,mBAAmB,CAAC,aAAa,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC;YACvF,QAAQ,CACT,CAAA;IACH,CAAC;CACF,CAAA;AAED,eAAe,qBAAqB,CAAA"}
@@ -0,0 +1,142 @@
1
+ import { type EntryReplacementVariant, type PersonalizationEntry, type PersonalizedEntry, type SelectedPersonalization, type SelectedPersonalizationArray } from '@contentful/optimization-api-client';
2
+ import type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from 'contentful';
3
+ /**
4
+ * Result returned by {@link PersonalizedEntryResolver.resolve}.
5
+ *
6
+ * @typeParam S - Entry skeleton type.
7
+ * @typeParam M - Chain modifiers.
8
+ * @typeParam L - Locale code.
9
+ * @public
10
+ */
11
+ export interface ResolvedData<S extends EntrySkeletonType, M extends ChainModifiers = ChainModifiers, L extends LocaleCode = LocaleCode> {
12
+ /** The baseline or resolved variant entry. */
13
+ entry: Entry<S, M, L>;
14
+ /** The selected personalization metadata, if a non‑baseline variant was chosen. */
15
+ personalization?: SelectedPersonalization;
16
+ }
17
+ /**
18
+ * Resolve a personalized Contentful entry to the correct variant for the current
19
+ * selections.
20
+ *
21
+ * @public
22
+ * @remarks
23
+ * Given a baseline {@link PersonalizedEntry} and a set of selected personalizations
24
+ * (variants per experience), this resolver finds the matching replacement variant
25
+ * for the component configured against the baseline entry.
26
+ *
27
+ * **Variant indexing**: `variantIndex` in {@link SelectedPersonalization} is treated as
28
+ * 1‑based (index 1 = first variant). A value of `0` indicates baseline.
29
+ */
30
+ declare const PersonalizedEntryResolver: {
31
+ /**
32
+ * Find the personalization entry corresponding to one of the selected experiences.
33
+ *
34
+ * @param params - Object containing the baseline personalized entry and the selections.
35
+ * @param skipValidation - When `true`, skip type/shape validation for perf.
36
+ * @returns The matching {@link PersonalizationEntry}, or `undefined` if not found/invalid.
37
+ * @example
38
+ * ```ts
39
+ * const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry({
40
+ * personalizedEntry: entry,
41
+ * selectedPersonalizations
42
+ * })
43
+ * ```
44
+ * @remarks
45
+ * A personalization entry is a personalization configuration object supplied in a
46
+ * `PersonalizedEntry.nt_experiences` array. A personalized entry may relate to
47
+ * multiple personalizations.
48
+ */
49
+ getPersonalizationEntry({ personalizedEntry, selectedPersonalizations, }: {
50
+ personalizedEntry: PersonalizedEntry;
51
+ selectedPersonalizations: SelectedPersonalizationArray;
52
+ }, skipValidation?: boolean): PersonalizationEntry | undefined;
53
+ /**
54
+ * Look up the selection metadata for a specific personalization entry.
55
+ *
56
+ * @param params - Object with the target personalization entry and selections.
57
+ * @param skipValidation - When `true`, skip type checks.
58
+ * @returns The matching {@link SelectedPersonalization}, if present.
59
+ * @example
60
+ * ```ts
61
+ * const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization({
62
+ * personalizationEntry,
63
+ * selectedPersonalizations
64
+ * })
65
+ * ```
66
+ * @remarks
67
+ * Selected personalizations are supplied by the Experience API in the
68
+ * `experiences` response data property.
69
+ */
70
+ getSelectedPersonalization({ personalizationEntry, selectedPersonalizations, }: {
71
+ personalizationEntry: PersonalizationEntry;
72
+ selectedPersonalizations: SelectedPersonalizationArray;
73
+ }, skipValidation?: boolean): SelectedPersonalization | undefined;
74
+ /**
75
+ * Get the replacement variant config for the given selection index.
76
+ *
77
+ * @param params - Baseline entry, personalization entry, and 1‑based variant index.
78
+ * @param skipValidation - When `true`, skip type checks.
79
+ * @returns The {@link EntryReplacementVariant} for the component, if any.
80
+ * @example
81
+ * ```ts
82
+ * const selectedVariant = PersonalizedEntryResolver.getSelectedVariant({
83
+ * personalizedEntry: entry,
84
+ * personalizationEntry,
85
+ * selectedVariantIndex: 2 // second variant (1‑based)
86
+ * })
87
+ * ```
88
+ * @remarks
89
+ * Entry replacement variants are variant configurations specified in a
90
+ * personalization configuration component's `variants` array supplied by the
91
+ * personalized entry via its `nt_config` field.
92
+ */
93
+ getSelectedVariant({ personalizedEntry, personalizationEntry, selectedVariantIndex, }: {
94
+ personalizedEntry: PersonalizedEntry;
95
+ personalizationEntry: PersonalizationEntry;
96
+ selectedVariantIndex: number;
97
+ }, skipValidation?: boolean): EntryReplacementVariant | undefined;
98
+ /**
99
+ * Resolve the concrete Contentful entry that corresponds to a selected variant.
100
+ *
101
+ * @typeParam S - Entry skeleton type.
102
+ * @typeParam M - Chain modifiers.
103
+ * @typeParam L - Locale code.
104
+ * @param params - Personalization entry and selected variant.
105
+ * @param skipValidation - When `true`, skip type checks.
106
+ * @returns The resolved entry typed as {@link Entry} or `undefined`.
107
+ * @example
108
+ * ```ts
109
+ * const selectedVariantEntry = PersonalizedEntryResolver.getSelectedVariantEntry<{ fields: unknown }>({
110
+ * personalizationEntry,
111
+ * selectedVariant
112
+ * })
113
+ * ```
114
+ * @remarks
115
+ * A personalized entry will resolve either to the baseline (the entry
116
+ * supplied as `personalizedEntry`) or the selected variant.
117
+ */
118
+ getSelectedVariantEntry<S extends EntrySkeletonType, M extends ChainModifiers = ChainModifiers, L extends LocaleCode = string>({ personalizationEntry, selectedVariant, }: {
119
+ personalizationEntry: PersonalizationEntry;
120
+ selectedVariant: EntryReplacementVariant;
121
+ }, skipValidation?: boolean): Entry<S, M, L> | undefined;
122
+ /**
123
+ * Resolve the selected entry (baseline or variant) for a personalized entry
124
+ * and optional selected personalizations, returning both the entry and the
125
+ * personalization metadata.
126
+ *
127
+ * @typeParam S - Entry skeleton type.
128
+ * @typeParam M - Chain modifiers.
129
+ * @typeParam L - Locale code.
130
+ * @param entry - The baseline personalized entry.
131
+ * @param selectedPersonalizations - Optional selections for the current profile.
132
+ * @returns An object containing the resolved entry and (if chosen) the selection.
133
+ * @example
134
+ * ```ts
135
+ * const { entry: personalizedEntry, personalization } = PersonalizedEntryResolver.resolve(entry, selections)
136
+ * if (personalization) console.log('Variant index', personalization.variantIndex)
137
+ * ```
138
+ */
139
+ resolve<S extends EntrySkeletonType, M extends ChainModifiers = ChainModifiers, L extends LocaleCode = string>(entry: Entry<S, M, L>, selectedPersonalizations?: SelectedPersonalizationArray): ResolvedData<S, M, L>;
140
+ };
141
+ export default PersonalizedEntryResolver;
142
+ //# sourceMappingURL=PersonalizedEntryResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalizedEntryResolver.d.ts","sourceRoot":"","sources":["../../../src/personalization/resolvers/PersonalizedEntryResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,uBAAuB,EAM5B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EAClC,MAAM,qCAAqC,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAKtF;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY,CAC3B,CAAC,SAAS,iBAAiB,EAC3B,CAAC,SAAS,cAAc,GAAG,cAAc,EACzC,CAAC,SAAS,UAAU,GAAG,UAAU;IAEjC,8CAA8C;IAC9C,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACrB,mFAAmF;IACnF,eAAe,CAAC,EAAE,uBAAuB,CAAA;CAC1C;AAKD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,yBAAyB;IAC7B;;;;;;;;;;;;;;;;;OAiBG;8EAKE;QACD,iBAAiB,EAAE,iBAAiB,CAAA;QACpC,wBAAwB,EAAE,4BAA4B,CAAA;KACvD,6BAEA,oBAAoB,GAAG,SAAS;IAkBnC;;;;;;;;;;;;;;;;OAgBG;oFAKE;QACD,oBAAoB,EAAE,oBAAoB,CAAA;QAC1C,wBAAwB,EAAE,4BAA4B,CAAA;KACvD,6BAEA,uBAAuB,GAAG,SAAS;IActC;;;;;;;;;;;;;;;;;;OAkBG;2FAME;QACD,iBAAiB,EAAE,iBAAiB,CAAA;QACpC,oBAAoB,EAAE,oBAAoB,CAAA;QAC1C,oBAAoB,EAAE,MAAM,CAAA;KAC7B,6BAEA,uBAAuB,GAAG,SAAS;IAmBtC;;;;;;;;;;;;;;;;;;;OAmBG;4BAED,CAAC,SAAS,iBAAiB,EAC3B,CAAC,SAAS,cAAc,mBACxB,CAAC,SAAS,UAAU,uDAKjB;QACD,oBAAoB,EAAE,oBAAoB,CAAA;QAC1C,eAAe,EAAE,uBAAuB,CAAA;KACzC,6BAEA,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS;IAc7B;;;;;;;;;;;;;;;;OAgBG;YAED,CAAC,SAAS,iBAAiB,EAC3B,CAAC,SAAS,cAAc,mBACxB,CAAC,SAAS,UAAU,kBAEb,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,6BACM,4BAA4B,GACtD,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CAmFzB,CAAA;AAED,eAAe,yBAAyB,CAAA"}
@@ -0,0 +1,196 @@
1
+ import { isEntry, isEntryReplacementComponent, isEntryReplacementVariant, isPersonalizationEntry, isPersonalizedEntry, } from '@contentful/optimization-api-client';
2
+ import { createScopedLogger } from 'logger';
3
+ const logger = createScopedLogger('Personalization');
4
+ /** Base string for resolver warning messages. */
5
+ const RESOLUTION_WARNING_BASE = 'Could not resolve personalized entry variant:';
6
+ /**
7
+ * Resolve a personalized Contentful entry to the correct variant for the current
8
+ * selections.
9
+ *
10
+ * @public
11
+ * @remarks
12
+ * Given a baseline {@link PersonalizedEntry} and a set of selected personalizations
13
+ * (variants per experience), this resolver finds the matching replacement variant
14
+ * for the component configured against the baseline entry.
15
+ *
16
+ * **Variant indexing**: `variantIndex` in {@link SelectedPersonalization} is treated as
17
+ * 1‑based (index 1 = first variant). A value of `0` indicates baseline.
18
+ */
19
+ const PersonalizedEntryResolver = {
20
+ /**
21
+ * Find the personalization entry corresponding to one of the selected experiences.
22
+ *
23
+ * @param params - Object containing the baseline personalized entry and the selections.
24
+ * @param skipValidation - When `true`, skip type/shape validation for perf.
25
+ * @returns The matching {@link PersonalizationEntry}, or `undefined` if not found/invalid.
26
+ * @example
27
+ * ```ts
28
+ * const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry({
29
+ * personalizedEntry: entry,
30
+ * selectedPersonalizations
31
+ * })
32
+ * ```
33
+ * @remarks
34
+ * A personalization entry is a personalization configuration object supplied in a
35
+ * `PersonalizedEntry.nt_experiences` array. A personalized entry may relate to
36
+ * multiple personalizations.
37
+ */
38
+ getPersonalizationEntry({ personalizedEntry, selectedPersonalizations, }, skipValidation = false) {
39
+ if (!skipValidation &&
40
+ (!selectedPersonalizations.length || !isPersonalizedEntry(personalizedEntry)))
41
+ return;
42
+ const personalizationEntry = personalizedEntry.fields.nt_experiences
43
+ .filter((maybePersonalization) => isPersonalizationEntry(maybePersonalization))
44
+ .find((personalizationEntry) => selectedPersonalizations.some(({ experienceId }) => experienceId === personalizationEntry.fields.nt_experience_id));
45
+ return personalizationEntry;
46
+ },
47
+ /**
48
+ * Look up the selection metadata for a specific personalization entry.
49
+ *
50
+ * @param params - Object with the target personalization entry and selections.
51
+ * @param skipValidation - When `true`, skip type checks.
52
+ * @returns The matching {@link SelectedPersonalization}, if present.
53
+ * @example
54
+ * ```ts
55
+ * const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization({
56
+ * personalizationEntry,
57
+ * selectedPersonalizations
58
+ * })
59
+ * ```
60
+ * @remarks
61
+ * Selected personalizations are supplied by the Experience API in the
62
+ * `experiences` response data property.
63
+ */
64
+ getSelectedPersonalization({ personalizationEntry, selectedPersonalizations, }, skipValidation = false) {
65
+ if (!skipValidation &&
66
+ (!selectedPersonalizations.length || !isPersonalizationEntry(personalizationEntry)))
67
+ return;
68
+ const selectedPersonalization = selectedPersonalizations.find(({ experienceId }) => experienceId === personalizationEntry.fields.nt_experience_id);
69
+ return selectedPersonalization;
70
+ },
71
+ /**
72
+ * Get the replacement variant config for the given selection index.
73
+ *
74
+ * @param params - Baseline entry, personalization entry, and 1‑based variant index.
75
+ * @param skipValidation - When `true`, skip type checks.
76
+ * @returns The {@link EntryReplacementVariant} for the component, if any.
77
+ * @example
78
+ * ```ts
79
+ * const selectedVariant = PersonalizedEntryResolver.getSelectedVariant({
80
+ * personalizedEntry: entry,
81
+ * personalizationEntry,
82
+ * selectedVariantIndex: 2 // second variant (1‑based)
83
+ * })
84
+ * ```
85
+ * @remarks
86
+ * Entry replacement variants are variant configurations specified in a
87
+ * personalization configuration component's `variants` array supplied by the
88
+ * personalized entry via its `nt_config` field.
89
+ */
90
+ getSelectedVariant({ personalizedEntry, personalizationEntry, selectedVariantIndex, }, skipValidation = false) {
91
+ if (!skipValidation &&
92
+ (!isPersonalizedEntry(personalizedEntry) || !isPersonalizationEntry(personalizationEntry)))
93
+ return;
94
+ const relevantVariants = personalizationEntry.fields.nt_config?.components
95
+ ?.filter((component) => isEntryReplacementComponent(component) && !component.baseline.hidden)
96
+ .find((component) => component.baseline.id === personalizedEntry.sys.id)?.variants;
97
+ if (!relevantVariants?.length)
98
+ return;
99
+ return relevantVariants.at(selectedVariantIndex - 1);
100
+ },
101
+ /**
102
+ * Resolve the concrete Contentful entry that corresponds to a selected variant.
103
+ *
104
+ * @typeParam S - Entry skeleton type.
105
+ * @typeParam M - Chain modifiers.
106
+ * @typeParam L - Locale code.
107
+ * @param params - Personalization entry and selected variant.
108
+ * @param skipValidation - When `true`, skip type checks.
109
+ * @returns The resolved entry typed as {@link Entry} or `undefined`.
110
+ * @example
111
+ * ```ts
112
+ * const selectedVariantEntry = PersonalizedEntryResolver.getSelectedVariantEntry<{ fields: unknown }>({
113
+ * personalizationEntry,
114
+ * selectedVariant
115
+ * })
116
+ * ```
117
+ * @remarks
118
+ * A personalized entry will resolve either to the baseline (the entry
119
+ * supplied as `personalizedEntry`) or the selected variant.
120
+ */
121
+ getSelectedVariantEntry({ personalizationEntry, selectedVariant, }, skipValidation = false) {
122
+ if (!skipValidation &&
123
+ (!isPersonalizationEntry(personalizationEntry) || !isEntryReplacementVariant(selectedVariant)))
124
+ return;
125
+ const selectedVariantEntry = personalizationEntry.fields.nt_variants?.find((variant) => variant.sys.id === selectedVariant.id);
126
+ return isEntry(selectedVariantEntry) ? selectedVariantEntry : undefined;
127
+ },
128
+ /**
129
+ * Resolve the selected entry (baseline or variant) for a personalized entry
130
+ * and optional selected personalizations, returning both the entry and the
131
+ * personalization metadata.
132
+ *
133
+ * @typeParam S - Entry skeleton type.
134
+ * @typeParam M - Chain modifiers.
135
+ * @typeParam L - Locale code.
136
+ * @param entry - The baseline personalized entry.
137
+ * @param selectedPersonalizations - Optional selections for the current profile.
138
+ * @returns An object containing the resolved entry and (if chosen) the selection.
139
+ * @example
140
+ * ```ts
141
+ * const { entry: personalizedEntry, personalization } = PersonalizedEntryResolver.resolve(entry, selections)
142
+ * if (personalization) console.log('Variant index', personalization.variantIndex)
143
+ * ```
144
+ */
145
+ resolve(entry, selectedPersonalizations) {
146
+ logger.debug(`Resolving personalized entry for baseline entry ${entry.sys.id}`);
147
+ if (!selectedPersonalizations?.length) {
148
+ logger.warn(`${RESOLUTION_WARNING_BASE} no selectedPersonalizations exist for the current profile`);
149
+ return { entry };
150
+ }
151
+ if (!isPersonalizedEntry(entry)) {
152
+ logger.warn(`${RESOLUTION_WARNING_BASE} entry ${entry.sys.id} is not personalized`);
153
+ return { entry };
154
+ }
155
+ const personalizationEntry = PersonalizedEntryResolver.getPersonalizationEntry({
156
+ personalizedEntry: entry,
157
+ selectedPersonalizations,
158
+ }, true);
159
+ if (!personalizationEntry) {
160
+ logger.warn(`${RESOLUTION_WARNING_BASE} could not find a personalization entry for ${entry.sys.id}`);
161
+ return { entry };
162
+ }
163
+ const selectedPersonalization = PersonalizedEntryResolver.getSelectedPersonalization({
164
+ personalizationEntry,
165
+ selectedPersonalizations,
166
+ }, true);
167
+ const selectedVariantIndex = selectedPersonalization?.variantIndex ?? 0;
168
+ if (selectedVariantIndex === 0) {
169
+ logger.debug(`Resolved personalization entry for entry ${entry.sys.id} is baseline`);
170
+ return { entry };
171
+ }
172
+ const selectedVariant = PersonalizedEntryResolver.getSelectedVariant({
173
+ personalizedEntry: entry,
174
+ personalizationEntry,
175
+ selectedVariantIndex,
176
+ }, true);
177
+ if (!selectedVariant) {
178
+ logger.warn(`${RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`);
179
+ return { entry };
180
+ }
181
+ const selectedVariantEntry = PersonalizedEntryResolver.getSelectedVariantEntry({
182
+ personalizationEntry,
183
+ selectedVariant,
184
+ }, true);
185
+ if (!selectedVariantEntry) {
186
+ logger.warn(`${RESOLUTION_WARNING_BASE} could not find a valid replacement variant entry for ${entry.sys.id}`);
187
+ return { entry };
188
+ }
189
+ else {
190
+ logger.debug(`Entry ${entry.sys.id} has been resolved to variant entry ${selectedVariantEntry.sys.id}`);
191
+ }
192
+ return { entry: selectedVariantEntry, personalization: selectedPersonalization };
193
+ },
194
+ };
195
+ export default PersonalizedEntryResolver;
196
+ //# sourceMappingURL=PersonalizedEntryResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalizedEntryResolver.js","sourceRoot":"","sources":["../../../src/personalization/resolvers/PersonalizedEntryResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export * from './FlagsResolver';
2
+ export { default as FlagsResolver } from './FlagsResolver';
3
+ export * from './MergeTagValueResolver';
4
+ export { default as MergeTagValueResolver } from './MergeTagValueResolver';
5
+ export * from './PersonalizedEntryResolver';
6
+ export { default as PersonalizedEntryResolver } from './PersonalizedEntryResolver';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/personalization/resolvers/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE1D,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAE1E,cAAc,6BAA6B,CAAA;AAC3C,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAA"}
@@ -0,0 +1,7 @@
1
+ export * from './FlagsResolver';
2
+ export { default as FlagsResolver } from './FlagsResolver';
3
+ export * from './MergeTagValueResolver';
4
+ export { default as MergeTagValueResolver } from './MergeTagValueResolver';
5
+ export * from './PersonalizedEntryResolver';
6
+ export { default as PersonalizedEntryResolver } from './PersonalizedEntryResolver';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/personalization/resolvers/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE1D,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAE1E,cAAc,6BAA6B,CAAA;AAC3C,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAA"}
@@ -0,0 +1,35 @@
1
+ import type { InsightsEvent as AnalyticsEvent, ChangeArray, Flags, ExperienceEvent as PersonalizationEvent, Profile } from '@contentful/optimization-api-client';
2
+ import { batch, effect, type Signal } from '@preact/signals-core';
3
+ export declare const changes: Signal<ChangeArray | undefined>;
4
+ export declare const consent: Signal<boolean | undefined>;
5
+ export declare const event: Signal<AnalyticsEvent | PersonalizationEvent | undefined>;
6
+ export declare const flags: import("@preact/signals-core").ReadonlySignal<Flags | undefined>;
7
+ export declare const online: Signal<boolean | undefined>;
8
+ export declare const personalizations: Signal<{
9
+ experienceId: string;
10
+ variantIndex: number;
11
+ variants: Record<string, string>;
12
+ sticky?: boolean | undefined;
13
+ }[] | undefined>;
14
+ export declare const profile: Signal<Profile | undefined>;
15
+ export interface Signals {
16
+ changes: typeof changes;
17
+ consent: typeof consent;
18
+ event: typeof event;
19
+ flags: typeof flags;
20
+ online: typeof online;
21
+ personalizations: typeof personalizations;
22
+ profile: typeof profile;
23
+ }
24
+ export interface Subscription {
25
+ unsubscribe: () => void;
26
+ }
27
+ export interface Observable<T> {
28
+ subscribe: (next: (v: T) => void) => Subscription;
29
+ }
30
+ export declare function toObservable<T>(s: {
31
+ value: T;
32
+ }): Observable<T>;
33
+ export declare const signals: Signals;
34
+ export { batch, effect, type Signal };
35
+ //# sourceMappingURL=signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,IAAI,cAAc,EAC/B,WAAW,EACX,KAAK,EACL,eAAe,IAAI,oBAAoB,EACvC,OAAO,EAER,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,KAAK,EAAY,MAAM,EAAU,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAGnF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,CAAqC,CAAA;AAEzF,eAAO,MAAM,OAAO,6BAAgC,CAAA;AAEpD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,cAAc,GAAG,oBAAoB,GAAG,SAAS,CAEzE,CAAA;AAEH,eAAO,MAAM,KAAK,kEAAgF,CAAA;AAElG,eAAO,MAAM,MAAM,6BAAoC,CAAA;AAEvD,eAAO,MAAM,gBAAgB;;;;;gBAAqD,CAAA;AAElF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAiC,CAAA;AAEjF,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,OAAO,OAAO,CAAA;IACvB,OAAO,EAAE,OAAO,OAAO,CAAA;IACvB,KAAK,EAAE,OAAO,KAAK,CAAA;IACnB,KAAK,EAAE,OAAO,KAAK,CAAA;IACnB,MAAM,EAAE,OAAO,MAAM,CAAA;IACrB,gBAAgB,EAAE,OAAO,gBAAgB,CAAA;IACzC,OAAO,EAAE,OAAO,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,KAAK,YAAY,CAAA;CAClD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAU9D;AAED,eAAO,MAAM,OAAO,EAAE,OAQrB,CAAA;AAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { batch, computed, effect, signal } from '@preact/signals-core';
2
+ import { FlagsResolver } from './personalization/resolvers';
3
+ export const changes = signal();
4
+ export const consent = signal();
5
+ export const event = signal();
6
+ export const flags = computed(() => FlagsResolver.resolve(changes.value ?? []));
7
+ export const online = signal(true);
8
+ export const personalizations = signal();
9
+ export const profile = signal();
10
+ export function toObservable(s) {
11
+ return {
12
+ subscribe(next) {
13
+ const dispose = effect(() => {
14
+ next(s.value);
15
+ });
16
+ return { unsubscribe: dispose };
17
+ },
18
+ };
19
+ }
20
+ export const signals = {
21
+ changes,
22
+ consent,
23
+ event,
24
+ flags,
25
+ online,
26
+ personalizations,
27
+ profile,
28
+ };
29
+ export { batch, effect };
30
+ //# sourceMappingURL=signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.js","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAe,MAAM,sBAAsB,CAAA;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAE3D,MAAM,CAAC,MAAM,OAAO,GAAoC,MAAM,EAA2B,CAAA;AAEzF,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,EAAuB,CAAA;AAEpD,MAAM,CAAC,MAAM,KAAK,GAA8D,MAAM,EAEnF,CAAA;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAoB,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAA;AAElG,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAA;AAEvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,EAA4C,CAAA;AAElF,MAAM,CAAC,MAAM,OAAO,GAAgC,MAAM,EAAuB,CAAA;AAoBjF,MAAM,UAAU,YAAY,CAAI,CAAe;IAC7C,OAAO;QACL,SAAS,CAAC,IAAI;YACZ,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE;gBAC1B,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;YACf,CAAC,CAAC,CAAA;YAEF,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAA;QACjC,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,OAAO;IACP,OAAO;IACP,KAAK;IACL,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,OAAO;CACR,CAAA;AAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAe,CAAA"}