storyblok 4.6.4 → 4.6.7
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 +91 -66
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -856,7 +856,7 @@ const loginStrategy = {
|
|
|
856
856
|
short: "Email"
|
|
857
857
|
},
|
|
858
858
|
{
|
|
859
|
-
name: "With Token (SSO)",
|
|
859
|
+
name: "With Token (Personal Access Token \u2013 works also for SSO accounts)",
|
|
860
860
|
value: "login-with-token",
|
|
861
861
|
short: "Token"
|
|
862
862
|
}
|
|
@@ -915,8 +915,13 @@ program$i.command(commands.LOGIN).description("Login to the Storyblok CLI").opti
|
|
|
915
915
|
try {
|
|
916
916
|
const strategy = await select(loginStrategy);
|
|
917
917
|
if (strategy === "login-with-token") {
|
|
918
|
+
konsola.info([
|
|
919
|
+
"\u{1F511} You can use a Personal Access Token to log in.",
|
|
920
|
+
"This works for all accounts, including SSO accounts.",
|
|
921
|
+
`Generate one in your Storyblok account settings: ${chalk.underline.blue("https://app.storyblok.com/#/me/account?tab=token")}`
|
|
922
|
+
].join("\n"));
|
|
918
923
|
const userToken = await password({
|
|
919
|
-
message: "Please enter your
|
|
924
|
+
message: "Please enter your Personal Access Token:",
|
|
920
925
|
validate: (value) => {
|
|
921
926
|
return value.length > 0;
|
|
922
927
|
}
|
|
@@ -1572,6 +1577,7 @@ componentsCommand.command("pull [componentName]").option("-f, --filename <filena
|
|
|
1572
1577
|
}
|
|
1573
1578
|
});
|
|
1574
1579
|
|
|
1580
|
+
const fieldTypesWithDependencies = ["bloks", "richtext"];
|
|
1575
1581
|
function buildDependencyGraph(context) {
|
|
1576
1582
|
const { spaceState } = context;
|
|
1577
1583
|
const graph = { nodes: /* @__PURE__ */ new Map() };
|
|
@@ -1676,7 +1682,7 @@ function collectWhitelistDependencies(schema) {
|
|
|
1676
1682
|
const componentNames = /* @__PURE__ */ new Set();
|
|
1677
1683
|
const datasourceNames = /* @__PURE__ */ new Set();
|
|
1678
1684
|
function traverseField(field) {
|
|
1679
|
-
if (field.type
|
|
1685
|
+
if (fieldTypesWithDependencies.includes(field.type)) {
|
|
1680
1686
|
if (field.component_group_whitelist && Array.isArray(field.component_group_whitelist)) {
|
|
1681
1687
|
field.component_group_whitelist.forEach((uuid) => groupUuids.add(uuid));
|
|
1682
1688
|
}
|
|
@@ -2024,7 +2030,7 @@ class ComponentNode extends GraphNode {
|
|
|
2024
2030
|
return field.map(resolveField);
|
|
2025
2031
|
}
|
|
2026
2032
|
const resolvedField = { ...field };
|
|
2027
|
-
if (resolvedField.type
|
|
2033
|
+
if (fieldTypesWithDependencies.includes(resolvedField.type)) {
|
|
2028
2034
|
if (resolvedField.component_group_whitelist && Array.isArray(resolvedField.component_group_whitelist)) {
|
|
2029
2035
|
resolvedField.component_group_whitelist = resolvedField.component_group_whitelist.map((groupUuid) => {
|
|
2030
2036
|
const groupNodeId = `group:${groupUuid}`;
|
|
@@ -3074,7 +3080,8 @@ function applyMigrationToAllBlocks(content, migrationFunction, targetComponent)
|
|
|
3074
3080
|
migratedContent = migrationFunction({ ...content });
|
|
3075
3081
|
processed = true;
|
|
3076
3082
|
}
|
|
3077
|
-
|
|
3083
|
+
const uniqueKeys = /* @__PURE__ */ new Set([...Object.keys(content), ...Object.keys(migratedContent || {})]);
|
|
3084
|
+
for (const key of uniqueKeys) {
|
|
3078
3085
|
if (migratedContent) {
|
|
3079
3086
|
if (!(key in migratedContent)) {
|
|
3080
3087
|
delete content[key];
|
|
@@ -3102,7 +3109,7 @@ async function saveRollbackData({
|
|
|
3102
3109
|
path,
|
|
3103
3110
|
story,
|
|
3104
3111
|
migrationTimestamp,
|
|
3105
|
-
|
|
3112
|
+
migrationNames
|
|
3106
3113
|
}) {
|
|
3107
3114
|
const rollbackData = {
|
|
3108
3115
|
storyId: story.id,
|
|
@@ -3110,7 +3117,9 @@ async function saveRollbackData({
|
|
|
3110
3117
|
content: story.content
|
|
3111
3118
|
};
|
|
3112
3119
|
const rollbacksPath = resolvePath(path, `migrations/${space}/rollbacks`);
|
|
3113
|
-
const
|
|
3120
|
+
const componentNames = migrationNames.map((n) => getComponentNameFromFilename(n));
|
|
3121
|
+
const rollbackName = [...new Set(componentNames)].join("~");
|
|
3122
|
+
const rollbackFileName = `${rollbackName}.${migrationTimestamp}.jsonl`;
|
|
3114
3123
|
const rollbackFilePath = join(rollbacksPath, rollbackFileName);
|
|
3115
3124
|
await appendToFile(
|
|
3116
3125
|
rollbackFilePath,
|
|
@@ -3168,67 +3177,71 @@ class MigrationStream extends Transform {
|
|
|
3168
3177
|
callback(error);
|
|
3169
3178
|
}
|
|
3170
3179
|
}
|
|
3171
|
-
async
|
|
3172
|
-
if (
|
|
3173
|
-
|
|
3174
|
-
this.results.failed.push({
|
|
3175
|
-
storyId: story.id,
|
|
3176
|
-
migrationName: migrationFile.name,
|
|
3177
|
-
error: new Error("Story content is missing")
|
|
3178
|
-
});
|
|
3179
|
-
}
|
|
3180
|
-
return [];
|
|
3180
|
+
async getOrLoadMigrationFunction(migrationFile) {
|
|
3181
|
+
if (this.migrationFunctions.has(migrationFile.name)) {
|
|
3182
|
+
return this.migrationFunctions.get(migrationFile.name);
|
|
3181
3183
|
}
|
|
3184
|
+
const migrationFunction = await getMigrationFunction(
|
|
3185
|
+
migrationFile.name,
|
|
3186
|
+
this.options.space,
|
|
3187
|
+
this.options.path
|
|
3188
|
+
);
|
|
3189
|
+
this.migrationFunctions.set(migrationFile.name, migrationFunction);
|
|
3190
|
+
return migrationFunction;
|
|
3191
|
+
}
|
|
3192
|
+
async processStory(story) {
|
|
3182
3193
|
const relevantMigrations = this.options.componentName ? this.options.migrationFiles.filter((file) => {
|
|
3183
3194
|
const targetComponent = getComponentNameFromFilename(file.name);
|
|
3184
3195
|
return targetComponent.split(".")[0] === this.options.componentName;
|
|
3185
3196
|
}) : this.options.migrationFiles;
|
|
3197
|
+
if (!story.content) {
|
|
3198
|
+
this.results.failed.push({
|
|
3199
|
+
storyId: story.id,
|
|
3200
|
+
migrationNames: relevantMigrations.map((m) => m.name),
|
|
3201
|
+
error: new Error("Story content is missing")
|
|
3202
|
+
});
|
|
3203
|
+
return [];
|
|
3204
|
+
}
|
|
3186
3205
|
const successfulResults = [];
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
successfulResults.push(result);
|
|
3191
|
-
}
|
|
3206
|
+
const result = await this.applyMigrationsToStory(story, relevantMigrations);
|
|
3207
|
+
if (result) {
|
|
3208
|
+
successfulResults.push(result);
|
|
3192
3209
|
}
|
|
3193
3210
|
return successfulResults;
|
|
3194
3211
|
}
|
|
3195
|
-
async
|
|
3212
|
+
async applyMigrationsToStory(story, migrationFiles) {
|
|
3213
|
+
const migrationNames = migrationFiles.map((f) => f.name);
|
|
3196
3214
|
try {
|
|
3197
|
-
let migrationFunction = this.migrationFunctions.get(migrationFile.name);
|
|
3198
|
-
if (!migrationFunction) {
|
|
3199
|
-
migrationFunction = await getMigrationFunction(
|
|
3200
|
-
migrationFile.name,
|
|
3201
|
-
this.options.space,
|
|
3202
|
-
this.options.path
|
|
3203
|
-
);
|
|
3204
|
-
this.migrationFunctions.set(migrationFile.name, migrationFunction);
|
|
3205
|
-
}
|
|
3206
|
-
if (!migrationFunction) {
|
|
3207
|
-
this.results.failed.push({
|
|
3208
|
-
storyId: story.id,
|
|
3209
|
-
migrationName: migrationFile.name,
|
|
3210
|
-
error: new Error(`Failed to load migration function from file "${migrationFile.name}"`)
|
|
3211
|
-
});
|
|
3212
|
-
return null;
|
|
3213
|
-
}
|
|
3214
|
-
await saveRollbackData({
|
|
3215
|
-
space: this.options.space,
|
|
3216
|
-
path: this.options.path,
|
|
3217
|
-
story: { id: story.id, name: story.name || "", content: story.content },
|
|
3218
|
-
migrationTimestamp: this.timestamp,
|
|
3219
|
-
migrationFile: migrationFile.name
|
|
3220
|
-
});
|
|
3221
3215
|
const storyContent = structuredClone(story.content);
|
|
3222
3216
|
const originalContentHash = hash(storyContent);
|
|
3223
|
-
|
|
3224
|
-
const
|
|
3217
|
+
let processed = false;
|
|
3218
|
+
for (const migrationFile of migrationFiles) {
|
|
3219
|
+
const migrationFunction = await this.getOrLoadMigrationFunction(migrationFile);
|
|
3220
|
+
if (!migrationFunction) {
|
|
3221
|
+
this.results.failed.push({
|
|
3222
|
+
storyId: story.id,
|
|
3223
|
+
migrationNames,
|
|
3224
|
+
error: new Error(`Failed to load migration function from file "${migrationFile.name}"`)
|
|
3225
|
+
});
|
|
3226
|
+
return null;
|
|
3227
|
+
}
|
|
3228
|
+
const targetComponent = this.options.componentName || getComponentNameFromFilename(migrationFile.name);
|
|
3229
|
+
processed = applyMigrationToAllBlocks(storyContent, migrationFunction, targetComponent);
|
|
3230
|
+
}
|
|
3225
3231
|
const newContentHash = hash(storyContent);
|
|
3226
3232
|
const contentChanged = originalContentHash !== newContentHash;
|
|
3227
3233
|
if (processed && contentChanged) {
|
|
3234
|
+
await saveRollbackData({
|
|
3235
|
+
space: this.options.space,
|
|
3236
|
+
path: this.options.path,
|
|
3237
|
+
story: { id: story.id, name: story.name || "", content: story.content },
|
|
3238
|
+
migrationTimestamp: this.timestamp,
|
|
3239
|
+
migrationNames
|
|
3240
|
+
});
|
|
3228
3241
|
this.results.successful.push({
|
|
3229
3242
|
storyId: story.id,
|
|
3230
3243
|
name: story.name,
|
|
3231
|
-
|
|
3244
|
+
migrationNames,
|
|
3232
3245
|
content: storyContent
|
|
3233
3246
|
});
|
|
3234
3247
|
return {
|
|
@@ -3240,24 +3253,28 @@ class MigrationStream extends Transform {
|
|
|
3240
3253
|
this.results.skipped.push({
|
|
3241
3254
|
storyId: story.id,
|
|
3242
3255
|
name: story.name,
|
|
3243
|
-
|
|
3256
|
+
migrationNames,
|
|
3244
3257
|
reason: "No changes detected after migration"
|
|
3245
3258
|
});
|
|
3246
3259
|
return null;
|
|
3247
3260
|
} else {
|
|
3248
|
-
const
|
|
3261
|
+
const reason = migrationFiles.map((migrationFile) => {
|
|
3262
|
+
const targetComponent = this.options.componentName || getComponentNameFromFilename(migrationFile.name);
|
|
3263
|
+
const baseComponent = targetComponent.split(".")[0];
|
|
3264
|
+
return baseComponent === this.options.componentName ? `No matching components found for ${migrationFile.name}` : `Different component target ${migrationFile.name}`;
|
|
3265
|
+
}).join("\n");
|
|
3249
3266
|
this.results.skipped.push({
|
|
3250
3267
|
storyId: story.id,
|
|
3251
3268
|
name: story.name,
|
|
3252
|
-
|
|
3253
|
-
reason
|
|
3269
|
+
migrationNames,
|
|
3270
|
+
reason
|
|
3254
3271
|
});
|
|
3255
3272
|
return null;
|
|
3256
3273
|
}
|
|
3257
3274
|
} catch (error) {
|
|
3258
3275
|
this.results.failed.push({
|
|
3259
3276
|
storyId: story.id,
|
|
3260
|
-
|
|
3277
|
+
migrationNames,
|
|
3261
3278
|
error
|
|
3262
3279
|
});
|
|
3263
3280
|
return null;
|
|
@@ -3355,8 +3372,9 @@ class UpdateStream extends Writable {
|
|
|
3355
3372
|
} else if (this.options.publish === "all") {
|
|
3356
3373
|
payload.publish = 1;
|
|
3357
3374
|
}
|
|
3358
|
-
const updatedStory = await updateStory(this.options.space, storyId, payload);
|
|
3359
|
-
|
|
3375
|
+
const updatedStory = !this.options.dryRun && await updateStory(this.options.space, storyId, payload);
|
|
3376
|
+
const isStoryUpdated = Boolean(updatedStory);
|
|
3377
|
+
if (isStoryUpdated || this.options.dryRun) {
|
|
3360
3378
|
this.results.successful.push({ storyId, name: storyName });
|
|
3361
3379
|
this.results.totalProcessed++;
|
|
3362
3380
|
this.options.onProgress?.(this.results.totalProcessed);
|
|
@@ -3415,6 +3433,10 @@ class UpdateStream extends Writable {
|
|
|
3415
3433
|
const program$8 = getProgram();
|
|
3416
3434
|
migrationsCommand.command("run [componentName]").description("Run migrations").option("--fi, --filter <filter>", "glob filter to apply to the components before pushing").option("-d, --dry-run", "Preview changes without applying them to Storyblok").option("-q, --query <query>", 'Filter stories by content attributes using Storyblok filter query syntax. Example: --query="[highlighted][in]=true"').option("--starts-with <path>", 'Filter stories by path. Example: --starts-with="/en/blog/"').option("--publish <publish>", "Options for publication mode: all | published | published-with-changes").action(async (componentName, options) => {
|
|
3417
3435
|
konsola.title(`${commands.MIGRATIONS}`, colorPalette.MIGRATIONS, componentName ? `Running migrations for component ${componentName}...` : "Running migrations...");
|
|
3436
|
+
if (options.dryRun) {
|
|
3437
|
+
konsola.warn(`DRY RUN MODE ENABLED: No changes will be made.
|
|
3438
|
+
`);
|
|
3439
|
+
}
|
|
3418
3440
|
const verbose = program$8.opts().verbose;
|
|
3419
3441
|
const { filter, dryRun = false, query, startsWith, publish } = options;
|
|
3420
3442
|
const { space, path } = migrationsCommand.opts();
|
|
@@ -4001,6 +4023,7 @@ const storyblokSchemas = /* @__PURE__ */ new Map([
|
|
|
4001
4023
|
]);
|
|
4002
4024
|
|
|
4003
4025
|
const STORY_TYPE = "ISbStoryData";
|
|
4026
|
+
const DEFAULT_COMPONENT_FILENAME = "storyblok-components";
|
|
4004
4027
|
const DEFAULT_TYPEDEFS_HEADER = [
|
|
4005
4028
|
"// This file was generated by the storyblok CLI.",
|
|
4006
4029
|
"// DO NOT MODIFY THIS FILE BY HAND."
|
|
@@ -4263,8 +4286,8 @@ const generateTypes = async (spaceData, options = {
|
|
|
4263
4286
|
handleError(error);
|
|
4264
4287
|
}
|
|
4265
4288
|
};
|
|
4266
|
-
const
|
|
4267
|
-
const { filename =
|
|
4289
|
+
const saveTypesToComponentsFile = async (space, typedefString, options) => {
|
|
4290
|
+
const { filename = DEFAULT_COMPONENT_FILENAME, path } = options;
|
|
4268
4291
|
const resolvedPath = path ? resolve(process.cwd(), path, "types", space) : resolvePath(path, `types/${space}`);
|
|
4269
4292
|
try {
|
|
4270
4293
|
await saveToFile(join(resolvedPath, `${filename}.d.ts`), typedefString);
|
|
@@ -4273,7 +4296,7 @@ const saveTypesToFile = async (space, typedefString, options) => {
|
|
|
4273
4296
|
}
|
|
4274
4297
|
};
|
|
4275
4298
|
const generateStoryblokTypes = async (options = {}) => {
|
|
4276
|
-
const {
|
|
4299
|
+
const { path } = options;
|
|
4277
4300
|
try {
|
|
4278
4301
|
const storyblokTypesPath = resolve(__dirname, "./index.d.ts");
|
|
4279
4302
|
const storyblokTypesContent = readFileSync(storyblokTypesPath, "utf-8");
|
|
@@ -4284,7 +4307,7 @@ const generateStoryblokTypes = async (options = {}) => {
|
|
|
4284
4307
|
storyblokTypesContent
|
|
4285
4308
|
].join("\n");
|
|
4286
4309
|
const resolvedPath = path ? resolve(process.cwd(), path, "types") : resolvePath(path, "types");
|
|
4287
|
-
await saveToFile(join(resolvedPath,
|
|
4310
|
+
await saveToFile(join(resolvedPath, `storyblok.d.ts`), typeDefs);
|
|
4288
4311
|
return true;
|
|
4289
4312
|
} catch (error) {
|
|
4290
4313
|
handleFileSystemError("read", error);
|
|
@@ -4293,7 +4316,10 @@ const generateStoryblokTypes = async (options = {}) => {
|
|
|
4293
4316
|
};
|
|
4294
4317
|
|
|
4295
4318
|
const program$5 = getProgram();
|
|
4296
|
-
typesCommand.command("generate").description("Generate types d.ts for your component schemas").option("--sf, --separate-files", "
|
|
4319
|
+
typesCommand.command("generate").description("Generate types d.ts for your component schemas").option("--sf, --separate-files", "Generate one .d.ts file per component instead of a single combined file").option(
|
|
4320
|
+
"--filename <name>",
|
|
4321
|
+
"Base file name for all component types when generating a single declarations file (e.g. components.d.ts). Ignored when using --separate-files."
|
|
4322
|
+
).option("--strict", "strict mode, no loose typing").option("--type-prefix <prefix>", "prefix to be prepended to all generated component type names").option("--type-suffix <suffix>", "suffix to be appended to all generated component type names").option("--suffix <suffix>", "Components suffix").option("--custom-fields-parser <path>", "Path to the parser file for Custom Field Types").option("--compiler-options <options>", "path to the compiler options from json-schema-to-typescript").action(async (options) => {
|
|
4297
4323
|
konsola.title(`${commands.TYPES}`, colorPalette.TYPES, "Generating types...");
|
|
4298
4324
|
const verbose = program$5.opts().verbose;
|
|
4299
4325
|
const { space, path } = typesCommand.opts();
|
|
@@ -4308,7 +4334,6 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
|
|
|
4308
4334
|
path
|
|
4309
4335
|
});
|
|
4310
4336
|
await generateStoryblokTypes({
|
|
4311
|
-
...options,
|
|
4312
4337
|
path
|
|
4313
4338
|
});
|
|
4314
4339
|
const spaceDataWithDatasources = {
|
|
@@ -4320,8 +4345,8 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
|
|
|
4320
4345
|
path
|
|
4321
4346
|
});
|
|
4322
4347
|
if (typedefString) {
|
|
4323
|
-
await
|
|
4324
|
-
|
|
4348
|
+
await saveTypesToComponentsFile(space, typedefString, {
|
|
4349
|
+
filename: options.filename,
|
|
4325
4350
|
path
|
|
4326
4351
|
});
|
|
4327
4352
|
}
|
|
@@ -5157,7 +5182,7 @@ program$1.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
|
|
|
5157
5182
|
konsola.br();
|
|
5158
5183
|
});
|
|
5159
5184
|
|
|
5160
|
-
const version = "4.6.
|
|
5185
|
+
const version = "4.6.7";
|
|
5161
5186
|
const pkg = {
|
|
5162
5187
|
version: version};
|
|
5163
5188
|
|