Skip to content

Commit db6b44f

Browse files
committed
feat: allow widgets to register types
1 parent 5190560 commit db6b44f

File tree

3 files changed

+96
-57
lines changed

3 files changed

+96
-57
lines changed

packages/decap-cms-core/src/actions/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ function getI18nDefaults(
132132
}
133133
}
134134

135-
function setI18nDefaultsForFields(collectionOrFileFields: CmsField[], hasI18n: boolean) {
135+
function setI18nDefaultsForFields(collectionOrFileFields: CmsField<true>[], hasI18n: boolean) {
136136
if (hasI18n) {
137137
return traverseFieldsJS(collectionOrFileFields, setI18nField);
138138
} else {
@@ -205,7 +205,7 @@ export function normalizeConfig(config: CmsConfig) {
205205
}
206206

207207
export function applyDefaults(originalConfig: CmsConfig) {
208-
return produce(originalConfig, (config: CmsConfig<true>) => {
208+
return produce(originalConfig, (config: CmsConfig) => {
209209
config.publish_mode = config.publish_mode || SIMPLE_PUBLISH_MODE;
210210
config.slug = config.slug || {};
211211
config.collections = config.collections || [];

packages/decap-cms-core/src/reducers/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const defaultState = {
1010
isFetching: true,
1111
};
1212

13-
const config = produce((state: CmsConfig<true>, action: ConfigAction) => {
13+
const config = produce((state: CmsConfig, action: ConfigAction) => {
1414
switch (action.type) {
1515
case CONFIG_REQUEST:
1616
state.isFetching = true;

packages/decap-cms-core/src/types/redux.ts

Lines changed: 93 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ export interface CmsFieldBase {
8080
comment?: string;
8181
}
8282

83-
export interface CmsFieldBoolean {
83+
export interface CmsFieldBoolean extends CmsFieldBase {
8484
widget: 'boolean';
8585
default?: boolean;
8686
}
8787

88-
export interface CmsFieldCode {
88+
export interface CmsFieldCode extends CmsFieldBase {
8989
widget: 'code';
9090
default?: unknown; // was any in public types
9191

@@ -95,15 +95,15 @@ export interface CmsFieldCode {
9595
output_code_only?: boolean;
9696
}
9797

98-
export interface CmsFieldColor {
98+
export interface CmsFieldColor extends CmsFieldBase {
9999
widget: 'color';
100100
default?: string;
101101

102102
allowInput?: boolean;
103103
enableAlpha?: boolean;
104104
}
105105

106-
export interface CmsFieldDateTime {
106+
export interface CmsFieldDateTime extends CmsFieldBase {
107107
widget: 'datetime';
108108
default?: string;
109109

@@ -126,7 +126,7 @@ export interface CmsFieldDateTime {
126126
pickerUtc?: boolean;
127127
}
128128

129-
export interface CmsFieldFileOrImage {
129+
export interface CmsFieldFileOrImage extends CmsFieldBase {
130130
widget: 'file' | 'image';
131131
default?: string;
132132

@@ -136,7 +136,7 @@ export interface CmsFieldFileOrImage {
136136
config?: unknown; // was any in public type
137137
}
138138

139-
export interface CmsFieldObject {
139+
export interface CmsFieldObject extends CmsFieldBase {
140140
widget: 'object';
141141
default?: unknown; // was any in public
142142

@@ -145,7 +145,7 @@ export interface CmsFieldObject {
145145
fields: CmsField[];
146146
}
147147

148-
export interface CmsFieldList {
148+
export interface CmsFieldList extends CmsFieldBase {
149149
widget: 'list';
150150
default?: unknown; // was any in public
151151

@@ -162,15 +162,15 @@ export interface CmsFieldList {
162162
types?: (CmsFieldBase & CmsFieldObject)[];
163163
}
164164

165-
export interface CmsFieldMap {
165+
export interface CmsFieldMap extends CmsFieldBase {
166166
widget: 'map';
167167
default?: string;
168168

169169
decimals?: number;
170170
type?: CmsMapWidgetType;
171171
}
172172

173-
export interface CmsFieldMarkdown {
173+
export interface CmsFieldMarkdown extends CmsFieldBase {
174174
widget: 'markdown';
175175
default?: string;
176176

@@ -185,7 +185,7 @@ export interface CmsFieldMarkdown {
185185
editorComponents?: string[];
186186
}
187187

188-
export interface CmsFieldNumber {
188+
export interface CmsFieldNumber extends CmsFieldBase {
189189
widget: 'number';
190190
default?: string | number;
191191

@@ -201,7 +201,7 @@ export interface CmsFieldNumber {
201201
valueType?: 'int' | 'float' | string;
202202
}
203203

204-
export interface CmsFieldSelect {
204+
export interface CmsFieldSelect extends CmsFieldBase {
205205
widget: 'select';
206206
default?: string | string[];
207207

@@ -211,7 +211,7 @@ export interface CmsFieldSelect {
211211
max?: number;
212212
}
213213

214-
export interface CmsFieldRelation {
214+
export interface CmsFieldRelation extends CmsFieldBase {
215215
widget: 'relation';
216216
default?: string | string[];
217217

@@ -241,54 +241,93 @@ export interface CmsFieldRelation {
241241
optionsLength?: number;
242242
}
243243

244-
export interface CmsFieldHidden {
244+
export interface CmsFieldHidden extends CmsFieldBase {
245245
widget: 'hidden';
246246
default?: unknown; // was any in public type
247247
}
248248

249-
export interface CmsFieldStringOrText {
250-
// This is the default widget, so declaring its type is optional.
251-
widget?: 'string' | 'text';
249+
export interface CmsFieldStringBase extends CmsFieldBase {
252250
default?: string;
253251
visualEditing?: boolean;
254252
}
255253

256-
export interface CmsFieldMeta {
257-
name: string;
258-
label: string;
259-
widget: string;
260-
required: boolean;
254+
export interface CmsFieldString extends CmsFieldStringBase {
255+
widget: 'string';
256+
}
257+
258+
export interface CmsFieldText extends CmsFieldStringBase {
259+
widget: 'text';
260+
}
261+
262+
/**
263+
* Interface that can be augmented by custom widgets to add their own properties.
264+
*/
265+
export interface CmsFields {
266+
boolean: CmsFieldBoolean;
267+
code: CmsFieldCode;
268+
color: CmsFieldColor;
269+
datetime: CmsFieldDateTime;
270+
file: CmsFieldFileOrImage;
271+
image: CmsFieldFileOrImage;
272+
list: CmsFieldList;
273+
map: CmsFieldMap;
274+
markdown: CmsFieldMarkdown;
275+
number: CmsFieldNumber;
276+
object: CmsFieldObject;
277+
relation: CmsFieldRelation;
278+
select: CmsFieldSelect;
279+
hidden: CmsFieldHidden;
280+
string: CmsFieldString;
281+
text: CmsFieldText;
282+
}
283+
284+
type RegisteredCmsField = {
285+
[K in keyof CmsFields]: { widget: K } & CmsFields[K];
286+
}[keyof CmsFields];
287+
288+
/**
289+
* Meta fields are defined outside of the fields[] array but added to it
290+
* internally.
291+
*/
292+
export type CmsFieldMeta<IsInternal extends boolean = false> = {
261293
index_file: string;
262-
meta: boolean;
263-
}
264-
265-
export type CmsFieldCore =
266-
| CmsFieldBoolean
267-
| CmsFieldCode
268-
| CmsFieldColor
269-
| CmsFieldDateTime
270-
| CmsFieldFileOrImage
271-
| CmsFieldList
272-
| CmsFieldMap
273-
| CmsFieldMarkdown
274-
| CmsFieldNumber
275-
| CmsFieldObject
276-
| CmsFieldRelation
277-
| CmsFieldSelect
278-
| CmsFieldHidden
279-
| CmsFieldStringOrText;
280-
281-
export type CmsFieldCustom = Record<string, any> & {
282-
widget: Exclude<string, CmsFieldCore['widget']>;
283-
};
284-
285-
export type CmsField = CmsFieldBase & (CmsFieldCore | CmsFieldMeta | CmsFieldCustom);
286-
287-
export interface CmsCollectionFile {
294+
label?: string;
295+
hint?: string;
296+
comment?: string;
297+
} & IsInternal extends true
298+
? {
299+
widget: 'string';
300+
name: 'path';
301+
meta: true;
302+
required: true;
303+
}
304+
: {
305+
widget?: 'string';
306+
name?: never;
307+
};
308+
309+
/**
310+
* Fields without a widget prop are treated as string fields.
311+
*/
312+
export type CmsFieldDefault<IsInternal extends boolean = true> = CmsFieldStringBase &
313+
(IsInternal extends true
314+
? {
315+
widget: 'string';
316+
}
317+
: {
318+
widget?: never;
319+
});
320+
321+
export type CmsField<IsInternal extends boolean = true> =
322+
| RegisteredCmsField
323+
| CmsFieldDefault<IsInternal>
324+
| CmsFieldMeta<IsInternal>;
325+
326+
export interface CmsCollectionFile<IsInternal extends boolean = true> {
288327
name: string;
289328
label: string;
290329
file: string;
291-
fields: CmsField[];
330+
fields: CmsField<IsInternal>[];
292331
label_singular?: string;
293332
description?: string;
294333
preview_path?: string;
@@ -310,13 +349,13 @@ export type ViewGroup<IsInternal extends boolean = true> = {
310349
pattern: string;
311350
} & (IsInternal extends true ? { id: string } : {});
312351

313-
export type CmsCollection<IsInternal extends boolean = false> = {
352+
export type CmsCollection<IsInternal extends boolean = true> = {
314353
name: string;
315354
label: string;
316355
label_singular?: string;
317356
description?: string;
318357
folder?: string;
319-
files?: CmsCollectionFile[];
358+
files?: CmsCollectionFile<IsInternal>[];
320359
identifier_field?: string;
321360
summary?: string;
322361
slug?: string;
@@ -333,7 +372,7 @@ export type CmsCollection<IsInternal extends boolean = false> = {
333372
nested?: {
334373
depth: number;
335374
};
336-
meta?: { path?: { label: string; widget: string; index_file: string } };
375+
meta?: { path?: CmsFieldMeta<IsInternal> };
337376

338377
/**
339378
* It accepts the following values: yml, yaml, toml, json, md, markdown, html
@@ -344,7 +383,7 @@ export type CmsCollection<IsInternal extends boolean = false> = {
344383
format?: CmsCollectionFormatType;
345384

346385
frontmatter_delimiter?: string[] | string;
347-
fields?: CmsField[];
386+
fields?: CmsField<IsInternal>[];
348387
filter?: { field: string; value: unknown }; // value way any in public type!
349388
path?: string;
350389
media_folder?: string;
@@ -397,7 +436,7 @@ export interface CmsLocalBackend {
397436
allowed_hosts?: string[];
398437
}
399438

400-
export type CmsConfig<IsInternal extends boolean = false> = {
439+
export type CmsConfig<IsInternal extends boolean = true> = {
401440
backend: CmsBackend;
402441
collections: CmsCollection<IsInternal>[];
403442
locale?: string;
@@ -699,7 +738,7 @@ export type Cursors = StaticallyTypedRecord<{}>;
699738

700739
export interface State {
701740
auth: Auth;
702-
config: CmsConfig<true>;
741+
config: CmsConfig;
703742
cursors: Cursors;
704743
collections: Collections;
705744
deploys: Deploys;

0 commit comments

Comments
 (0)