sb-mig 6.0.0-beta.6 → 6.0.0-beta.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.
@@ -246,7 +246,6 @@ const applySingleMigrationToItems = ({ itemType, itemsToMigrate, preparedMigrati
246
246
  };
247
247
  };
248
248
  export const runMigrationPipelineInMemory = ({ itemType, itemsToMigrate, preparedMigrationConfigs, }) => {
249
- const originalItems = deepClone(itemsToMigrate);
250
249
  let workingItems = deepClone(itemsToMigrate);
251
250
  const stepReports = [];
252
251
  for (const preparedMigrationConfig of preparedMigrationConfigs) {
@@ -283,7 +282,7 @@ export const runMigrationPipelineInMemory = ({ itemType, itemsToMigrate, prepare
283
282
  stepReports.push(stepReport);
284
283
  }
285
284
  const changedItems = workingItems.filter((item, index) => {
286
- const originalItem = originalItems[index];
285
+ const originalItem = itemsToMigrate[index];
287
286
  if (!originalItem) {
288
287
  return true;
289
288
  }
@@ -1,9 +1,11 @@
1
1
  import chalk from "chalk";
2
+ import { mapWithConcurrency } from "../../utils/async-utils.js";
2
3
  import Logger from "../../utils/logger.js";
3
4
  import { notNullish } from "../../utils/object-utils.js";
4
5
  import { getAllItemsWithPagination } from "../utils/request.js";
5
6
  const resolveStoryLabel = (content, storyId) => content?.full_slug || content?.slug || content?.name || String(storyId);
6
7
  const DEFAULT_PUBLISH_LANGUAGE = "[default]";
8
+ const STORY_CONTENT_FETCH_CONCURRENCY = 10;
7
9
  const isDefaultLanguageToken = (language) => language.toLowerCase() === "default" ||
8
10
  language === DEFAULT_PUBLISH_LANGUAGE;
9
11
  const normalizePublishLanguageCodes = (languages) => {
@@ -144,7 +146,7 @@ export const getAllStories = async (args, config) => {
144
146
  });
145
147
  Logger.success(`Successfully pre-fetched ${allStoriesWithoutContent.length} stories.`);
146
148
  let heartBeat = 0;
147
- const allStories = await Promise.all(allStoriesWithoutContent.map(async (story) => {
149
+ const allStories = await mapWithConcurrency(allStoriesWithoutContent, STORY_CONTENT_FETCH_CONCURRENCY, async (story) => {
148
150
  const result = await getStoryById(story.id, config);
149
151
  heartBeat++;
150
152
  if (heartBeat % 10 === 0 ||
@@ -152,7 +154,7 @@ export const getAllStories = async (args, config) => {
152
154
  Logger.success(`Successfully fetched ${heartBeat} stories with full content.`);
153
155
  }
154
156
  return result;
155
- }));
157
+ });
156
158
  return allStories;
157
159
  };
158
160
  // GET
@@ -1,12 +1,12 @@
1
+ import { pathToFileURL } from "url";
1
2
  import Logger from "../utils/logger.js";
3
+ const toImportSpecifier = (filePath) => process.platform === "win32" ? pathToFileURL(filePath).href : filePath;
2
4
  export { defaultConfig } from "./defaultConfig.js";
3
5
  export { SCHEMA } from "./constants.js";
4
6
  export const getStoryblokConfigContent = (data) => {
5
- let prefix = "";
6
- if (process.platform === "win32") {
7
- prefix = "file://";
8
- }
9
- return import(`${prefix}${data.filePath}${data.ext}`)
7
+ const configSpecifier = toImportSpecifier(`${data.filePath}${data.ext}`);
8
+ const fallbackConfigSpecifier = toImportSpecifier(`${data.filePath}.mjs`);
9
+ return import(/* @vite-ignore */ configSpecifier)
10
10
  .then((res) => {
11
11
  Logger.success("Found storyblok.config.js!");
12
12
  return res.default;
@@ -14,10 +14,9 @@ export const getStoryblokConfigContent = (data) => {
14
14
  .catch(() => {
15
15
  Logger.warning("Cannot find requested file with .js extension.");
16
16
  Logger.log("Trying .mjs extension\n");
17
- return import(`${prefix}${data.filePath}.mjs`)
17
+ return import(/* @vite-ignore */ fallbackConfigSpecifier)
18
18
  .then((res) => {
19
19
  Logger.success("Found storyblok.config.mjs!");
20
- console.log("res", res);
21
20
  return res.default;
22
21
  })
23
22
  .catch(() => {
@@ -11,3 +11,4 @@
11
11
  * await delay(1000); // Wait 1 second
12
12
  */
13
13
  export declare const delay: (time: number) => Promise<void>;
14
+ export declare const mapWithConcurrency: <T, R>(items: T[], concurrency: number, mapper: (item: T, index: number) => Promise<R>) => Promise<R[]>;
@@ -11,3 +11,19 @@
11
11
  * await delay(1000); // Wait 1 second
12
12
  */
13
13
  export const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));
14
+ export const mapWithConcurrency = async (items, concurrency, mapper) => {
15
+ if (items.length === 0) {
16
+ return [];
17
+ }
18
+ const limit = Math.max(1, Math.floor(concurrency));
19
+ const results = new Array(items.length);
20
+ let nextIndex = 0;
21
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
22
+ while (nextIndex < items.length) {
23
+ const currentIndex = nextIndex++;
24
+ results[currentIndex] = await mapper(items[currentIndex], currentIndex);
25
+ }
26
+ });
27
+ await Promise.all(workers);
28
+ return results;
29
+ };
@@ -1,4 +1,5 @@
1
1
  import type { RequestBaseConfig } from "../api/utils/request.js";
2
+ export declare const toImportSpecifier: (filePath: string, platform?: NodeJS.Platform) => string;
2
3
  /**
3
4
  * Asynchronously load a file using dynamic import
4
5
  * Returns the default export of the module
@@ -1,11 +1,25 @@
1
1
  import * as fs from "fs";
2
2
  import { writeFile } from "fs";
3
3
  import { createRequire } from "module";
4
- import path from "path";
4
+ import nodePath from "path";
5
+ import { pathToFileURL } from "url";
5
6
  import pkg from "ncp";
6
7
  import { generateDatestamp } from "./date-utils.js";
7
8
  import Logger from "./logger.js";
8
9
  const { ncp } = pkg;
10
+ const resolveFromCwd = (filePath, pathApi = nodePath) => pathApi.isAbsolute(filePath)
11
+ ? filePath
12
+ : pathApi.resolve(process.cwd(), filePath);
13
+ export const toImportSpecifier = (filePath, platform = process.platform) => {
14
+ if (/^(file|data|node):/.test(filePath)) {
15
+ return filePath;
16
+ }
17
+ const pathApi = platform === "win32" ? nodePath.win32 : nodePath;
18
+ const resolvedPath = resolveFromCwd(filePath, pathApi);
19
+ return platform === "win32"
20
+ ? pathToFileURL(resolvedPath, { windows: true }).href
21
+ : resolvedPath;
22
+ };
9
23
  // ============================================================================
10
24
  // File Content Loading
11
25
  // ============================================================================
@@ -17,7 +31,7 @@ const { ncp } = pkg;
17
31
  * @returns The default export of the imported module
18
32
  */
19
33
  export const getFileContent = (data) => {
20
- return import(data.file)
34
+ return import(/* @vite-ignore */ toImportSpecifier(data.file))
21
35
  .then((res) => {
22
36
  return res.default;
23
37
  })
@@ -56,14 +70,14 @@ export const getFilesContentWithRequire = (data) => {
56
70
  * @returns Parsed package.json object
57
71
  */
58
72
  export const getPackageJson = () => {
59
- const packageJsonPath = path.join(process.cwd(), "package.json");
73
+ const packageJsonPath = nodePath.join(process.cwd(), "package.json");
60
74
  const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
61
75
  const packageJson = JSON.parse(packageJsonContent);
62
76
  return packageJson;
63
77
  };
64
78
  export const isDirectoryExists = (path) => fs.existsSync(path);
65
79
  export const createDir = async (dirPath) => {
66
- await fs.promises.mkdir(`${process.cwd()}/${dirPath}`, {
80
+ await fs.promises.mkdir(resolveFromCwd(dirPath), {
67
81
  recursive: true,
68
82
  });
69
83
  };
@@ -103,10 +117,10 @@ export const copyFolder = async (src, dest) => {
103
117
  });
104
118
  };
105
119
  export const copyFile = async (src, dest) => {
106
- const directory = dest.split("/").slice(0, dest.split("/").length - 1);
107
- const fileName = src.split("/")[src.split("/").length - 1];
108
- if (!isDirectoryExists(directory.join("/"))) {
109
- await createDir(directory.join("/"));
120
+ const directory = nodePath.dirname(dest);
121
+ const fileName = nodePath.basename(src);
122
+ if (!isDirectoryExists(directory)) {
123
+ await createDir(directory);
110
124
  }
111
125
  fs.copyFile(src, dest, (err) => {
112
126
  if (err) {
@@ -141,10 +155,7 @@ export const createAndSaveToFile = async (args, config) => {
141
155
  Logger.success(`All response written to a file: ${fullPath}`);
142
156
  }
143
157
  if (path) {
144
- const folderPath = path
145
- .split("/")
146
- .slice(0, path.split("/").length - 1)
147
- .join("/");
158
+ const folderPath = nodePath.dirname(path);
148
159
  await createDir(folderPath);
149
160
  await createJsonFile(JSON.stringify(res, undefined, 2), path);
150
161
  Logger.success(`All response written to a file: ${path}`);
@@ -169,7 +180,7 @@ export const createAndSaveComponentListToFile = async ({ file, folder, res, time
169
180
  Logger.success(`All components written to a file: ${filename}`);
170
181
  };
171
182
  export const readFile = async (pathToFile) => {
172
- const absolutePath = path.join(process.cwd(), pathToFile);
183
+ const absolutePath = resolveFromCwd(pathToFile);
173
184
  try {
174
185
  const result = await fs.promises.readFile(absolutePath);
175
186
  return result.toString();
@@ -192,13 +203,13 @@ export const dumpToFile = async (path, content) => {
192
203
  };
193
204
  export const getConsumerPackageJson = async () => {
194
205
  const consumerPkg = await getFileContentWithRequire({
195
- file: path.join(process.cwd(), "package.json"),
206
+ file: nodePath.join(process.cwd(), "package.json"),
196
207
  });
197
208
  return consumerPkg;
198
209
  };
199
210
  export const getSbMigPackageJson = async () => {
200
211
  const sbMigPkg = await getFileContentWithRequire({
201
- file: path.join("..", "..", "package.json"),
212
+ file: nodePath.join("..", "..", "package.json"),
202
213
  });
203
214
  return sbMigPkg;
204
215
  };
@@ -5,11 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.deepUpsertStory = exports.upsertStory = exports.updateStories = exports.publishStoryLanguages = exports.updateStory = exports.createStory = exports.getStoryBySlug = exports.getStoryById = exports.getAllStories = exports.removeAllStories = exports.removeStory = exports.resolvePublishLanguageCodes = exports.parsePublishLanguagesOption = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
+ const async_utils_js_1 = require("../../utils/async-utils.js");
8
9
  const logger_js_1 = __importDefault(require("../../utils/logger.js"));
9
10
  const object_utils_js_1 = require("../../utils/object-utils.js");
10
11
  const request_js_1 = require("../utils/request.js");
11
12
  const resolveStoryLabel = (content, storyId) => content?.full_slug || content?.slug || content?.name || String(storyId);
12
13
  const DEFAULT_PUBLISH_LANGUAGE = "[default]";
14
+ const STORY_CONTENT_FETCH_CONCURRENCY = 10;
13
15
  const isDefaultLanguageToken = (language) => language.toLowerCase() === "default" ||
14
16
  language === DEFAULT_PUBLISH_LANGUAGE;
15
17
  const normalizePublishLanguageCodes = (languages) => {
@@ -154,7 +156,7 @@ const getAllStories = async (args, config) => {
154
156
  });
155
157
  logger_js_1.default.success(`Successfully pre-fetched ${allStoriesWithoutContent.length} stories.`);
156
158
  let heartBeat = 0;
157
- const allStories = await Promise.all(allStoriesWithoutContent.map(async (story) => {
159
+ const allStories = await (0, async_utils_js_1.mapWithConcurrency)(allStoriesWithoutContent, STORY_CONTENT_FETCH_CONCURRENCY, async (story) => {
158
160
  const result = await (0, exports.getStoryById)(story.id, config);
159
161
  heartBeat++;
160
162
  if (heartBeat % 10 === 0 ||
@@ -162,7 +164,7 @@ const getAllStories = async (args, config) => {
162
164
  logger_js_1.default.success(`Successfully fetched ${heartBeat} stories with full content.`);
163
165
  }
164
166
  return result;
165
- }));
167
+ });
166
168
  return allStories;
167
169
  };
168
170
  exports.getAllStories = getAllStories;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Async utility functions
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.mapWithConcurrency = exports.delay = void 0;
7
+ /**
8
+ * Delay execution for a specified time
9
+ *
10
+ * @param time - Time to delay in milliseconds
11
+ * @returns Promise that resolves after the delay
12
+ *
13
+ * @example
14
+ * await delay(1000); // Wait 1 second
15
+ */
16
+ const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));
17
+ exports.delay = delay;
18
+ const mapWithConcurrency = async (items, concurrency, mapper) => {
19
+ if (items.length === 0) {
20
+ return [];
21
+ }
22
+ const limit = Math.max(1, Math.floor(concurrency));
23
+ const results = new Array(items.length);
24
+ let nextIndex = 0;
25
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
26
+ while (nextIndex < items.length) {
27
+ const currentIndex = nextIndex++;
28
+ results[currentIndex] = await mapper(items[currentIndex], currentIndex);
29
+ }
30
+ });
31
+ await Promise.all(workers);
32
+ return results;
33
+ };
34
+ exports.mapWithConcurrency = mapWithConcurrency;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sb-mig",
3
- "version": "6.0.0-beta.6",
3
+ "version": "6.0.0-beta.7",
4
4
  "description": "CLI to rule the world. (and handle stuff related to Storyblok CMS)",
5
5
  "author": "Marcin Krawczyk <marckraw@icloud.com>",
6
6
  "license": "MIT",
@@ -42,7 +42,7 @@
42
42
  ],
43
43
  "scripts": {
44
44
  "lint-staged": "node ./src/scripts/fix-esm.js && lint-staged",
45
- "build": "rm -rf dist dist-cjs && tsc -p tsconfig.json && tsc -p tsconfig.api-v2.cjs.json && node ./src/scripts/write-cjs-package.js && chmod +x ./dist/cli/index.js",
45
+ "build": "node ./src/scripts/clean-build.js && tsc -p tsconfig.json && tsc -p tsconfig.api-v2.cjs.json && node ./src/scripts/write-cjs-package.js && node ./src/scripts/make-cli-executable.js",
46
46
  "build:dev": "chokidar 'src/**/*.{js,ts,cjs,mjs}' -c 'npm run build'",
47
47
  "lint": "eslint . --max-warnings=0",
48
48
  "lint:fix": "eslint --fix",