@contentchef/contentchef-types 11.0.0-alpha.1 → 11.0.0-alpha.2

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.
@@ -367,6 +367,12 @@ export type ListContentsFilters = {
367
367
  * Filter list by ContentTranslation status
368
368
  */
369
369
  translationStatus?: ContentTranslationStatus;
370
+ /**
371
+ * This filter is used to search contents whose segmented fields have rules referencing the segments
372
+ * inserted, as `segment` or `segment:key` tokens. A bare `segment` matches whichever key a content
373
+ * uses it with, and several tokens narrow the result like `tags` do
374
+ */
375
+ segments?: string[];
370
376
  };
371
377
  /**
372
378
  * This type represent the data needed to make a list content API request
@@ -771,7 +777,16 @@ export declare enum ContentFieldViolationCodes {
771
777
  textFieldValueIsNotAString = "textField.valueIsNotAString",
772
778
  textFieldBlankValueNotAllowed = "textField.blankValueNotAllowed",
773
779
  segmentedFieldValueIsNotSegmented = "segmentedField.valueIsNotSegmented",
774
- segmentedFieldSegmentNotDeclared = "segmentedField.segmentNotDeclared"
780
+ segmentedFieldRulesIsNotAnArray = "segmentedField.rulesIsNotAnArray",
781
+ segmentedFieldRuleIsNotAnObject = "segmentedField.ruleIsNotAnObject",
782
+ segmentedFieldRuleConditionMissing = "segmentedField.ruleConditionMissing",
783
+ segmentedFieldDuplicateRuleId = "segmentedField.duplicateRuleId",
784
+ segmentedFieldSegmentNotDeclared = "segmentedField.segmentNotDeclared",
785
+ segmentedFieldFallbackRequired = "segmentedField.fallbackRequired",
786
+ segmentedFieldSegmentNotFound = "segmentedField.segmentNotFound",
787
+ segmentedFieldSegmentArchived = "segmentedField.segmentArchived",
788
+ segmentedFieldSegmentKeyNotFound = "segmentedField.segmentKeyNotFound",
789
+ segmentedFieldSegmentKeyDeprecated = "segmentedField.segmentKeyDeprecated"
775
790
  }
776
791
  /**
777
792
  * Request type for getContentStatus
@@ -87,7 +87,16 @@ var ContentFieldViolationCodes;
87
87
  ContentFieldViolationCodes["textFieldValueIsNotAString"] = "textField.valueIsNotAString";
88
88
  ContentFieldViolationCodes["textFieldBlankValueNotAllowed"] = "textField.blankValueNotAllowed";
89
89
  ContentFieldViolationCodes["segmentedFieldValueIsNotSegmented"] = "segmentedField.valueIsNotSegmented";
90
+ ContentFieldViolationCodes["segmentedFieldRulesIsNotAnArray"] = "segmentedField.rulesIsNotAnArray";
91
+ ContentFieldViolationCodes["segmentedFieldRuleIsNotAnObject"] = "segmentedField.ruleIsNotAnObject";
92
+ ContentFieldViolationCodes["segmentedFieldRuleConditionMissing"] = "segmentedField.ruleConditionMissing";
93
+ ContentFieldViolationCodes["segmentedFieldDuplicateRuleId"] = "segmentedField.duplicateRuleId";
90
94
  ContentFieldViolationCodes["segmentedFieldSegmentNotDeclared"] = "segmentedField.segmentNotDeclared";
95
+ ContentFieldViolationCodes["segmentedFieldFallbackRequired"] = "segmentedField.fallbackRequired";
96
+ ContentFieldViolationCodes["segmentedFieldSegmentNotFound"] = "segmentedField.segmentNotFound";
97
+ ContentFieldViolationCodes["segmentedFieldSegmentArchived"] = "segmentedField.segmentArchived";
98
+ ContentFieldViolationCodes["segmentedFieldSegmentKeyNotFound"] = "segmentedField.segmentKeyNotFound";
99
+ ContentFieldViolationCodes["segmentedFieldSegmentKeyDeprecated"] = "segmentedField.segmentKeyDeprecated";
91
100
  })(ContentFieldViolationCodes || (exports.ContentFieldViolationCodes = ContentFieldViolationCodes = {}));
92
101
  var LocalizationSettings;
93
102
  (function (LocalizationSettings) {
@@ -175,6 +175,11 @@ export type ContentDefinitionResponse = {
175
175
  * Valued with paths to each array or null if definition is legacy
176
176
  */
177
177
  trackableArrayFields?: ArrayField[] | null;
178
+ /**
179
+ * The mnemonic ids of the segments this definition's segmented fields vary by
180
+ * Derived from the schema on every save, never assigned by the client
181
+ */
182
+ segments?: string[];
178
183
  };
