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

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.
@@ -5,6 +5,7 @@ import { ContentDefinitionId, ContentDefinitionResponse } from "./ContentDefinit
5
5
  import { SchemaTypeIds } from "./ContentDefinitionSchema";
6
6
  import { ContentRepositoryId, ContentRepositoryResponse } from "./ContentRepository";
7
7
  import { ContentTranslation, ContentTranslationStatus } from "./ContentTranslation";
8
+ import { CoverageReport } from "./Segment";
8
9
  /**
9
10
  * This type represent the content unique id type
10
11
  */
@@ -824,3 +825,36 @@ export type ToggleContentTranslationsRequest = {
824
825
  localizationSettings: LocalizationSettings;
825
826
  };
826
827
  export type ToggleContentTranslationsResponse = ContentResponse;
828
+ /**
829
+ * This type represent the data needed to make an analyse segmented rules API request
830
+ */
831
+ export type AnalyseSegmentedRulesRequest = {
832
+ /**
833
+ * Id of the content whose segmented fields have to be analysed
834
+ */
835
+ contentId: ContentId;
836
+ };
837
+ /**
838
+ * This type represent the coverage of one segmented field of a content
839
+ */
840
+ export type SegmentedFieldCoverage = CoverageReport & {
841
+ /**
842
+ * Where the field sits in the payload
843
+ */
844
+ path: string;
845
+ /**
846
+ * Whether the field carries a fallback. An optional field without one resolves to nothing for the
847
+ * assignments in [[CoverageReport.fallbackAssignments]], which is worth knowing
848
+ */
849
+ hasFallback: boolean;
850
+ };
851
+ /**
852
+ * This type represent the response of an analyse segmented rules API request: one report per
853
+ * segmented field of the content, empty when it has none
854
+ */
855
+ export type AnalyseSegmentedRulesResponse = {
856
+ /**
857
+ * One entry per segmented field found in the content payload
858
+ */
859
+ fields: SegmentedFieldCoverage[];
860
+ };
@@ -266,6 +266,15 @@ export type ContentDefinitionSchemaErrors = {
266
266
  * This attribute represents an error if the language of the schema is not a valid string
267
267
  */
268
268
  lang?: string;
269
+ /**
270
+ * This attribute represents all the error that occurs inside the segments declaration of the
271
+ * definition schema object
272
+ *
273
+ * - The value is a string if the segments value is not in the expected format
274
+ * - The value is a list of AttributeViolation, one per declared segment that does not exist in the
275
+ * space or is archived
276
+ */
277
+ segments?: string | AttributeViolation[];
269
278
  };
270
279
  /**
271
280
  * This type represent the model for the schema fragment errors
@@ -397,5 +406,6 @@ export declare enum SchemaFieldViolationCodes {
397
406
  segmentTypeNotAllowed = "segmentTypeNotAllowed",
398
407
  segmentNameNotFound = "segmentNameNotFound",
399
408
  segmentArchived = "segmentArchived",
409
+ segmentNotDeclaredByDefinition = "segmentNotDeclaredByDefinition",
400
410
  duplicateSegmentName = "duplicateSegmentName"
401
411
  }
@@ -48,5 +48,6 @@ var SchemaFieldViolationCodes;
48
48
  SchemaFieldViolationCodes["segmentTypeNotAllowed"] = "segmentTypeNotAllowed";
49
49
  SchemaFieldViolationCodes["segmentNameNotFound"] = "segmentNameNotFound";
50
50
  SchemaFieldViolationCodes["segmentArchived"] = "segmentArchived";
51
+ SchemaFieldViolationCodes["segmentNotDeclaredByDefinition"] = "segmentNotDeclaredByDefinition";
51
52
  SchemaFieldViolationCodes["duplicateSegmentName"] = "duplicateSegmentName";
52
53
  })(SchemaFieldViolationCodes || (exports.SchemaFieldViolationCodes = SchemaFieldViolationCodes = {}));
@@ -48,6 +48,14 @@ export type ContentDefinitionSchema = {
48
48
  * A Fragment is a custom field defined by the user and can be used internally in the definition
49
49
  */
50
50
  fragments: FragmentsTable;
