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

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.
@@ -0,0 +1,592 @@
1
+ import { AuthorResponse } from './Author';
2
+ import { PagedListResponse } from './common';
3
+ import {
4
+ AttributeViolation,
5
+ ContentDefinitionId,
6
+ GetContentDefinitionResponse,
7
+ SchemaFieldViolationsErrors
8
+ } from './ContentDefinition';
9
+ import { ContentDefinitionSchemaInput, Field, FragmentDefinition } from './ContentDefinitionSchema';
10
+
11
+ /**
12
+ * The component unique id
13
+ */
14
+ export type ComponentId = number;
15
+
16
+ /**
17
+ * A component's mnemonicId must match this pattern. It becomes the fragment's name in every definition
18
+ * using the component, so it is unique in the space, case insensitively, and never changes
19
+ */
20
+ export const COMPONENT_NAME_PATTERN = /^[a-zA-Z0-9_]+$/;
21
+
22
+ /**
23
+ * This type represent the fragment a component defines: its fields and optionally its labels, nothing
24
+ * else. Its labels, hints, placeholders and list value labels need at least one locale, any locale
25
+ */
26
+ export type ComponentFragment = Omit<FragmentDefinition, 'component'>;
27
+
28
+ /**
29
+ * This type represent a field a version renames, declared when it is published so that the values
30
+ * written under the old name follow
31
+ */
32
+ export type ComponentRename = {
33
+ from: string;
34
+ to: string;
35
+ };
36
+
37
+ /**
38
+ * This type represent field names, by what happened to them between two versions of a fragment.
39
+ * A field whose type changed is `changed`; a renamed field is in `renamed`, and in neither `added` nor
40
+ * `removed`
41
+ */
42
+ export type FieldChanges = {
43
+ added: string[];
44
+ removed: string[];
45
+ changed: string[];
46
+ renamed: ComponentRename[];
47
+ };
48
+
49
+ /**
50
+ * This type represent the author of a component, or of one of its versions
51
+ */
52
+ export type ComponentAuthor = Pick<AuthorResponse, 'authorId' | 'fullName'>;
53
+
54
+ /**
55
+ * This type represent a published version of a component, which never changes
56
+ */
57
+ export type ComponentVersion = ComponentFragment & {
58
+ /**
59
+ * The version number, from 1
60
+ */
61
+ version: number;
62
+ /**
63
+ * The changes from the version before. Version 1 lists every field as added
64
+ */
65
+ changes: FieldChanges;
66
+ /**
67
+ * The note given when publishing
68
+ */
69
+ note?: string;
70
+ publishedBy: ComponentAuthor;
71
+ publishedDate: Date;
72
+ };
73
+
74
+ /**
75
+ * This type represent a version of a component without its fragment
76
+ */
77
+ export type ComponentVersionSummary = Omit<ComponentVersion, 'labels' | 'fields'>;
78
+
79
+ /**
80
+ * This type represent a definition using a component
81
+ */
82
+ export type ComponentUsedBy = {
83
+ definitionId: ContentDefinitionId;
84
+ definitionMnemonicId: string;
85
+ definitionName: string;
86
+ /**
87
+ * The component version the definition copies
88
+ */
89
+ version: number;
90
+ };
91
+
92
+ /**
93
+ * This type represent a component as the list components API request answers it
94
+ *
95
+ * A component is a fragment a space defines once, for any of its definitions to use. Publishing its
96
+ * draft makes its next version, and a definition moves to a newer version only when it is upgraded
97
+ */
98
+ export type ComponentSummary = {
99
+ id: ComponentId;
100
+ /**
101
+ * The component mnemonic id, matching [[COMPONENT_NAME_PATTERN]]
102
+ */
103
+ mnemonicId: string;
104
+ name: string;
105
+ /**
106
+ * An archived component keeps working in the definitions using it, and cannot be added to another
107
+ * definition or component
108
+ */
109
+ archived: boolean;
110
+ /**
111
+ * The latest version, null until the first publish
112
+ */
113
+ latestVersion: number | null;
114
+ /**
115
+ * Whether the draft differs from the latest version, true before the first publish
116
+ */
117
+ draftChanged: boolean;
118
+ /**
119
+ * How many definitions use the component, and how many of those are on an older version
120
+ */
121
+ usage: { definitions: number; behind: number };
122
+ };
123
+
124
+ /**
125
+ * This type represent the model of a component, as every component API request but list answers it
126
+ */
127
+ export type ComponentResponse = ComponentSummary & {
128
+ archivedDate: Date | null;
129
+ /**
130
+ * The fragment being edited
131
+ */
132
+ draft: ComponentFragment;
133
+ /**
134
+ * The version asked for, the latest by default, null before the first publish
135
+ */
136
+ version: ComponentVersion | null;
137
+ /**
138
+ * Every version, newest first
139
+ */
140
+ versions: ComponentVersionSummary[];
141
+ usedBy: ComponentUsedBy[];
142
+ createdDate: Date;
143
+ lastModifiedDate: Date;
144
+ author: ComponentAuthor;
145
+ latestContributor: ComponentAuthor;
146
+ };
147
+
148
+ /**
149
+ * This type represent all possible filters used to retrieve a list of components
150
+ */
151
+ export type ListComponentsFilters = {
152
+ /**
153
+ * Matches the name or the mnemonic id, case insensitively, anywhere in it. At most 100 characters
154
+ */
155
+ name?: string;
156
+ /**
157
+ * Left out, the list holds both archived and not archived components
158
+ */
159
+ archived?: boolean;
160
+ };
161
+
162
+ /**
163
+ * This type represent the data needed to make a list components API request
164
+ */
165
+ export type ListComponentsRequest = {
166
+ /**
167
+ * The number of components to skip, 0 by default
168
+ */
169
+ skip?: number;
170
+ /**
171
+ * The number of components to take, 10 by default and at most 100
172
+ */
173
+ take?: number;
174
+ filters?: ListComponentsFilters;
175
+ };
176
+
177
+ /**
178
+ * This type represent the response of a list components API request
179
+ */
180
+ export type ListComponentsResponse = PagedListResponse<ComponentSummary>;
181
+
182
+ /**
183
+ * This type represent the data needed to make a get component API request, by id or by mnemonic id
184
+ */
185
+ export type GetComponentRequest = ({ id: ComponentId } | { mnemonicId: string }) & {
186
+ /**
187
+ * The version to answer with, the latest by default
188
+ */
189
+ version?: number;
190
+ };
191
+
192
+ /**
193
+ * This type represent the response of a get component API request
194
+ */
195
+ export type GetComponentResponse = ComponentResponse;
196
+
197
+ /**
198
+ * This type represent the data needed to make a create component API request
199
+ */
200
+ export type CreateComponentRequest = {
201
+ /**
202
+ * The component mnemonic id, matching [[COMPONENT_NAME_PATTERN]]
203
+ */
204
+ mnemonicId: string;
205
+ name: string;
206
+ draft: ComponentFragment;
207
+ };
208
+
209
+ /**
210
+ * This type represent the response of a create component API request, with no version yet
211
+ */
212
+ export type CreateComponentResponse = ComponentResponse;
213
+
214
+ /**
215
+ * This type represent the data needed to make an update component API request. The name and the whole
216
+ * draft are replaced, and the last save wins
217
+ */
218
+ export type UpdateComponentRequest = {
219
+ id: ComponentId;
220
+ name: string;
221
+ draft: ComponentFragment;
222
+ };
223
+
224
+ /**
225
+ * This type represent the response of an update component API request
226
+ */
227
+ export type UpdateComponentResponse = ComponentResponse;
228
+
229
+ /**
230
+ * This type represent the data needed to make a publish component API request
231
+ */
232
+ export type PublishComponentRequest = {
233
+ id: ComponentId;
234
+ /**
235
+ * A note on the version, at most 2000 characters
236
+ */
237
+ note?: string;
238
+ /**
239
+ * The fields the version renames: `from` a field of the latest version the draft no longer has, `to`
240
+ * a field of the draft the latest version does not have, of the same type and changed only as a kept
241
+ * field may. A name is in one rename at most
242
+ */
243
+ renames?: ComponentRename[];
244
+ };
245
+
246
+ /**
247
+ * This type represent the response of a publish component API request, its `version` the one just
248
+ * published
249
+ */
250
+ export type PublishComponentResponse = ComponentResponse;
251
+
252
+ /**
253
+ * This type represent the data needed to make a toggle archived component API request
254
+ */
255
+ export type ToggleArchivedComponentRequest = {
256
+ id: ComponentId;
257
+ archived: boolean;
258
+ };
259
+
260
+ /**
261
+ * This type represent the response of a toggle archived component API request
262
+ */
263
+ export type ToggleArchivedComponentResponse = ComponentResponse;
264
+
265
+ /**
266
+ * This type represent the data needed to make an adopt component API request: the definition's own
267
+ * fragment named `mnemonicId` becomes the managed fragment of that component version
268
+ */
269
+ export type AdoptComponentRequest = {
270
+ definitionId: ContentDefinitionId;
271
+ mnemonicId: string;
272
+ version: number;
273
+ };
274
+
275
+ /**
276
+ * This type represent the response of an adopt component API request: the definition, as the get
277
+ * content definition API request answers it
278
+ */
279
+ export type AdoptComponentResponse = NonNullable<GetContentDefinitionResponse>;
280
+
281
+ /**
282
+ * This type represent the data needed to make a promote component API request: the definition's own
283
+ * fragment becomes version 1 of a new component, whose mnemonic id is the fragment's name
284
+ */
285
+ export type PromoteComponentRequest = {
286
+ definitionId: ContentDefinitionId;
287
+ fragment: string;
288
+ /**
289
+ * The component name, the fragment's name by default
290
+ */
291
+ name?: string;
292
+ };
293
+
294
+ /**
295
+ * This type represent the response of a promote component API request
296
+ */
297
+ export type PromoteComponentResponse = {
298
+ component: ComponentResponse;
299
+ /**
300
+ * The definition, as the get content definition API request answers it
301
+ */
302
+ definition: NonNullable<GetContentDefinitionResponse>;
303
+ };
304
+
305
+ /**
306
+ * Thin enum represent the error types of the component API requests, and of the content definition
307
+ * ones using components. Each is the `type` of a `RequestError`, whose `details` is a [[ComponentError]]
308
+ */
309
+ export enum ComponentErrorTypes {
310
+ componentNotFound = 'ComponentNotFound',
311
+ componentVersionNotFound = 'ComponentVersionNotFound',
312
+ failedComponentValidation = 'FailedComponentValidation',
313
+ componentVersionRefused = 'ComponentVersionRefused',
314
+ nothingToPublish = 'NothingToPublish',
315
+ mnemonicIdNotUnique = 'MnemonicIdNotUnique',
316
+ managedFragmentEdited = 'ManagedFragmentEdited',
317
+ componentArchived = 'ComponentArchived',
318
+ componentAdoptionRequired = 'ComponentAdoptionRequired',
319
+ componentDowngradeRefused = 'ComponentDowngradeRefused',
320
+ noFragmentToAdopt = 'NoFragmentToAdopt',
321
+ noFragmentToPromote = 'NoFragmentToPromote',
322
+ definitionMigrating = 'DefinitionMigrating',
323
+ oneMigrationPerSave = 'OneMigrationPerSave',
324
+ migrationPreviewNotFound = 'MigrationPreviewNotFound'
325
+ }
326
+
327
+ /**
328
+ * Thin enum represent the codes of a [[ComponentVersionViolation]]
329
+ */
330
+ export enum ComponentVersionViolationCodes {
331
+ /**
332
+ * An added field, or one whose type changed, must be optional
333
+ */
334
+ requiredField = 'component.requiredField',
335
+ /**
336
+ * An added field, or one whose type changed, can be neither compact nor a facet
337
+ */
338
+ compactOrFacet = 'component.compactOrFacet',
339
+ /**
340
+ * A kept field may only change its texts, or loosen its constraints
341
+ */
342
+ notLooser = 'component.notLooser',
343
+ /**
344
+ * A rename must go from a field the draft no longer has to a new one of the same type
345
+ */
346
+ invalidRename = 'component.invalidRename'
347
+ }
348
+
349
+ /**
350
+ * This type represent a field a new version may not change as the draft does
351
+ */
352
+ export type ComponentVersionViolation = {
353
+ field: string;
354
+ /**
355
+ * One of [[ComponentVersionViolationCodes]]
356
+ */
357
+ code: string;
358
+ message: string;
359
+ };
360
+
361
+ type ComponentErrorOf<T extends ComponentErrorTypes, D = {}> = { type: T; message: string } & D;
362
+
363
+ /**
364
+ * This type represent the `details` of a `RequestError` whose `type` is one of [[ComponentErrorTypes]].
365
+ * Where present, `fragment` names the definition's fragment at fault
366
+ */
367
+ export type ComponentError =
368
+ | ComponentErrorOf<ComponentErrorTypes.componentNotFound, { fragment?: string }>
369
+ | ComponentErrorOf<ComponentErrorTypes.componentVersionNotFound, { fragment?: string }>
370
+ | ComponentErrorOf<ComponentErrorTypes.failedComponentValidation, {
371
+ /**
372
+ * The draft's violations, as a definition fragment's. A component a field references while
373
+ * unpublished or archived is reported on its `constraints` as `componentNotPublished` or
374
+ * `componentArchived`, with the components at fault as affected attributes
375
+ */
376
+ validation: (SchemaFieldViolationsErrors | AttributeViolation)[];
377
+ }>
378
+ | ComponentErrorOf<ComponentErrorTypes.componentVersionRefused, {
379
+ violations: ComponentVersionViolation[];
380
+ /**
381
+ * Set by an adoption, naming the fragment it refuses
382
+ */
383
+ fragment?: string;
384
+ }>
385
+ | ComponentErrorOf<ComponentErrorTypes.nothingToPublish>
386
+ | ComponentErrorOf<ComponentErrorTypes.mnemonicIdNotUnique, {
387
+ mnemonicId: string;
388
+ /**
389
+ * Set by a promotion: every component mnemonic id already taken, whatever its case. Adopt
390
+ * those components instead
391
+ */
392
+ mnemonicIds?: string[];
393
+ }>
394
+ | ComponentErrorOf<ComponentErrorTypes.managedFragmentEdited, { fragment: string; mnemonicId: string; version: number }>
395
+ | ComponentErrorOf<ComponentErrorTypes.componentArchived, { fragment: string }>
396
+ | ComponentErrorOf<ComponentErrorTypes.componentAdoptionRequired, { fragment: string }>
397
+ | ComponentErrorOf<ComponentErrorTypes.componentDowngradeRefused, { fragment: string; mnemonicId: string; from: number; to: number }>
398
+ | ComponentErrorOf<ComponentErrorTypes.noFragmentToAdopt, { fragment: string }>
399
+ | ComponentErrorOf<ComponentErrorTypes.noFragmentToPromote, { fragment: string }>
400
+ /**
401
+ * A save changing the schema while the definition's contents are still being migrated
402
+ */
403
+ | ComponentErrorOf<ComponentErrorTypes.definitionMigrating, DefinitionMigrationState>
404
+ /**
405
+ * A save that would migrate the values of more than one component: save one, then the next once it
406
+ * has finished
407
+ */
408
+ | ComponentErrorOf<ComponentErrorTypes.oneMigrationPerSave, { mnemonicIds: string[] }>
409
+ | ComponentErrorOf<ComponentErrorTypes.migrationPreviewNotFound, { id: MigrationPreviewId }>;
410
+
411
+ /**
412
+ * This type represent where a definition's contents stand, as the get content definition API request
413
+ * answers it
414
+ *
415
+ * An upgrade or adoption that renames, removes or retypes fields bumps the definition's revision and
416
+ * migrates its contents in the background, one migration at a time per definition
417
+ */
418
+ export type DefinitionMigrationState = {
419
+ /**
420
+ * Bumped by each save that migrates values
421
+ */
422
+ revision: number;
423
+ /**
424
+ * The contents, archived ones included, still waiting for the migration to `revision`, 0 when none
425
+ * runs. While above 0, a save changing the schema is refused with `DefinitionMigrating`
426
+ */
427
+ behind: number;
428
+ };
429
+
430
+ /**
431
+ * This type represent a translation of a value set aside
432
+ */
433
+ export type SetAsideTranslation = {
434
+ /**
435
+ * Relative to the value's `path`, empty for the value itself
436
+ */
437
+ key: string;
438
+ value: string | null;
439
+ checksum: string | null;
440
+ };
441
+
442
+ /**
443
+ * This type represent a value a migration could not carry, waiting beside its content for a person to
444
+ * move into a field or discard
445
+ */
446
+ export type SetAsideValue = {
447
+ /**
448
+ * The definition revision whose migration set it aside
449
+ */
450
+ revision: number;
451
+ /**
452
+ * The component it was a value of
453
+ */
454
+ mnemonicId: string;
455
+ /**
456
+ * Where it was, in the key format translation entries use, with the names the payload has now:
457
+ * `pic.credit`, `gallery.$k1.width`
458
+ */
459
+ path: string;
460
+ /**
461
+ * The field as the version it came from defined it, for the form to show the value
462
+ */
463
+ field: Field;
464
+ reason: 'removed' | 'changed';
465
+ /**
466
+ * Null when the value followed its field and only its translations, which have no place there, wait
467
+ */
468
+ value: unknown;
469
+ /**
470
+ * Its translations by locale
471
+ */
472
+ translations: { [locale: string]: SetAsideTranslation[] };
473
+ /**
474
+ * Absent while the content still waits for its migration: the value is set aside by the read
475
+ */
476
+ setAsideDate?: Date;
477
+ };
478
+
479
+ /**
480
+ * This type represent a value set aside that a content save resolves. The value itself moves in the
481
+ * payload, where the person put it, and is then deleted; values not named stay
482
+ */
483
+ export type SetAsideResolution = {
484
+ revision: number;
485
+ path: string;
486
+ /**
487
+ * The path of the field the value moved to, for its translations to follow there, where that field
488
+ * is translatable. Left out, the value is discarded
489
+ */
490
+ into?: string;
491
+ };
492
+
493
+ /**
494
+ * The migration preview unique id
495
+ */
496
+ export type MigrationPreviewId = number;
497
+
498
+ /**
499
+ * This type represent the data needed to make a migration preview API request: the definition, and the
500
+ * schema about to be saved with the update content definition API request or the adoption about to be made
501
+ */
502
+ export type MigrationPreviewRequest =
503
+ | { id: ContentDefinitionId; schema: ContentDefinitionSchemaInput }
504
+ | { id: ContentDefinitionId; adopt: { mnemonicId: string; version: number } };
505
+
506
+ /**
507
+ * This type represent the response of a migration preview API request: the preview's id, or null when
508
+ * the save would migrate nothing
509
+ */
510
+ export type MigrationPreviewResponse = {
511
+ id: MigrationPreviewId | null;
512
+ };
513
+
514
+ /**
515
+ * This type represent the data needed to make a get migration preview API request
516
+ */
517
+ export type GetMigrationPreviewRequest = {
518
+ id: MigrationPreviewId;
519
+ };
520
+
521
+ /**
522
+ * This type represent what a migration does to one field of the version the definition is on, whose
523
+ * values move or are checked
524
+ */
525
+ export type MigrationPreviewField = {
526
+ field: string;
527
+ outcome: 'renamed' | 'changed' | 'removed';
528
+ /**
529
+ * The field it becomes, null when removed
530
+ */
531
+ to: string | null;
532
+ /**
533
+ * The contents holding a value of it
534
+ */
535
+ contents: number;
536
+ renamed: number;
537
+ converted: number;
538
+ setAside: number;
539
+ /**
540
+ * The translations moved
541
+ */
542
+ translations: number;
543
+ /**
544
+ * Up to 20 of the contents' ids
545
+ */
546
+ examples: number[];
547
+ };
548
+
549
+ /**
550
+ * This type represent the response of a get migration preview API request, to poll until `status` is
551
+ * `done`. Previews are kept a day
552
+ */
553
+ export type GetMigrationPreviewResponse = {
554
+ id: MigrationPreviewId;
555
+ definitionId: ContentDefinitionId;
556
+ mnemonicId: string;
557
+ /**
558
+ * Null for an adoption
559
+ */
560
+ from: number | null;
561
+ to: number;
562
+ status: 'running' | 'done';
563
+ /**
564
+ * The contents walked so far, out of `total`
565
+ */
566
+ scanned: number;
567
+ total: number;
568
+ fields: MigrationPreviewField[];
569
+ /**
570
+ * The contents whose payload or translations would change
571
+ */
572
+ changing: number;
573
+ /**
574
+ * The contents that would hold values set aside
575
+ */
576
+ settingAside: number;
577
+ };
578
+
579
+ /**
580
+ * This type represent the data needed to make a resume migration API request
581
+ */
582
+ export type ResumeMigrationRequest = {
583
+ /**
584
+ * The content definition unique id
585
+ */
586
+ id: ContentDefinitionId;
587
+ };
588
+
589
+ /**
590
+ * This type represent the response of a resume migration API request
591
+ */
592
+ export type ResumeMigrationResponse = DefinitionMigrationState;
@@ -15,6 +15,7 @@ import {
15
15
  ContentTranslationStatus,
16
16
  } from "./ContentTranslation";
