@storyblok/migrations 0.1.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,420 @@
1
+ import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
2
+ import { extname, join } from "pathe";
3
+ import { htmlToStoryblokRichtext } from "@storyblok/richtext/html-parser";
4
+ import { markdownToStoryblokRichtext } from "@storyblok/richtext/markdown-parser";
5
+
6
+ //#region src/delete-out-of-schema-fields.ts
7
+ const SYSTEM_FIELDS = new Set([
8
+ "_uid",
9
+ "component",
10
+ "_editable"
11
+ ]);
12
+ function cleanBlok(blok, schemaDefinition, removedFields) {
13
+ const componentName = blok.component;
14
+ if (!componentName) return blok;
15
+ const schema = schemaDefinition[componentName];
16
+ if (!schema) return blok;
17
+ const validFieldSet = new Set(Object.keys(schema));
18
+ const result = {};
19
+ for (const [key, value] of Object.entries(blok)) {
20
+ if (SYSTEM_FIELDS.has(key)) {
21
+ result[key] = value;
22
+ continue;
23
+ }
24
+ const baseFieldName = key.replace(/__i18n__.*/, "");
25
+ if (!validFieldSet.has(baseFieldName)) {
26
+ removedFields.push({
27
+ component: componentName,
28
+ field: key
29
+ });
30
+ continue;
31
+ }
32
+ if (Array.isArray(value) && value.some((item) => item && typeof item === "object" && !Array.isArray(item) && item.component)) result[key] = value.map((item) => {
33
+ if (item && typeof item === "object" && !Array.isArray(item) && item.component) return cleanBlok(item, schemaDefinition, removedFields);
34
+ return item;
35
+ });
36
+ else result[key] = value;
37
+ }
38
+ return result;
39
+ }
40
+ function deleteOutOfSchemaFields(story, schemaDefinition) {
41
+ const removedFields = [];
42
+ if (!story.content) return {
43
+ story,
44
+ removedFields
45
+ };
46
+ const newContent = cleanBlok(story.content, schemaDefinition, removedFields);
47
+ return {
48
+ story: {
49
+ ...story,
50
+ content: newContent
51
+ },
52
+ removedFields
53
+ };
54
+ }
55
+
56
+ //#endregion
57
+ //#region src/local-utils.ts
58
+ async function readLocalJsonFiles(dir) {
59
+ let files;
60
+ try {
61
+ files = await readdir(dir);
62
+ } catch (error) {
63
+ if (error.code === "ENOENT") return [];
64
+ throw error;
65
+ }
66
+ const jsonFiles = files.filter((f) => extname(f) === ".json");
67
+ return await Promise.all(jsonFiles.map(async (file) => {
68
+ const filePath = join(dir, file);
69
+ const content = await readFile(filePath, "utf8");
70
+ try {
71
+ return JSON.parse(content);
72
+ } catch (error) {
73
+ throw new Error(`Failed to parse ${filePath}: ${error.message}`);
74
+ }
75
+ }));
76
+ }
77
+ async function writeLocalJsonFile(dir, filename, data) {
78
+ await mkdir(dir, { recursive: true });
79
+ await writeFile(join(dir, filename), JSON.stringify(data, void 0, 2), "utf8");
80
+ }
81
+
82
+ //#endregion
83
+ //#region src/local-assets.ts
84
+ function getAssetFilename(asset) {
85
+ return `${(asset.short_filename || String(asset.id)).replace(/\.[^.]+$/, "")}_${asset.id}.json`;
86
+ }
87
+ async function getLocalAssets(dir) {
88
+ return readLocalJsonFiles(dir);
89
+ }
90
+ async function updateLocalAsset(dir, asset) {
91
+ await writeLocalJsonFile(dir, getAssetFilename(asset), asset);
92
+ }
93
+
94
+ //#endregion
95
+ //#region src/local-components.ts
96
+ function getComponentFilename(component) {
97
+ return `${component.name}.json`;
98
+ }
99
+ async function getLocalComponents(dir) {
100
+ return readLocalJsonFiles(dir);
101
+ }
102
+ async function updateLocalComponent(dir, component) {
103
+ await writeLocalJsonFile(dir, getComponentFilename(component), component);
104
+ }
105
+
106
+ //#endregion
107
+ //#region src/local-datasources.ts
108
+ function getDatasourceFilename(datasource) {
109
+ return `${datasource.slug}_${datasource.id}.json`;
110
+ }
111
+ async function getLocalDatasources(dir) {
112
+ return readLocalJsonFiles(dir);
113
+ }
114
+ async function updateLocalDatasource(dir, datasource) {
115
+ await writeLocalJsonFile(dir, getDatasourceFilename(datasource), datasource);
116
+ }
117
+
118
+ //#endregion
119
+ //#region src/local-stories.ts
120
+ function getStoryFilename(story) {
121
+ return `${story.slug}_${story.uuid}.json`;
122
+ }
123
+ async function getLocalStories(dir) {
124
+ return readLocalJsonFiles(dir);
125
+ }
126
+ async function updateLocalStory(dir, story) {
127
+ await writeLocalJsonFile(dir, getStoryFilename(story), story);
128
+ }
129
+
130
+ //#endregion
131
+ //#region src/map-refs.ts
132
+ function isRecord(value) {
133
+ return value !== null && typeof value === "object" && !Array.isArray(value);
134
+ }
135
+ function asRecord(value) {
136
+ return isRecord(value) ? value : {};
137
+ }
138
+ function asArray(value) {
139
+ return Array.isArray(value) ? value : [];
140
+ }
141
+ const traverseAndMapBySchema = (data, { schemas, maps, fieldRefMappers, processedFields, missingSchemas }) => {
142
+ if (!isRecord(data) || typeof data.component !== "string") return data ?? {};
143
+ const schema = schemas[data.component];
144
+ if (!schema) {
145
+ missingSchemas.add(data.component);
146
+ return data;
147
+ }
148
+ const dataNew = { ...data };
149
+ for (const [fieldName, fieldValue] of Object.entries(data)) {
150
+ const fieldSchema = schema[fieldName.replace(/__i18n__.*/, "")];
151
+ const fieldType = fieldSchema && typeof fieldSchema === "object" && "type" in fieldSchema && fieldSchema.type;
152
+ const fieldRefMapper = typeof fieldType === "string" && fieldRefMappers[fieldType];
153
+ if (fieldSchema) processedFields.add(fieldSchema);
154
+ if (fieldRefMapper) dataNew[fieldName] = fieldRefMapper(fieldValue, {
155
+ schema: fieldSchema,
156
+ schemas,
157
+ maps,
158
+ fieldRefMappers,
159
+ processedFields,
160
+ missingSchemas
161
+ });
162
+ }
163
+ return dataNew;
164
+ };
165
+ const traverseAndMapRichtextDoc = (data, { schemas, maps, fieldRefMappers, processedFields, missingSchemas }) => {
166
+ if (Array.isArray(data)) return data.map((item) => traverseAndMapRichtextDoc(item, {
167
+ schemas,
168
+ maps,
169
+ fieldRefMappers,
170
+ processedFields,
171
+ missingSchemas
172
+ }));
173
+ if (isRecord(data)) {
174
+ if (data.type === "link" && asRecord(data.attrs).linktype === "story") return {
175
+ ...data,
176
+ attrs: {
177
+ ...asRecord(data.attrs),
178
+ uuid: maps.stories?.get(asRecord(data.attrs).uuid) ?? asRecord(data.attrs).uuid
179
+ }
180
+ };
181
+ if (data.type === "blok") return {
182
+ ...data,
183
+ attrs: {
184
+ ...asRecord(data.attrs),
185
+ body: asArray(asRecord(data.attrs).body).map((d) => traverseAndMapBySchema(d, {
186
+ schemas,
187
+ maps,
188
+ fieldRefMappers,
189
+ processedFields,
190
+ missingSchemas
191
+ }))
192
+ }
193
+ };
194
+ const newData = {};
195
+ for (const [k, value] of Object.entries(data)) newData[k] = traverseAndMapRichtextDoc(value, {
196
+ schemas,
197
+ maps,
198
+ fieldRefMappers,
199
+ processedFields,
200
+ missingSchemas
201
+ });
202
+ return newData;
203
+ }
204
+ return data;
205
+ };
206
+ const richtextFieldRefMapper = (data, { schemas, maps, fieldRefMappers, processedFields, missingSchemas }) => traverseAndMapRichtextDoc(data, {
207
+ schemas,
208
+ maps,
209
+ fieldRefMappers,
210
+ processedFields,
211
+ missingSchemas
212
+ });
213
+ const multilinkFieldRefMapper = (data, { maps }) => {
214
+ if (!isRecord(data) || data.linktype !== "story") return data;
215
+ return {
216
+ ...data,
217
+ id: maps.stories?.get(data.id) ?? data.id
218
+ };
219
+ };
220
+ const bloksFieldRefMapper = (data, { schemas, maps, fieldRefMappers, processedFields, missingSchemas }) => {
221
+ if (!Array.isArray(data)) throw new TypeError(`Invalid bloks field: expected an array, but received ${JSON.stringify(data)}.`);
222
+ return data.map((d) => traverseAndMapBySchema(d, {
223
+ schemas,
224
+ maps,
225
+ fieldRefMappers,
226
+ processedFields,
227
+ missingSchemas
228
+ }));
229
+ };
230
+ const assetFieldRefMapper = (data, { maps }) => {
231
+ if (!isRecord(data)) return data;
232
+ const newId = typeof data.id === "number" ? maps.assets?.get(data.id) : void 0;
233
+ return newId === void 0 ? data : {
234
+ ...data,
235
+ id: newId
236
+ };
237
+ };
238
+ const multiassetFieldRefMapper = (data, options) => {
239
+ if (!Array.isArray(data)) throw new TypeError(`Invalid multiasset field: expected an array, but received ${JSON.stringify(data)}.`);
240
+ return data.map((d) => assetFieldRefMapper(d, options));
241
+ };
242
+ const optionsFieldRefMapper = (data, { schema, maps }) => {
243
+ if (!Array.isArray(data)) return data;
244
+ const sourceMap = {
245
+ internal_stories: maps.stories,
246
+ internal_users: maps.users,
247
+ internal_tags: maps.tags,
248
+ internal_datasources: maps.datasources
249
+ }[schema.source ?? ""];
250
+ if (!sourceMap) return data;
251
+ return data.map((d) => sourceMap.get(d) ?? d);
252
+ };
253
+ const fieldRefMappers = {
254
+ asset: assetFieldRefMapper,
255
+ bloks: bloksFieldRefMapper,
256
+ multiasset: multiassetFieldRefMapper,
257
+ multilink: multilinkFieldRefMapper,
258
+ options: optionsFieldRefMapper,
259
+ richtext: richtextFieldRefMapper
260
+ };
261
+ function mapRefs(story, options) {
262
+ const { schemas, maps } = options;
263
+ const processedFields = /* @__PURE__ */ new Set();
264
+ const missingSchemas = /* @__PURE__ */ new Set();
265
+ const alternates = story.alternates ? story.alternates.map((alternate) => {
266
+ const mappedAlternate = asRecord(alternate);
267
+ return {
268
+ ...mappedAlternate,
269
+ id: maps.stories?.get(mappedAlternate.id) ?? mappedAlternate.id,
270
+ parent_id: maps.stories?.get(mappedAlternate.parent_id) ?? mappedAlternate.parent_id
271
+ };
272
+ }) : story.alternates;
273
+ const parentId = maps.stories?.get(story.parent_id) ?? story.parent_id;
274
+ const mappedContentRaw = story.content?.component ? traverseAndMapBySchema(story.content, {
275
+ schemas,
276
+ maps,
277
+ fieldRefMappers,
278
+ processedFields,
279
+ missingSchemas
280
+ }) : story.content;
281
+ return {
282
+ mappedStory: {
283
+ ...story,
284
+ content: mappedContentRaw,
285
+ id: Number(maps.stories?.get(story.id) ?? story.id),
286
+ uuid: String(maps.stories?.get(story.uuid) ?? story.uuid),
287
+ parent_id: parentId != null ? Number(parentId) : null,
288
+ alternates
289
+ },
290
+ processedFields,
291
+ missingSchemas
292
+ };
293
+ }
294
+
295
+ //#endregion
296
+ //#region src/rename-datasource-value.ts
297
+ function traverseRichtext(data, componentsToUpdate, oldValue, newValue, changes, path) {
298
+ if (Array.isArray(data)) return data.map((item, index) => traverseRichtext(item, componentsToUpdate, oldValue, newValue, changes, `${path}[${index}]`));
299
+ if (data && typeof data === "object" && !Array.isArray(data)) {
300
+ const record = data;
301
+ if (record.type === "blok" && record.attrs && typeof record.attrs === "object") {
302
+ const attrs = record.attrs;
303
+ if (Array.isArray(attrs.body)) return {
304
+ ...record,
305
+ attrs: {
306
+ ...attrs,
307
+ body: attrs.body.map((item, index) => {
308
+ if (item && typeof item === "object" && !Array.isArray(item)) return traverseObject(item, componentsToUpdate, oldValue, newValue, changes, `${path}.attrs.body[${index}]`);
309
+ return item;
310
+ })
311
+ }
312
+ };
313
+ }
314
+ const result = {};
315
+ for (const [key, value] of Object.entries(record)) result[key] = traverseRichtext(value, componentsToUpdate, oldValue, newValue, changes, `${path}.${key}`);
316
+ return result;
317
+ }
318
+ return data;
319
+ }
320
+ function traverseObject(obj, componentsToUpdate, oldValue, newValue, changes, path) {
321
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
322
+ const result = { ...obj };
323
+ const componentName = obj.component;
324
+ if (componentName) for (const { field, name } of componentsToUpdate) {
325
+ if (name !== componentName) continue;
326
+ const fieldValue = result[field];
327
+ if (typeof fieldValue === "string" && fieldValue === oldValue) {
328
+ result[field] = newValue;
329
+ changes.push({
330
+ component: componentName,
331
+ field,
332
+ path: `${path}.${field}`
333
+ });
334
+ } else if (Array.isArray(fieldValue)) result[field] = fieldValue.map((item) => {
335
+ if (item === oldValue) {
336
+ changes.push({
337
+ component: componentName,
338
+ field,
339
+ path: `${path}.${field}[]`
340
+ });
341
+ return newValue;
342
+ }
343
+ return item;
344
+ });
345
+ }
346
+ for (const [key, value] of Object.entries(result)) if (Array.isArray(value)) result[key] = value.map((item, index) => {
347
+ if (item && typeof item === "object" && !Array.isArray(item)) return traverseObject(item, componentsToUpdate, oldValue, newValue, changes, `${path}.${key}[${index}]`);
348
+ return item;
349
+ });
350
+ else if (value && typeof value === "object" && !Array.isArray(value) && value.type === "doc" && Array.isArray(value.content)) result[key] = traverseRichtext(value, componentsToUpdate, oldValue, newValue, changes, `${path}.${key}`);
351
+ return result;
352
+ }
353
+ function renameDataSourceValue(story, componentsToUpdate, oldValue, newValue) {
354
+ const changes = [];
355
+ const newContent = traverseObject(story.content, componentsToUpdate, oldValue, newValue, changes, "content");
356
+ return {
357
+ story: {
358
+ ...story,
359
+ content: newContent
360
+ },
361
+ changes
362
+ };
363
+ }
364
+
365
+ //#endregion
366
+ //#region src/url-to-asset.ts
367
+ function urlToAsset(url, options) {
368
+ return {
369
+ fieldtype: "asset",
370
+ id: 0,
371
+ filename: url,
372
+ src: url,
373
+ name: url.split("/").at(-1) || url,
374
+ alt: null,
375
+ title: null,
376
+ copyright: null,
377
+ focus: null,
378
+ meta_data: {},
379
+ source: null,
380
+ is_external_url: true,
381
+ is_private: false,
382
+ updated_at: "",
383
+ width: null,
384
+ height: null,
385
+ aspect_ratio: null,
386
+ public_id: null,
387
+ content_type: "",
388
+ ...options
389
+ };
390
+ }
391
+
392
+ //#endregion
393
+ //#region src/url-to-link.ts
394
+ function urlToLink(url, options) {
395
+ if (url.startsWith("mailto:")) return {
396
+ fieldtype: "multilink",
397
+ id: "",
398
+ url: "",
399
+ cached_url: "",
400
+ linktype: "email",
401
+ email: url.slice(7),
402
+ ...options
403
+ };
404
+ const hashIndex = url.indexOf("#");
405
+ const anchor = hashIndex === -1 ? void 0 : url.slice(hashIndex + 1);
406
+ const cleanUrl = hashIndex === -1 ? url : url.slice(0, hashIndex);
407
+ return {
408
+ fieldtype: "multilink",
409
+ id: "",
410
+ url: cleanUrl,
411
+ cached_url: cleanUrl,
412
+ linktype: "url",
413
+ ...anchor ? { anchor } : {},
414
+ ...options
415
+ };
416
+ }
417
+
418
+ //#endregion
419
+ export { deleteOutOfSchemaFields, getLocalAssets, getLocalComponents, getLocalDatasources, getLocalStories, htmlToStoryblokRichtext, mapRefs, markdownToStoryblokRichtext, renameDataSourceValue, updateLocalAsset, updateLocalComponent, updateLocalDatasource, updateLocalStory, urlToAsset, urlToLink };
420
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/delete-out-of-schema-fields.ts","../src/local-utils.ts","../src/local-assets.ts","../src/local-components.ts","../src/local-datasources.ts","../src/local-stories.ts","../src/map-refs.ts","../src/rename-datasource-value.ts","../src/url-to-asset.ts","../src/url-to-link.ts"],"sourcesContent":["import type { Story } from '@storyblok/management-api-client/resources/stories';\n\nimport type { ComponentSchemas } from './map-refs';\n\nconst SYSTEM_FIELDS = new Set(['_uid', 'component', '_editable']);\n\ninterface RemovedField {\n component: string;\n field: string;\n}\n\nfunction cleanBlok(\n blok: Record<string, unknown>,\n schemaDefinition: ComponentSchemas,\n removedFields: RemovedField[],\n): Record<string, unknown> {\n const componentName = blok.component as string | undefined;\n if (!componentName) {\n return blok;\n }\n\n const schema = schemaDefinition[componentName];\n if (!schema) {\n // Unknown component — leave untouched\n return blok;\n }\n\n const validFieldSet = new Set(Object.keys(schema));\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(blok)) {\n // Always keep system fields\n if (SYSTEM_FIELDS.has(key)) {\n result[key] = value;\n continue;\n }\n\n // Strip i18n suffix to get base field name\n const baseFieldName = key.replace(/__i18n__.*/, '');\n\n // Field not in schema — remove it\n if (!validFieldSet.has(baseFieldName)) {\n removedFields.push({ component: componentName, field: key });\n continue;\n }\n\n // Check if this is an array of bloks (objects with component property)\n const isBlokArray\n = Array.isArray(value)\n && value.some(\n item =>\n item\n && typeof item === 'object'\n && !Array.isArray(item)\n && (item as Record<string, unknown>).component,\n );\n\n if (isBlokArray) {\n // Traverse blok arrays and process nested bloks recursively\n result[key] = (value as unknown[]).map((item) => {\n if (\n item\n && typeof item === 'object'\n && !Array.isArray(item)\n && (item as Record<string, unknown>).component\n ) {\n return cleanBlok(\n item as Record<string, unknown>,\n schemaDefinition,\n removedFields,\n );\n }\n return item;\n });\n }\n else {\n // Valid field — keep it\n result[key] = value;\n }\n }\n\n return result;\n}\n\nexport function deleteOutOfSchemaFields(\n story: Story,\n schemaDefinition: ComponentSchemas,\n): { story: Story; removedFields: RemovedField[] } {\n const removedFields: RemovedField[] = [];\n\n if (!story.content) {\n return { story, removedFields };\n }\n\n const newContent = cleanBlok(\n story.content as Record<string, unknown>,\n schemaDefinition,\n removedFields,\n );\n\n return {\n // cleanBlok returns Record<string,unknown>; runtime shape satisfies Blok\n story: { ...story, content: newContent as unknown as Story['content'] },\n removedFields,\n };\n}\n","import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';\nimport { extname, join } from 'pathe';\n\nexport async function readLocalJsonFiles<T>(dir: string): Promise<T[]> {\n let files: string[];\n try {\n files = await readdir(dir);\n }\n catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n\n const jsonFiles = files.filter(f => extname(f) === '.json');\n\n const items = await Promise.all(\n jsonFiles.map(async (file) => {\n const filePath = join(dir, file);\n const content = await readFile(filePath, 'utf8');\n try {\n return JSON.parse(content) as T;\n }\n catch (error: unknown) {\n throw new Error(\n `Failed to parse ${filePath}: ${(error as Error).message}`,\n );\n }\n }),\n );\n\n return items;\n}\n\nexport async function writeLocalJsonFile(\n dir: string,\n filename: string,\n data: unknown,\n): Promise<void> {\n await mkdir(dir, { recursive: true });\n const filePath = join(dir, filename);\n await writeFile(filePath, JSON.stringify(data, undefined, 2), 'utf8');\n}\n","import type { Asset } from '@storyblok/management-api-client/resources/assets';\n\nimport { readLocalJsonFiles, writeLocalJsonFile } from './local-utils';\n\nfunction getAssetFilename(asset: Pick<Asset, 'id' | 'short_filename'>): string {\n const name = (asset.short_filename || String(asset.id)).replace(\n /\\.[^.]+$/,\n '',\n ); // strip extension\n return `${name}_${asset.id}.json`;\n}\n\nexport async function getLocalAssets(dir: string): Promise<Asset[]> {\n return readLocalJsonFiles<Asset>(dir);\n}\n\nexport async function updateLocalAsset(\n dir: string,\n asset: Asset,\n): Promise<void> {\n await writeLocalJsonFile(dir, getAssetFilename(asset), asset);\n}\n","import type { Component } from '@storyblok/management-api-client/resources/components';\n\nimport { readLocalJsonFiles, writeLocalJsonFile } from './local-utils';\n\nfunction getComponentFilename(component: Pick<Component, 'name'>): string {\n return `${component.name}.json`;\n}\n\nexport async function getLocalComponents(dir: string): Promise<Component[]> {\n return readLocalJsonFiles<Component>(dir);\n}\n\nexport async function updateLocalComponent(\n dir: string,\n component: Component,\n): Promise<void> {\n await writeLocalJsonFile(dir, getComponentFilename(component), component);\n}\n","import type { Datasource } from '@storyblok/management-api-client/resources/datasources';\n\nimport { readLocalJsonFiles, writeLocalJsonFile } from './local-utils';\n\nfunction getDatasourceFilename(\n datasource: Pick<Datasource, 'slug' | 'id'>,\n): string {\n return `${datasource.slug}_${datasource.id}.json`;\n}\n\nexport async function getLocalDatasources(dir: string): Promise<Datasource[]> {\n return readLocalJsonFiles<Datasource>(dir);\n}\n\nexport async function updateLocalDatasource(\n dir: string,\n datasource: Datasource,\n): Promise<void> {\n await writeLocalJsonFile(dir, getDatasourceFilename(datasource), datasource);\n}\n\nexport type { Datasource };\n","import type { Story } from '@storyblok/management-api-client/resources/stories';\n\nimport { readLocalJsonFiles, writeLocalJsonFile } from './local-utils';\n\nfunction getStoryFilename(story: Pick<Story, 'slug' | 'uuid'>): string {\n return `${story.slug}_${story.uuid}.json`;\n}\n\nexport async function getLocalStories(dir: string): Promise<Story[]> {\n return readLocalJsonFiles<Story>(dir);\n}\n\nexport async function updateLocalStory(\n dir: string,\n story: Story,\n): Promise<void> {\n await writeLocalJsonFile(dir, getStoryFilename(story), story);\n}\n","import type { Component } from '@storyblok/management-api-client/resources/components';\nimport type { Story } from '@storyblok/management-api-client/resources/stories';\n\nexport interface RefMaps {\n assets?: Map<unknown, string | number>;\n stories?: Map<unknown, string | number>;\n users?: Map<unknown, string | number>;\n tags?: Map<unknown, string | number>;\n datasources?: Map<unknown, string | number>;\n}\n\nexport type ComponentSchemas = Record<\n string,\n Record<string, { type: string; source?: string }>\n>;\n\nexport interface MapRefsOptions {\n schemas: ComponentSchemas;\n maps: RefMaps;\n}\n\ntype ProcessedFields = Set<Component['schema']>;\ntype MissingSchemas = Set<Component['name']>;\ntype UnknownRecord = Record<string, unknown>;\n\ntype RefMapper = (\n data: unknown,\n options: {\n schema: Component['schema'];\n schemas: ComponentSchemas;\n maps: RefMaps;\n fieldRefMappers: FieldRefMappers;\n processedFields: ProcessedFields;\n missingSchemas: MissingSchemas;\n },\n) => unknown;\n\ntype FieldRefMappers = Record<string, RefMapper>;\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction asRecord(value: unknown): UnknownRecord {\n return isRecord(value) ? value : {};\n}\n\nfunction asArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nconst traverseAndMapBySchema = (\n data: unknown,\n {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n }: {\n schemas: ComponentSchemas;\n maps: RefMaps;\n fieldRefMappers: FieldRefMappers;\n processedFields: ProcessedFields;\n missingSchemas: MissingSchemas;\n },\n): unknown => {\n if (!isRecord(data) || typeof data.component !== 'string') {\n return data ?? {};\n }\n\n const schema = schemas[data.component];\n if (!schema) {\n missingSchemas.add(data.component);\n return data;\n }\n\n const dataNew: UnknownRecord = { ...data };\n\n for (const [fieldName, fieldValue] of Object.entries(data)) {\n const fieldSchema = schema[\n fieldName.replace(/__i18n__.*/, '')\n ] as Component['schema'];\n const fieldType\n = fieldSchema\n && typeof fieldSchema === 'object'\n && 'type' in fieldSchema\n && fieldSchema.type;\n const fieldRefMapper\n = typeof fieldType === 'string' && fieldRefMappers[fieldType];\n\n if (fieldSchema) {\n processedFields.add(fieldSchema);\n }\n\n if (fieldRefMapper) {\n dataNew[fieldName] = fieldRefMapper(fieldValue, {\n schema: fieldSchema,\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n });\n }\n }\n\n return dataNew;\n};\n\nconst traverseAndMapRichtextDoc = (\n data: unknown,\n {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n }: {\n schemas: ComponentSchemas;\n maps: RefMaps;\n fieldRefMappers: FieldRefMappers;\n processedFields: ProcessedFields;\n missingSchemas: MissingSchemas;\n },\n): unknown => {\n if (Array.isArray(data)) {\n return data.map(item =>\n traverseAndMapRichtextDoc(item, {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n }),\n );\n }\n\n if (isRecord(data)) {\n if (data.type === 'link' && asRecord(data.attrs).linktype === 'story') {\n return {\n ...data,\n attrs: {\n ...asRecord(data.attrs),\n uuid:\n maps.stories?.get(asRecord(data.attrs).uuid)\n ?? asRecord(data.attrs).uuid,\n },\n };\n }\n\n if (data.type === 'blok') {\n return {\n ...data,\n attrs: {\n ...asRecord(data.attrs),\n body: asArray(asRecord(data.attrs).body).map(d =>\n traverseAndMapBySchema(d, {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n }),\n ),\n },\n };\n }\n\n const newData: UnknownRecord = {};\n for (const [k, value] of Object.entries(data)) {\n newData[k] = traverseAndMapRichtextDoc(value, {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n });\n }\n\n return newData;\n }\n\n return data;\n};\n\nconst richtextFieldRefMapper: RefMapper = (\n data,\n { schemas, maps, fieldRefMappers, processedFields, missingSchemas },\n) =>\n traverseAndMapRichtextDoc(data, {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n });\n\nconst multilinkFieldRefMapper: RefMapper = (data, { maps }) => {\n if (!isRecord(data) || data.linktype !== 'story') {\n return data;\n }\n\n return {\n ...data,\n id: maps.stories?.get(data.id) ?? data.id,\n };\n};\n\nconst bloksFieldRefMapper: RefMapper = (\n data,\n { schemas, maps, fieldRefMappers, processedFields, missingSchemas },\n) => {\n if (!Array.isArray(data)) {\n throw new TypeError(\n `Invalid bloks field: expected an array, but received ${JSON.stringify(data)}.`,\n );\n }\n\n return data.map(d =>\n traverseAndMapBySchema(d, {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n }),\n );\n};\n\nconst assetFieldRefMapper: RefMapper = (data, { maps }) => {\n if (!isRecord(data)) {\n return data;\n }\n\n const newId\n = typeof data.id === 'number' ? maps.assets?.get(data.id) : undefined;\n return newId === undefined ? data : { ...data, id: newId };\n};\n\nconst multiassetFieldRefMapper: RefMapper = (data, options) => {\n if (!Array.isArray(data)) {\n throw new TypeError(\n `Invalid multiasset field: expected an array, but received ${JSON.stringify(data)}.`,\n );\n }\n\n return data.map(d => assetFieldRefMapper(d, options));\n};\n\nconst optionsFieldRefMapper: RefMapper = (data, { schema, maps }) => {\n if (!Array.isArray(data)) {\n return data;\n }\n\n const sourceMapBySchema: Record<\n string,\n Map<unknown, string | number> | undefined\n > = {\n internal_stories: maps.stories,\n internal_users: maps.users,\n internal_tags: maps.tags,\n internal_datasources: maps.datasources,\n };\n\n const sourceMap\n = sourceMapBySchema[(schema as { source?: string }).source ?? ''];\n if (!sourceMap) {\n return data;\n }\n\n return data.map(d => sourceMap.get(d) ?? d);\n};\n\nconst fieldRefMappers = {\n asset: assetFieldRefMapper,\n bloks: bloksFieldRefMapper,\n multiasset: multiassetFieldRefMapper,\n multilink: multilinkFieldRefMapper,\n options: optionsFieldRefMapper,\n richtext: richtextFieldRefMapper,\n} as const;\n\nexport function mapRefs(\n story: Story,\n options: MapRefsOptions,\n): {\n mappedStory: Story;\n processedFields: ProcessedFields;\n missingSchemas: MissingSchemas;\n } {\n const { schemas, maps } = options;\n const processedFields: ProcessedFields = new Set();\n const missingSchemas: MissingSchemas = new Set();\n\n const alternatesRaw = story.alternates\n ? (story.alternates as Required<Story>['alternates']).map((alternate) => {\n const mappedAlternate = asRecord(alternate);\n return {\n ...mappedAlternate,\n id: maps.stories?.get(mappedAlternate.id) ?? mappedAlternate.id,\n parent_id:\n maps.stories?.get(mappedAlternate.parent_id)\n ?? mappedAlternate.parent_id,\n };\n })\n : story.alternates;\n // mapped ids may be string|number at runtime but shape is compatible\n const alternates = alternatesRaw as Story['alternates'];\n\n const parentId = maps.stories?.get(story.parent_id) ?? story.parent_id;\n const mappedContentRaw = story.content?.component\n ? traverseAndMapBySchema(story.content, {\n schemas,\n maps,\n fieldRefMappers,\n processedFields,\n missingSchemas,\n })\n : story.content;\n\n const mappedStory = {\n ...story,\n // traverseAndMapBySchema returns unknown; runtime shape satisfies Blok\n content: mappedContentRaw as unknown as Story['content'],\n id: Number(maps.stories?.get(story.id) ?? story.id),\n uuid: String(maps.stories?.get(story.uuid) ?? story.uuid),\n parent_id: parentId != null ? Number(parentId) : null,\n alternates,\n } satisfies Story;\n\n return {\n mappedStory,\n processedFields,\n missingSchemas,\n };\n}\n","import type { Story } from '@storyblok/management-api-client/resources/stories';\n\ninterface ComponentToUpdate {\n field: string;\n name: string;\n}\n\ninterface Change {\n component: string;\n field: string;\n path: string;\n}\n\nfunction traverseRichtext(\n data: unknown,\n componentsToUpdate: ComponentToUpdate[],\n oldValue: string,\n newValue: string,\n changes: Change[],\n path: string,\n): unknown {\n if (Array.isArray(data)) {\n return data.map((item, index) =>\n traverseRichtext(item, componentsToUpdate, oldValue, newValue, changes, `${path}[${index}]`),\n );\n }\n\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n const record = data as Record<string, unknown>;\n\n if (record.type === 'blok' && record.attrs && typeof record.attrs === 'object') {\n const attrs = record.attrs as Record<string, unknown>;\n if (Array.isArray(attrs.body)) {\n return {\n ...record,\n attrs: {\n ...attrs,\n body: attrs.body.map((item: unknown, index: number) => {\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n return traverseObject(\n item as Record<string, unknown>,\n componentsToUpdate,\n oldValue,\n newValue,\n changes,\n `${path}.attrs.body[${index}]`,\n );\n }\n return item;\n }),\n },\n };\n }\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(record)) {\n result[key] = traverseRichtext(value, componentsToUpdate, oldValue, newValue, changes, `${path}.${key}`);\n }\n return result;\n }\n\n return data;\n}\n\nfunction traverseObject(\n obj: Record<string, unknown>,\n componentsToUpdate: ComponentToUpdate[],\n oldValue: string,\n newValue: string,\n changes: Change[],\n path: string,\n): Record<string, unknown> {\n if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {\n return obj;\n }\n\n const result = { ...obj };\n const componentName = obj.component as string | undefined;\n\n if (componentName) {\n for (const { field, name } of componentsToUpdate) {\n if (name !== componentName) {\n continue;\n }\n\n const fieldValue = result[field];\n\n if (typeof fieldValue === 'string' && fieldValue === oldValue) {\n result[field] = newValue;\n changes.push({\n component: componentName,\n field,\n path: `${path}.${field}`,\n });\n }\n else if (Array.isArray(fieldValue)) {\n const newArray = fieldValue.map((item) => {\n if (item === oldValue) {\n changes.push({\n component: componentName,\n field,\n path: `${path}.${field}[]`,\n });\n return newValue;\n }\n return item;\n });\n result[field] = newArray;\n }\n }\n }\n\n // Traverse nested arrays (bloks fields) and richtext fields\n for (const [key, value] of Object.entries(result)) {\n if (Array.isArray(value)) {\n result[key] = value.map((item, index) => {\n if (item && typeof item === 'object' && !Array.isArray(item)) {\n return traverseObject(\n item as Record<string, unknown>,\n componentsToUpdate,\n oldValue,\n newValue,\n changes,\n `${path}.${key}[${index}]`,\n );\n }\n return item;\n });\n }\n else if (\n value\n && typeof value === 'object'\n && !Array.isArray(value)\n && (value as Record<string, unknown>).type === 'doc'\n && Array.isArray((value as Record<string, unknown>).content)\n ) {\n result[key] = traverseRichtext(value, componentsToUpdate, oldValue, newValue, changes, `${path}.${key}`);\n }\n }\n\n return result;\n}\n\nexport function renameDataSourceValue(\n story: Story,\n componentsToUpdate: ComponentToUpdate[],\n oldValue: string,\n newValue: string,\n): { story: Story; changes: Change[] } {\n const changes: Change[] = [];\n\n const newContent = traverseObject(\n story.content as Record<string, unknown>,\n componentsToUpdate,\n oldValue,\n newValue,\n changes,\n 'content',\n );\n\n return {\n // traverseObject returns Record<string,unknown>; runtime shape satisfies Blok\n story: { ...story, content: newContent as unknown as Story['content'] },\n changes,\n };\n}\n","import type { StoryblokAsset } from './types';\n\nexport interface UrlToAssetOptions {\n alt?: string | null;\n title?: string | null;\n copyright?: string | null;\n focus?: string | null;\n}\n\nexport function urlToAsset(\n url: string,\n options?: UrlToAssetOptions,\n): StoryblokAsset {\n // Derive name from last path segment\n const pathSegments = url.split('/');\n const name = pathSegments.at(-1) || url;\n\n return {\n fieldtype: 'asset',\n id: 0,\n filename: url,\n src: url,\n name,\n alt: null,\n title: null,\n copyright: null,\n focus: null,\n meta_data: {},\n source: null,\n is_external_url: true,\n is_private: false,\n updated_at: '',\n width: null,\n height: null,\n aspect_ratio: null,\n public_id: null,\n content_type: '',\n ...options,\n };\n}\n","import type { StoryblokMultilink } from './types';\n\nexport interface UrlToLinkOptions {\n target?: '_blank' | '_self';\n title?: string;\n rel?: string;\n anchor?: string;\n}\n\nexport function urlToLink(\n url: string,\n options?: UrlToLinkOptions,\n): StoryblokMultilink {\n // Detect mailto: links\n if (url.startsWith('mailto:')) {\n return {\n fieldtype: 'multilink',\n id: '',\n url: '',\n cached_url: '',\n linktype: 'email',\n email: url.slice('mailto:'.length),\n ...options,\n };\n }\n\n // Extract anchor from fragment\n const hashIndex = url.indexOf('#');\n const anchor = hashIndex === -1 ? undefined : url.slice(hashIndex + 1);\n const cleanUrl = hashIndex === -1 ? url : url.slice(0, hashIndex);\n\n return {\n fieldtype: 'multilink',\n id: '',\n url: cleanUrl,\n cached_url: cleanUrl,\n linktype: 'url',\n ...(anchor ? { anchor } : {}),\n ...options,\n };\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@storyblok/migrations",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "private": false,
6
+ "description": "Migration utilities for Storyblok",
7
+ "author": "Storyblok",
8
+ "license": "MIT",
9
+ "homepage": "https://github.com/storyblok/monoblok/tree/main/packages/migrations#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/storyblok/monoblok.git",
13
+ "directory": "packages/migrations"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/storyblok/monoblok/issues"
17
+ },
18
+ "keywords": [
19
+ "storyblok",
20
+ "migrations",
21
+ "content",
22
+ "cms",
23
+ "headless",
24
+ "schema",
25
+ "data-migration"
26
+ ],
27
+ "sideEffects": false,
28
+ "exports": {
29
+ ".": {
30
+ "import": "./dist/index.mjs",
31
+ "require": "./dist/index.cjs"
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "main": "./dist/index.cjs",
36
+ "module": "./dist/index.mjs",
37
+ "types": "./dist/index.d.cts",
38
+ "files": [
39
+ "dist"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "dependencies": {
45
+ "pathe": "^2.0.3",
46
+ "@storyblok/management-api-client": "0.2.0",
47
+ "@storyblok/richtext": "4.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^22.15.18",
51
+ "@vitest/coverage-v8": "^3.1.3",
52
+ "eslint": "^9.26.0",
53
+ "jiti": "^2.4.2",
54
+ "tsdown": "^0.20.3",
55
+ "typescript": "5.8.3",
56
+ "vitest": "^3.1.3",
57
+ "@storyblok/eslint-config": "0.5.0"
58
+ },
59
+ "scripts": {
60
+ "build": "tsdown",
61
+ "dev": "vitest dev",
62
+ "play": "jiti playground",
63
+ "lint": "eslint .",
64
+ "lint:fix": "eslint . --fix",
65
+ "test": "pnpm lint && pnpm test:types && vitest run --coverage",
66
+ "test:unit": "vitest",
67
+ "test:unit:ci": "vitest run",
68
+ "test:types": "tsc --noEmit --skipLibCheck",
69
+ "coverage": "vitest run --coverage"
70
+ }
71
+ }