@stackbit/cms-core 0.1.21-cross-references.0 → 0.1.21
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.
- package/dist/content-store-types.d.ts +8 -34
- package/dist/content-store-types.d.ts.map +1 -1
- package/dist/content-store-utils.d.ts +1 -3
- package/dist/content-store-utils.d.ts.map +1 -1
- package/dist/content-store-utils.js +1 -8
- package/dist/content-store-utils.js.map +1 -1
- package/dist/content-store.d.ts +4 -5
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +49 -62
- package/dist/content-store.js.map +1 -1
- package/dist/utils/create-update-csi-docs.d.ts +10 -11
- package/dist/utils/create-update-csi-docs.d.ts.map +1 -1
- package/dist/utils/create-update-csi-docs.js +13 -92
- package/dist/utils/create-update-csi-docs.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +1 -69
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/duplicate-document.js +0 -3
- package/dist/utils/duplicate-document.js.map +1 -1
- package/dist/utils/model-utils.d.ts +4 -4
- package/dist/utils/model-utils.d.ts.map +1 -1
- package/dist/utils/model-utils.js +2 -67
- package/dist/utils/model-utils.js.map +1 -1
- package/dist/utils/schema-utils.d.ts +87 -0
- package/dist/utils/schema-utils.d.ts.map +1 -0
- package/dist/utils/schema-utils.js +195 -0
- package/dist/utils/schema-utils.js.map +1 -0
- package/dist/utils/store-to-api-docs-converter.d.ts.map +1 -1
- package/dist/utils/store-to-api-docs-converter.js +1 -38
- package/dist/utils/store-to-api-docs-converter.js.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.js +0 -30
- package/dist/utils/store-to-csi-docs-converter.js.map +1 -1
- package/package.json +4 -4
- package/src/content-store-types.ts +3 -41
- package/src/content-store-utils.ts +1 -9
- package/src/content-store.ts +50 -66
- package/src/utils/create-update-csi-docs.ts +18 -109
- package/src/utils/csi-to-store-docs-converter.ts +17 -91
- package/src/utils/duplicate-document.ts +0 -3
- package/src/utils/model-utils.ts +7 -95
- package/src/utils/schema-utils.js +212 -0
- package/src/utils/store-to-api-docs-converter.ts +1 -38
- package/src/utils/store-to-csi-docs-converter.ts +0 -30
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
|
|
3
|
+
const FIELD_TYPES = [
|
|
4
|
+
'string',
|
|
5
|
+
'text',
|
|
6
|
+
'markdown',
|
|
7
|
+
'html',
|
|
8
|
+
'url',
|
|
9
|
+
'slug',
|
|
10
|
+
'number',
|
|
11
|
+
'boolean',
|
|
12
|
+
'select',
|
|
13
|
+
'enum',
|
|
14
|
+
'date',
|
|
15
|
+
'datetime',
|
|
16
|
+
'color',
|
|
17
|
+
'image',
|
|
18
|
+
'file',
|
|
19
|
+
'json',
|
|
20
|
+
'reference',
|
|
21
|
+
'model',
|
|
22
|
+
'models',
|
|
23
|
+
'object',
|
|
24
|
+
'list',
|
|
25
|
+
'array'
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
FIELD_TYPES,
|
|
30
|
+
isObjectField,
|
|
31
|
+
isModelField,
|
|
32
|
+
isModelsField,
|
|
33
|
+
isReferenceField,
|
|
34
|
+
isCustomModelField,
|
|
35
|
+
isListField,
|
|
36
|
+
isListOfObjectsField,
|
|
37
|
+
isListOfModelField,
|
|
38
|
+
isListOfModelsField,
|
|
39
|
+
isListOfCustomModelField,
|
|
40
|
+
isListOfReferenceField,
|
|
41
|
+
getListItemsField,
|
|
42
|
+
iterateModelFieldsRecursively,
|
|
43
|
+
resolveLabelFieldForModel,
|
|
44
|
+
resolveLabelFieldFromFields,
|
|
45
|
+
getUrlPath,
|
|
46
|
+
getNormalizedModelType
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
function resolveLabelFieldForModel(model, modelLabelFieldPath, fields) {
|
|
51
|
+
let labelField = _.get(model, modelLabelFieldPath, null);
|
|
52
|
+
if (labelField) {
|
|
53
|
+
return labelField;
|
|
54
|
+
}
|
|
55
|
+
return resolveLabelFieldFromFields(fields);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveLabelFieldFromFields(fields) {
|
|
59
|
+
let labelField = null;
|
|
60
|
+
let titleField = _.find(fields, field => field.name === 'title' && _.includes(['string', 'text'], field.type));
|
|
61
|
+
if (!titleField) {
|
|
62
|
+
// get first string field
|
|
63
|
+
titleField = _.find(fields, {type: 'string'});
|
|
64
|
+
}
|
|
65
|
+
if (titleField) {
|
|
66
|
+
labelField = _.get(titleField, 'name');
|
|
67
|
+
}
|
|
68
|
+
return labelField;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isObjectField(field) {
|
|
72
|
+
return field.type === 'object';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isReferenceField(field) {
|
|
76
|
+
return field.type === 'reference';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isCustomModelField(field, modelsByName) {
|
|
80
|
+
return !FIELD_TYPES.includes(field.type) && (!modelsByName || _.has(modelsByName, field.type));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isModelField(field) {
|
|
84
|
+
return field.type === 'model';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isModelsField(field) {
|
|
88
|
+
return field.type === 'models';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function isListField(field) {
|
|
92
|
+
return ['list', 'array'].includes(field.type);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isListOfObjectsField(field) {
|
|
96
|
+
return isListField(field) && isObjectField(getListItemsField(field));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function isListOfModelField(field) {
|
|
100
|
+
return isListField(field) && isModelField(getListItemsField(field));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isListOfModelsField(field) {
|
|
104
|
+
return isListField(field) && isModelsField(getListItemsField(field));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isListOfCustomModelField(field) {
|
|
108
|
+
return isListField(field) && isCustomModelField(getListItemsField(field));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function isListOfReferenceField(field) {
|
|
112
|
+
return isListField(field) && isReferenceField(getListItemsField(field));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Gets a list field and returns its items field. If list field does not define
|
|
117
|
+
* items field, the default field is string:
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* listItemField = getListItemsField({
|
|
121
|
+
* type: 'list',
|
|
122
|
+
* name: '...',
|
|
123
|
+
* items: { type: 'object', fields: [] }
|
|
124
|
+
* }
|
|
125
|
+
* listItemField => {
|
|
126
|
+
* type: 'object',
|
|
127
|
+
* name: '...',
|
|
128
|
+
* fields: []
|
|
129
|
+
* }
|
|
130
|
+
*
|
|
131
|
+
* // list field without `items`
|
|
132
|
+
* listItemField = getListItemsField({ type: 'list', name: '...' }
|
|
133
|
+
* listItemField => { type: 'string' }
|
|
134
|
+
*
|
|
135
|
+
* @param {Object} field
|
|
136
|
+
* @return {Object}
|
|
137
|
+
*/
|
|
138
|
+
function getListItemsField(field) {
|
|
139
|
+
// items.type defaults to string
|
|
140
|
+
return _.defaults({}, _.get(field, 'items', {}), {type: 'string'});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* This function invokes the `iterator` function for every field of the `model`.
|
|
145
|
+
* It recursively traverses through fields of type `object` and `list` with
|
|
146
|
+
* items of type `object` and invokes the `iterator` on their child fields,
|
|
147
|
+
* and so on. The traversal is a depth-first and the `iterator` is invoked
|
|
148
|
+
* before traversing the field's child fields.
|
|
149
|
+
*
|
|
150
|
+
* The iterator is invoked with two parameters, `field` and `fieldPath`. The
|
|
151
|
+
* `field` is the currently iterated field, and `fieldPath` is an array of
|
|
152
|
+
* strings indicating the path of the `field` relative to the model.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* model = {
|
|
156
|
+
* fields: [
|
|
157
|
+
* { name: "title", type: "string" },
|
|
158
|
+
* {
|
|
159
|
+
* name: "banner",
|
|
160
|
+
* type: "object",
|
|
161
|
+
* fields: [
|
|
162
|
+
* { name: "logo", type: "image" }
|
|
163
|
+
* ]}
|
|
164
|
+
* {
|
|
165
|
+
* name: "actions",
|
|
166
|
+
* type: "list",
|
|
167
|
+
* items: {
|
|
168
|
+
* type: "object",
|
|
169
|
+
* fields: [
|
|
170
|
+
* {name: "label", type: "string"}
|
|
171
|
+
* ]
|
|
172
|
+
* }
|
|
173
|
+
* }
|
|
174
|
+
* ]
|
|
175
|
+
* }
|
|
176
|
+
* iterateModelFieldsRecursively(model, iterator);
|
|
177
|
+
* // will call the iterator with following field.name and fieldPath
|
|
178
|
+
* - 'title', ['fields', 'title']
|
|
179
|
+
* - 'banner', ['fields', 'banner']
|
|
180
|
+
* - 'logo', ['fields', 'banner', 'fields', 'logo']
|
|
181
|
+
* - 'actions', ['fields', 'actions']
|
|
182
|
+
* - 'label', ['fields', 'actions', 'items', 'fields', 'label']
|
|
183
|
+
*
|
|
184
|
+
* @param {Object} model The root model to iterate fields
|
|
185
|
+
* @param {Function} iterator The iterator function
|
|
186
|
+
* @param {Array} [fieldPath]
|
|
187
|
+
*/
|
|
188
|
+
function iterateModelFieldsRecursively(model, iterator, fieldPath = []) {
|
|
189
|
+
const fields = _.get(model, 'fields', []);
|
|
190
|
+
fieldPath = fieldPath.concat('fields');
|
|
191
|
+
_.forEach(fields, (field) => {
|
|
192
|
+
const childFieldPath = fieldPath.concat(field.name);
|
|
193
|
+
iterator(field, childFieldPath);
|
|
194
|
+
if (isObjectField(field)) {
|
|
195
|
+
iterateModelFieldsRecursively(field, iterator, childFieldPath);
|
|
196
|
+
} else if (isListOfObjectsField(field)) {
|
|
197
|
+
iterateModelFieldsRecursively(getListItemsField(field), iterator, childFieldPath.concat('items'));
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function getUrlPath(stackbitModel) {
|
|
203
|
+
const modelType = getNormalizedModelType(stackbitModel);
|
|
204
|
+
if (modelType === 'page') {
|
|
205
|
+
return _.get(stackbitModel, 'urlPath', '/{slug}');
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function getNormalizedModelType(stackbitModel) {
|
|
211
|
+
return stackbitModel ? (stackbitModel.type === 'config' ? 'data' : stackbitModel.type) : 'object';
|
|
212
|
+
}
|
|
@@ -144,7 +144,7 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
|
|
|
144
144
|
}),
|
|
145
145
|
...localeFields(docField.localized)
|
|
146
146
|
};
|
|
147
|
-
case 'reference':
|
|
147
|
+
case 'reference':
|
|
148
148
|
if (docField.localized) {
|
|
149
149
|
const { type, refType, localized, locales, ...base } = docField;
|
|
150
150
|
const localeProps = locales && locale ? locales[locale] : undefined;
|
|
@@ -179,43 +179,6 @@ function toLocalizedAPIField(docField: ContentStoreTypes.DocumentField, locale?:
|
|
|
179
179
|
...base,
|
|
180
180
|
...localeFields(docField.localized)
|
|
181
181
|
};
|
|
182
|
-
}
|
|
183
|
-
case 'cross-reference': {
|
|
184
|
-
if (docField.localized) {
|
|
185
|
-
const { type, refType, localized, locales, ...base } = docField;
|
|
186
|
-
const localeProps = locales && locale ? locales[locale] : undefined;
|
|
187
|
-
// if reference field isUnset === true, it behaves like a regular object
|
|
188
|
-
if (!localeProps) {
|
|
189
|
-
return {
|
|
190
|
-
type: 'object',
|
|
191
|
-
isUnset: true,
|
|
192
|
-
...base,
|
|
193
|
-
...localeFields(localized)
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
return {
|
|
197
|
-
type: 'cross-reference',
|
|
198
|
-
refType: refType,
|
|
199
|
-
...base,
|
|
200
|
-
...localeProps,
|
|
201
|
-
...localeFields(localized)
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
const { type, refType, ...base } = docField;
|
|
205
|
-
if (base.isUnset) {
|
|
206
|
-
return {
|
|
207
|
-
type: 'object',
|
|
208
|
-
...base,
|
|
209
|
-
...localeFields(docField.localized)
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
return {
|
|
213
|
-
type: 'cross-reference',
|
|
214
|
-
refType: refType,
|
|
215
|
-
...base,
|
|
216
|
-
...localeFields(docField.localized)
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
182
|
case 'list':
|
|
220
183
|
if (docField.localized) {
|
|
221
184
|
const { localized, locales, ...base } = docField;
|
|
@@ -179,36 +179,6 @@ function mapStoreFieldToCSIField(documentField: ContentStoreTypes.DocumentField)
|
|
|
179
179
|
refId: documentField.refId
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
|
-
case 'cross-reference': {
|
|
183
|
-
if (documentField.localized) {
|
|
184
|
-
if (_.isEmpty(documentField.locales)) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
type: 'json',
|
|
189
|
-
localized: true,
|
|
190
|
-
locales: _.mapValues(documentField.locales, (locale) => ({
|
|
191
|
-
locale: locale.locale,
|
|
192
|
-
value: {
|
|
193
|
-
refId: locale.refId,
|
|
194
|
-
refSrcType: locale.refSrcType,
|
|
195
|
-
srcProjectId: locale.refProjectId
|
|
196
|
-
}
|
|
197
|
-
}))
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
if (documentField.isUnset) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
return {
|
|
204
|
-
type: 'json',
|
|
205
|
-
value: {
|
|
206
|
-
refId: documentField.refId,
|
|
207
|
-
refSrcType: documentField.refSrcType,
|
|
208
|
-
srcProjectId: documentField.refProjectId
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
182
|
case 'list': {
|
|
213
183
|
if (documentField.localized) {
|
|
214
184
|
if (_.isEmpty(documentField.locales)) {
|