@byline/core 3.20.3 → 3.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/@types/collection-types.d.ts +28 -3
  2. package/dist/@types/field-data-types.d.ts +8 -10
  3. package/dist/@types/field-data-types.js +1 -1
  4. package/dist/@types/field-data-types.test.node.d.ts +1 -0
  5. package/dist/@types/field-data-types.test.node.js +70 -0
  6. package/dist/@types/index.d.ts +1 -0
  7. package/dist/@types/index.js +1 -0
  8. package/dist/@types/relation-types.d.ts +38 -0
  9. package/dist/@types/relation-types.js +8 -0
  10. package/dist/@types/site-config.d.ts +1 -1
  11. package/dist/codegen/fixtures/all-fields.d.ts +342 -0
  12. package/dist/codegen/fixtures/all-fields.expected.d.ts +120 -0
  13. package/dist/codegen/fixtures/all-fields.expected.js +1 -0
  14. package/dist/codegen/fixtures/all-fields.js +94 -0
  15. package/dist/codegen/index.d.ts +16 -0
  16. package/dist/codegen/index.js +431 -0
  17. package/dist/codegen/index.test.node.d.ts +1 -0
  18. package/dist/codegen/index.test.node.js +230 -0
  19. package/dist/config/validate-collections.d.ts +3 -0
  20. package/dist/config/validate-collections.js +25 -0
  21. package/dist/config/validate-collections.test.node.js +42 -0
  22. package/dist/core.d.ts +1 -1
  23. package/dist/query/parse-where.d.ts +1 -1
  24. package/dist/schemas/zod/builder.js +7 -3
  25. package/dist/schemas/zod/builder.test.node.d.ts +1 -0
  26. package/dist/schemas/zod/builder.test.node.js +49 -0
  27. package/dist/services/collection-bootstrap.d.ts +1 -1
  28. package/dist/services/discover-counter-groups.d.ts +1 -1
  29. package/dist/services/document-lifecycle/create.d.ts +2 -2
  30. package/dist/services/document-lifecycle/create.js +5 -2
  31. package/dist/services/document-lifecycle/update.d.ts +4 -4
  32. package/dist/services/document-lifecycle/update.js +9 -4
  33. package/dist/services/document-lifecycle.test.node.js +66 -0
  34. package/dist/services/index.d.ts +1 -0
  35. package/dist/services/index.js +1 -0
  36. package/dist/services/normalize-numeric-fields.d.ts +23 -0
  37. package/dist/services/normalize-numeric-fields.js +89 -0
  38. package/dist/services/normalize-numeric-fields.test.node.d.ts +8 -0
  39. package/dist/services/normalize-numeric-fields.test.node.js +99 -0
  40. package/dist/services/populate.d.ts +2 -20
  41. package/dist/services/richtext-populate.d.ts +1 -1
  42. package/dist/services/validate-search-config.d.ts +1 -1
  43. package/dist/storage/collection-fingerprint.js +6 -0
  44. package/dist/storage/collection-fingerprint.test.node.js +21 -0
  45. package/package.json +7 -2