179
184
  /**
180
185
  * This type represent the response of a create content definition API request
@@ -390,5 +395,7 @@ export declare enum SchemaFieldViolationCodes {
390
395
  invalidEnumValue = "invalidEnumValue",
391
396
  compactCannotBeNested = "compactCannotBeNested",
392
397
  segmentTypeNotAllowed = "segmentTypeNotAllowed",
393
- segmentNameNotFound = "segmentNameNotFound"
398
+ segmentNameNotFound = "segmentNameNotFound",
399
+ segmentArchived = "segmentArchived",
400
+ duplicateSegmentName = "duplicateSegmentName"
394
401
  }
@@ -47,4 +47,6 @@ var SchemaFieldViolationCodes;
47
47
  SchemaFieldViolationCodes["compactCannotBeNested"] = "compactCannotBeNested";
48
48
  SchemaFieldViolationCodes["segmentTypeNotAllowed"] = "segmentTypeNotAllowed";
49
49
  SchemaFieldViolationCodes["segmentNameNotFound"] = "segmentNameNotFound";
50
+ SchemaFieldViolationCodes["segmentArchived"] = "segmentArchived";
51
+ SchemaFieldViolationCodes["duplicateSegmentName"] = "duplicateSegmentName";
50
52
  })(SchemaFieldViolationCodes || (exports.SchemaFieldViolationCodes = SchemaFieldViolationCodes = {}));
@@ -295,66 +295,37 @@ export type OneLinkedContentOfConstraints = {
295
295
  linkType?: LinkType;
296
296
  };
297
297
  /**
298
- * This type represent one segment of a segmented field: the same `{ type, constraints }` pair a
299
- * schema field carries, minus the name, because the map key in `SegmentsTable` is the name
298
+ * This type represent what every value of a segmented field holds: one descriptor for the whole field,
299
+ * so the rules and the fallback cannot differ in type
300
300
  *
301
- * `oneLinkedContentOf` is the only reference form admitted, `linked-content` is its single
302
- * definition special case and carries the identical payload value
301
+ * Only the two `one...Of` forms are admitted: `fragment` and `linked-content` are each the
302
+ * single-target special case of one of them, carrying an identical payload value
303
303
  */
304
- export type SegmentDescriptor = {
305
- type: SchemaTypeIds.FRAGMENT;
306
- constraints: FragmentFieldConstraints;
307
- } | {
304
+ export type SegmentVariantType = {
308
305
  type: SchemaTypeIds.ONE_FRAGMENT_OF;
309
306
  constraints: OneFragmentOfConstraints;
310
307
  } | {
311
308
  type: SchemaTypeIds.ONE_LINKED_CONTENT_OF;
312
309
  constraints: OneLinkedContentOfConstraints;
313
310
  };
314
- /**
315
- * This type represent the model to define a segment of a segmented field
316
- */
317
- export type SegmentDefinition = SegmentDescriptor & {
318
- /**
319
- * The friendly labels of the segment
320
- */
321
- labels?: I18NDictionary;
322
- };
323
- /**
324
- * This type represent the model of the attribute segments of a segmented field, keyed by segment
325
- * name, like `FragmentsTable`
326
- * Names must match `^[a-z0-9_-]+$` and are unordered
327
- */
328
- export type SegmentsTable = {
329
- /**
330
- * The name is the unique id of the segment and its value is the model representing the segment
331
- */
332
- [name: string]: SegmentDefinition;
333
- };
334
- /**
335
- * This enum constrains every segment of a field to one family
336
- * When omitted, segments of both families are allowed in the same field
337
- */
338
- export declare enum SegmentsType {
339
- FRAGMENTS = "fragments",
340
- REFERENCES = "references"
341
- }
342
311
  /**
343
312
  * This type represent the model of a segmented field constraints
313
+ *
314
+ * A segmented field declares only *what varies* and *what shape the values have*. Which conditions
315
+ * exist and what each of them serves is authored per content, as an ordered list of rules plus a
316
+ * fallback - see [[SegmentedFieldPayload]] - so no combination has to be pre-declared here and two
317
+ * contents of the same definition may carry entirely different rule sets
344
318
  */
345
319
  export type SegmentedFieldConstraints = {
346
320
  /**
347
- * Set this value to define the segments the field is made of
348
- */
349
- segments: SegmentsTable;
350
- /**
351
- * Set this value to define the segment served when the request matches none of this field's segments
321
+ * The mnemonic ids of the segments this field varies by. Declaration order carries no meaning: a
322
+ * rule wins by being first in the content, not by which segment it constrains
352
323
  */
353
- defaultSegment?: string;
324
+ segments: string[];
354
325
  /**
355
- * Set this value to constrain every segment of the field to one family
326
+ * The shape every rule value and the fallback conform to
356
327
  */
357
- segmentsType?: SegmentsType;
328
+ variantType: SegmentVariantType;
358
329
  };
359
330
  /**
360
331
  * This type represent the model of an array field constraints
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SegmentsType = exports.LinkType = exports.LongTextSubTypes = exports.SchemaTypeIds = void 0;
3
+ exports.LinkType = exports.LongTextSubTypes = exports.SchemaTypeIds = void 0;
4
4
  /**
5
5
  * This enum represent al possible schema field type ids
6
6
  */
@@ -40,12 +40,3 @@ var LinkType;
40
40
  LinkType[LinkType["LAZY"] = 1] = "LAZY";
41
41
  LinkType[LinkType["COMPACT"] = 2] = "COMPACT";
42
42
  })(LinkType || (exports.LinkType = LinkType = {}));
