@ninetailed/experience.js-utils-contentful 3.0.0-beta.33 → 3.0.0-beta.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,3 +1,11 @@
1
- export * from './types';
2
- export { AudienceMapper, ExperienceMapper, isEntry, isAudienceEntry, isExperienceEntry, } from './lib';
3
- export type { MapVariant } from './lib';
1
+ export { AudienceMapper } from './lib/AudienceMapper';
2
+ export { ExperienceMapper } from './lib/ExperienceMapper';
3
+ export { isEntry } from './lib/isEntry';
4
+ export { isAudienceEntry } from './lib/isAudienceEntry';
5
+ export { isExperienceEntry } from './lib/isExperienceEntry';
6
+ export type { AudienceEntry, AudienceEntryLike, AudienceEntryFields, } from './types/AudienceEntry';
7
+ export type { BaselineWithExperiencesEntry, BaselineWithExperiencesEntryLike, } from './types/BaselineWithExperiencesEntry';
8
+ export type { Entry, EntryLike } from './types/Entry';
9
+ export type { EntryFields } from './types/EntryFields';
10
+ export type { ExperienceEntry, ExperienceEntryLike, ExperienceFields, } from './types/ExperienceEntry';
11
+ export type { ExperimentEntry, ExperimentEntryLike, } from './types/ExperimentEntry';
package/index.js CHANGED
@@ -1,13 +1,23 @@
1
- import { z } from 'zod';
2
- import { Config, ExperienceMapper as ExperienceMapper$1 } from '@ninetailed/experience.js-utils';
3
1
  import { logger } from '@ninetailed/experience.js-shared';
2
+ import { Config, ExperienceMapper as ExperienceMapper$1 } from '@ninetailed/experience.js-utils';
3
+ import { z } from 'zod';
4
+
5
+ class AudienceMapper {
6
+ static mapAudience(audience) {
7
+ return {
8
+ id: audience.fields.nt_audience_id
9
+ };
10
+ }
11
+ }
12
+
13
+ const EntryFields = z.object({}).catchall(z.unknown());
4
14
 
5
15
  const EntryLink = z.object({
6
- type: z.literal('Link'),
16
+ type: z.string(),
7
17
  linkType: z.string(),
8
18
  id: z.string()
9
19
  });
