storyblok 4.15.1 → 4.16.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/lib/config/types.ts"],"sourcesContent":["import type { RegionCode } from '../../constants';\nimport type { Command, Option } from 'commander';\nimport type { CommandOptions } from '../../types';\nimport type { PullComponentsOptions } from '../../commands/components/pull/constants';\nimport type { PushComponentsOptions } from '../../commands/components/push/constants';\nimport type { PullDatasourcesOptions } from '../../commands/datasources/pull/constants';\nimport type { PushDatasourcesOptions } from '../../commands/datasources/push/constants';\nimport type { DeleteDatasourceOptions } from '../../commands/datasources/delete/constants';\nimport type { MigrationsGenerateOptions } from '../../commands/migrations/generate/constants';\nimport type { MigrationsRunOptions } from '../../commands/migrations/run/constants';\nimport type { MigrationsRollbackOptions } from '../../commands/migrations/rollback/types';\nimport type { GenerateTypesOptions } from '../../commands/types/generate/constants';\nimport type { PullLanguagesOptions } from '../../commands/languages/constants';\nimport type { PullAssetsOptions } from '../../commands/assets/pull/types';\nimport type { PushAssetsOptions } from '../../commands/assets/push/types';\nimport type { PullStoriesOptions } from '../../commands/stories/pull/types';\nimport type { PushStoriesOptions } from '../../commands/stories/push/types';\nimport type { PruneLogsOptions } from '../../commands/logs/prune/types';\nimport type { PruneReportsOptions } from '../../commands/reports/prune/types';\nimport type { DeepPartial } from '../../utils/types';\n\nexport type PlainObject = Record<string, any>;\n\nexport interface ApiConfig {\n maxRetries: number;\n maxConcurrency: number;\n}\n\nexport interface LogConsoleConfig {\n enabled: boolean;\n level: string;\n}\n\nexport interface LogFileConfig {\n enabled: boolean;\n level: string;\n maxFiles: number;\n}\n\nexport interface LogConfig {\n console: LogConsoleConfig;\n file: LogFileConfig;\n}\n\nexport interface ReportConfig {\n enabled: boolean;\n maxFiles: number;\n}\n\nexport interface UiConfig {\n enabled: boolean;\n}\n\nexport interface GlobalConfig {\n region?: RegionCode;\n space?: number | string;\n path?: string;\n api: ApiConfig;\n log: LogConfig;\n report: ReportConfig;\n ui: UiConfig;\n verbose: boolean;\n}\n\nexport interface ResolvedCliConfig extends GlobalConfig {\n [key: string]: any;\n}\n\ntype StripCommandOption<T> = T extends CommandOptions ? Omit<T, keyof CommandOptions> : T;\ntype CommandConfig<T> = Partial<StripCommandOption<T>>;\n\nexport interface SharedConfigOptions {\n space?: number | string;\n path?: string;\n}\n\nexport interface CommandOptionsMap {\n components: { pull: PullComponentsOptions; push: PushComponentsOptions };\n datasources: { pull: PullDatasourcesOptions; push: PushDatasourcesOptions; delete: DeleteDatasourceOptions };\n migrations: { generate: MigrationsGenerateOptions; run: MigrationsRunOptions; rollback: MigrationsRollbackOptions };\n types: { generate: GenerateTypesOptions };\n languages: { pull: PullLanguagesOptions };\n assets: { pull: PullAssetsOptions; push: PushAssetsOptions };\n stories: { pull: PullStoriesOptions; push: PushStoriesOptions };\n logs: { list: Record<string, never>; prune: PruneLogsOptions };\n reports: { list: Record<string, never>; prune: PruneReportsOptions };\n}\n\ntype SubcommandConfig<T> = SharedConfigOptions & CommandConfig<T>;\n\ntype ModuleConfig<Subs extends Record<string, any>> = SharedConfigOptions & {\n [K in keyof Subs]?: SubcommandConfig<Subs[K]>;\n};\n\nexport type ModulesConfig = {\n [K in keyof CommandOptionsMap]?: ModuleConfig<CommandOptionsMap[K]>;\n};\n\nexport type ComponentsModuleConfig = ModulesConfig['components'];\nexport type DatasourcesModuleConfig = ModulesConfig['datasources'];\nexport type MigrationsModuleConfig = ModulesConfig['migrations'];\nexport type TypesModuleConfig = ModulesConfig['types'];\nexport type LanguagesModuleConfig = ModulesConfig['languages'];\nexport type AssetsModuleConfig = ModulesConfig['assets'];\nexport type StoriesModuleConfig = ModulesConfig['stories'];\nexport type LogsModuleConfig = ModulesConfig['logs'];\nexport type ReportsModuleConfig = ModulesConfig['reports'];\n\nexport interface StoryblokConfig extends DeepPartial<GlobalConfig> {\n modules?: ModulesConfig;\n}\n\nexport function defineConfig<T extends StoryblokConfig>(config: T): T {\n return config;\n}\n\nexport type OptionParser<T> = (value: string, previous?: T) => T;\n\nexport interface GlobalOptionDefinition<T = unknown> {\n flags: string;\n description: string;\n defaultValue?: T;\n parser?: OptionParser<T>;\n}\n\nexport interface ConfigLocation {\n cwd: string;\n configFile: string;\n}\n\nexport type CommanderOption = Option;\nexport type CommanderCommand = Command;\n"],"names":[],"mappings":"AAgHO,SAAS,aAAwC,MAAc,EAAA;AACpE,EAAO,OAAA,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/lib/config/types.ts"],"sourcesContent":["import type { RegionCode } from '../../constants';\nimport type { Command, Option } from 'commander';\nimport type { CommandOptions } from '../../types';\nimport type { PullComponentsOptions } from '../../commands/components/pull/constants';\nimport type { PushComponentsOptions } from '../../commands/components/push/constants';\nimport type { PullDatasourcesOptions } from '../../commands/datasources/pull/constants';\nimport type { PushDatasourcesOptions } from '../../commands/datasources/push/constants';\nimport type { DeleteDatasourceOptions } from '../../commands/datasources/delete/constants';\nimport type { MigrationsGenerateOptions } from '../../commands/migrations/generate/constants';\nimport type { MigrationsRunOptions } from '../../commands/migrations/run/constants';\nimport type { MigrationsRollbackOptions } from '../../commands/migrations/rollback/types';\nimport type { GenerateTypesOptions } from '../../commands/types/generate/constants';\nimport type { PullLanguagesOptions } from '../../commands/languages/constants';\nimport type { PullAssetsOptions } from '../../commands/assets/pull/types';\nimport type { PushAssetsOptions } from '../../commands/assets/push/types';\nimport type { PullStoriesOptions } from '../../commands/stories/pull/types';\nimport type { PushStoriesOptions } from '../../commands/stories/push/types';\nimport type { PruneLogsOptions } from '../../commands/logs/prune/types';\nimport type { PruneReportsOptions } from '../../commands/reports/prune/types';\nimport type { DeepPartial } from '../../utils/types';\n\nexport type PlainObject = Record<string, any>;\n\nexport interface ApiConfig {\n maxRetries: number;\n maxConcurrency: number;\n}\n\nexport interface LogConsoleConfig {\n enabled: boolean;\n level: string;\n}\n\nexport interface LogFileConfig {\n enabled: boolean;\n level: string;\n maxFiles: number;\n}\n\nexport interface LogConfig {\n console: LogConsoleConfig;\n file: LogFileConfig;\n}\n\nexport interface ReportConfig {\n enabled: boolean;\n maxFiles: number;\n}\n\nexport interface UiConfig {\n enabled: boolean;\n}\n\nexport interface GlobalConfig {\n region?: RegionCode;\n space?: number | string;\n path?: string;\n api: ApiConfig;\n log: LogConfig;\n report: ReportConfig;\n ui: UiConfig;\n verbose: boolean;\n}\n\nexport interface ResolvedCliConfig extends GlobalConfig {\n [key: string]: any;\n}\n\ntype StripCommandOption<T> = T extends CommandOptions ? Omit<T, keyof CommandOptions> : T;\ntype CommandConfig<T> = Partial<StripCommandOption<T>>;\n\nexport interface SharedConfigOptions {\n space?: number | string;\n path?: string;\n}\n\nexport interface CommandOptionsMap {\n components: { pull: PullComponentsOptions; push: PushComponentsOptions };\n datasources: { pull: PullDatasourcesOptions; push: PushDatasourcesOptions; delete: DeleteDatasourceOptions };\n migrations: { generate: MigrationsGenerateOptions; run: MigrationsRunOptions; rollback: MigrationsRollbackOptions };\n types: { generate: GenerateTypesOptions };\n languages: { pull: PullLanguagesOptions };\n assets: { pull: PullAssetsOptions; push: PushAssetsOptions };\n stories: { pull: PullStoriesOptions; push: PushStoriesOptions };\n logs: { list: Record<string, never>; prune: PruneLogsOptions };\n reports: { list: Record<string, never>; prune: PruneReportsOptions };\n}\n\ntype SubcommandConfig<T> = SharedConfigOptions & CommandConfig<T>;\n\ntype ModuleConfig<Subs extends Record<string, any>> = SharedConfigOptions & {\n [K in keyof Subs]?: SubcommandConfig<Subs[K]>;\n};\n\nexport type ModulesConfig = {\n [K in keyof CommandOptionsMap]?: ModuleConfig<CommandOptionsMap[K]>;\n};\n\nexport type ComponentsModuleConfig = ModulesConfig['components'];\nexport type DatasourcesModuleConfig = ModulesConfig['datasources'];\nexport type MigrationsModuleConfig = ModulesConfig['migrations'];\nexport type TypesModuleConfig = ModulesConfig['types'];\nexport type LanguagesModuleConfig = ModulesConfig['languages'];\nexport type AssetsModuleConfig = ModulesConfig['assets'];\nexport type StoriesModuleConfig = ModulesConfig['stories'];\nexport type LogsModuleConfig = ModulesConfig['logs'];\nexport type ReportsModuleConfig = ModulesConfig['reports'];\n\nexport interface StoryblokConfig extends DeepPartial<GlobalConfig> {\n modules?: ModulesConfig;\n}\n\nexport function defineConfig<T extends StoryblokConfig>(config: T): T {\n return config;\n}\n\nexport type OptionParser<T> = (value: string, previous?: T) => T;\n\nexport interface GlobalOptionDefinition<T = unknown> {\n flags: string;\n description: string;\n defaultValue?: T;\n parser?: OptionParser<T>;\n}\n\nexport interface ConfigLocation {\n cwd: string;\n configFile: string;\n}\n\nexport type CommanderOption = Option;\nexport type CommanderCommand = Command;\n"],"names":[],"mappings":"AAgHO,SAAS,aAAwC,MAAA,EAAc;AACpE,EAAA,OAAO,MAAA;AACT;;;;"}
package/dist/index.mjs CHANGED
@@ -1,14 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import 'dotenv/config';
3
3
  import { fileURLToPath, pathToFileURL } from 'node:url';
