storyblok 4.0.0-beta.1 → 4.0.0-beta.3
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/index.mjs +146 -90
- package/dist/index.mjs.map +1 -0
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import dotenv from 'dotenv';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { dirname
|
|
4
|
+
import { dirname } from 'pathe';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
|
-
import
|
|
8
|
-
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { readPackageUp } from 'read-package-up';
|
|
9
8
|
import { Spinner } from '@topcli/spinner';
|
|
10
9
|
import { select, password, input } from '@inquirer/prompts';
|
|
11
10
|
import { mkdir, writeFile, readFile as readFile$1, access, readdir } from 'node:fs/promises';
|
|
12
|
-
import { join, parse, resolve
|
|
11
|
+
import { join, parse, resolve } from 'node:path';
|
|
13
12
|
import { hash } from 'ohash';
|
|
14
13
|
import { compile } from 'json-schema-to-typescript';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
15
|
|
|
16
16
|
const commands = {
|
|
17
17
|
LOGIN: "login",
|
|
@@ -353,7 +353,10 @@ const toPascalCase = (str) => {
|
|
|
353
353
|
return str.replace(/(?:^|_)(\w)/g, (_, char) => char.toUpperCase());
|
|
354
354
|
};
|
|
355
355
|
const toCamelCase = (str) => {
|
|
356
|
-
return str.replace(/
|
|
356
|
+
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/_/g, "").replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/[^a-z0-9]([a-z])/gi, (_, letter) => letter.toUpperCase()).replace(/[^a-z0-9]/gi, "");
|
|
357
|
+
};
|
|
358
|
+
const capitalize = (str) => {
|
|
359
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
357
360
|
};
|
|
358
361
|
function maskToken(token) {
|
|
359
362
|
if (token.length <= 4) {
|
|
@@ -425,7 +428,7 @@ const konsola = {
|
|
|
425
428
|
const warnHeader = chalk.bgYellow.bold.black(` Warning `);
|
|
426
429
|
console.warn(formatHeader(warnHeader));
|
|
427
430
|
}
|
|
428
|
-
console.warn(message ? `${chalk.yellow("\u26A0\uFE0F")} ${message}` : "");
|
|
431
|
+
console.warn(message ? `${chalk.yellow("\u26A0\uFE0F ")} ${message}` : "");
|
|
429
432
|
},
|
|
430
433
|
error: (message, info, options) => {
|
|
431
434
|
if (options?.header) {
|
|
@@ -447,13 +450,25 @@ function isRegion(value) {
|
|
|
447
450
|
}
|
|
448
451
|
const isVitest = process.env.VITEST === "true";
|
|
449
452
|
|
|
450
|
-
|
|
451
|
-
const
|
|
453
|
+
let packageJson;
|
|
454
|
+
const result = await readPackageUp({
|
|
455
|
+
cwd: __dirname
|
|
456
|
+
});
|
|
457
|
+
if (!result) {
|
|
458
|
+
console.debug("Metadata not found");
|
|
459
|
+
packageJson = {
|
|
460
|
+
name: "storyblok",
|
|
461
|
+
description: "Storyblok CLI",
|
|
462
|
+
version: "0.0.0"
|
|
463
|
+
};
|
|
464
|
+
} else {
|
|
465
|
+
packageJson = result.packageJson;
|
|
466
|
+
}
|
|
452
467
|
let programInstance = null;
|
|
453
468
|
function getProgram() {
|
|
454
469
|
if (!programInstance) {
|
|
455
470
|
programInstance = new Command();
|
|
456
|
-
programInstance.name(packageJson.name).description(packageJson.description).version(packageJson.version);
|
|
471
|
+
programInstance.name(packageJson.name).description(packageJson.description || "").version(packageJson.version);
|
|
457
472
|
programInstance.configureOutput({
|
|
458
473
|
writeErr: (str) => handleError(new Error(str))
|
|
459
474
|
});
|
|
@@ -539,9 +554,9 @@ const readFile = async (filePath) => {
|
|
|
539
554
|
};
|
|
540
555
|
const resolvePath = (path, folder) => {
|
|
541
556
|
if (path) {
|
|
542
|
-
return resolve
|
|
557
|
+
return resolve(process.cwd(), path, folder);
|
|
543
558
|
}
|
|
544
|
-
return resolve
|
|
559
|
+
return resolve(resolve(process.cwd(), ".storyblok"), folder);
|
|
545
560
|
};
|
|
546
561
|
const getComponentNameFromFilename = (filename) => {
|
|
547
562
|
return filename.replace(/\.js$/, "");
|
|
@@ -551,14 +566,18 @@ const getCredentials = async (filePath = join(getStoryblokGlobalPath(), "credent
|
|
|
551
566
|
try {
|
|
552
567
|
await access(filePath);
|
|
553
568
|
const content = await readFile(filePath);
|
|
554
|
-
|
|
569
|
+
const parsedContent = JSON.parse(content);
|
|
570
|
+
if (Object.keys(parsedContent).length === 0) {
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
return parsedContent;
|
|
555
574
|
} catch (error) {
|
|
556
575
|
if (error.code === "ENOENT") {
|
|
557
576
|
await saveToFile(filePath, JSON.stringify({}, null, 2), { mode: 384 });
|
|
558
|
-
return
|
|
577
|
+
return null;
|
|
559
578
|
}
|
|
560
579
|
handleFileSystemError("read", error);
|
|
561
|
-
return
|
|
580
|
+
return null;
|
|
562
581
|
}
|
|
563
582
|
};
|
|
564
583
|
const addCredentials = async ({
|
|
@@ -592,7 +611,7 @@ function createSession() {
|
|
|
592
611
|
const state = {
|
|
593
612
|
isLoggedIn: false
|
|
594
613
|
};
|
|
595
|
-
async function initializeSession(
|
|
614
|
+
async function initializeSession() {
|
|
596
615
|
const envCredentials = getEnvCredentials();
|
|
597
616
|
if (envCredentials) {
|
|
598
617
|
state.isLoggedIn = true;
|
|
@@ -602,9 +621,9 @@ function createSession() {
|
|
|
602
621
|
state.envLogin = true;
|
|
603
622
|
return;
|
|
604
623
|
}
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
624
|
+
const credentials = await getCredentials();
|
|
625
|
+
if (credentials) {
|
|
626
|
+
const creds = Object.values(credentials)[0];
|
|
608
627
|
state.isLoggedIn = true;
|
|
609
628
|
state.login = creds.login;
|
|
610
629
|
state.password = creds.password;
|
|
@@ -688,31 +707,43 @@ const loginStrategy = {
|
|
|
688
707
|
};
|
|
689
708
|
program$d.command(commands.LOGIN).description("Login to the Storyblok CLI").option("-t, --token <token>", "Token to login directly without questions, like for CI environments").option(
|
|
690
709
|
"-r, --region <region>",
|
|
691
|
-
`The region you would like to work in. Please keep in mind that the region must match the region of your space. This region flag will be used for the other cli's commands. You can use the values: ${allRegionsText}
|
|
692
|
-
regions.EU
|
|
710
|
+
`The region you would like to work in. Please keep in mind that the region must match the region of your space. This region flag will be used for the other cli's commands. You can use the values: ${allRegionsText}.`
|
|
693
711
|
).action(async (options) => {
|
|
694
712
|
konsola.title(` ${commands.LOGIN} `, colorPalette.LOGIN);
|
|
695
713
|
const verbose = program$d.opts().verbose;
|
|
696
714
|
const { token, region } = options;
|
|
697
|
-
if (!isRegion(region)) {
|
|
698
|
-
handleError(new CommandError(`The provided region: ${region} is not valid. Please use one of the following values: ${Object.values(regions).join(" | ")}`));
|
|
699
|
-
}
|
|
700
715
|
const { state, updateSession, persistCredentials, initializeSession } = session();
|
|
701
716
|
await initializeSession();
|
|
702
717
|
if (state.isLoggedIn && !state.envLogin) {
|
|
703
718
|
konsola.ok(`You are already logged in. If you want to login with a different account, please logout first.`);
|
|
704
719
|
return;
|
|
705
720
|
}
|
|
721
|
+
if (region && !isRegion(region)) {
|
|
722
|
+
handleError(new CommandError(`The provided region: ${region} is not valid. Please use one of the following values: ${Object.values(regions).join(" | ")}`));
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
706
725
|
if (token) {
|
|
707
726
|
const spinner = new Spinner({
|
|
708
727
|
verbose: !isVitest
|
|
709
|
-
})
|
|
728
|
+
});
|
|
710
729
|
try {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
730
|
+
let userRegion = region;
|
|
731
|
+
if (!userRegion) {
|
|
732
|
+
userRegion = await select({
|
|
733
|
+
message: "Please select the region you would like to work in:",
|
|
734
|
+
choices: Object.values(regions).map((region2) => ({
|
|
735
|
+
name: regionNames[region2],
|
|
736
|
+
value: region2
|
|
737
|
+
})),
|
|
738
|
+
default: regions.EU
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
spinner.start(`Logging in with token`);
|
|
742
|
+
const { user } = await loginWithToken(token, userRegion);
|
|
743
|
+
updateSession(user.email, token, userRegion);
|
|
744
|
+
await persistCredentials(userRegion);
|
|
714
745
|
spinner.succeed();
|
|
715
|
-
konsola.ok(`Successfully logged in. Welcome ${chalk.hex(colorPalette.PRIMARY)(user.friendly_name)}.`, true);
|
|
746
|
+
konsola.ok(`Successfully logged in to region ${chalk.hex(colorPalette.PRIMARY)(`${regionNames[userRegion]} (${userRegion})`)}. Welcome ${chalk.hex(colorPalette.PRIMARY)(user.friendly_name)}.`, true);
|
|
716
747
|
} catch (error) {
|
|
717
748
|
spinner.failed();
|
|
718
749
|
konsola.br();
|
|
@@ -736,7 +767,7 @@ program$d.command(commands.LOGIN).description("Login to the Storyblok CLI").opti
|
|
|
736
767
|
spinner.succeed();
|
|
737
768
|
updateSession(user.email, userToken, region);
|
|
738
769
|
await persistCredentials(region);
|
|
739
|
-
konsola.ok(`Successfully logged in. Welcome ${chalk.hex(colorPalette.PRIMARY)(user.friendly_name)}.`, true);
|
|
770
|
+
konsola.ok(`Successfully logged in to region ${chalk.hex(colorPalette.PRIMARY)(`${regionNames[region]} (${region})`)}. Welcome ${chalk.hex(colorPalette.PRIMARY)(user.friendly_name)}.`, true);
|
|
740
771
|
} else {
|
|
741
772
|
const userEmail = await input({
|
|
742
773
|
message: "Please enter your email address:",
|
|
@@ -749,14 +780,17 @@ program$d.command(commands.LOGIN).description("Login to the Storyblok CLI").opti
|
|
|
749
780
|
const userPassword = await password({
|
|
750
781
|
message: "Please enter your password:"
|
|
751
782
|
});
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
783
|
+
let userRegion = region;
|
|
784
|
+
if (!userRegion) {
|
|
785
|
+
userRegion = await select({
|
|
786
|
+
message: "Please select the region you would like to work in:",
|
|
787
|
+
choices: Object.values(regions).map((region2) => ({
|
|
788
|
+
name: regionNames[region2],
|
|
789
|
+
value: region2
|
|
790
|
+
})),
|
|
791
|
+
default: regions.EU
|
|
792
|
+
});
|
|
793
|
+
}
|
|
760
794
|
spinner.start(`Logging in with email`);
|
|
761
795
|
spinner.succeed();
|
|
762
796
|
const response = await loginWithEmailAndPassword(userEmail, userPassword, userRegion);
|
|
@@ -773,7 +807,7 @@ program$d.command(commands.LOGIN).description("Login to the Storyblok CLI").opti
|
|
|
773
807
|
updateSession(userEmail, response.access_token, userRegion);
|
|
774
808
|
}
|
|
775
809
|
await persistCredentials(region);
|
|
776
|
-
konsola.ok(`Successfully logged in. Welcome ${chalk.hex(colorPalette.PRIMARY)(userEmail)}.`, true);
|
|
810
|
+
konsola.ok(`Successfully logged in to region ${chalk.hex(colorPalette.PRIMARY)(`${regionNames[userRegion]} (${userRegion})`)}. Welcome ${chalk.hex(colorPalette.PRIMARY)(userEmail)}.`, true);
|
|
777
811
|
}
|
|
778
812
|
} catch (error) {
|
|
779
813
|
spinner.failed();
|
|
@@ -880,7 +914,7 @@ const fetchComponent = async (space, componentName, token, region) => {
|
|
|
880
914
|
Authorization: token
|
|
881
915
|
}
|
|
882
916
|
});
|
|
883
|
-
return response.components?.
|
|
917
|
+
return response.components?.find((c) => c.name === componentName);
|
|
884
918
|
} catch (error) {
|
|
885
919
|
handleAPIError("pull_components", error, `Failed to fetch component ${componentName}`);
|
|
886
920
|
}
|
|
@@ -927,7 +961,7 @@ const fetchComponentInternalTags = async (space, token, region) => {
|
|
|
927
961
|
const saveComponentsToFiles = async (space, spaceData, options) => {
|
|
928
962
|
const { components = [], groups = [], presets = [], internalTags = [] } = spaceData;
|
|
929
963
|
const { filename = "components", suffix, path, separateFiles } = options;
|
|
930
|
-
const resolvedPath = path ? resolve
|
|
964
|
+
const resolvedPath = path ? resolve(process.cwd(), path, "components", space) : resolvePath(path, `components/${space}`);
|
|
931
965
|
try {
|
|
932
966
|
if (separateFiles) {
|
|
933
967
|
for (const component of components) {
|
|
@@ -1095,7 +1129,7 @@ const upsertComponentPreset = async (space, preset, token, region) => {
|
|
|
1095
1129
|
const responseData = error.response?.data;
|
|
1096
1130
|
if (responseData?.name?.[0] === "has already been taken") {
|
|
1097
1131
|
const existingPresets = await fetchComponentPresets(space, token, region);
|
|
1098
|
-
const existingPreset = existingPresets?.find((p) => p.name === preset.name);
|
|
1132
|
+
const existingPreset = existingPresets?.find((p) => p.name === preset.name && p.component_id === preset.component_id);
|
|
1099
1133
|
if (existingPreset) {
|
|
1100
1134
|
return await updateComponentPreset(space, existingPreset.id, { preset }, token, region);
|
|
1101
1135
|
}
|
|
@@ -1421,7 +1455,7 @@ function findRelatedResources(components, spaceData) {
|
|
|
1421
1455
|
let currentGroup = groupsMap.get(groupUuid);
|
|
1422
1456
|
while (currentGroup) {
|
|
1423
1457
|
relatedGroups.add(currentGroup);
|
|
1424
|
-
if (currentGroup.parent_uuid && currentGroup.parent_uuid.length > 0) {
|
|
1458
|
+
if (currentGroup.parent_uuid && currentGroup.parent_uuid.length > 0 && currentGroup.parent_uuid !== currentGroup.uuid) {
|
|
1425
1459
|
currentGroup = groupsMap.get(currentGroup.parent_uuid);
|
|
1426
1460
|
} else {
|
|
1427
1461
|
currentGroup = void 0;
|
|
@@ -1521,7 +1555,7 @@ async function handleComponentGroups(space, password, region, spaceData, skipUui
|
|
|
1521
1555
|
// Maps old IDs to new IDs
|
|
1522
1556
|
};
|
|
1523
1557
|
const groupsToProcess = skipUuids ? spaceData.filter((group) => !skipUuids.has(group.uuid)) : spaceData;
|
|
1524
|
-
const rootGroups = groupsToProcess.filter((group) => !group.parent_uuid && !group.parent_id);
|
|
1558
|
+
const rootGroups = groupsToProcess.filter((group) => (!group.parent_uuid || group.parent_uuid === group.uuid) && !group.parent_id);
|
|
1525
1559
|
for (const group of rootGroups) {
|
|
1526
1560
|
const spinner = new Spinner({
|
|
1527
1561
|
verbose: !isVitest
|
|
@@ -1648,7 +1682,7 @@ function updateSchemaWhitelists(schema, groupsUuidMap, tagsIdMap, componentNameM
|
|
|
1648
1682
|
function getGroupHierarchy(group, allGroups) {
|
|
1649
1683
|
const hierarchy = [group];
|
|
1650
1684
|
let currentGroup = group;
|
|
1651
|
-
while (currentGroup.parent_uuid && currentGroup.parent_uuid.length > 0) {
|
|
1685
|
+
while (currentGroup.parent_uuid && currentGroup.parent_uuid.length > 0 && currentGroup.parent_uuid !== currentGroup.uuid) {
|
|
1652
1686
|
const parentGroup = allGroups.find((g) => g.uuid === currentGroup.parent_uuid);
|
|
1653
1687
|
if (parentGroup) {
|
|
1654
1688
|
hierarchy.unshift(parentGroup);
|
|
@@ -2119,7 +2153,9 @@ languagesCommand.command("pull").description(`Download your space's languages sc
|
|
|
2119
2153
|
spinner.start(`Fetching ${chalk.hex(colorPalette.LANGUAGES)("languages")}`);
|
|
2120
2154
|
const internationalization = await fetchLanguages(space, state.password, state.region);
|
|
2121
2155
|
if (!internationalization || internationalization.languages?.length === 0) {
|
|
2122
|
-
|
|
2156
|
+
spinner.failed();
|
|
2157
|
+
konsola.warn(`No languages found in the space ${space}`, true);
|
|
2158
|
+
konsola.br();
|
|
2123
2159
|
return;
|
|
2124
2160
|
}
|
|
2125
2161
|
await saveLanguagesToFile(space, internationalization, {
|
|
@@ -2157,7 +2193,7 @@ const getMigrationTemplate = () => {
|
|
|
2157
2193
|
`;
|
|
2158
2194
|
};
|
|
2159
2195
|
const generateMigration = async (space, path, component, suffix) => {
|
|
2160
|
-
const resolvedPath = path ? resolve
|
|
2196
|
+
const resolvedPath = path ? resolve(process.cwd(), path, "migrations", space) : resolvePath(path, `migrations/${space}`);
|
|
2161
2197
|
const fileName = suffix ? `${component.name}.${suffix}.js` : `${component.name}.js`;
|
|
2162
2198
|
const migrationPath = join(resolvedPath, fileName);
|
|
2163
2199
|
try {
|
|
@@ -3194,18 +3230,67 @@ const storyblokSchemas = /* @__PURE__ */ new Map([
|
|
|
3194
3230
|
["richtext", getRichtextJSONSchema]
|
|
3195
3231
|
]);
|
|
3196
3232
|
|
|
3233
|
+
const STORY_TYPE = "ISbStoryData";
|
|
3197
3234
|
const DEFAULT_TYPEDEFS_HEADER = [
|
|
3198
3235
|
"// This file was generated by the storyblok CLI.",
|
|
3199
3236
|
"// DO NOT MODIFY THIS FILE BY HAND."
|
|
3200
3237
|
];
|
|
3201
|
-
const getPropertyTypeAnnotation = (property) => {
|
|
3238
|
+
const getPropertyTypeAnnotation = (property, prefix) => {
|
|
3202
3239
|
if (Array.from(storyblokSchemas.keys()).includes(property.type)) {
|
|
3203
3240
|
return { type: property.type };
|
|
3204
3241
|
}
|
|
3242
|
+
let type = "unknown";
|
|
3205
3243
|
const options = property.options && property.options.length > 0 ? property.options.map((item) => item.value) : [];
|
|
3206
3244
|
if (options.length > 0 && property.exclude_empty_option !== true) {
|
|
3207
3245
|
options.unshift("");
|
|
3208
3246
|
}
|
|
3247
|
+
if (property.source === "internal_stories") {
|
|
3248
|
+
if (property.filter_content_type) {
|
|
3249
|
+
if (typeof property.filter_content_type === "string") {
|
|
3250
|
+
return {
|
|
3251
|
+
tsType: `(${getStoryType(property.filter_content_type, prefix)} | string )${property.type === "options" ? "[]" : ""}`
|
|
3252
|
+
};
|
|
3253
|
+
}
|
|
3254
|
+
return {
|
|
3255
|
+
tsType: `(${property.filter_content_type.map((type2) => getStoryType(type2, prefix)).join(" | ")} | string )${property.type === "options" ? "[]" : ""}`
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
if (
|
|
3260
|
+
// If there is no `source` and there are options, the data source is the component itself
|
|
3261
|
+
// TODO: check if this is an old behaviour (shouldn't this be handled as an "internal" source?)
|
|
3262
|
+
options.length > 0 && !property.source || property.source === "internal_languages" || property.source === "external"
|
|
3263
|
+
) {
|
|
3264
|
+
type = "string";
|
|
3265
|
+
}
|
|
3266
|
+
if (property.source === "internal") {
|
|
3267
|
+
type = ["number", "string"];
|
|
3268
|
+
}
|
|
3269
|
+
if (property.type === "option") {
|
|
3270
|
+
if (options.length > 0) {
|
|
3271
|
+
return {
|
|
3272
|
+
type,
|
|
3273
|
+
enum: options
|
|
3274
|
+
};
|
|
3275
|
+
}
|
|
3276
|
+
return {
|
|
3277
|
+
type
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
if (property.type === "options") {
|
|
3281
|
+
if (options.length > 0) {
|
|
3282
|
+
return {
|
|
3283
|
+
type: "array",
|
|
3284
|
+
items: {
|
|
3285
|
+
enum: options
|
|
3286
|
+
}
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
return {
|
|
3290
|
+
type: "array",
|
|
3291
|
+
items: { type }
|
|
3292
|
+
};
|
|
3293
|
+
}
|
|
3209
3294
|
switch (property.type) {
|
|
3210
3295
|
case "bloks":
|
|
3211
3296
|
return { type: "array" };
|
|
@@ -3222,6 +3307,9 @@ const getPropertyTypeAnnotation = (property) => {
|
|
|
3222
3307
|
return { type: "any" };
|
|
3223
3308
|
}
|
|
3224
3309
|
};
|
|
3310
|
+
function getStoryType(property, prefix) {
|
|
3311
|
+
return `${STORY_TYPE}<${prefix ?? ""}${capitalize(toCamelCase(property))}>`;
|
|
3312
|
+
}
|
|
3225
3313
|
const getComponentType = (componentName, options) => {
|
|
3226
3314
|
const prefix = options.typePrefix ?? "";
|
|
3227
3315
|
const sanitizedName = componentName.replace(/[^a-z0-9]/gi, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
@@ -3237,7 +3325,7 @@ const getComponentPropertiesTypeAnnotations = async (component, options, spaceDa
|
|
|
3237
3325
|
}
|
|
3238
3326
|
const propertyType = value.type;
|
|
3239
3327
|
const propertyTypeAnnotation = {
|
|
3240
|
-
[key]: getPropertyTypeAnnotation(value)
|
|
3328
|
+
[key]: getPropertyTypeAnnotation(value, options.typePrefix)
|
|
3241
3329
|
};
|
|
3242
3330
|
if (propertyType === "custom" && customFieldsParser) {
|
|
3243
3331
|
const customField = typeof customFieldsParser === "function" ? customFieldsParser(key, value) : {};
|
|
@@ -3294,7 +3382,7 @@ const getComponentPropertiesTypeAnnotations = async (component, options, spaceDa
|
|
|
3294
3382
|
};
|
|
3295
3383
|
const loadCustomFieldsParser = async (path) => {
|
|
3296
3384
|
try {
|
|
3297
|
-
const customFieldsParser = await import(resolve
|
|
3385
|
+
const customFieldsParser = await import(resolve(path));
|
|
3298
3386
|
return customFieldsParser.default;
|
|
3299
3387
|
} catch (error) {
|
|
3300
3388
|
handleError(error);
|
|
@@ -3303,7 +3391,7 @@ const loadCustomFieldsParser = async (path) => {
|
|
|
3303
3391
|
};
|
|
3304
3392
|
async function loadCompilerOptions(path) {
|
|
3305
3393
|
if (path) {
|
|
3306
|
-
const compilerOptions = await import(resolve
|
|
3394
|
+
const compilerOptions = await import(resolve(path));
|
|
3307
3395
|
return compilerOptions.default;
|
|
3308
3396
|
}
|
|
3309
3397
|
return {};
|
|
@@ -3325,7 +3413,7 @@ const generateTypes = async (spaceData, options = {
|
|
|
3325
3413
|
const schemas = await Promise.all(spaceData.components.map(async (component) => {
|
|
3326
3414
|
const type = getComponentType(component.name, options);
|
|
3327
3415
|
const componentPropertiesTypeAnnotations = await getComponentPropertiesTypeAnnotations(component, options, spaceData, customFieldsParser);
|
|
3328
|
-
const requiredFields = Object.entries(component
|
|
3416
|
+
const requiredFields = Object.entries(component?.schema || {}).reduce(
|
|
3329
3417
|
(acc, [key, value]) => {
|
|
3330
3418
|
if (value.required) {
|
|
3331
3419
|
return [...acc, key];
|
|
@@ -3385,7 +3473,7 @@ const generateTypes = async (spaceData, options = {
|
|
|
3385
3473
|
};
|
|
3386
3474
|
const saveTypesToFile = async (space, typedefString, options) => {
|
|
3387
3475
|
const { filename = "storyblok-components", path } = options;
|
|
3388
|
-
const resolvedPath = path ? resolve
|
|
3476
|
+
const resolvedPath = path ? resolve(process.cwd(), path, "types", space) : resolvePath(path, `types/${space}`);
|
|
3389
3477
|
try {
|
|
3390
3478
|
await saveToFile(join(resolvedPath, `${filename}.d.ts`), typedefString);
|
|
3391
3479
|
} catch (error) {
|
|
@@ -3395,47 +3483,14 @@ const saveTypesToFile = async (space, typedefString, options) => {
|
|
|
3395
3483
|
const generateStoryblokTypes = async (options = {}) => {
|
|
3396
3484
|
const { filename = "storyblok", path } = options;
|
|
3397
3485
|
try {
|
|
3398
|
-
const storyblokTypesPath = resolve
|
|
3486
|
+
const storyblokTypesPath = resolve(__dirname, "./index.d.ts");
|
|
3399
3487
|
const storyblokTypesContent = readFileSync(storyblokTypesPath, "utf-8");
|
|
3400
|
-
const lines = storyblokTypesContent.split("\n");
|
|
3401
|
-
const typeDefinitions = [];
|
|
3402
|
-
let isCollecting = false;
|
|
3403
|
-
let bracketCount = 0;
|
|
3404
|
-
let currentType = "";
|
|
3405
|
-
for (let i = 0; i < lines.length; i++) {
|
|
3406
|
-
const line = lines[i];
|
|
3407
|
-
if (line.includes("export type StoryblokPropertyType") || line.includes("export interface Storyblok")) {
|
|
3408
|
-
if (isCollecting) {
|
|
3409
|
-
typeDefinitions.push("");
|
|
3410
|
-
}
|
|
3411
|
-
isCollecting = true;
|
|
3412
|
-
typeDefinitions.push(line);
|
|
3413
|
-
currentType = line.includes("type") ? "type" : "interface";
|
|
3414
|
-
bracketCount += (line.match(/\{/g) || []).length;
|
|
3415
|
-
bracketCount -= (line.match(/\}/g) || []).length;
|
|
3416
|
-
if (currentType === "type") {
|
|
3417
|
-
isCollecting = false;
|
|
3418
|
-
continue;
|
|
3419
|
-
}
|
|
3420
|
-
let j = i + 1;
|
|
3421
|
-
while (j < lines.length && bracketCount > 0) {
|
|
3422
|
-
const nextLine = lines[j];
|
|
3423
|
-
bracketCount += (nextLine.match(/\{/g) || []).length;
|
|
3424
|
-
bracketCount -= (nextLine.match(/\}/g) || []).length;
|
|
3425
|
-
typeDefinitions.push(nextLine);
|
|
3426
|
-
j++;
|
|
3427
|
-
}
|
|
3428
|
-
i = j - 1;
|
|
3429
|
-
isCollecting = false;
|
|
3430
|
-
}
|
|
3431
|
-
}
|
|
3432
3488
|
const typeDefs = [
|
|
3433
|
-
"// This file was generated by the
|
|
3489
|
+
"// This file was generated by the Storyblok CLI.",
|
|
3434
3490
|
"// DO NOT MODIFY THIS FILE BY HAND.",
|
|
3435
|
-
|
|
3436
|
-
...typeDefinitions
|
|
3491
|
+
storyblokTypesContent
|
|
3437
3492
|
].join("\n");
|
|
3438
|
-
const resolvedPath = path ? resolve
|
|
3493
|
+
const resolvedPath = path ? resolve(process.cwd(), path, "types") : resolvePath(path, "types");
|
|
3439
3494
|
await saveToFile(join(resolvedPath, `${filename}.d.ts`), typeDefs);
|
|
3440
3495
|
return true;
|
|
3441
3496
|
} catch (error) {
|
|
@@ -3487,7 +3542,7 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
|
|
|
3487
3542
|
}
|
|
3488
3543
|
});
|
|
3489
3544
|
|
|
3490
|
-
const version = "4.0.0-beta.
|
|
3545
|
+
const version = "4.0.0-beta.3";
|
|
3491
3546
|
const pkg = {
|
|
3492
3547
|
version: version};
|
|
3493
3548
|
|
|
@@ -3509,3 +3564,4 @@ try {
|
|
|
3509
3564
|
} catch (error) {
|
|
3510
3565
|
handleError(error);
|
|
3511
3566
|
}
|
|
3567
|
+
//# sourceMappingURL=index.mjs.map
|