43
- /**
44
- * This enum constrains every segment of a field to one family
45
- * When omitted, segments of both families are allowed in the same field
46
- */
47
- var SegmentsType;
48
- (function (SegmentsType) {
49
- SegmentsType["FRAGMENTS"] = "fragments";
50
- SegmentsType["REFERENCES"] = "references";
51
- })(SegmentsType || (exports.SegmentsType = SegmentsType = {}));
@@ -0,0 +1,312 @@
1
+ import { AuthorResponse } from './Author';
2
+ import { PagedListResponse } from './common';
3
+ import { ContentDefinitionId } from './ContentDefinition';
4
+ /**
5
+ * The segment unique id
6
+ */
7
+ export type SegmentId = number;
8
+ /**
9
+ * A segment's mnemonicId and every one of its keys must match this pattern: lowercase, digits,
10
+ * underscore and hyphen. Stricter than the other authoring mnemonicIds on purpose, because both halves
11
+ * travel in the delivery `segments` query param and are compared against strings a client supplies
12
+ */
13
+ export declare const SEGMENT_NAME_PATTERN: RegExp;
14
+ /**
15
+ * This type represent one key of a segment, that is one of the values a visitor can have for it
16
+ */
17
+ export type SegmentKey = {
18
+ /**
19
+ * The key, matching [[SEGMENT_NAME_PATTERN]]
20
+ */
21
+ key: string;
22
+ /**
23
+ * A deprecated key cannot be referenced by new content rules, while every rule already written
24
+ * keeps resolving. The flag toggles both ways
25
+ */
26
+ deprecated?: boolean;
27
+ };
28
+ /**
29
+ * This type represent the model of a segment, that is a dimension a content can vary by - `gender`,
30
+ * `loyalty`, `auth_status` - holding the fixed set of keys a visitor can have for it
31
+ *
32
+ * Contents reference a segment by mnemonicId and key inside their rules, and definitions by
33
+ * mnemonicId, so segments are archived and never deleted, and a key can only be removed or renamed
34
+ * while no content references it
35
+ */
36
+ export type SegmentResponse = {
37
+ /**
38
+ * The segment unique id
39
+ */
40
+ id: SegmentId;
41
+ /**
42
+ * The segment name
43
+ */
44
+ name: string;
45
+ /**
46
+ * The segment mnemonic id, matching [[SEGMENT_NAME_PATTERN]]
47
+ */
48
+ mnemonicId: string;
49
+ /**
50
+ * The keys a visitor can hold for this segment, each carrying its own deprecation state
51
+ */
52
+ keys: SegmentKey[];
53
+ /**
54
+ * The archived status of the segment
55
+ */
56
+ archived: boolean;
57
+ /**
58
+ * The archive date of the segment
59
+ */
60
+ archivedDate: Date | null;
61
+ /**
62
+ * The segment creation date
63
+ */
64
+ createdDate: Date;
65
+ /**
66
+ * The segment last modified date
67
+ */
68
+ lastModifiedDate: Date;
69
+ /**
70
+ * The segment author, resolved by `list` only
71
+ */
72
+ author?: AuthorResponse;
73
+ /**
74
+ * The segment last modified author, resolved by every endpoint but `get`
75
+ */
76
+ latestContributor?: AuthorResponse;
77
+ };
78
+ /**
79
+ * This type represent all possible filters used to retrieve a list of segment
80
+ */
81
+ export type ListSegmentsFilters = {
82
+ /**
83
+ * This filter is used to retrieve archived or not archived segments. Defaults to not archived
84
+ */
85
+ archived?: boolean;
86
+ };
87
+ /**
88
+ * This type represent the data needed to make a list segments API request
89
+ */
90
+ export type ListSegmentsRequest = {
91
+ /**
92
+ * The number of segments to skip (this value is used for pagination)
93
+ */
94
+ skip?: number;
95
+ /**
96
+ * The number of segments to take (this value is used for pagination), at most 100
97
+ */
98
+ take?: number;
99
+ /**
100
+ * The data used to filter the list of segments
101
+ */
102
+ filters?: ListSegmentsFilters;
103
+ };
104
+ /**
105
+ * This type represent the item of a list segments API request
106
+ */
107
+ export type ListSegmentsItem = SegmentResponse;
108
+ /**
109
+ * This type represent the response of a list segments API request
110
+ */
111
+ export type ListSegmentsResponse = PagedListResponse<ListSegmentsItem>;
112
+ /**
113
+ * This type represent the usage of one key of a segment. A key with no entry is used by no content,
114
+ * and is therefore the only kind of key that can be removed or renamed
115
+ */
116
+ export type SegmentKeyUsage = {
117
+ /**
118
+ * The key, or null for the rules that constrain the segment without naming any key - that is the
119
+ * ones that only fire when the segment is unknown
120
+ */
121
+ key: string | null;
122
+ /**
123
+ * How many contents reference this key
124
+ */
125
+ contents: number;
126
+ };
127
+ /**
128
+ * This type represent a content definition that declares a segment
129
+ */
130
+ export type DefinitionUsingSegment = {
131
+ /**
132
+ * The content definition unique id
133
+ */
134
+ id: ContentDefinitionId;
135
+ /**
136
+ * The content definition mnemonic id
137
+ */
138
+ mnemonicId: string;
139
+ /**
140
+ * The content definition name
141
+ */
142
+ name: string;
143
+ };
144
+ /**
145
+ * This type represent the data needed to make a get segment API request
146
+ */
147
+ export type GetSegmentRequest = {
148
+ /**
149
+ * The unique segment id to retrieve
150
+ */
151
+ id: SegmentId;
152
+ };
153
+ /**
154
+ * This type represent the response of a get segment API request: the segment, plus the two things the
155
+ * editor cannot decide without, which keys are in use and which definitions vary by this segment
156
+ */
157
+ export type GetSegmentResponse = SegmentResponse & {
158
+ /**
159
+ * One entry per key at least one content references. A key absent from this list is unused
160
+ */
161
+ keyUsage: SegmentKeyUsage[];
162
+ /**
163
+ * The content definitions declaring this segment
164
+ */
165
+ definitions: DefinitionUsingSegment[];
166
+ };
167
+ /**
168
+ * This type represent the data needed to make a create segment API request
169
+ */
170
+ export type CreateSegmentRequest = {
171
+ /**
172
+ * The segment name
173
+ */
174
+ name: string;
175
+ /**
176
+ * The segment mnemonic id, matching [[SEGMENT_NAME_PATTERN]]
177
+ */
178
+ mnemonicId: string;
179
+ /**
180
+ * The keys a visitor can hold for this segment, at least one, each key unique
181
+ */
182
+ keys: SegmentKey[];
183
+ };
184
+ /**
185
+ * This type represent the response of a create segment API request
186
+ */
187
+ export type CreateSegmentResponse = SegmentResponse;
188
+ /**
189
+ * This type represent the data needed to make an update segment API request
190
+ *
191
+ * `keys` replaces the whole stored list, deprecation flags included. Adding keys and toggling
192
+ * deprecation are always allowed, while removing or renaming a key is refused while a content still
193
+ * references it. `mnemonicId` cannot be changed
194
+ */
195
+ export type UpdateSegmentRequest = {
196
+ /**
197
+ * The segment unique id
198
+ */
199
+ id: SegmentId;
200
+ /**
201
+ * The segment name to update
202
+ */
203
+ name: string;
204
+ /**
205
+ * The segment mnemonic id, which must be the stored one
206
+ */
207
+ mnemonicId: string;
208
+ /**
209
+ * The whole key list, replacing what is stored
210
+ */
211
+ keys: SegmentKey[];
212
+ };
213
+ /**
214
+ * This type represent the response of an update segment API request
215
+ */
216
+ export type UpdateSegmentResponse = SegmentResponse;
217
+ /**
218
+ * This type represent the data needed to make a toggle archived segment API request
219
+ */
220
+ export type ToggleArchivedSegmentRequest = {
221
+ /**
222
+ * The segment unique id
223
+ */
224
+ id: SegmentId;
225
+ /**
226
+ * This value represent the archive status to set in the specified segment
227
+ */
228
+ archived: boolean;
229
+ };
230
+ /**
231
+ * This type represent the response of a toggle archived segment API request
232
+ */
233
+ export type ToggleArchivedSegmentResponse = SegmentResponse;
234
+ /**
235
+ * This type represent the condition of one rule on a single segment: the visitor's value for
236
+ * [[segment]] has to be one of [[in]]
237
+ */
238
+ export type SegmentPredicate = {
239
+ /**
240
+ * The mnemonic id of the segment this predicate constrains, which the field must declare
241
+ */
242
+ segment: string;
243
+ /**
244
+ * The keys of the segment that satisfy this predicate
245
+ */
246
+ in: string[];
247
+ /**
248
+ * Set this value to also satisfy the predicate when the segment was not provided at all
249
+ *
250
+ * Not-provided is not a key, so no list of keys can express it, and an enumeration would silently
251
+ * narrow the moment a key is added to the segment. A key that was provided but is not listed does
252
+ * not satisfy this flag: it falls through to the field's fallback
253
+ */
254
+ orUnset?: boolean;
255
+ };
256
+ /**
257
+ * This type represent a condition satisfied when every child condition is satisfied
258
+ */
259
+ export type AllSegmentPredicate = {
260
+ all: SegmentRuleCondition[];
261
+ };
262
+ /**
263
+ * This type represent a condition satisfied when at least one child condition is satisfied
264
+ */
265
+ export type AnySegmentPredicate = {
266
+ any: SegmentRuleCondition[];
267
+ };
268
+ /**
269
+ * This type represent the condition of a rule
270
+ *
271
+ * The stored form is a tree so that new kinds of condition stay additive, but an editor only needs to
272
+ * build an [[AllSegmentPredicate]] of one [[SegmentPredicate]] per segment: or within a segment, and
273
+ * between segments. A segment the condition does not mention is unconstrained, which is a different
274
+ * thing from one listed with [[SegmentPredicate.orUnset]]
275
+ */
276
+ export type SegmentRuleCondition = SegmentPredicate | AllSegmentPredicate | AnySegmentPredicate;
277
+ /**
278
+ * This type represent one rule of a segmented field: the condition, and the value to serve when it wins
279
+ * @template T The type of the value served by the rule, which conforms to the field's `variantType`
280
+ */
281
+ export type SegmentRule<T = any> = {
282
+ /**
283
+ * The rule id, unique in the field. Used for diagnostics only, matching never reads it
284
+ */
285
+ id?: string;
286
+ /**
287
+ * The condition under which this rule wins
288
+ */
289
+ when: SegmentRuleCondition;
290
+ /**
291
+ * The value served when this rule wins
292
+ */
293
+ value: T;
294
+ };
295
+ /**
296
+ * This type represent the value a segmented field holds in a content payload: an ordered list of
297
+ * rules, first match wins, and the fallback served when no rule matches
298
+ *
299
+ * The fallback is mandatory exactly when the field is required, which keeps the delivery contract of a
300
+ * segmented field the same as any other field. Zero rules is legal: the field is then just its fallback
301
+ * @template T The type of the served values, which conform to the field's `variantType`
302
+ */
303
+ export type SegmentedFieldPayload<T = any> = {
304
+ /**
305
+ * The rules, in the order they are evaluated in
306
+ */
307
+ rules?: SegmentRule<T>[];
308
+ /**
309
+ * The value served when no rule matches
310
+ */
311
+ fallback?: T;
312
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SEGMENT_NAME_PATTERN = void 0;
4
+ /**
5
+ * A segment's mnemonicId and every one of its keys must match this pattern: lowercase, digits,
6
+ * underscore and hyphen. Stricter than the other authoring mnemonicIds on purpose, because both halves
7
+ * travel in the delivery `segments` query param and are compared against strings a client supplies
8
+ */
9
+ exports.SEGMENT_NAME_PATTERN = /^[a-z0-9_-]+$/;
@@ -12,6 +12,7 @@ export * from './Invites';
12
12
  export * from './MediaGallery';
13
13
  export * from './PublishedContent';
14
14
  export * from './PublishingRequest';
15
+ export * from './Segment';
15
16
  export * from './Space';
16
17
  export * from './Subscription';
17
18
  export * from './UnpublishRequest';
package/dist/api/index.js CHANGED
@@ -28,6 +28,7 @@ __exportStar(require("./Invites"), exports);
28
28
  __exportStar(require("./MediaGallery"), exports);
29
29
  __exportStar(require("./PublishedContent"), exports);
30
30
  __exportStar(require("./PublishingRequest"), exports);
31
+ __exportStar(require("./Segment"), exports);
31
32
  __exportStar(require("./Space"), exports);
32
33
  __exportStar(require("./Subscription"), exports);
33
34
  __exportStar(require("./UnpublishRequest"), exports);
@@ -401,6 +401,13 @@ export type ListContentsFilters = {
401
401
  * Filter list by ContentTranslation status
402
402
  */
403
403
  translationStatus?: ContentTranslationStatus;
404
+
405
+ /**
406
+ * This filter is used to search contents whose segmented fields have rules referencing the segments
407
+ * inserted, as `segment` or `segment:key` tokens. A bare `segment` matches whichever key a content
408
+ * uses it with, and several tokens narrow the result like `tags` do
409
+ */
410
+ segments?: string[];
404
411
  };
405
412
 
406
413
  /**
@@ -839,7 +846,16 @@ export enum ContentFieldViolationCodes {
839
846
  textFieldValueIsNotAString = "textField.valueIsNotAString",
840
847
  textFieldBlankValueNotAllowed = "textField.blankValueNotAllowed",
841
848
  segmentedFieldValueIsNotSegmented = "segmentedField.valueIsNotSegmented",
849
+ segmentedFieldRulesIsNotAnArray = "segmentedField.rulesIsNotAnArray",
850
+ segmentedFieldRuleIsNotAnObject = "segmentedField.ruleIsNotAnObject",
851
+ segmentedFieldRuleConditionMissing = "segmentedField.ruleConditionMissing",
852
+ segmentedFieldDuplicateRuleId = "segmentedField.duplicateRuleId",
842
853
  segmentedFieldSegmentNotDeclared = "segmentedField.segmentNotDeclared",
854
+ segmentedFieldFallbackRequired = "segmentedField.fallbackRequired",
855
+ segmentedFieldSegmentNotFound = "segmentedField.segmentNotFound",
856
+ segmentedFieldSegmentArchived = "segmentedField.segmentArchived",
857
+ segmentedFieldSegmentKeyNotFound = "segmentedField.segmentKeyNotFound",
858
+ segmentedFieldSegmentKeyDeprecated = "segmentedField.segmentKeyDeprecated",
843
859
  }
844
860
 
845
861
  /**
@@ -189,6 +189,12 @@ export type ContentDefinitionResponse = {
189
189
  * Valued with paths to each array or null if definition is legacy
190
190
  */
191
191
  trackableArrayFields?: ArrayField[] | null;
192
+
193
+ /**
194
+ * The mnemonic ids of the segments this definition's segmented fields vary by
195
+ * Derived from the schema on every save, never assigned by the client
196
+ */
197
+ segments?: string[];
192
198
  };