51
+ /**
52
+ * The segments this definition depends on, chosen by the author. Every one has to exist in the
53
+ * space and not be archived, and a segmented field may only vary by segments named here, so this
54
+ * is what scopes a definition and gives the field editor a short list to offer
55
+ *
56
+ * Optional: a definition that declares none simply cannot hold a segmented field
57
+ */
58
+ segments?: string[];
51
59
  };
52
60
  /**
53
61
  * This type represent the model of the attribute fragments in a content definition schema
@@ -318,8 +326,13 @@ export type SegmentVariantType = {
318
326
  */
319
327
  export type SegmentedFieldConstraints = {
320
328
  /**
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
329
+ * The mnemonic ids of the segments this field varies by, which must be among the ones the
330
+ * definition declares in [[ContentDefinitionSchema.segments]]. Only the declaration is checked
331
+ * against the space, so a segment that does not exist is one error on the definition rather than
332
+ * one on every field that reached for it
333
+ *
334
+ * Declaration order carries no meaning: a rule wins by being first in the content, not by which
335
+ * segment it constrains
323
336
  */
324
337
  segments: string[];
325
338
  /**
@@ -310,3 +310,134 @@ export type SegmentedFieldPayload<T = any> = {
310
310
  */
311
311
  fallback?: T;
312
312
  };
313
+ /**
314
+ * This type represent the visitor's value per segment, as the rule engine reads it. A segment missing
315
+ * from the map, or set to `undefined`, means "not provided" - which is what
316
+ * [[SegmentPredicate.orUnset]] answers
317
+ */
318
+ export type SegmentAssignment = {
319
+ [segmentMnemonicId: string]: string | undefined;
320
+ };
321
+ /**
322
+ * The stand-in a coverage report uses for "a key none of the rules mention"
323
+ *
324
+ * Not a real key - it cannot be one, since keys match [[SEGMENT_NAME_PATTERN]]. A rule only ever tests
325
+ * membership in its own list, so every unmentioned key behaves identically and one case covers them
326
+ * all, which is what keeps the analysis exact and small. [[CoverageReport.otherKeys]] says which real
327
+ * keys it stood for
328
+ */
329
+ export declare const OTHER_KEY = "<any other key>";
330
+ /**
331
+ * This type represent how much of a rule list one rule actually serves
332
+ */
333
+ export type RuleCoverage = {
334
+ /**
335
+ * The position of the rule in the analysed list
336
+ */
337
+ index: number;
338
+ /**
339
+ * The rule id, when it carries one
340
+ */
341
+ id?: string;
342
+ /**
343
+ * The condition in words, so a finding reads without decoding a predicate
344
+ */
345
+ condition: string;
346
+ /**
347
+ * How many of the analysed assignments this rule wins. Zero means it can never serve anyone
348
+ */
349
+ wins: number;
350
+ };
351
+ /**
352
+ * This type represent what an ordered rule list covers, worked out from the rules and the segments'
353
+ * keys alone - no request traffic is involved
354
+ *
355
+ * The findings are advisory and never validation violations: a gap is usually deliberate, that being
356
+ * what a fallback is for, while an unreachable rule is almost always a mistake
357
+ */
358
+ export type CoverageReport = {
359
+ /**
360
+ * How many assignments were evaluated, after collapsing the keys no rule mentions
361
+ */
362
+ combinations: number;
363
+ /**
364
+ * One entry per analysed rule, in author order
365
+ */
366
+ rules: RuleCoverage[];
367
+ /**
368
+ * The rules that win nothing: shadowed by an earlier rule, or self-contradictory
369
+ */
370
+ unreachableRules: RuleCoverage[];
371
+ /**
372
+ * The assignments no rule claims, so they reach the fallback. Capped at 25 entries, while
373
+ * [[fallbackCount]] is the real total
374
+ */
375
+ fallbackAssignments: SegmentAssignment[];
376
+ /**
377
+ * How many assignments reach the fallback, of [[combinations]]
378
+ */
379
+ fallbackCount: number;
380
+ /**
381
+ * The segments declared by the field but constrained by no rule, so they change nothing about what
382
+ * it serves
383
+ */
384
+ unusedSegments: string[];
385
+ /**
386
+ * What [[OTHER_KEY]] stood for, per segment: the real unmentioned keys, capped at 10, with their
387
+ * total. Only the segments that needed the stand-in appear
388
+ */
389
+ otherKeys: {
390
+ [segment: string]: {
391
+ keys: string[];
392
+ total: number;
393
+ };
394
+ };
395
+ /**
396
+ * Set when the rules and their segments were too large to enumerate. Everything else is then
397
+ * unpopulated rather than guessed, because a sampled "no gaps" is not a fact
398
+ */
399
+ notAnalysed?: {
400
+ reason: 'tooManyCombinations';
401
+ combinations: number;
402
+ };
403
+ };
404
+ /**
405
+ * This type represent one rule as the analyse rules API request takes it: the condition, and nothing
406
+ * about what the rule serves. Coverage is decided by conditions only, so the values stay out of the
407
+ * request - and a half written rule with no condition is analysed as one that matches nothing rather
408
+ * than refused
409
+ */
410
+ export type SegmentRuleDraft = {
411
+ /**
412
+ * The rule id, when it carries one. Reported back on the finding, so a client can match a finding
413
+ * to the rule on screen without relying on the index
414
+ */
415
+ id?: string;
416
+ /**
417
+ * The condition under which this rule wins
418
+ */
419
+ when?: SegmentRuleCondition;
420
+ };
421
+ /**
422
+ * This type represent the data needed to make an analyse rules API request, which is what a field's
423
+ * rule editor asks about the rules on screen, before anything is saved
424
+ *
425
+ * The keys of every segment are read from the space rather than taken from the request, so a client
426
+ * never has to hold them or keep them current
427
+ */
428
+ export type AnalyseSegmentRulesRequest = {
429
+ /**
430
+ * The mnemonic ids of the segments the field varies by, at most 20. The analysis is bounded by
431
+ * these, as the field's rules are
432
+ */
433
+ segments: string[];
434
+ /**
435
+ * The rules in author order, at most 200. The order is the whole point: first match wins, so a rule
436
+ * being unreachable is a consequence of what precedes it
437
+ */
438
+ rules: SegmentRuleDraft[];
439
+ };
440
+ /**
441
+ * This type represent the response of an analyse rules API request
442
+ */
443
+ export type AnalyseSegmentRulesResponse = CoverageReport;
@@ -1,9 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SEGMENT_NAME_PATTERN = void 0;
3
+ exports.OTHER_KEY = exports.SEGMENT_NAME_PATTERN = void 0;
4
4
  /**
5
5
  * A segment's mnemonicId and every one of its keys must match this pattern: lowercase, digits,
6
6
  * underscore and hyphen. Stricter than the other authoring mnemonicIds on purpose, because both halves
7
7
  * travel in the delivery `segments` query param and are compared against strings a client supplies
8
8
  */
