{"version":3,"file":"transforms.cjs","names":["babelTsParser","firstInsertIndex"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/transforms.ts"],"sourcesContent":["import * as recast from 'recast';\nimport { babelTsParser } from '../../../utils/babelParser';\nimport { ensureNamedImport, firstInsertIndex } from '../../utils/astImports';\n\nconst { builders: b } = recast.types;\n\n/** babel-ts parser handles TypeScript *and* JSX (the `typescript` parser does not). */\nconst parseTsx = (code: string): any =>\n  recast.parse(code, { parser: babelTsParser });\n\n/** Result of a source transform. `code` is unchanged for any non-`wrapped` status. */\nexport type TransformResult = {\n  code: string;\n  status: 'wrapped' | 'already' | 'skipped-client' | 'skipped';\n};\n\n/** Detects a top-level `'use client'` directive (client components can't be async server providers). */\nconst isClientComponent = (ast: any): boolean => {\n  const directives = ast.program.directives ?? [];\n  if (\n    directives.some((directive: any) => directive.value?.value === 'use client')\n  ) {\n    return true;\n  }\n  return ast.program.body.some(\n    (stmt: any) =>\n      stmt.type === 'ExpressionStatement' &&\n      stmt.expression?.type === 'StringLiteral' &&\n      stmt.expression.value === 'use client'\n  );\n};\n\n/** Finds the function node behind `export default`, following an identifier reference if needed. */\nconst findDefaultExportFunction = (ast: any): any => {\n  const body = ast.program.body;\n\n  const asFunction = (node: any): any =>\n    node &&\n    (node.type === 'ArrowFunctionExpression' ||\n      node.type === 'FunctionExpression' ||\n      node.type === 'FunctionDeclaration')\n      ? node\n      : null;\n\n  for (const stmt of body) {\n    if (stmt.type !== 'ExportDefaultDeclaration') continue;\n\n    const direct = asFunction(stmt.declaration);\n    if (direct) return direct;\n\n    if (stmt.declaration?.type === 'Identifier') {\n      const name = stmt.declaration.name;\n      for (const candidate of body) {\n        if (candidate.type === 'VariableDeclaration') {\n          for (const declarator of candidate.declarations) {\n            if (\n              declarator.id?.type === 'Identifier' &&\n              declarator.id.name === name\n            ) {\n              const fn = asFunction(declarator.init);\n              if (fn) return fn;\n            }\n          }\n        }\n        if (\n          candidate.type === 'FunctionDeclaration' &&\n          candidate.id?.name === name\n        ) {\n          return candidate;\n        }\n      }\n    }\n  }\n\n  return null;\n};\n\n/** Ensures `export { exportedName } from source`, skipping when already declared/re-exported. */\nconst ensureExportFrom = (\n  ast: any,\n  exportedName: string,\n  source: string\n): void => {\n  const body = ast.program.body;\n\n  const alreadyPresent = body.some((stmt: any) => {\n    if (\n      stmt.type === 'ExportNamedDeclaration' &&\n      stmt.source?.value === source\n    ) {\n      return stmt.specifiers.some(\n        (spec: any) => spec.exported?.name === exportedName\n      );\n    }\n    // Locally declared `export const/function generateStaticParams`\n    if (stmt.type === 'ExportNamedDeclaration' && stmt.declaration) {\n      const decl = stmt.declaration;\n      if (decl.type === 'FunctionDeclaration' && decl.id?.name === exportedName)\n        return true;\n      if (decl.type === 'VariableDeclaration') {\n        return decl.declarations.some(\n          (d: any) => d.id?.type === 'Identifier' && d.id.name === exportedName\n        );\n      }\n    }\n    return false;\n  });\n\n  if (alreadyPresent) return;\n\n  const exportNode = parseTsx(`export { ${exportedName} } from \"${source}\";`)\n    .program.body[0];\n  ast.program.body.splice(firstInsertIndex(ast), 0, exportNode);\n};\n\n/** Makes the function async and inserts `const locale = await getLocale();` once, at the top of its body. */\nconst ensureAwaitedLocale = (funcNode: any): void => {\n  funcNode.async = true;\n\n  if (funcNode.body.type !== 'BlockStatement') {\n    funcNode.body = b.blockStatement([b.returnStatement(funcNode.body)]);\n  }\n\n  const hasLocale = funcNode.body.body.some(\n    (stmt: any) =>\n      stmt.type === 'VariableDeclaration' &&\n      stmt.declarations.some(\n        (d: any) =>\n          // const locale = ...\n          (d.id?.type === 'Identifier' && d.id.name === 'locale') ||\n          // const { locale } = ... or const { locale: locale } = ...\n          (d.id?.type === 'ObjectPattern' &&\n            d.id.properties?.some(\n              (prop: any) =>\n                prop.value?.type === 'Identifier' &&\n                prop.value?.name === 'locale'\n            ))\n      )\n  );\n\n  if (!hasLocale) {\n    const localeStatement = parseTsx('const locale = await getLocale();')\n      .program.body[0];\n    funcNode.body.body.unshift(localeStatement);\n  }\n};\n\n/** Builds `<providerName locale={locale}>{child}</providerName>` around an existing JSX child node. */\nconst buildProviderElement = (providerName: string, childNode: any): any => {\n  const template = parseTsx(\n    `const __wrap = <${providerName} locale={locale}>{__child__}</${providerName}>;`\n  );\n  const providerElement = template.program.body[0].declarations[0].init;\n  providerElement.children = [childNode];\n  return providerElement;\n};\n\n/** Sets `lang={locale}` on the first `<html>` element, if present. */\nconst setHtmlLang = (ast: any): void => {\n  recast.visit(ast, {\n    visitJSXOpeningElement(path) {\n      const node = path.node;\n      if (node.name?.type === 'JSXIdentifier' && node.name.name === 'html') {\n        const langAttr = node.attributes?.find(\n          (attr: any) =>\n            attr.type === 'JSXAttribute' && attr.name?.name === 'lang'\n        ) as any;\n        const localeExpression = b.jsxExpressionContainer(\n          b.identifier('locale')\n        );\n        if (langAttr) {\n          langAttr.value = localeExpression;\n        } else {\n          node.attributes.push(\n            b.jsxAttribute(b.jsxIdentifier('lang'), localeExpression)\n          );\n        }\n        return false;\n      }\n      this.traverse(path);\n    },\n  });\n};\n\n/**\n * Wraps the `{children}` of a Next.js App Router **layout** with the unified\n * `IntlayerProvider`, deriving the locale via `getLocale()`. Safe and\n * idempotent: bails (returns the original code) for client components, when no\n * `{children}` placeholder is found, or when there is no default export.\n *\n * `IntlayerProvider` seeds both the server context and the client provider in\n * one mount, so this is the only provider a Next.js App Router app needs —\n * pages below the locale layout read locale/variant from it without wrapping\n * themselves individually (see the removed `wrapPageWithProvider`).\n */\nexport const wrapLayoutWithProvider = (code: string): TransformResult => {\n  const ast = parseTsx(code);\n\n  if (isClientComponent(ast)) return { code, status: 'skipped-client' };\n  if (code.includes('IntlayerProvider')) return { code, status: 'already' };\n\n  const funcNode = findDefaultExportFunction(ast);\n  if (!funcNode) return { code, status: 'skipped' };\n\n  let wrapped = false;\n  recast.visit(funcNode, {\n    visitJSXExpressionContainer(path) {\n      if (wrapped) return false;\n      const expression = path.node.expression;\n      if (expression?.type === 'Identifier' && expression.name === 'children') {\n        path.replace(buildProviderElement('IntlayerProvider', path.node));\n        wrapped = true;\n        return false;\n      }\n      this.traverse(path);\n    },\n  });\n\n  if (!wrapped) return { code, status: 'skipped' };\n\n  ensureNamedImport(ast, 'IntlayerProvider', 'next-intlayer/server');\n  ensureNamedImport(ast, 'getLocale', 'next-intlayer/server');\n  ensureExportFrom(ast, 'generateStaticParams', 'next-intlayer');\n  ensureAwaitedLocale(funcNode);\n  setHtmlLang(ast);\n\n  return { code: recast.print(ast).code, status: 'wrapped' };\n};\n"],"mappings":"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"}