193
199
 
194
200
  /**
@@ -417,5 +423,7 @@ export enum SchemaFieldViolationCodes {
417
423
  invalidEnumValue = 'invalidEnumValue',
418
424
  compactCannotBeNested = 'compactCannotBeNested',
419
425
  segmentTypeNotAllowed = 'segmentTypeNotAllowed',
420
- segmentNameNotFound = 'segmentNameNotFound'
426
+ segmentNameNotFound = 'segmentNameNotFound',
427
+ segmentArchived = 'segmentArchived',
428
+ duplicateSegmentName = 'duplicateSegmentName'
421
429
  }
@@ -321,64 +321,34 @@ export type OneLinkedContentOfConstraints = {
321
321
  };
322
322
 
323
323
  /**
324
- * This type represent one segment of a segmented field: the same `{ type, constraints }` pair a
325
- * schema field carries, minus the name, because the map key in `SegmentsTable` is the name
324
+ * This type represent what every value of a segmented field holds: one descriptor for the whole field,
325
+ * so the rules and the fallback cannot differ in type
326
326
  *
327
- * `oneLinkedContentOf` is the only reference form admitted, `linked-content` is its single
328
- * definition special case and carries the identical payload value
327
+ * Only the two `one...Of` forms are admitted: `fragment` and `linked-content` are each the
328
+ * single-target special case of one of them, carrying an identical payload value
329
329
  */