4
- import { resolve, dirname, isAbsolute, relative as relative$1, join as join$1 } from 'pathe';
4
+ import { resolve, dirname, join, parse, extname, relative, isAbsolute, basename } from 'pathe';
5
5
  import { existsSync, mkdirSync, appendFileSync, writeFileSync, readdirSync, unlinkSync, readFileSync } from 'node:fs';
6
6
  import { homedir } from 'node:os';
7
7
  import { loadConfig as loadConfig$1, SUPPORTED_EXTENSIONS } from 'c12';
8
8
  import chalk from 'chalk';
9
9
  import { readPackageUp } from 'read-package-up';
10
10
  import { Command } from 'commander';
11
- import path, { join, resolve as resolve$1, parse, dirname as dirname$1, extname, relative, basename } from 'node:path';
12
11
  import { MultiBar, Presets } from 'cli-progress';
13
12
  import { Spinner } from '@topcli/spinner';
14
13
  import fs, { mkdir, writeFile, readFile as readFile$1, appendFile, access, constants, readdir, unlink } from 'node:fs/promises';
@@ -1075,10 +1074,10 @@ const konsola = {
1075
1074
  }
1076
1075
  };
1077
1076
 
1078
- const __filename$1 = fileURLToPath(import.meta.url);
1079
- const __dirname$1 = dirname(__filename$1);
1077
+ const __filename$2 = fileURLToPath(import.meta.url);
1078
+ const __dirname$2 = dirname(__filename$2);
1080
1079
  const result = await readPackageUp({
1081
- cwd: __dirname$1
1080
+ cwd: __dirname$2
1082
1081
  });
