@stackbit/sdk 0.2.39 → 0.3.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.
- package/dist/analyzer/site-analyzer.d.ts.map +1 -1
- package/dist/analyzer/site-analyzer.js +3 -1
- package/dist/analyzer/site-analyzer.js.map +1 -1
- package/dist/config/config-errors.d.ts +3 -0
- package/dist/config/config-errors.d.ts.map +1 -1
- package/dist/config/config-errors.js +7 -2
- package/dist/config/config-errors.js.map +1 -1
- package/dist/config/config-loader-esbuild.d.ts +3 -14
- package/dist/config/config-loader-esbuild.d.ts.map +1 -1
- package/dist/config/config-loader-esbuild.js +19 -2
- package/dist/config/config-loader-esbuild.js.map +1 -1
- package/dist/config/config-loader-static.d.ts +14 -0
- package/dist/config/config-loader-static.d.ts.map +1 -0
- package/dist/config/config-loader-static.js +170 -0
- package/dist/config/config-loader-static.js.map +1 -0
- package/dist/config/config-loader-utils.d.ts +34 -0
- package/dist/config/config-loader-utils.d.ts.map +1 -0
- package/dist/config/config-loader-utils.js +211 -0
- package/dist/config/config-loader-utils.js.map +1 -0
- package/dist/config/config-loader.d.ts +13 -9
- package/dist/config/config-loader.d.ts.map +1 -1
- package/dist/config/config-loader.js +175 -199
- package/dist/config/config-loader.js.map +1 -1
- package/dist/config/config-schema/style-field-schema.d.ts.map +1 -1
- package/dist/config/config-schema/style-field-schema.js.map +1 -1
- package/dist/config/config-schema.d.ts +2 -2
- package/dist/config/config-schema.d.ts.map +1 -1
- package/dist/config/config-schema.js +5 -6
- package/dist/config/config-schema.js.map +1 -1
- package/dist/config/config-types.d.ts +32 -2
- package/dist/config/config-types.d.ts.map +1 -1
- package/dist/config/config-validator.d.ts +5 -3
- package/dist/config/config-validator.d.ts.map +1 -1
- package/dist/config/config-validator.js.map +1 -1
- package/dist/config/config-writer.d.ts +1 -4
- package/dist/config/config-writer.d.ts.map +1 -1
- package/dist/config/config-writer.js +3 -27
- package/dist/config/config-writer.js.map +1 -1
- package/dist/content/content-schema.js +5 -6
- package/dist/content/content-schema.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/model-extender.d.ts +1 -1
- package/dist/utils/model-extender.d.ts.map +1 -1
- package/dist/utils/model-extender.js.map +1 -1
- package/package.json +4 -3
- package/src/analyzer/site-analyzer.ts +3 -1
- package/src/config/config-errors.ts +7 -1
- package/src/config/config-loader-esbuild.ts +24 -19
- package/src/config/config-loader-static.ts +210 -0
- package/src/config/config-loader-utils.ts +253 -0
- package/src/config/config-loader.ts +210 -237
- package/src/config/config-schema/style-field-schema.ts +1 -4
- package/src/config/config-schema.ts +17 -18
- package/src/config/config-types.ts +31 -2
- package/src/config/config-validator.ts +5 -3
- package/src/config/config-writer.ts +2 -30
- package/src/content/content-schema.ts +17 -18
- package/src/index.ts +4 -2
- package/src/utils/index.ts +1 -1
- package/src/utils/model-extender.ts +2 -2
|
@@ -25,28 +25,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
25
25
|
exports.loadConfigFromDir = exports.validateAndNormalizeConfig = exports.extendConfig = exports.loadConfig = void 0;
|
|
26
26
|
const path_1 = __importDefault(require("path"));
|
|
27
27
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
28
|
-
const
|
|
28
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
29
29
|
const semver_1 = __importDefault(require("semver"));
|
|
30
30
|
const lodash_1 = __importDefault(require("lodash"));
|
|
31
|
+
const utils_1 = require("@stackbit/utils");
|
|
31
32
|
const config_validator_1 = require("./config-validator");
|
|
32
33
|
const config_errors_1 = require("./config-errors");
|
|
33
34
|
const config_loader_esbuild_1 = require("./config-loader-esbuild");
|
|
34
|
-
const
|
|
35
|
-
const utils_2 = require("@stackbit/utils");
|
|
35
|
+
const utils_2 = require("../utils");
|
|
36
36
|
const presets_loader_1 = require("./presets-loader");
|
|
37
|
-
|
|
37
|
+
const config_loader_utils_1 = require("./config-loader-utils");
|
|
38
|
+
async function loadConfig({ dirPath, modelsSource, stackbitConfigESBuildOutDir, watchCallback, logger }) {
|
|
39
|
+
let wrappedCallback;
|
|
40
|
+
if (watchCallback) {
|
|
41
|
+
wrappedCallback = async (rawConfigResult) => {
|
|
42
|
+
const configLoaderResult = await processConfigLoaderResult({ rawConfigResult, dirPath, modelsSource });
|
|
43
|
+
watchCallback(configLoaderResult);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
38
46
|
const rawConfigResult = await loadConfigFromDir({
|
|
39
47
|
dirPath,
|
|
40
48
|
stackbitConfigESBuildOutDir,
|
|
41
|
-
watchCallback:
|
|
42
|
-
|
|
43
|
-
const configLoaderResult = await processConfigLoaderResult({ rawConfigResult, dirPath, modelsSource });
|
|
44
|
-
watchCallback(configLoaderResult);
|
|
45
|
-
}
|
|
46
|
-
: undefined
|
|
49
|
+
watchCallback: wrappedCallback,
|
|
50
|
+
logger
|
|
47
51
|
});
|
|
48
52
|
const configLoaderResult = await processConfigLoaderResult({ rawConfigResult, dirPath, modelsSource });
|
|
49
|
-
return Object.assign(configLoaderResult, {
|
|
53
|
+
return Object.assign(configLoaderResult, {
|
|
54
|
+
stop: rawConfigResult.stop,
|
|
55
|
+
reload: rawConfigResult.reload
|
|
56
|
+
});
|
|
50
57
|
}
|
|
51
58
|
exports.loadConfig = loadConfig;
|
|
52
59
|
async function processConfigLoaderResult({ rawConfigResult, dirPath, modelsSource }) {
|
|
@@ -59,16 +66,16 @@ async function processConfigLoaderResult({ rawConfigResult, dirPath, modelsSourc
|
|
|
59
66
|
};
|
|
60
67
|
}
|
|
61
68
|
const { models: externalModels, errors: externalModelsLoadErrors } = await loadModelsFromExternalSource(config, dirPath, modelsSource);
|
|
62
|
-
const extendedConfig = await extendConfig({
|
|
69
|
+
const extendedConfig = await extendConfig({ config, externalModels });
|
|
63
70
|
return {
|
|
64
71
|
valid: extendedConfig.valid,
|
|
65
72
|
config: extendedConfig.config,
|
|
66
73
|
errors: [...configLoadErrors, ...externalModelsLoadErrors, ...extendedConfig.errors]
|
|
67
74
|
};
|
|
68
75
|
}
|
|
69
|
-
async function extendConfig({
|
|
76
|
+
async function extendConfig({ config, externalModels }) {
|
|
70
77
|
const normalizedResult = validateAndNormalizeConfig(config, externalModels);
|
|
71
|
-
const presetsResult = await presets_loader_1.loadPresets(dirPath, normalizedResult.config);
|
|
78
|
+
const presetsResult = await presets_loader_1.loadPresets(config.dirPath, normalizedResult.config);
|
|
72
79
|
return {
|
|
73
80
|
valid: normalizedResult.valid,
|
|
74
81
|
config: presetsResult.config,
|
|
@@ -80,7 +87,7 @@ function validateAndNormalizeConfig(config, externalModels) {
|
|
|
80
87
|
// extend config models having the "extends" property
|
|
81
88
|
// this must be done before any validation as some properties like
|
|
82
89
|
// the labelField will not work when validating models without extending them first
|
|
83
|
-
const { models: extendedModels, errors: extendModelErrors } =
|
|
90
|
+
const { models: extendedModels, errors: extendModelErrors } = utils_2.extendModelMap(config.models);
|
|
84
91
|
const extendedConfig = {
|
|
85
92
|
...config,
|
|
86
93
|
models: extendedModels
|
|
@@ -102,25 +109,71 @@ function validateAndNormalizeConfig(config, externalModels) {
|
|
|
102
109
|
});
|
|
103
110
|
}
|
|
104
111
|
exports.validateAndNormalizeConfig = validateAndNormalizeConfig;
|
|
105
|
-
async function loadConfigFromDir({ dirPath, stackbitConfigESBuildOutDir, watchCallback }) {
|
|
106
|
-
var _a;
|
|
112
|
+
async function loadConfigFromDir({ dirPath, stackbitConfigESBuildOutDir, watchCallback, logger }) {
|
|
107
113
|
// try to load stackbit config from YAML files
|
|
108
114
|
try {
|
|
109
|
-
const stackbitYamlPath =
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
const stackbitYamlPath = await utils_1.getFirstExistingFile(config_loader_utils_1.STACKBIT_CONFIG_YAML_FILES, dirPath);
|
|
116
|
+
if (stackbitYamlPath) {
|
|
117
|
+
const { config, errors } = await config_loader_utils_1.loadConfigWithModelsFromDir(dirPath);
|
|
118
|
+
let close = async () => void 0;
|
|
119
|
+
let reload = () => void 0;
|
|
120
|
+
let stopped = false;
|
|
121
|
+
if (watchCallback) {
|
|
122
|
+
const watcher = chokidar_1.default.watch([...config_loader_utils_1.STACKBIT_CONFIG_YAML_FILES, '.stackbit'], {
|
|
123
|
+
cwd: dirPath,
|
|
124
|
+
persistent: true,
|
|
125
|
+
ignoreInitial: true
|
|
126
|
+
});
|
|
127
|
+
const throttledFileChange = lodash_1.default.throttle(async () => {
|
|
128
|
+
const { config, errors } = await config_loader_utils_1.loadConfigWithModelsFromDir(dirPath);
|
|
129
|
+
watchCallback({
|
|
130
|
+
config: config
|
|
131
|
+
? {
|
|
132
|
+
...config,
|
|
133
|
+
dirPath: dirPath,
|
|
134
|
+
filePath: stackbitYamlPath
|
|
135
|
+
}
|
|
136
|
+
: undefined,
|
|
137
|
+
errors
|
|
138
|
+
});
|
|
139
|
+
}, 1000);
|
|
140
|
+
const handleFileChange = (path) => {
|
|
141
|
+
logger === null || logger === void 0 ? void 0 : logger.debug(`identified change in stackbit config file: ${path}, reloading config...`);
|
|
142
|
+
throttledFileChange();
|
|
143
|
+
};
|
|
144
|
+
watcher.on('add', handleFileChange);
|
|
145
|
+
watcher.on('change', handleFileChange);
|
|
146
|
+
watcher.on('unlink', handleFileChange);
|
|
147
|
+
watcher.on('addDir', handleFileChange);
|
|
148
|
+
watcher.on('unlinkDir', handleFileChange);
|
|
149
|
+
watcher.on('error', (error) => {
|
|
150
|
+
watchCallback({
|
|
151
|
+
errors: [new config_errors_1.ConfigLoadError(`Error loading Stackbit configuration: ${error.message}`, { originalError: error })]
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
close = async () => {
|
|
155
|
+
if (stopped) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
stopped = true;
|
|
159
|
+
throttledFileChange.cancel();
|
|
160
|
+
watcher.close();
|
|
161
|
+
};
|
|
162
|
+
reload = () => {
|
|
163
|
+
throttledFileChange();
|
|
164
|
+
};
|
|
115
165
|
}
|
|
116
|
-
const { models: modelsFromFiles, errors: fileModelsErrors } = await loadModelsFromFiles(dirPath, stackbitYamlResult.config);
|
|
117
|
-
const mergedModels = mergeConfigModelsWithModelsFromFiles((_a = stackbitYamlResult.config.models) !== null && _a !== void 0 ? _a : {}, modelsFromFiles);
|
|
118
166
|
return {
|
|
119
|
-
config:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
167
|
+
config: config
|
|
168
|
+
? {
|
|
169
|
+
...config,
|
|
170
|
+
dirPath: dirPath,
|
|
171
|
+
filePath: stackbitYamlPath
|
|
172
|
+
}
|
|
173
|
+
: undefined,
|
|
174
|
+
stop: close,
|
|
175
|
+
reload: reload,
|
|
176
|
+
errors: errors
|
|
124
177
|
};
|
|
125
178
|
}
|
|
126
179
|
}
|
|
@@ -129,7 +182,7 @@ async function loadConfigFromDir({ dirPath, stackbitConfigESBuildOutDir, watchCa
|
|
|
129
182
|
errors: [new config_errors_1.ConfigLoadError(`Error loading Stackbit configuration: ${error.message}`, { originalError: error })]
|
|
130
183
|
};
|
|
131
184
|
}
|
|
132
|
-
function wrapResult(result) {
|
|
185
|
+
function wrapResult(result, configFilePath) {
|
|
133
186
|
if (result.error) {
|
|
134
187
|
return {
|
|
135
188
|
errors: [result.error]
|
|
@@ -137,26 +190,31 @@ async function loadConfigFromDir({ dirPath, stackbitConfigESBuildOutDir, watchCa
|
|
|
137
190
|
}
|
|
138
191
|
else {
|
|
139
192
|
return {
|
|
140
|
-
config:
|
|
193
|
+
config: {
|
|
194
|
+
...result.config,
|
|
195
|
+
dirPath: dirPath,
|
|
196
|
+
filePath: configFilePath
|
|
197
|
+
},
|
|
141
198
|
errors: []
|
|
142
199
|
};
|
|
143
200
|
}
|
|
144
201
|
}
|
|
145
202
|
// try to load stackbit config from JavaScript files
|
|
146
203
|
try {
|
|
147
|
-
const configFilePath = await
|
|
204
|
+
const configFilePath = await utils_1.getFirstExistingFile(config_loader_utils_1.STACKBIT_CONFIG_JS_FILES, dirPath);
|
|
148
205
|
if (configFilePath) {
|
|
149
206
|
const configResult = await config_loader_esbuild_1.loadStackbitConfigFromJs({
|
|
150
207
|
configPath: configFilePath,
|
|
151
|
-
outDir: stackbitConfigESBuildOutDir,
|
|
208
|
+
outDir: stackbitConfigESBuildOutDir !== null && stackbitConfigESBuildOutDir !== void 0 ? stackbitConfigESBuildOutDir : '.stackbit/cache',
|
|
152
209
|
watch: !!watchCallback,
|
|
210
|
+
logger: logger,
|
|
153
211
|
callback: watchCallback
|
|
154
212
|
? (result) => {
|
|
155
|
-
watchCallback(wrapResult(result));
|
|
213
|
+
watchCallback(wrapResult(result, configFilePath));
|
|
156
214
|
}
|
|
157
215
|
: undefined
|
|
158
216
|
});
|
|
159
|
-
return Object.assign(wrapResult(configResult), { stop: configResult.stop });
|
|
217
|
+
return Object.assign(wrapResult(configResult, configFilePath), { stop: configResult.stop });
|
|
160
218
|
}
|
|
161
219
|
}
|
|
162
220
|
catch (error) {
|
|
@@ -165,79 +223,15 @@ async function loadConfigFromDir({ dirPath, stackbitConfigESBuildOutDir, watchCa
|
|
|
165
223
|
};
|
|
166
224
|
}
|
|
167
225
|
return {
|
|
168
|
-
errors: [
|
|
169
|
-
new config_errors_1.ConfigLoadError('stackbit.yaml or stackbit.config.js was not found, please refer Stackbit documentation: https://www.stackbit.com/docs/stackbit-yaml/')
|
|
170
|
-
]
|
|
226
|
+
errors: [new config_errors_1.ConfigLoadError(config_errors_1.STACKBIT_CONFIG_NOT_FOUND)]
|
|
171
227
|
};
|
|
172
228
|
}
|
|
173
229
|
exports.loadConfigFromDir = loadConfigFromDir;
|
|
174
|
-
async function loadConfigFromStackbitYaml(stackbitYamlPath) {
|
|
175
|
-
const stackbitYaml = await fs_extra_1.default.readFile(stackbitYamlPath);
|
|
176
|
-
const config = js_yaml_1.default.load(stackbitYaml.toString('utf8'), { schema: js_yaml_1.default.JSON_SCHEMA });
|
|
177
|
-
if (!config || typeof config !== 'object') {
|
|
178
|
-
return {
|
|
179
|
-
error: new config_errors_1.ConfigLoadError('error parsing stackbit.yaml, please refer Stackbit documentation: https://www.stackbit.com/docs/stackbit-yaml/')
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
return { config };
|
|
183
|
-
}
|
|
184
|
-
async function loadModelsFromFiles(dirPath, config) {
|
|
185
|
-
const modelsSource = lodash_1.default.get(config, 'modelsSource', {});
|
|
186
|
-
const sourceType = lodash_1.default.get(modelsSource, 'type', 'files');
|
|
187
|
-
const defaultModelDirs = ['node_modules/@stackbit/components/models', '.stackbit/models'];
|
|
188
|
-
const modelDirs = sourceType === 'files'
|
|
189
|
-
? lodash_1.default.castArray(lodash_1.default.get(modelsSource, 'modelDirs', defaultModelDirs)).map((modelDir) => lodash_1.default.trim(modelDir, '/'))
|
|
190
|
-
: defaultModelDirs;
|
|
191
|
-
const modelFiles = await utils_2.reducePromise(modelDirs, async (modelFiles, modelDir) => {
|
|
192
|
-
const absModelsDir = path_1.default.join(dirPath, modelDir);
|
|
193
|
-
const dirExists = await fs_extra_1.default.pathExists(absModelsDir);
|
|
194
|
-
if (!dirExists) {
|
|
195
|
-
return modelFiles;
|
|
196
|
-
}
|
|
197
|
-
const files = await readModelFilesFromDir(absModelsDir);
|
|
198
|
-
return modelFiles.concat(files.map((filePath) => path_1.default.join(modelDir, filePath)));
|
|
199
|
-
}, []);
|
|
200
|
-
return utils_2.reducePromise(modelFiles, async (result, modelFile) => {
|
|
201
|
-
let model;
|
|
202
|
-
try {
|
|
203
|
-
model = await utils_2.parseFile(path_1.default.join(dirPath, modelFile));
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
return {
|
|
207
|
-
models: result.models,
|
|
208
|
-
errors: result.errors.concat(new config_errors_1.ConfigLoadError(`error parsing model, file: ${modelFile}`))
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
const modelName = model === null || model === void 0 ? void 0 : model.name;
|
|
212
|
-
if (!modelName) {
|
|
213
|
-
return {
|
|
214
|
-
models: result.models,
|
|
215
|
-
errors: result.errors.concat(new config_errors_1.ConfigLoadError(`model does not have a name, file: ${modelFile}`))
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
result.models[modelName] = lodash_1.default.omit(model, 'name');
|
|
219
|
-
result.models[modelName].__metadata = {
|
|
220
|
-
filePath: modelFile
|
|
221
|
-
};
|
|
222
|
-
return result;
|
|
223
|
-
}, { models: {}, errors: [] });
|
|
224
|
-
}
|
|
225
|
-
async function readModelFilesFromDir(modelsDir) {
|
|
226
|
-
return await utils_2.readDirRecursively(modelsDir, {
|
|
227
|
-
filter: (filePath, stats) => {
|
|
228
|
-
if (stats.isDirectory()) {
|
|
229
|
-
return true;
|
|
230
|
-
}
|
|
231
|
-
const extension = path_1.default.extname(filePath).substring(1);
|
|
232
|
-
return stats.isFile() && ['yaml', 'yml'].includes(extension);
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
230
|
async function loadModelsFromExternalSource(config, dirPath, modelsSource) {
|
|
237
|
-
modelsSource = lodash_1.default.assign({}, modelsSource, config.
|
|
231
|
+
modelsSource = lodash_1.default.assign({}, modelsSource, config.modelsSource);
|
|
238
232
|
const sourceType = lodash_1.default.get(modelsSource, 'type', 'files');
|
|
239
233
|
if (sourceType === 'files') {
|
|
240
|
-
// we already loaded models from files inside
|
|
234
|
+
// we already loaded models from files inside loadConfigFromDir function
|
|
241
235
|
return { models: [], errors: [] };
|
|
242
236
|
}
|
|
243
237
|
else if (sourceType === 'contentful') {
|
|
@@ -291,34 +285,6 @@ async function loadConfigFromDotStackbit(dirPath) {
|
|
|
291
285
|
}
|
|
292
286
|
return lodash_1.default.isEmpty(config) ? null : config;
|
|
293
287
|
}
|
|
294
|
-
function mergeConfigModelsWithModelsFromFiles(configModels, modelsFromFiles) {
|
|
295
|
-
const mergedModels = lodash_1.default.mapValues(modelsFromFiles, (modelFromFile, modelName) => {
|
|
296
|
-
var _a, _b, _c;
|
|
297
|
-
// resolve thumbnails of models loaded from files
|
|
298
|
-
const modelFilePath = (_a = modelFromFile.__metadata) === null || _a === void 0 ? void 0 : _a.filePath;
|
|
299
|
-
resolveThumbnailPathForModel(modelFromFile, modelFilePath);
|
|
300
|
-
utils_1.iterateModelFieldsRecursively(modelFromFile, (field) => {
|
|
301
|
-
if (utils_1.isListField(field)) {
|
|
302
|
-
field = utils_1.normalizeListFieldInPlace(field);
|
|
303
|
-
field = field.items;
|
|
304
|
-
}
|
|
305
|
-
if (utils_1.isObjectField(field)) {
|
|
306
|
-
resolveThumbnailPathForModel(field, modelFilePath);
|
|
307
|
-
}
|
|
308
|
-
else if (utils_1.isEnumField(field)) {
|
|
309
|
-
resolveThumbnailPathForEnumField(field, modelFilePath);
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
const configModel = lodash_1.default.get(configModels, modelName);
|
|
313
|
-
if (!configModel) {
|
|
314
|
-
return modelFromFile;
|
|
315
|
-
}
|
|
316
|
-
return lodash_1.default.assign({}, modelFromFile, configModel, {
|
|
317
|
-
fields: lodash_1.default.unionBy((_b = configModel === null || configModel === void 0 ? void 0 : configModel.fields) !== null && _b !== void 0 ? _b : [], (_c = modelFromFile === null || modelFromFile === void 0 ? void 0 : modelFromFile.fields) !== null && _c !== void 0 ? _c : [], 'name')
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
return Object.assign({}, configModels, mergedModels);
|
|
321
|
-
}
|
|
322
288
|
function mergeConfigWithExternalModels(config, externalModels) {
|
|
323
289
|
var _a;
|
|
324
290
|
if (!externalModels || externalModels.length === 0) {
|
|
@@ -341,12 +307,12 @@ function mergeConfigWithExternalModels(config, externalModels) {
|
|
|
341
307
|
}
|
|
342
308
|
const modelType = stackbitModel.type ? (stackbitModel.type === 'config' ? 'data' : stackbitModel.type) : (_a = externalModel.type) !== null && _a !== void 0 ? _a : 'object';
|
|
343
309
|
const urlPath = modelType === 'page' ? (_b = stackbitModel === null || stackbitModel === void 0 ? void 0 : stackbitModel.urlPath) !== null && _b !== void 0 ? _b : '/{slug}' : null;
|
|
344
|
-
externalModel = Object.assign({}, externalModel, lodash_1.default.pick(stackbitModel, ['__metadata', 'label', 'description', 'thumbnail', 'singleInstance', 'readOnly', 'labelField', 'fieldGroups']),
|
|
310
|
+
externalModel = Object.assign({}, externalModel, lodash_1.default.pick(stackbitModel, ['__metadata', 'label', 'description', 'thumbnail', 'singleInstance', 'readOnly', 'labelField', 'fieldGroups']), utils_1.omitByNil({
|
|
345
311
|
type: modelType,
|
|
346
312
|
urlPath
|
|
347
313
|
}));
|
|
348
|
-
externalModel =
|
|
349
|
-
const stackbitField =
|
|
314
|
+
externalModel = utils_2.mapModelFieldsRecursively(externalModel, (externalField, modelKeyPath) => {
|
|
315
|
+
const stackbitField = utils_2.getModelFieldForModelKeyPath(stackbitModel, modelKeyPath);
|
|
350
316
|
if (!stackbitField) {
|
|
351
317
|
return externalField;
|
|
352
318
|
}
|
|
@@ -384,8 +350,12 @@ function normalizeConfig(config) {
|
|
|
384
350
|
const stackbitYamlVersion = String(lodash_1.default.get(config, 'stackbitVersion', ''));
|
|
385
351
|
const ver = semver_1.default.coerce(stackbitYamlVersion);
|
|
386
352
|
const isStackbitYamlV2 = ver ? semver_1.default.satisfies(ver, '<0.3.0') : false;
|
|
353
|
+
const isStackbitYamlV5 = ver ? semver_1.default.satisfies(ver, '>=0.5.0') : false;
|
|
387
354
|
const models = (config === null || config === void 0 ? void 0 : config.models) || {};
|
|
388
355
|
const gitCMS = isGitCMS(config);
|
|
356
|
+
utils_1.rename(config, 'logicFields', 'noEncodeFields');
|
|
357
|
+
config.hcrHandled = !stackbitYamlVersion || lodash_1.default.get(config, 'customContentReload', lodash_1.default.get(config, 'hcrHandled', !isStackbitYamlV5));
|
|
358
|
+
config.internalStackbitRunnerOptions = getInternalStackbitRunnerOptions(config);
|
|
389
359
|
lodash_1.default.forEach(models, (model, modelName) => {
|
|
390
360
|
if (!model) {
|
|
391
361
|
return;
|
|
@@ -400,54 +370,54 @@ function normalizeConfig(config) {
|
|
|
400
370
|
if (lodash_1.default.has(model, 'fields') && !Array.isArray(model.fields)) {
|
|
401
371
|
model.fields = [];
|
|
402
372
|
}
|
|
403
|
-
if (
|
|
373
|
+
if (utils_2.isPageModel(model)) {
|
|
404
374
|
// rename old 'template' property to 'layout'
|
|
405
|
-
|
|
375
|
+
utils_1.rename(model, 'template', 'layout');
|
|
406
376
|
updatePageUrlPath(model);
|
|
407
377
|
if (gitCMS) {
|
|
408
378
|
updatePageFilePath(model, config);
|
|
409
379
|
addMarkdownContentField(model);
|
|
410
380
|
}
|
|
411
381
|
}
|
|
412
|
-
else if (
|
|
382
|
+
else if (utils_2.isDataModel(model) && gitCMS) {
|
|
413
383
|
updateDataFilePath(model, config);
|
|
414
384
|
}
|
|
415
385
|
if (gitCMS) {
|
|
416
386
|
// TODO: do not add pageLayoutKey and objectTypeKey fields to models,
|
|
417
387
|
// The content validator should always assume these fields.
|
|
418
388
|
// And when new objects created from UI, it should add these fields automatically.
|
|
419
|
-
if (
|
|
389
|
+
if (utils_2.isPageModel(model)) {
|
|
420
390
|
addLayoutFieldToPageModel(model, pageLayoutKey, modelName);
|
|
421
391
|
}
|
|
422
|
-
else if (
|
|
392
|
+
else if (utils_2.isDataModel(model) && !utils_2.isListDataModel(model)) {
|
|
423
393
|
addObjectTypeKeyField(model, objectTypeKey, modelName);
|
|
424
394
|
}
|
|
425
395
|
}
|
|
426
|
-
if (
|
|
396
|
+
if (utils_2.isListDataModel(model)) {
|
|
427
397
|
// 'items.type' of list model defaults to 'string', set it explicitly
|
|
428
398
|
if (!lodash_1.default.has(model, 'items.type')) {
|
|
429
399
|
lodash_1.default.set(model, 'items.type', 'string');
|
|
430
400
|
}
|
|
431
|
-
if (
|
|
432
|
-
|
|
401
|
+
if (utils_2.isObjectListItems(model.items)) {
|
|
402
|
+
utils_2.assignLabelFieldIfNeeded(model.items);
|
|
433
403
|
}
|
|
434
404
|
}
|
|
435
405
|
else if (!lodash_1.default.has(model, 'labelField')) {
|
|
436
|
-
|
|
406
|
+
utils_2.assignLabelFieldIfNeeded(model);
|
|
437
407
|
}
|
|
438
|
-
|
|
408
|
+
utils_2.iterateModelFieldsRecursively(model, (field) => {
|
|
439
409
|
// add field label if label is not set
|
|
440
410
|
if (!lodash_1.default.has(field, 'label')) {
|
|
441
411
|
field.label = lodash_1.default.startCase(field.name);
|
|
442
412
|
}
|
|
443
|
-
if (
|
|
444
|
-
field =
|
|
413
|
+
if (utils_2.isListField(field)) {
|
|
414
|
+
field = utils_2.normalizeListFieldInPlace(field);
|
|
445
415
|
field = field.items;
|
|
446
416
|
}
|
|
447
|
-
if (
|
|
448
|
-
|
|
417
|
+
if (utils_2.isObjectField(field)) {
|
|
418
|
+
utils_2.assignLabelFieldIfNeeded(field);
|
|
449
419
|
}
|
|
450
|
-
else if (
|
|
420
|
+
else if (utils_2.isCustomModelField(field, models)) {
|
|
451
421
|
// stackbit v0.2.0 compatibility
|
|
452
422
|
// convert the old custom model field type: { type: 'action' }
|
|
453
423
|
// to the new 'model' field type: { type: 'model', models: ['action'] }
|
|
@@ -470,7 +440,7 @@ function normalizeConfig(config) {
|
|
|
470
440
|
}
|
|
471
441
|
if (isStackbitYamlV2) {
|
|
472
442
|
// in stackbit.yaml v0.2.x, the 'reference' field was what we have today as 'model' field:
|
|
473
|
-
if (
|
|
443
|
+
if (utils_2.isReferenceField(field)) {
|
|
474
444
|
field = field;
|
|
475
445
|
field.type = 'model';
|
|
476
446
|
field.models = lodash_1.default.get(field, 'models', []);
|
|
@@ -540,7 +510,7 @@ function addMarkdownContentField(model) {
|
|
|
540
510
|
if (hasMarkdownContent) {
|
|
541
511
|
return;
|
|
542
512
|
}
|
|
543
|
-
|
|
513
|
+
utils_1.append(model, 'fields', {
|
|
544
514
|
type: 'markdown',
|
|
545
515
|
name: 'markdown_content',
|
|
546
516
|
label: 'Content',
|
|
@@ -559,7 +529,7 @@ function addLayoutFieldToPageModel(model, pageLayoutKey, modelName) {
|
|
|
559
529
|
if (hasLayoutField) {
|
|
560
530
|
return;
|
|
561
531
|
}
|
|
562
|
-
|
|
532
|
+
utils_1.prepend(model, 'fields', {
|
|
563
533
|
type: 'string',
|
|
564
534
|
name: pageLayoutKey,
|
|
565
535
|
label: lodash_1.default.startCase(pageLayoutKey),
|
|
@@ -572,7 +542,7 @@ function addObjectTypeKeyField(model, objectTypeKey, modelName) {
|
|
|
572
542
|
if (hasObjectTypeField) {
|
|
573
543
|
return;
|
|
574
544
|
}
|
|
575
|
-
|
|
545
|
+
utils_1.prepend(model, 'fields', {
|
|
576
546
|
type: 'string',
|
|
577
547
|
name: objectTypeKey,
|
|
578
548
|
label: 'Object Type',
|
|
@@ -581,37 +551,6 @@ function addObjectTypeKeyField(model, objectTypeKey, modelName) {
|
|
|
581
551
|
hidden: true
|
|
582
552
|
});
|
|
583
553
|
}
|
|
584
|
-
function resolveThumbnailPathForModel(modelOrField, modelFilePath) {
|
|
585
|
-
if (modelOrField.thumbnail && modelFilePath) {
|
|
586
|
-
const modelDirPath = path_1.default.dirname(modelFilePath);
|
|
587
|
-
modelOrField.thumbnail = resolveThumbnailPath(modelOrField.thumbnail, modelDirPath);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
function resolveThumbnailPathForEnumField(enumField, modelFilePath) {
|
|
591
|
-
if (enumField.controlType === 'thumbnails' && modelFilePath) {
|
|
592
|
-
const modelDirPath = path_1.default.dirname(modelFilePath);
|
|
593
|
-
lodash_1.default.forEach(enumField.options, (option) => {
|
|
594
|
-
if (option.thumbnail) {
|
|
595
|
-
option.thumbnail = resolveThumbnailPath(option.thumbnail, modelDirPath);
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
function resolveThumbnailPath(thumbnail, modelDirPath) {
|
|
601
|
-
if (thumbnail.startsWith('//') || /https?:\/\//.test(thumbnail)) {
|
|
602
|
-
return thumbnail;
|
|
603
|
-
}
|
|
604
|
-
if (thumbnail.startsWith('/')) {
|
|
605
|
-
if (modelDirPath.endsWith('@stackbit/components/models')) {
|
|
606
|
-
modelDirPath = modelDirPath.replace(/\/models$/, '');
|
|
607
|
-
}
|
|
608
|
-
else {
|
|
609
|
-
modelDirPath = '';
|
|
610
|
-
}
|
|
611
|
-
thumbnail = thumbnail.replace(/^\//, '');
|
|
612
|
-
}
|
|
613
|
-
return path_1.default.join(modelDirPath, thumbnail);
|
|
614
|
-
}
|
|
615
554
|
/**
|
|
616
555
|
* Returns model names referenced by polymorphic 'model' and 'reference' fields.
|
|
617
556
|
* That is, fields that can hold objects of different types.
|
|
@@ -620,19 +559,19 @@ function resolveThumbnailPath(thumbnail, modelDirPath) {
|
|
|
620
559
|
*/
|
|
621
560
|
function getReferencedModelNames(field) {
|
|
622
561
|
var _a, _b;
|
|
623
|
-
if (
|
|
624
|
-
field =
|
|
562
|
+
if (utils_2.isListField(field)) {
|
|
563
|
+
field = utils_2.getListFieldItems(field);
|
|
625
564
|
}
|
|
626
565
|
// TODO: add type field to model fields inside container update/create object logic rather adding type to schema
|
|
627
566
|
// 'object' models referenced by 'model' fields should have 'type' field
|
|
628
567
|
// if these fields have than 1 model.
|
|
629
568
|
// 'data' models referenced by 'reference' fields should always have 'type' field.
|
|
630
569
|
let referencedModelNames = [];
|
|
631
|
-
if (
|
|
570
|
+
if (utils_2.isModelField(field) && ((_a = field.models) === null || _a === void 0 ? void 0 : _a.length) > 1) {
|
|
632
571
|
const modelNames = field.models;
|
|
633
572
|
referencedModelNames = lodash_1.default.union(referencedModelNames, modelNames);
|
|
634
573
|
}
|
|
635
|
-
else if (
|
|
574
|
+
else if (utils_2.isReferenceField(field) && ((_b = field.models) === null || _b === void 0 ? void 0 : _b.length) > 0) {
|
|
636
575
|
const modelNames = field.models;
|
|
637
576
|
referencedModelNames = lodash_1.default.union(referencedModelNames, modelNames);
|
|
638
577
|
}
|
|
@@ -702,7 +641,7 @@ function normalizeValidationResult(validationResult) {
|
|
|
702
641
|
return convertModelsToArray(validationResult);
|
|
703
642
|
}
|
|
704
643
|
function filterAndOrderConfigFields(validationResult) {
|
|
705
|
-
// TODO:
|
|
644
|
+
// TODO: check if we can move filtering and sorting to Joi
|
|
706
645
|
return {
|
|
707
646
|
...validationResult,
|
|
708
647
|
value: lodash_1.default.pick(validationResult.value, [
|
|
@@ -714,6 +653,9 @@ function filterAndOrderConfigFields(validationResult) {
|
|
|
714
653
|
'buildCommand',
|
|
715
654
|
'publishDir',
|
|
716
655
|
'nodeVersion',
|
|
656
|
+
'postGitCloneCommand',
|
|
657
|
+
'preInstallCommand',
|
|
658
|
+
'postInstallCommand',
|
|
717
659
|
'devCommand',
|
|
718
660
|
'staticDir',
|
|
719
661
|
'uploadDir',
|
|
@@ -728,11 +670,29 @@ function filterAndOrderConfigFields(validationResult) {
|
|
|
728
670
|
'contentModels',
|
|
729
671
|
'presetSource',
|
|
730
672
|
'modelsSource',
|
|
673
|
+
'mapModels',
|
|
674
|
+
'presetReferenceBehavior',
|
|
675
|
+
'nonDuplicatableModels',
|
|
676
|
+
'duplicatableModels',
|
|
677
|
+
'contentSources',
|
|
678
|
+
'hcrHandled',
|
|
679
|
+
'internalStackbitRunnerOptions',
|
|
680
|
+
'dirPath',
|
|
681
|
+
'filePath',
|
|
731
682
|
'models',
|
|
732
|
-
'presets'
|
|
683
|
+
'presets',
|
|
684
|
+
'pageData',
|
|
685
|
+
'pageModels',
|
|
686
|
+
'encodedFieldTypes',
|
|
687
|
+
'noEncodeFields',
|
|
688
|
+
'omitFields' // obsolete, left for backward compatibility
|
|
733
689
|
])
|
|
734
690
|
};
|
|
735
691
|
}
|
|
692
|
+
/**
|
|
693
|
+
* Collects models groups and injects them into the `models` array of the
|
|
694
|
+
* `reference` and `model` field types
|
|
695
|
+
*/
|
|
736
696
|
function convertModelGroupsToModelList(validationResult) {
|
|
737
697
|
var _a, _b;
|
|
738
698
|
const models = (_b = (_a = validationResult.value) === null || _a === void 0 ? void 0 : _a.models) !== null && _b !== void 0 ? _b : {};
|
|
@@ -742,7 +702,7 @@ function convertModelGroupsToModelList(validationResult) {
|
|
|
742
702
|
}
|
|
743
703
|
const key = (model === null || model === void 0 ? void 0 : model.type) === 'object' ? 'objectModels' : 'documentModels';
|
|
744
704
|
lodash_1.default.forEach(model.groups, (groupName) => {
|
|
745
|
-
|
|
705
|
+
utils_1.append(groupMap, [groupName, key], modelName);
|
|
746
706
|
});
|
|
747
707
|
delete model.groups;
|
|
748
708
|
return groupMap;
|
|
@@ -754,16 +714,16 @@ function convertModelGroupsToModelList(validationResult) {
|
|
|
754
714
|
});
|
|
755
715
|
});
|
|
756
716
|
lodash_1.default.forEach(models, (model) => {
|
|
757
|
-
|
|
758
|
-
if (
|
|
717
|
+
utils_2.iterateModelFieldsRecursively(model, (field) => {
|
|
718
|
+
if (utils_2.isListField(field)) {
|
|
759
719
|
field = field.items;
|
|
760
720
|
}
|
|
761
721
|
if (field.groups) {
|
|
762
722
|
let key = null;
|
|
763
|
-
if (
|
|
723
|
+
if (utils_2.isModelField(field)) {
|
|
764
724
|
key = 'objectModels';
|
|
765
725
|
}
|
|
766
|
-
else if (
|
|
726
|
+
else if (utils_2.isReferenceField(field)) {
|
|
767
727
|
key = 'documentModels';
|
|
768
728
|
}
|
|
769
729
|
if (key) {
|
|
@@ -778,12 +738,12 @@ function convertModelGroupsToModelList(validationResult) {
|
|
|
778
738
|
});
|
|
779
739
|
}
|
|
780
740
|
function convertModelsToArray(validationResult) {
|
|
781
|
-
var _a;
|
|
782
741
|
const config = validationResult.value;
|
|
742
|
+
const { stackbitVersion = config_loader_utils_1.LATEST_STACKBIT_VERSION, models, ...rest } = config;
|
|
783
743
|
// in stackbit.yaml 'models' are defined as object where keys are the model names,
|
|
784
744
|
// convert 'models' to array of objects and set their 'name' property to the
|
|
785
745
|
// model name
|
|
786
|
-
const modelMap =
|
|
746
|
+
const modelMap = models !== null && models !== void 0 ? models : {};
|
|
787
747
|
const modelArray = lodash_1.default.map(modelMap, (yamlModel, modelName) => {
|
|
788
748
|
return {
|
|
789
749
|
name: modelName,
|
|
@@ -806,7 +766,8 @@ function convertModelsToArray(validationResult) {
|
|
|
806
766
|
return {
|
|
807
767
|
valid: validationResult.valid,
|
|
808
768
|
config: {
|
|
809
|
-
|
|
769
|
+
stackbitVersion,
|
|
770
|
+
...rest,
|
|
810
771
|
models: modelArray
|
|
811
772
|
},
|
|
812
773
|
errors: convertedErrors
|
|
@@ -825,6 +786,21 @@ function addImageModel(models) {
|
|
|
825
786
|
});
|
|
826
787
|
}
|
|
827
788
|
function isGitCMS(config) {
|
|
828
|
-
return !config.cmsName || config.cmsName === 'git';
|
|
789
|
+
return !config.contentSources && (!config.cmsName || config.cmsName === 'git');
|
|
790
|
+
}
|
|
791
|
+
function getInternalStackbitRunnerOptions(config) {
|
|
792
|
+
const experimentalSsgData = lodash_1.default.get(config, 'experimental.ssg');
|
|
793
|
+
if (!experimentalSsgData) {
|
|
794
|
+
return lodash_1.default.get(config, '__unsafe_internal_stackbitRunnerOptions');
|
|
795
|
+
}
|
|
796
|
+
const doneStart = lodash_1.default.get(experimentalSsgData, 'logPatterns.up');
|
|
797
|
+
return {
|
|
798
|
+
displayName: experimentalSsgData.name || 'ssg',
|
|
799
|
+
triggerInstallFiles: lodash_1.default.get(experimentalSsgData, 'watch.reinstallPackages', ['package.json', 'package-lock.json']),
|
|
800
|
+
directPaths: experimentalSsgData.passthrough || [],
|
|
801
|
+
patterns: {
|
|
802
|
+
doneStart: lodash_1.default.isEmpty(doneStart) || lodash_1.default.isArray(doneStart) ? doneStart : [doneStart]
|
|
803
|
+
}
|
|
804
|
+
};
|
|
829
805
|
}
|
|
830
806
|
//# sourceMappingURL=config-loader.js.map
|