330
- export type SegmentDescriptor =
331
- | { type: SchemaTypeIds.FRAGMENT; constraints: FragmentFieldConstraints; }
330
+ export type SegmentVariantType =
332
331
  | { type: SchemaTypeIds.ONE_FRAGMENT_OF; constraints: OneFragmentOfConstraints; }
333
332
  | { type: SchemaTypeIds.ONE_LINKED_CONTENT_OF; constraints: OneLinkedContentOfConstraints; };
334
333
 
335
- /**
336
- * This type represent the model to define a segment of a segmented field
337
- */
338
- export type SegmentDefinition = SegmentDescriptor & {
339
- /**
340
- * The friendly labels of the segment
341
- */
342
- labels?: I18NDictionary;
343
- };
344
-
345
- /**
346
- * This type represent the model of the attribute segments of a segmented field, keyed by segment
347
- * name, like `FragmentsTable`
348
- * Names must match `^[a-z0-9_-]+$` and are unordered
349
- */
350
- export type SegmentsTable = {
351
- /**
352
- * The name is the unique id of the segment and its value is the model representing the segment
353
- */
354
- [name: string]: SegmentDefinition;
355
- };
356
-
357
- /**
358
- * This enum constrains every segment of a field to one family
359
- * When omitted, segments of both families are allowed in the same field
360
- */
361
- export enum SegmentsType {
362
- FRAGMENTS = 'fragments',
363
- REFERENCES = 'references'
364
- }
365
-
366
334
  /**
367
335
  * This type represent the model of a segmented field constraints
336
+ *
337
+ * A segmented field declares only *what varies* and *what shape the values have*. Which conditions
338
+ * exist and what each of them serves is authored per content, as an ordered list of rules plus a
339
+ * fallback - see [[SegmentedFieldPayload]] - so no combination has to be pre-declared here and two
340
+ * contents of the same definition may carry entirely different rule sets
368
341
  */
