storyblok 4.6.4 → 4.6.6
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 +88 -64
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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
|
}
|
|
@@ -3074,7 +3079,8 @@ function applyMigrationToAllBlocks(content, migrationFunction, targetComponent)
|
|
|
3074
3079
|
migratedContent = migrationFunction({ ...content });
|
|
3075
3080
|
processed = true;
|
|
3076
3081
|
}
|
|
3077
|
-
|
|
3082
|
+
const uniqueKeys = /* @__PURE__ */ new Set([...Object.keys(content), ...Object.keys(migratedContent || {})]);
|
|
3083
|
+
for (const key of uniqueKeys) {
|
|
3078
3084
|
if (migratedContent) {
|
|
3079
3085
|
if (!(key in migratedContent)) {
|
|
3080
3086
|
delete content[key];
|
|
@@ -3102,7 +3108,7 @@ async function saveRollbackData({
|
|
|
3102
3108
|
path,
|
|
3103
3109
|
story,
|
|
3104
3110
|
migrationTimestamp,
|
|
3105
|
-
|
|
3111
|
+
migrationNames
|
|
3106
3112
|
}) {
|
|
3107
3113
|
const rollbackData = {
|
|
3108
3114
|
storyId: story.id,
|
|
@@ -3110,7 +3116,9 @@ async function saveRollbackData({
|
|
|
3110
3116
|
content: story.content
|
|
3111
3117
|
};
|
|
3112
3118
|
const rollbacksPath = resolvePath(path, `migrations/${space}/rollbacks`);
|
|
3113
|
-
const
|
|
3119
|
+
const componentNames = migrationNames.map((n) => getComponentNameFromFilename(n));
|
|
3120
|
+
const rollbackName = [...new Set(componentNames)].join("~");
|
|
3121
|
+
const rollbackFileName = `${rollbackName}.${migrationTimestamp}.jsonl`;
|
|
3114
3122
|
const rollbackFilePath = join(rollbacksPath, rollbackFileName);
|
|
3115
3123
|
await appendToFile(
|
|
3116
3124
|
rollbackFilePath,
|
|
@@ -3168,67 +3176,71 @@ class MigrationStream extends Transform {
|
|
|
3168
3176
|
callback(error);
|
|
3169
3177
|
}
|
|
3170
3178
|
}
|
|
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 [];
|
|
3179
|
+
async getOrLoadMigrationFunction(migrationFile) {
|
|
3180
|
+
if (this.migrationFunctions.has(migrationFile.name)) {
|
|
3181
|
+
return this.migrationFunctions.get(migrationFile.name);
|
|
3181
3182
|
}
|
|
3183
|
+
const migrationFunction = await getMigrationFunction(
|
|
3184
|
+
migrationFile.name,
|
|
3185
|
+
this.options.space,
|
|
3186
|
+
this.options.path
|
|
3187
|
+
);
|
|
3188
|
+
this.migrationFunctions.set(migrationFile.name, migrationFunction);
|
|
3189
|
+
return migrationFunction;
|
|
3190
|
+
}
|
|
3191
|
+
async processStory(story) {
|
|
3182
3192
|
const relevantMigrations = this.options.componentName ? this.options.migrationFiles.filter((file) => {
|
|
3183
3193
|
const targetComponent = getComponentNameFromFilename(file.name);
|
|
3184
3194
|
return targetComponent.split(".")[0] === this.options.componentName;
|
|
3185
3195
|
}) : this.options.migrationFiles;
|
|
3196
|
+
if (!story.content) {
|
|
3197
|
+
this.results.failed.push({
|
|
3198
|
+
storyId: story.id,
|
|
3199
|
+
migrationNames: relevantMigrations.map((m) => m.name),
|
|
3200
|
+
error: new Error("Story content is missing")
|
|
3201
|
+
});
|
|
3202
|
+
return [];
|
|
3203
|
+
}
|
|
3186
3204
|
const successfulResults = [];
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
successfulResults.push(result);
|
|
3191
|
-
}
|
|
3205
|
+
const result = await this.applyMigrationsToStory(story, relevantMigrations);
|
|
3206
|
+
if (result) {
|
|
3207
|
+
successfulResults.push(result);
|
|
3192
3208
|
}
|
|
3193
3209
|
return successfulResults;
|
|
3194
3210
|
}
|
|
3195
|
-
async
|
|
3211
|
+
async applyMigrationsToStory(story, migrationFiles) {
|
|
3212
|
+
const migrationNames = migrationFiles.map((f) => f.name);
|
|
3196
3213
|
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
3214
|
const storyContent = structuredClone(story.content);
|
|
3222
3215
|
const originalContentHash = hash(storyContent);
|
|
3223
|
-
|
|
3224
|
-
const
|
|
3216
|
+
let processed = false;
|
|
3217
|
+
for (const migrationFile of migrationFiles) {
|
|
3218
|
+
const migrationFunction = await this.getOrLoadMigrationFunction(migrationFile);
|
|
3219
|
+
if (!migrationFunction) {
|
|
3220
|
+
this.results.failed.push({
|
|
3221
|
+
storyId: story.id,
|
|
3222
|
+
migrationNames,
|
|
3223
|
+
error: new Error(`Failed to load migration function from file "${migrationFile.name}"`)
|
|
3224
|
+
});
|
|
3225
|
+
return null;
|
|
3226
|
+
}
|
|
3227
|
+
const targetComponent = this.options.componentName || getComponentNameFromFilename(migrationFile.name);
|
|
3228
|
+
processed = applyMigrationToAllBlocks(storyContent, migrationFunction, targetComponent);
|
|
3229
|
+
}
|
|
3225
3230
|
const newContentHash = hash(storyContent);
|
|
3226
3231
|
const contentChanged = originalContentHash !== newContentHash;
|
|
3227
3232
|
if (processed && contentChanged) {
|
|
3233
|
+
await saveRollbackData({
|
|
3234
|
+
space: this.options.space,
|
|
3235
|
+
path: this.options.path,
|
|
3236
|
+
story: { id: story.id, name: story.name || "", content: story.content },
|
|
3237
|
+
migrationTimestamp: this.timestamp,
|
|
3238
|
+
migrationNames
|
|
3239
|
+
});
|
|
3228
3240
|
this.results.successful.push({
|
|
3229
3241
|
storyId: story.id,
|
|
3230
3242
|
name: story.name,
|
|
3231
|
-
|
|
3243
|
+
migrationNames,
|
|
3232
3244
|
content: storyContent
|
|
3233
3245
|
});
|
|
3234
3246
|
return {
|
|
@@ -3240,24 +3252,28 @@ class MigrationStream extends Transform {
|
|
|
3240
3252
|
this.results.skipped.push({
|
|
3241
3253
|
storyId: story.id,
|
|
3242
3254
|
name: story.name,
|
|
3243
|
-
|
|
3255
|
+
migrationNames,
|
|
3244
3256
|
reason: "No changes detected after migration"
|
|
3245
3257
|
});
|
|
3246
3258
|
return null;
|
|
3247
3259
|
} else {
|
|
3248
|
-
const
|
|
3260
|
+
const reason = migrationFiles.map((migrationFile) => {
|
|
3261
|
+
const targetComponent = this.options.componentName || getComponentNameFromFilename(migrationFile.name);
|
|
3262
|
+
const baseComponent = targetComponent.split(".")[0];
|
|
3263
|
+
return baseComponent === this.options.componentName ? `No matching components found for ${migrationFile.name}` : `Different component target ${migrationFile.name}`;
|
|
3264
|
+
}).join("\n");
|
|
3249
3265
|
this.results.skipped.push({
|
|
3250
3266
|
storyId: story.id,
|
|
3251
3267
|
name: story.name,
|
|
3252
|
-
|
|
3253
|
-
reason
|
|
3268
|
+
migrationNames,
|
|
3269
|
+
reason
|
|
3254
3270
|
});
|
|
3255
3271
|
return null;
|
|
3256
3272
|
}
|
|
3257
3273
|
} catch (error) {
|
|
3258
3274
|
this.results.failed.push({
|
|
3259
3275
|
storyId: story.id,
|
|
3260
|
-
|
|
3276
|
+
migrationNames,
|
|
3261
3277
|
error
|
|
3262
3278
|
});
|
|
3263
3279
|
return null;
|
|
@@ -3355,8 +3371,9 @@ class UpdateStream extends Writable {
|
|
|
3355
3371
|
} else if (this.options.publish === "all") {
|
|
3356
3372
|
payload.publish = 1;
|
|
3357
3373
|
}
|
|
3358
|
-
const updatedStory = await updateStory(this.options.space, storyId, payload);
|
|
3359
|
-
|
|
3374
|
+
const updatedStory = !this.options.dryRun && await updateStory(this.options.space, storyId, payload);
|
|
3375
|
+
const isStoryUpdated = Boolean(updatedStory);
|
|
3376
|
+
if (isStoryUpdated || this.options.dryRun) {
|
|
3360
3377
|
this.results.successful.push({ storyId, name: storyName });
|
|
3361
3378
|
this.results.totalProcessed++;
|
|
3362
3379
|
this.options.onProgress?.(this.results.totalProcessed);
|
|
@@ -3415,6 +3432,10 @@ class UpdateStream extends Writable {
|
|
|
3415
3432
|
const program$8 = getProgram();
|
|
3416
3433
|
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
3434
|
konsola.title(`${commands.MIGRATIONS}`, colorPalette.MIGRATIONS, componentName ? `Running migrations for component ${componentName}...` : "Running migrations...");
|
|
3435
|
+
if (options.dryRun) {
|
|
3436
|
+
konsola.warn(`DRY RUN MODE ENABLED: No changes will be made.
|
|
3437
|
+
`);
|
|
3438
|
+
}
|
|
3418
3439
|
const verbose = program$8.opts().verbose;
|
|
3419
3440
|
const { filter, dryRun = false, query, startsWith, publish } = options;
|
|
3420
3441
|
const { space, path } = migrationsCommand.opts();
|
|
@@ -4001,6 +4022,7 @@ const storyblokSchemas = /* @__PURE__ */ new Map([
|
|
|
4001
4022
|
]);
|
|
4002
4023
|
|
|
4003
4024
|
const STORY_TYPE = "ISbStoryData";
|
|
4025
|
+
const DEFAULT_COMPONENT_FILENAME = "storyblok-components";
|
|
4004
4026
|
const DEFAULT_TYPEDEFS_HEADER = [
|
|
4005
4027
|
"// This file was generated by the storyblok CLI.",
|
|
4006
4028
|
"// DO NOT MODIFY THIS FILE BY HAND."
|
|
@@ -4263,8 +4285,8 @@ const generateTypes = async (spaceData, options = {
|
|
|
4263
4285
|
handleError(error);
|
|
4264
4286
|
}
|
|
4265
4287
|
};
|
|
4266
|
-
const
|
|
4267
|
-
const { filename =
|
|
4288
|
+
const saveTypesToComponentsFile = async (space, typedefString, options) => {
|
|
4289
|
+
const { filename = DEFAULT_COMPONENT_FILENAME, path } = options;
|
|
4268
4290
|
const resolvedPath = path ? resolve(process.cwd(), path, "types", space) : resolvePath(path, `types/${space}`);
|
|
4269
4291
|
try {
|
|
4270
4292
|
await saveToFile(join(resolvedPath, `${filename}.d.ts`), typedefString);
|
|
@@ -4273,7 +4295,7 @@ const saveTypesToFile = async (space, typedefString, options) => {
|
|
|
4273
4295
|
}
|
|
4274
4296
|
};
|
|
4275
4297
|
const generateStoryblokTypes = async (options = {}) => {
|
|
4276
|
-
const {
|
|
4298
|
+
const { path } = options;
|
|
4277
4299
|
try {
|
|
4278
4300
|
const storyblokTypesPath = resolve(__dirname, "./index.d.ts");
|
|
4279
4301
|
const storyblokTypesContent = readFileSync(storyblokTypesPath, "utf-8");
|
|
@@ -4284,7 +4306,7 @@ const generateStoryblokTypes = async (options = {}) => {
|
|
|
4284
4306
|
storyblokTypesContent
|
|
4285
4307
|
].join("\n");
|
|
4286
4308
|
const resolvedPath = path ? resolve(process.cwd(), path, "types") : resolvePath(path, "types");
|
|
4287
|
-
await saveToFile(join(resolvedPath,
|
|
4309
|
+
await saveToFile(join(resolvedPath, `storyblok.d.ts`), typeDefs);
|
|
4288
4310
|
return true;
|
|
4289
4311
|
} catch (error) {
|
|
4290
4312
|
handleFileSystemError("read", error);
|
|
@@ -4293,7 +4315,10 @@ const generateStoryblokTypes = async (options = {}) => {
|
|
|
4293
4315
|
};
|
|
4294
4316
|
|
|
4295
4317
|
const program$5 = getProgram();
|
|
4296
|
-
typesCommand.command("generate").description("Generate types d.ts for your component schemas").option("--sf, --separate-files", "
|
|
4318
|
+
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(
|
|
4319
|
+
"--filename <name>",
|
|
4320
|
+
"Base file name for all component types when generating a single declarations file (e.g. components.d.ts). Ignored when using --separate-files."
|
|
4321
|
+
).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
4322
|
konsola.title(`${commands.TYPES}`, colorPalette.TYPES, "Generating types...");
|
|
4298
4323
|
const verbose = program$5.opts().verbose;
|
|
4299
4324
|
const { space, path } = typesCommand.opts();
|
|
@@ -4308,7 +4333,6 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
|
|
|
4308
4333
|
path
|
|
4309
4334
|
});
|
|
4310
4335
|
await generateStoryblokTypes({
|
|
4311
|
-
...options,
|
|
4312
4336
|
path
|
|
4313
4337
|
});
|
|
4314
4338
|
const spaceDataWithDatasources = {
|
|
@@ -4320,8 +4344,8 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
|
|
|
4320
4344
|
path
|
|
4321
4345
|
});
|
|
4322
4346
|
if (typedefString) {
|
|
4323
|
-
await
|
|
4324
|
-
|
|
4347
|
+
await saveTypesToComponentsFile(space, typedefString, {
|
|
4348
|
+
filename: options.filename,
|
|
4325
4349
|
path
|
|
4326
4350
|
});
|
|
4327
4351
|
}
|
|
@@ -5157,7 +5181,7 @@ program$1.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
|
|
|
5157
5181
|
konsola.br();
|
|
5158
5182
|
});
|
|
5159
5183
|
|
|
5160
|
-
const version = "4.6.
|
|
5184
|
+
const version = "4.6.6";
|
|
5161
5185
|
const pkg = {
|
|
5162
5186
|
version: version};
|
|
5163
5187
|
|