9
9
  exports.SEGMENT_NAME_PATTERN = /^[a-z0-9_-]+$/;
10
+ /**
11
+ * The stand-in a coverage report uses for "a key none of the rules mention"
12
+ *
13
+ * Not a real key - it cannot be one, since keys match [[SEGMENT_NAME_PATTERN]]. A rule only ever tests
14
+ * membership in its own list, so every unmentioned key behaves identically and one case covers them
15
+ * all, which is what keeps the analysis exact and small. [[CoverageReport.otherKeys]] says which real
16
+ * keys it stood for
17
+ */
18
+ exports.OTHER_KEY = '<any other key>';
@@ -14,6 +14,7 @@ import {
14
14
  ContentTranslation,
15
15
  ContentTranslationStatus,
16
16
  } from "./ContentTranslation";
17
+ import { CoverageReport } from "./Segment";
17
18
 
18
19
  /**
19
20
  * This type represent the content unique id type
@@ -900,3 +901,39 @@ export type ToggleContentTranslationsRequest = {
900
901
  };
901
902
 
902
903
  export type ToggleContentTranslationsResponse = ContentResponse;
904
+
905
+ /**
906
+ * This type represent the data needed to make an analyse segmented rules API request
907
+ */
908
+ export type AnalyseSegmentedRulesRequest = {
909
+ /**
910
+ * Id of the content whose segmented fields have to be analysed
911
+ */
912
+ contentId: ContentId;
913
+ };
914
+
915
+ /**
916
+ * This type represent the coverage of one segmented field of a content
917
+ */
918
+ export type SegmentedFieldCoverage = CoverageReport & {
919
+ /**
920
+ * Where the field sits in the payload
921
+ */
922
+ path: string;
923
+ /**
924
+ * Whether the field carries a fallback. An optional field without one resolves to nothing for the
925
+ * assignments in [[CoverageReport.fallbackAssignments]], which is worth knowing
926
+ */
927
+ hasFallback: boolean;
928
+ };
929
+
930
+ /**
931
+ * This type represent the response of an analyse segmented rules API request: one report per
932
+ * segmented field of the content, empty when it has none
933
+ */
934
+ export type AnalyseSegmentedRulesResponse = {
935
+ /**
936
+ * One entry per segmented field found in the content payload
937
+ */
938
+ fields: SegmentedFieldCoverage[];
939
+ };
@@ -287,6 +287,15 @@ export type ContentDefinitionSchemaErrors = {
287
287
  * This attribute represents an error if the language of the schema is not a valid string
288
288
  */
289
289
  lang?: string;
290
+ /**
291
+ * This attribute represents all the error that occurs inside the segments declaration of the
292
+ * definition schema object
293
+ *
294
+ * - The value is a string if the segments value is not in the expected format
295
+ * - The value is a list of AttributeViolation, one per declared segment that does not exist in the
296
+ * space or is archived
297
+ */
298
+ segments?: string | AttributeViolation[];
290
299
  };