369
342
  export type SegmentedFieldConstraints = {
370
343
  /**
371
- * Set this value to define the segments the field is made of
372
- */
373
- segments: SegmentsTable;
374
- /**
375
- * Set this value to define the segment served when the request matches none of this field's segments
344
+ * The mnemonic ids of the segments this field varies by. Declaration order carries no meaning: a
345
+ * rule wins by being first in the content, not by which segment it constrains
376
346
  */
377
- defaultSegment?: string;
347
+ segments: string[];
378
348
  /**
379
- * Set this value to constrain every segment of the field to one family
349
+ * The shape every rule value and the fallback conform to
380
350
  */
381
- segmentsType?: SegmentsType;
351
+ variantType: SegmentVariantType;
382
352
  };
383
353
 
384
354
  /**
@@ -0,0 +1,336 @@
1
+ import { AuthorResponse } from './Author';
2
+ import { PagedListResponse } from './common';
3
+ import { ContentDefinitionId } from './ContentDefinition';
4
+
5
+ /**
6
+ * The segment unique id
7
+ */
8
+ export type SegmentId = number;
9
+
10
+ /**
11
+ * A segment's mnemonicId and every one of its keys must match this pattern: lowercase, digits,
12
+ * underscore and hyphen. Stricter than the other authoring mnemonicIds on purpose, because both halves
13
+ * travel in the delivery `segments` query param and are compared against strings a client supplies
14
+ */
15
+ export const SEGMENT_NAME_PATTERN = /^[a-z0-9_-]+$/;
16
+
17
+ /**
18
+ * This type represent one key of a segment, that is one of the values a visitor can have for it
19
+ */
20
+ export type SegmentKey = {
21
+ /**
22
+ * The key, matching [[SEGMENT_NAME_PATTERN]]
23
+ */
24
+ key: string;
25
+ /**
26
+ * A deprecated key cannot be referenced by new content rules, while every rule already written
27
+ * keeps resolving. The flag toggles both ways
28
+ */
29
+ deprecated?: boolean;
30
+ };
31
+
32
+ /**
33
+ * This type represent the model of a segment, that is a dimension a content can vary by - `gender`,
34
+ * `loyalty`, `auth_status` - holding the fixed set of keys a visitor can have for it
35
+ *
36
+ * Contents reference a segment by mnemonicId and key inside their rules, and definitions by
37
+ * mnemonicId, so segments are archived and never deleted, and a key can only be removed or renamed
38
+ * while no content references it
39
+ */
40
+ export type SegmentResponse = {
41
+ /**
42
+ * The segment unique id
43
+ */
44
+ id: SegmentId;
45
+ /**
46
+ * The segment name
47
+ */
48
+ name: string;
49
+ /**
50
+ * The segment mnemonic id, matching [[SEGMENT_NAME_PATTERN]]
51
+ */
52
+ mnemonicId: string;
53
+ /**
54
+ * The keys a visitor can hold for this segment, each carrying its own deprecation state
55
+ */
56
+ keys: SegmentKey[];
57
+ /**
58
+ * The archived status of the segment
59
+ */
60
+ archived: boolean;
61
+ /**
62
+ * The archive date of the segment
63
+ */
64
+ archivedDate: Date | null;
65
+ /**
66
+ * The segment creation date
67
+ */
68
+ createdDate: Date;
69
+ /**
70
+ * The segment last modified date
71
+ */
72
+ lastModifiedDate: Date;
73
+ /**
74
+ * The segment author, resolved by `list` only
75
+ */
76
+ author?: AuthorResponse;
77
+ /**
78
+ * The segment last modified author, resolved by every endpoint but `get`
79
+ */
80
+ latestContributor?: AuthorResponse;
81
+ };
82
+
83
+ /**
84
+ * This type represent all possible filters used to retrieve a list of segment
85
+ */
86
+ export type ListSegmentsFilters = {
87
+ /**
88
+ * This filter is used to retrieve archived or not archived segments. Defaults to not archived
89
+ */
90
+ archived?: boolean;
91
+ };
92
+
93
+ /**
94
+ * This type represent the data needed to make a list segments API request
95
+ */
96
+ export type ListSegmentsRequest = {
97
+ /**
98
+ * The number of segments to skip (this value is used for pagination)
99
+ */
100
+ skip?: number;
101
+ /**
102
+ * The number of segments to take (this value is used for pagination), at most 100
103
+ */
104
+ take?: number;
105
+ /**
106
+ * The data used to filter the list of segments
107
+ */
108
+ filters?: ListSegmentsFilters;
109
+ };
110
+
111
+ /**
112
+ * This type represent the item of a list segments API request
113
+ */
114
+ export type ListSegmentsItem = SegmentResponse;
115
+
116
+ /**
117
+ * This type represent the response of a list segments API request
118
+ */
119
+ export type ListSegmentsResponse = PagedListResponse<ListSegmentsItem>;
120
+
121
+ /**
122
+ * This type represent the usage of one key of a segment. A key with no entry is used by no content,
123
+ * and is therefore the only kind of key that can be removed or renamed
124
+ */
125
+ export type SegmentKeyUsage = {
126
+ /**
127
+ * The key, or null for the rules that constrain the segment without naming any key - that is the
128
+ * ones that only fire when the segment is unknown
129
+ */
130
+ key: string | null;
131
+ /**
132
+ * How many contents reference this key
133
+ */
134
+ contents: number;
135
+ };
136
+
137
+ /**
138
+ * This type represent a content definition that declares a segment
139
+ */
140
+ export type DefinitionUsingSegment = {
141
+ /**
142
+ * The content definition unique id
143
+ */
144
+ id: ContentDefinitionId;
145
+ /**
146
+ * The content definition mnemonic id
147
+ */
148
+ mnemonicId: string;
149
+ /**
150
+ * The content definition name
151
+ */
152
+ name: string;
153
+ };
154
+
155
+ /**
156
+ * This type represent the data needed to make a get segment API request
157
+ */
158
+ export type GetSegmentRequest = {
159
+ /**
160
+ * The unique segment id to retrieve
161
+ */
162
+ id: SegmentId;
163
+ };
164
+
165
+ /**
166
+ * This type represent the response of a get segment API request: the segment, plus the two things the
167
+ * editor cannot decide without, which keys are in use and which definitions vary by this segment
168
+ */
169
+ export type GetSegmentResponse = SegmentResponse & {
170
+ /**
171
+ * One entry per key at least one content references. A key absent from this list is unused
172
+ */
173
+ keyUsage: SegmentKeyUsage[];
174
+ /**
175
+ * The content definitions declaring this segment
176
+ */
177
+ definitions: DefinitionUsingSegment[];
178
+ };
179
+
180
+ /**
181
+ * This type represent the data needed to make a create segment API request
182
+ */
183
+ export type CreateSegmentRequest = {
184
+ /**
185
+ * The segment name
186
+ */
187
+ name: string;
188
+ /**
189
+ * The segment mnemonic id, matching [[SEGMENT_NAME_PATTERN]]
190
+ */
191
+ mnemonicId: string;
192
+ /**
193
+ * The keys a visitor can hold for this segment, at least one, each key unique
194
+ */
195
+ keys: SegmentKey[];
196
+ };
197
+
198
+ /**
199
+ * This type represent the response of a create segment API request
200
+ */
201
+ export type CreateSegmentResponse = SegmentResponse;
202
+
203
+ /**
204
+ * This type represent the data needed to make an update segment API request
205
+ *
206
+ * `keys` replaces the whole stored list, deprecation flags included. Adding keys and toggling
207
+ * deprecation are always allowed, while removing or renaming a key is refused while a content still
208
+ * references it. `mnemonicId` cannot be changed
209
+ */
210
+ export type UpdateSegmentRequest = {
211
+ /**
212
+ * The segment unique id
213
+ */
214
+ id: SegmentId;
215
+ /**
216
+ * The segment name to update
217
+ */
218
+ name: string;
219
+ /**
220
+ * The segment mnemonic id, which must be the stored one
221
+ */
222
+ mnemonicId: string;
223
+ /**
224
+ * The whole key list, replacing what is stored
225
+ */
226
+ keys: SegmentKey[];
227
+ };
228
+
229
+ /**
230
+ * This type represent the response of an update segment API request
231
+ */
232
+ export type UpdateSegmentResponse = SegmentResponse;
233
+
234
+ /**
235
+ * This type represent the data needed to make a toggle archived segment API request
236
+ */
237
+ export type ToggleArchivedSegmentRequest = {
238
+ /**
239
+ * The segment unique id
240
+ */
241
+ id: SegmentId;
242
+ /**
243
+ * This value represent the archive status to set in the specified segment
244
+ */
245
+ archived: boolean;
246
+ };
247
+
248
+ /**
249
+ * This type represent the response of a toggle archived segment API request
250
+ */
251
+ export type ToggleArchivedSegmentResponse = SegmentResponse;
252
+
253
+ /**
254
+ * This type represent the condition of one rule on a single segment: the visitor's value for
255
+ * [[segment]] has to be one of [[in]]
256
+ */
257
+ export type SegmentPredicate = {
258
+ /**
259
+ * The mnemonic id of the segment this predicate constrains, which the field must declare
260
+ */
261
+ segment: string;
262
+ /**
263
+ * The keys of the segment that satisfy this predicate
264
+ */
265
+ in: string[];
266
+ /**
267
+ * Set this value to also satisfy the predicate when the segment was not provided at all
268
+ *
269
+ * Not-provided is not a key, so no list of keys can express it, and an enumeration would silently
270
+ * narrow the moment a key is added to the segment. A key that was provided but is not listed does
271
+ * not satisfy this flag: it falls through to the field's fallback
272
+ */
273
+ orUnset?: boolean;
274
+ };
275
+
276
+ /**
277
+ * This type represent a condition satisfied when every child condition is satisfied
278
+ */
279
+ export type AllSegmentPredicate = {
280
+ all: SegmentRuleCondition[];
281
+ };
282
+
283
+ /**
284
+ * This type represent a condition satisfied when at least one child condition is satisfied
285
+ */
286
+ export type AnySegmentPredicate = {
287
+ any: SegmentRuleCondition[];
288
+ };
289
+
290
+ /**
291
+ * This type represent the condition of a rule
292
+ *
293
+ * The stored form is a tree so that new kinds of condition stay additive, but an editor only needs to
294
+ * build an [[AllSegmentPredicate]] of one [[SegmentPredicate]] per segment: or within a segment, and
295
+ * between segments. A segment the condition does not mention is unconstrained, which is a different
296
+ * thing from one listed with [[SegmentPredicate.orUnset]]
297
+ */
298
+ export type SegmentRuleCondition = SegmentPredicate | AllSegmentPredicate | AnySegmentPredicate;
299
+
300
+ /**
301
+ * This type represent one rule of a segmented field: the condition, and the value to serve when it wins
302
+ * @template T The type of the value served by the rule, which conforms to the field's `variantType`
303
+ */
304
+ export type SegmentRule<T = any> = {
305
+ /**
306
+ * The rule id, unique in the field. Used for diagnostics only, matching never reads it
307
+ */
308
+ id?: string;
309
+ /**
310
+ * The condition under which this rule wins
311
+ */
312
+ when: SegmentRuleCondition;
313
+ /**
314
+ * The value served when this rule wins
315
+ */
316
+ value: T;
317
+ };
318
+
319
+ /**
320
+ * This type represent the value a segmented field holds in a content payload: an ordered list of
321
+ * rules, first match wins, and the fallback served when no rule matches
322
+ *
323
+ * The fallback is mandatory exactly when the field is required, which keeps the delivery contract of a
324
+ * segmented field the same as any other field. Zero rules is legal: the field is then just its fallback
325
+ * @template T The type of the served values, which conform to the field's `variantType`
326
+ */
327
+ export type SegmentedFieldPayload<T = any> = {
328
+ /**
329
+ * The rules, in the order they are evaluated in
330
+ */
331
+ rules?: SegmentRule<T>[];
332
+ /**
333
+ * The value served when no rule matches
334
+ */
335
+ fallback?: T;
336
+ };
package/lib/api/index.ts CHANGED
@@ -12,6 +12,7 @@ export * from './Invites';
12
12
  export * from './MediaGallery';
13
13
  export * from './PublishedContent';
14
14
  export * from './PublishingRequest';
15
+ export * from './Segment';
15
16
  export * from './Space';
16
17
  export * from './Subscription';
17
18
  export * from './UnpublishRequest';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentchef/contentchef-types",
3
- "version": "11.0.0-alpha.1",
3
+ "version": "11.0.0-alpha.2",
4
4
  "description": "ContentChef types",
5
5
  "author": "PierpaoloIannone <piannone@byte-code.com>",
6
6
  "homepage": "https://github.com/ContentChef/contentchef-management-js-client#readme",
@@ -34,5 +34,5 @@
34
34
  "devDependencies": {
35
35
  "typescript": "^5.9.3"
36
36
  },
37
- "gitHead": "b618c00d0b1642ac9a75685fa08e214b83e22fc8"
37
+ "gitHead": "58fd14f63fafe3be82bc829bb3a835a2e4f94c30"
38
38
  }