10
- const Entry = z.object({
20
+ const EntrySchema = z.object({
11
21
  sys: z.object({
12
22
  type: z.string().optional(),
13
23
  id: z.string(),
@@ -17,31 +27,52 @@ const Entry = z.object({
17
27
  revision: z.number().optional(),
18
28
  space: z.object({
19
29
  sys: EntryLink.extend({
20
- linkType: z.literal('Space')
30
+ linkType: z.string()
21
31
  })
22
32
  }).optional(),
23
33
  environment: z.object({
24
34
  sys: EntryLink.extend({
25
- linkType: z.literal('Environment')
35
+ linkType: z.string()
26
36
  })
27
37
  }).optional(),
28
38
  contentType: z.object({
29
39
  sys: EntryLink.extend({
30
- linkType: z.literal('ContentType')
40
+ linkType: z.string()
31
41
  })
32
42
  }).optional()
33
43
  }),
34
- fields: z.object({}).passthrough(),
44
+ fields: EntryFields,
35
45
  metadata: z.object({
36
46
  tags: z.array(z.object({
37
47
  sys: EntryLink.extend({
38
- linkType: z.literal('Tag')
48
+ linkType: z.string()
39
49
  })
40
50
  }))
41
51
  }).optional()
42
52
  });
53
+ const parse$1 = input => {
54
+ const output = EntrySchema.parse(input);
55
+ return Object.assign(Object.assign({}, output), {
56
+ fields: input.fields
57
+ });
58
+ };
59
+ const safeParse$1 = input => {
60
+ const output = EntrySchema.safeParse(input);
61
+ if (!output.success) {
62
+ return output;
63
+ }
64
+ return Object.assign(Object.assign({}, output), {
65
+ data: Object.assign(Object.assign({}, output.data), {
66
+ fields: input.fields
67
+ })
68
+ });
69
+ };
70
+ const Entry = Object.assign(Object.assign({}, EntrySchema), {
71
+ parse: parse$1,
72
+ safeParse: safeParse$1
73
+ });
43
74
 
44
- const AudienceFields = z.object({
75
+ const AudienceEntryFields = EntryFields.extend({
45
76
  /**
46
77
  * The name of the audience (Short Text)
47
78
  */
@@ -51,11 +82,11 @@ const AudienceFields = z.object({
51
82
  */
52
83
  nt_audience_id: z.string()
53
84
  });
54
- const AudienceEntry = Entry.extend({
55
- fields: AudienceFields
85
+ const AudienceEntry = EntrySchema.extend({
86
+ fields: AudienceEntryFields
56
87
  });
57
88
 
58
- const ExperienceFields = z.object({
89
+ const ExperienceEntryFields = z.object({
59
90
  /**
60
91
  * The name of the experience (Short Text)
61
92
  */
@@ -63,11 +94,17 @@ const ExperienceFields = z.object({
63
94
  /**
64
95
  * The type if the experience (nt_experiment | nt_personalization)
65
96
  */
66
- nt_type: z.union([z.literal('nt_experiment'), z.literal('nt_personalization')]),
97
+ nt_type: z.union([z.string(), z.string()]),
67
98
  /**
68
99
  * The config of the experience (JSON)
69
100
  */
70
- nt_config: Config.optional().nullable(),
101
+ nt_config: Config.optional().nullable().default(null).transform(val => {
102
+ return val !== null && val !== void 0 ? val : {
103
+ traffic: 0,
104
+ distribution: [0.5, 0.5],
105
+ components: []
106
+ };
107
+ }),
71
108
  /**
72
109
  * The audience of the experience (Audience)
73
110
  */
@@ -75,83 +112,115 @@ const ExperienceFields = z.object({
75
112
  /**
76
113
  * All used variants of the experience (Contentful references to other Content Types)
77
114
  */
78
- nt_variants: z.array(Entry).default([])
115
+ nt_variants: z.array(EntrySchema).default([])
79
116
  });
80
- const ExperienceEntry = Entry.extend({
81
- fields: ExperienceFields
117
+ const ExperienceEntrySchema = EntrySchema.extend({
118
+ fields: ExperienceEntryFields
119
+ });
120
+ const parse = input => {
121
+ const output = ExperienceEntrySchema.parse(input);
122
+ return Object.assign(Object.assign({}, output), {
123
+ fields: Object.assign(Object.assign({}, output.fields), {
124
+ nt_variants: input.fields.nt_variants
125
+ })
126
+ });
127
+ };
128
+ const safeParse = input => {
129
+ const output = ExperienceEntrySchema.safeParse(input);
130
+ if (!output.success) {
131
+ return output;
132
+ }
133
+ return Object.assign(Object.assign({}, output), {
134
+ data: Object.assign(Object.assign({}, output.data), {
135
+ fields: Object.assign(Object.assign({}, output.data.fields), {
136
+ nt_variants: input.fields.nt_variants
137
+ })
138
+ })
139
+ });
140
+ };
141
+ const ExperienceEntry = Object.assign(Object.assign({}, ExperienceEntrySchema), {
142
+ parse,
143
+ safeParse
82
144
  });
83
145
 
84
146
  const ExperimentEntry = ExperienceEntry.extend({
85
- fields: ExperienceFields.extend({
86
- nt_type: z.literal('nt_experiment')
147
+ fields: ExperienceEntryFields.extend({
148
+ nt_type: z.string().regex(/^nt_experiment$/g)
87
149
  })
88
150
  });
89
151
 
90
- class AudienceMapper {
91
- static mapAudience(audience) {
92
- return {
93
- id: audience.fields.nt_audience_id
94
- };
152
+ function mapAudience(ctfAudienceEntry) {
153
+ return {
154
+ id: ctfAudienceEntry.fields.nt_audience_id
155
+ };
156
+ }
157
+ function createExperience(id, fields, variants) {
158
+ const {
159
+ nt_name,
160
+ nt_type,
161
+ nt_audience,
162
+ nt_config
163
+ } = fields;
164
+ return Object.assign(Object.assign({
165
+ id,
166
+ name: nt_name,
167
+ type: nt_type
168
+ }, nt_audience ? {
169
+ audience: mapAudience(nt_audience)
170
+ } : {}), {
171
+ config: nt_config,
172
+ variants
173
+ });
174
+ }
175
+ function validateExperienceEntry(entry) {
176
+ const parsedExperience = ExperienceEntry.safeParse(entry);
177
+ if (!parsedExperience.success) {
178
+ logger.warn('[Ninetailed Contentful ExperienceMapper]', 'Error parsing experience', parsedExperience.error.format());
179
+ throw new Error(`[Ninetailed Contentful ExperienceMapper] The Experience Input is not valid. Please filter data first with "ExperienceMapper.isExperienceEntry".\n${JSON.stringify(parsedExperience.error.format(), null, 2)}`);
95
180
  }
181
+ return parsedExperience.data;
96
182
  }
97
-
98
- const isEntry = entry => {
99
- return Entry.safeParse(entry).success;
100
- };
101
-
102
- const defaultMapVariant = variant => Object.assign(Object.assign({}, variant), {
103
- id: variant.sys.id
104
- });
105
183
  class ExperienceMapper {
106
184
  static isExperienceEntry(entry) {
107
185
  return ExperienceEntry.safeParse(entry).success;
108
186
  }
109
- static mapExperience(entry, options) {
110
- const _mapVariant = (options === null || options === void 0 ? void 0 : options.mapVariant) || defaultMapVariant;
111
- const parsedExperience = ExperienceEntry.safeParse(entry);
112
- if (!parsedExperience.success) {
113
- logger.warn('[Ninetailed Contentful ExperienceMapper]', 'Error parsing experience', parsedExperience.error.format());
114
- throw new Error(`[Ninetailed Contentful ExperienceMapper] The Experience Input is not valid. Please filter data first with "ExperienceMapper.isExperienceEntry".\n${JSON.stringify(parsedExperience.error.format(), null, 2)}`);
115
- }
187
+ static mapExperience(ctfEntry) {
116
188
  const {
117
- sys: {
118
- id
119
- },
120
- fields: {
121
- nt_type,
122
- nt_name,
123
- nt_config,
124
- nt_audience,
125
- nt_variants
126
- }
127
- } = parsedExperience.data;
128
- return ExperienceMapper$1.mapExperience(Object.assign(Object.assign(Object.assign({
129
- id,
130
- type: nt_type,
131
- name: nt_name
132
- }, nt_audience ? {
133
- audience: AudienceMapper.mapAudience(nt_audience)
134
- } : {}), nt_config ? {
135
- config: nt_config
136
- } : {}), {
137
- variants: nt_variants.map(variant => _mapVariant(variant))
189
+ sys,
190
+ fields
191
+ } = validateExperienceEntry(ctfEntry);
192
+ const variants = fields.nt_variants.map(variant => Object.assign(Object.assign({}, variant), {
193
+ id: variant.sys.id
138
194
  }));
195
+ const experience = createExperience(sys.id, fields, variants);
196
+ return ExperienceMapper$1.mapExperience(experience);
197
+ }
198
+ static mapCustomExperience(ctfEntry, mapFn) {
199
+ const {
200
+ sys,
201
+ fields
202
+ } = validateExperienceEntry(ctfEntry);
203
+ const variants = fields.nt_variants.map(variantEntry => mapFn(variantEntry));
204
+ const experience = createExperience(sys.id, fields, variants);
205
+ return ExperienceMapper$1.mapExperience(experience);
139
206
  }
140
207
  static isExperiment(entry) {
141
208
  return ExperimentEntry.safeParse(entry).success;
142
209
  }
143
210
  static mapExperiment(entry) {
144
- return ExperienceMapper.mapExperience(entry, {
145
- mapVariant: () => ({
146
- id: ''
147
- })
148
- });
211
+ return ExperienceMapper.mapCustomExperience(entry, () => ({
212
+ id: ''
213
+ }));
149
214
  }
150
215
  static mapBaselineWithExperiences(entry) {
151
- return entry.fields.nt_experiences.filter(isEntry).map(experience => ExperienceMapper.mapExperience(experience));
216
+ return entry.fields.nt_experiences.filter(ExperienceMapper.isExperienceEntry).map(experience => ExperienceMapper.mapExperience(experience));
152
217
  }
153
218
  }
154
219
 
220
+ const isEntry = entry => {
221
+ return Entry.safeParse(entry).success;
222
+ };
223
+
155
224
  const isAudienceEntry = entry => {
156
225
  return AudienceEntry.safeParse(entry).success;
157
226
  };
@@ -160,4 +229,4 @@ const isExperienceEntry = entry => {
160
229
  return ExperienceEntry.safeParse(entry).success;
161
230
  };
162
231
 
163
- export { AudienceEntry, AudienceMapper, Entry, ExperienceEntry, ExperienceMapper, ExperimentEntry, isAudienceEntry, isEntry, isExperienceEntry };
232
+ export { AudienceMapper, ExperienceMapper, isAudienceEntry, isEntry, isExperienceEntry };
@@ -1,16 +1,103 @@
1
- import { ExperienceConfiguration } from '@ninetailed/experience.js';
2
- import { Variant } from '@ninetailed/experience.js-utils';
3
- import { ExperienceEntry, Entry, ExperimentEntry } from '../types';
1
+ import { Reference } from '@ninetailed/experience.js';
4
2
  import { BaselineWithExperiencesEntry } from '../types/BaselineWithExperiencesEntry';
5
- export declare type MapVariant<VariantType extends Entry = Entry> = (variant: VariantType) => Variant;
6
- declare type MapExperienceOptions = {
7
- mapVariant?: MapVariant;
8
- };
3
+ import { EntryLike } from '../types/Entry';
4
+ import { EntryFields } from '../types/EntryFields';
5
+ import { ExperienceEntry, ExperienceEntryLike } from '../types/ExperienceEntry';
6
+ import { ExperimentEntry, ExperimentEntryLike } from '../types/ExperimentEntry';
7
+ export declare type MapVariantFunction<In extends EntryFields, Out extends Reference> = (input: EntryLike<In> & {
8
+ fields: In;
9
+ }) => Out;
9
10
  export declare class ExperienceMapper {
10
- static isExperienceEntry(entry: unknown): entry is ExperienceEntry;
11
- static mapExperience(entry: ExperienceEntry, options?: MapExperienceOptions): ExperienceConfiguration;
12
- static isExperiment(entry: Entry): entry is ExperimentEntry;
13
- static mapExperiment(entry: ExperienceEntry): ExperienceConfiguration;
14
- static mapBaselineWithExperiences(entry: BaselineWithExperiencesEntry): ExperienceConfiguration[];
11
+ static isExperienceEntry<Fields extends EntryFields>(entry: ExperienceEntryLike<Fields>): entry is ExperienceEntry<Fields>;
12
+ static mapExperience<VariantFields extends EntryFields>(ctfEntry: ExperienceEntryLike<VariantFields>): import("@ninetailed/experience.js").ExperienceConfiguration<{
13
+ id: string;
14
+ sys: {
15
+ type?: string | undefined;
16
+ createdAt?: string | undefined;
17
+ updatedAt?: string | undefined;
18
+ locale?: string | undefined;
19
+ revision?: number | undefined;
20
+ space?: {
21
+ sys: {
22
+ type: "Link";
23
+ id: string;
24
+ linkType: "Space";
25
+ };
26
+ } | undefined;
27
+ environment?: {
28
+ sys: {
29
+ type: "Link";
30
+ id: string;
31
+ linkType: "Environment";
32
+ };
33
+ } | undefined;
34
+ contentType?: {
35
+ sys: {
36
+ type: "Link";
37
+ id: string;
38
+ linkType: "ContentType";
39
+ };
40
+ } | undefined;
41
+ id: string;
42
+ };
43
+ metadata?: {
44
+ tags: {
45
+ sys: {
46
+ type: "Link";
47
+ id: string;
48
+ linkType: "Tag";
49
+ };
50
+ }[];
51
+ } | undefined;
52
+ fields: VariantFields;
53
+ }>;
54
+ static mapCustomExperience<Variant extends Reference, VariantFields extends EntryFields>(ctfEntry: ExperienceEntryLike<VariantFields>, mapFn: MapVariantFunction<VariantFields, Variant>): import("@ninetailed/experience.js").ExperienceConfiguration<Variant>;
55
+ static isExperiment(entry: ExperimentEntryLike): entry is ExperimentEntry;
56
+ static mapExperiment(entry: ExperienceEntry): import("@ninetailed/experience.js").ExperienceConfiguration<{
57
+ id: string;
58
+ }>;
59
+ static mapBaselineWithExperiences<Fields extends EntryFields>(entry: BaselineWithExperiencesEntry<Fields>): import("@ninetailed/experience.js").ExperienceConfiguration<{
60
+ id: string;
61
+ sys: {
62
+ type?: string | undefined;
63
+ createdAt?: string | undefined;
64
+ updatedAt?: string | undefined;
65
+ locale?: string | undefined;
66
+ revision?: number | undefined;
67
+ space?: {
68
+ sys: {
69
+ type: "Link";
70
+ id: string;
71
+ linkType: "Space";
72
+ };
73
+ } | undefined;
74
+ environment?: {
75
+ sys: {
76
+ type: "Link";
77
+ id: string;
78
+ linkType: "Environment";
79
+ };
80
+ } | undefined;
81
+ contentType?: {
82
+ sys: {
83
+ type: "Link";
84
+ id: string;
85
+ linkType: "ContentType";
86
+ };
87
+ } | undefined;
88
+ id: string;
89
+ };
90
+ metadata?: {
91
+ tags: {
92
+ sys: {
93
+ type: "Link";
94
+ id: string;
95
+ linkType: "Tag";
96
+ };
97
+ }[];
98
+ } | undefined;
99
+ fields: {
100
+ [x: string]: unknown;
101
+ };
102
+ }>[];
15
103
  }
16
- export {};
@@ -0,0 +1,229 @@
1
+ export declare const EXPERIENCES: {
2
+ metadata: {
3
+ tags: never[];
4
+ };
5
+ sys: {
6
+ space: {
7
+ sys: {
8
+ type: "Link";
9
+ linkType: "Space";
10
+ id: string;
11
+ };
12
+ };
13
+ id: string;
14
+ type: "Entry";
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ environment: {
18
+ sys: {
19
+ id: string;
20
+ type: "Link";
21
+ linkType: "Environment";
22
+ };
23
+ };
24
+ revision: number;
25
+ contentType: {
26
+ sys: {
27
+ type: "Link";
28
+ linkType: "ContentType";
29
+ id: string;
30
+ };
31
+ };
32
+ locale: string;
33
+ };
34
+ fields: {
35
+ nt_name: string;
36
+ nt_description: string;
37
+ nt_type: "nt_personalization";
38
+ nt_config: {
39
+ traffic: number;
40
+ components: {
41
+ baseline: {
42
+ id: string;
43
+ title: string;
44
+ };
45
+ variants: {
46
+ id: string;
47
+ hidden: boolean;
48
+ }[];
49
+ }[];
50
+ distribution: number[];
51
+ };
52
+ nt_audience: {
53
+ metadata: {
54
+ tags: never[];
55
+ };
56
+ sys: {
57
+ space: {
58
+ sys: {
59
+ type: "Link";
60
+ linkType: "Space";
61
+ id: string;
62
+ };
63
+ };
64
+ id: string;
65
+ type: "Entry";
66
+ createdAt: string;
67
+ updatedAt: string;
68
+ environment: {
69
+ sys: {
70
+ id: string;
71
+ type: "Link";
72
+ linkType: "Environment";
73
+ };
74
+ };
75
+ revision: number;
76
+ contentType: {
77
+ sys: {
78
+ type: "Link";
79
+ linkType: "ContentType";
80
+ id: string;
81
+ };
82
+ };
83
+ locale: string;
84
+ };
85
+ fields: {
86
+ nt_name: string;
87
+ nt_rules: {
88
+ any: {
89
+ all: {
90
+ type: string;
91
+ operator: string;
92
+ count: string;
93
+ value: string;
94
+ key: string;
95
+ conditions: {
96
+ key: {
97
+ id: string;
98
+ value: string;
99
+ key: string;
100
+ category: {
101
+ name: string;
102
+ label: string;
103
+ type: string;
104
+ };
105
+ label: string;
106
+ useOnce: boolean;
107
+ };
108
+ operator: string;
109
+ value: string;
110
+ }[];
111
+ }[];
112
+ }[];
113
+ };
114
+ nt_audience_id: string;
115
+ };
116
+ };
117
+ nt_variants: {
118
+ metadata: {
119
+ tags: never[];
120
+ };
121
+ sys: {
122
+ space: {
123
+ sys: {
124
+ type: "Link";
125
+ linkType: "Space";
126
+ id: string;
127
+ };
128
+ };
129
+ id: string;
130
+ type: "Entry";
131
+ createdAt: string;
132
+ updatedAt: string;
133
+ environment: {
134
+ sys: {
135
+ id: string;
136
+ type: "Link";
137
+ linkType: "Environment";
138
+ };
139
+ };
140
+ revision: number;
141
+ contentType: {
142
+ sys: {
143
+ type: "Link";
144
+ linkType: "ContentType";
145
+ id: string;
146
+ };
147
+ };
148
+ locale: string;
149
+ };
150
+ fields: {
151
+ entryTitle: string;
152
+ variant: string;
153
+ description: {
154
+ data: {};
155
+ content: {
156
+ data: {};
157
+ content: {
158
+ data: {};
159
+ marks: {
160
+ type: string;
161
+ }[];
162
+ value: string;
163
+ nodeType: string;
164
+ }[];
165
+ nodeType: string;
166
+ }[];
167
+ nodeType: string;
168
+ };
169
+ desktopImage: {
170
+ url: string;
171
+ tags: never[];
172
+ type: string;
173
+ bytes: number;
174
+ width: number;
175
+ format: string;
176
+ height: number;
177
+ context: {
178
+ custom: {
179
+ alt: string;
180
+ };
181
+ };
182
+ version: number;
183
+ duration: null;
184
+ metadata: never[];
185
+ public_id: string;
186
+ created_at: string;
187
+ secure_url: string;
188
+ original_url: string;
189
+ resource_type: string;
190
+ raw_transformation: string;
191
+ original_secure_url: string;
192
+ }[];
193
+ mobileImage: {
194
+ url: string;
195
+ tags: never[];
196
+ type: string;
197
+ bytes: number;
198
+ width: number;
199
+ format: string;
200
+ height: number;
201
+ context: {
202
+ custom: {
203
+ alt: string;
204
+ };
205
+ };
206
+ version: number;
207
+ duration: null;
208
+ metadata: never[];
209
+ public_id: string;
210
+ created_at: string;
211
+ secure_url: string;
212
+ original_url: string;
213
+ resource_type: string;
214
+ raw_transformation: string;
215
+ original_secure_url: string;
216
+ }[];
217
+ ctaLink: {
218
+ id: string;
219
+ url: string;
220
+ type: string;
221
+ label: string;
222
+ }[];
223
+ theme: string;
224
+ headline: string;
225
+ headlineStyle: string;
226
+ };
227
+ }[];
228
+ };
229
+ }[];
@@ -1,5 +1,5 @@
1
- import { Entry } from '../types';
2
- export declare const isAudienceEntry: (entry?: Entry) => entry is {
1
+ import { AudienceEntryLike } from '../types/AudienceEntry';
2
+ export declare const isAudienceEntry: (entry: AudienceEntryLike) => entry is {
3
3
  metadata?: {
4
4
  tags: {
5
5
  sys: {
@@ -39,6 +39,7 @@ export declare const isAudienceEntry: (entry?: Entry) => entry is {
39
39
  id: string;
40
40
  };
41
41
  fields: {
42
+ [x: string]: unknown;
42
43
  nt_name: string;
43
44
  nt_audience_id: string;
44
45
  };