291
300
 
292
301
  /**
@@ -425,5 +434,6 @@ export enum SchemaFieldViolationCodes {
425
434
  segmentTypeNotAllowed = 'segmentTypeNotAllowed',
426
435
  segmentNameNotFound = 'segmentNameNotFound',
427
436
  segmentArchived = 'segmentArchived',
437
+ segmentNotDeclaredByDefinition = 'segmentNotDeclaredByDefinition',
428
438
  duplicateSegmentName = 'duplicateSegmentName'
429
439
  }
@@ -51,6 +51,14 @@ export type ContentDefinitionSchema = {
51
51
  * A Fragment is a custom field defined by the user and can be used internally in the definition
52
52
  */
53
53
  fragments: FragmentsTable;
54
+ /**
55
+ * The segments this definition depends on, chosen by the author. Every one has to exist in the
56
+ * space and not be archived, and a segmented field may only vary by segments named here, so this
57
+ * is what scopes a definition and gives the field editor a short list to offer
58
+ *
59
+ * Optional: a definition that declares none simply cannot hold a segmented field
60
+ */
61
+ segments?: string[];
54
62
  };
55
63
 
56
64
  /**
@@ -341,8 +349,13 @@ export type SegmentVariantType =
341
349
  */
342
350
  export type SegmentedFieldConstraints = {
343
351
  /**
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
352
+ * The mnemonic ids of the segments this field varies by, which must be among the ones the
353
+ * definition declares in [[ContentDefinitionSchema.segments]]. Only the declaration is checked
354
+ * against the space, so a segment that does not exist is one error on the definition rather than
355
+ * one on every field that reached for it
356
+ *
357
+ * Declaration order carries no meaning: a rule wins by being first in the content, not by which
358
+ * segment it constrains
346
359
  */
347
360
  segments: string[];
348
361
  /**
@@ -334,3 +334,133 @@ export type SegmentedFieldPayload<T = any> = {
334
334
  */
335
335
  fallback?: T;
336
336
  };
