@artinstack/migrator 0.1.1 → 0.1.3

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 +0,0 @@
1
- {"version":3,"sources":["../src/parsers/wordpress/parse-wxr.ts","../src/parsers/wordpress/index.ts","../src/parsers/smugmug/api.ts","../src/parsers/smugmug/parse-node.ts","../src/parsers/smugmug/index.ts","../src/parsers/squarespace/index.ts","../src/parsers/index.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { XMLParser } from \"fast-xml-parser\";\n\nimport { discoverContentAssetUrls } from \"../../lib/content-asset-urls.js\";\nimport { linkToPath, sanitizeSlug } from \"../../lib/utility.js\";\nimport type {\n NormalizedAsset,\n NormalizedCategory,\n NormalizedEntity,\n NormalizedPage,\n NormalizedPost,\n NormalizedTag,\n PublishStatus,\n SourceMetadata,\n} from \"../../normalizer/types.js\";\n\nconst PLATFORM = \"wordpress\" as const;\n\nexport interface WxrParseOptions {\n filePath: string;\n exportedAt?: string;\n}\n\ninterface WxrItem {\n title?: string;\n link?: string;\n encoded?: string;\n post_id?: string | number;\n post_date?: string;\n post_name?: string;\n status?: string;\n post_type?: string;\n attachment_url?: string;\n postmeta?: WxrPostMeta | WxrPostMeta[];\n category?: WxrCategory | WxrCategory[];\n}\n\ninterface WxrPostMeta {\n meta_key?: string;\n meta_value?: string | number;\n}\n\ninterface WxrCategory {\n \"@_domain\"?: string;\n \"@_nicename\"?: string;\n \"#text\"?: string;\n}\n\ninterface AttachmentIndexEntry {\n sourceUrl: string;\n filename: string;\n mimeType?: string;\n title?: string;\n}\n\nfunction asArray<T>(value: T | T[] | undefined): T[] {\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\nfunction textValue(value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\" || typeof value === \"number\") return String(value);\n if (typeof value === \"object\" && value !== null && \"#text\" in value) {\n return String((value as { \"#text\": unknown })[\"#text\"] ?? \"\");\n }\n return String(value);\n}\n\nfunction mapPublishStatus(wpStatus: string | undefined): PublishStatus {\n switch ((wpStatus ?? \"\").toLowerCase()) {\n case \"publish\":\n return \"published\";\n case \"draft\":\n case \"pending\":\n return \"draft\";\n default:\n return \"archived\";\n }\n}\n\nfunction getContentEncoded(item: WxrItem): string {\n const content = (item as { content?: { encoded?: string } | string }).content;\n if (content !== undefined) {\n if (typeof content === \"string\") return content;\n return textValue(content.encoded);\n }\n return textValue(item.encoded);\n}\n\nfunction sourceMeta(id: string, link?: string, exportedAt?: string): SourceMetadata {\n return {\n platform: PLATFORM,\n id,\n url: link || undefined,\n path: linkToPath(link),\n exportedAt,\n };\n}\n\nfunction getExcerpt(item: WxrItem): string {\n const excerpt = (item as { excerpt?: { encoded?: string } | string }).excerpt;\n if (!excerpt) return \"\";\n if (typeof excerpt === \"string\") return excerpt;\n return textValue(excerpt.encoded);\n}\n\nfunction getPostMeta(item: WxrItem, key: string): string | undefined {\n for (const meta of asArray(item.postmeta)) {\n if (textValue(meta.meta_key) === key) {\n return textValue(meta.meta_value);\n }\n }\n return undefined;\n}\n\nfunction parseItems(xml: string): WxrItem[] {\n const parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n removeNSPrefix: true,\n trimValues: false,\n parseTagValue: false,\n });\n\n const doc = parser.parse(xml) as {\n rss?: { channel?: { item?: WxrItem | WxrItem[] } };\n };\n\n return asArray(doc.rss?.channel?.item);\n}\n\nfunction buildAttachmentIndex(items: WxrItem[]): Map<string, AttachmentIndexEntry> {\n const index = new Map<string, AttachmentIndexEntry>();\n\n for (const item of items) {\n if (textValue(item.post_type) !== \"attachment\") continue;\n const id = textValue(item.post_id);\n const url = textValue(item.attachment_url) || textValue(item.link);\n if (!id || !url) continue;\n\n const filename = basename(new URL(url, \"http://local.invalid\").pathname) || `attachment-${id}`;\n index.set(id, {\n sourceUrl: url,\n filename,\n mimeType: getPostMeta(item, \"_wp_attached_file\") ? undefined : guessMime(filename),\n title: textValue(item.title),\n });\n }\n\n return index;\n}\n\nfunction guessMime(filename: string): string | undefined {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const map: Record<string, string> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n pdf: \"application/pdf\",\n };\n return ext ? map[ext] : undefined;\n}\n\nfunction collectTaxonomies(items: WxrItem[]): {\n categories: Map<string, NormalizedCategory>;\n tags: Map<string, NormalizedTag>;\n} {\n const categories = new Map<string, NormalizedCategory>();\n const tags = new Map<string, NormalizedTag>();\n\n for (const item of items) {\n const postType = textValue(item.post_type);\n if (postType !== \"post\" && postType !== \"page\") continue;\n\n for (const cat of asArray(item.category)) {\n const domain = cat[\"@_domain\"] ?? \"\";\n const nicename = sanitizeSlug(cat[\"@_nicename\"] ?? textValue(cat[\"#text\"]));\n const name = textValue(cat[\"#text\"]) || nicename;\n if (!nicename) continue;\n\n if (domain === \"category\") {\n if (!categories.has(nicename)) {\n categories.set(nicename, {\n type: \"category\",\n source: sourceMeta(`cat:${nicename}`),\n sourceId: `cat:${nicename}`,\n name,\n slug: nicename,\n });\n }\n } else if (domain === \"post_tag\") {\n if (!tags.has(nicename)) {\n tags.set(nicename, {\n type: \"tag\",\n source: sourceMeta(`tag:${nicename}`),\n sourceId: `tag:${nicename}`,\n name,\n slug: nicename,\n });\n }\n }\n }\n }\n\n return { categories, tags };\n}\n\nfunction collectInlineAssets(\n html: string,\n attachmentIndex: Map<string, AttachmentIndexEntry>,\n seenUrls: Set<string>,\n exportedAt?: string,\n): NormalizedAsset[] {\n const assets: NormalizedAsset[] = [];\n for (const src of discoverContentAssetUrls(html)) {\n if (seenUrls.has(src)) continue;\n seenUrls.add(src);\n\n let filename: string;\n try {\n filename = basename(new URL(src, \"http://local.invalid\").pathname) || \"inline-asset\";\n } catch {\n filename = \"inline-asset\";\n }\n\n assets.push({\n type: \"asset\",\n source: sourceMeta(`url:${src}`, src, exportedAt),\n sourceId: `url:${src}`,\n sourceUrl: src,\n filename,\n mimeType: guessMime(filename),\n });\n }\n\n // Resolve attachment-index URLs referenced in content if not already seen\n for (const [id, entry] of attachmentIndex) {\n if (seenUrls.has(entry.sourceUrl)) continue;\n // Only auto-include attachments referenced via wp-content in posts is handled by inline src\n void id;\n }\n\n return assets;\n}\n\nexport async function* enumerateWxrEntities(\n options: WxrParseOptions,\n): AsyncGenerator<NormalizedEntity> {\n const xml = await readFile(options.filePath, \"utf8\");\n const items = parseItems(xml);\n const attachmentIndex = buildAttachmentIndex(items);\n const { categories, tags } = collectTaxonomies(items);\n const seenAssetUrls = new Set<string>();\n const emittedAttachmentIds = new Set<string>();\n\n for (const category of categories.values()) {\n yield category;\n }\n for (const tag of tags.values()) {\n yield tag;\n }\n\n // Emit attachment assets\n for (const [id, entry] of attachmentIndex) {\n emittedAttachmentIds.add(id);\n seenAssetUrls.add(entry.sourceUrl);\n yield {\n type: \"asset\",\n source: sourceMeta(id, entry.sourceUrl, options.exportedAt),\n sourceId: id,\n sourceUrl: entry.sourceUrl,\n filename: entry.filename,\n mimeType: entry.mimeType,\n caption: entry.title,\n } satisfies NormalizedAsset;\n }\n\n for (const item of items) {\n const postType = textValue(item.post_type);\n if (postType !== \"post\" && postType !== \"page\") continue;\n\n const id = textValue(item.post_id);\n const link = textValue(item.link);\n const slug = sanitizeSlug(textValue(item.post_name) || textValue(item.title) || id);\n const rawHtml = getContentEncoded(item);\n\n for (const asset of collectInlineAssets(\n rawHtml,\n attachmentIndex,\n seenAssetUrls,\n options.exportedAt,\n )) {\n yield asset;\n }\n\n const categorySlugs: string[] = [];\n const tagSlugs: string[] = [];\n for (const cat of asArray(item.category)) {\n const domain = cat[\"@_domain\"] ?? \"\";\n const nicename = sanitizeSlug(cat[\"@_nicename\"] ?? textValue(cat[\"#text\"]));\n if (!nicename) continue;\n if (domain === \"category\") categorySlugs.push(nicename);\n if (domain === \"post_tag\") tagSlugs.push(nicename);\n }\n\n if (postType === \"post\") {\n const thumbnailId = getPostMeta(item, \"_thumbnail_id\");\n let featuredAssetSourceId: string | undefined;\n if (thumbnailId && attachmentIndex.has(thumbnailId)) {\n featuredAssetSourceId = thumbnailId;\n }\n\n const post: NormalizedPost = {\n type: \"post\",\n source: sourceMeta(id, link, options.exportedAt),\n sourceId: id,\n title: textValue(item.title) || slug,\n slug,\n excerpt: getExcerpt(item) || undefined,\n contentHtml: rawHtml,\n publishedAt: textValue(item.post_date) || undefined,\n status: mapPublishStatus(textValue(item.status)),\n categorySlugs: categorySlugs.length ? categorySlugs : undefined,\n tagSlugs: tagSlugs.length ? tagSlugs : undefined,\n sourceFeaturedMediaId: thumbnailId,\n featuredAssetSourceId,\n };\n yield post;\n } else {\n const isHomePage =\n getPostMeta(item, \"_wp_show_on_front\") === \"1\" ||\n getPostMeta(item, \"page_on_front\") === \"1\";\n\n const page: NormalizedPage = {\n type: \"page\",\n source: sourceMeta(id, link, options.exportedAt),\n sourceId: id,\n title: textValue(item.title) || slug,\n slug,\n contentHtml: rawHtml,\n isHomePage: isHomePage || undefined,\n status: mapPublishStatus(textValue(item.status)),\n };\n yield page;\n }\n }\n}\n\nexport async function validateWxrFile(filePath: string): Promise<{\n ok: boolean;\n issues: { code: string; message: string }[];\n summary: Record<string, number>;\n}> {\n const issues: { code: string; message: string }[] = [];\n let xml: string;\n try {\n xml = await readFile(filePath, \"utf8\");\n } catch {\n return {\n ok: false,\n issues: [{ code: \"file_not_found\", message: `Cannot read file: ${filePath}` }],\n summary: {},\n };\n }\n\n const looksLikeWxr =\n xml.includes(\"<rss\") &&\n (xml.includes(\"wp:wxr_version\") ||\n xml.includes(\"xmlns:wp=\") ||\n xml.includes(\"WordPress eXtended RSS\"));\n if (!looksLikeWxr) {\n issues.push({ code: \"invalid_wxr\", message: \"File does not appear to be WordPress WXR\" });\n }\n\n const items = parseItems(xml);\n const summary = {\n posts: items.filter((i) => textValue(i.post_type) === \"post\").length,\n pages: items.filter((i) => textValue(i.post_type) === \"page\").length,\n assets: items.filter((i) => textValue(i.post_type) === \"attachment\").length,\n portfolios: 0,\n categories: 0,\n tags: 0,\n };\n\n const { categories, tags } = collectTaxonomies(items);\n summary.categories = categories.size;\n summary.tags = tags.size;\n\n return { ok: issues.length === 0, issues, summary };\n}\n","import type { AdapterContext, MigrationAdapter, ValidationResult } from \"../../normalizer/types.js\";\nimport { enumerateWxrEntities, validateWxrFile } from \"./parse-wxr.js\";\n\nfunction resolvePath(input: unknown): string {\n if (typeof input === \"string\") return input;\n if (input && typeof input === \"object\" && \"path\" in input) {\n return String((input as { path: string }).path);\n }\n throw new Error(\"WordPress adapter requires input path (string or { path })\");\n}\n\nexport const wordpressAdapter: MigrationAdapter = {\n platform: \"wordpress\",\n\n async validateInput(input: unknown): Promise<ValidationResult> {\n const path = resolvePath(input);\n const result = await validateWxrFile(path);\n return {\n ok: result.ok,\n issues: result.issues,\n summary: result.summary,\n };\n },\n\n enumerateEntities(ctx: AdapterContext) {\n const path = resolvePath(ctx.input);\n return enumerateWxrEntities({ filePath: path });\n },\n};\n","import { createHmac, randomBytes } from \"node:crypto\";\n\nimport { z } from \"zod\";\n\nimport type { SmugMugFlatAlbum, SmugMugFlatExport, SmugMugFlatFolder, SmugMugFlatImage } from \"./types.js\";\n\n/** SmugMug API v2 base (OAuth 1.0a). No secrets — inject credentials at runtime. */\nexport const SMUGMUG_API_HOST = \"api.smugmug.com\";\nexport const SMUGMUG_API_BASE = `https://${SMUGMUG_API_HOST}/api/v2`;\n\nexport const SMUGMUG_OAUTH_ENDPOINTS = {\n requestToken: \"https://api.smugmug.com/services/oauth/1.0a/getRequestToken\",\n authorize: \"https://api.smugmug.com/services/oauth/1.0a/authorize\",\n accessToken: \"https://api.smugmug.com/services/oauth/1.0a/getAccessToken\",\n} as const;\n\nexport const smugMugCredentialsSchema = z.object({\n consumerKey: z.string().min(1),\n consumerSecret: z.string().min(1),\n accessToken: z.string().min(1),\n accessTokenSecret: z.string().min(1),\n});\n\nexport type SmugMugCredentials = z.infer<typeof smugMugCredentialsSchema>;\n\nexport const smugMugClientOptionsSchema = z.object({\n credentials: smugMugCredentialsSchema,\n pageSize: z.number().int().min(1).max(500).default(100),\n maxRetries: z.number().int().min(0).max(10).default(3),\n retryBaseDelayMs: z.number().int().min(0).default(500),\n maxRetryDelayMs: z.number().int().min(0).default(8000),\n requestIntervalMs: z.number().int().min(0).default(200),\n fetchImpl: z.custom<typeof fetch>().optional(),\n});\n\nexport type SmugMugClientOptions = z.input<typeof smugMugClientOptionsSchema>;\n\nconst ALBUM_IMAGES_CONFIG = {\n expand: {\n AlbumImage: {\n expand: {\n Image: {\n filter: [\"FileName\", \"Caption\", \"KeywordsArray\"],\n filteruri: [\"ImageMetadata\", \"ImageSizeDetails\"],\n expand: {\n ImageMetadata: {\n filter: [\"ISO\", \"Aperture\", \"ApertureValue\", \"ShutterSpeed\", \"ExposureTime\", \"FocalLength\"],\n },\n ImageSizeDetails: {\n filter: [\"OriginalImageUrl\"],\n },\n },\n },\n },\n },\n },\n};\n\ninterface SmugMugPages {\n Total?: number;\n Start?: number;\n Count?: number;\n NextPage?: string;\n}\n\ninterface SmugMugApiEnvelope<T> {\n Response: T & { Pages?: SmugMugPages; Uri?: string };\n Code: number;\n Message: string;\n}\n\ninterface SmugMugUserWire {\n NickName?: string;\n Uri: string;\n Uris: { Node: string };\n}\n\ninterface SmugMugNodeWire {\n NodeID: string;\n Type: \"Folder\" | \"Album\" | \"Page\" | string;\n Name: string;\n Description?: string;\n UrlName?: string;\n WebUri?: string;\n Uri: string;\n Uris?: { Album?: string; ChildNodes?: string };\n}\n\ninterface SmugMugImageMetadataWire {\n ISO?: number | string;\n Aperture?: number | string;\n ApertureValue?: number | string;\n ShutterSpeed?: string;\n ExposureTime?: string;\n FocalLength?: number | string;\n}\n\ninterface SmugMugImageWire {\n FileName?: string;\n Caption?: string;\n KeywordsArray?: string[];\n ImageMetadata?: SmugMugImageMetadataWire;\n ImageSizeDetails?: { OriginalImageUrl?: string };\n}\n\ninterface SmugMugAlbumImageWire {\n ImageKey: string;\n Caption?: string;\n FileName?: string;\n WebUri?: string;\n Image?: SmugMugImageWire;\n LargestImage?: { Url?: string };\n ImageMetadata?: SmugMugImageMetadataWire;\n}\n\n/** RFC 3986 encoding used by OAuth 1.0a parameter normalization. */\nexport function oauthPercentEncode(value: string): string {\n return encodeURIComponent(value).replace(/[!'()*]/g, (char) =>\n `%${char.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n}\n\nfunction normalizeRequestUrl(url: URL): string {\n const protocol = url.protocol.replace(/:$/, \"\").toLowerCase();\n const host = url.hostname.toLowerCase();\n const defaultPort = protocol === \"http\" ? \"80\" : \"443\";\n const port = url.port && url.port !== defaultPort ? `:${url.port}` : \"\";\n return `${protocol}://${host}${port}${url.pathname}`;\n}\n\nfunction sortedParameterString(params: Record<string, string>): string {\n return Object.keys(params)\n .sort((a, b) => (a === b ? 0 : a < b ? -1 : 1))\n .map((key) => `${oauthPercentEncode(key)}=${oauthPercentEncode(params[key]!)}`)\n .join(\"&\");\n}\n\nfunction collectSignatureParams(\n url: URL,\n oauthParams: Record<string, string>,\n bodyParams?: Record<string, string>,\n): Record<string, string> {\n const params: Record<string, string> = { ...oauthParams };\n url.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n if (bodyParams) {\n for (const [key, value] of Object.entries(bodyParams)) {\n params[key] = value;\n }\n }\n return params;\n}\n\n/** Build OAuth 1.0a HMAC-SHA1 signature for a SmugMug API request. */\nexport function signSmugMugOAuthRequest(input: {\n method: string;\n url: string;\n credentials: SmugMugCredentials;\n oauthParams: Record<string, string>;\n bodyParams?: Record<string, string>;\n}): string {\n const url = new URL(input.url);\n const parameterString = sortedParameterString(\n collectSignatureParams(url, input.oauthParams, input.bodyParams),\n );\n const signatureBase = [\n input.method.toUpperCase(),\n oauthPercentEncode(normalizeRequestUrl(url)),\n oauthPercentEncode(parameterString),\n ].join(\"&\");\n const signingKey = `${oauthPercentEncode(input.credentials.consumerSecret)}&${oauthPercentEncode(input.credentials.accessTokenSecret)}`;\n return createHmac(\"sha1\", signingKey).update(signatureBase).digest(\"base64\");\n}\n\nfunction buildOAuthParams(credentials: SmugMugCredentials, nonce: string, timestamp: string) {\n return {\n oauth_consumer_key: credentials.consumerKey,\n oauth_token: credentials.accessToken,\n oauth_signature_method: \"HMAC-SHA1\",\n oauth_timestamp: timestamp,\n oauth_nonce: nonce,\n oauth_version: \"1.0\",\n };\n}\n\nexport function buildSmugMugAuthorizationHeader(input: {\n method: string;\n url: string;\n credentials: SmugMugCredentials;\n nonce?: string;\n timestamp?: string;\n bodyParams?: Record<string, string>;\n}): string {\n const nonce = input.nonce ?? randomBytes(16).toString(\"hex\");\n const timestamp = input.timestamp ?? String(Math.floor(Date.now() / 1000));\n const oauthParams = buildOAuthParams(input.credentials, nonce, timestamp);\n const signature = signSmugMugOAuthRequest({\n method: input.method,\n url: input.url,\n credentials: input.credentials,\n oauthParams,\n bodyParams: input.bodyParams,\n });\n const headerParams = { ...oauthParams, oauth_signature: signature };\n const headerValue = Object.keys(headerParams)\n .sort()\n .map((key) => `${oauthPercentEncode(key)}=\"${oauthPercentEncode(headerParams[key as keyof typeof headerParams]!)}\"`)\n .join(\", \");\n return `OAuth ${headerValue}`;\n}\n\nexport function readSmugMugCredentialsFromEnv(\n env: Record<string, string | undefined> = process.env,\n): SmugMugCredentials {\n return smugMugCredentialsSchema.parse({\n consumerKey: env.SMUGMUG_CONSUMER_KEY,\n consumerSecret: env.SMUGMUG_CONSUMER_SECRET,\n accessToken: env.SMUGMUG_ACCESS_TOKEN,\n accessTokenSecret: env.SMUGMUG_ACCESS_TOKEN_SECRET,\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction albumKeyFromUri(uri: string): string {\n const match = uri.match(/\\/album\\/([^/?!]+)/i);\n if (!match?.[1]) {\n throw new Error(`Unable to parse album key from URI: ${uri}`);\n }\n return match[1];\n}\n\nfunction nodeIdFromUri(uri: string): string {\n const match = uri.match(/\\/node\\/([^/?!]+)/i);\n if (!match?.[1]) {\n throw new Error(`Unable to parse node id from URI: ${uri}`);\n }\n return match[1];\n}\n\nfunction mapAlbumImage(\n albumImage: SmugMugAlbumImageWire,\n portfolioSourceId: string,\n sort: number,\n): SmugMugFlatImage {\n const image = albumImage.Image;\n const metadata = image?.ImageMetadata ?? albumImage.ImageMetadata;\n const originalUrl =\n image?.ImageSizeDetails?.OriginalImageUrl ?? albumImage.LargestImage?.Url ?? albumImage.WebUri;\n const fileName = image?.FileName ?? albumImage.FileName;\n return {\n sourceId: albumImage.ImageKey,\n portfolioSourceId,\n sort,\n fileName,\n originalUrl,\n caption: albumImage.Caption ?? image?.Caption,\n keywords: image?.KeywordsArray?.length ? image.KeywordsArray : undefined,\n exif: metadata\n ? {\n iso: metadata.ISO,\n aperture: metadata.Aperture ?? metadata.ApertureValue,\n shutter: metadata.ShutterSpeed ?? metadata.ExposureTime,\n focalLength: metadata.FocalLength,\n }\n : undefined,\n };\n}\n\n/** Signed SmugMug API client — recursively discovers folders, albums, and images. */\nexport class SmugMugApiClient {\n readonly credentials: SmugMugCredentials;\n readonly pageSize: number;\n readonly maxRetries: number;\n readonly retryBaseDelayMs: number;\n readonly maxRetryDelayMs: number;\n readonly requestIntervalMs: number;\n readonly fetchImpl: typeof fetch;\n\n private lastRequestAt = 0;\n\n constructor(options: SmugMugClientOptions) {\n const parsed = smugMugClientOptionsSchema.parse(options);\n this.credentials = parsed.credentials;\n this.pageSize = parsed.pageSize;\n this.maxRetries = parsed.maxRetries;\n this.retryBaseDelayMs = parsed.retryBaseDelayMs;\n this.maxRetryDelayMs = parsed.maxRetryDelayMs;\n this.requestIntervalMs = parsed.requestIntervalMs;\n this.fetchImpl = parsed.fetchImpl ?? fetch;\n }\n\n /** Validate credentials against `GET /user/!authuser`. */\n async validateCredentials(): Promise<{ nick?: string; rootNodeUri: string }> {\n const user = await this.getAuthUser();\n return { nick: user.NickName, rootNodeUri: user.Uris.Node };\n }\n\n /** Crawl the authenticated user's node tree into flat export tables for `parse-node.ts`. */\n async crawlExport(): Promise<SmugMugFlatExport> {\n const user = await this.getAuthUser();\n const folders: SmugMugFlatFolder[] = [];\n const albums: SmugMugFlatAlbum[] = [];\n const images: SmugMugFlatImage[] = [];\n\n await this.walkNode(user.Uris.Node, undefined, folders, albums, images);\n\n return {\n exportVersion: 1,\n exportedAt: new Date().toISOString(),\n Folders: folders,\n Albums: albums,\n Images: images,\n };\n }\n\n private async getAuthUser(): Promise<SmugMugUserWire> {\n const envelope = await this.requestJson<SmugMugUserWire>(`${SMUGMUG_API_BASE}/user/!authuser`);\n return envelope.Response;\n }\n\n private async walkNode(\n nodeUri: string,\n parentFolderId: string | undefined,\n folders: SmugMugFlatFolder[],\n albums: SmugMugFlatAlbum[],\n images: SmugMugFlatImage[],\n ): Promise<void> {\n const childrenPath = `${nodeUri}!children`;\n for await (const child of this.paginateNodes(childrenPath)) {\n if (child.Type === \"Page\") continue;\n\n if (child.Type === \"Folder\") {\n folders.push({\n sourceId: child.NodeID,\n name: child.Name,\n parentSourceId: parentFolderId,\n slug: child.UrlName,\n description: child.Description,\n });\n await this.walkNode(child.Uri, child.NodeID, folders, albums, images);\n continue;\n }\n\n if (child.Type === \"Album\") {\n albums.push({\n sourceId: child.NodeID,\n name: child.Name,\n parentSourceId: parentFolderId,\n slug: child.UrlName,\n description: child.Description,\n url: child.WebUri,\n });\n const albumUri = child.Uris?.Album;\n if (albumUri) {\n await this.collectAlbumImages(albumUri, child.NodeID, images);\n }\n }\n }\n }\n\n private async collectAlbumImages(\n albumUri: string,\n portfolioSourceId: string,\n images: SmugMugFlatImage[],\n ): Promise<void> {\n const albumKey = albumKeyFromUri(albumUri);\n const configQuery = `_config=${encodeURIComponent(JSON.stringify(ALBUM_IMAGES_CONFIG))}`;\n const initialPath = `${SMUGMUG_API_BASE}/album/${albumKey}!images?${configQuery}`;\n\n let sort = 0;\n for await (const albumImage of this.paginateAlbumImages(initialPath)) {\n images.push(mapAlbumImage(albumImage, portfolioSourceId, sort));\n sort += 1;\n }\n }\n\n private async *paginateNodes(path: string): AsyncGenerator<SmugMugNodeWire> {\n for await (const page of this.paginate<{ Node?: SmugMugNodeWire[] }>(path)) {\n for (const node of page.Node ?? []) {\n yield node;\n }\n }\n }\n\n private async *paginateAlbumImages(path: string): AsyncGenerator<SmugMugAlbumImageWire> {\n for await (const page of this.paginate<{ AlbumImage?: SmugMugAlbumImageWire[] }>(path)) {\n for (const albumImage of page.AlbumImage ?? []) {\n yield albumImage;\n }\n }\n }\n\n private async *paginate<T extends Record<string, unknown>>(\n initialPath: string,\n ): AsyncGenerator<T> {\n let nextPath: string | undefined = appendPagination(initialPath, this.pageSize, 1);\n while (nextPath) {\n const envelope: SmugMugApiEnvelope<T> = await this.requestJson<T>(nextPath);\n yield envelope.Response;\n nextPath = envelope.Response.Pages?.NextPage;\n }\n }\n\n private async requestJson<T>(pathOrUrl: string): Promise<SmugMugApiEnvelope<T>> {\n const url = toAbsoluteUrl(pathOrUrl);\n const response = await this.requestWithRetry(url);\n const body = (await response.json()) as SmugMugApiEnvelope<T>;\n if (body.Code !== 200) {\n throw new Error(`SmugMug API error ${body.Code}: ${body.Message}`);\n }\n return body;\n }\n\n private async requestWithRetry(url: URL): Promise<Response> {\n let attempt = 0;\n while (true) {\n await this.throttle();\n const authorization = buildSmugMugAuthorizationHeader({\n method: \"GET\",\n url: url.toString(),\n credentials: this.credentials,\n });\n const response = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n Authorization: authorization,\n },\n });\n\n if (response.ok) {\n return response;\n }\n\n const retryable = response.status === 429 || response.status >= 500;\n if (!retryable || attempt >= this.maxRetries) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `SmugMug HTTP ${response.status}${detail ? `: ${detail.slice(0, 200)}` : \"\"}`,\n );\n }\n\n const retryAfter = Number.parseInt(response.headers.get(\"retry-after\") ?? \"\", 10);\n const delay = Number.isFinite(retryAfter)\n ? retryAfter * 1000\n : Math.min(this.maxRetryDelayMs, this.retryBaseDelayMs * 2 ** attempt);\n await sleep(delay);\n attempt += 1;\n }\n }\n\n private async throttle(): Promise<void> {\n if (this.requestIntervalMs <= 0) return;\n const elapsed = Date.now() - this.lastRequestAt;\n if (elapsed < this.requestIntervalMs) {\n await sleep(this.requestIntervalMs - elapsed);\n }\n this.lastRequestAt = Date.now();\n }\n}\n\nfunction toAbsoluteUrl(pathOrUrl: string): URL {\n if (pathOrUrl.startsWith(\"http://\") || pathOrUrl.startsWith(\"https://\")) {\n return new URL(pathOrUrl);\n }\n if (pathOrUrl.startsWith(\"/\")) {\n return new URL(`https://${SMUGMUG_API_HOST}${pathOrUrl}`);\n }\n return new URL(pathOrUrl);\n}\n\nfunction appendPagination(pathOrUrl: string, count: number, start: number): string {\n const url = toAbsoluteUrl(pathOrUrl);\n url.searchParams.set(\"count\", String(count));\n url.searchParams.set(\"start\", String(start));\n return url.toString();\n}\n\n/** @internal Exported for crawl tests — resolves root node id from user node URI. */\nexport function smugMugRootNodeIdFromUserNodeUri(nodeUri: string): string {\n return nodeIdFromUri(nodeUri);\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport { sanitizeSlug } from \"../../lib/utility.js\";\nimport type {\n NormalizedAsset,\n NormalizedAssetExif,\n NormalizedEntity,\n NormalizedPortfolio,\n SourceMetadata,\n} from \"../../normalizer/types.js\";\nimport { SmugMugApiClient, type SmugMugClientOptions, type SmugMugCredentials } from \"./api.js\";\nimport type {\n SmugMugExportDocument,\n SmugMugFlatExport,\n SmugMugFlatImage,\n SmugMugMockAlbum,\n SmugMugMockExport,\n SmugMugMockFolder,\n} from \"./types.js\";\n\nconst PLATFORM = \"smugmug\" as const;\nconst UNRESOLVED_URL_PREFIX = \"unspecified://smugmug/\";\n\nexport interface SmugMugParseOptions {\n filePath?: string;\n data?: SmugMugExportDocument;\n /** Pre-constructed signed API client (live crawl). */\n client?: SmugMugApiClient;\n /** OAuth credentials — builds a client when `client` is omitted. */\n credentials?: SmugMugCredentials;\n /** Optional tuning for credential-backed client. */\n clientOptions?: Omit<SmugMugClientOptions, \"credentials\">;\n}\n\nfunction sourceMeta(id: string, url?: string, exportedAt?: string): SourceMetadata {\n return {\n platform: PLATFORM,\n id,\n url,\n exportedAt,\n };\n}\n\nfunction guessMime(filename: string): string | undefined {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const map: Record<string, string> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n tif: \"image/tiff\",\n tiff: \"image/tiff\",\n };\n return ext ? map[ext] : undefined;\n}\n\nfunction parseExifNumber(value: number | string | undefined): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n const parsed = Number.parseFloat(String(value).replace(/[^0-9.]/g, \"\"));\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction normalizeExif(\n exif: SmugMugFlatImage[\"exif\"] | SmugMugMockAlbum[\"images\"][0][\"exif\"],\n): NormalizedAssetExif | undefined {\n if (!exif || Object.keys(exif).length === 0) return undefined;\n const normalized: NormalizedAssetExif = {\n iso: parseExifNumber(exif.iso),\n aperture: parseExifNumber(exif.aperture),\n shutter: exif.shutter,\n focalLength: parseExifNumber(exif.focalLength),\n };\n if (\n normalized.iso === undefined &&\n normalized.aperture === undefined &&\n !normalized.shutter &&\n normalized.focalLength === undefined\n ) {\n return undefined;\n }\n return normalized;\n}\n\nexport function isSmugMugFlatExport(value: unknown): value is SmugMugFlatExport {\n if (!value || typeof value !== \"object\") return false;\n const record = value as SmugMugFlatExport;\n const version = record.exportVersion;\n return (\n (version === 1 || version === \"1\") &&\n Array.isArray(record.Folders) &&\n Array.isArray(record.Albums) &&\n Array.isArray(record.Images)\n );\n}\n\nfunction isSmugMugNestedExport(value: unknown): value is SmugMugMockExport {\n if (!value || typeof value !== \"object\") return false;\n const record = value as SmugMugMockExport;\n const version = record.exportVersion;\n return (version === 1 || version === \"1\") && Array.isArray(record.folders);\n}\n\nexport async function loadSmugMugExport(options: SmugMugParseOptions): Promise<SmugMugExportDocument> {\n if (options.data) return options.data;\n if (!options.filePath) {\n throw new Error(\"SmugMug parser requires filePath or data\");\n }\n const raw: unknown = JSON.parse(await readFile(options.filePath, \"utf8\"));\n if (isSmugMugFlatExport(raw) || isSmugMugNestedExport(raw)) {\n return raw;\n }\n throw new Error(\n \"Invalid SmugMug export: expected exportVersion 1 with folders[] (nested) or Folders/Albums/Images (flat)\",\n );\n}\n\nfunction resolveAssetUrl(image: SmugMugFlatImage): string {\n if (image.originalUrl) return image.originalUrl;\n return `${UNRESOLVED_URL_PREFIX}${image.sourceId}`;\n}\n\nfunction resolveFilename(image: SmugMugFlatImage): string {\n if (image.fileName) return image.fileName;\n return `${image.sourceId}.jpg`;\n}\n\nfunction* emitNestedFolderPortfolio(\n folder: SmugMugMockFolder,\n exportedAt?: string,\n): Generator<NormalizedPortfolio> {\n yield {\n type: \"portfolio\",\n source: sourceMeta(folder.id, undefined, exportedAt),\n sourceId: folder.id,\n title: folder.name,\n slug: sanitizeSlug(folder.slug ?? folder.name),\n description: folder.description,\n };\n}\n\nfunction* emitNestedAlbumPortfolio(\n folder: SmugMugMockFolder,\n album: SmugMugMockAlbum,\n exportedAt?: string,\n): Generator<NormalizedPortfolio> {\n yield {\n type: \"portfolio\",\n source: sourceMeta(album.id, album.url, exportedAt),\n sourceId: album.id,\n title: album.name,\n slug: sanitizeSlug(album.slug ?? album.name),\n description: album.description,\n parentSourceId: folder.id,\n };\n}\n\nfunction* emitNestedAlbumAssets(\n album: SmugMugMockAlbum,\n exportedAt?: string,\n): Generator<NormalizedAsset> {\n for (let index = 0; index < album.images.length; index++) {\n const image = album.images[index]!;\n yield {\n type: \"asset\",\n source: sourceMeta(image.id, image.originalUrl, exportedAt),\n sourceId: image.id,\n sourceUrl: image.originalUrl,\n filename: image.fileName,\n mimeType: guessMime(image.fileName),\n caption: image.caption,\n keywords: image.keywords?.length ? image.keywords : undefined,\n exif: normalizeExif(image.exif),\n portfolioSourceId: album.id,\n sort: index,\n };\n }\n}\n\nasync function* enumerateNestedExport(\n doc: SmugMugMockExport,\n): AsyncGenerator<NormalizedEntity> {\n const exportedAt = doc.exportedAt;\n for (const folder of doc.folders) {\n yield* emitNestedFolderPortfolio(folder, exportedAt);\n for (const album of folder.albums) {\n yield* emitNestedAlbumPortfolio(folder, album, exportedAt);\n yield* emitNestedAlbumAssets(album, exportedAt);\n }\n }\n}\n\nasync function* enumerateFlatExport(doc: SmugMugFlatExport): AsyncGenerator<NormalizedEntity> {\n const exportedAt = doc.exportedAt;\n\n for (const folder of doc.Folders) {\n yield {\n type: \"portfolio\",\n source: sourceMeta(folder.sourceId, undefined, exportedAt),\n sourceId: folder.sourceId,\n title: folder.name,\n slug: sanitizeSlug(folder.slug ?? folder.name),\n description: folder.description,\n parentSourceId: folder.parentSourceId,\n } satisfies NormalizedPortfolio;\n }\n\n for (const album of doc.Albums) {\n yield {\n type: \"portfolio\",\n source: sourceMeta(album.sourceId, album.url, exportedAt),\n sourceId: album.sourceId,\n title: album.name,\n slug: sanitizeSlug(album.slug ?? album.name),\n description: album.description,\n parentSourceId: album.parentSourceId,\n } satisfies NormalizedPortfolio;\n }\n\n for (const image of doc.Images) {\n const filename = resolveFilename(image);\n yield {\n type: \"asset\",\n source: sourceMeta(image.sourceId, image.originalUrl, exportedAt),\n sourceId: image.sourceId,\n sourceUrl: resolveAssetUrl(image),\n filename,\n mimeType: guessMime(filename),\n caption: image.caption,\n keywords: image.keywords?.length ? image.keywords : undefined,\n exif: normalizeExif(image.exif),\n portfolioSourceId: image.portfolioSourceId,\n sort: image.sort ?? 0,\n } satisfies NormalizedAsset;\n }\n}\n\nasync function resolveSmugMugDocument(options: SmugMugParseOptions): Promise<SmugMugExportDocument> {\n if (options.data) return options.data;\n if (options.client) return options.client.crawlExport();\n if (options.credentials) {\n const client = new SmugMugApiClient({ credentials: options.credentials, ...options.clientOptions });\n return client.crawlExport();\n }\n return loadSmugMugExport(options);\n}\n\n/** Walk discovered SmugMug nodes — fixture JSON or live API crawl via injected credentials. */\nexport async function* enumerateSmugMugEntities(\n options: SmugMugParseOptions,\n): AsyncGenerator<NormalizedEntity> {\n const doc = await resolveSmugMugDocument(options);\n if (isSmugMugFlatExport(doc)) {\n yield* enumerateFlatExport(doc);\n return;\n }\n yield* enumerateNestedExport(doc);\n}\n\nexport function summarizeSmugMugExport(doc: SmugMugExportDocument): {\n folders: number;\n albums: number;\n assets: number;\n portfolios: number;\n} {\n if (isSmugMugFlatExport(doc)) {\n return {\n folders: doc.Folders.length,\n albums: doc.Albums.length,\n assets: doc.Images.length,\n portfolios: doc.Folders.length + doc.Albums.length,\n };\n }\n\n const folders = doc.folders.length;\n let albums = 0;\n let assets = 0;\n for (const folder of doc.folders) {\n albums += folder.albums.length;\n for (const album of folder.albums) {\n assets += album.images.length;\n }\n }\n return {\n folders,\n albums,\n assets,\n portfolios: folders + albums,\n };\n}\n\nexport async function validateSmugMugExportFile(filePath: string): Promise<{\n ok: boolean;\n issues: { code: string; message: string }[];\n summary: Record<string, number>;\n}> {\n const issues: { code: string; message: string }[] = [];\n let doc: SmugMugExportDocument;\n try {\n doc = await loadSmugMugExport({ filePath });\n } catch (error) {\n return {\n ok: false,\n issues: [\n {\n code: \"invalid_export\",\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n summary: {},\n };\n }\n\n if (isSmugMugFlatExport(doc)) {\n if (doc.Folders.length === 0 && doc.Albums.length === 0) {\n issues.push({ code: \"empty_export\", message: \"No folders or albums in export\" });\n }\n } else if (doc.folders.length === 0) {\n issues.push({ code: \"empty_export\", message: \"No folders in export\" });\n }\n\n const summary = summarizeSmugMugExport(doc);\n return {\n ok: issues.length === 0,\n issues,\n summary: {\n portfolios: summary.portfolios,\n assets: summary.assets,\n categories: summary.folders,\n posts: 0,\n pages: 0,\n tags: 0,\n },\n };\n}\n\n/** @deprecated Use validateSmugMugExportFile */\nexport const validateSmugMugMockFile = validateSmugMugExportFile;\n","import type { AdapterContext, MigrationAdapter, ValidationResult } from \"../../normalizer/types.js\";\nimport type { SmugMugClientOptions } from \"./api.js\";\nimport {\n SmugMugApiClient,\n readSmugMugCredentialsFromEnv,\n smugMugCredentialsSchema,\n} from \"./api.js\";\nimport {\n enumerateSmugMugEntities,\n summarizeSmugMugExport,\n validateSmugMugExportFile,\n} from \"./parse-node.js\";\nimport type { SmugMugExportDocument } from \"./types.js\";\n\ninterface SmugMugParseInput {\n path?: string;\n data?: SmugMugExportDocument;\n credentials?: ReturnType<typeof smugMugCredentialsSchema.parse>;\n client?: SmugMugApiClient;\n clientOptions?: Omit<SmugMugClientOptions, \"credentials\">;\n /** When true, read SMUGMUG_* env vars for live API crawl (no file path required). */\n live?: boolean;\n}\n\nfunction resolveInput(input: unknown): SmugMugParseInput {\n if (typeof input === \"string\") return { path: input };\n if (input && typeof input === \"object\") {\n const record = input as SmugMugParseInput;\n if (record.client || record.credentials || record.live) return record;\n if (record.data) return { data: record.data };\n if (record.path) return { path: record.path };\n }\n throw new Error(\n \"SmugMug adapter requires input path (string or { path }), { data }, { credentials }, { client }, or { live: true }\",\n );\n}\n\nfunction resolveLiveCredentials(input: SmugMugParseInput) {\n if (input.credentials) return input.credentials;\n if (input.live) return readSmugMugCredentialsFromEnv();\n return undefined;\n}\n\nexport const smugmugAdapter: MigrationAdapter = {\n platform: \"smugmug\",\n\n async validateInput(input: unknown): Promise<ValidationResult> {\n try {\n const resolved = resolveInput(input);\n const credentials = resolveLiveCredentials(resolved);\n\n if (resolved.data) {\n const summary = summarizeSmugMugExport(resolved.data);\n return {\n ok: true,\n issues: [],\n summary: {\n portfolios: summary.portfolios,\n assets: summary.assets,\n categories: summary.folders,\n posts: 0,\n pages: 0,\n tags: 0,\n },\n };\n }\n\n if (resolved.client || credentials) {\n const client =\n resolved.client ??\n new SmugMugApiClient({ credentials: credentials!, ...resolved.clientOptions });\n await client.validateCredentials();\n const doc = await client.crawlExport();\n const summary = summarizeSmugMugExport(doc);\n return {\n ok: true,\n issues: [],\n summary: {\n portfolios: summary.portfolios,\n assets: summary.assets,\n categories: summary.folders,\n posts: 0,\n pages: 0,\n tags: 0,\n },\n };\n }\n\n const result = await validateSmugMugExportFile(resolved.path!);\n return {\n ok: result.ok,\n issues: result.issues,\n summary: result.summary,\n };\n } catch (error) {\n return {\n ok: false,\n issues: [\n {\n code: \"invalid_input\",\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n },\n\n enumerateEntities(ctx: AdapterContext) {\n const resolved = resolveInput(ctx.input);\n const credentials = resolveLiveCredentials(resolved);\n return enumerateSmugMugEntities({\n filePath: resolved.path,\n data: resolved.data,\n client: resolved.client,\n credentials,\n clientOptions: resolved.clientOptions,\n });\n },\n};\n\nexport type { SmugMugExportDocument, SmugMugFlatExport, SmugMugMockExport } from \"./types.js\";\nexport {\n SmugMugApiClient,\n SMUGMUG_API_BASE,\n SMUGMUG_OAUTH_ENDPOINTS,\n buildSmugMugAuthorizationHeader,\n oauthPercentEncode,\n readSmugMugCredentialsFromEnv,\n signSmugMugOAuthRequest,\n smugMugCredentialsSchema,\n} from \"./api.js\";\nexport type { SmugMugClientOptions, SmugMugCredentials } from \"./api.js\";\nexport {\n enumerateSmugMugEntities,\n isSmugMugFlatExport,\n loadSmugMugExport,\n summarizeSmugMugExport,\n validateSmugMugExportFile,\n validateSmugMugMockFile,\n} from \"./parse-node.js\";\n","import type { AdapterContext, MigrationAdapter, ValidationResult } from \"../../normalizer/types.js\";\nimport {\n SquarespaceCollectionClient,\n type SquarespaceClientOptions,\n type SquarespaceCollectTarget,\n} from \"./collect.js\";\nimport {\n enumerateSquarespaceEntities,\n summarizeSquarespaceExport,\n validateSquarespaceExportFile,\n} from \"./parse-export.js\";\nimport type { SquarespaceExport } from \"./types.js\";\n\ninterface SquarespaceParseInput {\n path?: string;\n data?: SquarespaceExport;\n client?: SquarespaceCollectionClient;\n collectTargets?: SquarespaceCollectTarget[];\n clientOptions?: SquarespaceClientOptions;\n}\n\nfunction resolveInput(input: unknown): SquarespaceParseInput {\n if (typeof input === \"string\") return { path: input };\n if (input && typeof input === \"object\") {\n const record = input as SquarespaceParseInput;\n if (record.client || record.collectTargets) return record;\n if (record.data) return { data: record.data };\n if (record.path) return { path: record.path };\n }\n throw new Error(\n \"Squarespace adapter requires input path (string or { path }), { data }, { client, collectTargets }, or { collectTargets }\",\n );\n}\n\nexport const squarespaceAdapter: MigrationAdapter = {\n platform: \"squarespace\",\n\n async validateInput(input: unknown): Promise<ValidationResult> {\n try {\n const resolved = resolveInput(input);\n\n if (resolved.data) {\n const summary = summarizeSquarespaceExport(resolved.data);\n return {\n ok: true,\n issues: [],\n summary: {\n pages: summary.pages,\n posts: summary.posts,\n categories: summary.categories,\n tags: summary.tags,\n },\n };\n }\n\n if (resolved.client || resolved.collectTargets?.length) {\n if (!resolved.collectTargets?.length) {\n throw new Error(\"Squarespace live validation requires collectTargets\");\n }\n const client =\n resolved.client ?? new SquarespaceCollectionClient(resolved.clientOptions);\n const doc = await client.collectExport(resolved.collectTargets);\n const summary = summarizeSquarespaceExport(doc);\n return {\n ok: true,\n issues: [],\n summary: {\n pages: summary.pages,\n posts: summary.posts,\n categories: summary.categories,\n tags: summary.tags,\n },\n };\n }\n\n const result = await validateSquarespaceExportFile(resolved.path!);\n return {\n ok: result.ok,\n issues: result.issues,\n summary: result.summary,\n };\n } catch (error) {\n return {\n ok: false,\n issues: [\n {\n code: \"invalid_input\",\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n },\n\n enumerateEntities(ctx: AdapterContext) {\n const resolved = resolveInput(ctx.input);\n return enumerateSquarespaceEntities({\n filePath: resolved.path,\n data: resolved.data,\n client: resolved.client,\n collectTargets: resolved.collectTargets,\n clientOptions: resolved.clientOptions,\n });\n },\n};\n\nexport type { SquarespaceExport } from \"./types.js\";\nexport {\n SQUARESPACE_JSON_FORMAT,\n SquarespaceCollectionClient,\n buildJsonPrettyUrl,\n extractBlocksFromBodyHtml,\n inferBlockTypeFromClassName,\n mapJsonPrettyWire,\n mergeSquarespaceExportPartials,\n squarespaceClientOptionsSchema,\n} from \"./collect.js\";\nexport type { SquarespaceClientOptions, SquarespaceCollectTarget } from \"./collect.js\";\nexport {\n SUPPORTED_BLOCK_TYPES,\n UNSUPPORTED_BLOCK_TYPES,\n enumerateSquarespaceEntities,\n findUnsupportedBlockMarkers,\n flattenSquarespaceBlock,\n flattenSquarespaceBlocks,\n isSquarespaceExport,\n loadSquarespaceExport,\n summarizeSquarespaceExport,\n validateSquarespaceExportFile,\n} from \"./parse-export.js\";\n","export { wordpressAdapter } from \"./wordpress/index.js\";\nexport {\n SmugMugApiClient,\n SMUGMUG_API_BASE,\n SMUGMUG_OAUTH_ENDPOINTS,\n buildSmugMugAuthorizationHeader,\n readSmugMugCredentialsFromEnv,\n signSmugMugOAuthRequest,\n smugmugAdapter,\n smugMugCredentialsSchema,\n} from \"./smugmug/index.js\";\nexport type { SmugMugClientOptions, SmugMugCredentials } from \"./smugmug/index.js\";\nexport { squarespaceAdapter } from \"./squarespace/index.js\";\nexport {\n SquarespaceCollectionClient,\n SQUARESPACE_JSON_FORMAT,\n buildJsonPrettyUrl,\n mapJsonPrettyWire,\n} from \"./squarespace/index.js\";\nexport type { SquarespaceClientOptions, SquarespaceCollectTarget } from \"./squarespace/index.js\";\n\nimport type { MigrationPlatform } from \"../normalizer/types.js\";\nimport { smugmugAdapter } from \"./smugmug/index.js\";\nimport { squarespaceAdapter } from \"./squarespace/index.js\";\nimport { wordpressAdapter } from \"./wordpress/index.js\";\n\nconst adapters = {\n wordpress: wordpressAdapter,\n smugmug: smugmugAdapter,\n squarespace: squarespaceAdapter,\n} as const;\n\nexport function getAdapter(platform: MigrationPlatform) {\n return adapters[platform];\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AAEzB,SAAS,iBAAiB;AAe1B,IAAM,WAAW;AAuCjB,SAAS,QAAW,OAAiC;AACnD,MAAI,UAAU,OAAW,QAAO,CAAC;AACjC,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAC9C;AAEA,SAAS,UAAU,OAAwB;AACzC,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAC/E,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,WAAW,OAAO;AACnE,WAAO,OAAQ,MAA+B,OAAO,KAAK,EAAE;AAAA,EAC9D;AACA,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,iBAAiB,UAA6C;AACrE,WAAS,YAAY,IAAI,YAAY,GAAG;AAAA,IACtC,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,kBAAkB,MAAuB;AAChD,QAAM,UAAW,KAAqD;AACtE,MAAI,YAAY,QAAW;AACzB,QAAI,OAAO,YAAY,SAAU,QAAO;AACxC,WAAO,UAAU,QAAQ,OAAO;AAAA,EAClC;AACA,SAAO,UAAU,KAAK,OAAO;AAC/B;AAEA,SAAS,WAAW,IAAY,MAAe,YAAqC;AAClF,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,KAAK,QAAQ;AAAA,IACb,MAAM,WAAW,IAAI;AAAA,IACrB;AAAA,EACF;AACF;AAEA,SAAS,WAAW,MAAuB;AACzC,QAAM,UAAW,KAAqD;AACtE,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,SAAO,UAAU,QAAQ,OAAO;AAClC;AAEA,SAAS,YAAY,MAAe,KAAiC;AACnE,aAAW,QAAQ,QAAQ,KAAK,QAAQ,GAAG;AACzC,QAAI,UAAU,KAAK,QAAQ,MAAM,KAAK;AACpC,aAAO,UAAU,KAAK,UAAU;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,KAAwB;AAC1C,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,MAAM,OAAO,MAAM,GAAG;AAI5B,SAAO,QAAQ,IAAI,KAAK,SAAS,IAAI;AACvC;AAEA,SAAS,qBAAqB,OAAqD;AACjF,QAAM,QAAQ,oBAAI,IAAkC;AAEpD,aAAW,QAAQ,OAAO;AACxB,QAAI,UAAU,KAAK,SAAS,MAAM,aAAc;AAChD,UAAM,KAAK,UAAU,KAAK,OAAO;AACjC,UAAM,MAAM,UAAU,KAAK,cAAc,KAAK,UAAU,KAAK,IAAI;AACjE,QAAI,CAAC,MAAM,CAAC,IAAK;AAEjB,UAAM,WAAW,SAAS,IAAI,IAAI,KAAK,sBAAsB,EAAE,QAAQ,KAAK,cAAc,EAAE;AAC5F,UAAM,IAAI,IAAI;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA,UAAU,YAAY,MAAM,mBAAmB,IAAI,SAAY,UAAU,QAAQ;AAAA,MACjF,OAAO,UAAU,KAAK,KAAK;AAAA,IAC7B,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,UAAU,UAAsC;AACvD,QAAM,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY;AACnD,QAAM,MAA8B;AAAA,IAClC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,EACP;AACA,SAAO,MAAM,IAAI,GAAG,IAAI;AAC1B;AAEA,SAAS,kBAAkB,OAGzB;AACA,QAAM,aAAa,oBAAI,IAAgC;AACvD,QAAM,OAAO,oBAAI,IAA2B;AAE5C,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,UAAU,KAAK,SAAS;AACzC,QAAI,aAAa,UAAU,aAAa,OAAQ;AAEhD,eAAW,OAAO,QAAQ,KAAK,QAAQ,GAAG;AACxC,YAAM,SAAS,IAAI,UAAU,KAAK;AAClC,YAAM,WAAW,aAAa,IAAI,YAAY,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC;AAC1E,YAAM,OAAO,UAAU,IAAI,OAAO,CAAC,KAAK;AACxC,UAAI,CAAC,SAAU;AAEf,UAAI,WAAW,YAAY;AACzB,YAAI,CAAC,WAAW,IAAI,QAAQ,GAAG;AAC7B,qBAAW,IAAI,UAAU;AAAA,YACvB,MAAM;AAAA,YACN,QAAQ,WAAW,OAAO,QAAQ,EAAE;AAAA,YACpC,UAAU,OAAO,QAAQ;AAAA,YACzB;AAAA,YACA,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAAA,MACF,WAAW,WAAW,YAAY;AAChC,YAAI,CAAC,KAAK,IAAI,QAAQ,GAAG;AACvB,eAAK,IAAI,UAAU;AAAA,YACjB,MAAM;AAAA,YACN,QAAQ,WAAW,OAAO,QAAQ,EAAE;AAAA,YACpC,UAAU,OAAO,QAAQ;AAAA,YACzB;AAAA,YACA,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,YAAY,KAAK;AAC5B;AAEA,SAAS,oBACP,MACA,iBACA,UACA,YACmB;AACnB,QAAM,SAA4B,CAAC;AACnC,aAAW,OAAO,yBAAyB,IAAI,GAAG;AAChD,QAAI,SAAS,IAAI,GAAG,EAAG;AACvB,aAAS,IAAI,GAAG;AAEhB,QAAI;AACJ,QAAI;AACF,iBAAW,SAAS,IAAI,IAAI,KAAK,sBAAsB,EAAE,QAAQ,KAAK;AAAA,IACxE,QAAQ;AACN,iBAAW;AAAA,IACb;AAEA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,WAAW,OAAO,GAAG,IAAI,KAAK,UAAU;AAAA,MAChD,UAAU,OAAO,GAAG;AAAA,MACpB,WAAW;AAAA,MACX;AAAA,MACA,UAAU,UAAU,QAAQ;AAAA,IAC9B,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,IAAI,KAAK,KAAK,iBAAiB;AACzC,QAAI,SAAS,IAAI,MAAM,SAAS,EAAG;AAEnC,SAAK;AAAA,EACP;AAEA,SAAO;AACT;AAEA,gBAAuB,qBACrB,SACkC;AAClC,QAAM,MAAM,MAAM,SAAS,QAAQ,UAAU,MAAM;AACnD,QAAM,QAAQ,WAAW,GAAG;AAC5B,QAAM,kBAAkB,qBAAqB,KAAK;AAClD,QAAM,EAAE,YAAY,KAAK,IAAI,kBAAkB,KAAK;AACpD,QAAM,gBAAgB,oBAAI,IAAY;AACtC,QAAM,uBAAuB,oBAAI,IAAY;AAE7C,aAAW,YAAY,WAAW,OAAO,GAAG;AAC1C,UAAM;AAAA,EACR;AACA,aAAW,OAAO,KAAK,OAAO,GAAG;AAC/B,UAAM;AAAA,EACR;AAGA,aAAW,CAAC,IAAI,KAAK,KAAK,iBAAiB;AACzC,yBAAqB,IAAI,EAAE;AAC3B,kBAAc,IAAI,MAAM,SAAS;AACjC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,IAAI,MAAM,WAAW,QAAQ,UAAU;AAAA,MAC1D,UAAU;AAAA,MACV,WAAW,MAAM;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,IACjB;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,UAAU,KAAK,SAAS;AACzC,QAAI,aAAa,UAAU,aAAa,OAAQ;AAEhD,UAAM,KAAK,UAAU,KAAK,OAAO;AACjC,UAAM,OAAO,UAAU,KAAK,IAAI;AAChC,UAAM,OAAO,aAAa,UAAU,KAAK,SAAS,KAAK,UAAU,KAAK,KAAK,KAAK,EAAE;AAClF,UAAM,UAAU,kBAAkB,IAAI;AAEtC,eAAW,SAAS;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV,GAAG;AACD,YAAM;AAAA,IACR;AAEA,UAAM,gBAA0B,CAAC;AACjC,UAAM,WAAqB,CAAC;AAC5B,eAAW,OAAO,QAAQ,KAAK,QAAQ,GAAG;AACxC,YAAM,SAAS,IAAI,UAAU,KAAK;AAClC,YAAM,WAAW,aAAa,IAAI,YAAY,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC;AAC1E,UAAI,CAAC,SAAU;AACf,UAAI,WAAW,WAAY,eAAc,KAAK,QAAQ;AACtD,UAAI,WAAW,WAAY,UAAS,KAAK,QAAQ;AAAA,IACnD;AAEA,QAAI,aAAa,QAAQ;AACvB,YAAM,cAAc,YAAY,MAAM,eAAe;AACrD,UAAI;AACJ,UAAI,eAAe,gBAAgB,IAAI,WAAW,GAAG;AACnD,gCAAwB;AAAA,MAC1B;AAEA,YAAM,OAAuB;AAAA,QAC3B,MAAM;AAAA,QACN,QAAQ,WAAW,IAAI,MAAM,QAAQ,UAAU;AAAA,QAC/C,UAAU;AAAA,QACV,OAAO,UAAU,KAAK,KAAK,KAAK;AAAA,QAChC;AAAA,QACA,SAAS,WAAW,IAAI,KAAK;AAAA,QAC7B,aAAa;AAAA,QACb,aAAa,UAAU,KAAK,SAAS,KAAK;AAAA,QAC1C,QAAQ,iBAAiB,UAAU,KAAK,MAAM,CAAC;AAAA,QAC/C,eAAe,cAAc,SAAS,gBAAgB;AAAA,QACtD,UAAU,SAAS,SAAS,WAAW;AAAA,QACvC,uBAAuB;AAAA,QACvB;AAAA,MACF;AACA,YAAM;AAAA,IACR,OAAO;AACL,YAAM,aACJ,YAAY,MAAM,mBAAmB,MAAM,OAC3C,YAAY,MAAM,eAAe,MAAM;AAEzC,YAAM,OAAuB;AAAA,QAC3B,MAAM;AAAA,QACN,QAAQ,WAAW,IAAI,MAAM,QAAQ,UAAU;AAAA,QAC/C,UAAU;AAAA,QACV,OAAO,UAAU,KAAK,KAAK,KAAK;AAAA,QAChC;AAAA,QACA,aAAa;AAAA,QACb,YAAY,cAAc;AAAA,QAC1B,QAAQ,iBAAiB,UAAU,KAAK,MAAM,CAAC;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAsB,gBAAgB,UAInC;AACD,QAAM,SAA8C,CAAC;AACrD,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,SAAS,UAAU,MAAM;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ,CAAC,EAAE,MAAM,kBAAkB,SAAS,qBAAqB,QAAQ,GAAG,CAAC;AAAA,MAC7E,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,eACJ,IAAI,SAAS,MAAM,MAClB,IAAI,SAAS,gBAAgB,KAC5B,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,wBAAwB;AACzC,MAAI,CAAC,cAAc;AACjB,WAAO,KAAK,EAAE,MAAM,eAAe,SAAS,2CAA2C,CAAC;AAAA,EAC1F;AAEA,QAAM,QAAQ,WAAW,GAAG;AAC5B,QAAM,UAAU;AAAA,IACd,OAAO,MAAM,OAAO,CAAC,MAAM,UAAU,EAAE,SAAS,MAAM,MAAM,EAAE;AAAA,IAC9D,OAAO,MAAM,OAAO,CAAC,MAAM,UAAU,EAAE,SAAS,MAAM,MAAM,EAAE;AAAA,IAC9D,QAAQ,MAAM,OAAO,CAAC,MAAM,UAAU,EAAE,SAAS,MAAM,YAAY,EAAE;AAAA,IACrE,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM;AAAA,EACR;AAEA,QAAM,EAAE,YAAY,KAAK,IAAI,kBAAkB,KAAK;AACpD,UAAQ,aAAa,WAAW;AAChC,UAAQ,OAAO,KAAK;AAEpB,SAAO,EAAE,IAAI,OAAO,WAAW,GAAG,QAAQ,QAAQ;AACpD;;;ACvYA,SAAS,YAAY,OAAwB;AAC3C,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AACzD,WAAO,OAAQ,MAA2B,IAAI;AAAA,EAChD;AACA,QAAM,IAAI,MAAM,4DAA4D;AAC9E;AAEO,IAAM,mBAAqC;AAAA,EAChD,UAAU;AAAA,EAEV,MAAM,cAAc,OAA2C;AAC7D,UAAM,OAAO,YAAY,KAAK;AAC9B,UAAM,SAAS,MAAM,gBAAgB,IAAI;AACzC,WAAO;AAAA,MACL,IAAI,OAAO;AAAA,MACX,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,kBAAkB,KAAqB;AACrC,UAAM,OAAO,YAAY,IAAI,KAAK;AAClC,WAAO,qBAAqB,EAAE,UAAU,KAAK,CAAC;AAAA,EAChD;AACF;;;AC5BA,SAAS,YAAY,mBAAmB;AAExC,SAAS,SAAS;AAKX,IAAM,mBAAmB;AACzB,IAAM,mBAAmB,WAAW,gBAAgB;AAEpD,IAAM,0BAA0B;AAAA,EACrC,cAAc;AAAA,EACd,WAAW;AAAA,EACX,aAAa;AACf;AAEO,IAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAChC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,mBAAmB,EAAE,OAAO,EAAE,IAAI,CAAC;AACrC,CAAC;AAIM,IAAM,6BAA6B,EAAE,OAAO;AAAA,EACjD,aAAa;AAAA,EACb,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG;AAAA,EACtD,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;AAAA,EACrD,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG;AAAA,EACrD,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAI;AAAA,EACrD,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG;AAAA,EACtD,WAAW,EAAE,OAAqB,EAAE,SAAS;AAC/C,CAAC;AAID,IAAM,sBAAsB;AAAA,EAC1B,QAAQ;AAAA,IACN,YAAY;AAAA,MACV,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,QAAQ,CAAC,YAAY,WAAW,eAAe;AAAA,UAC/C,WAAW,CAAC,iBAAiB,kBAAkB;AAAA,UAC/C,QAAQ;AAAA,YACN,eAAe;AAAA,cACb,QAAQ,CAAC,OAAO,YAAY,iBAAiB,gBAAgB,gBAAgB,aAAa;AAAA,YAC5F;AAAA,YACA,kBAAkB;AAAA,cAChB,QAAQ,CAAC,kBAAkB;AAAA,YAC7B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AA4DO,SAAS,mBAAmB,OAAuB;AACxD,SAAO,mBAAmB,KAAK,EAAE;AAAA,IAAQ;AAAA,IAAY,CAAC,SACpD,IAAI,KAAK,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,YAAY,CAAC;AAAA,EACnD;AACF;AAEA,SAAS,oBAAoB,KAAkB;AAC7C,QAAM,WAAW,IAAI,SAAS,QAAQ,MAAM,EAAE,EAAE,YAAY;AAC5D,QAAM,OAAO,IAAI,SAAS,YAAY;AACtC,QAAM,cAAc,aAAa,SAAS,OAAO;AACjD,QAAM,OAAO,IAAI,QAAQ,IAAI,SAAS,cAAc,IAAI,IAAI,IAAI,KAAK;AACrE,SAAO,GAAG,QAAQ,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,QAAQ;AACpD;AAEA,SAAS,sBAAsB,QAAwC;AACrE,SAAO,OAAO,KAAK,MAAM,EACtB,KAAK,CAAC,GAAG,MAAO,MAAM,IAAI,IAAI,IAAI,IAAI,KAAK,CAAE,EAC7C,IAAI,CAAC,QAAQ,GAAG,mBAAmB,GAAG,CAAC,IAAI,mBAAmB,OAAO,GAAG,CAAE,CAAC,EAAE,EAC7E,KAAK,GAAG;AACb;AAEA,SAAS,uBACP,KACA,aACA,YACwB;AACxB,QAAM,SAAiC,EAAE,GAAG,YAAY;AACxD,MAAI,aAAa,QAAQ,CAAC,OAAO,QAAQ;AACvC,WAAO,GAAG,IAAI;AAAA,EAChB,CAAC;AACD,MAAI,YAAY;AACd,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,wBAAwB,OAM7B;AACT,QAAM,MAAM,IAAI,IAAI,MAAM,GAAG;AAC7B,QAAM,kBAAkB;AAAA,IACtB,uBAAuB,KAAK,MAAM,aAAa,MAAM,UAAU;AAAA,EACjE;AACA,QAAM,gBAAgB;AAAA,IACpB,MAAM,OAAO,YAAY;AAAA,IACzB,mBAAmB,oBAAoB,GAAG,CAAC;AAAA,IAC3C,mBAAmB,eAAe;AAAA,EACpC,EAAE,KAAK,GAAG;AACV,QAAM,aAAa,GAAG,mBAAmB,MAAM,YAAY,cAAc,CAAC,IAAI,mBAAmB,MAAM,YAAY,iBAAiB,CAAC;AACrI,SAAO,WAAW,QAAQ,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,QAAQ;AAC7E;AAEA,SAAS,iBAAiB,aAAiC,OAAe,WAAmB;AAC3F,SAAO;AAAA,IACL,oBAAoB,YAAY;AAAA,IAChC,aAAa,YAAY;AAAA,IACzB,wBAAwB;AAAA,IACxB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,gCAAgC,OAOrC;AACT,QAAM,QAAQ,MAAM,SAAS,YAAY,EAAE,EAAE,SAAS,KAAK;AAC3D,QAAM,YAAY,MAAM,aAAa,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,CAAC;AACzE,QAAM,cAAc,iBAAiB,MAAM,aAAa,OAAO,SAAS;AACxE,QAAM,YAAY,wBAAwB;AAAA,IACxC,QAAQ,MAAM;AAAA,IACd,KAAK,MAAM;AAAA,IACX,aAAa,MAAM;AAAA,IACnB;AAAA,IACA,YAAY,MAAM;AAAA,EACpB,CAAC;AACD,QAAM,eAAe,EAAE,GAAG,aAAa,iBAAiB,UAAU;AAClE,QAAM,cAAc,OAAO,KAAK,YAAY,EACzC,KAAK,EACL,IAAI,CAAC,QAAQ,GAAG,mBAAmB,GAAG,CAAC,KAAK,mBAAmB,aAAa,GAAgC,CAAE,CAAC,GAAG,EAClH,KAAK,IAAI;AACZ,SAAO,SAAS,WAAW;AAC7B;AAEO,SAAS,8BACd,MAA0C,QAAQ,KAC9B;AACpB,SAAO,yBAAyB,MAAM;AAAA,IACpC,aAAa,IAAI;AAAA,IACjB,gBAAgB,IAAI;AAAA,IACpB,aAAa,IAAI;AAAA,IACjB,mBAAmB,IAAI;AAAA,EACzB,CAAC;AACH;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,SAAS,gBAAgB,KAAqB;AAC5C,QAAM,QAAQ,IAAI,MAAM,qBAAqB;AAC7C,MAAI,CAAC,QAAQ,CAAC,GAAG;AACf,UAAM,IAAI,MAAM,uCAAuC,GAAG,EAAE;AAAA,EAC9D;AACA,SAAO,MAAM,CAAC;AAChB;AAUA,SAAS,cACP,YACA,mBACA,MACkB;AAClB,QAAM,QAAQ,WAAW;AACzB,QAAM,WAAW,OAAO,iBAAiB,WAAW;AACpD,QAAM,cACJ,OAAO,kBAAkB,oBAAoB,WAAW,cAAc,OAAO,WAAW;AAC1F,QAAM,WAAW,OAAO,YAAY,WAAW;AAC/C,SAAO;AAAA,IACL,UAAU,WAAW;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,WAAW,WAAW,OAAO;AAAA,IACtC,UAAU,OAAO,eAAe,SAAS,MAAM,gBAAgB;AAAA,IAC/D,MAAM,WACF;AAAA,MACE,KAAK,SAAS;AAAA,MACd,UAAU,SAAS,YAAY,SAAS;AAAA,MACxC,SAAS,SAAS,gBAAgB,SAAS;AAAA,MAC3C,aAAa,SAAS;AAAA,IACxB,IACA;AAAA,EACN;AACF;AAGO,IAAM,mBAAN,MAAuB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED,gBAAgB;AAAA,EAExB,YAAY,SAA+B;AACzC,UAAM,SAAS,2BAA2B,MAAM,OAAO;AACvD,SAAK,cAAc,OAAO;AAC1B,SAAK,WAAW,OAAO;AACvB,SAAK,aAAa,OAAO;AACzB,SAAK,mBAAmB,OAAO;AAC/B,SAAK,kBAAkB,OAAO;AAC9B,SAAK,oBAAoB,OAAO;AAChC,SAAK,YAAY,OAAO,aAAa;AAAA,EACvC;AAAA;AAAA,EAGA,MAAM,sBAAuE;AAC3E,UAAM,OAAO,MAAM,KAAK,YAAY;AACpC,WAAO,EAAE,MAAM,KAAK,UAAU,aAAa,KAAK,KAAK,KAAK;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAM,cAA0C;AAC9C,UAAM,OAAO,MAAM,KAAK,YAAY;AACpC,UAAM,UAA+B,CAAC;AACtC,UAAM,SAA6B,CAAC;AACpC,UAAM,SAA6B,CAAC;AAEpC,UAAM,KAAK,SAAS,KAAK,KAAK,MAAM,QAAW,SAAS,QAAQ,MAAM;AAEtE,WAAO;AAAA,MACL,eAAe;AAAA,MACf,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAc,cAAwC;AACpD,UAAM,WAAW,MAAM,KAAK,YAA6B,GAAG,gBAAgB,iBAAiB;AAC7F,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,MAAc,SACZ,SACA,gBACA,SACA,QACA,QACe;AACf,UAAM,eAAe,GAAG,OAAO;AAC/B,qBAAiB,SAAS,KAAK,cAAc,YAAY,GAAG;AAC1D,UAAI,MAAM,SAAS,OAAQ;AAE3B,UAAI,MAAM,SAAS,UAAU;AAC3B,gBAAQ,KAAK;AAAA,UACX,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,gBAAgB;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,aAAa,MAAM;AAAA,QACrB,CAAC;AACD,cAAM,KAAK,SAAS,MAAM,KAAK,MAAM,QAAQ,SAAS,QAAQ,MAAM;AACpE;AAAA,MACF;AAEA,UAAI,MAAM,SAAS,SAAS;AAC1B,eAAO,KAAK;AAAA,UACV,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,gBAAgB;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,aAAa,MAAM;AAAA,UACnB,KAAK,MAAM;AAAA,QACb,CAAC;AACD,cAAM,WAAW,MAAM,MAAM;AAC7B,YAAI,UAAU;AACZ,gBAAM,KAAK,mBAAmB,UAAU,MAAM,QAAQ,MAAM;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,mBACZ,UACA,mBACA,QACe;AACf,UAAM,WAAW,gBAAgB,QAAQ;AACzC,UAAM,cAAc,WAAW,mBAAmB,KAAK,UAAU,mBAAmB,CAAC,CAAC;AACtF,UAAM,cAAc,GAAG,gBAAgB,UAAU,QAAQ,WAAW,WAAW;AAE/E,QAAI,OAAO;AACX,qBAAiB,cAAc,KAAK,oBAAoB,WAAW,GAAG;AACpE,aAAO,KAAK,cAAc,YAAY,mBAAmB,IAAI,CAAC;AAC9D,cAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,OAAe,cAAc,MAA+C;AAC1E,qBAAiB,QAAQ,KAAK,SAAuC,IAAI,GAAG;AAC1E,iBAAW,QAAQ,KAAK,QAAQ,CAAC,GAAG;AAClC,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAe,oBAAoB,MAAqD;AACtF,qBAAiB,QAAQ,KAAK,SAAmD,IAAI,GAAG;AACtF,iBAAW,cAAc,KAAK,cAAc,CAAC,GAAG;AAC9C,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAe,SACb,aACmB;AACnB,QAAI,WAA+B,iBAAiB,aAAa,KAAK,UAAU,CAAC;AACjF,WAAO,UAAU;AACf,YAAM,WAAkC,MAAM,KAAK,YAAe,QAAQ;AAC1E,YAAM,SAAS;AACf,iBAAW,SAAS,SAAS,OAAO;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAc,YAAe,WAAmD;AAC9E,UAAM,MAAM,cAAc,SAAS;AACnC,UAAM,WAAW,MAAM,KAAK,iBAAiB,GAAG;AAChD,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,KAAK,SAAS,KAAK;AACrB,YAAM,IAAI,MAAM,qBAAqB,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE;AAAA,IACnE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,iBAAiB,KAA6B;AAC1D,QAAI,UAAU;AACd,WAAO,MAAM;AACX,YAAM,KAAK,SAAS;AACpB,YAAM,gBAAgB,gCAAgC;AAAA,QACpD,QAAQ;AAAA,QACR,KAAK,IAAI,SAAS;AAAA,QAClB,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF,CAAC;AAED,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAEA,YAAM,YAAY,SAAS,WAAW,OAAO,SAAS,UAAU;AAChE,UAAI,CAAC,aAAa,WAAW,KAAK,YAAY;AAC5C,cAAM,SAAS,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACnD,cAAM,IAAI;AAAA,UACR,gBAAgB,SAAS,MAAM,GAAG,SAAS,KAAK,OAAO,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE;AAAA,QAC7E;AAAA,MACF;AAEA,YAAM,aAAa,OAAO,SAAS,SAAS,QAAQ,IAAI,aAAa,KAAK,IAAI,EAAE;AAChF,YAAM,QAAQ,OAAO,SAAS,UAAU,IACpC,aAAa,MACb,KAAK,IAAI,KAAK,iBAAiB,KAAK,mBAAmB,KAAK,OAAO;AACvE,YAAM,MAAM,KAAK;AACjB,iBAAW;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAc,WAA0B;AACtC,QAAI,KAAK,qBAAqB,EAAG;AACjC,UAAM,UAAU,KAAK,IAAI,IAAI,KAAK;AAClC,QAAI,UAAU,KAAK,mBAAmB;AACpC,YAAM,MAAM,KAAK,oBAAoB,OAAO;AAAA,IAC9C;AACA,SAAK,gBAAgB,KAAK,IAAI;AAAA,EAChC;AACF;AAEA,SAAS,cAAc,WAAwB;AAC7C,MAAI,UAAU,WAAW,SAAS,KAAK,UAAU,WAAW,UAAU,GAAG;AACvE,WAAO,IAAI,IAAI,SAAS;AAAA,EAC1B;AACA,MAAI,UAAU,WAAW,GAAG,GAAG;AAC7B,WAAO,IAAI,IAAI,WAAW,gBAAgB,GAAG,SAAS,EAAE;AAAA,EAC1D;AACA,SAAO,IAAI,IAAI,SAAS;AAC1B;AAEA,SAAS,iBAAiB,WAAmB,OAAe,OAAuB;AACjF,QAAM,MAAM,cAAc,SAAS;AACnC,MAAI,aAAa,IAAI,SAAS,OAAO,KAAK,CAAC;AAC3C,MAAI,aAAa,IAAI,SAAS,OAAO,KAAK,CAAC;AAC3C,SAAO,IAAI,SAAS;AACtB;;;ACheA,SAAS,YAAAA,iBAAgB;AAoBzB,IAAMC,YAAW;AACjB,IAAM,wBAAwB;AAa9B,SAASC,YAAW,IAAY,KAAc,YAAqC;AACjF,SAAO;AAAA,IACL,UAAUD;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAASE,WAAU,UAAsC;AACvD,QAAM,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY;AACnD,QAAM,MAA8B;AAAA,IAClC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACA,SAAO,MAAM,IAAI,GAAG,IAAI;AAC1B;AAEA,SAAS,gBAAgB,OAAwD;AAC/E,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,QAAM,SAAS,OAAO,WAAW,OAAO,KAAK,EAAE,QAAQ,YAAY,EAAE,CAAC;AACtE,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;AAEA,SAAS,cACP,MACiC;AACjC,MAAI,CAAC,QAAQ,OAAO,KAAK,IAAI,EAAE,WAAW,EAAG,QAAO;AACpD,QAAM,aAAkC;AAAA,IACtC,KAAK,gBAAgB,KAAK,GAAG;AAAA,IAC7B,UAAU,gBAAgB,KAAK,QAAQ;AAAA,IACvC,SAAS,KAAK;AAAA,IACd,aAAa,gBAAgB,KAAK,WAAW;AAAA,EAC/C;AACA,MACE,WAAW,QAAQ,UACnB,WAAW,aAAa,UACxB,CAAC,WAAW,WACZ,WAAW,gBAAgB,QAC3B;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,oBAAoB,OAA4C;AAC9E,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAS;AACf,QAAM,UAAU,OAAO;AACvB,UACG,YAAY,KAAK,YAAY,QAC9B,MAAM,QAAQ,OAAO,OAAO,KAC5B,MAAM,QAAQ,OAAO,MAAM,KAC3B,MAAM,QAAQ,OAAO,MAAM;AAE/B;AAEA,SAAS,sBAAsB,OAA4C;AACzE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAS;AACf,QAAM,UAAU,OAAO;AACvB,UAAQ,YAAY,KAAK,YAAY,QAAQ,MAAM,QAAQ,OAAO,OAAO;AAC3E;AAEA,eAAsB,kBAAkB,SAA8D;AACpG,MAAI,QAAQ,KAAM,QAAO,QAAQ;AACjC,MAAI,CAAC,QAAQ,UAAU;AACrB,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AACA,QAAM,MAAe,KAAK,MAAM,MAAMC,UAAS,QAAQ,UAAU,MAAM,CAAC;AACxE,MAAI,oBAAoB,GAAG,KAAK,sBAAsB,GAAG,GAAG;AAC1D,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAiC;AACxD,MAAI,MAAM,YAAa,QAAO,MAAM;AACpC,SAAO,GAAG,qBAAqB,GAAG,MAAM,QAAQ;AAClD;AAEA,SAAS,gBAAgB,OAAiC;AACxD,MAAI,MAAM,SAAU,QAAO,MAAM;AACjC,SAAO,GAAG,MAAM,QAAQ;AAC1B;AAEA,UAAU,0BACR,QACA,YACgC;AAChC,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,QAAQF,YAAW,OAAO,IAAI,QAAW,UAAU;AAAA,IACnD,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,MAAM,aAAa,OAAO,QAAQ,OAAO,IAAI;AAAA,IAC7C,aAAa,OAAO;AAAA,EACtB;AACF;AAEA,UAAU,yBACR,QACA,OACA,YACgC;AAChC,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,QAAQA,YAAW,MAAM,IAAI,MAAM,KAAK,UAAU;AAAA,IAClD,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI;AAAA,IAC3C,aAAa,MAAM;AAAA,IACnB,gBAAgB,OAAO;AAAA,EACzB;AACF;AAEA,UAAU,sBACR,OACA,YAC4B;AAC5B,WAAS,QAAQ,GAAG,QAAQ,MAAM,OAAO,QAAQ,SAAS;AACxD,UAAM,QAAQ,MAAM,OAAO,KAAK;AAChC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQA,YAAW,MAAM,IAAI,MAAM,aAAa,UAAU;AAAA,MAC1D,UAAU,MAAM;AAAA,MAChB,WAAW,MAAM;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,UAAUC,WAAU,MAAM,QAAQ;AAAA,MAClC,SAAS,MAAM;AAAA,MACf,UAAU,MAAM,UAAU,SAAS,MAAM,WAAW;AAAA,MACpD,MAAM,cAAc,MAAM,IAAI;AAAA,MAC9B,mBAAmB,MAAM;AAAA,MACzB,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,gBAAgB,sBACd,KACkC;AAClC,QAAM,aAAa,IAAI;AACvB,aAAW,UAAU,IAAI,SAAS;AAChC,WAAO,0BAA0B,QAAQ,UAAU;AACnD,eAAW,SAAS,OAAO,QAAQ;AACjC,aAAO,yBAAyB,QAAQ,OAAO,UAAU;AACzD,aAAO,sBAAsB,OAAO,UAAU;AAAA,IAChD;AAAA,EACF;AACF;AAEA,gBAAgB,oBAAoB,KAA0D;AAC5F,QAAM,aAAa,IAAI;AAEvB,aAAW,UAAU,IAAI,SAAS;AAChC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQD,YAAW,OAAO,UAAU,QAAW,UAAU;AAAA,MACzD,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO;AAAA,MACd,MAAM,aAAa,OAAO,QAAQ,OAAO,IAAI;AAAA,MAC7C,aAAa,OAAO;AAAA,MACpB,gBAAgB,OAAO;AAAA,IACzB;AAAA,EACF;AAEA,aAAW,SAAS,IAAI,QAAQ;AAC9B,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQA,YAAW,MAAM,UAAU,MAAM,KAAK,UAAU;AAAA,MACxD,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI;AAAA,MAC3C,aAAa,MAAM;AAAA,MACnB,gBAAgB,MAAM;AAAA,IACxB;AAAA,EACF;AAEA,aAAW,SAAS,IAAI,QAAQ;AAC9B,UAAM,WAAW,gBAAgB,KAAK;AACtC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQA,YAAW,MAAM,UAAU,MAAM,aAAa,UAAU;AAAA,MAChE,UAAU,MAAM;AAAA,MAChB,WAAW,gBAAgB,KAAK;AAAA,MAChC;AAAA,MACA,UAAUC,WAAU,QAAQ;AAAA,MAC5B,SAAS,MAAM;AAAA,MACf,UAAU,MAAM,UAAU,SAAS,MAAM,WAAW;AAAA,MACpD,MAAM,cAAc,MAAM,IAAI;AAAA,MAC9B,mBAAmB,MAAM;AAAA,MACzB,MAAM,MAAM,QAAQ;AAAA,IACtB;AAAA,EACF;AACF;AAEA,eAAe,uBAAuB,SAA8D;AAClG,MAAI,QAAQ,KAAM,QAAO,QAAQ;AACjC,MAAI,QAAQ,OAAQ,QAAO,QAAQ,OAAO,YAAY;AACtD,MAAI,QAAQ,aAAa;AACvB,UAAM,SAAS,IAAI,iBAAiB,EAAE,aAAa,QAAQ,aAAa,GAAG,QAAQ,cAAc,CAAC;AAClG,WAAO,OAAO,YAAY;AAAA,EAC5B;AACA,SAAO,kBAAkB,OAAO;AAClC;AAGA,gBAAuB,yBACrB,SACkC;AAClC,QAAM,MAAM,MAAM,uBAAuB,OAAO;AAChD,MAAI,oBAAoB,GAAG,GAAG;AAC5B,WAAO,oBAAoB,GAAG;AAC9B;AAAA,EACF;AACA,SAAO,sBAAsB,GAAG;AAClC;AAEO,SAAS,uBAAuB,KAKrC;AACA,MAAI,oBAAoB,GAAG,GAAG;AAC5B,WAAO;AAAA,MACL,SAAS,IAAI,QAAQ;AAAA,MACrB,QAAQ,IAAI,OAAO;AAAA,MACnB,QAAQ,IAAI,OAAO;AAAA,MACnB,YAAY,IAAI,QAAQ,SAAS,IAAI,OAAO;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,QAAQ;AAC5B,MAAI,SAAS;AACb,MAAI,SAAS;AACb,aAAW,UAAU,IAAI,SAAS;AAChC,cAAU,OAAO,OAAO;AACxB,eAAW,SAAS,OAAO,QAAQ;AACjC,gBAAU,MAAM,OAAO;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,UAAU;AAAA,EACxB;AACF;AAEA,eAAsB,0BAA0B,UAI7C;AACD,QAAM,SAA8C,CAAC;AACrD,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,kBAAkB,EAAE,SAAS,CAAC;AAAA,EAC5C,SAAS,OAAO;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAChE;AAAA,MACF;AAAA,MACA,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,oBAAoB,GAAG,GAAG;AAC5B,QAAI,IAAI,QAAQ,WAAW,KAAK,IAAI,OAAO,WAAW,GAAG;AACvD,aAAO,KAAK,EAAE,MAAM,gBAAgB,SAAS,iCAAiC,CAAC;AAAA,IACjF;AAAA,EACF,WAAW,IAAI,QAAQ,WAAW,GAAG;AACnC,WAAO,KAAK,EAAE,MAAM,gBAAgB,SAAS,uBAAuB,CAAC;AAAA,EACvE;AAEA,QAAM,UAAU,uBAAuB,GAAG;AAC1C,SAAO;AAAA,IACL,IAAI,OAAO,WAAW;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,MACP,YAAY,QAAQ;AAAA,MACpB,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;ACvTA,SAAS,aAAa,OAAmC;AACvD,MAAI,OAAO,UAAU,SAAU,QAAO,EAAE,MAAM,MAAM;AACpD,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,SAAS;AACf,QAAI,OAAO,UAAU,OAAO,eAAe,OAAO,KAAM,QAAO;AAC/D,QAAI,OAAO,KAAM,QAAO,EAAE,MAAM,OAAO,KAAK;AAC5C,QAAI,OAAO,KAAM,QAAO,EAAE,MAAM,OAAO,KAAK;AAAA,EAC9C;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,uBAAuB,OAA0B;AACxD,MAAI,MAAM,YAAa,QAAO,MAAM;AACpC,MAAI,MAAM,KAAM,QAAO,8BAA8B;AACrD,SAAO;AACT;AAEO,IAAM,iBAAmC;AAAA,EAC9C,UAAU;AAAA,EAEV,MAAM,cAAc,OAA2C;AAC7D,QAAI;AACF,YAAM,WAAW,aAAa,KAAK;AACnC,YAAM,cAAc,uBAAuB,QAAQ;AAEnD,UAAI,SAAS,MAAM;AACjB,cAAM,UAAU,uBAAuB,SAAS,IAAI;AACpD,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,QAAQ,CAAC;AAAA,UACT,SAAS;AAAA,YACP,YAAY,QAAQ;AAAA,YACpB,QAAQ,QAAQ;AAAA,YAChB,YAAY,QAAQ;AAAA,YACpB,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,UAAU,aAAa;AAClC,cAAM,SACJ,SAAS,UACT,IAAI,iBAAiB,EAAE,aAA2B,GAAG,SAAS,cAAc,CAAC;AAC/E,cAAM,OAAO,oBAAoB;AACjC,cAAM,MAAM,MAAM,OAAO,YAAY;AACrC,cAAM,UAAU,uBAAuB,GAAG;AAC1C,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,QAAQ,CAAC;AAAA,UACT,SAAS;AAAA,YACP,YAAY,QAAQ;AAAA,YACpB,QAAQ,QAAQ;AAAA,YAChB,YAAY,QAAQ;AAAA,YACpB,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,0BAA0B,SAAS,IAAK;AAC7D,aAAO;AAAA,QACL,IAAI,OAAO;AAAA,QACX,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO;AAAA,MAClB;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,QAAQ;AAAA,UACN;AAAA,YACE,MAAM;AAAA,YACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBAAkB,KAAqB;AACrC,UAAM,WAAW,aAAa,IAAI,KAAK;AACvC,UAAM,cAAc,uBAAuB,QAAQ;AACnD,WAAO,yBAAyB;AAAA,MAC9B,UAAU,SAAS;AAAA,MACnB,MAAM,SAAS;AAAA,MACf,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,eAAe,SAAS;AAAA,IAC1B,CAAC;AAAA,EACH;AACF;;;ACjGA,SAASE,cAAa,OAAuC;AAC3D,MAAI,OAAO,UAAU,SAAU,QAAO,EAAE,MAAM,MAAM;AACpD,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,SAAS;AACf,QAAI,OAAO,UAAU,OAAO,eAAgB,QAAO;AACnD,QAAI,OAAO,KAAM,QAAO,EAAE,MAAM,OAAO,KAAK;AAC5C,QAAI,OAAO,KAAM,QAAO,EAAE,MAAM,OAAO,KAAK;AAAA,EAC9C;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEO,IAAM,qBAAuC;AAAA,EAClD,UAAU;AAAA,EAEV,MAAM,cAAc,OAA2C;AAC7D,QAAI;AACF,YAAM,WAAWA,cAAa,KAAK;AAEnC,UAAI,SAAS,MAAM;AACjB,cAAM,UAAU,2BAA2B,SAAS,IAAI;AACxD,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,QAAQ,CAAC;AAAA,UACT,SAAS;AAAA,YACP,OAAO,QAAQ;AAAA,YACf,OAAO,QAAQ;AAAA,YACf,YAAY,QAAQ;AAAA,YACpB,MAAM,QAAQ;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,UAAU,SAAS,gBAAgB,QAAQ;AACtD,YAAI,CAAC,SAAS,gBAAgB,QAAQ;AACpC,gBAAM,IAAI,MAAM,qDAAqD;AAAA,QACvE;AACA,cAAM,SACJ,SAAS,UAAU,IAAI,4BAA4B,SAAS,aAAa;AAC3E,cAAM,MAAM,MAAM,OAAO,cAAc,SAAS,cAAc;AAC9D,cAAM,UAAU,2BAA2B,GAAG;AAC9C,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,QAAQ,CAAC;AAAA,UACT,SAAS;AAAA,YACP,OAAO,QAAQ;AAAA,YACf,OAAO,QAAQ;AAAA,YACf,YAAY,QAAQ;AAAA,YACpB,MAAM,QAAQ;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,8BAA8B,SAAS,IAAK;AACjE,aAAO;AAAA,QACL,IAAI,OAAO;AAAA,QACX,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO;AAAA,MAClB;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,QAAQ;AAAA,UACN;AAAA,YACE,MAAM;AAAA,YACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBAAkB,KAAqB;AACrC,UAAM,WAAWA,cAAa,IAAI,KAAK;AACvC,WAAO,6BAA6B;AAAA,MAClC,UAAU,SAAS;AAAA,MACnB,MAAM,SAAS;AAAA,MACf,QAAQ,SAAS;AAAA,MACjB,gBAAgB,SAAS;AAAA,MACzB,eAAe,SAAS;AAAA,IAC1B,CAAC;AAAA,EACH;AACF;;;AC9EA,IAAM,WAAW;AAAA,EACf,WAAW;AAAA,EACX,SAAS;AAAA,EACT,aAAa;AACf;AAEO,SAAS,WAAW,UAA6B;AACtD,SAAO,SAAS,QAAQ;AAC1B;","names":["readFile","PLATFORM","sourceMeta","guessMime","readFile","resolveInput"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/normalizer/types.ts","../src/normalizer/idempotency.ts","../src/normalizer/bundle.ts","../src/normalizer/portfolio-media.ts"],"sourcesContent":["export type MigrationPlatform = \"wordpress\" | \"smugmug\" | \"squarespace\";\n\nexport type EntityType = \"post\" | \"page\" | \"asset\" | \"portfolio\" | \"category\" | \"tag\";\n\nexport type PublishStatus = \"draft\" | \"published\" | \"archived\";\n\nexport interface SourceMetadata {\n platform: MigrationPlatform;\n id: string;\n url?: string;\n path?: string;\n exportedAt?: string;\n}\n\n/** Canonical post DTO — raw HTML; sanitize at host sink. */\nexport interface NormalizedPost {\n type: \"post\";\n source: SourceMetadata;\n sourceId: string;\n title: string;\n slug: string;\n excerpt?: string;\n contentHtml: string;\n publishedAt?: string;\n status: PublishStatus;\n categorySlugs?: string[];\n tagSlugs?: string[];\n /** WordPress attachment id before two-pass resolution. */\n sourceFeaturedMediaId?: string;\n featuredAssetSourceId?: string;\n seoTitle?: string;\n seoDescription?: string;\n}\n\n/** Canonical page DTO — raw HTML snapshot. */\nexport interface NormalizedPage {\n type: \"page\";\n source: SourceMetadata;\n sourceId: string;\n title: string;\n slug: string;\n contentHtml: string;\n contentCss?: string;\n isHomePage?: boolean;\n status: PublishStatus;\n seoTitle?: string;\n seoDescription?: string;\n}\n\n/** EXIF fields preserved from SmugMug / camera metadata when present. */\nexport interface NormalizedAssetExif {\n iso?: number;\n aperture?: number;\n shutter?: string;\n focalLength?: number;\n}\n\n/** Remote asset to stream into the host sink. */\nexport interface NormalizedAsset {\n type: \"asset\";\n source: SourceMetadata;\n sourceId: string;\n sourceUrl: string;\n filename: string;\n mimeType?: string;\n caption?: string;\n altText?: string;\n keywords?: string[];\n exif?: NormalizedAssetExif;\n portfolioSourceId?: string;\n sort?: number;\n}\n\n/** M2M index: portfolio ↔ asset membership and sort order. */\nexport interface PortfolioMediaLink {\n portfolioSourceId: string;\n assetSourceId: string;\n sort: number;\n}\n\nexport interface NormalizedPortfolio {\n type: \"portfolio\";\n source: SourceMetadata;\n sourceId: string;\n title: string;\n slug: string;\n description?: string;\n parentSourceId?: string;\n}\n\nexport interface NormalizedCategory {\n type: \"category\";\n source: SourceMetadata;\n sourceId: string;\n name: string;\n slug: string;\n}\n\nexport interface NormalizedTag {\n type: \"tag\";\n source: SourceMetadata;\n sourceId: string;\n name: string;\n slug: string;\n}\n\nexport type NormalizedEntity =\n | NormalizedPost\n | NormalizedPage\n | NormalizedAsset\n | NormalizedPortfolio\n | NormalizedCategory\n | NormalizedTag;\n\nexport interface ValidationIssue {\n code: string;\n message: string;\n path?: string;\n}\n\nexport interface ValidationResult {\n ok: boolean;\n issues: ValidationIssue[];\n summary?: {\n posts?: number;\n pages?: number;\n assets?: number;\n portfolios?: number;\n categories?: number;\n tags?: number;\n };\n}\n\nexport interface AdapterContext {\n input: unknown;\n cursor?: MigrationCursor;\n}\n\nexport interface MigrationAdapter {\n platform: MigrationPlatform;\n validateInput(input: unknown): ValidationResult | Promise<ValidationResult>;\n enumerateEntities(ctx: AdapterContext): AsyncIterable<NormalizedEntity>;\n}\n\nexport interface MigrationCursor {\n lastEntityKey?: EntityKey;\n state?: Record<string, unknown>;\n}\n\nexport interface EntityKey {\n platform: MigrationPlatform;\n entityType: EntityType;\n sourceId: string;\n}\n\nexport function entityKey(entity: NormalizedEntity, platform: MigrationPlatform): EntityKey {\n return {\n platform,\n entityType: entity.type,\n sourceId: entity.sourceId,\n };\n}\n","import type { EntityKey, MigrationCursor } from \"./types.js\";\n\n/** Portable entity state for resume / idempotency (not Directus field names). */\nexport type EntityState = \"pending\" | \"done\" | \"failed\" | \"skipped\";\n\nexport interface TrackedEntity extends EntityKey {\n state: EntityState;\n targetId?: string;\n errorMessage?: string;\n}\n\nexport interface MigrationCheckpoint {\n jobId: string;\n cursor: MigrationCursor;\n entities: TrackedEntity[];\n updatedAt: string;\n}\n\nexport function isTerminalState(state: EntityState): boolean {\n return state === \"done\" || state === \"skipped\";\n}\n\nexport function shouldProcessEntity(\n key: EntityKey,\n entities: TrackedEntity[],\n): boolean {\n const existing = entities.find(\n (e) =>\n e.platform === key.platform &&\n e.entityType === key.entityType &&\n e.sourceId === key.sourceId,\n );\n return !existing || !isTerminalState(existing.state);\n}\n","import type {\n NormalizedAsset,\n NormalizedCategory,\n NormalizedEntity,\n NormalizedPage,\n NormalizedPortfolio,\n NormalizedPost,\n NormalizedTag,\n} from \"./types.js\";\n\nexport interface EntityBundle {\n posts: NormalizedPost[];\n pages: NormalizedPage[];\n media: NormalizedAsset[];\n portfolios: NormalizedPortfolio[];\n categories: NormalizedCategory[];\n tags: NormalizedTag[];\n}\n\nexport function emptyBundle(): EntityBundle {\n return {\n posts: [],\n pages: [],\n media: [],\n portfolios: [],\n categories: [],\n tags: [],\n };\n}\n\nexport async function collectEntities(\n entities: AsyncIterable<NormalizedEntity>,\n): Promise<EntityBundle> {\n const bundle = emptyBundle();\n\n for await (const entity of entities) {\n switch (entity.type) {\n case \"post\":\n bundle.posts.push(entity);\n break;\n case \"page\":\n bundle.pages.push(entity);\n break;\n case \"asset\":\n bundle.media.push(entity);\n break;\n case \"portfolio\":\n bundle.portfolios.push(entity);\n break;\n case \"category\":\n bundle.categories.push(entity);\n break;\n case \"tag\":\n bundle.tags.push(entity);\n break;\n default: {\n const _exhaustive: never = entity;\n throw new Error(`Unknown entity type: ${(_exhaustive as NormalizedEntity).type}`);\n }\n }\n }\n\n return bundle;\n}\n\nexport interface BundleCounts {\n posts: number;\n pages: number;\n assets: number;\n portfolios: number;\n categories: number;\n tags: number;\n}\n\nexport function bundleCounts(bundle: EntityBundle): BundleCounts {\n return {\n posts: bundle.posts.length,\n pages: bundle.pages.length,\n assets: bundle.media.length,\n portfolios: bundle.portfolios.length,\n categories: bundle.categories.length,\n tags: bundle.tags.length,\n };\n}\n","import type { EntityBundle } from \"./bundle.js\";\nimport type { PortfolioMediaLink } from \"./types.js\";\n\n/** Derive portfolio↔asset M2M rows from assets carrying `portfolioSourceId`. */\nexport function buildPortfolioMediaLinks(bundle: EntityBundle): PortfolioMediaLink[] {\n const links: PortfolioMediaLink[] = [];\n\n for (const asset of bundle.media) {\n if (!asset.portfolioSourceId) continue;\n links.push({\n portfolioSourceId: asset.portfolioSourceId,\n assetSourceId: asset.sourceId,\n sort: asset.sort ?? 0,\n });\n }\n\n links.sort((a, b) => {\n if (a.portfolioSourceId !== b.portfolioSourceId) {\n return a.portfolioSourceId.localeCompare(b.portfolioSourceId);\n }\n return a.sort - b.sort || a.assetSourceId.localeCompare(b.assetSourceId);\n });\n\n return links;\n}\n"],"mappings":";AA2JO,SAAS,UAAU,QAA0B,UAAwC;AAC1F,SAAO;AAAA,IACL;AAAA,IACA,YAAY,OAAO;AAAA,IACnB,UAAU,OAAO;AAAA,EACnB;AACF;;;AC/IO,SAAS,gBAAgB,OAA6B;AAC3D,SAAO,UAAU,UAAU,UAAU;AACvC;AAEO,SAAS,oBACd,KACA,UACS;AACT,QAAM,WAAW,SAAS;AAAA,IACxB,CAAC,MACC,EAAE,aAAa,IAAI,YACnB,EAAE,eAAe,IAAI,cACrB,EAAE,aAAa,IAAI;AAAA,EACvB;AACA,SAAO,CAAC,YAAY,CAAC,gBAAgB,SAAS,KAAK;AACrD;;;ACdO,SAAS,cAA4B;AAC1C,SAAO;AAAA,IACL,OAAO,CAAC;AAAA,IACR,OAAO,CAAC;AAAA,IACR,OAAO,CAAC;AAAA,IACR,YAAY,CAAC;AAAA,IACb,YAAY,CAAC;AAAA,IACb,MAAM,CAAC;AAAA,EACT;AACF;AAEA,eAAsB,gBACpB,UACuB;AACvB,QAAM,SAAS,YAAY;AAE3B,mBAAiB,UAAU,UAAU;AACnC,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AACH,eAAO,MAAM,KAAK,MAAM;AACxB;AAAA,MACF,KAAK;AACH,eAAO,MAAM,KAAK,MAAM;AACxB;AAAA,MACF,KAAK;AACH,eAAO,MAAM,KAAK,MAAM;AACxB;AAAA,MACF,KAAK;AACH,eAAO,WAAW,KAAK,MAAM;AAC7B;AAAA,MACF,KAAK;AACH,eAAO,WAAW,KAAK,MAAM;AAC7B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,KAAK,MAAM;AACvB;AAAA,MACF,SAAS;AACP,cAAM,cAAqB;AAC3B,cAAM,IAAI,MAAM,wBAAyB,YAAiC,IAAI,EAAE;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAWO,SAAS,aAAa,QAAoC;AAC/D,SAAO;AAAA,IACL,OAAO,OAAO,MAAM;AAAA,IACpB,OAAO,OAAO,MAAM;AAAA,IACpB,QAAQ,OAAO,MAAM;AAAA,IACrB,YAAY,OAAO,WAAW;AAAA,IAC9B,YAAY,OAAO,WAAW;AAAA,IAC9B,MAAM,OAAO,KAAK;AAAA,EACpB;AACF;;;AC/EO,SAAS,yBAAyB,QAA4C;AACnF,QAAM,QAA8B,CAAC;AAErC,aAAW,SAAS,OAAO,OAAO;AAChC,QAAI,CAAC,MAAM,kBAAmB;AAC9B,UAAM,KAAK;AAAA,MACT,mBAAmB,MAAM;AAAA,MACzB,eAAe,MAAM;AAAA,MACrB,MAAM,MAAM,QAAQ;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,QAAM,KAAK,CAAC,GAAG,MAAM;AACnB,QAAI,EAAE,sBAAsB,EAAE,mBAAmB;AAC/C,aAAO,EAAE,kBAAkB,cAAc,EAAE,iBAAiB;AAAA,IAC9D;AACA,WAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,cAAc,EAAE,aAAa;AAAA,EACzE,CAAC;AAED,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sinks/types.ts","../src/sinks/run-migration.ts","../src/lib/content-asset-urls.ts","../src/transformers/rewrite-inline-images.ts","../src/sinks/conflicts.ts","../src/parsers/squarespace/parse-export.ts","../src/lib/utility.ts","../src/parsers/squarespace/collect.ts","../src/sinks/filesystem.ts","../src/sinks/filesystem-sink.ts","../src/sinks/migration-report.ts","../src/sinks/storage-estimate.ts","../src/sinks/dry-run.ts"],"sourcesContent":["import type { Readable } from \"node:stream\";\n\nimport type {\n EntityKey,\n NormalizedAsset,\n NormalizedCategory,\n NormalizedPage,\n NormalizedPortfolio,\n NormalizedPost,\n NormalizedTag,\n PortfolioMediaLink,\n} from \"../normalizer/types.js\";\nimport type { RewriteInlineImagesOptions } from \"../transformers/rewrite-inline-images.js\";\n\nexport interface CreatePostResult {\n targetId: string;\n publicPath: string;\n}\n\nexport interface CreatePageResult {\n targetId: string;\n publicPath: string;\n}\n\nexport interface UploadAssetInput {\n asset: NormalizedAsset;\n /** Byte stream from source URL or local file. Optional for metadata-only sinks. */\n body?: Readable | ReadableStream<Uint8Array>;\n contentLength?: number;\n}\n\nexport interface UploadAssetResult {\n targetId: string;\n publicUrl?: string;\n}\n\nexport interface MigrationRedirect {\n fromPath: string;\n toPath: string;\n statusCode: number;\n}\n\nexport interface MigrationProgress {\n stage: string;\n progress: number;\n message?: string;\n}\n\n/**\n * Host-implemented write surface (e.g. ArtInStack PlatformMigrationSink).\n * This package defines the interface only — no Directus or platform imports.\n */\nexport interface MigrationSink {\n createCategory?(category: NormalizedCategory): Promise<{ targetId: string }>;\n createTag?(tag: NormalizedTag): Promise<{ targetId: string }>;\n uploadAsset(input: UploadAssetInput): Promise<UploadAssetResult>;\n createPortfolio?(portfolio: NormalizedPortfolio): Promise<{ targetId: string }>;\n createPost(post: NormalizedPost): Promise<CreatePostResult>;\n createPage(page: NormalizedPage): Promise<CreatePageResult>;\n linkPortfolioMedia?(link: PortfolioMediaLink): Promise<void>;\n writeRedirect?(redirect: MigrationRedirect): Promise<void>;\n reportProgress?(progress: MigrationProgress): Promise<void>;\n /** Optional lookup for idempotent re-runs. */\n findExisting?(key: EntityKey): Promise<string | undefined>;\n}\n\nexport interface ResolvedAssetStream {\n body: Readable | ReadableStream<Uint8Array>;\n contentLength?: number;\n}\n\nexport interface MigrationRunOptions {\n sink: MigrationSink;\n entities: AsyncIterable<import(\"../normalizer/types.js\").NormalizedEntity>;\n platform: import(\"../normalizer/types.js\").MigrationPlatform;\n /** Fetch source bytes before uploadAsset; omit for metadata-only sinks. */\n resolveAssetStream?: (asset: NormalizedAsset) => Promise<ResolvedAssetStream | null>;\n /** Rewrite post/page HTML after assets are uploaded. */\n rewriteInlineImages?: RewriteInlineImagesOptions;\n onEntityProcessed?: (key: EntityKey, result: \"done\" | \"failed\" | \"skipped\", error?: string) => void;\n}\n\nexport interface MigrationRunResult {\n processed: number;\n failed: number;\n skipped: number;\n}\n\nexport const MIGRATION_WRITE_STAGES = [\n \"taxonomy\",\n \"assets\",\n \"portfolios\",\n \"content\",\n \"bindings\",\n \"redirects\",\n] as const;\n\nexport type MigrationWriteStage = (typeof MIGRATION_WRITE_STAGES)[number];\n","import { Readable } from \"node:stream\";\n\nimport { collectEntities, type EntityBundle } from \"../normalizer/bundle.js\";\nimport { buildPortfolioMediaLinks } from \"../normalizer/portfolio-media.js\";\nimport { shouldProcessEntity } from \"../normalizer/idempotency.js\";\nimport { entityKey } from \"../normalizer/types.js\";\nimport type {\n EntityKey,\n NormalizedPage,\n NormalizedPost,\n} from \"../normalizer/types.js\";\nimport { normalizeAssetUrl } from \"../lib/content-asset-urls.js\";\nimport { rewriteInlineImages, type RewriteInlineImagesOptions } from \"../transformers/rewrite-inline-images.js\";\nimport { buildRedirectMap } from \"./conflicts.js\";\nimport type {\n MigrationRunOptions,\n MigrationRunResult,\n MigrationWriteStage,\n UploadAssetResult,\n} from \"./types.js\";\n\nexport async function runMigration(options: MigrationRunOptions): Promise<MigrationRunResult> {\n const bundle = await collectEntities(options.entities);\n return runMigrationFromBundle(bundle, options);\n}\n\nexport async function runMigrationFromBundle(\n bundle: EntityBundle,\n options: MigrationRunOptions,\n): Promise<MigrationRunResult> {\n const { sink, platform, onEntityProcessed } = options;\n const checkpointEntities: import(\"../normalizer/idempotency.js\").TrackedEntity[] = [];\n const uploadedAssets = new Map<string, UploadAssetResult>();\n\n let processed = 0;\n let failed = 0;\n let skipped = 0;\n\n const track = async (\n stage: MigrationWriteStage,\n key: EntityKey,\n action: () => Promise<void>,\n ): Promise<void> => {\n if (!shouldProcessEntity(key, checkpointEntities)) {\n skipped += 1;\n onEntityProcessed?.(key, \"skipped\");\n return;\n }\n\n const existingTargetId = await sink.findExisting?.(key);\n if (existingTargetId) {\n skipped += 1;\n onEntityProcessed?.(key, \"skipped\");\n return;\n }\n\n try {\n await sink.reportProgress?.({\n stage,\n progress: processed + failed + skipped,\n message: `${stage}:${key.entityType}:${key.sourceId}`,\n });\n await action();\n processed += 1;\n onEntityProcessed?.(key, \"done\");\n } catch (error) {\n failed += 1;\n const message = error instanceof Error ? error.message : String(error);\n onEntityProcessed?.(key, \"failed\", message);\n }\n };\n\n for (const category of bundle.categories) {\n const key = entityKey(category, platform);\n await track(\"taxonomy\", key, async () => {\n if (!sink.createCategory) return;\n await sink.createCategory(category);\n });\n }\n\n for (const tag of bundle.tags) {\n const key = entityKey(tag, platform);\n await track(\"taxonomy\", key, async () => {\n if (!sink.createTag) return;\n await sink.createTag(tag);\n });\n }\n\n for (const asset of bundle.media) {\n const key = entityKey(asset, platform);\n await track(\"assets\", key, async () => {\n const stream = options.resolveAssetStream ? await options.resolveAssetStream(asset) : null;\n const result = await sink.uploadAsset({\n asset,\n body: stream?.body ?? emptyBody(),\n contentLength: stream?.contentLength,\n });\n uploadedAssets.set(asset.sourceId, result);\n });\n }\n\n for (const portfolio of bundle.portfolios) {\n const key = entityKey(portfolio, platform);\n await track(\"portfolios\", key, async () => {\n if (!sink.createPortfolio) {\n throw new Error(\"Sink does not support portfolios\");\n }\n await sink.createPortfolio(portfolio);\n });\n }\n\n for (const post of bundle.posts) {\n const key = entityKey(post, platform);\n await track(\"content\", key, async () => {\n await sink.createPost(\n prepareContentEntity(post, options, uploadedAssets, bundle),\n );\n });\n }\n\n for (const page of bundle.pages) {\n const key = entityKey(page, platform);\n await track(\"content\", key, async () => {\n await sink.createPage(\n prepareContentEntity(page, options, uploadedAssets, bundle),\n );\n });\n }\n\n const portfolioLinks = buildPortfolioMediaLinks(bundle);\n for (const link of portfolioLinks) {\n const key: EntityKey = {\n platform,\n entityType: \"asset\",\n sourceId: `${link.portfolioSourceId}:${link.assetSourceId}`,\n };\n await track(\"bindings\", key, async () => {\n if (!sink.linkPortfolioMedia) return;\n await sink.linkPortfolioMedia(link);\n });\n }\n\n const redirects = buildRedirectMap(bundle);\n for (const redirect of redirects) {\n const key: EntityKey = {\n platform,\n entityType: \"page\",\n sourceId: `redirect:${redirect.fromPath}`,\n };\n await track(\"redirects\", key, async () => {\n if (!sink.writeRedirect) return;\n await sink.writeRedirect(redirect);\n });\n }\n\n return { processed, failed, skipped };\n}\n\nfunction prepareContentEntity<T extends NormalizedPost | NormalizedPage>(\n entity: T,\n options: MigrationRunOptions,\n uploadedAssets: Map<string, UploadAssetResult>,\n bundle: EntityBundle,\n): T {\n if (!options.rewriteInlineImages) return entity;\n\n const rewriteOptions = mergeRewriteOptions(bundle, options.rewriteInlineImages);\n const rewritten = rewriteInlineImages(entity.contentHtml, rewriteOptions, uploadedAssets);\n\n return {\n ...entity,\n contentHtml: rewritten.html,\n };\n}\n\nfunction mergeRewriteOptions(\n bundle: EntityBundle,\n options: RewriteInlineImagesOptions,\n): RewriteInlineImagesOptions {\n const urlToSourceId = new Map<string, string>();\n for (const asset of bundle.media) {\n urlToSourceId.set(asset.sourceUrl, asset.sourceId);\n const normalized = normalizeAssetUrl(asset.sourceUrl);\n if (normalized) urlToSourceId.set(normalized, asset.sourceId);\n }\n\n return {\n resolveAsset: (src) => {\n const resolved = options.resolveAsset(src);\n if (resolved) return resolved;\n const normalized = normalizeAssetUrl(src);\n const sourceAssetId =\n (normalized ? urlToSourceId.get(normalized) : undefined) ?? urlToSourceId.get(src);\n if (!sourceAssetId) return undefined;\n return { originalSrc: src, sourceAssetId };\n },\n replaceWith: options.replaceWith,\n };\n}\n\nfunction emptyBody(): Readable {\n return Readable.from([]);\n}\n\nexport type { EntityKey };\n","import * as cheerio from \"cheerio\";\n\n/** Builder-agnostic attribute names that commonly hold image URLs in post_content. */\nconst ASSET_URL_PARAM_PATTERN =\n /\\b(?:src|image|url)\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n\nconst IMAGE_EXTENSION_PATTERN = /\\.(?:jpe?g|png|gif|webp|avif|svg)(?:[?#]|$)/i;\nconst WP_UPLOADS_PATTERN = /\\/wp-content\\/uploads\\//i;\n\nfunction extractImgTagSrcs(content: string): string[] {\n if (!content.trim()) return [];\n const $ = cheerio.load(content, { xml: false });\n const srcs: string[] = [];\n $(\"img[src]\").each((_, el) => {\n const src = $(el).attr(\"src\")?.trim();\n if (src) srcs.push(src);\n });\n return srcs;\n}\n\n/** All `<img src>` values (including those not ingested as vault assets). */\nexport function discoverRawImgSrcs(content: string): string[] {\n return extractImgTagSrcs(content).filter((src) => !src.startsWith(\"data:\"));\n}\n\n/** Normalize protocol-relative and trim; skip data URIs. */\nexport function normalizeAssetUrl(raw: string): string | undefined {\n const trimmed = raw.trim();\n if (!trimmed || trimmed.startsWith(\"data:\")) return undefined;\n if (trimmed.startsWith(\"//\")) return `https:${trimmed}`;\n return trimmed;\n}\n\n/** Heuristic: URL likely points at a raster/vector image asset, not a page link. */\nexport function isLikelyImageUrl(url: string): boolean {\n if (!url || url.startsWith(\"data:\")) return false;\n\n if (url.startsWith(\"/\")) {\n return WP_UPLOADS_PATTERN.test(url) || IMAGE_EXTENSION_PATTERN.test(url);\n }\n\n if (!/^https?:\\/\\//i.test(url)) return false;\n\n if (WP_UPLOADS_PATTERN.test(url)) return true;\n\n try {\n const pathname = new URL(url).pathname;\n return IMAGE_EXTENSION_PATTERN.test(pathname);\n } catch {\n return IMAGE_EXTENSION_PATTERN.test(url);\n }\n}\n\n/**\n * Generic content-discovery pass: collect image URLs from HTML `<img>` tags and\n * common shortcode/builder attributes (`src=`, `image=`, `url=`) without parsing\n * builder-specific structure (Tatsu, Elementor, etc.).\n */\nexport function discoverContentAssetUrls(content: string): string[] {\n if (!content.trim()) return [];\n\n const urls = new Set<string>();\n\n for (const raw of extractImgTagSrcs(content)) {\n const normalized = normalizeAssetUrl(raw);\n if (normalized && isLikelyImageUrl(normalized)) {\n urls.add(normalized);\n }\n }\n\n for (const match of content.matchAll(ASSET_URL_PARAM_PATTERN)) {\n const normalized = normalizeAssetUrl(match[1] ?? \"\");\n if (normalized && isLikelyImageUrl(normalized)) {\n urls.add(normalized);\n }\n }\n\n return [...urls];\n}\n\n/** @deprecated Use discoverContentAssetUrls — kept for call-site clarity during transition. */\nexport function extractInlineImageSrcs(content: string): string[] {\n return discoverContentAssetUrls(content);\n}\n","import * as cheerio from \"cheerio\";\n\nimport { normalizeAssetUrl } from \"../lib/content-asset-urls.js\";\n\nexport interface RewriteInlineImageRef {\n originalSrc: string;\n sourceAssetId?: string;\n}\n\nexport interface UploadedAssetRef {\n targetId: string;\n publicUrl?: string;\n}\n\nexport interface RewriteInlineImagesOptions {\n resolveAsset: (src: string) => RewriteInlineImageRef | undefined;\n replaceWith: (ref: RewriteInlineImageRef, uploaded: UploadedAssetRef) => string;\n}\n\nexport interface RewriteInlineImagesResult {\n html: string;\n referencedSources: string[];\n unresolved: string[];\n}\n\nfunction rewriteSrcset(\n srcset: string,\n options: RewriteInlineImagesOptions,\n uploadedBySourceId: Map<string, UploadedAssetRef>,\n referencedSources: Set<string>,\n unresolved: Set<string>,\n): string {\n return srcset\n .split(\",\")\n .map((entry) => {\n const trimmed = entry.trim();\n if (!trimmed) return entry;\n const [urlPart, descriptor] = trimmed.split(/\\s+/, 2);\n const normalized = normalizeAssetUrl(urlPart ?? \"\");\n if (!normalized) return entry;\n referencedSources.add(normalized);\n const ref = options.resolveAsset(normalized);\n if (!ref?.sourceAssetId) {\n unresolved.add(normalized);\n return entry;\n }\n const uploaded = uploadedBySourceId.get(ref.sourceAssetId);\n if (!uploaded) {\n unresolved.add(normalized);\n return entry;\n }\n const replaced = options.replaceWith(ref, uploaded);\n return descriptor ? `${replaced} ${descriptor}` : replaced;\n })\n .join(\", \");\n}\n\n/** Rewrite `<img src>` / `srcset` using uploaded asset targets supplied by the host sink. */\nexport function rewriteInlineImages(\n html: string,\n options: RewriteInlineImagesOptions,\n uploadedBySourceId: Map<string, UploadedAssetRef>,\n): RewriteInlineImagesResult {\n if (!html.trim()) {\n return { html, referencedSources: [], unresolved: [] };\n }\n\n const $ = cheerio.load(html, { xml: false });\n const referencedSources = new Set<string>();\n const unresolved = new Set<string>();\n\n $(\"img\").each((_, element) => {\n const img = $(element);\n const src = img.attr(\"src\")?.trim();\n if (src && !src.startsWith(\"data:\")) {\n const normalized = normalizeAssetUrl(src);\n if (normalized) {\n referencedSources.add(normalized);\n const ref = options.resolveAsset(normalized);\n if (!ref?.sourceAssetId) {\n unresolved.add(normalized);\n } else {\n const uploaded = uploadedBySourceId.get(ref.sourceAssetId);\n if (!uploaded) {\n unresolved.add(normalized);\n } else {\n img.attr(\"src\", options.replaceWith(ref, uploaded));\n }\n }\n }\n }\n\n const srcset = img.attr(\"srcset\")?.trim();\n if (srcset) {\n img.attr(\"srcset\", rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved));\n }\n });\n\n return {\n html: $.root().html() ?? html,\n referencedSources: [...referencedSources],\n unresolved: [...unresolved],\n };\n}\n","import * as cheerio from \"cheerio\";\n\nimport type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { discoverRawImgSrcs, normalizeAssetUrl } from \"../lib/content-asset-urls.js\";\nimport { findUnsupportedBlockMarkers } from \"../parsers/squarespace/parse-export.js\";\nexport interface DuplicateSlugConflict {\n entityType: \"post\" | \"page\";\n slug: string;\n sourceIds: string[];\n}\n\nexport interface MissingFeaturedImageConflict {\n postSourceId: string;\n featuredMediaSourceId: string;\n reason: string;\n}\n\nexport interface StaleAssetUrlConflict {\n sourceId: string;\n url: string;\n reason: string;\n}\n\nexport interface InvalidHtmlConflict {\n entityType: \"post\" | \"page\";\n sourceId: string;\n issues: string[];\n}\n\nexport interface UnresolvedInlineImageConflict {\n postOrPageSourceId: string;\n src: string;\n}\n\nexport interface UnsupportedBlockConflict {\n entityType: \"post\" | \"page\";\n sourceId: string;\n blockType: string;\n blockId?: string;\n}\n\nexport interface RedirectLoopConflict {\n fromPath: string;\n toPath: string;\n blocked: boolean;\n}\n\nexport interface ConflictReport {\n duplicatePostSlugs: DuplicateSlugConflict[];\n duplicatePageSlugs: DuplicateSlugConflict[];\n missingFeaturedImages: MissingFeaturedImageConflict[];\n staleAssetUrls: StaleAssetUrlConflict[];\n invalidHtml: InvalidHtmlConflict[];\n unresolvedInlineImages: UnresolvedInlineImageConflict[];\n unsupportedBlocks: UnsupportedBlockConflict[];\n redirectLoops: RedirectLoopConflict[];\n}\n\nexport function emptyConflictReport(): ConflictReport {\n return {\n duplicatePostSlugs: [],\n duplicatePageSlugs: [],\n missingFeaturedImages: [],\n staleAssetUrls: [],\n invalidHtml: [],\n unresolvedInlineImages: [],\n unsupportedBlocks: [],\n redirectLoops: [],\n };\n}\n\nfunction findDuplicateSlugs(\n items: { sourceId: string; slug: string }[],\n entityType: \"post\" | \"page\",\n): DuplicateSlugConflict[] {\n const bySlug = new Map<string, string[]>();\n for (const item of items) {\n const list = bySlug.get(item.slug) ?? [];\n list.push(item.sourceId);\n bySlug.set(item.slug, list);\n }\n\n const conflicts: DuplicateSlugConflict[] = [];\n for (const [slug, sourceIds] of bySlug) {\n if (sourceIds.length > 1) {\n conflicts.push({ entityType, slug, sourceIds });\n }\n }\n return conflicts;\n}\n\nfunction analyzeHtml(html: string): string[] {\n const issues: string[] = [];\n if (/<script\\b/i.test(html)) {\n issues.push(\"script_tag_present\");\n }\n\n try {\n const $ = cheerio.load(html, { xml: false });\n $(\"p\").each((_, el) => {\n const inner = $(el).html() ?? \"\";\n if (inner.includes(\"<p\")) {\n issues.push(\"nested_paragraph\");\n }\n });\n } catch {\n issues.push(\"html_parse_error\");\n }\n\n return [...new Set(issues)];\n}\n\nfunction mediaUrlSet(bundle: EntityBundle): Set<string> {\n const urls = new Set<string>();\n for (const asset of bundle.media) {\n const normalized = normalizeAssetUrl(asset.sourceUrl);\n if (normalized) urls.add(normalized);\n urls.add(asset.sourceUrl);\n }\n return urls;\n}\n\nfunction findUnresolvedInlineImages(\n sourceId: string,\n contentHtml: string,\n mediaUrls: Set<string>,\n): UnresolvedInlineImageConflict[] {\n const conflicts: UnresolvedInlineImageConflict[] = [];\n for (const raw of discoverRawImgSrcs(contentHtml)) {\n const normalized = normalizeAssetUrl(raw);\n if (!normalized) continue;\n if (!mediaUrls.has(normalized) && !mediaUrls.has(raw)) {\n conflicts.push({ postOrPageSourceId: sourceId, src: raw });\n }\n }\n return conflicts;\n}\n\nfunction findUnsupportedBlocks(\n entityType: \"post\" | \"page\",\n sourceId: string,\n contentHtml: string,\n): UnsupportedBlockConflict[] {\n return findUnsupportedBlockMarkers(contentHtml).map((marker) => ({\n entityType,\n sourceId,\n blockType: marker.blockType,\n blockId: marker.blockId,\n }));\n}\n\nexport function analyzeConflicts(\n bundle: EntityBundle,\n options?: {\n staleAssetUrls?: StaleAssetUrlConflict[];\n redirectLoops?: RedirectLoopConflict[];\n },\n): ConflictReport {\n const report = emptyConflictReport();\n const mediaUrls = mediaUrlSet(bundle);\n\n report.duplicatePostSlugs = findDuplicateSlugs(bundle.posts, \"post\");\n report.duplicatePageSlugs = findDuplicateSlugs(bundle.pages, \"page\");\n\n for (const post of bundle.posts) {\n if (post.sourceFeaturedMediaId && !post.featuredAssetSourceId) {\n report.missingFeaturedImages.push({\n postSourceId: post.sourceId,\n featuredMediaSourceId: post.sourceFeaturedMediaId,\n reason: \"attachment_not_in_export\",\n });\n }\n\n const htmlIssues = analyzeHtml(post.contentHtml);\n if (htmlIssues.length) {\n report.invalidHtml.push({\n entityType: \"post\",\n sourceId: post.sourceId,\n issues: htmlIssues,\n });\n }\n\n report.unresolvedInlineImages.push(\n ...findUnresolvedInlineImages(post.sourceId, post.contentHtml, mediaUrls),\n );\n report.unsupportedBlocks.push(\n ...findUnsupportedBlocks(\"post\", post.sourceId, post.contentHtml),\n );\n }\n\n for (const page of bundle.pages) {\n const htmlIssues = analyzeHtml(page.contentHtml);\n if (htmlIssues.length) {\n report.invalidHtml.push({\n entityType: \"page\",\n sourceId: page.sourceId,\n issues: htmlIssues,\n });\n }\n\n report.unresolvedInlineImages.push(\n ...findUnresolvedInlineImages(page.sourceId, page.contentHtml, mediaUrls),\n );\n report.unsupportedBlocks.push(\n ...findUnsupportedBlocks(\"page\", page.sourceId, page.contentHtml),\n );\n }\n\n if (options?.staleAssetUrls) {\n report.staleAssetUrls = options.staleAssetUrls;\n }\n if (options?.redirectLoops) {\n report.redirectLoops = options.redirectLoops;\n }\n\n return report;\n}\n\nexport function hasBlockingConflicts(report: ConflictReport): boolean {\n return report.duplicatePageSlugs.length > 0 || report.redirectLoops.some((r) => r.blocked);\n}\n\nexport function hasWarnings(report: ConflictReport): boolean {\n return (\n report.duplicatePostSlugs.length > 0 ||\n report.missingFeaturedImages.length > 0 ||\n report.staleAssetUrls.length > 0 ||\n report.invalidHtml.length > 0 ||\n report.unresolvedInlineImages.length > 0 ||\n report.unsupportedBlocks.length > 0\n );\n}\n\nexport function buildRedirectMap(bundle: EntityBundle): {\n fromPath: string;\n toPath: string;\n statusCode: number;\n}[] {\n const redirects: { fromPath: string; toPath: string; statusCode: number }[] = [];\n\n for (const post of bundle.posts) {\n const from = post.source.path;\n if (!from) continue;\n const to = `/blog/${post.slug}`;\n if (from.replace(/\\/$/, \"\") === to.replace(/\\/$/, \"\")) continue;\n redirects.push({ fromPath: from, toPath: to, statusCode: 301 });\n }\n\n for (const page of bundle.pages) {\n const from = page.source.path;\n if (!from) continue;\n const to = `/${page.slug}`;\n if (from.replace(/\\/$/, \"\") === to.replace(/\\/$/, \"\")) continue;\n redirects.push({ fromPath: from, toPath: to, statusCode: 301 });\n }\n\n return redirects;\n}\n\nexport function detectRedirectLoops(\n redirects: { fromPath: string; toPath: string }[],\n): RedirectLoopConflict[] {\n const loops: RedirectLoopConflict[] = [];\n for (const row of redirects) {\n if (row.fromPath.replace(/\\/$/, \"\") === row.toPath.replace(/\\/$/, \"\")) {\n loops.push({ fromPath: row.fromPath, toPath: row.toPath, blocked: true });\n }\n }\n return loops;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { discoverContentAssetUrls } from \"../../lib/content-asset-urls.js\";\nimport { linkToPath, sanitizeSlug } from \"../../lib/utility.js\";\nimport type {\n NormalizedAsset,\n NormalizedCategory,\n NormalizedEntity,\n NormalizedPage,\n NormalizedPost,\n NormalizedTag,\n PublishStatus,\n SourceMetadata,\n} from \"../../normalizer/types.js\";\nimport {\n SquarespaceCollectionClient,\n type SquarespaceClientOptions,\n type SquarespaceCollectTarget,\n} from \"./collect.js\";\nimport type {\n SquarespaceBlock,\n SquarespaceExport,\n SquarespaceGalleryItem,\n SquarespacePage,\n SquarespacePost,\n} from \"./types.js\";\n\nconst PLATFORM = \"squarespace\" as const;\nconst UNSUPPORTED_ATTR = \"data-artinstack-unsupported-block\";\nconst BLOCK_ID_ATTR = \"data-artinstack-block-id\";\n\n/** Block types flattened to HTML without a conflict flag. */\nconst SUPPORTED_BLOCK_TYPES = new Set([\n \"html\",\n \"text\",\n \"markdown\",\n \"image\",\n \"gallery\",\n \"quote\",\n \"button\",\n \"video\",\n \"code\",\n \"spacer\",\n \"line\",\n \"horizontalrule\",\n \"hr\",\n]);\n\n/** Known Squarespace block types that cannot be migrated as static HTML snapshots. */\nconst UNSUPPORTED_BLOCK_TYPES = new Set([\n \"product\",\n \"products\",\n \"form\",\n \"newsletter\",\n \"donation\",\n \"calendar\",\n \"chart\",\n \"map\",\n \"music\",\n \"social\",\n \"summary\",\n \"archive\",\n \"acuity\",\n \"member-area\",\n \"digital-product\",\n \"folder\",\n \"index\",\n \"tock\",\n \"opentable\",\n \"soundcloud\",\n \"foursquare\",\n]);\n\nexport interface SquarespaceParseOptions {\n filePath?: string;\n data?: SquarespaceExport;\n /** Pre-constructed json-pretty collector (live crawl). */\n client?: SquarespaceCollectionClient;\n /** Shorthand targets when constructing a client inline. */\n collectTargets?: SquarespaceCollectTarget[];\n clientOptions?: SquarespaceClientOptions;\n}\n\nexport interface FlattenBlocksResult {\n contentHtml: string;\n assetUrls: string[];\n}\n\nfunction sourceMeta(id: string, url?: string, exportedAt?: string): SourceMetadata {\n return {\n platform: PLATFORM,\n id,\n url,\n path: linkToPath(url),\n exportedAt,\n };\n}\n\nfunction mapPublishStatus(status: string | undefined): PublishStatus {\n switch ((status ?? \"published\").toLowerCase()) {\n case \"published\":\n return \"published\";\n case \"draft\":\n case \"scheduled\":\n return \"draft\";\n default:\n return \"archived\";\n }\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nfunction blockShell(type: string, inner: string, blockId?: string): string {\n const idAttr = blockId ? ` id=\"sqs-block-${blockId}\"` : \"\";\n return `<div class=\"sqs-block sqs-block-${type}\"${idAttr}>${inner}</div>`;\n}\n\nfunction unsupportedPlaceholder(type: string, blockId?: string): string {\n const idPart = blockId ? ` ${BLOCK_ID_ATTR}=\"${escapeHtml(blockId)}\"` : \"\";\n return `<div class=\"sqs-block sqs-block-unsupported\" ${UNSUPPORTED_ATTR}=\"${escapeHtml(type)}\"${idPart} aria-hidden=\"true\"></div>`;\n}\n\nfunction flattenGalleryItem(item: SquarespaceGalleryItem): string {\n const alt = item.altText ? ` alt=\"${escapeHtml(item.altText)}\"` : \"\";\n const caption = item.caption ? `<figcaption>${item.caption}</figcaption>` : \"\";\n return `<figure><img src=\"${escapeHtml(item.imageUrl)}\"${alt} />${caption}</figure>`;\n}\n\nexport function flattenSquarespaceBlock(block: SquarespaceBlock): FlattenBlocksResult {\n const type = block.type.toLowerCase();\n const blockId = block.id;\n const assetUrls: string[] = [];\n\n if (UNSUPPORTED_BLOCK_TYPES.has(type)) {\n return {\n contentHtml: unsupportedPlaceholder(type, blockId),\n assetUrls,\n };\n }\n\n if (!SUPPORTED_BLOCK_TYPES.has(type)) {\n return {\n contentHtml: unsupportedPlaceholder(type || \"unknown\", blockId),\n assetUrls,\n };\n }\n\n switch (type) {\n case \"html\":\n case \"text\":\n return {\n contentHtml: blockShell(type, block.html ?? block.value ?? \"\", blockId),\n assetUrls,\n };\n\n case \"markdown\":\n return {\n contentHtml: blockShell(\n type,\n block.html ?? `<div class=\"sqs-markdown\">${escapeHtml(block.value ?? \"\")}</div>`,\n blockId,\n ),\n assetUrls,\n };\n\n case \"image\": {\n const url = block.imageUrl ?? \"\";\n if (url) assetUrls.push(url);\n const alt = block.altText ? ` alt=\"${escapeHtml(block.altText)}\"` : \"\";\n const caption = block.caption ? `<figcaption>${block.caption}</figcaption>` : \"\";\n const inner = url\n ? `<figure><img src=\"${escapeHtml(url)}\"${alt} />${caption}</figure>`\n : \"\";\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"gallery\": {\n const figures = (block.items ?? [])\n .map((item) => {\n assetUrls.push(item.imageUrl);\n return flattenGalleryItem(item);\n })\n .join(\"\");\n return {\n contentHtml: blockShell(type, `<div class=\"sqs-gallery\">${figures}</div>`, blockId),\n assetUrls,\n };\n }\n\n case \"quote\": {\n const inner = block.html ?? `<blockquote>${escapeHtml(block.value ?? \"\")}</blockquote>`;\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"button\": {\n const href = block.url ?? \"#\";\n const label = escapeHtml(block.label ?? block.value ?? \"Learn more\");\n return {\n contentHtml: blockShell(\n type,\n `<p><a class=\"sqs-block-button\" href=\"${escapeHtml(href)}\">${label}</a></p>`,\n blockId,\n ),\n assetUrls,\n };\n }\n\n case \"video\": {\n const inner =\n block.embedHtml ??\n block.html ??\n (block.url ? `<p><a href=\"${escapeHtml(block.url)}\">Video</a></p>` : \"\");\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"code\": {\n const inner =\n block.html ??\n `<pre><code>${escapeHtml(block.value ?? \"\")}</code></pre>`;\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"spacer\":\n return {\n contentHtml: blockShell(type, `<div class=\"sqs-spacer\" aria-hidden=\"true\"></div>`, blockId),\n assetUrls,\n };\n\n case \"line\":\n case \"horizontalrule\":\n case \"hr\":\n return { contentHtml: blockShell(\"line\", \"<hr />\", blockId), assetUrls };\n\n default:\n return {\n contentHtml: unsupportedPlaceholder(type, blockId),\n assetUrls,\n };\n }\n}\n\nexport function flattenSquarespaceBlocks(blocks: SquarespaceBlock[]): FlattenBlocksResult {\n const parts: string[] = [];\n const assetUrls: string[] = [];\n for (const block of blocks) {\n const flattened = flattenSquarespaceBlock(block);\n parts.push(flattened.contentHtml);\n assetUrls.push(...flattened.assetUrls);\n }\n return {\n contentHtml: parts.join(\"\\n\"),\n assetUrls,\n };\n}\n\nfunction resolveContentHtml(\n entity: SquarespacePage | SquarespacePost,\n): FlattenBlocksResult {\n if (entity.blocks?.length) {\n return flattenSquarespaceBlocks(entity.blocks);\n }\n const html = entity.contentHtml ?? \"\";\n return {\n contentHtml: html,\n assetUrls: [...discoverContentAssetUrls(html)],\n };\n}\n\nfunction guessMime(filename: string): string | undefined {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const map: Record<string, string> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n };\n return ext ? map[ext] : undefined;\n}\n\nfunction filenameFromUrl(url: string, fallback: string): string {\n try {\n return basename(new URL(url).pathname) || fallback;\n } catch {\n return basename(url.split(\"?\")[0] ?? \"\") || fallback;\n }\n}\n\nfunction assetFromUrl(\n url: string,\n exportedAt: string | undefined,\n index: number,\n): NormalizedAsset {\n const filename = filenameFromUrl(url, `asset-${index}.jpg`);\n const sourceId = `asset-${sanitizeSlug(filename)}-${index}`;\n return {\n type: \"asset\",\n source: sourceMeta(sourceId, url, exportedAt),\n sourceId,\n sourceUrl: url,\n filename,\n mimeType: guessMime(filename),\n };\n}\n\nexport function isSquarespaceExport(value: unknown): value is SquarespaceExport {\n if (!value || typeof value !== \"object\") return false;\n const record = value as SquarespaceExport;\n const version = record.exportVersion;\n return (version === 1 || version === \"1\") && Array.isArray(record.pages);\n}\n\nexport async function loadSquarespaceExport(\n options: SquarespaceParseOptions,\n): Promise<SquarespaceExport> {\n if (options.data) return options.data;\n if (options.client) {\n if (!options.collectTargets?.length) {\n throw new Error(\"Squarespace client.collectExport requires collectTargets\");\n }\n return options.client.collectExport(options.collectTargets);\n }\n if (options.collectTargets?.length) {\n const client = new SquarespaceCollectionClient(options.clientOptions);\n return client.collectExport(options.collectTargets);\n }\n if (!options.filePath) {\n throw new Error(\"Squarespace parser requires filePath, data, client, or collectTargets\");\n }\n const raw: unknown = JSON.parse(await readFile(options.filePath, \"utf8\"));\n if (isSquarespaceExport(raw)) return raw;\n throw new Error(\"Invalid Squarespace export: expected exportVersion 1 with pages[]\");\n}\n\nfunction* emitAssetsFromContent(\n contentHtml: string,\n explicitUrls: string[],\n exportedAt?: string,\n): Generator<NormalizedAsset> {\n const seen = new Set<string>();\n const urls = [...explicitUrls, ...discoverContentAssetUrls(contentHtml)];\n let index = 0;\n for (const url of urls) {\n if (seen.has(url)) continue;\n seen.add(url);\n yield assetFromUrl(url, exportedAt, index);\n index += 1;\n }\n}\n\nasync function* emitPage(page: SquarespacePage, exportedAt?: string): AsyncGenerator<NormalizedEntity> {\n const { contentHtml, assetUrls } = resolveContentHtml(page);\n yield {\n type: \"page\",\n source: sourceMeta(page.id, page.url, exportedAt),\n sourceId: page.id,\n title: page.title,\n slug: sanitizeSlug(page.slug),\n contentHtml,\n contentCss: page.contentCss,\n isHomePage: page.isHomePage,\n status: mapPublishStatus(page.status),\n seoTitle: page.seoTitle,\n seoDescription: page.seoDescription,\n } satisfies NormalizedPage;\n\n yield* emitAssetsFromContent(contentHtml, assetUrls, exportedAt);\n}\n\nasync function* emitPost(post: SquarespacePost, exportedAt?: string): AsyncGenerator<NormalizedEntity> {\n const { contentHtml, assetUrls } = resolveContentHtml(post);\n\n let featuredAssetSourceId: string | undefined;\n if (post.featuredImageUrl) {\n featuredAssetSourceId = `featured-${post.id}`;\n }\n\n yield {\n type: \"post\",\n source: sourceMeta(post.id, post.url, exportedAt),\n sourceId: post.id,\n title: post.title,\n slug: sanitizeSlug(post.slug),\n excerpt: post.excerpt,\n contentHtml,\n publishedAt: post.publishedAt,\n status: mapPublishStatus(post.status),\n categorySlugs: post.categorySlugs,\n tagSlugs: post.tagSlugs,\n featuredAssetSourceId,\n seoTitle: post.seoTitle,\n seoDescription: post.seoDescription,\n } satisfies NormalizedPost;\n\n if (post.featuredImageUrl) {\n const filename = filenameFromUrl(post.featuredImageUrl, `${post.id}-featured.jpg`);\n yield {\n type: \"asset\",\n source: sourceMeta(featuredAssetSourceId!, post.featuredImageUrl, exportedAt),\n sourceId: featuredAssetSourceId!,\n sourceUrl: post.featuredImageUrl,\n filename,\n mimeType: guessMime(filename),\n } satisfies NormalizedAsset;\n }\n\n yield* emitAssetsFromContent(contentHtml, assetUrls, exportedAt);\n}\n\n/** Parse Squarespace JSON export → normalizer DTOs (static HTML snapshots). */\nexport async function* enumerateSquarespaceEntities(\n options: SquarespaceParseOptions,\n): AsyncGenerator<NormalizedEntity> {\n const doc = await loadSquarespaceExport(options);\n const exportedAt = doc.exportedAt;\n\n for (const category of doc.categories ?? []) {\n yield {\n type: \"category\",\n source: sourceMeta(category.id, undefined, exportedAt),\n sourceId: category.id,\n name: category.name,\n slug: sanitizeSlug(category.slug),\n } satisfies NormalizedCategory;\n }\n\n for (const tag of doc.tags ?? []) {\n yield {\n type: \"tag\",\n source: sourceMeta(tag.id, undefined, exportedAt),\n sourceId: tag.id,\n name: tag.name,\n slug: sanitizeSlug(tag.slug),\n } satisfies NormalizedTag;\n }\n\n for (const page of doc.pages) {\n yield* emitPage(page, exportedAt);\n }\n\n for (const post of doc.posts ?? []) {\n yield* emitPost(post, exportedAt);\n }\n}\n\nexport function summarizeSquarespaceExport(doc: SquarespaceExport): {\n pages: number;\n posts: number;\n categories: number;\n tags: number;\n} {\n return {\n pages: doc.pages.length,\n posts: doc.posts?.length ?? 0,\n categories: doc.categories?.length ?? 0,\n tags: doc.tags?.length ?? 0,\n };\n}\n\nexport async function validateSquarespaceExportFile(filePath: string): Promise<{\n ok: boolean;\n issues: { code: string; message: string }[];\n summary: Record<string, number>;\n}> {\n const issues: { code: string; message: string }[] = [];\n let doc: SquarespaceExport;\n try {\n doc = await loadSquarespaceExport({ filePath });\n } catch (error) {\n return {\n ok: false,\n issues: [\n {\n code: \"invalid_export\",\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n summary: {},\n };\n }\n\n if (doc.pages.length === 0 && (doc.posts?.length ?? 0) === 0) {\n issues.push({ code: \"empty_export\", message: \"No pages or posts in export\" });\n }\n\n const summary = summarizeSquarespaceExport(doc);\n return {\n ok: issues.length === 0,\n issues,\n summary: {\n pages: summary.pages,\n posts: summary.posts,\n categories: summary.categories,\n tags: summary.tags,\n portfolios: 0,\n assets: 0,\n },\n };\n}\n\n/** @internal Scan flattened HTML for unsupported block markers (used by conflict analysis). */\nexport function findUnsupportedBlockMarkers(html: string): { blockType: string; blockId?: string }[] {\n const markers: { blockType: string; blockId?: string }[] = [];\n const pattern =\n /data-artinstack-unsupported-block=\"([^\"]+)\"(?:\\s+data-artinstack-block-id=\"([^\"]*)\")?/g;\n for (const match of html.matchAll(pattern)) {\n markers.push({\n blockType: match[1] ?? \"unknown\",\n blockId: match[2] || undefined,\n });\n }\n return markers;\n}\n\nexport { SUPPORTED_BLOCK_TYPES, UNSUPPORTED_BLOCK_TYPES, UNSUPPORTED_ATTR, BLOCK_ID_ATTR };\n","/** Lowercase URL-safe slug from WordPress post_name or title. */\nexport function sanitizeSlug(raw: string): string {\n return raw\n .trim()\n .toLowerCase()\n .replace(/&[^;]+;/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 200);\n}\n\n/** Normalize absolute permalink to root-relative path. */\nexport function linkToPath(link: string | undefined): string | undefined {\n if (!link) return undefined;\n try {\n const url = new URL(link);\n const path = url.pathname;\n if (!path || path === \"/\") return \"/\";\n return path.endsWith(\"/\") ? path : `${path}/`;\n } catch {\n if (link.startsWith(\"/\")) {\n return link.endsWith(\"/\") ? link : `${link}/`;\n }\n return undefined;\n }\n}\n","import * as cheerio from \"cheerio\";\nimport { z } from \"zod\";\n\nimport { sanitizeSlug } from \"../../lib/utility.js\";\nimport type {\n SquarespaceBlock,\n SquarespaceCategory,\n SquarespaceExport,\n SquarespaceGalleryItem,\n SquarespacePage,\n SquarespacePost,\n SquarespaceTag,\n} from \"./types.js\";\n\nexport const SQUARESPACE_JSON_FORMAT = \"json-pretty\" as const;\nexport const SQUARESPACE_JSON_FORMAT_COMPACT = \"json\" as const;\n\nexport type SquarespaceJsonFormat =\n | typeof SQUARESPACE_JSON_FORMAT\n | typeof SQUARESPACE_JSON_FORMAT_COMPACT;\n\nexport const squarespaceClientOptionsSchema = z.object({\n format: z.enum([\"json\", \"json-pretty\"]).default(\"json-pretty\"),\n maxRetries: z.number().int().min(0).max(10).default(3),\n retryBaseDelayMs: z.number().int().min(0).default(500),\n maxRetryDelayMs: z.number().int().min(0).default(8000),\n requestIntervalMs: z.number().int().min(0).default(200),\n fetchImpl: z.custom<typeof fetch>().optional(),\n});\n\nexport type SquarespaceClientOptions = z.input<typeof squarespaceClientOptionsSchema>;\n\nexport interface SquarespaceCollectTarget {\n /** Page or collection URL on the live Squarespace site (without format query). */\n url: string;\n /** `collection` paginates `items[]`; `page` fetches a single static page/item. */\n kind?: \"auto\" | \"page\" | \"collection\";\n isHomePage?: boolean;\n}\n\ninterface WireRecord {\n [key: string]: unknown;\n}\n\ninterface WirePagination {\n nextPage?: boolean;\n nextPageUrl?: string;\n}\n\nfunction isRecord(value: unknown): value is WireRecord {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asRecord(value: unknown): WireRecord | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((entry): entry is string => typeof entry === \"string\");\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Append Squarespace `?format=json-pretty` (or `json`) to a site URL. */\nexport function buildJsonPrettyUrl(\n pageUrl: string,\n format: SquarespaceJsonFormat = SQUARESPACE_JSON_FORMAT,\n): string {\n const url = new URL(pageUrl);\n url.searchParams.set(\"format\", format);\n return url.toString();\n}\n\nfunction mapWorkflowState(state: unknown): SquarespacePage[\"status\"] {\n if (state === 1 || state === \"1\") return \"published\";\n if (state === 2 || state === \"2\") return \"draft\";\n return \"published\";\n}\n\nfunction mapPublishOn(value: unknown): string | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return new Date(value).toISOString();\n}\n\nfunction readSeo(seoData: unknown, field: \"title\" | \"description\"): string | undefined {\n const record = asRecord(seoData);\n if (!record) return undefined;\n const value = record[field];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** Infer block type from Squarespace LayoutEngine / Fluid Engine class names. */\nexport function inferBlockTypeFromClassName(className: string): string {\n const match = className.match(/\\bsqs-block-([a-z0-9-]+)\\b/i);\n if (!match?.[1]) return \"html\";\n const raw = match[1].toLowerCase();\n if (raw === \"horizontalrule\") return \"line\";\n return raw.replace(/-block$/g, \"\");\n}\n\n/** Parse rendered `body` HTML into block entries when wire JSON has no structured blocks. */\nexport function extractBlocksFromBodyHtml(html: string): SquarespaceBlock[] {\n if (!html.trim()) return [];\n const $ = cheerio.load(html, { xml: false });\n const blocks: SquarespaceBlock[] = [];\n\n $(\".sqs-block\").each((_, element) => {\n const el = $(element);\n const className = el.attr(\"class\") ?? \"\";\n const type = inferBlockTypeFromClassName(className);\n const id = el.attr(\"id\")?.replace(/^block-/, \"\");\n const content = el.find(\".sqs-block-content\").first();\n const innerHtml = (content.length ? content.html() : el.html()) ?? \"\";\n\n if (type === \"image\") {\n const img = content.find(\"img\").first();\n const imageUrl = img.attr(\"data-src\") ?? img.attr(\"src\") ?? undefined;\n blocks.push({\n id,\n type,\n imageUrl,\n altText: img.attr(\"alt\") ?? undefined,\n caption: content.find(\"figcaption\").text() || undefined,\n html: innerHtml || undefined,\n });\n return;\n }\n\n if (type === \"gallery\") {\n const items: SquarespaceGalleryItem[] = [];\n content.find(\"img\").each((idx, imgEl) => {\n const img = $(imgEl);\n const imageUrl = img.attr(\"data-src\") ?? img.attr(\"src\");\n if (!imageUrl) return;\n items.push({\n id: img.attr(\"data-image-id\") ?? `gallery-${idx}`,\n imageUrl,\n altText: img.attr(\"alt\") ?? undefined,\n });\n });\n blocks.push({ id, type, items, html: innerHtml || undefined });\n return;\n }\n\n if (type === \"button\") {\n const anchor = content.find(\"a\").first();\n blocks.push({\n id,\n type,\n url: anchor.attr(\"href\") ?? undefined,\n label: anchor.text() || undefined,\n html: innerHtml || undefined,\n });\n return;\n }\n\n if (type === \"video\" || type === \"embed\") {\n const iframe = content.find(\"iframe\").first();\n blocks.push({\n id,\n type: type === \"embed\" ? \"embed\" : \"video\",\n embedHtml: iframe.length ? $.html(iframe) : innerHtml || undefined,\n html: innerHtml || undefined,\n });\n return;\n }\n\n blocks.push({\n id,\n type,\n html: innerHtml || undefined,\n value: type === \"markdown\" || type === \"quote\" ? content.text() : undefined,\n });\n });\n\n return blocks;\n}\n\nfunction mapWireBlocks(value: unknown): SquarespaceBlock[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const blocks: SquarespaceBlock[] = [];\n for (const entry of value) {\n const record = asRecord(entry);\n if (!record) continue;\n const type = String(record.type ?? record.blockType ?? \"html\");\n blocks.push({\n id: record.id ? String(record.id) : undefined,\n type,\n html: typeof record.html === \"string\" ? record.html : undefined,\n value: typeof record.value === \"string\" ? record.value : undefined,\n imageUrl:\n typeof record.imageUrl === \"string\"\n ? record.imageUrl\n : typeof record.assetUrl === \"string\"\n ? record.assetUrl\n : undefined,\n altText: typeof record.altText === \"string\" ? record.altText : undefined,\n caption: typeof record.caption === \"string\" ? record.caption : undefined,\n url: typeof record.url === \"string\" ? record.url : undefined,\n label: typeof record.label === \"string\" ? record.label : undefined,\n embedHtml: typeof record.embedHtml === \"string\" ? record.embedHtml : undefined,\n items: Array.isArray(record.items)\n ? record.items\n .map((item) => asRecord(item))\n .filter((item): item is WireRecord => !!item)\n .map((item) => ({\n id: item.id ? String(item.id) : undefined,\n imageUrl: String(item.imageUrl ?? item.assetUrl ?? \"\"),\n altText: typeof item.altText === \"string\" ? item.altText : undefined,\n caption: typeof item.caption === \"string\" ? item.caption : undefined,\n }))\n .filter((item) => item.imageUrl.length > 0)\n : undefined,\n });\n }\n return blocks.length > 0 ? blocks : undefined;\n}\n\nfunction mapStructuredBlocksFromItem(item: WireRecord): SquarespaceBlock[] | undefined {\n const direct = mapWireBlocks(item.blocks);\n if (direct?.length) return direct;\n\n const sections = item.sections;\n if (!Array.isArray(sections)) return undefined;\n\n const flattened: SquarespaceBlock[] = [];\n for (const section of sections) {\n const sectionRecord = asRecord(section);\n if (!sectionRecord) continue;\n const rows = sectionRecord.rows;\n if (!Array.isArray(rows)) continue;\n for (const row of rows) {\n const rowRecord = asRecord(row);\n if (!rowRecord) continue;\n const columns = rowRecord.columns;\n if (!Array.isArray(columns)) continue;\n for (const column of columns) {\n const columnRecord = asRecord(column);\n if (!columnRecord) continue;\n const blocks = mapWireBlocks(columnRecord.blocks);\n if (blocks) flattened.push(...blocks);\n }\n }\n }\n return flattened.length > 0 ? flattened : undefined;\n}\n\nfunction mapWireItemContent(item: WireRecord): Pick<SquarespacePage, \"blocks\" | \"contentHtml\"> {\n const structured = mapStructuredBlocksFromItem(item);\n if (structured?.length) {\n return { blocks: structured };\n }\n\n const body = typeof item.body === \"string\" ? item.body : undefined;\n if (!body) return { contentHtml: \"\" };\n\n const parsedBlocks = extractBlocksFromBodyHtml(body);\n if (parsedBlocks.length > 0) {\n return { blocks: parsedBlocks };\n }\n return { contentHtml: body };\n}\n\nfunction isBlogCollection(collection: WireRecord | undefined): boolean {\n if (!collection) return false;\n const ordering = String(collection.ordering ?? \"\").toLowerCase();\n if (ordering === \"chronological\" || ordering === \"calendar\") return true;\n const typeName = String(collection.typeName ?? collection.typeLabel ?? \"\").toLowerCase();\n return typeName.includes(\"blog\");\n}\n\nfunction isStaticPageItem(item: WireRecord, collection: WireRecord | undefined): boolean {\n const recordTypeLabel = String(item.recordTypeLabel ?? \"\").toLowerCase();\n if (recordTypeLabel.includes(\"page\")) return true;\n const collectionType = String(collection?.typeName ?? collection?.typeLabel ?? \"\").toLowerCase();\n return collectionType === \"page\" || collectionType.includes(\"page-collection\");\n}\n\nfunction mapWireItemToPost(item: WireRecord): SquarespacePost {\n const content = mapWireItemContent(item);\n return {\n id: String(item.id ?? item.systemDataId ?? item.urlId ?? \"\"),\n title: String(item.title ?? \"Untitled\"),\n slug: sanitizeSlug(String(item.urlId ?? item.title ?? item.id ?? \"post\")),\n url: typeof item.fullUrl === \"string\" ? item.fullUrl : undefined,\n excerpt: typeof item.excerpt === \"string\" ? item.excerpt : undefined,\n publishedAt: mapPublishOn(item.publishOn ?? item.addedOn),\n status: mapWorkflowState(item.workflowState),\n categorySlugs: asStringArray(item.categories).map((slug) => sanitizeSlug(slug)),\n tagSlugs: asStringArray(item.tags).map((slug) => sanitizeSlug(slug)),\n featuredImageUrl: typeof item.assetUrl === \"string\" ? item.assetUrl : undefined,\n seoTitle: readSeo(item.seoData, \"title\"),\n seoDescription: readSeo(item.seoData, \"description\"),\n ...content,\n };\n}\n\nfunction mapWireItemToPage(\n item: WireRecord,\n options?: { isHomePage?: boolean; fallbackUrl?: string },\n): SquarespacePage {\n const content = mapWireItemContent(item);\n return {\n id: String(item.id ?? item.urlId ?? \"\"),\n title: String(item.title ?? \"Untitled\"),\n slug: sanitizeSlug(String(item.urlId ?? item.title ?? item.id ?? \"page\")),\n url:\n typeof item.fullUrl === \"string\"\n ? item.fullUrl\n : options?.fallbackUrl,\n status: mapWorkflowState(item.workflowState),\n isHomePage: options?.isHomePage,\n seoTitle: readSeo(item.seoData, \"title\"),\n seoDescription: readSeo(item.seoData, \"description\"),\n ...content,\n };\n}\n\nfunction mapWireCategories(collection: WireRecord | undefined): SquarespaceCategory[] {\n if (!collection) return [];\n return asStringArray(collection.categories).map((name) => ({\n id: `cat-${sanitizeSlug(name)}`,\n name,\n slug: sanitizeSlug(name),\n }));\n}\n\nfunction mapWireTags(items: WireRecord[]): SquarespaceTag[] {\n const seen = new Map<string, SquarespaceTag>();\n for (const item of items) {\n for (const tag of asStringArray(item.tags)) {\n const slug = sanitizeSlug(tag);\n if (!seen.has(slug)) {\n seen.set(slug, { id: `tag-${slug}`, name: tag, slug });\n }\n }\n }\n return [...seen.values()];\n}\n\nfunction siteFromWire(wire: WireRecord): SquarespaceExport[\"site\"] {\n const website = asRecord(wire.website);\n if (!website) return undefined;\n const url =\n typeof website.authenticUrl === \"string\"\n ? website.authenticUrl\n : typeof website.baseUrl === \"string\"\n ? website.baseUrl\n : undefined;\n const title = typeof website.siteTitle === \"string\" ? website.siteTitle : undefined;\n if (!url && !title) return undefined;\n return { url, title };\n}\n\n/** Map one Squarespace `?format=json-pretty` response into export partials. */\nexport function mapJsonPrettyWire(\n wire: unknown,\n context?: { fetchedUrl?: string; isHomePage?: boolean },\n): Partial<SquarespaceExport> {\n if (!isRecord(wire)) {\n throw new Error(\"Invalid Squarespace json-pretty response\");\n }\n\n const collection = asRecord(wire.collection);\n const partial: Partial<SquarespaceExport> = {\n site: siteFromWire(wire),\n pages: [],\n posts: [],\n categories: mapWireCategories(collection),\n tags: [],\n };\n\n if (Array.isArray(wire.items)) {\n const itemRecords = wire.items\n .map((entry) => asRecord(entry))\n .filter((entry): entry is WireRecord => !!entry);\n\n partial.tags = mapWireTags(itemRecords);\n\n for (const item of itemRecords) {\n if (isStaticPageItem(item, collection)) {\n partial.pages!.push(\n mapWireItemToPage(item, { fallbackUrl: context?.fetchedUrl, isHomePage: context?.isHomePage }),\n );\n } else {\n partial.posts!.push(mapWireItemToPost(item));\n }\n }\n return partial;\n }\n\n const item = asRecord(wire.item);\n if (item) {\n if (isStaticPageItem(item, collection)) {\n partial.pages!.push(\n mapWireItemToPage(item, { fallbackUrl: context?.fetchedUrl, isHomePage: context?.isHomePage }),\n );\n } else {\n partial.posts!.push(mapWireItemToPost(item));\n partial.tags = mapWireTags([item]);\n }\n return partial;\n }\n\n if (collection && isBlogCollection(collection) === false) {\n partial.pages!.push(\n mapWireItemToPage(\n {\n id: collection.id ?? collection.urlId ?? collection.fullUrl,\n title: collection.title ?? collection.navigationTitle,\n urlId: collection.urlId,\n fullUrl: collection.fullUrl ?? context?.fetchedUrl,\n body: collection.description,\n workflowState: collection.draft ? 2 : 1,\n seoData: collection.seoData,\n },\n { fallbackUrl: context?.fetchedUrl, isHomePage: context?.isHomePage },\n ),\n );\n }\n\n return partial;\n}\n\nfunction dedupeById<T extends { id: string }>(items: T[]): T[] {\n const seen = new Map<string, T>();\n for (const item of items) {\n seen.set(item.id, item);\n }\n return [...seen.values()];\n}\n\nfunction dedupeBySlug<T extends { slug: string }>(items: T[]): T[] {\n const seen = new Map<string, T>();\n for (const item of items) {\n seen.set(item.slug, item);\n }\n return [...seen.values()];\n}\n\n/** Merge multiple mapped partial exports into one canonical `SquarespaceExport`. */\nexport function mergeSquarespaceExportPartials(\n partials: Partial<SquarespaceExport>[],\n): SquarespaceExport {\n const merged: SquarespaceExport = {\n exportVersion: 1,\n exportedAt: new Date().toISOString(),\n pages: [],\n posts: [],\n categories: [],\n tags: [],\n };\n\n for (const partial of partials) {\n if (partial.site) merged.site = { ...merged.site, ...partial.site };\n merged.pages.push(...(partial.pages ?? []));\n merged.posts!.push(...(partial.posts ?? []));\n merged.categories!.push(...(partial.categories ?? []));\n merged.tags!.push(...(partial.tags ?? []));\n }\n\n merged.pages = dedupeById(merged.pages);\n merged.posts = dedupeById(merged.posts ?? []);\n merged.categories = dedupeBySlug(merged.categories ?? []);\n merged.tags = dedupeBySlug(merged.tags ?? []);\n return merged;\n}\n\nfunction paginationFromWire(wire: unknown): WirePagination | undefined {\n return asRecord(wire)?.pagination as WirePagination | undefined;\n}\n\nfunction inferTargetKind(target: SquarespaceCollectTarget): \"page\" | \"collection\" {\n if (target.kind && target.kind !== \"auto\") return target.kind;\n try {\n const pathname = new URL(target.url).pathname;\n if (pathname === \"/\" || pathname.endsWith(\"/\")) return \"collection\";\n } catch {\n return \"page\";\n }\n return \"page\";\n}\n\n/** Fetch json-pretty pages/collections and assemble a canonical export document. */\nexport class SquarespaceCollectionClient {\n readonly format: SquarespaceJsonFormat;\n readonly maxRetries: number;\n readonly retryBaseDelayMs: number;\n readonly maxRetryDelayMs: number;\n readonly requestIntervalMs: number;\n readonly fetchImpl: typeof fetch;\n\n private lastRequestAt = 0;\n\n constructor(options: SquarespaceClientOptions = {}) {\n const parsed = squarespaceClientOptionsSchema.parse(options);\n this.format = parsed.format;\n this.maxRetries = parsed.maxRetries;\n this.retryBaseDelayMs = parsed.retryBaseDelayMs;\n this.maxRetryDelayMs = parsed.maxRetryDelayMs;\n this.requestIntervalMs = parsed.requestIntervalMs;\n this.fetchImpl = parsed.fetchImpl ?? fetch;\n }\n\n buildJsonPrettyUrl(pageUrl: string): string {\n return buildJsonPrettyUrl(pageUrl, this.format);\n }\n\n async fetchWire(url: string): Promise<unknown> {\n const response = await this.requestWithRetry(this.buildJsonPrettyUrl(url));\n return response.json() as Promise<unknown>;\n }\n\n async collectExport(targets: SquarespaceCollectTarget[]): Promise<SquarespaceExport> {\n if (targets.length === 0) {\n throw new Error(\"Squarespace collector requires at least one target URL\");\n }\n\n const partials: Partial<SquarespaceExport>[] = [];\n for (const target of targets) {\n const kind = inferTargetKind(target);\n if (kind === \"collection\") {\n partials.push(...(await this.collectCollectionPages(target)));\n } else {\n const wire = await this.fetchWire(target.url);\n partials.push(\n mapJsonPrettyWire(wire, { fetchedUrl: target.url, isHomePage: target.isHomePage }),\n );\n }\n }\n\n return mergeSquarespaceExportPartials(partials);\n }\n\n private async collectCollectionPages(\n target: SquarespaceCollectTarget,\n ): Promise<Partial<SquarespaceExport>[]> {\n const partials: Partial<SquarespaceExport>[] = [];\n let nextUrl: string | undefined = target.url;\n\n while (nextUrl) {\n const wire = await this.fetchWire(nextUrl);\n partials.push(\n mapJsonPrettyWire(wire, { fetchedUrl: nextUrl, isHomePage: target.isHomePage }),\n );\n\n const pagination = paginationFromWire(wire);\n if (!pagination?.nextPage || !pagination.nextPageUrl) break;\n const base = new URL(target.url);\n nextUrl = new URL(pagination.nextPageUrl, `${base.origin}/`).toString();\n }\n\n return partials;\n }\n\n private async requestWithRetry(url: string): Promise<Response> {\n let attempt = 0;\n while (true) {\n await this.throttle();\n const response = await this.fetchImpl(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n });\n\n if (response.ok) {\n return response;\n }\n\n const retryable = response.status === 429 || response.status >= 500;\n if (!retryable || attempt >= this.maxRetries) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `Squarespace HTTP ${response.status}${detail ? `: ${detail.slice(0, 200)}` : \"\"}`,\n );\n }\n\n const retryAfter = Number.parseInt(response.headers.get(\"retry-after\") ?? \"\", 10);\n const delay = Number.isFinite(retryAfter)\n ? retryAfter * 1000\n : Math.min(this.maxRetryDelayMs, this.retryBaseDelayMs * 2 ** attempt);\n await sleep(delay);\n attempt += 1;\n }\n }\n\n private async throttle(): Promise<void> {\n if (this.requestIntervalMs <= 0) return;\n const elapsed = Date.now() - this.lastRequestAt;\n if (elapsed < this.requestIntervalMs) {\n await sleep(this.requestIntervalMs - elapsed);\n }\n this.lastRequestAt = Date.now();\n }\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { buildPortfolioMediaLinks } from \"../normalizer/portfolio-media.js\";\nimport type { ConflictReport } from \"./conflicts.js\";\nimport type { MigrationReport } from \"./migration-report.js\";\n\nexport interface WriteFilesystemOptions {\n outDir: string;\n bundle: EntityBundle;\n conflicts?: ConflictReport;\n report?: MigrationReport;\n}\n\nasync function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function writeFilesystemExport(options: WriteFilesystemOptions): Promise<void> {\n await mkdir(options.outDir, { recursive: true });\n\n await writeJson(join(options.outDir, \"posts.json\"), options.bundle.posts);\n await writeJson(join(options.outDir, \"pages.json\"), options.bundle.pages);\n await writeJson(join(options.outDir, \"media.json\"), options.bundle.media);\n await writeJson(join(options.outDir, \"portfolios.json\"), options.bundle.portfolios);\n await writeJson(\n join(options.outDir, \"portfolio-media.json\"),\n buildPortfolioMediaLinks(options.bundle),\n );\n await writeJson(join(options.outDir, \"categories.json\"), options.bundle.categories);\n await writeJson(join(options.outDir, \"tags.json\"), options.bundle.tags);\n\n if (options.conflicts) {\n await writeJson(join(options.outDir, \"conflicts.json\"), options.conflicts);\n }\n if (options.report) {\n await writeJson(join(options.outDir, \"migration-report.json\"), options.report);\n }\n}\n\nexport function bundleToCombinedJson(bundle: EntityBundle): Record<string, unknown> {\n return {\n posts: bundle.posts,\n pages: bundle.pages,\n media: bundle.media,\n portfolios: bundle.portfolios,\n portfolioMedia: buildPortfolioMediaLinks(bundle),\n categories: bundle.categories,\n tags: bundle.tags,\n };\n}\n","import type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { emptyBundle } from \"../normalizer/bundle.js\";\nimport { buildPortfolioMediaLinks } from \"../normalizer/portfolio-media.js\";\nimport type {\n NormalizedAsset,\n NormalizedCategory,\n NormalizedPage,\n NormalizedPortfolio,\n NormalizedPost,\n NormalizedTag,\n PortfolioMediaLink,\n} from \"../normalizer/types.js\";\nimport type {\n CreatePageResult,\n CreatePostResult,\n MigrationRedirect,\n MigrationSink,\n UploadAssetInput,\n UploadAssetResult,\n} from \"./types.js\";\nimport { writeFilesystemExport, type WriteFilesystemOptions } from \"./filesystem.js\";\n\n/** Reference MigrationSink that accumulates entities and writes M0 JSON bundles. */\nexport class FilesystemMigrationSink implements MigrationSink {\n readonly bundle: EntityBundle = emptyBundle();\n readonly portfolioMediaLinks: PortfolioMediaLink[] = [];\n readonly redirects: MigrationRedirect[] = [];\n\n async createCategory(category: NormalizedCategory): Promise<{ targetId: string }> {\n this.bundle.categories.push(category);\n return { targetId: category.sourceId };\n }\n\n async createTag(tag: NormalizedTag): Promise<{ targetId: string }> {\n this.bundle.tags.push(tag);\n return { targetId: tag.sourceId };\n }\n\n async uploadAsset(input: UploadAssetInput): Promise<UploadAssetResult> {\n this.bundle.media.push(input.asset);\n return {\n targetId: input.asset.sourceId,\n publicUrl: input.asset.sourceUrl,\n };\n }\n\n async createPortfolio(portfolio: NormalizedPortfolio): Promise<{ targetId: string }> {\n this.bundle.portfolios.push(portfolio);\n return { targetId: portfolio.sourceId };\n }\n\n async createPost(post: NormalizedPost): Promise<CreatePostResult> {\n this.bundle.posts.push(post);\n return {\n targetId: post.sourceId,\n publicPath: post.source.path ?? `/${post.slug}`,\n };\n }\n\n async createPage(page: NormalizedPage): Promise<CreatePageResult> {\n this.bundle.pages.push(page);\n return {\n targetId: page.sourceId,\n publicPath: page.source.path ?? `/${page.slug}`,\n };\n }\n\n async linkPortfolioMedia(link: PortfolioMediaLink): Promise<void> {\n this.portfolioMediaLinks.push(link);\n }\n\n async writeRedirect(redirect: MigrationRedirect): Promise<void> {\n this.redirects.push(redirect);\n }\n\n async flush(options: WriteFilesystemOptions): Promise<void> {\n await writeFilesystemExport({\n ...options,\n bundle: this.bundle,\n });\n }\n}\n\nexport function createFilesystemMigrationSink(): FilesystemMigrationSink {\n return new FilesystemMigrationSink();\n}\n\n/** Verify sink-produced M2M links match bundle-derived index. */\nexport function portfolioMediaMatchesBundle(\n sink: FilesystemMigrationSink,\n): boolean {\n const expected = buildPortfolioMediaLinks(sink.bundle);\n if (expected.length !== sink.portfolioMediaLinks.length) return false;\n return expected.every((link, index) => {\n const actual = sink.portfolioMediaLinks[index];\n return (\n actual?.portfolioSourceId === link.portfolioSourceId &&\n actual?.assetSourceId === link.assetSourceId &&\n actual?.sort === link.sort\n );\n });\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { bundleCounts } from \"../normalizer/bundle.js\";\nimport type { MigrationPlatform } from \"../normalizer/types.js\";\nimport type { ConflictReport } from \"./conflicts.js\";\n\nexport type MigrationRunMode = \"dry-run\" | \"export\" | \"sink\" | \"worker\";\n\nexport interface MigrationReport {\n runId: string;\n platform: MigrationPlatform;\n mode: MigrationRunMode;\n startedAt: string;\n finishedAt: string;\n summary: {\n posts: number;\n pages: number;\n assets: number;\n portfolios: number;\n categories: number;\n tags: number;\n storageBytesEstimated?: number;\n };\n warnings: string[];\n errors: string[];\n conflicts: ConflictReport;\n redirectMap: { fromPath: string; toPath: string; statusCode: number }[];\n}\n\nexport function buildMigrationReport(input: {\n platform: MigrationPlatform;\n mode: MigrationRunMode;\n bundle: EntityBundle;\n conflicts: ConflictReport;\n redirectMap: { fromPath: string; toPath: string; statusCode: number }[];\n startedAt: Date;\n finishedAt?: Date;\n storageBytesEstimated?: number;\n warnings?: string[];\n errors?: string[];\n runId?: string;\n}): MigrationReport {\n const counts = bundleCounts(input.bundle);\n return {\n runId: input.runId ?? randomUUID(),\n platform: input.platform,\n mode: input.mode,\n startedAt: input.startedAt.toISOString(),\n finishedAt: (input.finishedAt ?? new Date()).toISOString(),\n summary: {\n ...counts,\n storageBytesEstimated: input.storageBytesEstimated,\n },\n warnings: input.warnings ?? [],\n errors: input.errors ?? [],\n conflicts: input.conflicts,\n redirectMap: input.redirectMap,\n };\n}\n","import type { NormalizedAsset } from \"../normalizer/types.js\";\n\nexport const FALLBACK_ASSET_BYTES = 4 * 1024 * 1024; // 4 MB\n\nexport interface AssetSizeResult {\n sourceId: string;\n url: string;\n bytes: number;\n source: \"head\" | \"fallback\";\n error?: string;\n}\n\nexport interface StorageEstimate {\n totalBytes: number;\n assets: AssetSizeResult[];\n}\n\nexport interface EstimateStorageOptions {\n assets: NormalizedAsset[];\n /** When true, skip network and use fallback for all assets. */\n offline?: boolean;\n fetchFn?: typeof fetch;\n}\n\nexport async function estimateStorage(\n options: EstimateStorageOptions,\n): Promise<StorageEstimate> {\n const fetchFn = options.fetchFn ?? fetch;\n const results: AssetSizeResult[] = [];\n\n for (const asset of options.assets) {\n if (options.offline) {\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: FALLBACK_ASSET_BYTES,\n source: \"fallback\",\n error: \"offline_mode\",\n });\n continue;\n }\n\n try {\n const response = await fetchFn(asset.sourceUrl, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(8000),\n });\n\n if (response.ok) {\n const length = response.headers.get(\"content-length\");\n const bytes = length ? Number.parseInt(length, 10) : FALLBACK_ASSET_BYTES;\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: Number.isFinite(bytes) ? bytes : FALLBACK_ASSET_BYTES,\n source: \"head\",\n });\n } else {\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: FALLBACK_ASSET_BYTES,\n source: \"fallback\",\n error: `http_${response.status}`,\n });\n }\n } catch (error) {\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: FALLBACK_ASSET_BYTES,\n source: \"fallback\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n const totalBytes = results.reduce((sum, r) => sum + r.bytes, 0);\n return { totalBytes, assets: results };\n}\n\nexport function staleUrlsFromEstimate(estimate: StorageEstimate) {\n return estimate.assets\n .filter((a) => a.source === \"fallback\" && a.error && a.error !== \"offline_mode\")\n .map((a) => ({\n sourceId: a.sourceId,\n url: a.url,\n reason: a.error ?? \"unknown\",\n }));\n}\n","import { collectEntities, type EntityBundle } from \"../normalizer/bundle.js\";\nimport type { MigrationAdapter, MigrationPlatform } from \"../normalizer/types.js\";\nimport {\n analyzeConflicts,\n buildRedirectMap,\n detectRedirectLoops,\n hasBlockingConflicts,\n hasWarnings,\n type ConflictReport,\n} from \"./conflicts.js\";\nimport { buildMigrationReport, type MigrationReport } from \"./migration-report.js\";\nimport { estimateStorage, staleUrlsFromEstimate } from \"./storage-estimate.js\";\n\nexport interface DryRunOptions {\n adapter: MigrationAdapter;\n input: unknown;\n platform: MigrationPlatform;\n offlineStorageEstimate?: boolean;\n fetchFn?: typeof fetch;\n}\n\nexport interface DryRunResult {\n bundle: EntityBundle;\n conflicts: ConflictReport;\n report: MigrationReport;\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runDryRun(options: DryRunOptions): Promise<DryRunResult> {\n const startedAt = new Date();\n const bundle = await collectEntities(\n options.adapter.enumerateEntities({ input: options.input }),\n );\n\n const estimate = await estimateStorage({\n assets: bundle.media,\n offline: options.offlineStorageEstimate,\n fetchFn: options.fetchFn,\n });\n\n const redirectMap = buildRedirectMap(bundle);\n const redirectLoops = detectRedirectLoops(redirectMap);\n const staleAssetUrls = staleUrlsFromEstimate(estimate);\n\n const conflicts = analyzeConflicts(bundle, { staleAssetUrls, redirectLoops });\n\n const warnings: string[] = [];\n if (staleAssetUrls.length > 0) {\n warnings.push(`${staleAssetUrls.length} asset URL(s) unreachable; used 4 MB fallback each`);\n }\n if (conflicts.duplicatePostSlugs.length > 0) {\n warnings.push(\n `${conflicts.duplicatePostSlugs.length} duplicate post slug group(s); host may auto-suffix`,\n );\n }\n\n const report = buildMigrationReport({\n platform: options.platform,\n mode: \"dry-run\",\n bundle,\n conflicts,\n redirectMap,\n startedAt,\n storageBytesEstimated: estimate.totalBytes,\n warnings,\n });\n\n let exitCode: 0 | 1 | 2 = 0;\n if (hasBlockingConflicts(conflicts)) exitCode = 1;\n else if (hasWarnings(conflicts) || warnings.length > 0) exitCode = 2;\n\n return { bundle, conflicts, report, exitCode };\n}\n"],"mappings":"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","names":["cheerio","cheerio","cheerio","item"]}