1083
1082
  const packageJson$1 = result ? result.packageJson : {
1084
1083
  name: "storyblok",
@@ -1092,8 +1091,8 @@ function getPackageJson() {
1092
1091
  return packageJson$1;
1093
1092
  }
1094
1093
 
1095
- const __filename = fileURLToPath(import.meta.url);
1096
- const __dirname = dirname(__filename);
1094
+ const __filename$1 = fileURLToPath(import.meta.url);
1095
+ const __dirname$1 = dirname(__filename$1);
1097
1096
  function isRegion(value) {
1098
1097
  return Object.values(regions).includes(value);
1099
1098
  }
@@ -1309,7 +1308,7 @@ const deduplicateManifest = async (manifestFile) => {
1309
1308
  };
1310
1309
  const resolvePath = (path, folder) => {
1311
1310
  const basePath = path ?? DEFAULT_STORAGE_DIR;
1312
- return resolve$1(process.cwd(), basePath, folder);
1311
+ return resolve(process.cwd(), basePath, folder);
1313
1312
  };
1314
1313
  function resolveCommandPath(commandPath, space, baseDir) {
1315
1314
  if (space) {
@@ -1421,7 +1420,7 @@ class Reporter {
1421
1420
  if (this.maxFiles === void 0) {
1422
1421
  return;
1423
1422
  }
1424
- const dir = dirname$1(this.filePath);
1423
+ const dir = dirname(this.filePath);
1425
1424
  const ext = extname(this.filePath);
1426
1425
  Reporter.pruneReportFiles(dir, this.maxFiles, ext);
1427
1426
  }
@@ -1479,7 +1478,7 @@ class FileTransport {
1479
1478
  if (this.maxFiles === void 0) {
1480
1479
  return;
1481
1480
  }
1482
- const dir = dirname$1(this.filePath);
1481
+ const dir = dirname(this.filePath);
1483
1482
  const ext = extname(this.filePath);
1484
1483
  FileTransport.pruneLogFiles(dir, this.maxFiles, ext);
1485
1484
  }
@@ -1878,7 +1877,7 @@ function getProgram() {
1878
1877
  options.path
1879
1878
  );
1880
1879
  const logFilename = `${commandPieces.join("-")}-${runId}.jsonl`;
1881
- logFilePath = path.join(logsPath, logFilename);
1880
+ logFilePath = join(logsPath, logFilename);
1882
1881
  transports.push(
1883
1882
  new FileTransport({
1884
1883
  filePath: logFilePath,
@@ -1902,7 +1901,7 @@ function getProgram() {
1902
1901
  options.path
1903
1902
  );
1904
1903
  const reportFilename = `${commandPieces.join("-")}-${runId}.json`;
1905
- const reportFilePath = path.join(reportPath, reportFilename);
1904
+ const reportFilePath = join(reportPath, reportFilename);
1906
1905
  const reporter = getReporter({
1907
1906
  enabled: true,
1908
1907
  filePath: reportFilePath,
@@ -2339,7 +2338,7 @@ const fetchComponentInternalTags = async (spaceId) => {
2339
2338
  const saveComponentsToFiles = async (space, spaceData, options) => {
2340
2339
  const { components = [], groups = [], presets = [], internalTags = [] } = spaceData;
2341
2340
  const { filename = DEFAULT_COMPONENTS_FILENAME, suffix, path, separateFiles } = options;
2342
- const resolvedPath = path ? resolve$1(process.cwd(), path, "components", space) : resolvePath(path, `components/${space}`);
2341
+ const resolvedPath = path ? resolve(process.cwd(), path, "components", space) : resolvePath(path, `components/${space}`);
2343
2342
  try {
2344
2343
  if (separateFiles) {
2345
2344
  for (const component of components) {
@@ -2713,17 +2712,17 @@ pullCmd$4.action(async (componentName, options, command) => {
2713
2712
  konsola.warn(`The --filename option is ignored when using --separate-files`);
2714
2713
  }
2715
2714
  const filePath = `${componentsOutputDir}/`;
2716
- const displayPath = path && isAbsolute(path) ? filePath : `${relative$1(process.cwd(), componentsOutputDir)}/`;
2715
+ const displayPath = path && isAbsolute(path) ? filePath : `${relative(process.cwd(), componentsOutputDir)}/`;
2717
2716
  konsola.ok(`Components downloaded successfully to ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`);
2718
2717
  } else if (componentName) {
2719
2718
  const fileName = suffix ? `${actualFilename}.${suffix}.json` : `${componentName}.json`;
2720
- const filePath = join$1(componentsOutputDir, fileName);
2721
- const displayPath = path && isAbsolute(path) ? filePath : relative$1(process.cwd(), filePath);
2719
+ const filePath = join(componentsOutputDir, fileName);
2720
+ const displayPath = path && isAbsolute(path) ? filePath : relative(process.cwd(), filePath);
2722
2721
  konsola.ok(`Component ${chalk.hex(colorPalette.PRIMARY)(componentName)} downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`);
2723
2722
  } else {
2724
2723
  const fileName = suffix ? `${actualFilename}.${suffix}.json` : `${actualFilename}.json`;
2725
- const filePath = join$1(componentsOutputDir, fileName);
2726
- const displayPath = path && isAbsolute(path) ? filePath : relative$1(process.cwd(), filePath);
2724
+ const filePath = join(componentsOutputDir, fileName);
2725
+ const displayPath = path && isAbsolute(path) ? filePath : relative(process.cwd(), filePath);
2727
2726
  konsola.ok(`Components downloaded successfully to ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`);
2728
2727
  }
2729
2728
  konsola.br();
@@ -3906,8 +3905,8 @@ pullCmd$3.action(async (options, command) => {
3906
3905
  });
3907
3906
  const languagesOutputDir = resolveCommandPath("languages", space, path);
3908
3907
  const fileName = suffix ? `${filename}.${suffix}.json` : `${filename}.json`;
3909
- const filePath = join$1(languagesOutputDir, fileName);
3910
- const displayPath = path && isAbsolute(path) ? filePath : relative$1(process.cwd(), filePath);
3908
+ const filePath = join(languagesOutputDir, fileName);
3909
+ const displayPath = path && isAbsolute(path) ? filePath : relative(process.cwd(), filePath);
3911
3910
  spinner.succeed();
3912
3911
  konsola.ok(`Languages schema downloaded successfully at ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`, true);
3913
3912
  } catch (error) {
@@ -3937,7 +3936,7 @@ const getMigrationTemplate = () => {
3937
3936
  `;
3938
3937
  };
3939
3938
  const generateMigration = async (space, path, component, suffix) => {
3940
- const resolvedPath = path ? resolve$1(process.cwd(), path, "migrations", space) : resolvePath(path, `migrations/${space}`);
3939
+ const resolvedPath = path ? resolve(process.cwd(), path, "migrations", space) : resolvePath(path, `migrations/${space}`);
3941
3940
  const fileName = suffix ? `${component.name}.${suffix}.js` : `${component.name}.js`;
3942
3941
  const migrationPath = join(resolvedPath, fileName);
3943
3942
  try {
@@ -4078,6 +4077,36 @@ const updateStory = async (spaceId, storyId, payload) => {
4078
4077
  handleAPIError("update_story", error);
4079
4078
  }
4080
4079
  };
4080
+ const prefetchTargetStories = async (spaceId, options) => {
4081
+ const result = {
4082
+ bySlug: /* @__PURE__ */ new Map(),
4083
+ byId: /* @__PURE__ */ new Map()
4084
+ };
4085
+ let page = 1;
4086
+ let totalPages = 1;
4087
+ while (page <= totalPages) {
4088
+ const response = await fetchStories(spaceId, { page, per_page: 100 });
4089
+ if (!response) {
4090
+ break;
4091
+ }
4092
+ const total = Number(response.headers.get("Total"));
4093
+ const perPage = Number(response.headers.get("Per-Page"));
4094
+ totalPages = Math.ceil(total / perPage);
4095
+ if (page === 1) {
4096
+ options?.onTotal?.(total);
4097
+ }
4098
+ for (const story of response.stories) {
4099
+ const ref = { id: story.id, uuid: story.uuid };
4100
+ if (story.full_slug) {
4101
+ result.bySlug.set(story.full_slug, ref);
4102
+ }
4103
+ result.byId.set(story.id, ref);
4104
+ }
4105
+ options?.onIncrement?.(response.stories.length);
4106
+ page++;
4107
+ }
4108
+ return result;
4109
+ };
4081
4110
 
4082
4111
  const ERROR_CODES = {
4083
4112
  MIGRATION_APPLY_TO_STORY_ERROR: "MIGRATION_APPLY_TO_STORY_ERROR",
@@ -4545,8 +4574,8 @@ const findComponentSchemas = async (directoryPath) => {
4545
4574
  }
4546
4575
  throw error;
4547
4576
  });
4548
- const fileContents = files.filter((f) => path.extname(f) === ".json").map((f) => {
4549
- const filePath = path.join(directoryPath, f);
4577
+ const fileContents = files.filter((f) => extname(f) === ".json").map((f) => {
4578
+ const filePath = join(directoryPath, f);
4550
4579
  const fileContent = readFileSync(filePath, "utf-8");
4551
4580
  return JSON.parse(fileContent);
4552
4581
  });
@@ -5611,7 +5640,7 @@ const getComponentPropertiesTypeAnnotations = async (component, options, spaceDa
5611
5640
  };
5612
5641
  const loadCustomFieldsParser = async (path) => {
5613
5642
  try {
5614
- const customFieldsParser = await import(resolve$1(path));
5643
+ const customFieldsParser = await import(pathToFileURL(resolve(path)).href);
5615
5644
  return customFieldsParser.default;
5616
5645
  } catch (error) {
5617
5646
  handleError(error);
@@ -5620,7 +5649,7 @@ const loadCustomFieldsParser = async (path) => {
5620
5649
  };
5621
5650
  async function loadCompilerOptions(path) {
5622
5651
  if (path) {
5623
- const compilerOptions = await import(resolve$1(path));
5652
+ const compilerOptions = await import(pathToFileURL(resolve(path)).href);
5624
5653
  return compilerOptions.default;
5625
5654
  }
5626
5655
  return {};
@@ -5770,7 +5799,7 @@ const generateTypes = async (spaceData, options = {
5770
5799
  };
5771
5800
  const saveTypesToComponentsFile = async (space, typedefData, options) => {
5772
5801
  const { filename = DEFAULT_COMPONENT_FILENAME, path, separateFiles } = options;
5773
- const resolvedPath = path ? resolve$1(process.cwd(), path, "types", space) : resolvePath(path, `types/${space}`);
5802
+ const resolvedPath = path ? resolve(process.cwd(), path, "types", space) : resolvePath(path, `types/${space}`);
5774
5803
  try {
5775
5804
  if (separateFiles && Array.isArray(typedefData)) {
5776
5805
  for (const { name, content } of typedefData) {
@@ -5786,7 +5815,7 @@ const saveTypesToComponentsFile = async (space, typedefData, options) => {
5786
5815
  const generateStoryblokTypes = async (options = {}) => {
5787
5816
  const { path } = options;
5788
5817
  try {
5789
- const storyblokTypesPath = resolve$1(__dirname, "./index.d.ts");
5818
+ const storyblokTypesPath = resolve(__dirname$1, "./index.d.ts");
5790
5819
  const storyblokTypesContent = readFileSync(storyblokTypesPath, "utf-8");
5791
5820
  const typeDefs = [
5792
5821
  "// This file was generated by the Storyblok CLI.",
@@ -5794,7 +5823,7 @@ const generateStoryblokTypes = async (options = {}) => {
5794
5823
  `import type { ${STORY_TYPE} } from '@storyblok/js';`,
5795
5824
  storyblokTypesContent
5796
5825
  ].join("\n");
5797
- const resolvedPath = path ? resolve$1(process.cwd(), path, "types") : resolvePath(path, "types");
5826
+ const resolvedPath = path ? resolve(process.cwd(), path, "types") : resolvePath(path, "types");
5798
5827
  await saveToFile(join(resolvedPath, `storyblok.d.ts`), typeDefs);
5799
5828
  return true;
5800
5829
  } catch (error) {
@@ -6113,7 +6142,7 @@ const fetchDatasource = async (spaceId, datasourceName) => {
6113
6142
  };
6114
6143
  const saveDatasourcesToFiles = async (space, datasources, options) => {
6115
6144
  const { filename = DEFAULT_DATASOURCES_FILENAME, suffix, path, separateFiles } = options;
6116
- const resolvedPath = path ? resolve$1(process.cwd(), path, "datasources", space) : resolvePath(path, `datasources/${space}`);
6145
+ const resolvedPath = path ? resolve(process.cwd(), path, "datasources", space) : resolvePath(path, `datasources/${space}`);
6117
6146
  try {
6118
6147
  if (separateFiles) {
6119
6148
  for (const datasource of datasources) {
@@ -6181,17 +6210,17 @@ pullCmd$2.action(async (datasourceName, options, command) => {
6181
6210
  konsola.warn(`The --filename option is ignored when using --separate-files`);
6182
6211
  }
6183
6212
  const filePath = `${datasourcesOutputDir}/`;
6184
- const displayPath = path && isAbsolute(path) ? filePath : `${relative$1(process.cwd(), datasourcesOutputDir)}/`;
6213
+ const displayPath = path && isAbsolute(path) ? filePath : `${relative(process.cwd(), datasourcesOutputDir)}/`;
6185
6214
  konsola.ok(`Datasources downloaded successfully to ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`);
6186
6215
  } else if (datasourceName) {
6187
6216
  const fileName = suffix ? `${actualFilename}.${suffix}.json` : `${datasourceName}.json`;
6188
- const filePath = join$1(datasourcesOutputDir, fileName);
6189
- const displayPath = path && isAbsolute(path) ? filePath : relative$1(process.cwd(), filePath);
6217
+ const filePath = join(datasourcesOutputDir, fileName);
6218
+ const displayPath = path && isAbsolute(path) ? filePath : relative(process.cwd(), filePath);
6190
6219
  konsola.ok(`Datasource ${chalk.hex(colorPalette.PRIMARY)(datasourceName)} downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`);
6191
6220
  } else {
6192
6221
  const fileName = suffix ? `${actualFilename}.${suffix}.json` : `${actualFilename}.json`;
6193
- const filePath = join$1(datasourcesOutputDir, fileName);
6194
- const displayPath = path && isAbsolute(path) ? filePath : relative$1(process.cwd(), filePath);
6222
+ const filePath = join(datasourcesOutputDir, fileName);
6223
+ const displayPath = path && isAbsolute(path) ? filePath : relative(process.cwd(), filePath);
6195
6224
  konsola.ok(`Datasources downloaded successfully to ${chalk.hex(colorPalette.PRIMARY)(displayPath)}`);
6196
6225
  }
6197
6226
  konsola.br();
@@ -6400,7 +6429,7 @@ const createOctokit = (token) => {
6400
6429
 
6401
6430
  const generateProject = async (blueprint, projectName, targetPath = process.cwd()) => {
6402
6431
  try {
6403
- const projectPath = path.join(targetPath, projectName);
6432
+ const projectPath = join(targetPath, projectName);
6404
6433
  const templateRepo = `storyblok/blueprint-core-${blueprint}`;
6405
6434
  try {
6406
6435
  await fs.access(projectPath);
@@ -6437,7 +6466,7 @@ const generateProject = async (blueprint, projectName, targetPath = process.cwd(
6437
6466
  };
6438
6467
  const createEnvFile = async (projectPath, storyblokVars, additionalVars) => {
6439
6468
  try {
6440
- const envPath = path.join(projectPath, ".env");
6469
+ const envPath = join(projectPath, ".env");
6441
6470
  let envContent = `# Storyblok Configuration
6442
6471
  ${Object.entries(storyblokVars).map(([key, value]) => `${key}=${value}`).join("\n")}
6443
6472
  `;
@@ -6655,7 +6684,7 @@ program$5.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
6655
6684
  if (!value.trim()) {
6656
6685
  return "Project path is required";
6657
6686
  }
6658
- const projectName2 = path.basename(value);
6687
+ const projectName2 = basename(value);
6659
6688
  if (!/^[\w-]+$/.test(projectName2)) {
6660
6689
  return "Project name (last part of the path) can only contain letters, numbers, hyphens, and underscores";
6661
6690
  }
@@ -6663,9 +6692,9 @@ program$5.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
6663
6692
  }
6664
6693
  });
6665
6694
  }
6666
- const resolvedPath = path.resolve(finalProjectPath);
6667
- const targetDirectory = path.dirname(resolvedPath);
6668
- const projectName = path.basename(resolvedPath);
6695
+ const resolvedPath = resolve(finalProjectPath);
6696
+ const targetDirectory = dirname(resolvedPath);
6697
+ const projectName = basename(resolvedPath);
6669
6698
  konsola.br();
6670
6699
  konsola.info(`Scaffolding your project using the ${chalk.hex(colorPalette.CREATE)(technologyTemplate)} template...`);
6671
6700
  await generateProject(technologyTemplate, projectName, targetDirectory);
@@ -7125,7 +7154,7 @@ const parseAssetData = (raw) => {
7125
7154
  }
7126
7155
  };
7127
7156
  const getSidecarFilename = (assetBinaryPath) => {
7128
- return join(dirname$1(assetBinaryPath), `${basename(assetBinaryPath, extname(assetBinaryPath))}.json`);
7157
+ return join(dirname(assetBinaryPath), `${basename(assetBinaryPath, extname(assetBinaryPath))}.json`);
7129
7158
  };
7130
7159
  const loadSidecarAssetData = async (assetBinaryPath) => {
7131
7160
  const sidecarPath = getSidecarFilename(assetBinaryPath);
@@ -8187,23 +8216,8 @@ const mapReferencesStream = ({
8187
8216
  }
8188
8217
  });
8189
8218
  };
8190
- const getRemoteStory = async ({ spaceId, storyId }) => {
8191
- const { data, response } = await getMapiClient().stories.get({
8192
- path: {
8193
- space_id: spaceId,
8194
- story_id: storyId
8195
- }
8196
- });
8197
- if (!response.ok && response.status !== 404) {
8198
- handleAPIError("pull_story", new FetchError(response.statusText, response));
8199
- }
8200
- if (data?.story?.deleted_at) {
8201
- return void 0;
8202
- }
8203
- return data?.story;
8204
- };
8205
8219
  const makeCreateStoryAPITransport = ({ spaceId }) => async (localStory) => {
8206
- const { id: _id, uuid: _uuid, parent_id: _parentId, content, ...newStoryData } = localStory;
8220
+ const { id: _id, uuid: _uuid, parent_id: _parentId, is_startpage: _isStartpage, content, ...newStoryData } = localStory;
8207
8221
  if (!localStory.is_folder && !content?.component) {
8208
8222
  throw new Error(`Story "${localStory.slug}" is missing a content type (content.component). Every story must define a content field with a valid component.`);
8209
8223
  }
@@ -8234,7 +8248,8 @@ const makeAppendToManifestFSTransport = ({ manifestFile }) => async (localStory,
8234
8248
  };
8235
8249
  const createStoryPlaceholderStream = ({
8236
8250
  maps,
8237
- spaceId,
8251
+ existingTargetStories,
8252
+ isCrossSpace,
8238
8253
  transports,
8239
8254
  onIncrement,
8240
8255
  onStorySuccess,
@@ -8249,16 +8264,19 @@ const createStoryPlaceholderStream = ({
8249
8264
  const task = (async () => {
8250
8265
  try {
8251
8266
  const mappedStoryId = maps.stories?.get(localStory.id);
8252
- const mappedRemoteStory = mappedStoryId && await getRemoteStory({ spaceId, storyId: Number(mappedStoryId) });
8267
+ const mappedRemoteStory = mappedStoryId ? existingTargetStories.byId.get(Number(mappedStoryId)) : void 0;
8253
8268
  if (mappedRemoteStory) {
8254
8269
  onStorySkipped?.(localStory, mappedRemoteStory);
8255
8270
  return;
8256
8271
  }
8257
- const existingRemoteStory = await getRemoteStory({ spaceId, storyId: localStory.id });
8258
- if (existingRemoteStory && existingRemoteStory.uuid === localStory.uuid) {
8259
- await transports.appendStoryManifest(localStory, existingRemoteStory);
8260
- onStorySkipped?.(localStory, existingRemoteStory);
8261
- return;
8272
+ const existingBySlug = localStory.full_slug ? existingTargetStories.bySlug.get(localStory.full_slug) : void 0;
8273
+ if (existingBySlug) {
8274
+ const isMatchConfirmed = isCrossSpace || existingBySlug.uuid === localStory.uuid;
8275
+ if (isMatchConfirmed) {
8276
+ await transports.appendStoryManifest(localStory, existingBySlug);
8277
+ onStorySkipped?.(localStory, existingBySlug);
8278
+ return;
8279
+ }
8262
8280
  }
8263
8281
  const newRemoteStory = await transports.createStory(localStory);
8264
8282
  await transports.appendStoryManifest(localStory, newRemoteStory);
@@ -8281,7 +8299,7 @@ const createStoryPlaceholderStream = ({
8281
8299
  });
8282
8300
  };
8283
8301
  const makeWriteStoryFSTransport = ({ directoryPath }) => async (story) => {
8284
- await saveToFile(resolve$1(directoryPath, getStoryFilename(story)), JSON.stringify(story, null, 2));
8302
+ await saveToFile(resolve(directoryPath, getStoryFilename(story)), JSON.stringify(story, null, 2));
8285
8303
  return story;
8286
8304
  };
8287
8305
  const makeWriteStoryAPITransport = ({ spaceId, publish }) => (mappedLocalStory) => updateStory(spaceId, mappedLocalStory.id, {
@@ -8295,7 +8313,7 @@ const makeCleanupStoryFSTransport = ({ directoryPath, maps }) => async (mappedSt
8295
8313
  slug: mappedStory.slug,
8296
8314
  uuid: originalUuid
8297
8315
  });
8298
- const storyFilePath = resolve$1(directoryPath, storyFilename);
8316
+ const storyFilePath = resolve(directoryPath, storyFilename);
8299
8317
  await unlink(storyFilePath);
8300
8318
  };
8301
8319
  const writeStoryStream = ({
@@ -8896,6 +8914,12 @@ pushCmd.action(async (options, command) => {
8896
8914
  logger.error(message);
8897
8915
  return;
8898
8916
  }
8917
+ const fetchProgress = ui.createProgressBar({ title: "Matching Stories...".padEnd(21) });
8918
+ const existingTargetStories = await prefetchTargetStories(space, {
8919
+ onTotal: (total) => fetchProgress.setTotal(total),
8920
+ onIncrement: (count) => fetchProgress.increment(count)
8921
+ });
8922
+ fetchProgress.stop();
8899
8923
  const storiesDirectoryPath = resolveCommandPath(directories.stories, fromSpace, basePath);
8900
8924
  const creationProgress = ui.createProgressBar({ title: "Creating Stories...".padEnd(21) });
8901
8925
  const processProgress = ui.createProgressBar({ title: "Processing Stories...".padEnd(21) });
@@ -8925,7 +8949,8 @@ pushCmd.action(async (options, command) => {
8925
8949
  // Create remote stories.
8926
8950
  createStoryPlaceholderStream({
8927
8951
  maps,
8928
- spaceId: space,
8952
+ existingTargetStories,
8953
+ isCrossSpace: fromSpace !== space,
8929
8954
  transports: {
8930
8955
  createStory: options.dryRun ? async (story) => story : makeCreateStoryAPITransport({
8931
8956
  spaceId: space