storyblok 4.6.2 → 4.6.4

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 CHANGED
@@ -9,12 +9,11 @@ import { Spinner } from '@topcli/spinner';
9
9
  import { select, password, input, confirm } from '@inquirer/prompts';
10
10
  import { ManagementApiClient } from '@storyblok/management-api-client';
11
11
  import { RateLimit, Sema } from 'async-sema';
12
- import fs, { mkdir, writeFile, readFile as readFile$1, access, readdir } from 'node:fs/promises';
12
+ import fs, { mkdir, writeFile, readFile as readFile$1, appendFile, access, readdir } from 'node:fs/promises';
13
13
  import path, { join, parse, resolve } from 'node:path';
14
14
  import filenamify from 'filenamify';
15
15
  import { exec, spawn } from 'node:child_process';
16
16
  import { promisify } from 'node:util';
17
- import { getRegion } from '@storyblok/region-helper';
18
17
  import { minimatch } from 'minimatch';
19
18
  import { Readable, pipeline, Transform, Writable } from 'node:stream';
20
19
  import { hash } from 'ohash';
@@ -669,6 +668,22 @@ const saveToFile = async (filePath, data, options) => {
669
668
  handleFileSystemError("write", writeError);
670
669
  }
671
670
  };
671
+ const appendToFile = async (filePath, data, options) => {
672
+ const resolvedPath = parse(filePath).dir;
673
+ try {
674
+ await mkdir(resolvedPath, { recursive: true });
675
+ } catch (mkdirError) {
676
+ handleFileSystemError("mkdir", mkdirError);
677
+ return;
678
+ }
679
+ try {
680
+ const dataWithNewline = data.endsWith("\n") ? data : `${data}
681
+ `;
682
+ await appendFile(filePath, dataWithNewline, options);
683
+ } catch (writeError) {
684
+ handleFileSystemError("write", writeError);
685
+ }
686
+ };
672
687
  const readFile = async (filePath) => {
673
688
  try {
674
689
  return await readFile$1(filePath, "utf8");
@@ -1083,30 +1098,8 @@ program$f.command(commands.USER).description("Get the current user").action(asyn
1083
1098
  konsola.br();
1084
1099
  });
1085
1100
 
1086
- function getRegionFromSpaceId(spaceId) {
1087
- try {
1088
- const region = getRegion(spaceId);
1089
- return region;
1090
- } catch (error) {
1091
- console.warn(`Failed to determine region from space ID: ${error}`);
1092
- return void 0;
1093
- }
1094
- }
1095
- const resolveRegion = async (thisCommand) => {
1096
- const options = thisCommand.opts();
1097
- const spaceId = options.space;
1098
- if (spaceId) {
1099
- const { state, initializeSession } = session();
1100
- await initializeSession();
1101
- const detectedRegion = getRegionFromSpaceId(spaceId);
1102
- if (detectedRegion) {
1103
- state.region = detectedRegion;
1104
- }
1105
- }
1106
- };
1107
-
1108
1101
  const program$e = getProgram();
1109
- const componentsCommand = program$e.command(commands.COMPONENTS).alias("comp").description(`Manage your space's block schema`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/components").hook("preAction", resolveRegion);
1102
+ const componentsCommand = program$e.command(commands.COMPONENTS).alias("comp").description(`Manage your space's block schema`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/components");
1110
1103
 
1111
1104
  const fetchComponents = async (spaceId) => {
1112
1105
  try {
@@ -2721,7 +2714,7 @@ const saveLanguagesToFile = async (space, internationalizationOptions, options)
2721
2714
  };
2722
2715
 
2723
2716
  const program$b = getProgram();
2724
- const languagesCommand = program$b.command(commands.LANGUAGES).alias("lang").description(`Manage your space's languages`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/languages").hook("preAction", resolveRegion);
2717
+ const languagesCommand = program$b.command(commands.LANGUAGES).alias("lang").description(`Manage your space's languages`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/languages");
2725
2718
  languagesCommand.command("pull").description(`Download your space's languages schema as json`).option("-f, --filename <filename>", "filename to save the file as <filename>.<suffix>.json").option("--su, --suffix <suffix>", "suffix to add to the file name (e.g. languages.<suffix>.json). By default, the space ID is used.").action(async (options) => {
2726
2719
  konsola.title(`${commands.LANGUAGES}`, colorPalette.LANGUAGES);
2727
2720
  const verbose = program$b.opts().verbose;
@@ -2772,7 +2765,7 @@ languagesCommand.command("pull").description(`Download your space's languages sc
2772
2765
  });
2773
2766
 
2774
2767
  const program$a = getProgram();
2775
- const migrationsCommand = program$a.command(commands.MIGRATIONS).alias("mig").description(`Manage your space's migrations`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/migrations").hook("preAction", resolveRegion);
2768
+ const migrationsCommand = program$a.command(commands.MIGRATIONS).alias("mig").description(`Manage your space's migrations`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/migrations");
2776
2769
 
2777
2770
  const getMigrationTemplate = () => {
2778
2771
  return `export default function (block) {
@@ -2922,7 +2915,8 @@ async function* storiesIterator(spaceId, params, onTotal) {
2922
2915
  const result = await fetchStories(spaceId, {
2923
2916
  ...transformedParams,
2924
2917
  per_page: perPage,
2925
- page: 1
2918
+ page: 1,
2919
+ story_only: true
2926
2920
  });
2927
2921
  if (!result) {
2928
2922
  return;
@@ -2938,7 +2932,8 @@ async function* storiesIterator(spaceId, params, onTotal) {
2938
2932
  const result2 = await fetchStories(spaceId, {
2939
2933
  ...transformedParams,
2940
2934
  per_page: perPage,
2941
- page
2935
+ page,
2936
+ story_only: true
2942
2937
  });
2943
2938
  if (!result2) {
2944
2939
  return;
@@ -3069,69 +3064,58 @@ async function getMigrationFunction(fileName, space, basePath) {
3069
3064
  }
3070
3065
  }
3071
3066
  function applyMigrationToAllBlocks(content, migrationFunction, targetComponent) {
3067
+ let processed = false;
3072
3068
  if (!content || typeof content !== "object") {
3073
- return false;
3069
+ return processed;
3074
3070
  }
3075
- let modified = false;
3076
3071
  const baseTargetComponent = targetComponent.split(".")[0];
3072
+ let migratedContent = null;
3077
3073
  if (content.component === baseTargetComponent) {
3078
- const migratedContent = migrationFunction({ ...content });
3079
- Object.assign(content, migratedContent);
3080
- modified = true;
3074
+ migratedContent = migrationFunction({ ...content });
3075
+ processed = true;
3081
3076
  }
3082
- for (const key in content) {
3083
- if (Object.prototype.hasOwnProperty.call(content, key)) {
3084
- const value = content[key];
3085
- if (Array.isArray(value)) {
3086
- for (let i = 0; i < value.length; i++) {
3087
- if (value[i] && typeof value[i] === "object") {
3088
- const blockModified = applyMigrationToAllBlocks(value[i], migrationFunction, targetComponent);
3089
- modified = modified || blockModified;
3090
- }
3077
+ for (const key of Object.keys(content)) {
3078
+ if (migratedContent) {
3079
+ if (!(key in migratedContent)) {
3080
+ delete content[key];
3081
+ continue;
3082
+ }
3083
+ content[key] = migratedContent[key];
3084
+ }
3085
+ if (Array.isArray(content[key])) {
3086
+ for (const value of content[key]) {
3087
+ if (value && typeof value === "object") {
3088
+ const blockProcessed = applyMigrationToAllBlocks(value, migrationFunction, targetComponent);
3089
+ processed = processed || blockProcessed;
3091
3090
  }
3092
- } else if (value && typeof value === "object") {
3093
- const blockModified = applyMigrationToAllBlocks(value, migrationFunction, targetComponent);
3094
- modified = modified || blockModified;
3095
3091
  }
3092
+ } else if (content[key] && typeof content[key] === "object") {
3093
+ const blockProcessed = applyMigrationToAllBlocks(content[key], migrationFunction, targetComponent);
3094
+ processed = processed || blockProcessed;
3096
3095
  }
3097
3096
  }
3098
- return modified;
3097
+ return processed;
3099
3098
  }
3100
3099
 
3101
3100
  async function saveRollbackData({
3102
3101
  space,
3103
3102
  path,
3104
- stories,
3103
+ story,
3104
+ migrationTimestamp,
3105
3105
  migrationFile
3106
3106
  }) {
3107
3107
  const rollbackData = {
3108
- stories: stories.map((story) => ({
3109
- storyId: story.id,
3110
- name: story.name,
3111
- content: story.content
3112
- }))
3108
+ storyId: story.id,
3109
+ name: story.name,
3110
+ content: story.content
3113
3111
  };
3114
3112
  const rollbacksPath = resolvePath(path, `migrations/${space}/rollbacks`);
3115
- const timestamp = Date.now();
3116
- const rollbackFileName = `${migrationFile.replace(".js", "")}.${timestamp}.json`;
3113
+ const rollbackFileName = `${migrationFile.replace(".js", "")}.${migrationTimestamp}.jsonl`;
3117
3114
  const rollbackFilePath = join(rollbacksPath, rollbackFileName);
3118
- try {
3119
- await saveToFile(
3120
- rollbackFilePath,
3121
- JSON.stringify(rollbackData, null, 2)
3122
- );
3123
- } catch (error) {
3124
- if (error.code === "ENOENT") {
3125
- const fs = await import('node:fs/promises');
3126
- await fs.mkdir(rollbacksPath, { recursive: true });
3127
- await saveToFile(
3128
- rollbackFilePath,
3129
- JSON.stringify(rollbackData, null, 2)
3130
- );
3131
- } else {
3132
- throw error;
3133
- }
3134
- }
3115
+ await appendToFile(
3116
+ rollbackFilePath,
3117
+ JSON.stringify(rollbackData)
3118
+ );
3135
3119
  }
3136
3120
  async function readRollbackFile({
3137
3121
  space,
@@ -3141,8 +3125,10 @@ async function readRollbackFile({
3141
3125
  try {
3142
3126
  const resolvedPath = resolvePath(path, `migrations/${space}/rollbacks`);
3143
3127
  const rollbackFilePath = join(resolvedPath, migrationFile);
3144
- const filePath = rollbackFilePath.endsWith(".json") ? rollbackFilePath : `${rollbackFilePath}.json`;
3145
- return JSON.parse(await readFile$1(filePath, "utf-8"));
3128
+ const filePath = rollbackFilePath.endsWith(".jsonl") ? rollbackFilePath : `${rollbackFilePath}.jsonl`;
3129
+ return {
3130
+ stories: (await readFile$1(filePath, "utf-8")).trim().split("\n").filter(Boolean).map((x) => JSON.parse(x))
3131
+ };
3146
3132
  } catch (error) {
3147
3133
  throw new CommandError(`Failed to read rollback file: ${error.message}`);
3148
3134
  }
@@ -3161,22 +3147,22 @@ class MigrationStream extends Transform {
3161
3147
  totalProcessed: 0
3162
3148
  };
3163
3149
  }
3150
+ timestamp = Date.now();
3164
3151
  results;
3165
3152
  migrationFunctions = /* @__PURE__ */ new Map();
3166
3153
  totalProcessed = 0;
3167
- _transform(chunk, _encoding, callback) {
3154
+ async _transform(chunk, _encoding, callback) {
3168
3155
  try {
3169
- this.processStory(chunk).then((results) => {
3170
- this.results.totalProcessed++;
3171
- this.options.onProgress?.(this.results.totalProcessed);
3172
- if (results.length > 0) {
3173
- this.totalProcessed += results.length;
3174
- this.options.onTotal?.(this.totalProcessed);
3175
- for (const result of results) {
3176
- this.push(result);
3177
- }
3156
+ const results = await this.processStory(chunk);
3157
+ this.results.totalProcessed++;
3158
+ this.options.onProgress?.(this.results.totalProcessed);
3159
+ if (results.length > 0) {
3160
+ this.totalProcessed += results.length;
3161
+ this.options.onTotal?.(this.totalProcessed);
3162
+ for (const result of results) {
3163
+ this.push(result);
3178
3164
  }
3179
- });
3165
+ }
3180
3166
  callback();
3181
3167
  } catch (error) {
3182
3168
  callback(error);
@@ -3228,16 +3214,17 @@ class MigrationStream extends Transform {
3228
3214
  await saveRollbackData({
3229
3215
  space: this.options.space,
3230
3216
  path: this.options.path,
3231
- stories: [{ id: story.id, name: story.name || "", content: story.content }],
3217
+ story: { id: story.id, name: story.name || "", content: story.content },
3218
+ migrationTimestamp: this.timestamp,
3232
3219
  migrationFile: migrationFile.name
3233
3220
  });
3234
3221
  const storyContent = structuredClone(story.content);
3235
- const originalContentHash = hash(story.content);
3222
+ const originalContentHash = hash(storyContent);
3236
3223
  const targetComponent = this.options.componentName || getComponentNameFromFilename(migrationFile.name);
3237
- const modified = applyMigrationToAllBlocks(storyContent, migrationFunction, targetComponent);
3224
+ const processed = applyMigrationToAllBlocks(storyContent, migrationFunction, targetComponent);
3238
3225
  const newContentHash = hash(storyContent);
3239
3226
  const contentChanged = originalContentHash !== newContentHash;
3240
- if (modified && contentChanged) {
3227
+ if (processed && contentChanged) {
3241
3228
  this.results.successful.push({
3242
3229
  storyId: story.id,
3243
3230
  name: story.name,
@@ -3249,7 +3236,7 @@ class MigrationStream extends Transform {
3249
3236
  name: story.name,
3250
3237
  content: storyContent
3251
3238
  };
3252
- } else if (modified && !contentChanged) {
3239
+ } else if (processed && !contentChanged) {
3253
3240
  this.results.skipped.push({
3254
3241
  storyId: story.id,
3255
3242
  name: story.name,
@@ -3557,6 +3544,13 @@ migrationsCommand.command("rollback [migrationFile]").description("Rollback a mi
3557
3544
  handleError(new CommandError(`Please provide the space as argument --space YOUR_SPACE_ID.`), verbose);
3558
3545
  return;
3559
3546
  }
3547
+ const { password, region } = state;
3548
+ mapiClient({
3549
+ token: {
3550
+ accessToken: password
3551
+ },
3552
+ region
3553
+ });
3560
3554
  try {
3561
3555
  const rollbackData = await readRollbackFile({
3562
3556
  space,
@@ -3585,7 +3579,7 @@ migrationsCommand.command("rollback [migrationFile]").description("Rollback a mi
3585
3579
  });
3586
3580
 
3587
3581
  const program$6 = getProgram();
3588
- const typesCommand = program$6.command(commands.TYPES).alias("ts").description(`Generate types d.ts for your component schemas`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/types").hook("preAction", resolveRegion);
3582
+ const typesCommand = program$6.command(commands.TYPES).alias("ts").description(`Generate types d.ts for your component schemas`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/types");
3589
3583
 
3590
3584
  const getAssetJSONSchema = (title) => ({
3591
3585
  $id: "#/asset",
@@ -4342,7 +4336,7 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
4342
4336
  });
4343
4337
 
4344
4338
  const program$4 = getProgram();
4345
- const datasourcesCommand = program$4.command(commands.DATASOURCES).alias("ds").description(`Manage your space's datasources`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/datasources").hook("preAction", resolveRegion);
4339
+ const datasourcesCommand = program$4.command(commands.DATASOURCES).alias("ds").description(`Manage your space's datasources`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/datasources");
4346
4340
 
4347
4341
  const fetchDatasourceEntries = async (spaceId, datasourceId) => {
4348
4342
  try {
@@ -5163,7 +5157,7 @@ program$1.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
5163
5157
  konsola.br();
5164
5158
  });
5165
5159
 
5166
- const version = "4.6.2";
5160
+ const version = "4.6.4";
5167
5161
  const pkg = {
5168
5162
  version: version};
5169
5163