@@ -993,9 +993,7 @@ export interface CollectionDefinition {
993
993
  * Text fields contribute their value; `richText` fields are extracted to
994
994
  * plain text via the registered `fields.richText.toText` seam. Each entry
995
995
  * is a field path, or `{ field, boost }` to weight it for scoring
996
- * providers that support `capabilities.weighting`. Drives the admin
997
- * list-view search box (its `store_text` subset). Falls back to the
998
- * identity field (`useAsTitle`) when omitted.
996
+ * providers that support `capabilities.weighting`.
999
997
  * - `facets` — relation field paths to controlled-vocabulary collections.
1000
998
  * Core resolves each target's `counter` field (the stable aggregation id)
1001
999
  * and its `useAsTitle` (the term, folded into searchable text). `{ field,
@@ -1015,6 +1013,27 @@ export interface CollectionDefinition {
1015
1013
  filters?: string[];
1016
1014
  zones?: string[];
1017
1015
  };
1016
+ /**
1017
+ * Admin list-view quick-search fields — the top-level text-store field
1018
+ * names (`text` / `textArea` / `select`) the list route's search box
1019
+ * matches with substring (`ILIKE`) queries against `store_text`.
1020
+ *
1021
+ * Deliberately separate from `search`, which configures provider indexing
1022
+ * for site search: the two answer different questions ("find the row I
1023
+ * mean" vs. "rank relevant published content") and need not name the same
1024
+ * fields — a collection with a six-field weighted `search.body` typically
1025
+ * wants only its identity field (plus maybe a serial/code field) here.
1026
+ * Declaring one without the other is equally valid: `listSearch` with no
1027
+ * `search` keeps the list box working on an unindexed collection.
1028
+ *
1029
+ * Falls back to the identity field (`useAsTitle`, else the first declared
1030
+ * text field) when omitted — most collections need no declaration.
1031
+ *
1032
+ * Lives on the schema (not admin config) for the same reason as
1033
+ * `useAsTitle`: the query layer (`findDocuments` in the db adapter)
1034
+ * resolves it server-side from the `CollectionDefinition`.
1035
+ */
1036
+ listSearch?: string[];
1018
1037
  /**
1019
1038
  * The field that represents this document's identity — used anywhere a
1020
1039
  * single-line label for the document is needed: form headings, relation
@@ -1168,6 +1187,12 @@ export interface CollectionDefinition {
1168
1187
  export declare function defineCollection<const C extends CollectionDefinition>(definition: C & CollectionDefinition): C;
1169
1188
  export type CollectionFieldData<C extends CollectionDefinition> = FieldSetData<C['fields']>;
1170
1189
  export type CollectionFieldDataAllLocales<C extends CollectionDefinition> = FieldSetDataAllLocales<C['fields']>;
1190
+ /** Broad collection registry used when an application has not supplied its schema types. */
1191
+ export type CollectionRegistry = Record<string, Record<string, any>>;
1192
+ /** Infer a path-to-fields registry from a shared readonly collection-definition tuple. */
1193
+ export type InferCollectionRegistry<TCollections extends readonly CollectionDefinition[]> = {
1194
+ [TCollection in TCollections[number] as TCollection['path']]: CollectionFieldData<TCollection>;
1195
+ };
1171
1196
  /**
1172
1197
  * Type-safe factory for creating a Block. Returns the definition as-is,
1173
1198
  * but locks in literal types for `blockType`, field names, and select
@@ -5,7 +5,8 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
- import type { ArrayField, BlocksField, Field, FieldSet, GroupField, LocalizedField, OptionalField, SelectField } from './field-types.js';
8
+ import type { ArrayField, BlocksField, Field, FieldSet, GroupField, LocalizedField, OptionalField, RelationField, SelectField } from './field-types.js';
9
+ import type { RelatedDocumentValue } from './relation-types.js';
9
10
  import type { Prettify, ValueUnion } from './type-utils.js';
10
11
  /**
11
12
  * Structural type for any JSON-serializable value. Used as the type for
@@ -55,9 +56,12 @@ type BlocksFieldData<T extends BlocksField> = Array<Prettify<ValueUnion<{
55
56
  _type: K['blockType'];
56
57
  } & FieldSetData<K['fields']>>;
57
58
  }>>>;
59
+ type RelationFieldData<T extends RelationField> = T extends {
60
+ hasMany: true;
61
+ } ? RelatedDocumentValue[] : RelatedDocumentValue;
58
62
  type BaseFieldData<T extends Field> = T extends ArrayField ? Array<Prettify<{
59
63
  _id: string;
60
- } & FieldSetData<T['fields']>>> : T extends BlocksField ? Prettify<BlocksFieldData<T>> : T extends GroupField ? FieldSetData<T['fields']> : T extends SelectField ? T['options'][number]['value'] : BaseFieldDataTypes[T['type']];
64
+ } & FieldSetData<T['fields']>>> : T extends BlocksField ? Prettify<BlocksFieldData<T>> : T extends GroupField ? FieldSetData<T['fields']> : T extends SelectField ? T['options'][number]['value'] : T extends RelationField ? RelationFieldData<T> : BaseFieldDataTypes[T['type']];
61
65
  export type FieldData<T extends Field = Field> = T extends OptionalField ? BaseFieldData<T> | undefined : BaseFieldData<T>;
62
66
  export type FieldSetData<T extends FieldSet = FieldSet> = Prettify<{
63
67
  -readonly [F in T[number] as F extends OptionalField ? never : F['name']]: FieldData<F>;
@@ -75,7 +79,7 @@ type BlocksFieldDataAllLocales<T extends BlocksField> = Array<Prettify<ValueUnio
75
79
  }>>>;
76
80
  type BaseFieldDataAllLocales<T extends Field> = T extends ArrayField ? Array<Prettify<{
77
81
  _id: string;
78
- } & FieldSetDataAllLocales<T['fields']>>> : T extends BlocksField ? Prettify<BlocksFieldDataAllLocales<T>> : T extends GroupField ? FieldSetDataAllLocales<T['fields']> : T extends SelectField ? T['options'][number]['value'] : BaseFieldDataTypes[T['type']];
82
+ } & FieldSetDataAllLocales<T['fields']>>> : T extends BlocksField ? Prettify<BlocksFieldDataAllLocales<T>> : T extends GroupField ? FieldSetDataAllLocales<T['fields']> : T extends SelectField ? T['options'][number]['value'] : T extends RelationField ? RelationFieldData<T> : BaseFieldDataTypes[T['type']];
79
83
  type LocalizedFieldDataAllLocales<T extends Field> = T extends LocalizedField ? PerLocale<BaseFieldDataAllLocales<T>> : BaseFieldDataAllLocales<T>;
80
84
  export type FieldDataAllLocales<T extends Field = Field> = T extends OptionalField ? LocalizedFieldDataAllLocales<T> | undefined : LocalizedFieldDataAllLocales<T>;
81
85
  export type FieldSetDataAllLocales<T extends FieldSet = FieldSet> = Prettify<{
@@ -135,7 +139,7 @@ export interface PendingStoredFileValue {
135
139
  filename: string;
136
140
  originalFilename: string;
137
141
  mimeType: string;
138
- fileSize: string;
142
+ fileSize: number;
139
143
  storageProvider: 'pending';
140
144
  storagePath: '';
141
145
  storageUrl: string;
@@ -157,10 +161,4 @@ export declare function createPendingStoredFileValue(file: File, previewUrl: str
157
161
  width: number;
158
162
  height: number;
159
163
  }): PendingStoredFileValue;
160
- export interface RelatedDocumentValue {
161
- targetDocumentId: string;
162
- targetCollectionId: string;
163
- relationshipType?: string;
164
- cascadeDelete?: boolean;
165
- }
166
164
  export {};
@@ -23,7 +23,7 @@ export function createPendingStoredFileValue(file, previewUrl, dimensions) {
23
23
  filename: file.name,
24
24
  originalFilename: file.name,
25
25
  mimeType: file.type,
26
- fileSize: String(file.size),
26
+ fileSize: file.size,
27
27
  storageProvider: 'pending',
28
28
  storagePath: '',
29
29
  storageUrl: previewUrl,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ import { File } from 'node:buffer';
2
+ import { describe, expect, expectTypeOf, it } from 'vitest';
3
+ import { defineCollection } from './collection-types.js';
4
+ import { createPendingStoredFileValue } from './field-data-types.js';
5
+ const RelationShapes = defineCollection({
6
+ path: 'relation-shapes',
7
+ labels: { singular: 'Relation shape', plural: 'Relation shapes' },
8
+ fields: [
9
+ { name: 'single', type: 'relation', targetCollection: 'people' },
10
+ { name: 'many', type: 'relation', targetCollection: 'people', hasMany: true },
11
+ {
12
+ name: 'group',
13
+ type: 'group',
14
+ fields: [
15
+ { name: 'single', type: 'relation', targetCollection: 'people' },
16
+ { name: 'many', type: 'relation', targetCollection: 'people', hasMany: true },
17
+ ],
18
+ },
19
+ {
20
+ name: 'items',
21
+ type: 'array',
22
+ fields: [
23
+ { name: 'single', type: 'relation', targetCollection: 'people' },
24
+ { name: 'many', type: 'relation', targetCollection: 'people', hasMany: true },
25
+ ],
26
+ },
27
+ {
28
+ name: 'content',
29
+ type: 'blocks',
30
+ blocks: [
31
+ {
32
+ blockType: 'relations',
33
+ fields: [
34
+ { name: 'single', type: 'relation', targetCollection: 'people' },
35
+ { name: 'many', type: 'relation', targetCollection: 'people', hasMany: true },
36
+ ],
37
+ },
38
+ ],
39
+ },
40
+ { name: 'localizedTitle', type: 'text', localized: true },
41
+ ],
42
+ });
43
+ describe('field data contracts', () => {
44
+ it('infers single and hasMany relations through nested structures', () => {
45
+ expectTypeOf().toEqualTypeOf();
46
+ expectTypeOf().toEqualTypeOf();
47
+ expectTypeOf().toEqualTypeOf();
48
+ expectTypeOf().toEqualTypeOf();
49
+ expectTypeOf().toEqualTypeOf();
50
+ expectTypeOf().toEqualTypeOf();
51
+ expectTypeOf().toEqualTypeOf();
52
+ expectTypeOf().toEqualTypeOf();
53
+ expectTypeOf().toEqualTypeOf();
54
+ expectTypeOf().toEqualTypeOf();
55
+ expectTypeOf().toEqualTypeOf();
56
+ expectTypeOf().toEqualTypeOf();
57
+ expectTypeOf().toEqualTypeOf();
58
+ expectTypeOf().toEqualTypeOf();
59
+ });
60
+ it('keeps a pending file size numeric', () => {
61
+ const pending = createPendingStoredFileValue(new File(['content'], 'fixture.txt', { type: 'text/plain' }), 'blob:fixture');
62
+ expect(pending.fileSize).toBe(7);
63
+ expectTypeOf(pending.fileSize).toEqualTypeOf();
64
+ });
65
+ it('exposes generic single and hasMany relation read envelopes', () => {
66
+ expectTypeOf().toEqualTypeOf();
67
+ expectTypeOf().toEqualTypeOf();
68
+ expectTypeOf().toEqualTypeOf();
69
+ });
70
+ });
@@ -12,6 +12,7 @@ export * from './field-data-types.js';
12
12
  export * from './field-types.js';
13
13
  export * from './populate-types.js';
14
14
  export * from './query-predicate.js';
15
+ export * from './relation-types.js';
15
16
  export * from './search-types.js';
16
17
  export * from './site-config.js';
17
18
  export * from './storage-types.js';
@@ -12,6 +12,7 @@ export * from './field-data-types.js';
12
12
  export * from './field-types.js';
13
13
  export * from './populate-types.js';
14
14
  export * from './query-predicate.js';
15
+ export * from './relation-types.js';
15
16
  export * from './search-types.js';
16
17
  export * from './site-config.js';
17
18
  export * from './storage-types.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ /** The persisted, unpopulated value of a relation field. */
9
+ export interface RelatedDocumentValue {
10
+ targetDocumentId: string;
11
+ targetCollectionId: string;
12
+ relationshipType?: string;
13
+ cascadeDelete?: boolean;
14
+ }
15
+ /** A relation value that has not passed through population. */
16
+ export interface UnpopulatedRelationValue extends RelatedDocumentValue {
17
+ _resolved?: never;
18
+ _cycle?: never;
19
+ document?: never;
20
+ }
21
+ /** Marker used when the target was already materialised in this read request. */
22
+ export interface CycleRelationValue extends RelatedDocumentValue {
23
+ _resolved: true;
24
+ _cycle: true;
25
+ }
26
+ /** Marker used when the referenced target could not be read. */
27
+ export interface UnresolvedRelationValue extends RelatedDocumentValue {
28
+ _resolved: false;
29
+ }
30
+ /** Relation envelope used when population successfully resolves the target. */
31
+ export interface PopulatedRelationValue<TDocument = Record<string, any>> extends RelatedDocumentValue {
32
+ _resolved: true;
33
+ document: TDocument;
34
+ }
35
+ /** Every relation shape that can occur on the read path. */
36
+ export type RelationReadValue<TDocument = Record<string, any>> = UnpopulatedRelationValue | PopulatedRelationValue<TDocument> | UnresolvedRelationValue | CycleRelationValue;
37
+ /** Read shape for a single-target or `hasMany` relation field. */
38
+ export type RelationFieldReadValue<HasMany extends boolean, TDocument = Record<string, any>> = HasMany extends true ? RelationReadValue<TDocument>[] : RelationReadValue<TDocument>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ export {};
@@ -113,7 +113,7 @@ export interface BaseConfig {
113
113
  */
114
114
  translations?: TranslationBundleShape;
115
115
  };
116
- collections: CollectionDefinition[];
116
+ collections: readonly CollectionDefinition[];
117
117
  /**
118
118
  * URL segments for admin and API routes. Both keys default to `/admin`
119
119
  * and `/api` respectively — installations only set this when they want
@@ -0,0 +1,342 @@
1
+ export declare const QuoteBlock: {
2
+ readonly blockType: "quote'block";
3
+ readonly fields: readonly [{
4
+ readonly name: "quotation";
5
+ readonly type: "textArea";
6
+ readonly localized: true;
7
+ }, {
8
+ readonly name: "tone'choice";
9
+ readonly type: "select";
10
+ readonly optional: true;
11
+ readonly options: [{
12
+ readonly label: "Calm";
13
+ readonly value: "calm";
14
+ }, {
15
+ readonly label: "Quoted";
16
+ readonly value: "author's";
17
+ }];
18
+ }];
19
+ };
20
+ export declare const MediaBlock: {
21
+ readonly blockType: "media";
22
+ readonly fields: readonly [{
23
+ readonly name: "caption";
24
+ readonly type: "text";
25
+ readonly localized: true;
26
+ readonly optional: true;
27
+ }, {
28
+ readonly name: "image";
29
+ readonly type: "image";
30
+ }];
31
+ };
32
+ export declare const AllFieldsCollection: {
33
+ readonly path: "all-fields";
34
+ readonly labels: {
35
+ readonly singular: "All fields";
36
+ readonly plural: "All fields";
37
+ };
38
+ readonly fields: [{
39
+ readonly name: "integer";
40
+ readonly type: "integer";
41
+ }, {
42
+ readonly name: "float";
43
+ readonly type: "float";
44
+ }, {
45
+ readonly name: "counter";
46
+ readonly type: "counter";
47
+ readonly group: "fixture";
48
+ }, {
49
+ readonly name: "decimal";
50
+ readonly type: "decimal";
51
+ }, {
52
+ readonly name: "date";
53
+ readonly type: "date";
54
+ }, {
55
+ readonly name: "datetime";
56
+ readonly type: "datetime";
57
+ }, {
58
+ readonly name: "time";
59
+ readonly type: "time";
60
+ }, {
61
+ readonly name: "text";
62
+ readonly type: "text";
63
+ }, {
64
+ readonly name: "localizedText";
65
+ readonly type: "text";
66
+ readonly localized: true;
67
+ }, {
68
+ readonly name: "textArea";
69
+ readonly type: "textArea";
70
+ }, {
71
+ readonly name: "boolean";
72
+ readonly type: "boolean";
73
+ }, {
74
+ readonly name: "checkbox";
75
+ readonly type: "checkbox";
76
+ }, {
77
+ readonly name: "select";
78
+ readonly type: "select";
79
+ readonly options: [{
80
+ readonly label: "First";
81
+ readonly value: "first";
82
+ }, {
83
+ readonly label: "Second";
84
+ readonly value: "second's";
85
+ }];
86
+ }, {
87
+ readonly name: "json";
88
+ readonly type: "json";
89
+ }, {
90
+ readonly name: "localizedJson";
91
+ readonly type: "json";
92
+ readonly localized: true;
93
+ }, {
94
+ readonly name: "object";
95
+ readonly type: "object";
96
+ }, {
97
+ readonly name: "richText";
98
+ readonly type: "richText";
99
+ }, {
100
+ readonly name: "file";
101
+ readonly type: "file";
102
+ }, {
103
+ readonly name: "image";
104
+ readonly type: "image";
105
+ }, {
106
+ readonly name: "relation";
107
+ readonly type: "relation";
108
+ readonly targetCollection: "people";
109
+ }, {
110
+ readonly name: "relations";
111
+ readonly type: "relation";
112
+ readonly targetCollection: "people";
113
+ readonly hasMany: true;
114
+ }, {
115
+ readonly name: "optionalText";
116
+ readonly type: "text";
117
+ readonly optional: true;
118
+ }, {
119
+ readonly name: "group";
120
+ readonly type: "group";
121
+ readonly fields: readonly [{
122
+ readonly name: "title";
123
+ readonly type: "text";
124
+ readonly localized: true;
125
+ }, {
126
+ readonly name: "enabled";
127
+ readonly type: "boolean";
128
+ readonly optional: true;
129
+ }];
130
+ }, {
131
+ readonly name: "array";
132
+ readonly type: "array";
133
+ readonly fields: readonly [{
134
+ readonly name: "label";
135
+ readonly type: "text";
136
+ readonly localized: true;
137
+ }, {
138
+ readonly name: "score";
139
+ readonly type: "integer";
140
+ readonly optional: true;
141
+ }];
142
+ }, {
143
+ readonly name: "content's";
144
+ readonly type: "blocks";
145
+ readonly blocks: [{
146
+ readonly blockType: "quote'block";
147
+ readonly fields: readonly [{
148
+ readonly name: "quotation";
149
+ readonly type: "textArea";
150
+ readonly localized: true;
151
+ }, {
152
+ readonly name: "tone'choice";
153
+ readonly type: "select";
154
+ readonly optional: true;
155
+ readonly options: [{
156
+ readonly label: "Calm";
157
+ readonly value: "calm";
158
+ }, {
159
+ readonly label: "Quoted";
160
+ readonly value: "author's";
161
+ }];
162
+ }];
163
+ }, {
164
+ readonly blockType: "media";
165
+ readonly fields: readonly [{
166
+ readonly name: "caption";
167
+ readonly type: "text";
168
+ readonly localized: true;
169
+ readonly optional: true;
170
+ }, {
171
+ readonly name: "image";
172
+ readonly type: "image";
173
+ }];
174
+ }];
175
+ }];
176
+ };
177
+ export declare const MinimalCollection: {
178
+ readonly path: "minimal";
179
+ readonly labels: {
180
+ readonly singular: "Minimal";
181
+ readonly plural: "Minimal";
182
+ };
183
+ readonly fields: [{
184
+ readonly name: "title";
185
+ readonly type: "text";
186
+ }];
187
+ };
188
+ export declare const AllFieldsCollections: readonly [{
189
+ readonly path: "all-fields";
190
+ readonly labels: {
191
+ readonly singular: "All fields";
192
+ readonly plural: "All fields";
193
+ };
194
+ readonly fields: [{
195
+ readonly name: "integer";
196
+ readonly type: "integer";
197
+ }, {
198
+ readonly name: "float";
199
+ readonly type: "float";
200
+ }, {
201
+ readonly name: "counter";
202
+ readonly type: "counter";
203
+ readonly group: "fixture";
204
+ }, {
205
+ readonly name: "decimal";
206
+ readonly type: "decimal";
207
+ }, {
208
+ readonly name: "date";
209
+ readonly type: "date";
210
+ }, {
211
+ readonly name: "datetime";
212
+ readonly type: "datetime";
213
+ }, {
214
+ readonly name: "time";
215
+ readonly type: "time";
216
+ }, {
217
+ readonly name: "text";
218
+ readonly type: "text";
219
+ }, {
220
+ readonly name: "localizedText";
221
+ readonly type: "text";
222
+ readonly localized: true;
223
+ }, {
224
+ readonly name: "textArea";
225
+ readonly type: "textArea";
226
+ }, {
227
+ readonly name: "boolean";
228
+ readonly type: "boolean";
229
+ }, {
230
+ readonly name: "checkbox";
231
+ readonly type: "checkbox";
232
+ }, {
233
+ readonly name: "select";
234
+ readonly type: "select";
235
+ readonly options: [{
236
+ readonly label: "First";
237
+ readonly value: "first";
238
+ }, {
239
+ readonly label: "Second";
240
+ readonly value: "second's";
241
+ }];
242
+ }, {
243
+ readonly name: "json";
244
+ readonly type: "json";
245
+ }, {
246
+ readonly name: "localizedJson";
247
+ readonly type: "json";
248
+ readonly localized: true;
249
+ }, {
250
+ readonly name: "object";
251
+ readonly type: "object";
252
+ }, {
253
+ readonly name: "richText";
254
+ readonly type: "richText";
255
+ }, {
256
+ readonly name: "file";
257
+ readonly type: "file";
258
+ }, {
259
+ readonly name: "image";
260
+ readonly type: "image";
261
+ }, {
262
+ readonly name: "relation";
263
+ readonly type: "relation";
264
+ readonly targetCollection: "people";
265
+ }, {
266
+ readonly name: "relations";
267
+ readonly type: "relation";
268
+ readonly targetCollection: "people";
269
+ readonly hasMany: true;
270
+ }, {
271
+ readonly name: "optionalText";
272
+ readonly type: "text";
273
+ readonly optional: true;
274
+ }, {
275
+ readonly name: "group";
276
+ readonly type: "group";
277
+ readonly fields: readonly [{
278
+ readonly name: "title";
279
+ readonly type: "text";
280
+ readonly localized: true;
281
+ }, {
282
+ readonly name: "enabled";
283
+ readonly type: "boolean";
284
+ readonly optional: true;
285
+ }];
286
+ }, {
287
+ readonly name: "array";
288
+ readonly type: "array";
289
+ readonly fields: readonly [{
290
+ readonly name: "label";
291
+ readonly type: "text";
292
+ readonly localized: true;
293
+ }, {
294
+ readonly name: "score";
295
+ readonly type: "integer";
296
+ readonly optional: true;
297
+ }];
298
+ }, {
299
+ readonly name: "content's";
300
+ readonly type: "blocks";
301
+ readonly blocks: [{
302
+ readonly blockType: "quote'block";
303
+ readonly fields: readonly [{
304
+ readonly name: "quotation";
305
+ readonly type: "textArea";
306
+ readonly localized: true;
307
+ }, {
308
+ readonly name: "tone'choice";
309
+ readonly type: "select";
310
+ readonly optional: true;
311
+ readonly options: [{
312
+ readonly label: "Calm";
313
+ readonly value: "calm";
314
+ }, {
315
+ readonly label: "Quoted";
316
+ readonly value: "author's";
317
+ }];
318
+ }];
319
+ }, {
320
+ readonly blockType: "media";
321
+ readonly fields: readonly [{
322
+ readonly name: "caption";
323
+ readonly type: "text";
324
+ readonly localized: true;
325
+ readonly optional: true;
326
+ }, {
327
+ readonly name: "image";
328
+ readonly type: "image";
329
+ }];
330
+ }];
331
+ }];
332
+ }, {
333
+ readonly path: "minimal";
334
+ readonly labels: {
335
+ readonly singular: "Minimal";
336
+ readonly plural: "Minimal";
337
+ };
338
+ readonly fields: [{
339
+ readonly name: "title";
340
+ readonly type: "text";
341
+ }];
342
+ }];