17
17
  import { CoverageReport } from "./Audience";
18
+ import { SetAsideResolution, SetAsideValue } from "./Component";
18
19
 
19
20
  /**
20
21
  * This type represent the content unique id type
@@ -335,6 +336,12 @@ export type UpdateContentRequest = {
335
336
  * set an identifier coming from a third party application
336
337
  */
337
338
  externalIdentifier?: string;
339
+
340
+ /**
341
+ * The values a migration set aside that this save resolves, moved into the payload by the person or
342
+ * discarded
343
+ */
344
+ setAside?: SetAsideResolution[];
338
345
  };
339
346
 
340
347
  /**
@@ -408,6 +415,11 @@ export type ListContentsFilters = {
408
415
  * audience mnemonic ids inserted. Several of them narrow the result like `tags` do
409
416
  */
410
417
  audiences?: string[];
418
+
419
+ /**
420
+ * true lists only the contents holding values a migration set aside
421
+ */
422
+ setAside?: boolean;
411
423
  };
412
424
 
413
425
  /**
@@ -716,9 +728,10 @@ export type LinkingContents = ContentResponse;
716
728
  */
717
729
  export type GetContentResponse = {
718
730
  /**
719
- * The requested content
731
+ * The requested content, migrated when it still waits for its definition's migration, with the values
732
+ * set aside beside it
720
733
  */
721
- content: ContentResponse | undefined;
734
+ content: (ContentResponse & { setAside: SetAsideValue[] }) | undefined;
722
735
  /**
723
736
  * The contents that use the requested content
724
737
  */