337
+
338
+ /**
339
+ * This type represent the visitor's value per segment, as the rule engine reads it. A segment missing
340
+ * from the map, or set to `undefined`, means "not provided" - which is what
341
+ * [[SegmentPredicate.orUnset]] answers
342
+ */
343
+ export type SegmentAssignment = {
344
+ [segmentMnemonicId: string]: string | undefined;
345
+ };
346
+
347
+ /**
348
+ * The stand-in a coverage report uses for "a key none of the rules mention"
349
+ *
350
+ * Not a real key - it cannot be one, since keys match [[SEGMENT_NAME_PATTERN]]. A rule only ever tests
351
+ * membership in its own list, so every unmentioned key behaves identically and one case covers them
352
+ * all, which is what keeps the analysis exact and small. [[CoverageReport.otherKeys]] says which real
353
+ * keys it stood for
354
+ */
355
+ export const OTHER_KEY = '<any other key>';
356
+
357
+ /**
358
+ * This type represent how much of a rule list one rule actually serves
359
+ */
360
+ export type RuleCoverage = {
361
+ /**
362
+ * The position of the rule in the analysed list
363
+ */
364
+ index: number;
365
+ /**
366
+ * The rule id, when it carries one
367
+ */
368
+ id?: string;
369
+ /**
370
+ * The condition in words, so a finding reads without decoding a predicate
371
+ */
372
+ condition: string;
373
+ /**
374
+ * How many of the analysed assignments this rule wins. Zero means it can never serve anyone
375
+ */
376
+ wins: number;
377
+ };
378
+
379
+ /**
380
+ * This type represent what an ordered rule list covers, worked out from the rules and the segments'
381
+ * keys alone - no request traffic is involved
382
+ *
383
+ * The findings are advisory and never validation violations: a gap is usually deliberate, that being
384
+ * what a fallback is for, while an unreachable rule is almost always a mistake
385
+ */
386
+ export type CoverageReport = {
387
+ /**
388
+ * How many assignments were evaluated, after collapsing the keys no rule mentions
389
+ */
390
+ combinations: number;
391
+ /**
392
+ * One entry per analysed rule, in author order
393
+ */
394
+ rules: RuleCoverage[];
395
+ /**
396
+ * The rules that win nothing: shadowed by an earlier rule, or self-contradictory
397
+ */
398
+ unreachableRules: RuleCoverage[];
399
+ /**
400
+ * The assignments no rule claims, so they reach the fallback. Capped at 25 entries, while
401
+ * [[fallbackCount]] is the real total
402
+ */
403
+ fallbackAssignments: SegmentAssignment[];
404
+ /**
405
+ * How many assignments reach the fallback, of [[combinations]]
406
+ */
407
+ fallbackCount: number;
408
+ /**
409
+ * The segments declared by the field but constrained by no rule, so they change nothing about what
410
+ * it serves
411
+ */
412
+ unusedSegments: string[];
413
+ /**
414
+ * What [[OTHER_KEY]] stood for, per segment: the real unmentioned keys, capped at 10, with their
415
+ * total. Only the segments that needed the stand-in appear
416
+ */
417
+ otherKeys: { [segment: string]: { keys: string[]; total: number } };
418
+ /**
419
+ * Set when the rules and their segments were too large to enumerate. Everything else is then
420
+ * unpopulated rather than guessed, because a sampled "no gaps" is not a fact
421
+ */
422
+ notAnalysed?: { reason: 'tooManyCombinations'; combinations: number };
423
+ };
424
+
425
+ /**
426
+ * This type represent one rule as the analyse rules API request takes it: the condition, and nothing
427
+ * about what the rule serves. Coverage is decided by conditions only, so the values stay out of the
428
+ * request - and a half written rule with no condition is analysed as one that matches nothing rather
429
+ * than refused
430
+ */
431
+ export type SegmentRuleDraft = {
432
+ /**
433
+ * The rule id, when it carries one. Reported back on the finding, so a client can match a finding
434
+ * to the rule on screen without relying on the index
435
+ */
436
+ id?: string;
437
+ /**
438
+ * The condition under which this rule wins
439
+ */
440
+ when?: SegmentRuleCondition;
441
+ };
442
+
443
+ /**
444
+ * This type represent the data needed to make an analyse rules API request, which is what a field's
445
+ * rule editor asks about the rules on screen, before anything is saved
446
+ *
447
+ * The keys of every segment are read from the space rather than taken from the request, so a client
448
+ * never has to hold them or keep them current
449
+ */
450
+ export type AnalyseSegmentRulesRequest = {
451
+ /**
452
+ * The mnemonic ids of the segments the field varies by, at most 20. The analysis is bounded by
453
+ * these, as the field's rules are
454
+ */
455
+ segments: string[];
456
+ /**
457
+ * The rules in author order, at most 200. The order is the whole point: first match wins, so a rule
458
+ * being unreachable is a consequence of what precedes it
459
+ */
460
+ rules: SegmentRuleDraft[];
461
+ };
462
+
463
+ /**
464
+ * This type represent the response of an analyse rules API request
465
+ */
466
+ export type AnalyseSegmentRulesResponse = CoverageReport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentchef/contentchef-types",
3
- "version": "11.0.0-alpha.2",
3
+ "version": "11.0.0-alpha.4",
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": "58fd14f63fafe3be82bc829bb3a835a2e4f94c30"
37
+ "gitHead": "e6dc1e7bcc12adafcb1d1428f27bbd3b9e3c2bc5"
38
38
  }