storyblok 4.19.0 → 4.19.2

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
@@ -5751,10 +5751,8 @@ const getPropertyTypeAnnotation = (property, prefix, suffix) => {
5751
5751
  return { type: property.type };
5752
5752
  }
5753
5753
  let type = "unknown";
5754
- const options = property.options && property.options.length > 0 ? property.options.map((item) => item.value) : [];
5755
- if (options.length > 0 && property.exclude_empty_option !== true) {
5756
- options.unshift("");
5757
- }
5754
+ const optionValues = property.options && property.options.length > 0 ? property.options.map((item) => item.value).filter((value) => value !== "") : [];
5755
+ const options = optionValues.length > 0 && !property.required ? ["", ...optionValues] : optionValues;
5758
5756
  if (property.source === "internal_stories") {
5759
5757
  if (property.filter_content_type) {
5760
5758
  return {
@@ -6107,11 +6105,18 @@ const generateStoryblokTypes = async (options = {}) => {
6107
6105
  const pushDatasource = async (spaceId, datasource) => {
6108
6106
  try {
6109
6107
  const client = getMapiClient();
6108
+ const { dimensions, ...datasourceFields } = datasource;
6109
+ const dimensionsAttributes = (dimensions ?? []).filter((dimension) => dimension.entry_value).map((dimension) => ({ name: dimension.name ?? dimension.entry_value ?? "", entry_value: dimension.entry_value ?? "" }));
6110
6110
  const { data } = await client.datasources.create({
6111
6111
  path: {
6112
6112
  space_id: Number(spaceId)
6113
6113
  },
6114
- body: { datasource },
6114
+ body: {
6115
+ datasource: {
6116
+ ...datasourceFields,
6117
+ ...dimensionsAttributes.length > 0 && { dimensions_attributes: dimensionsAttributes }
6118
+ }
6119
+ },
6115
6120
  throwOnError: true
6116
6121
  });
6117
6122
  return data.datasource;
@@ -6146,13 +6151,14 @@ const upsertDatasource = async (space, datasource, existingId) => {
6146
6151
  const pushDatasourceEntry = async (spaceId, datasourceId, entry, position) => {
6147
6152
  try {
6148
6153
  const client = getMapiClient();
6154
+ const { dimension_values, ...entryFields } = entry;
6149
6155
  const { data } = await client.datasourceEntries.create({
6150
6156
  path: {
6151
6157
  space_id: Number(spaceId)
6152
6158
  },
6153
6159
  body: {
6154
6160
  datasource_entry: {
6155
- ...entry,
6161
+ ...entryFields,
6156
6162
  value: entry.value ?? "",
6157
6163
  datasource_id: datasourceId,
6158
6164
  ...position != null && { position }
@@ -6168,13 +6174,14 @@ const pushDatasourceEntry = async (spaceId, datasourceId, entry, position) => {
6168
6174
  const updateDatasourceEntry = async (spaceId, entryId, entry, position) => {
6169
6175
  try {
6170
6176
  const client = getMapiClient();
6177
+ const { dimension_values, ...entryFields } = entry;
6171
6178
  await client.datasourceEntries.update(entryId, {
6172
6179
  path: {
6173
6180
  space_id: Number(spaceId)
6174
6181
  },
6175
6182
  body: {
6176
6183
  datasource_entry: {
6177
- ...entry,
6184
+ ...entryFields,
6178
6185
  ...position != null && { position }
6179
6186
  }
6180
6187
  },
@@ -6184,6 +6191,27 @@ const updateDatasourceEntry = async (spaceId, entryId, entry, position) => {
6184
6191
  handleAPIError("update_datasource", error, `Failed to update datasource entry ${entry.name}`);
6185
6192
  }
6186
6193
  };
6194
+ const updateDatasourceEntryDimension = async (spaceId, entryId, entry, dimensionId, dimensionValue) => {
6195
+ try {
6196
+ const client = getMapiClient();
6197
+ await client.datasourceEntries.update(entryId, {
6198
+ path: {
6199
+ space_id: Number(spaceId)
6200
+ },
6201
+ query: { dimension_id: dimensionId },
6202
+ body: {
6203
+ datasource_entry: {
6204
+ name: entry.name,
6205
+ value: entry.value ?? "",
6206
+ dimension_value: dimensionValue
6207
+ }
6208
+ },
6209
+ throwOnError: true
6210
+ });
6211
+ } catch (error) {
6212
+ handleAPIError("update_datasource", error, `Failed to update datasource entry ${entry.name} for dimension ${dimensionId}`);
6213
+ }
6214
+ };
6187
6215
  const upsertDatasourceEntry = async (space, datasourceId, entry, existingId, position) => {
6188
6216
  if (existingId) {
6189
6217
  await updateDatasourceEntry(space, existingId, entry, position);
@@ -6343,7 +6371,7 @@ const datasourcesCommand = program$6.command(commands.DATASOURCES).alias("ds").d
6343
6371
 
6344
6372
  const DEFAULT_DATASOURCES_FILENAME = "datasources";
6345
6373
 
6346
- const fetchDatasourceEntries = async (spaceId, datasourceId) => {
6374
+ const fetchDatasourceEntries = async (spaceId, datasourceId, dimensionId) => {
6347
6375
  try {
6348
6376
  const client = getMapiClient();
6349
6377
  return await fetchAllPages(
@@ -6353,7 +6381,9 @@ const fetchDatasourceEntries = async (spaceId, datasourceId) => {
6353
6381
  },
6354
6382
  query: {
6355
6383
  datasource_id: datasourceId,
6356
- page
6384
+ page,
6385
+ // MAPI matches `dimension` against the numeric dimension id.
6386
+ ...dimensionId != null && { dimension: String(dimensionId) }
6357
6387
  },
6358
6388
  throwOnError: true
6359
6389
  }),
@@ -6363,6 +6393,34 @@ const fetchDatasourceEntries = async (spaceId, datasourceId) => {
6363
6393
  handleAPIError("pull_datasources", error);
6364
6394
  }
6365
6395
  };
6396
+ const fetchDatasourceEntriesWithDimensions = async (spaceId, datasource) => {
6397
+ const defaultEntries = await fetchDatasourceEntries(spaceId, datasource.id) ?? [];
6398
+ const entries = defaultEntries.map(({ dimension_value, ...rest }) => rest);
6399
+ const dimensions = datasource.dimensions ?? [];
6400
+ if (!dimensions.length) {
6401
+ return entries;
6402
+ }
6403
+ const entriesById = new Map(entries.map((entry) => [entry.id, entry]));
6404
+ for (const dimension of dimensions) {
6405
+ if (dimension.id == null || !dimension.entry_value) {
6406
+ continue;
6407
+ }
6408
+ const dimensionEntries = await fetchDatasourceEntries(spaceId, datasource.id, dimension.id) ?? [];
6409
+ for (const dimensionEntry of dimensionEntries) {
6410
+ const value = dimensionEntry.dimension_value;
6411
+ if (!value) {
6412
+ continue;
6413
+ }
6414
+ const entry = entriesById.get(dimensionEntry.id);
6415
+ if (!entry) {
6416
+ continue;
6417
+ }
6418
+ entry.dimension_values ??= {};
6419
+ entry.dimension_values[dimension.entry_value] = value;
6420
+ }
6421
+ }
6422
+ return entries;
6423
+ };
6366
6424
  const fetchDatasources = async (spaceId) => {
6367
6425
  try {
6368
6426
  const client = getMapiClient();
@@ -6383,7 +6441,7 @@ const fetchDatasources = async (spaceId) => {
6383
6441
  if (!ds.id) {
6384
6442
  return { ...ds, entries: [] };
6385
6443
  }
6386
- const entries = await fetchDatasourceEntries(spaceId, ds.id);
6444
+ const entries = await fetchDatasourceEntriesWithDimensions(spaceId, ds);
6387
6445
  return { ...ds, entries };
6388
6446
  })
6389
6447
  );
@@ -6412,8 +6470,8 @@ const fetchDatasource = async (spaceId, datasourceName) => {
6412
6470
  if (!found) {
6413
6471
  return void 0;
6414
6472
  }
6415
- const entries = await fetchDatasourceEntries(spaceId, found.id);
6416
- return { ...found, entries: entries || [] };
6473
+ const entries = await fetchDatasourceEntriesWithDimensions(spaceId, found);
6474
+ return { ...found, entries };
6417
6475
  } catch (error) {
6418
6476
  handleAPIError("pull_datasources", error, `Failed to fetch datasource ${datasourceName}`);
6419
6477
  }
@@ -6511,6 +6569,14 @@ pullCmd$2.action(async (datasourceName, options, command) => {
6511
6569
  }
6512
6570
  });
6513
6571
 
6572
+ function dimensionValuesEqual(a, b) {
6573
+ const aKeys = Object.keys(a ?? {});
6574
+ const bKeys = Object.keys(b ?? {});
6575
+ if (aKeys.length !== bKeys.length) {
6576
+ return false;
6577
+ }
6578
+ return aKeys.every((key) => a?.[key] === b?.[key]);
6579
+ }
6514
6580
  const pushCmd$2 = datasourcesCommand.command("push [datasourceName]").description(`Push your space's datasources schema as json`).option("-f, --from <from>", "source space id").option("--fi, --filter <filter>", "glob filter to apply to the datasources before pushing").option("--sf, --separate-files", "Read from separate files instead of consolidated files").option("--su, --suffix <suffix>", "Load only files matching *.<suffix>.json (e.g. datasources.dev.json)").option("-s, --space <space>", "space ID");
6515
6581
  pushCmd$2.action(async (datasourceName, options, command) => {
6516
6582
  konsola.title(`${commands.DATASOURCES}`, colorPalette.DATASOURCES, datasourceName ? `Pushing datasource ${datasourceName}...` : "Pushing datasources...");
@@ -6582,19 +6648,39 @@ pushCmd$2.action(async (datasourceName, options, command) => {
6582
6648
  results.successful.push(datasource.name);
6583
6649
  const localEntries = entries ?? [];
6584
6650
  const existingEntries = existingDatasource?.entries ?? [];
6651
+ const dimensionWarnings = [];
6585
6652
  const existingEntryMap = new Map(existingEntries.map((e, idx) => [e.name, { entry: e, position: idx + 1 }]));
6586
6653
  for (let i = 0; i < localEntries.length; i++) {
6587
6654
  const entry = localEntries[i];
6588
6655
  const existing = existingEntryMap.get(entry.name);
6589
6656
  const existingEntryId = existing?.entry.id;
6590
6657
  const targetPosition = i + 1;
6591
- if (existing && existing.entry.value === entry.value && existing.entry.dimension_value === entry.dimension_value && existing.position === targetPosition) {
6658
+ if (existing && existing.entry.value === entry.value && dimensionValuesEqual(existing.entry.dimension_values, entry.dimension_values) && existing.position === targetPosition) {
6592
6659
  logger.info("Skipped datasource entry (unchanged)", { datasource: datasource.name, entry: entry.name, position: targetPosition });
6593
6660
  continue;
6594
6661
  }
6595
6662
  try {
6596
- await upsertDatasourceEntry(space, result.id, entry, existingEntryId, i + 1);
6663
+ const upserted = await upsertDatasourceEntry(space, result.id, entry, existingEntryId, i + 1);
6664
+ const entryId = existingEntryId ?? upserted?.id;
6597
6665
  logger.info(existingEntryId ? "Updated datasource entry" : "Created datasource entry", { datasource: datasource.name, entry: entry.name, position: i + 1 });
6666
+ if (entryId != null && entry.dimension_values !== void 0) {
6667
+ const localDimensionValues = entry.dimension_values;
6668
+ const targetDimensionValues = existing?.entry.dimension_values ?? {};
6669
+ const dimensionCodes = /* @__PURE__ */ new Set([...Object.keys(localDimensionValues), ...Object.keys(targetDimensionValues)]);
6670
+ for (const code of dimensionCodes) {
6671
+ const localValue = localDimensionValues[code] ?? "";
6672
+ const targetValue = targetDimensionValues[code] ?? "";
6673
+ if (localValue === targetValue) {
6674
+ continue;
6675
+ }
6676
+ const dimension = result.dimensions?.find((d) => d.entry_value === code);
6677
+ if (!dimension?.id) {
6678
+ dimensionWarnings.push(`Skipping dimension "${code}" for entry "${entry.name}": no matching dimension in target space ${space}`);
6679
+ continue;
6680
+ }
6681
+ await updateDatasourceEntryDimension(space, entryId, entry, dimension.id, localValue);
6682
+ }
6683
+ }
6598
6684
  } catch (entryError) {
6599
6685
  results.failed.push({ name: datasource.name, error: entryError });
6600
6686
  spinner.failed(`${chalk.hex(colorPalette.DATASOURCES)(datasource.name)} - Failed in ${spinner.elapsedTime.toFixed(2)}ms`);
@@ -6612,6 +6698,7 @@ pushCmd$2.action(async (datasourceName, options, command) => {
6612
6698
  }
6613
6699
  }
6614
6700
  spinner.succeed(`${chalk.hex(colorPalette.DATASOURCES)(datasource.name)} - Completed in ${spinner.elapsedTime.toFixed(2)}ms`);
6701
+ dimensionWarnings.forEach((warning) => konsola.warn(warning));
6615
6702
  } else {
6616
6703
  results.failed.push({ name: datasource.name, error: result });
6617
6704
  spinner.failed(`${chalk.hex(colorPalette.DATASOURCES)(datasource.name)} - Failed in ${spinner.elapsedTime.toFixed(2)}ms`);
@@ -7725,7 +7812,7 @@ const extractAssetSizeFromFilename = (filename) => {
7725
7812
  }
7726
7813
  try {
7727
7814
  const segments = new URL(filename).pathname.split("/");
7728
- return segments.find((segment) => /^\d+x\d+$/.test(segment));
7815
+ return segments.find((segment) => /^\d+x\d+$/i.test(segment));
7729
7816
  } catch {
7730
7817
  return void 0;
7731
7818
  }