@trackunit/iris-app 2.5.19-alpha-62031fc7c43.0 → 2.5.20

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/migrations/entry.js.map +1 -0
  3. package/migrations/p-content-space-codemod/invent-content-space.js.map +1 -0
  4. package/migrations/p-content-space-codemod/orchestrator.js.map +1 -0
  5. package/migrations/p-content-space-codemod/remove-redundant-padding.js.map +1 -0
  6. package/migrations/p-content-space-codemod/report-run-messaging.js.map +1 -0
  7. package/migrations/p-content-space-codemod/report-unresolved.js.map +1 -0
  8. package/migrations/p-content-space-codemod/resolve-content-shell.js.map +1 -0
  9. package/migrations/p-content-space-codemod/rewrite-page-content.js.map +1 -0
  10. package/migrations/p-content-space-codemod/shell-skip-reason.js.map +1 -0
  11. package/migrations/utils/classname-ast-rewrite.js.map +1 -0
  12. package/migrations/utils/resolve-extension-types.js.map +1 -0
  13. package/migrations.json +1 -1
  14. package/package.json +6 -6
  15. package/src/executors/submit/executor.js.map +1 -0
  16. package/src/executors/unpublish/executor.js.map +1 -0
  17. package/src/executors/utils/authentication.js +5 -1
  18. package/src/executors/utils/authentication.js.map +1 -0
  19. package/src/executors/utils/irisAppServerSettings.js.map +1 -0
  20. package/src/executors/utils/src/index.js.map +1 -0
  21. package/src/generators/ai-agent-sync/README.md +5 -4
  22. package/src/generators/ai-agent-sync/generator.js +16 -22
  23. package/src/generators/ai-agent-sync/generator.js.map +1 -0
  24. package/src/generators/create/generator.js.map +1 -0
  25. package/src/generators/extend/dependencies.js.map +1 -0
  26. package/src/generators/extend/generator.js.map +1 -0
  27. package/src/generators/preset/generator.js +6 -8
  28. package/src/generators/preset/generator.js.map +1 -0
  29. package/src/generators/utils/get-package-manifest.js.map +1 -0
  30. package/src/generators/utils/link-claude-skills.js.map +1 -0
  31. package/src/index.js.map +1 -0
  32. package/src/utils/ast/astUtils.js.map +1 -0
  33. package/src/utils/fileUpdater.js.map +1 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,90 @@
1
+ ## 2.5.20 (2026-08-27)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **host:** resolve account.user.view from the viewUsers account action ([68660fa3246](https://github.com/Trackunit/manager/commit/68660fa3246))
6
+
7
+ ### 🧱 Updated Dependencies
8
+
9
+ - Updated iris-app-build-utilities to 2.4.19
10
+ - Updated iris-app-api to 2.4.13
11
+ - Updated react-graphql-tools to 1.16.3
12
+
13
+ ### ❤️ Thank You
14
+
15
+ - Claude Opus 5 (1M context)
16
+ - Kenneth Sejrsgaard-Jacobsen
17
+
18
+ ## 2.5.19 (2026-08-25)
19
+
20
+ ### 🩹 Fixes
21
+
22
+ - **iris-app-sdk:** retry Sentry HTTP 5xx during iris app builds ([#25075](https://github.com/Trackunit/manager/pull/25075), [#24915](https://github.com/Trackunit/manager/issues/24915), [#25062](https://github.com/Trackunit/manager/issues/25062))
23
+
24
+ ### 🧱 Updated Dependencies
25
+
26
+ - Updated iris-app-build-utilities to 2.4.18
27
+ - Updated iris-app-api to 2.4.12
28
+ - Updated react-vite-test-setup to 0.0.114
29
+ - Updated css-classname-utils to 0.0.22
30
+ - Updated react-graphql-tools to 1.16.2
31
+ - Updated shared-utils to 1.16.22
32
+
33
+ ### ❤️ Thank You
34
+
35
+ - Cursor Agent @cursoragent
36
+ - Kristian Bødker
37
+
38
+ ## 2.5.18 (2026-08-25)
39
+
40
+ ### 🩹 Fixes
41
+
42
+ - **iris-app-sdk:** retry Sentry HTTP 5xx during iris app builds ([#25075](https://github.com/Trackunit/manager/pull/25075), [#24915](https://github.com/Trackunit/manager/issues/24915), [#25062](https://github.com/Trackunit/manager/issues/25062))
43
+
44
+ ### 🧱 Updated Dependencies
45
+
46
+ - Updated iris-app-build-utilities to 2.4.17
47
+ - Updated iris-app-api to 2.4.11
48
+ - Updated react-vite-test-setup to 0.0.113
49
+ - Updated css-classname-utils to 0.0.21
50
+ - Updated react-graphql-tools to 1.16.1
51
+ - Updated shared-utils to 1.16.21
52
+
53
+ ### ❤️ Thank You
54
+
55
+ - Cursor Agent @cursoragent
56
+ - Kristian Bødker
57
+
58
+ ## 2.5.17 (2026-08-24)
59
+
60
+ ### 🧱 Updated Dependencies
61
+
62
+ - Updated iris-app-build-utilities to 2.4.16
63
+ - Updated react-graphql-tools to 1.16.0
64
+
65
+ ## 2.5.16 (2026-08-21)
66
+
67
+ ### 🧱 Updated Dependencies
68
+
69
+ - Updated iris-app-build-utilities to 2.4.15
70
+ - Updated iris-app-api to 2.4.10
71
+
72
+ ## 2.5.15 (2026-08-21)
73
+
74
+ ### 🩹 Fixes
75
+
76
+ - **iris-app:** SF-791 restore CircleCI approvals ([51cff4a72ad](https://github.com/Trackunit/manager/commit/51cff4a72ad))
77
+
78
+ ### ❤️ Thank You
79
+
80
+ - Mads Mætzke Tandrup
81
+
82
+ ## 2.5.14 (2026-08-20)
83
+
84
+ ### 🧱 Updated Dependencies
85
+
86
+ - Updated iris-app-build-utilities to 2.4.14
87
+
1
88
  ## 2.5.13 (2026-08-20)
2
89
 
3
90
  ### 🧱 Updated Dependencies
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["// Migration entry point for @nx/js:tsc build target.\n// Migrations are registered in ../migrations.json and resolved by NX at runtime.\nexport {};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invent-content-space.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/invent-content-space.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Tree } from \"@nx/devkit\";\nimport { splitClasses, type ClassnameLocation } from \"@trackunit/css-classname-utils\";\nimport { AST_NODE_TYPES, type TSESTree } from \"@typescript-eslint/types\";\nimport { simpleTraverse } from \"@typescript-eslint/typescript-estree\";\nimport {\n applyEdits,\n buildEditsForLocation,\n findClassnameLocations,\n parseTsestreeSource,\n type ClassnameEdit,\n} from \"../utils/classname-ast-rewrite\";\nimport type { ResolvedExtension } from \"../utils/resolve-extension-types\";\nimport { findUnresolvedSurface, type MigrationChangeReport } from \"./report-unresolved\";\nimport { resolveContentShells, type ResolvedContentShell } from \"./resolve-content-shell\";\nimport type { ShellSkipReason } from \"./shell-skip-reason\";\n\nconst CONTENT_SPACE_TOKEN = \"p-content-space\";\n\n/**\n * Extension types that may invent/convert content-shell padding. Fleet/Customer\n * remain swap-only (page-content rewrite) and must never invent or convert.\n * Shared with the orchestrator so the ASA gate lives in exactly one place.\n */\nexport const ASSET_SITE_ADMIN_TYPES: ReadonlySet<string> = new Set([\n \"ASSET_HOME_EXTENSION\",\n \"SITE_HOME_EXTENSION\",\n \"ADMIN_EXTENSION\",\n]);\n\nconst SHELL_INSET_SIDES = [\"p\", \"px\", \"py\", \"pt\", \"pr\", \"pb\", \"pl\"] as const;\nconst SHELL_INSET_VALUES = [\n \"1\",\n \"1.5\",\n \"2\",\n \"2.5\",\n \"3\",\n \"3.5\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"10\",\n \"11\",\n \"12\",\n \"14\",\n \"16\",\n \"20\",\n \"24\",\n \"28\",\n \"32\",\n \"36\",\n \"40\",\n \"44\",\n \"48\",\n \"52\",\n \"56\",\n \"60\",\n \"64\",\n \"72\",\n \"80\",\n \"96\",\n \"responsive-space\",\n] as const;\nconst BREAKPOINT_VARIANTS = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\"] as const;\n\nconst escapeRegExp = (value: string): string => value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/**\n * Tailwind padding utilities treated as content-region shell inset candidates.\n * Enumerated (not `.+`) so reset tokens (`px-0`, `pb-0.5`) and state/print\n * variants (`hover:`, `focus:`, `print:`) are left alone. Breakpoint variants\n * (`md:p-6`) are still converted — those are lossy and logged as such.\n */\nconst SHELL_PADDING_TOKEN = new RegExp(\n `^(?:(?:${BREAKPOINT_VARIANTS.join(\"|\")}):)?(?:${SHELL_INSET_SIDES.join(\"|\")})-(?:${SHELL_INSET_VALUES.map(escapeRegExp).join(\"|\")})$`\n);\n\nconst tokenBase = (token: string): string => (token.includes(\":\") ? token.slice(token.lastIndexOf(\":\") + 1) : token);\n\nconst isContentSpaceToken = (token: string): boolean => tokenBase(token) === CONTENT_SPACE_TOKEN;\n\nconst isShellPaddingToken = (token: string): boolean => {\n if (isContentSpaceToken(token)) {\n return false;\n }\n return SHELL_PADDING_TOKEN.test(token);\n};\n\ntype InventContentSpaceResult = {\n filesChanged: ReadonlyArray<string>;\n changes: ReadonlyArray<MigrationChangeReport>;\n skippedRouteNames: ReadonlyArray<string>;\n /** Set when shell discovery returned unresolved (invent made no edits). */\n unresolvedReason: ShellSkipReason | null;\n};\n\nconst emptyResult = (unresolvedReason: ShellSkipReason | null = null): InventContentSpaceResult => ({\n filesChanged: [],\n changes: [],\n skippedRouteNames: [],\n unresolvedReason,\n});\n\n/**\n * Ensures each resolved ASA content shell carries `p-content-space`:\n * - invents the token on a bare shell (reported as `addition`)\n * - converts custom shell padding (`p-*` / `px-*` / `py-*` / sides /\n * `p-responsive-space` / `pb-responsive-space`) to `p-content-space`,\n * removing those custom tokens (reported as `conversion`)\n *\n * Uses {@link resolveContentShells}: shared layout Outlet shells yield one\n * target; multi-route without a shared layout invents/converts each clear\n * leaf. Only classname locations bound to each host are edited — inner layout\n * padding is left alone. Idempotent when a shell already has `p-content-space`\n * (including a variant-prefixed form) and no custom shell padding (including\n * whitespace-only differences). Never invents an `overflow-*` token — existing\n * scroll ownership is preserved. Fleet/Customer types are a no-op (swap-only\n * surfaces).\n *\n * Returns empty `filesChanged` / `changes` (never throws) when shells are\n * unresolved, the extension type is out of scope, or already in the desired state.\n * `skippedRouteNames` names unanalysable routes on a partial graph so the\n * orchestrator can report them instead of treating the extension as fully migrated.\n */\nexport const inventContentSpace = (tree: Tree, extension: ResolvedExtension): InventContentSpaceResult => {\n if (!ASSET_SITE_ADMIN_TYPES.has(extension.type)) {\n return emptyResult();\n }\n\n const resolved = resolveContentShells(tree, extension);\n if (resolved.status === \"unresolved\") {\n return emptyResult(resolved.reason);\n }\n\n const skippedRouteNames = [...resolved.skippedRouteNames];\n\n // Single resolved shell that already carries the token (or page-content):\n // do not invent a second inset. A token on a *nested* file is not enough —\n // that hid Device Administration's layout shell (GLU-1903). Multi-route\n // graphs skip this so a padded sibling leaf does not leave other leaves flush.\n if (resolved.shells.length === 1 && findUnresolvedSurface(tree, extension) === null) {\n return { filesChanged: [], changes: [], skippedRouteNames, unresolvedReason: null };\n }\n\n const shellsByFile = groupShellsByFile(resolved.shells);\n const filesChanged: Array<string> = [];\n const changes: Array<MigrationChangeReport> = [];\n\n for (const [filePath, shells] of shellsByFile) {\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) {\n continue;\n }\n\n let program: TSESTree.Program;\n try {\n program = parseTsestreeSource(content);\n } catch {\n continue;\n }\n\n // Edit later ranges first so earlier offsets stay valid in one applyEdits pass.\n const orderedShells = [...shells].sort(\n (left, right) => right.location.reportNode.range[0] - left.location.reportNode.range[0]\n );\n\n const fileEdits: Array<ClassnameEdit> = [];\n const fileChanges: Array<MigrationChangeReport> = [];\n\n for (const shell of orderedShells) {\n const hostLocations = collectHostClassnameLocations(program, shell.location);\n const combinedBefore = hostLocations.map(hostLocation => hostLocation.value).join(\" \");\n const combinedPlan = planContentSpaceOnShell(combinedBefore);\n if (!combinedPlan.changed) {\n continue;\n }\n\n const alreadyHasContentSpace = splitClasses(combinedBefore).some(isContentSpaceToken);\n const primaryRange = shell.location.fixNode.range;\n const orderedLocations = [...hostLocations].sort((left, right) => {\n const leftIsPrimary = rangesEqual(left.fixNode.range, primaryRange);\n const rightIsPrimary = rangesEqual(right.fixNode.range, primaryRange);\n if (leftIsPrimary === rightIsPrimary) {\n return left.fixNode.range[0] - right.fixNode.range[0];\n }\n return leftIsPrimary ? -1 : 1;\n });\n\n let addedToken = alreadyHasContentSpace;\n const shellEdits: Array<ClassnameEdit> = [];\n for (const hostLocation of orderedLocations) {\n const locationEdits = buildEditsForLocation(\n hostLocation,\n value => {\n const next = transformClassnamePreservingWhitespace(value, { addContentSpace: !addedToken });\n if (!addedToken && splitClasses(next).some(isContentSpaceToken)) {\n addedToken = true;\n }\n return next;\n },\n content\n );\n shellEdits.push(...locationEdits);\n }\n\n if (shellEdits.length === 0) {\n continue;\n }\n\n fileEdits.push(...shellEdits);\n fileChanges.push({\n extensionId: extension.id,\n sourceRoot: extension.sourceRoot,\n filePath,\n kind: combinedPlan.removedTokens.length > 0 ? \"conversion\" : \"addition\",\n before: shell.classnameValue,\n after: planContentSpaceOnShell(shell.location.value).next,\n removedTokens: combinedPlan.removedTokens,\n });\n }\n\n if (fileEdits.length === 0) {\n continue;\n }\n\n tree.write(filePath, applyEdits(content, fileEdits));\n filesChanged.push(filePath);\n changes.push(...fileChanges.reverse());\n }\n\n if (filesChanged.length === 0) {\n return { filesChanged: [], changes: [], skippedRouteNames, unresolvedReason: null };\n }\n\n return { filesChanged, changes, skippedRouteNames, unresolvedReason: null };\n};\n\nconst groupShellsByFile = (shells: ReadonlyArray<ResolvedContentShell>): Map<string, Array<ResolvedContentShell>> => {\n const byFile = new Map<string, Array<ResolvedContentShell>>();\n for (const shell of shells) {\n const existing = byFile.get(shell.filePath);\n if (existing === undefined) {\n byFile.set(shell.filePath, [shell]);\n } else {\n existing.push(shell);\n }\n }\n return byFile;\n};\n\ntype ContentSpacePlan = {\n readonly next: string;\n readonly changed: boolean;\n readonly removedTokens: Array<string>;\n};\n\n/**\n * Strips custom shell-inset padding tokens and ensures `p-content-space` is\n * present, preserving the relative order of non-padding tokens.\n *\n * `changed` is true only when custom padding was stripped or `p-content-space`\n * was missing — not when the only difference would be whitespace normalization.\n */\nconst planContentSpaceOnShell = (classnameValue: string): ContentSpacePlan => {\n const classes = splitClasses(classnameValue);\n const removedTokens = classes.filter(isShellPaddingToken);\n const withoutCustomPadding = classes.filter(token => !isShellPaddingToken(token));\n const hadContentSpace = withoutCustomPadding.some(isContentSpaceToken);\n const nextClasses = hadContentSpace ? withoutCustomPadding : [...withoutCustomPadding, CONTENT_SPACE_TOKEN];\n return {\n next: nextClasses.join(\" \"),\n changed: removedTokens.length > 0 || !hadContentSpace,\n removedTokens,\n };\n};\n\nconst transformClassnamePreservingWhitespace = (value: string, options: { addContentSpace: boolean }): string => {\n const trimmedStart = value.length - value.trimStart().length;\n const trimmedEnd = value.length - value.trimEnd().length;\n const leading = value.slice(0, trimmedStart);\n const trailing = trimmedStart === value.length ? \"\" : value.slice(value.length - trimmedEnd);\n const classes = splitClasses(value);\n const kept = classes.filter(token => !isShellPaddingToken(token));\n const hasToken = kept.some(isContentSpaceToken);\n const nextClasses = options.addContentSpace && !hasToken ? [...kept, CONTENT_SPACE_TOKEN] : kept;\n const core = nextClasses.join(\" \");\n if (core === \"\") {\n return `${leading}${trailing}`;\n }\n return `${leading}${core}${trailing}`;\n};\n\nconst rangesEqual = (left: TSESTree.Range, right: TSESTree.Range): boolean =>\n left[0] === right[0] && left[1] === right[1];\n\n/**\n * All editable classname args bound to the same host as `primary` (every\n * string argument of a `cn()` / `cva()` call). Plain JSX literals stay a\n * single location. CVA variant objects are excluded so variant padding is\n * not stripped as if it were shell inset.\n */\nconst collectHostClassnameLocations = (\n program: TSESTree.Program,\n primary: ClassnameLocation\n): Array<ClassnameLocation> => {\n if (primary.context.type !== \"function-call\" && primary.context.type !== \"array-element\") {\n return [primary];\n }\n\n const callRange = findSmallestEnclosingCallRange(program, primary.reportNode);\n if (callRange === null) {\n return [primary];\n }\n\n const siblings = findClassnameLocations(program).filter(location => {\n if (location.reportNode.range[0] < callRange[0] || location.reportNode.range[1] > callRange[1]) {\n return false;\n }\n return location.context.type === \"function-call\" || location.context.type === \"array-element\";\n });\n\n return siblings.length > 0 ? siblings : [primary];\n};\n\nconst findSmallestEnclosingCallRange = (program: TSESTree.Program, inner: TSESTree.Node): TSESTree.Range | null => {\n let best: TSESTree.Range | null = null;\n simpleTraverse(program, {\n enter: node => {\n if (node.type !== AST_NODE_TYPES.CallExpression) return;\n if (inner.range[0] < node.range[0] || inner.range[1] > node.range[1]) return;\n if (best === null || node.range[1] - node.range[0] < best[1] - best[0]) {\n best = node.range;\n }\n },\n });\n return best;\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/orchestrator.ts"],"names":[],"mappings":";;AAoDA,oDA4EC;AAhID,uCAA+C;AAC/C,8EAAyE;AACzE,iEAAoF;AACpF,yEAAoE;AACpE,iEAA4F;AAC5F,2DAK6B;AAC7B,iEAA4D;AAE5D,MAAM,cAAc,GAAG,yBAAyB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,yBAAyB,GAAwB,IAAI,GAAG,CAAC,CAAC,iBAAiB,EAAE,yBAAyB,CAAC,CAAC,CAAC;AAE/G;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,SAAgB,oBAAoB,CAAC,IAAU;IAC7C,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAA,+CAAqB,EAAC,IAAI,CAAC,CAAC;IAE7D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,OAAO,GAAiC,EAAE,CAAC;IACjD,MAAM,OAAO,GAAmC,EAAE,CAAC;IACnD,IAAI,eAAe,GAAG,KAAK,CAAC;IAE5B,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;QACjC,IAAI,6CAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,eAAe,GAAG,IAAI,CAAC;YACvB,MAAM,CAAC,YAAY,EAAE,IAAA,yCAAkB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC;YACvE,MAAM,YAAY,GAAG,IAAA,yCAAkB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzD,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACtC,0EAA0E;YAC1E,kEAAkE;YAClE,wDAAwD;YACxD,MAAM,CAAC,YAAY,EAAE,IAAA,iDAAsB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC;YAE3E,MAAM,kBAAkB,GAAG,GAAG,SAAS,CAAC,UAAU,IAAI,SAAS,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC;YACtF,KAAK,MAAM,gBAAgB,IAAI,YAAY,CAAC,iBAAiB,EAAE,CAAC;gBAC9D,OAAO,CAAC,IAAI,CAAC;oBACX,WAAW,EAAE,SAAS,CAAC,EAAE;oBACzB,UAAU,EAAE,SAAS,CAAC,UAAU;oBAChC,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI;oBAC/E,QAAQ,EAAE,qCAAiB;oBAC3B,gBAAgB;oBAChB,UAAU,EAAE;wBACV,IAAI,EAAE,6BAA6B;wBACnC,OAAO,EAAE,UAAU,gBAAgB,mEAAmE;qBACvG;iBACF,CAAC,CAAC;YACL,CAAC;YAED,MAAM,MAAM,GAAG,IAAA,yCAAqB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACtD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC;oBACX,GAAG,MAAM;oBACT,UAAU,EAAE,YAAY,CAAC,gBAAgB,IAAI,MAAM,CAAC,UAAU;iBAC/D,CAAC,CAAC;YACL,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,yBAAyB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAClD,MAAM,CAAC,YAAY,EAAE,IAAA,yCAAkB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC;YACvE,SAAS;QACX,CAAC;IACH,CAAC;IAED,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC;IACtE,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG,oBAAoB,CAAC,CAAC;IAErE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,eAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,eAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,eAAM,CAAC,IAAI,CAAC,IAAA,6CAAsB,EAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,IAAA,iDAA0B,EAAC,EAAE,eAAe,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;QAC3G,eAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,eAAM,CAAC,IAAI,CACT,KAAK,cAAc,yCAAyC,IAAI,CAAC,SAAS,wBAAwB,IAAI,CAAC,GAAG,GAAG,CAC9G,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,MAAmB,EAAE,KAA4B;IAC/D,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,iBAAiB,GAAG,CAAC,MAA6B,EAAW,EAAE,CACnE,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAExH,sGAAsG;AACtG,SAAS,UAAU,CAAC,OAAe,EAAE,kBAA0B;IAC7D,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,eAAM,CAAC,IAAI,CAAC,KAAK,cAAc,oBAAoB,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IACD,MAAM,YAAY,GAAG,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,kBAAkB,kCAAkC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7G,eAAM,CAAC,IAAI,CAAC,KAAK,cAAc,aAAa,OAAO,WAAW,YAAY,EAAE,CAAC,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,MAA6B;IACvD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,KAAK,cAAc,kBAAkB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,QAAQ,OAAO,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,KAAK,GAAG,CAAC;IACjI,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,KAAK,cAAc,oBAAoB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,QAAQ,eAAe,OAAO,OAAO,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,KAAK,GAAG,CAAC;AACzJ,CAAC;AAED,kBAAe,oBAAoB,CAAC","sourcesContent":["import { logger, type Tree } from \"@nx/devkit\";\nimport { resolveExtensionTypes } from \"../utils/resolve-extension-types\";\nimport { ASSET_SITE_ADMIN_TYPES, inventContentSpace } from \"./invent-content-space\";\nimport { removeRedundantPadding } from \"./remove-redundant-padding\";\nimport { collectAsaEndOfRunMessages, formatUnresolvedReport } from \"./report-run-messaging\";\nimport {\n findUnresolvedSurface,\n PADDING_DOCS_LINK,\n type MigrationChangeReport,\n type UnresolvedSurfaceReport,\n} from \"./report-unresolved\";\nimport { rewritePageContent } from \"./rewrite-page-content\";\n\nconst MIGRATION_NAME = \"p-content-space-codemod\";\n\n/**\n * Extension types that get the swap-only `page-content` -> `overflow-auto\n * p-content-space` rewrite (GLU-1732). Unlike `ASSET_SITE_ADMIN_TYPES`, these\n * are always expected to already have a `page-content` region, so redundant-\n * padding removal, invent/convert, and unresolved-surface reporting don't apply\n * to this group — Fleet/Customer Home never received platform inset.\n */\nconst FLEET_CUSTOMER_HOME_TYPES: ReadonlySet<string> = new Set([\"FLEET_EXTENSION\", \"CUSTOMER_HOME_EXTENSION\"]);\n\n/**\n * Composes the extension-type resolver with the page-content rewrite,\n * redundant-padding removal, content-shell invent/convert, change reporting,\n * and unresolved-surface report for every resolved Asset Home/Site Home/Admin\n * extension in the workspace, and the swap-only page-content rewrite for every\n * resolved Fleet/Customer Home extension. Every other extension type is left\n * untouched.\n *\n * Ordering for Asset Home/Site Home/Admin:\n * 1. `rewritePageContent` — so a just-migrated region already carries\n * `p-content-space` before invent and padding cleanup look for it.\n * 2. `inventContentSpace` — invents or converts `p-content-space` on a\n * high-confidence content shell (ASA only); change reports distinguish\n * addition vs conversion.\n * 3. `removeRedundantPadding` — only strips `pb-*` from classname strings\n * that carry `p-content-space`, including tokens invent just added, so\n * unresolved extensions (no padded region) and local component spacing\n * are left alone by construction.\n * 4. `findUnresolvedSurface` — against post-rewrite/invent Tree state;\n * invented/converted surfaces must not be reported as unresolved.\n *\n * Formatting is intentionally the caller's job: `@trackunit/migrations`'\n * `run-migrations` generator already awaits `formatFiles(tree)` after every\n * migration. Invoking this orchestrator directly (e.g. against an `FsTree`\n * for an in-repo corpus run) must also call `formatFiles` before flushing,\n * otherwise Prettier/Tailwind class order will leave migrated files failing\n * the format gate.\n */\nexport function pContentSpaceCodemod(tree: Tree): void {\n const { resolved, unresolved } = resolveExtensionTypes(tree);\n\n const filesChanged = new Set<string>();\n const changes: Array<MigrationChangeReport> = [];\n const reports: Array<UnresolvedSurfaceReport> = [];\n let asaWorkOccurred = false;\n\n for (const extension of resolved) {\n if (ASSET_SITE_ADMIN_TYPES.has(extension.type)) {\n asaWorkOccurred = true;\n addAll(filesChanged, rewritePageContent(tree, extension).filesChanged);\n const inventResult = inventContentSpace(tree, extension);\n addAll(filesChanged, inventResult.filesChanged);\n changes.push(...inventResult.changes);\n // Runs after invent so a just-invented shell also loses redundant `pb-*`.\n // Removal is keyed on `p-content-space` being present in the same\n // classname string, so unresolved surfaces are a no-op.\n addAll(filesChanged, removeRedundantPadding(tree, extension).filesChanged);\n\n const entryComponentPath = `${extension.sourceRoot}/${extension.main ?? \"index.tsx\"}`;\n for (const skippedRouteName of inventResult.skippedRouteNames) {\n reports.push({\n extensionId: extension.id,\n sourceRoot: extension.sourceRoot,\n entryComponentPath: tree.exists(entryComponentPath) ? entryComponentPath : null,\n docsLink: PADDING_DOCS_LINK,\n skippedRouteName,\n skipReason: {\n code: \"router-no-analysable-leaves\",\n message: `route \"${skippedRouteName}\" could not be analysed into an inventable overflow content shell`,\n },\n });\n }\n\n const report = findUnresolvedSurface(tree, extension);\n if (report !== null) {\n reports.push({\n ...report,\n skipReason: inventResult.unresolvedReason ?? report.skipReason,\n });\n }\n continue;\n }\n\n if (FLEET_CUSTOMER_HOME_TYPES.has(extension.type)) {\n addAll(filesChanged, rewritePageContent(tree, extension).filesChanged);\n continue;\n }\n }\n\n const lossyConversionCount = changes.filter(isLossyConversion).length;\n logSummary(filesChanged.size, reports.length + lossyConversionCount);\n\n for (const change of changes) {\n const message = formatChangeReport(change);\n if (isLossyConversion(change)) {\n logger.warn(message);\n } else {\n logger.info(message);\n }\n }\n\n for (const report of reports) {\n logger.warn(formatUnresolvedReport(report));\n }\n\n for (const message of collectAsaEndOfRunMessages({ asaWorkOccurred, changes, unresolvedReports: reports })) {\n logger.info(message);\n }\n\n for (const item of unresolved) {\n logger.warn(\n ` ${MIGRATION_NAME}: could not resolve extension import \"${item.specifier}\" referenced by app \"${item.app}\"`\n );\n }\n}\n\nfunction addAll(target: Set<string>, items: ReadonlyArray<string>): void {\n for (const item of items) target.add(item);\n}\n\nconst isLossyConversion = (change: MigrationChangeReport): boolean =>\n change.kind === \"conversion\" && change.removedTokens.some(token => token.includes(\":\") || /-(?:0|0\\.5)$/.test(token));\n\n/** Mirrors the log style of `logSummary` in `libs/react/components/migrations/utils/jsx-utils.ts`. */\nfunction logSummary(touched: number, manualReviewNeeded: number): void {\n if (touched === 0) {\n logger.info(` ${MIGRATION_NAME}: no files changed`);\n return;\n }\n const reviewSuffix = manualReviewNeeded > 0 ? ` (${manualReviewNeeded} location(s) need manual review)` : \"\";\n logger.info(` ${MIGRATION_NAME}: updated ${touched} file(s)${reviewSuffix}`);\n}\n\n/**\n * Explicit addition/conversion log so a third-party reading the migration\n * output knows exactly what invent/convert did on each shell.\n */\nfunction formatChangeReport(change: MigrationChangeReport): string {\n if (change.kind === \"addition\") {\n return ` ${MIGRATION_NAME}: addition on \"${change.extensionId}\" (${change.filePath}): \"${change.before}\" → \"${change.after}\"`;\n }\n const removed = change.removedTokens.join(\", \");\n return ` ${MIGRATION_NAME}: conversion on \"${change.extensionId}\" (${change.filePath}): removed [${removed}]; \"${change.before}\" → \"${change.after}\"`;\n}\n\nexport default pContentSpaceCodemod;\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-redundant-padding.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/remove-redundant-padding.ts"],"names":[],"mappings":";;AAyBA,wDAiBC;AAzCD,wEAAiF;AACjF,0EAAoF;AAGpF,MAAM,sBAAsB,GAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAC9F,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAE9C;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,sBAAsB,CAAC,IAAU,EAAE,SAA4B;IAC7E,OAAO,IAAA,0DAAkC,EACvC,IAAI,EACJ,SAAS,CAAC,UAAU,EACpB,OAAO,CAAC,EAAE,CACR,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EACxG,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,IAAA,kCAAY,EAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACvD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,sBAAsB,EAAE,CAAC;YAC3C,MAAM,GAAG,IAAA,uCAAiB,EAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Tree } from \"@nx/devkit\";\nimport { replaceClassToken, splitClasses } from \"@trackunit/css-classname-utils\";\nimport { transformClassnamesUnderSourceRoot } from \"../utils/classname-ast-rewrite\";\nimport type { ResolvedExtension } from \"../utils/resolve-extension-types\";\n\nconst REDUNDANT_INSET_TOKENS: Array<string> = [\"pb-8\", \"pb-6\", \"pb-4\", \"pb-responsive-space\"];\nconst PADDED_REGION_TOKEN = \"p-content-space\";\n\n/**\n * Removes the redundant bottom-inset Tailwind tokens (`pb-8`, `pb-6`, `pb-4`,\n * `pb-responsive-space`) from classname strings that already carry\n * `p-content-space` under a single resolved extension's `sourceRoot`.\n *\n * Scoped to the padded region on purpose: local `pb-*` used as component\n * spacing (cards, timeline entries, wizard steps) must not be stripped just\n * because they live under the same `sourceRoot`. Callers must run\n * `rewritePageContent` first so a just-migrated `page-content` region already\n * reads as `p-content-space` before this transform looks for it. Extensions\n * with no padded region (the ones `findUnresolvedSurface` will report) are\n * therefore a complete no-op here — there is no `p-content-space` token to\n * key off.\n *\n * Scoped to one extension per call — the caller (the orchestrator) loops\n * over every Asset Home/Site Home/Admin extension.\n */\nexport function removeRedundantPadding(tree: Tree, extension: ResolvedExtension): { filesChanged: Array<string> } {\n return transformClassnamesUnderSourceRoot(\n tree,\n extension.sourceRoot,\n content =>\n content.includes(PADDED_REGION_TOKEN) && REDUNDANT_INSET_TOKENS.some(token => content.includes(token)),\n value => {\n if (!splitClasses(value).includes(PADDED_REGION_TOKEN)) {\n return value;\n }\n let result = value;\n for (const token of REDUNDANT_INSET_TOKENS) {\n result = replaceClassToken(result, token, \"\");\n }\n return result;\n }\n );\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-run-messaging.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/report-run-messaging.ts"],"names":[],"mappings":";;;AAAA,wEAA8D;AAC9D,2DAAkH;AAElH,MAAM,cAAc,GAAG,yBAAyB,CAAC;AASjD;;;;;GAKG;AACI,MAAM,gCAAgC,GAAG,GAAW,EAAE,CAC3D,KAAK,cAAc,8GAA8G,CAAC;AADvH,QAAA,gCAAgC,oCACuF;AAEpI;;;;GAIG;AACI,MAAM,6BAA6B,GAAG,GAAW,EAAE,CACxD,KAAK,cAAc,qYAAqY,qCAAiB,EAAE,CAAC;AADja,QAAA,6BAA6B,iCACoY;AAE9a;;;GAGG;AACI,MAAM,sBAAsB,GAAG,CAAC,MAA+B,EAAU,EAAE;IAChF,MAAM,YAAY,GAChB,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,MAAM,CAAC,UAAU,CAAC,IAAI,MAAM,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;IAE/G,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,KAAK,cAAc,gBAAgB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,UAAU,oBAAoB,MAAM,CAAC,gBAAgB,IAAI,YAAY,IAAI,uDAAuD,SAAS,MAAM,CAAC,QAAQ,EAAE,CAAC;IACtO,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,KAAK,cAAc,gBAAgB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,UAAU,sBAAsB,YAAY,mFAAmF,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC5N,CAAC;IAED,OAAO,KAAK,cAAc,gBAAgB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,UAAU,gOAAgO,MAAM,CAAC,QAAQ,EAAE,CAAC;AACvU,CAAC,CAAC;AAbW,QAAA,sBAAsB,0BAajC;AAEF;;;;GAIG;AACI,MAAM,8BAA8B,GAAG,CAAC,OAA6C,EAAiB,EAAE;IAC7G,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACpF,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CACX,KAAK,cAAc,wBAAwB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,QAAQ,0GAA0G,CAC7L,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAXW,QAAA,8BAA8B,kCAWzC;AAEF;;;;GAIG;AACI,MAAM,0BAA0B,GAAG,CAAC,OAA2B,EAAiB,EAAE;IACvF,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,sCAA8B,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,IAAA,qCAA6B,GAAE,CAAC,CAAC;IACjD,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,IAAA,wCAAgC,GAAE,CAAC,CAAC;IAClD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAXW,QAAA,0BAA0B,8BAWrC;AAEF,MAAM,sBAAsB,GAAG,CAAC,cAAsB,EAAW,EAAE;IACjE,OAAO,IAAA,kCAAY,EAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC","sourcesContent":["import { splitClasses } from \"@trackunit/css-classname-utils\";\nimport { PADDING_DOCS_LINK, type MigrationChangeReport, type UnresolvedSurfaceReport } from \"./report-unresolved\";\n\nconst MIGRATION_NAME = \"p-content-space-codemod\";\n\nexport type AsaEndOfRunContext = {\n /** True when any ASA extension was visited this migration run. */\n readonly asaWorkOccurred: boolean;\n readonly changes: ReadonlyArray<MigrationChangeReport>;\n readonly unresolvedReports: ReadonlyArray<UnresolvedSurfaceReport>;\n};\n\n/**\n * Developer-facing end-of-run reminder: verify appearance after migration, and\n * note that intentional edge-to-edge (no content inset) remains an allowed choice.\n * Emitted at most once per run when any ASA work happened — including runs that\n * only produced unresolved reports and no invent/convert edits.\n */\nexport const buildVerifyAndEdgeToEdgeReminder = (): string =>\n ` ${MIGRATION_NAME}: verify UI after migration; edge-to-edge content (no p-content-space) is an allowed choice when intentional`;\n\n/**\n * Explains what an inventable overflow content shell is when the migration\n * could not auto-pad one or more Asset/Site/Admin surfaces. Emitted once per\n * run that produced unresolved reports.\n */\nexport const buildUnresolvedInventGuidance = (): string =>\n ` ${MIGRATION_NAME}: could not auto-invent p-content-space on the surface(s) above — invent only targets a single inventable overflow content shell (a div/main/section with an editable className that itself owns overflow-auto/scroll, with no PageHeader/Topbar child). Card-only roots, multi-route graphs, and unclear shells need a manual p-content-space on that scroll owner (or accept edge-to-edge). See ${PADDING_DOCS_LINK}`;\n\n/**\n * Per-extension unresolved warning. Prefer this over a bare \"no token\" line so\n * developers learn *why* invent skipped them.\n */\nexport const formatUnresolvedReport = (report: UnresolvedSurfaceReport): string => {\n const reasonSuffix =\n report.skipReason === undefined ? \"\" : ` — reason [${report.skipReason.code}]: ${report.skipReason.message}`;\n\n if (report.skippedRouteName !== undefined) {\n return ` ${MIGRATION_NAME}: extension \"${report.extensionId}\" (${report.sourceRoot}) skipped route \"${report.skippedRouteName}\"${reasonSuffix || \" — no inventable overflow content shell on that route\"}; see ${report.docsLink}`;\n }\n\n if (report.skipReason !== undefined) {\n return ` ${MIGRATION_NAME}: extension \"${report.extensionId}\" (${report.sourceRoot}) not auto-invented${reasonSuffix}; add p-content-space manually on the scroll owner or accept edge-to-edge — see ${report.docsLink}`;\n }\n\n return ` ${MIGRATION_NAME}: extension \"${report.extensionId}\" (${report.sourceRoot}) has no page-content/p-content-space and no inventable overflow content shell (needs a scrolling div/main/section with editable className, not e.g. a bare Card) — add p-content-space manually or accept edge-to-edge; see ${report.docsLink}`;\n};\n\n/**\n * Advisory-only scrollbar notes for invent/convert onto a self-scrolling\n * (`overflow-*`) shell. Cannot measure real DOM scrollbars in the codemod —\n * documents the preferred flush-scrollbar outcome after content owns padding.\n */\nexport const buildScrollbarAdvisoryMessages = (changes: ReadonlyArray<MigrationChangeReport>): Array<string> => {\n const messages: Array<string> = [];\n for (const change of changes) {\n if (!shellHasOverflowScroll(change.before) && !shellHasOverflowScroll(change.after)) {\n continue;\n }\n messages.push(\n ` ${MIGRATION_NAME}: scrollbar note on \"${change.extensionId}\" (${change.filePath}): shell uses overflow scrolling — prefer a flush scrollbar at the panel edge after content owns padding`\n );\n }\n return messages;\n};\n\n/**\n * Collects end-of-run ASA developer messages (scrollbar advisories, unresolved\n * invent guidance when needed, + single verify/edge-to-edge reminder). Empty\n * when no ASA work occurred this run.\n */\nexport const collectAsaEndOfRunMessages = (context: AsaEndOfRunContext): Array<string> => {\n if (!context.asaWorkOccurred) {\n return [];\n }\n\n const messages = buildScrollbarAdvisoryMessages(context.changes);\n if (context.unresolvedReports.length > 0) {\n messages.push(buildUnresolvedInventGuidance());\n }\n messages.push(buildVerifyAndEdgeToEdgeReminder());\n return messages;\n};\n\nconst shellHasOverflowScroll = (classnameValue: string): boolean => {\n return splitClasses(classnameValue).some(cls => /(^|:)overflow-/.test(cls));\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-unresolved.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/report-unresolved.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Tree } from \"@nx/devkit\";\nimport { splitClasses } from \"@trackunit/css-classname-utils\";\nimport { findClassnameLocations, parseTsestreeSource, visitRewritableFiles } from \"../utils/classname-ast-rewrite\";\nimport type { ResolvedExtension } from \"../utils/resolve-extension-types\";\nimport { resolveContentShells } from \"./resolve-content-shell\";\n\nconst PAGE_CONTENT_TOKEN = \"page-content\";\nconst CONTENT_SPACE_TOKEN = \"p-content-space\";\nconst RESOLVED_TOKENS: Array<string> = [PAGE_CONTENT_TOKEN, CONTENT_SPACE_TOKEN];\n\nconst tokenBase = (token: string): string => (token.includes(\":\") ? token.slice(token.lastIndexOf(\":\") + 1) : token);\n\nconst isResolvedToken = (token: string): boolean => RESOLVED_TOKENS.includes(tokenBase(token));\n\nconst DEFAULT_ENTRY_COMPONENT_FILE = \"index.tsx\";\n\n/** In-repo docs for inventable overflow content shells (GLU-1571 / p-content-space migration). */\nexport const PADDING_DOCS_LINK = \"docs/tech/TAILWIND-ARCHITECTURE.md#p-content-space-inventable-shell\";\n\nexport type MigrationChangeKind = \"addition\" | \"conversion\";\n\n/**\n * Structured invent/convert outcome for a single content-shell edit. Emitted\n * so the orchestrator can log exactly what changed (added vs converted).\n */\nexport type MigrationChangeReport = {\n extensionId: string;\n sourceRoot: string;\n filePath: string;\n kind: MigrationChangeKind;\n /** Classname string on the shell before invent/convert. */\n before: string;\n /** Classname string on the shell after invent/convert. */\n after: string;\n /** Custom shell padding tokens removed (empty for pure additions). */\n removedTokens: Array<string>;\n};\n\nimport type { ShellSkipReason } from \"./shell-skip-reason\";\n\nexport type UnresolvedSurfaceReport = {\n extensionId: string;\n sourceRoot: string;\n /** Best-effort resolved path to the extension's entry component; `null` when it can't be found in the Tree. */\n entryComponentPath: string | null;\n docsLink: string;\n /** Route component or imported route binding that could not be analysed on a partial graph. */\n skippedRouteName?: string;\n /** Why invent/resolve declined this surface (when known). */\n skipReason?: ShellSkipReason;\n};\n\n/**\n * Read-only check for whether a single file already contains `page-content`\n * or `p-content-space` as a whole classname token (not matching inside e.g.\n * `page-content-with-gap`). Used as a suppressor on unresolvable graphs so\n * resolver limits do not permanently light up already-migrated extensions.\n */\nfunction fileHasResolvedToken(content: string): boolean {\n if (!RESOLVED_TOKENS.some(token => content.includes(token))) return false;\n\n const program = parseTsestreeSource(content);\n const locations = findClassnameLocations(program);\n return locations.some(location => splitClasses(location.value).some(isResolvedToken));\n}\n\nfunction sourceRootHasResolvedToken(tree: Tree, extension: ResolvedExtension): boolean {\n let found = false;\n visitRewritableFiles(tree, extension.sourceRoot, (_filePath, content) => {\n if (found) return;\n if (fileHasResolvedToken(content)) {\n found = true;\n }\n });\n return found;\n}\n\n/**\n * Determines whether the inventable content shell of an Asset Home/Site Home/Admin\n * extension still lacks `page-content` / `p-content-space`, and if so, builds a\n * report entry describing it.\n *\n * A token on a nested file is not enough when the graph *resolves*: Device\n * Administration hid behind `p-content-space` on a job-details leaf while the\n * layout shell still used `pb-responsive-space` (GLU-1903). Returns `null` only\n * when every *resolved content shell* already carries a resolved token (or still\n * uses `page-content`, which `rewritePageContent` handles separately so it must\n * not be double-reported).\n *\n * An unresolvable graph is *not* treated as a leftover if any rewritable file\n * already has a resolved token — otherwise Device Administration (and ~24 other\n * ASA extensions the walker cannot follow) stay permanently-on after padding.\n * Unresolvable graphs with no token anywhere still report.\n *\n * This function is read-only: it never calls `tree.write`. Callers must run it\n * against Tree state that already reflects `rewritePageContent`'s and\n * `removeRedundantPadding`'s edits for the same extension, since those two\n * transforms mutate `page-content` into `p-content-space` in place — running\n * this check first, against pre-rewrite content, would misreport a\n * just-fixed extension as unresolved.\n *\n * A `sourceRoot` that doesn't exist in the Tree at all (or contains no\n * rewritable files) is treated the same as \"no page-content and no\n * p-content-space found\": it gets reported, not silently skipped.\n */\nexport function findUnresolvedSurface(tree: Tree, extension: ResolvedExtension): UnresolvedSurfaceReport | null {\n const resolved = resolveContentShells(tree, extension);\n if (resolved.status === \"resolved\") {\n const everyShellHasResolvedToken = resolved.shells.every(shell =>\n splitClasses(shell.combinedClassnameValue).some(isResolvedToken)\n );\n if (everyShellHasResolvedToken) {\n return null;\n }\n } else if (sourceRootHasResolvedToken(tree, extension)) {\n return null;\n }\n\n const entryComponentPath = `${extension.sourceRoot}/${extension.main ?? DEFAULT_ENTRY_COMPONENT_FILE}`;\n\n return {\n extensionId: extension.id,\n sourceRoot: extension.sourceRoot,\n entryComponentPath: tree.exists(entryComponentPath) ? entryComponentPath : null,\n docsLink: PADDING_DOCS_LINK,\n };\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-content-shell.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/resolve-content-shell.ts"],"names":[],"mappings":";;;;AACA,wEAA0G;AAC1G,oDAAyE;AACzE,4EAAsE;AACtE,wDAAwB;AACxB,0EAA6F;AAE7F,2DAAsG;AA0CtG,MAAM,4BAA4B,GAAG,WAAW,CAAC;AAEjD,MAAM,eAAe,GAAG,CAAC,IAAyB,EAAE,MAAe,EAA6B,EAAE,CAAC,CAAC;IAClG,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,IAAA,mCAAe,EAAC,IAAI,EAAE,MAAM,CAAC;CACtC,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,CAAC,IAAyB,EAAE,MAAe,EAA8B,EAAE,CAAC,CAAC;IACpG,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,IAAA,mCAAe,EAAC,IAAI,EAAE,MAAM,CAAC;CACtC,CAAC,CAAC;AAEH,kFAAkF;AAClF,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;AAEnF;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAW,EAAE;IACnD,IACE,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,4BAA4B;QACrC,IAAI,KAAK,oBAAoB,EAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,KAAK,gBAAgB,CAAC;AAChE,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACI,MAAM,oBAAoB,GAAG,CAAC,IAAU,EAAE,SAA4B,EAA8B,EAAE;IAC3G,MAAM,SAAS,GAAG,GAAG,SAAS,CAAC,UAAU,IAAI,SAAS,CAAC,IAAI,IAAI,4BAA4B,EAAE,CAAC;IAC9F,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,gBAAgB,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,UAAU,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;AACjF,CAAC,CAAC;AAPW,QAAA,oBAAoB,wBAO/B;AAEF;;;;;GAKG;AACI,MAAM,mBAAmB,GAAG,CAAC,IAAU,EAAE,SAA4B,EAA6B,EAAE;IACzG,MAAM,MAAM,GAAG,IAAA,4BAAoB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,eAAe,CAAC,eAAe,EAAE,wCAAwC,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC,CAAC;AAVW,QAAA,mBAAmB,uBAU9B;AAEF,MAAM,qBAAqB,GAAG,CAC5B,IAAU,EACV,QAAgB,EAChB,UAAkB,EAClB,OAAoB,EACQ,EAAE;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,IAAA,2CAAmB,EAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,gBAAgB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QACnE,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YACnC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACzD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC;IAC/E,CAAC;IAED,MAAM,aAAa,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,gBAAgB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,aAAa,KAAK,gBAAgB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QAClF,OAAO,yBAAyB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACvF,CAAC;IAED,IAAI,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;QAC/C,OAAO,gBAAgB,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAChG,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,gBAAgB,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,yBAAyB,GAAG,CAChC,IAAU,EACV,QAAgB,EAChB,OAAyB,EACzB,cAAmC,EACnC,UAAkB,EAClB,OAAoB,EACQ,EAAE;IAC9B,MAAM,UAAU,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC;IAC3D,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IACnG,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;QAC9B,OAAO,6BAA6B,CAAC,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACpF,CAAC;IAED,oEAAoE;IACpE,OAAO,8BAA8B,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACtF,CAAC,CAAC;AAEF,MAAM,6BAA6B,GAAG,CACpC,IAAU,EACV,gBAAwB,EACxB,UAAkB,EAClB,OAAoB,EACQ,EAAE;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,OAAO,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,IAAA,2CAAmB,EAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,8BAA8B,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AAC9F,CAAC,CAAC;AAYF,MAAM,8BAA8B,GAAG,CACrC,IAAU,EACV,cAAsB,EACtB,OAAyB,EACzB,UAAkB,EAClB,OAAoB,EACQ,EAAE;IAC9B,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,gBAAgB,CAAC,6BAA6B,EAAE,gDAAgD,CAAC,CAAC;IAC3G,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC,EAAE,CAAC;QACxD,OAAO,gBAAgB,CAAC,gCAAgC,EAAE,cAAc,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAClC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CACnF,CAAC;IACF,MAAM,iBAAiB,GAAkB,6BAA6B,CAAC,OAAO,CAAC,CAAC,MAAM,CACpF,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CACxC,CAAC;IAEF,MAAM,QAAQ,GAAyB,EAAE,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,MAAM,aAAa,GAAG,0BAA0B,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QACjH,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,UAAU,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/G,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAC/C,OAAO,gBAAgB,CACrB,6BAA6B,EAC7B,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CACvE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC;QAC5B,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,CAAC;KAClD,CAAC;AACJ,CAAC,CAAC;AAMF,MAAM,qBAAqB,GAAG,CAC5B,IAAU,EACV,QAAgB,EAChB,aAAqB,EACrB,UAAkB,EAClB,OAAoB,EACW,EAAE;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,IAAI,aAAa,EAAE,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,IAAI,aAAa,EAAE,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,IAAA,2CAAmB,EAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QACnE,MAAM,WAAW,GAAG,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACpE,IAAI,WAAW,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,WAAW,GACf,qBAAqB,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3G,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;IACzF,CAAC;IAED,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,kBAAkB,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC5F,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kEAAkE;IAClE,2EAA2E;IAC3E,oEAAoE;IACpE,OAAO,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACjF,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,OAA4B,EAAiB,EAAE;IAC9E,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QAC1D,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,YAAY;YAAE,SAAS;QAC7D,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACvG,IAAI,SAAS,CAAC,KAAK,EAAE,IAAI,KAAK,sBAAc,CAAC,sBAAsB;YAAE,SAAS;QAC9E,IAAI,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;YAClE,OAAO,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,yBAAyB,GAAG,CAAC,UAAuC,EAA8B,EAAE;IACxG,IAAI,CAAC,CAAC,MAAM,IAAI,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,IAAI,IAAI,CAAC;AACjC,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,CAAC,OAAyB,EAAsB,EAAE;IAC5E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,kBAAkB;gBAAE,OAAO;YAC5D,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;gBAAE,OAAO;YACvD,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc;gBAAE,OAAO;YACzE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;gBAAE,OAAO;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,OAAO,EAAE,IAAI,KAAK,sBAAc,CAAC,gBAAgB;gBAAE,OAAO;YAC9D,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC;gBACV,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI;gBAC1B,aAAa,EAAE,iCAAiC,CAAC,OAAO,CAAC;gBACzD,kBAAkB,EAAE,wBAAwB,CAAC,OAAO,CAAC;aACtD,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc;gBAAE,OAAO;YACxD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;gBAAE,OAAO;YACtC,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,OAAO;YACnE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,OAAO,EAAE,IAAI,KAAK,sBAAc,CAAC,gBAAgB;gBAAE,OAAO;YAC9D,MAAM,CAAC,IAAI,CAAC;gBACV,YAAY,EAAE,IAAI;gBAClB,aAAa,EAAE,iCAAiC,CAAC,OAAO,CAAC;gBACzD,kBAAkB,EAAE,wBAAwB,CAAC,OAAO,CAAC;aACtD,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,CAAC,OAAkC,EAAiB,EAAE;IACrF,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1C,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,QAAQ;YAAE,SAAS;QACxD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,gBAAgB;YAAE,SAAS;QACxG,IACE,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,uBAAuB;YAC9D,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,kBAAkB,EACzD,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;YAC3D,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAClC,CAAC;QACD,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc,EAAE,CAAC;YAC/D,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,IAAI,SAAS,CAAC,QAAQ,KAAK,IAAI;oBAAE,SAAS;gBAC/F,MAAM,GAAG,GAAG,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAClD,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;oBAC3C,OAAO,GAAG,CAAC,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,6BAA6B,GAAG,CAAC,OAAyB,EAAiB,EAAE;IACjF,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc;gBAAE,OAAO;YACxD,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAAE,OAAO;YACzF,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;gBAAE,OAAO;YACpE,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,aAAa;gBAAE,OAAO;YACxD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,GAAG,EAAE,IAAI,KAAK,sBAAc,CAAC,eAAe;gBAAE,OAAO;YACzD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACnC,IAAI,OAAO,EAAE,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;oBAChD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAE9C,MAAM,oBAAoB,GAAG,CAAC,KAA2B,EAAW,EAAE,CACpE,IAAA,kCAAY,EAAC,KAAK,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAEnE;;;GAGG;AACH,MAAM,qBAAqB,GAAG,CAAC,MAAoC,EAA+B,EAAE;IAClG,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAChC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,KAAK,cAAc,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC/C,MAAM,QAAQ,GAAgC,EAAE,CAAC;IAEjD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,KAAK,cAAc;YAAE,SAAS;QACvD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;QACpF,MAAM,0BAA0B,GAAG,WAAW,CAAC,IAAI,CACjD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC5E,CAAC;QACF,IAAI,0BAA0B,EAAE,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,YAAY;YAAE,SAAS;QAC9E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACrB,IAAmB,EACnB,MAAqB,EACrB,UAAsC,EAC7B,EAAE;IACX,IAAI,MAAM,CAAC,YAAY,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,OAAO,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,IAAI,OAAO,KAAK,MAAM,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClB,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,kBAAkB,IAAI,IAAI,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,KAA4B,EAAiB,EAAE;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,IAA6B,EAAW,EAAE;IACpE,MAAM,UAAU,GAAG,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,IAAI,UAAU,KAAK,iBAAiB,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,2CAA2C;IAC3C,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9D,OAAO,SAAS,KAAK,4BAA4B,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAC9B,MAAyE,EAC1D,EAAE;IACjB,IAAI,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QAC9C,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,yBAAyB,EAAE,CAAC;QAC7D,OAAO,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,iCAAiC,GAAG,CAAC,OAAkC,EAAiB,EAAE;IAC9F,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1C,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,QAAQ;YAAE,SAAS;QACxD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QACnG,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;YACtD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,0BAA0B,GAAG,CACjC,IAAU,EACV,OAAyB,EACzB,YAAoB,EACpB,UAAkB,EAClB,aAAqB,EACN,EAAE;IACjB,MAAM,QAAQ,GAAG,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAClG,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,qBAAqB,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC;QAC3D,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,OAAmD,EAAW,EAAE;IAC7F,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,KAAK;gBAAE,OAAO;YAClB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,iBAAiB;gBAAE,OAAO;YAC3D,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,CAC5B,IAAU,EACV,QAAgB,EAChB,OAAyB,EACzB,IAAyB,EACzB,UAAkB,EAClB,OAAoB,EACX,EAAE;IACX,KAAK,MAAM,SAAS,IAAI,gCAAgC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,4BAA4B,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;YAC1F,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,gCAAgC,GAAG,CAAC,IAAyB,EAAiB,EAAE;IACpF,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;YAAE,SAAS;QACvD,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,4BAA4B,GAAG,CACnC,IAAU,EACV,YAAoB,EACpB,WAA6B,EAC7B,aAAqB,EACrB,UAAkB,EAClB,OAAoB,EACX,EAAE;IACX,MAAM,QAAQ,GAAG,GAAG,YAAY,eAAe,aAAa,EAAE,CAAC;IAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,IAAI,OAAO,GAAG,WAAW,CAAC;IAC1B,IAAI,qBAAqB,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QACxG,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC;YACH,OAAO,GAAG,IAAA,2CAAmB,EAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,qBAAqB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC1D,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,mBAAmB,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,qBAAqB,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,MAA2C,EAA+B,EAAE;IAChG,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAgC,EAAE,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5G,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,CAAC,OAAyB,EAAqD,EAAE;IAC1G,MAAM,iBAAiB,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;IAClE,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS;QAC5B,MAAM,GAAG,GAAG,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,GAAG,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,8BAA8B,GAAG,CAAC,OAAyB,EAAiB,EAAE;IAClF,IAAI,MAAM,GAAkB,IAAI,CAAC;IAEjC,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc;gBAAE,OAAO;YACxD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC;gBAAE,OAAO;YAC1D,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,sBAAc,CAAC,gBAAgB;gBAAE,OAAO;YAExE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;gBACpD,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,QAAQ;oBAAE,SAAS;gBACxD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,eAAe;oBAAE,SAAS;gBACvG,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;oBACtD,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,CAAC,SAAoC,EAAiB,EAAE;IACvF,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,sBAAsB,EAAE,CAAC;QAC7D,IAAI,SAAS,CAAC,WAAW,EAAE,IAAI,KAAK,sBAAc,CAAC,mBAAmB,EAAE,CAAC;YACvE,OAAO,SAAS,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,IAAI,IAAI,CAAC;QAChD,CAAC;QACD,IAAI,SAAS,CAAC,WAAW,EAAE,IAAI,KAAK,sBAAc,CAAC,mBAAmB,EAAE,CAAC;YACvE,MAAM,UAAU,GAAG,SAAS,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACzD,IAAI,UAAU,CAAC,EAAE,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;gBACrD,OAAO,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,wBAAwB,EAAE,CAAC;QAC/D,IAAI,SAAS,CAAC,WAAW,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;YAC7D,OAAO,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC;QACpC,CAAC;QACD,IAAI,SAAS,CAAC,WAAW,CAAC,IAAI,KAAK,sBAAc,CAAC,mBAAmB,EAAE,CAAC;YACtE,OAAO,SAAS,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,IAAI,IAAI,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAC5B,OAAyB,EACzB,IAAY,EACuC,EAAE;IACrD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,sBAAsB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC7B,SAAoC,EACpC,IAAY,EAC0C,EAAE;IACxD,MAAM,IAAI,GACR,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,sBAAsB;QACxD,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,wBAAwB;QACxD,CAAC,CAAC,SAAS,CAAC,WAAW;QACvB,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAE/B,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,mBAAmB,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAClG,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,mBAAmB,EAAE,CAAC;QACrD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC3C,IAAI,UAAU,CAAC,EAAE,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,UAAU,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI;gBAAE,SAAS;YAC9F,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;YAC7B,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,uBAAuB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,kBAAkB,EAAE,CAAC;gBAC5G,OAAO,IAAI,CAAC,IAAI,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,mBAAmB,IAAI,SAAS,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACxF,OAAO,SAAS,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CACtB,IAAmD,EACA,EAAE;IACrD,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,WAAW,EAAE,CAAC;QACxF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc,EAAE,CAAC;QAChD,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,IAAI,SAAS,CAAC,QAAQ,KAAK,IAAI;gBAAE,SAAS;YAC/F,MAAM,GAAG,GAAG,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAClD,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,WAAW,EAAE,CAAC;gBACtF,OAAO,GAAG,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,UAA+B,EAAuB,EAAE;IACjF,IAAI,OAAO,GAAG,UAAU,CAAC;IACzB,OAAO,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,qBAAqB,EAAE,CAAC;QAC/G,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,cAAc,GAAG,CACrB,IAAgD,EACG,EAAE;IACrD,IAAI,OAAO,GAA+C,IAAI,CAAC;IAE/D,SAAS,CAAC;QACR,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,WAAW,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAChC,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAChC,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CACpB,QAA0C,EACS,EAAE;IACrD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,WAAW,EAAE,CAAC;YAC1F,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,OAAmD,EAAW,EAAE;IACrF,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC7D,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,IAAI,KAAK,IAAI,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,OAAmD,EAAiB,EAAE;IACjG,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC5D,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAmC,EAAiB,EAAE;IAC/E,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,sBAAsB,GAAG,CAC7B,QAAgB,EAChB,OAAyB,EACzB,IAAyB,EACE,EAAE;IAC7B,MAAM,cAAc,GAAG,gCAAgC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACvE,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,eAAe,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,4BAA4B,CAAC,IAAA,kCAAY,EAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAClG,OAAO,eAAe,CAAC,2BAA2B,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAClE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,eAAe,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,eAAe,CAAC,8BAA8B,EAAE,QAAQ,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,eAAe,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO,eAAe,CAAC,wBAAwB,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,eAAe,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACpD,CAAC;IACD,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,KAAK,EAAE;YACL,QAAQ;YACR,cAAc,EAAE,QAAQ,CAAC,KAAK;YAC9B,sBAAsB,EAAE,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YACxF,QAAQ;SACT;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,gCAAgC,GAAG,CACvC,OAAyB,EACzB,IAAyB,EACC,EAAE;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CACnD,CAAC,IAAI,EAAiC,EAAE,CACtC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,YAAY;QACzC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa;QAC/C,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CACjE,CAAC;IACF,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAEvC,8CAA8C;IAC9C,MAAM,aAAa,GAAG,IAAA,8CAAsB,EAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;QACtE,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO,KAAK,CAAC;QAC5D,OAAO,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClH,CAAC,CAAC,CAAC;IACH,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,aAAa,CAAC;IAEnD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;IAC9B,IAAI,KAAK,EAAE,IAAI,KAAK,sBAAc,CAAC,sBAAsB;QAAE,OAAO,EAAE,CAAC;IACrE,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IAEpC,IAAI,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc,EAAE,CAAC;QACtD,OAAO,sCAAsC,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QAClD,OAAO,kCAAkC,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,sCAAsC,GAAG,CAC7C,OAAyB,EACzB,cAAuC,EACb,EAAE;IAC5B,IAAI,cAAc,CAAC,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QAC7D,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9C,IAAI,IAAA,wCAAkB,EAAC,UAAU,CAAC,EAAE,CAAC;QACnC,OAAO,IAAA,8CAAsB,EAAC,OAAO,CAAC,CAAC,MAAM,CAC3C,QAAQ,CAAC,EAAE,CACT,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;YACvD,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAC1D,CAAC;IACJ,CAAC;IAED,OAAO,kCAAkC,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACjE,CAAC,CAAC;AAEF,MAAM,kCAAkC,GAAG,CAAC,OAAyB,EAAE,IAAY,EAA4B,EAAE;IAC/G,MAAM,YAAY,GAAG,gCAAgC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrE,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,IAAA,8CAAsB,EAAC,OAAO,CAAC,CAAC,MAAM,CAC3C,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,CAC/G,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,gCAAgC,GAAG,CAAC,OAAyB,EAAE,IAAY,EAAyB,EAAE;IAC1G,IAAI,MAAM,GAA0B,IAAI,CAAC;IAEzC,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,kBAAkB;gBAAE,OAAO;YAC5D,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO;YAChF,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO;YAC/B,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC3B,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,8CAA8C,CAAC;AAC3E,MAAM,iBAAiB,GAAG,sCAAsC,CAAC;AAEjE,MAAM,8BAA8B,GAAG,CAAC,OAA8B,EAAW,EAAE,CACjF,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAErD,MAAM,4BAA4B,GAAG,CAAC,OAA8B,EAAW,EAAE,CAC/E,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEnD,MAAM,uBAAuB,GAAG,CAAC,QAA2B,EAAW,EAAE;IACvE,MAAM,OAAO,GAAG,IAAA,kCAAY,EAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,4BAA4B,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,8BAA8B,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE1F,MAAM,iBAAiB,GAAG,CAAC,IAAyB,EAAW,EAAE,CAC/D,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;IACpC,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,IAAI,KAAK,IAAI,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEL,MAAM,oBAAoB,GAAG,CAAC,OAAyB,EAAE,IAAyB,EAAW,EAAE,CAC7F,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CACpC,gCAAgC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CACjF,CAAC;AAEJ,MAAM,gBAAgB,GAAG,CAAC,IAAyB,EAA8B,EAAE;IACjF,MAAM,KAAK,GAA+B,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,CAAC,QAA0C,EAAQ,EAAE;QACjE,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;gBAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClB,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,WAAW,EAAE,CAAC;gBACrD,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,OAAyB,EAAE,aAAqB,EAAW,EAAE;IACvF,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,IAAA,kCAAc,EAAC,OAAO,EAAE;QACtB,KAAK,EAAE,IAAI,CAAC,EAAE;YACZ,IAAI,SAAS;gBAAE,OAAO;YACtB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,kBAAkB;gBAAE,OAAO;YAC5D,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,aAAa;gBAAE,OAAO;YACzF,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO;YAC/B,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,IAAmB,EAAW,EAAE;IAC7D,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAA,kCAAc,EAAC,IAAI,EAAE;QACnB,KAAK,EAAE,KAAK,CAAC,EAAE;YACb,IAAI,KAAK;gBAAE,OAAO;YAClB,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAc,CAAC,gBAAgB,EAAE,CAAC;gBACnD,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,wBAAwB,GAAG,CAC/B,IAAU,EACV,OAAyB,EACzB,YAAoB,EACpB,UAAkB,EAClB,aAAqB,EACN,EAAE;IACjB,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAc,CAAC,iBAAiB;YAAE,SAAS;QAClE,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;QACzC,IAAI,OAAO,SAAS,KAAK,QAAQ;YAAE,SAAS;QAC5C,MAAM,cAAc,GAAG,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACtD,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,sBAAsB,EAAE,CAAC;gBACxD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;YAC3C,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,EAAE,CAAC;gBACjD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;YAC3C,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,cAAc;YAAE,SAAS;QAE9B,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,cAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,kBAAkB,GAAG,cAAI,CAAC,KAAK,CAAC,SAAS,CAAC,cAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QACrF,MAAM,UAAU,GAAG;YACjB,kBAAkB;YAClB,GAAG,kBAAkB,MAAM;YAC3B,GAAG,kBAAkB,KAAK;YAC1B,GAAG,kBAAkB,YAAY;YACjC,GAAG,kBAAkB,WAAW;SACjC,CAAC;QAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,SAAS,KAAK,YAAY;gBAAE,SAAS;YACzC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,IAAI,SAAS,KAAK,UAAU;gBAAE,SAAS;YAClF,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAAE,SAAS;YACzE,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,uBAAuB;IACvB,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,MAAyC,EAAE,IAAY,EAAW,EAAE;IACzF,OAAO,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC;AAC3E,CAAC,CAAC","sourcesContent":["import type { Tree } from \"@nx/devkit\";\nimport { isTailwindFunction, splitClasses, type ClassnameLocation } from \"@trackunit/css-classname-utils\";\nimport { AST_NODE_TYPES, type TSESTree } from \"@typescript-eslint/types\";\nimport { simpleTraverse } from \"@typescript-eslint/typescript-estree\";\nimport path from \"path\";\nimport { findClassnameLocations, parseTsestreeSource } from \"../utils/classname-ast-rewrite\";\nimport type { ResolvedExtension } from \"../utils/resolve-extension-types\";\nimport { shellSkipReason, type ShellSkipReason, type ShellSkipReasonCode } from \"./shell-skip-reason\";\n\n/**\n * A high-confidence content-region classname host discovered under an\n * extension entry (literal / cva / cn on a div-like shell).\n */\nexport type ResolvedContentShell = {\n readonly filePath: string;\n /** Current classname string at the editable host. */\n readonly classnameValue: string;\n /**\n * Every classname bound to the same host, joined. A cva/cn call can split\n * tokens across arguments (`cvaMerge([\"p-content-space\", \"overflow-auto\"])`);\n * leftover reporting must look at this combined value, not `classnameValue`\n * alone, or it disagrees with invent.\n */\n readonly combinedClassnameValue: string;\n /** AST classname location invent uses to splice the edit. */\n readonly location: ClassnameLocation;\n};\n\nexport type ResolveContentShellResult =\n | { readonly status: \"resolved\"; readonly shell: ResolvedContentShell }\n | { readonly status: \"unresolved\"; readonly reason: ShellSkipReason };\n\n/**\n * Plural discovery result. Multi-route ASA apps may yield 0..N shells:\n * - shared layout content `div` wrapping `<Outlet />` → that layout's shell\n * - no shared layout → one shell per clear route leaf (static imports only)\n * - layout-wins is scoped to that layout's descendant leaves only\n * - unclear / unanalysable routes are named in `skippedRouteNames` when any\n * sibling still resolved (a partial graph must not look fully migrated)\n * - unclear graphs with no resolvable shells → unresolved (never guess a first-div)\n */\nexport type ResolveContentShellsResult =\n | {\n readonly status: \"resolved\";\n readonly shells: ReadonlyArray<ResolvedContentShell>;\n readonly skippedRouteNames: ReadonlyArray<string>;\n }\n | { readonly status: \"unresolved\"; readonly reason: ShellSkipReason };\n\nconst DEFAULT_ENTRY_COMPONENT_FILE = \"index.tsx\";\n\nconst unresolvedShell = (code: ShellSkipReasonCode, detail?: string): ResolveContentShellResult => ({\n status: \"unresolved\",\n reason: shellSkipReason(code, detail),\n});\n\nconst unresolvedShells = (code: ShellSkipReasonCode, detail?: string): ResolveContentShellsResult => ({\n status: \"unresolved\",\n reason: shellSkipReason(code, detail),\n});\n\n/** Intrinsic hosts treated as content-region shells for this walking skeleton. */\nconst DIV_LIKE_ELEMENTS: ReadonlySet<string> = new Set([\"div\", \"main\", \"section\"]);\n\n/**\n * Known non-DOM wrappers to skip when walking from an extension entry toward\n * the content shell (providers, Suspense, fragments).\n * `RouterProvider` is intentionally NOT a wrapper — it branches into light-touch\n * multi-route discovery instead of being skipped.\n */\nconst isKnownWrapperName = (name: string): boolean => {\n if (\n name === \"Suspense\" ||\n name === \"Fragment\" ||\n name === \"TrackunitInternalProviders\" ||\n name === \"TrackunitProviders\"\n ) {\n return true;\n }\n return name.endsWith(\"Provider\") && name !== \"RouterProvider\";\n};\n\n/**\n * Walks from `extension.main` through known non-DOM wrappers and static\n * imports to identify editable content-region classname host(s).\n *\n * Multi-route policy (light-touch, static imports only):\n * 1. Shared layout shell (div-like host wrapping `<Outlet />`) wins → one target.\n * 2. Else each resolvable route leaf with a clear shell is targeted.\n * 3. Exotic / unclear graphs → `{ status: \"unresolved\" }` (never throws; no first-div guess).\n */\nexport const resolveContentShells = (tree: Tree, extension: ResolvedExtension): ResolveContentShellsResult => {\n const entryPath = `${extension.sourceRoot}/${extension.main ?? DEFAULT_ENTRY_COMPONENT_FILE}`;\n if (!tree.exists(entryPath)) {\n return unresolvedShells(\"entry-missing\", entryPath);\n }\n\n return resolveShellsFromFile(tree, entryPath, extension.sourceRoot, new Set());\n};\n\n/**\n * Single-shell convenience wrapper over {@link resolveContentShells}.\n * Returns the first resolved shell when discovery finds one or more; unresolved\n * when none. Prefer {@link resolveContentShells} for RouterProvider / multi-route\n * graphs — an arbitrary one of N leaves is not a useful production answer.\n */\nexport const resolveContentShell = (tree: Tree, extension: ResolvedExtension): ResolveContentShellResult => {\n const result = resolveContentShells(tree, extension);\n if (result.status === \"unresolved\") {\n return { status: \"unresolved\", reason: result.reason };\n }\n const shell = result.shells[0];\n if (shell === undefined) {\n return unresolvedShell(\"unclear-graph\", \"resolved status with empty shells list\");\n }\n return { status: \"resolved\", shell };\n};\n\nconst resolveShellsFromFile = (\n tree: Tree,\n filePath: string,\n sourceRoot: string,\n visited: Set<string>\n): ResolveContentShellsResult => {\n if (visited.has(filePath)) {\n return unresolvedShells(\"cycle\", filePath);\n }\n visited.add(filePath);\n\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) {\n return unresolvedShells(\"entry-missing\", filePath);\n }\n\n let program: TSESTree.Program;\n try {\n program = parseTsestreeSource(content);\n } catch {\n return unresolvedShells(\"parse-failed\", filePath);\n }\n\n const rootJsx = findRootJsxElement(program);\n if (rootJsx === null) {\n return unresolvedShells(\"no-root-jsx\", filePath);\n }\n\n const leaf = unwrapWrappers(rootJsx);\n if (leaf === null) {\n return unresolvedShells(\"empty-wrapper\", filePath);\n }\n\n if (isDivLikeHost(leaf) && leaf.type === AST_NODE_TYPES.JSXElement) {\n const single = pickContentShellInFile(filePath, program, leaf);\n if (single.status === \"unresolved\") {\n return { status: \"unresolved\", reason: single.reason };\n }\n return { status: \"resolved\", shells: [single.shell], skippedRouteNames: [] };\n }\n\n const componentName = getJsxComponentName(leaf);\n if (componentName === null) {\n return unresolvedShells(\"non-host-element\", filePath);\n }\n\n if (componentName === \"RouterProvider\" && leaf.type === AST_NODE_TYPES.JSXElement) {\n return resolveFromRouterProvider(tree, filePath, program, leaf, sourceRoot, visited);\n }\n\n if (isDynamicComponent(program, componentName)) {\n return unresolvedShells(\"dynamic-component\", componentName);\n }\n\n const importPath = resolveStaticLocalImport(tree, program, filePath, sourceRoot, componentName);\n if (importPath === null) {\n return unresolvedShells(\"unresolvable-import\", componentName);\n }\n\n return resolveShellsFromFile(tree, importPath, sourceRoot, visited);\n};\n\n/**\n * Light-touch RouterProvider follow: read `router={name}`, resolve the router\n * module (import or same-file), collect Identifier `component:` targets from\n * `createRootRoute` / `createRoute` / `createRootRouteWithContext`. Skip arrow\n * wrappers and exotic graphs rather than guessing.\n */\nconst resolveFromRouterProvider = (\n tree: Tree,\n filePath: string,\n program: TSESTree.Program,\n routerProvider: TSESTree.JSXElement,\n sourceRoot: string,\n visited: Set<string>\n): ResolveContentShellsResult => {\n const routerName = getRouterPropIdentifier(routerProvider);\n if (routerName === null) {\n return unresolvedShells(\"router-prop-unresolved\");\n }\n\n const routerModulePath = resolveStaticLocalImport(tree, program, filePath, sourceRoot, routerName);\n if (routerModulePath !== null) {\n return collectShellsFromRouterModule(tree, routerModulePath, sourceRoot, visited);\n }\n\n // Same-file router (route factories live alongside RouterProvider).\n return collectShellsFromRouterProgram(tree, filePath, program, sourceRoot, visited);\n};\n\nconst collectShellsFromRouterModule = (\n tree: Tree,\n routerModulePath: string,\n sourceRoot: string,\n visited: Set<string>\n): ResolveContentShellsResult => {\n if (visited.has(routerModulePath)) {\n return unresolvedShells(\"cycle\", routerModulePath);\n }\n visited.add(routerModulePath);\n\n const content = tree.read(routerModulePath, \"utf-8\");\n if (content === null) {\n return unresolvedShells(\"entry-missing\", routerModulePath);\n }\n\n let program: TSESTree.Program;\n try {\n program = parseTsestreeSource(content);\n } catch {\n return unresolvedShells(\"parse-failed\", routerModulePath);\n }\n\n return collectShellsFromRouterProgram(tree, routerModulePath, program, sourceRoot, visited);\n};\n\ntype RouterRoute = {\n readonly variableName: string | null;\n readonly componentName: string | null;\n readonly parentVariableName: string | null;\n};\n\ntype AnalyzedRoute = RouterRoute & {\n readonly analysis: RouteComponentAnalysis | null;\n};\n\nconst collectShellsFromRouterProgram = (\n tree: Tree,\n routerFilePath: string,\n program: TSESTree.Program,\n sourceRoot: string,\n visited: Set<string>\n): ResolveContentShellsResult => {\n const routes = collectRouterRoutes(program);\n if (routes.length === 0) {\n return unresolvedShells(\"router-no-analysable-leaves\", \"no createRoute/createRootRoute factories found\");\n }\n\n if (routes.every(route => route.componentName === null)) {\n return unresolvedShells(\"router-inline-arrow-components\", routerFilePath);\n }\n\n const definedVariableNames = new Set(\n routes.flatMap(route => (route.variableName === null ? [] : [route.variableName]))\n );\n const skippedRouteNames: Array<string> = collectAddChildrenIdentifiers(program).filter(\n name => !definedVariableNames.has(name)\n );\n\n const analyzed: Array<AnalyzedRoute> = [];\n for (const route of routes) {\n if (route.componentName === null) {\n analyzed.push({ ...route, analysis: null });\n continue;\n }\n\n const componentFile = resolveComponentModulePath(tree, program, routerFilePath, sourceRoot, route.componentName);\n if (componentFile === null) {\n skippedRouteNames.push(route.componentName);\n analyzed.push({ ...route, analysis: null });\n continue;\n }\n\n const analysis = analyzeRouteComponent(tree, componentFile, route.componentName, sourceRoot, new Set(visited));\n if (analysis === null) {\n skippedRouteNames.push(route.componentName);\n analyzed.push({ ...route, analysis: null });\n continue;\n }\n\n analyzed.push({ ...route, analysis });\n }\n\n const shells = selectShellsForInvent(analyzed);\n if (shells.length === 0) {\n const skipped = uniqueNames(skippedRouteNames);\n return unresolvedShells(\n \"router-no-analysable-leaves\",\n skipped.length > 0 ? `skipped: ${skipped.join(\", \")}` : routerFilePath\n );\n }\n return {\n status: \"resolved\",\n shells: dedupeShells(shells),\n skippedRouteNames: uniqueNames(skippedRouteNames),\n };\n};\n\ntype RouteComponentAnalysis =\n | { readonly kind: \"layout-shell\"; readonly shell: ResolvedContentShell }\n | { readonly kind: \"leaf-shell\"; readonly shell: ResolvedContentShell };\n\nconst analyzeRouteComponent = (\n tree: Tree,\n filePath: string,\n componentName: string,\n sourceRoot: string,\n visited: Set<string>\n): RouteComponentAnalysis | null => {\n if (visited.has(`${filePath}#${componentName}`)) {\n return null;\n }\n visited.add(`${filePath}#${componentName}`);\n\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) {\n return null;\n }\n\n let program: TSESTree.Program;\n try {\n program = parseTsestreeSource(content);\n } catch {\n return null;\n }\n\n const rootJsx = findJsxReturnedByName(program, componentName);\n if (rootJsx === null) {\n return null;\n }\n\n const leaf = unwrapWrappers(rootJsx);\n if (leaf === null) {\n return null;\n }\n\n if (isDivLikeHost(leaf) && leaf.type === AST_NODE_TYPES.JSXElement) {\n const shellResult = pickContentShellInFile(filePath, program, leaf);\n if (shellResult.status === \"unresolved\") {\n return null;\n }\n const wrapsOutlet =\n elementContainsOutlet(leaf) || hostWrapsOutletOneHop(tree, filePath, program, leaf, sourceRoot, visited);\n return { kind: wrapsOutlet ? \"layout-shell\" : \"leaf-shell\", shell: shellResult.shell };\n }\n\n const childName = getJsxComponentName(leaf);\n if (childName === null || childName === \"Outlet\") {\n return null;\n }\n if (isDynamicComponent(program, childName)) {\n return null;\n }\n\n const importPath = resolveStaticLocalImport(tree, program, filePath, sourceRoot, childName);\n if (importPath === null) {\n return null;\n }\n\n // Preserve nested kind: a one-hop wrapper around an Outlet layout\n // (`Root` → `Shell` with Outlet) must stay `layout-shell` so shared layout\n // wins over clear leaves. Forcing `leaf-shell` here double-invents.\n return analyzeRouteComponent(tree, importPath, childName, sourceRoot, visited);\n};\n\nconst getRouterPropIdentifier = (element: TSESTree.JSXElement): string | null => {\n for (const attribute of element.openingElement.attributes) {\n if (attribute.type !== AST_NODE_TYPES.JSXAttribute) continue;\n if (attribute.name.type !== AST_NODE_TYPES.JSXIdentifier || attribute.name.name !== \"router\") continue;\n if (attribute.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) continue;\n if (attribute.value.expression.type === AST_NODE_TYPES.Identifier) {\n return attribute.value.expression.name;\n }\n }\n return null;\n};\n\nconst getVariableDeclaratorInit = (declarator: TSESTree.VariableDeclarator): TSESTree.Expression | null => {\n if (!(\"init\" in declarator)) {\n return null;\n }\n return declarator.init ?? null;\n};\n\n/**\n * Collects TanStack route factory bindings (`createRootRoute` / `createRoute` /\n * `createRootRouteWithContext`) with parent links from `getParentRoute`.\n * Arrow `component` wrappers have `componentName: null` (not guessed).\n */\nconst collectRouterRoutes = (program: TSESTree.Program): Array<RouterRoute> => {\n const coveredRanges = new Set<string>();\n const routes: Array<RouterRoute> = [];\n\n simpleTraverse(program, {\n enter: node => {\n if (node.type !== AST_NODE_TYPES.VariableDeclarator) return;\n if (node.id.type !== AST_NODE_TYPES.Identifier) return;\n const init = getVariableDeclaratorInit(node);\n if (init === null || init.type !== AST_NODE_TYPES.CallExpression) return;\n if (!isRouteFactoryCall(init)) return;\n const options = init.arguments[0];\n if (options?.type !== AST_NODE_TYPES.ObjectExpression) return;\n coveredRanges.add(`${init.range[0]}:${init.range[1]}`);\n routes.push({\n variableName: node.id.name,\n componentName: getComponentIdentifierFromOptions(options),\n parentVariableName: getParentRouteIdentifier(options),\n });\n },\n });\n\n simpleTraverse(program, {\n enter: node => {\n if (node.type !== AST_NODE_TYPES.CallExpression) return;\n if (!isRouteFactoryCall(node)) return;\n if (coveredRanges.has(`${node.range[0]}:${node.range[1]}`)) return;\n const options = node.arguments[0];\n if (options?.type !== AST_NODE_TYPES.ObjectExpression) return;\n routes.push({\n variableName: null,\n componentName: getComponentIdentifierFromOptions(options),\n parentVariableName: getParentRouteIdentifier(options),\n });\n },\n });\n\n return routes;\n};\n\nconst getParentRouteIdentifier = (options: TSESTree.ObjectExpression): string | null => {\n for (const property of options.properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n if (property.key.type !== AST_NODE_TYPES.Identifier || property.key.name !== \"getParentRoute\") continue;\n if (\n property.value.type !== AST_NODE_TYPES.ArrowFunctionExpression &&\n property.value.type !== AST_NODE_TYPES.FunctionExpression\n ) {\n continue;\n }\n if (property.value.body.type === AST_NODE_TYPES.Identifier) {\n return property.value.body.name;\n }\n if (property.value.body.type === AST_NODE_TYPES.BlockStatement) {\n for (const statement of property.value.body.body) {\n if (statement.type !== AST_NODE_TYPES.ReturnStatement || statement.argument === null) continue;\n const arg = unwrapParentheses(statement.argument);\n if (arg.type === AST_NODE_TYPES.Identifier) {\n return arg.name;\n }\n }\n }\n }\n return null;\n};\n\nconst collectAddChildrenIdentifiers = (program: TSESTree.Program): Array<string> => {\n const names: Array<string> = [];\n simpleTraverse(program, {\n enter: node => {\n if (node.type !== AST_NODE_TYPES.CallExpression) return;\n if (node.callee.type !== AST_NODE_TYPES.MemberExpression || node.callee.computed) return;\n if (node.callee.property.type !== AST_NODE_TYPES.Identifier) return;\n if (node.callee.property.name !== \"addChildren\") return;\n const arg = node.arguments[0];\n if (arg?.type !== AST_NODE_TYPES.ArrayExpression) return;\n for (const element of arg.elements) {\n if (element?.type === AST_NODE_TYPES.Identifier) {\n names.push(element.name);\n }\n }\n },\n });\n return names;\n};\n\nconst CONTENT_SPACE_TOKEN = \"p-content-space\";\n\nconst shellHasContentSpace = (shell: ResolvedContentShell): boolean =>\n splitClasses(shell.classnameValue).includes(CONTENT_SPACE_TOKEN);\n\n/**\n * Layout-wins is per route subtree: a layout covers only descendant leaves.\n * Already-migrated descendant leaves must not get a second inset on the layout.\n */\nconst selectShellsForInvent = (routes: ReadonlyArray<AnalyzedRoute>): Array<ResolvedContentShell> => {\n const byVariable = new Map<string, AnalyzedRoute>();\n for (const route of routes) {\n if (route.variableName !== null) {\n byVariable.set(route.variableName, route);\n }\n }\n\n const layouts = routes.filter(route => route.analysis?.kind === \"layout-shell\");\n const leaves = routes.filter(route => route.analysis?.kind === \"leaf-shell\");\n const coveredLeaves = new Set<AnalyzedRoute>();\n const selected: Array<ResolvedContentShell> = [];\n\n for (const layout of layouts) {\n if (layout.analysis?.kind !== \"layout-shell\") continue;\n const descendants = leaves.filter(leaf => isDescendantOf(leaf, layout, byVariable));\n const descendantsAlreadyMigrated = descendants.some(\n leaf => leaf.analysis !== null && shellHasContentSpace(leaf.analysis.shell)\n );\n if (descendantsAlreadyMigrated) {\n continue;\n }\n selected.push(layout.analysis.shell);\n for (const descendant of descendants) {\n coveredLeaves.add(descendant);\n }\n }\n\n for (const leaf of leaves) {\n if (coveredLeaves.has(leaf) || leaf.analysis?.kind !== \"leaf-shell\") continue;\n selected.push(leaf.analysis.shell);\n }\n\n return selected;\n};\n\nconst isDescendantOf = (\n leaf: AnalyzedRoute,\n layout: AnalyzedRoute,\n byVariable: Map<string, AnalyzedRoute>\n): boolean => {\n if (layout.variableName === null) return false;\n let current = leaf.parentVariableName;\n const seen = new Set<string>();\n while (current !== null && !seen.has(current)) {\n if (current === layout.variableName) return true;\n seen.add(current);\n current = byVariable.get(current)?.parentVariableName ?? null;\n }\n return false;\n};\n\nconst uniqueNames = (names: ReadonlyArray<string>): Array<string> => {\n const seen = new Set<string>();\n const result: Array<string> = [];\n for (const name of names) {\n if (seen.has(name)) continue;\n seen.add(name);\n result.push(name);\n }\n return result;\n};\n\nconst isRouteFactoryCall = (node: TSESTree.CallExpression): boolean => {\n const directName = getCalleeIdentifierName(node.callee);\n if (directName === \"createRootRoute\" || directName === \"createRoute\") {\n return true;\n }\n // createRootRouteWithContext<T>()({ ... })\n if (node.callee.type === AST_NODE_TYPES.CallExpression) {\n const innerName = getCalleeIdentifierName(node.callee.callee);\n return innerName === \"createRootRouteWithContext\";\n }\n return false;\n};\n\nconst getCalleeIdentifierName = (\n callee: TSESTree.Expression | TSESTree.Super | TSESTree.PrivateIdentifier\n): string | null => {\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n if (callee.type === AST_NODE_TYPES.TSInstantiationExpression) {\n return getCalleeIdentifierName(callee.expression);\n }\n return null;\n};\n\nconst getComponentIdentifierFromOptions = (options: TSESTree.ObjectExpression): string | null => {\n for (const property of options.properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n if (property.key.type !== AST_NODE_TYPES.Identifier || property.key.name !== \"component\") continue;\n if (property.value.type === AST_NODE_TYPES.Identifier) {\n return property.value.name;\n }\n }\n return null;\n};\n\nconst resolveComponentModulePath = (\n tree: Tree,\n program: TSESTree.Program,\n fromFilePath: string,\n sourceRoot: string,\n componentName: string\n): string | null => {\n const imported = resolveStaticLocalImport(tree, program, fromFilePath, sourceRoot, componentName);\n if (imported !== null) {\n return imported;\n }\n if (findJsxReturnedByName(program, componentName) !== null) {\n return fromFilePath;\n }\n return null;\n};\n\nconst elementContainsOutlet = (element: TSESTree.JSXElement | TSESTree.JSXFragment): boolean => {\n let found = false;\n simpleTraverse(element, {\n enter: node => {\n if (found) return;\n if (node.type !== AST_NODE_TYPES.JSXOpeningElement) return;\n const name = getJsxOpeningName(node.name);\n if (name === \"Outlet\") {\n found = true;\n }\n },\n });\n return found;\n};\n\n/**\n * True when a div-like shell's `<Outlet />` lives one custom-component hop\n * below (`<div><Main /></div>` where `Main` returns `<Outlet />`). Without this,\n * the ancestor is padded as a leaf alongside real route leaves.\n */\nconst hostWrapsOutletOneHop = (\n tree: Tree,\n filePath: string,\n program: TSESTree.Program,\n host: TSESTree.JSXElement,\n sourceRoot: string,\n visited: Set<string>\n): boolean => {\n for (const childName of collectCustomChildComponentNames(host)) {\n if (childName === \"Outlet\") {\n return true;\n }\n if (componentReturnsOutletOneHop(tree, filePath, program, childName, sourceRoot, visited)) {\n return true;\n }\n }\n return false;\n};\n\nconst collectCustomChildComponentNames = (host: TSESTree.JSXElement): Array<string> => {\n const names: Array<string> = [];\n for (const child of host.children) {\n if (child.type !== AST_NODE_TYPES.JSXElement) continue;\n const name = getJsxComponentName(child);\n if (name !== null) {\n names.push(name);\n }\n }\n return names;\n};\n\nconst componentReturnsOutletOneHop = (\n tree: Tree,\n fromFilePath: string,\n fromProgram: TSESTree.Program,\n componentName: string,\n sourceRoot: string,\n visited: Set<string>\n): boolean => {\n const visitKey = `${fromFilePath}#outlet-hop#${componentName}`;\n if (visited.has(visitKey)) {\n return false;\n }\n visited.add(visitKey);\n\n let program = fromProgram;\n if (findJsxReturnedByName(fromProgram, componentName) === null) {\n const importPath = resolveStaticLocalImport(tree, fromProgram, fromFilePath, sourceRoot, componentName);\n if (importPath === null) {\n return false;\n }\n const content = tree.read(importPath, \"utf-8\");\n if (content === null) {\n return false;\n }\n try {\n program = parseTsestreeSource(content);\n } catch {\n return false;\n }\n }\n\n const jsx = findJsxReturnedByName(program, componentName);\n if (jsx === null) {\n return false;\n }\n if (getJsxComponentName(jsx) === \"Outlet\") {\n return true;\n }\n return elementContainsOutlet(jsx);\n};\n\nconst dedupeShells = (shells: ReadonlyArray<ResolvedContentShell>): Array<ResolvedContentShell> => {\n const seen = new Set<string>();\n const result: Array<ResolvedContentShell> = [];\n for (const shell of shells) {\n const key = `${shell.filePath}:${shell.location.reportNode.range[0]}:${shell.location.reportNode.range[1]}`;\n if (seen.has(key)) continue;\n seen.add(key);\n result.push(shell);\n }\n return result;\n};\n\n/**\n * Finds the JSX element returned by the entry's primary component:\n * `singleSpaReact({ rootComponent })` when present, otherwise the first\n * exported function/const whose body returns JSX.\n */\nconst findRootJsxElement = (program: TSESTree.Program): TSESTree.JSXElement | TSESTree.JSXFragment | null => {\n const singleSpaRootName = findSingleSpaRootComponentName(program);\n if (singleSpaRootName !== null) {\n return findJsxReturnedByName(program, singleSpaRootName);\n }\n\n for (const statement of program.body) {\n const name = getExportedComponentName(statement);\n if (name === null) continue;\n const jsx = findJsxReturnedByName(program, name);\n if (jsx !== null) return jsx;\n }\n\n return null;\n};\n\nconst findSingleSpaRootComponentName = (program: TSESTree.Program): string | null => {\n let result: string | null = null;\n\n simpleTraverse(program, {\n enter: node => {\n if (result !== null) return;\n if (node.type !== AST_NODE_TYPES.CallExpression) return;\n if (!isCalleeNamed(node.callee, \"singleSpaReact\")) return;\n if (node.arguments[0]?.type !== AST_NODE_TYPES.ObjectExpression) return;\n\n for (const property of node.arguments[0].properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n if (property.key.type !== AST_NODE_TYPES.Identifier || property.key.name !== \"rootComponent\") continue;\n if (property.value.type === AST_NODE_TYPES.Identifier) {\n result = property.value.name;\n }\n }\n },\n });\n\n return result;\n};\n\nconst getExportedComponentName = (statement: TSESTree.ProgramStatement): string | null => {\n if (statement.type === AST_NODE_TYPES.ExportNamedDeclaration) {\n if (statement.declaration?.type === AST_NODE_TYPES.FunctionDeclaration) {\n return statement.declaration.id?.name ?? null;\n }\n if (statement.declaration?.type === AST_NODE_TYPES.VariableDeclaration) {\n const declarator = statement.declaration.declarations[0];\n if (declarator.id.type === AST_NODE_TYPES.Identifier) {\n return declarator.id.name;\n }\n }\n }\n if (statement.type === AST_NODE_TYPES.ExportDefaultDeclaration) {\n if (statement.declaration.type === AST_NODE_TYPES.Identifier) {\n return statement.declaration.name;\n }\n if (statement.declaration.type === AST_NODE_TYPES.FunctionDeclaration) {\n return statement.declaration.id?.name ?? null;\n }\n }\n return null;\n};\n\nconst findJsxReturnedByName = (\n program: TSESTree.Program,\n name: string\n): TSESTree.JSXElement | TSESTree.JSXFragment | null => {\n for (const statement of program.body) {\n const fn = matchNamedFunctionLike(statement, name);\n if (fn !== null) {\n return findReturnedJsx(fn);\n }\n }\n return null;\n};\n\nconst matchNamedFunctionLike = (\n statement: TSESTree.ProgramStatement,\n name: string\n): TSESTree.BlockStatement | TSESTree.Expression | null => {\n const decl =\n statement.type === AST_NODE_TYPES.ExportNamedDeclaration ||\n statement.type === AST_NODE_TYPES.ExportDefaultDeclaration\n ? statement.declaration\n : statement;\n\n if (decl === null) return null;\n\n if (decl.type === AST_NODE_TYPES.FunctionDeclaration && decl.id !== null && decl.id.name === name) {\n return decl.body;\n }\n\n if (decl.type === AST_NODE_TYPES.VariableDeclaration) {\n for (const declarator of decl.declarations) {\n if (declarator.id.type !== AST_NODE_TYPES.Identifier || declarator.id.name !== name) continue;\n const init = declarator.init;\n if (init === null) return null;\n if (init.type === AST_NODE_TYPES.ArrowFunctionExpression || init.type === AST_NODE_TYPES.FunctionExpression) {\n return init.body;\n }\n }\n }\n\n if (statement.type === AST_NODE_TYPES.FunctionDeclaration && statement.id.name === name) {\n return statement.body;\n }\n\n return null;\n};\n\nconst findReturnedJsx = (\n body: TSESTree.BlockStatement | TSESTree.Expression\n): TSESTree.JSXElement | TSESTree.JSXFragment | null => {\n if (body.type === AST_NODE_TYPES.JSXElement || body.type === AST_NODE_TYPES.JSXFragment) {\n return body;\n }\n if (body.type === AST_NODE_TYPES.BlockStatement) {\n for (const statement of body.body) {\n if (statement.type !== AST_NODE_TYPES.ReturnStatement || statement.argument === null) continue;\n const arg = unwrapParentheses(statement.argument);\n if (arg.type === AST_NODE_TYPES.JSXElement || arg.type === AST_NODE_TYPES.JSXFragment) {\n return arg;\n }\n }\n }\n return null;\n};\n\nconst unwrapParentheses = (expression: TSESTree.Expression): TSESTree.Expression => {\n let current = expression;\n while (current.type === AST_NODE_TYPES.TSAsExpression || current.type === AST_NODE_TYPES.TSSatisfiesExpression) {\n current = current.expression;\n }\n return current;\n};\n\n/**\n * Skips known provider / Suspense / fragment wrappers down to the first\n * meaningful child (host element or custom component).\n */\nconst unwrapWrappers = (\n node: TSESTree.JSXElement | TSESTree.JSXFragment\n): TSESTree.JSXElement | TSESTree.JSXFragment | null => {\n let current: TSESTree.JSXElement | TSESTree.JSXFragment = node;\n\n for (;;) {\n if (current.type === AST_NODE_TYPES.JSXFragment) {\n const child = firstJsxChild(current.children);\n if (child === null) return null;\n current = child;\n continue;\n }\n\n const name = getJsxComponentName(current);\n if (name !== null && isKnownWrapperName(name)) {\n const child = firstJsxChild(current.children);\n if (child === null) return null;\n current = child;\n continue;\n }\n\n return current;\n }\n};\n\nconst firstJsxChild = (\n children: ReadonlyArray<TSESTree.JSXChild>\n): TSESTree.JSXElement | TSESTree.JSXFragment | null => {\n for (const child of children) {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return child;\n }\n }\n return null;\n};\n\nconst isDivLikeHost = (element: TSESTree.JSXElement | TSESTree.JSXFragment): boolean => {\n if (element.type !== AST_NODE_TYPES.JSXElement) return false;\n const name = getJsxOpeningName(element.openingElement.name);\n return name !== null && DIV_LIKE_ELEMENTS.has(name);\n};\n\nconst getJsxComponentName = (element: TSESTree.JSXElement | TSESTree.JSXFragment): string | null => {\n if (element.type !== AST_NODE_TYPES.JSXElement) return null;\n const name = getJsxOpeningName(element.openingElement.name);\n if (name === null) return null;\n if (DIV_LIKE_ELEMENTS.has(name)) return null;\n if (/^[a-z]/.test(name)) return null;\n return name;\n};\n\nconst getJsxOpeningName = (name: TSESTree.JSXTagNameExpression): string | null => {\n if (name.type === AST_NODE_TYPES.JSXIdentifier) return name.name;\n return null;\n};\n\n/**\n * Confidence rule for this phase: a single editable content-region classname\n * host that itself owns scrollable overflow (`overflow-auto` / `scroll` /\n * `overlay`, including axis-prefixed forms). Clipping overflow (`hidden` /\n * `clip`), a scrolling descendant, or a header-ish child (`PageHeader` /\n * `Topbar` / `Header`) make the host unresolved — those cases go to the\n * unresolved-surface report for a human to place the inset.\n *\n * Classnames must be bound to the host's `className`/`class` attribute (literal\n * on the attribute, direct Tailwind call in the attribute, or the local\n * binding of that attribute's identifier/callee). Never invent from unrelated\n * file-wide classname locations.\n */\nconst pickContentShellInFile = (\n filePath: string,\n program: TSESTree.Program,\n host: TSESTree.JSXElement\n): ResolveContentShellResult => {\n const hostClassnames = collectEditableClassnamesForHost(program, host);\n if (hostClassnames.length === 0) {\n return unresolvedShell(\"no-editable-classname\", filePath);\n }\n\n if (hostClassnames.some(classname => classListHasClippingOverflow(splitClasses(classname.value)))) {\n return unresolvedShell(\"clipping-overflow-on-host\", filePath);\n }\n\n const candidates = hostClassnames.filter(isContentShellClassname);\n if (candidates.length === 0) {\n return unresolvedShell(\"no-overflow-on-host\", filePath);\n }\n if (candidates.length > 1) {\n return unresolvedShell(\"multiple-overflow-candidates\", filePath);\n }\n\n if (hostRendersHeader(host)) {\n return unresolvedShell(\"header-on-shell\", filePath);\n }\n if (descendantOwnsScroll(program, host)) {\n return unresolvedShell(\"descendant-owns-scroll\", filePath);\n }\n\n const location = candidates[0];\n if (location === undefined) {\n return unresolvedShell(\"unclear-graph\", filePath);\n }\n return {\n status: \"resolved\",\n shell: {\n filePath,\n classnameValue: location.value,\n combinedClassnameValue: hostClassnames.map(hostLocation => hostLocation.value).join(\" \"),\n location,\n },\n };\n};\n\nconst collectEditableClassnamesForHost = (\n program: TSESTree.Program,\n host: TSESTree.JSXElement\n): Array<ClassnameLocation> => {\n const attribute = host.openingElement.attributes.find(\n (attr): attr is TSESTree.JSXAttribute =>\n attr.type === AST_NODE_TYPES.JSXAttribute &&\n attr.name.type === AST_NODE_TYPES.JSXIdentifier &&\n (attr.name.name === \"className\" || attr.name.name === \"class\")\n );\n if (attribute === undefined) return [];\n\n // Direct literal classnames on the attribute.\n const fromAttribute = findClassnameLocations(program).filter(location => {\n if (location.context.type !== \"jsx-attribute\") return false;\n return location.reportNode.range[0] >= attribute.range[0] && location.reportNode.range[1] <= attribute.range[1];\n });\n if (fromAttribute.length > 0) return fromAttribute;\n\n const value = attribute.value;\n if (value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return [];\n const expression = value.expression;\n\n if (expression.type === AST_NODE_TYPES.CallExpression) {\n return collectClassnamesBoundToCallExpression(program, expression);\n }\n if (expression.type === AST_NODE_TYPES.Identifier) {\n return collectClassnamesBoundToIdentifier(program, expression.name);\n }\n return [];\n};\n\n/**\n * `className={cva(\"...\")}` — locations inside this call only.\n * `className={layout()}` — locations inside the local binding of `layout` only.\n */\nconst collectClassnamesBoundToCallExpression = (\n program: TSESTree.Program,\n callExpression: TSESTree.CallExpression\n): Array<ClassnameLocation> => {\n if (callExpression.callee.type !== AST_NODE_TYPES.Identifier) {\n return [];\n }\n\n const calleeName = callExpression.callee.name;\n if (isTailwindFunction(calleeName)) {\n return findClassnameLocations(program).filter(\n location =>\n location.reportNode.range[0] >= callExpression.range[0] &&\n location.reportNode.range[1] <= callExpression.range[1]\n );\n }\n\n return collectClassnamesBoundToIdentifier(program, calleeName);\n};\n\nconst collectClassnamesBoundToIdentifier = (program: TSESTree.Program, name: string): Array<ClassnameLocation> => {\n const bindingRange = findLocalBindingInitializerRange(program, name);\n if (bindingRange === null) {\n return [];\n }\n\n return findClassnameLocations(program).filter(\n location => location.reportNode.range[0] >= bindingRange[0] && location.reportNode.range[1] <= bindingRange[1]\n );\n};\n\nconst findLocalBindingInitializerRange = (program: TSESTree.Program, name: string): TSESTree.Range | null => {\n let result: TSESTree.Range | null = null;\n\n simpleTraverse(program, {\n enter: node => {\n if (result !== null) return;\n if (node.type !== AST_NODE_TYPES.VariableDeclarator) return;\n if (node.id.type !== AST_NODE_TYPES.Identifier || node.id.name !== name) return;\n if (node.init === null) return;\n result = node.init.range;\n },\n });\n\n return result;\n};\n\nconst SCROLLABLE_OVERFLOW = /(^|:)overflow-(x-|y-)?(auto|scroll|overlay)$/;\nconst CLIPPING_OVERFLOW = /(^|:)overflow-(x-|y-)?(hidden|clip)$/;\n\nconst classListHasScrollableOverflow = (classes: ReadonlyArray<string>): boolean =>\n classes.some(cls => SCROLLABLE_OVERFLOW.test(cls));\n\nconst classListHasClippingOverflow = (classes: ReadonlyArray<string>): boolean =>\n classes.some(cls => CLIPPING_OVERFLOW.test(cls));\n\nconst isContentShellClassname = (location: ClassnameLocation): boolean => {\n const classes = splitClasses(location.value);\n if (classListHasClippingOverflow(classes)) return false;\n return classListHasScrollableOverflow(classes);\n};\n\nconst HEADER_ISH_NAMES: ReadonlySet<string> = new Set([\"PageHeader\", \"Topbar\", \"Header\"]);\n\nconst hostRendersHeader = (host: TSESTree.JSXElement): boolean =>\n jsxElementsUnder(host).some(element => {\n const name = getJsxOpeningName(element.openingElement.name);\n return name !== null && HEADER_ISH_NAMES.has(name);\n });\n\nconst descendantOwnsScroll = (program: TSESTree.Program, host: TSESTree.JSXElement): boolean =>\n jsxElementsUnder(host).some(element =>\n collectEditableClassnamesForHost(program, element).some(isContentShellClassname)\n );\n\nconst jsxElementsUnder = (host: TSESTree.JSXElement): Array<TSESTree.JSXElement> => {\n const found: Array<TSESTree.JSXElement> = [];\n const visit = (children: ReadonlyArray<TSESTree.JSXChild>): void => {\n for (const child of children) {\n if (child.type === AST_NODE_TYPES.JSXElement) {\n found.push(child);\n visit(child.children);\n } else if (child.type === AST_NODE_TYPES.JSXFragment) {\n visit(child.children);\n }\n }\n };\n visit(host.children);\n return found;\n};\n\nconst isDynamicComponent = (program: TSESTree.Program, componentName: string): boolean => {\n let isDynamic = false;\n\n simpleTraverse(program, {\n enter: node => {\n if (isDynamic) return;\n if (node.type !== AST_NODE_TYPES.VariableDeclarator) return;\n if (node.id.type !== AST_NODE_TYPES.Identifier || node.id.name !== componentName) return;\n if (node.init === null) return;\n if (containsDynamicImport(node.init)) {\n isDynamic = true;\n }\n },\n });\n\n return isDynamic;\n};\n\nconst containsDynamicImport = (node: TSESTree.Node): boolean => {\n let found = false;\n simpleTraverse(node, {\n enter: child => {\n if (found) return;\n if (child.type === AST_NODE_TYPES.ImportExpression) {\n found = true;\n }\n },\n });\n return found;\n};\n\n/**\n * Resolves a component name to a static relative/local import under\n * `sourceRoot`. Returns null for external packages or missing bindings.\n */\nconst resolveStaticLocalImport = (\n tree: Tree,\n program: TSESTree.Program,\n fromFilePath: string,\n sourceRoot: string,\n componentName: string\n): string | null => {\n for (const statement of program.body) {\n if (statement.type !== AST_NODE_TYPES.ImportDeclaration) continue;\n const specifier = statement.source.value;\n if (typeof specifier !== \"string\") continue;\n const bindsComponent = statement.specifiers.some(spec => {\n if (spec.type === AST_NODE_TYPES.ImportDefaultSpecifier) {\n return spec.local.name === componentName;\n }\n if (spec.type === AST_NODE_TYPES.ImportSpecifier) {\n return spec.local.name === componentName;\n }\n return false;\n });\n if (!bindsComponent) continue;\n\n if (!(specifier.startsWith(\"./\") || specifier.startsWith(\"../\"))) {\n return null;\n }\n\n const fromDir = path.posix.dirname(fromFilePath);\n const resolvedWithoutExt = path.posix.normalize(path.posix.join(fromDir, specifier));\n const candidates = [\n resolvedWithoutExt,\n `${resolvedWithoutExt}.tsx`,\n `${resolvedWithoutExt}.ts`,\n `${resolvedWithoutExt}/index.tsx`,\n `${resolvedWithoutExt}/index.ts`,\n ];\n\n for (const candidate of candidates) {\n if (candidate === fromFilePath) continue;\n if (!candidate.startsWith(`${sourceRoot}/`) && candidate !== sourceRoot) continue;\n if (!(candidate.endsWith(\".tsx\") || candidate.endsWith(\".ts\"))) continue;\n if (tree.exists(candidate)) {\n return candidate;\n }\n }\n }\n\n // Local const binding (e.g. LazyPage) without an import — not followable as a\n // static local module.\n return null;\n};\n\nconst isCalleeNamed = (callee: TSESTree.CallExpression[\"callee\"], name: string): boolean => {\n return callee.type === AST_NODE_TYPES.Identifier && callee.name === name;\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewrite-page-content.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/rewrite-page-content.ts"],"names":[],"mappings":";;AAmCA,gDAYC;AA9CD,wEAAiF;AACjF,0EAAoF;AAGpF,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAC5C,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAC9C,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAE5C;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAA8B;IACtD,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,kBAAkB,CAAC,IAAU,EAAE,SAA4B;IACzE,OAAO,IAAA,0DAAkC,EACvC,IAAI,EACJ,SAAS,CAAC,UAAU,EACpB,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EACjD,KAAK,CAAC,EAAE;QACN,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAA,kCAAY,EAAC,KAAK,CAAC,CAAC;YACvD,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,GAAG,mBAAmB,IAAI,mBAAmB,EAAE,CAAC;QACpD,OAAO,IAAA,uCAAiB,EAAC,KAAK,EAAE,oBAAoB,EAAE,WAAW,CAAC,CAAC;IACrE,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Tree } from \"@nx/devkit\";\nimport { replaceClassToken, splitClasses } from \"@trackunit/css-classname-utils\";\nimport { transformClassnamesUnderSourceRoot } from \"../utils/classname-ast-rewrite\";\nimport type { ResolvedExtension } from \"../utils/resolve-extension-types\";\n\nconst PAGE_CONTENT_PATTERN = \"page-content\";\nconst CONTENT_SPACE_TOKEN = \"p-content-space\";\nconst OVERFLOW_AUTO_TOKEN = \"overflow-auto\";\n\n/**\n * True when `token` is already present as a whole class token, including when\n * wrapped in Tailwind variant prefixes (e.g. `xl:overflow-hidden`).\n */\nfunction hasOverflowToken(classes: ReadonlyArray<string>): boolean {\n return classes.some(cls => /(^|:)overflow-/.test(cls));\n}\n\n/**\n * Rewrites the legacy `page-content` Tailwind class to\n * `overflow-auto p-content-space` across every rewritable file under a\n * single resolved extension's `sourceRoot`.\n *\n * When the classname already declares its own `overflow-*` token, only\n * `p-content-space` is inserted — emitting a second `overflow-auto` would be\n * dead (or, when an identical `overflow-auto` is already present, a\n * duplicate). Scroll ownership stays with the element's existing overflow\n * declaration.\n *\n * Scoped to one extension per call — the caller (the orchestrator) loops\n * over every Asset Home/Site Home/Admin extension.\n *\n * Only performs the `page-content` classname rewrite: it does not touch\n * `pb-*`/`pb-responsive-space` classes or produce a report, both of which are\n * separate migration steps.\n */\nexport function rewritePageContent(tree: Tree, extension: ResolvedExtension): { filesChanged: Array<string> } {\n return transformClassnamesUnderSourceRoot(\n tree,\n extension.sourceRoot,\n content => content.includes(PAGE_CONTENT_PATTERN),\n value => {\n const replacement = hasOverflowToken(splitClasses(value))\n ? CONTENT_SPACE_TOKEN\n : `${OVERFLOW_AUTO_TOKEN} ${CONTENT_SPACE_TOKEN}`;\n return replaceClassToken(value, PAGE_CONTENT_PATTERN, replacement);\n }\n );\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-skip-reason.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/p-content-space-codemod/shell-skip-reason.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AA4BH,MAAM,QAAQ,GAAwC;IACpD,eAAe,EAAE,qDAAqD;IACtE,cAAc,EAAE,8DAA8D;IAC9E,aAAa,EAAE,yDAAyD;IACxE,eAAe,EAAE,mEAAmE;IACpF,KAAK,EAAE,uEAAuE;IAC9E,mBAAmB,EAAE,0EAA0E;IAC/F,qBAAqB,EAAE,gEAAgE;IACvF,kBAAkB,EAAE,sEAAsE;IAC1F,wBAAwB,EAAE,8DAA8D;IACxF,gCAAgC,EAC9B,+HAA+H;IACjI,6BAA6B,EAC3B,uFAAuF;IACzF,uBAAuB,EAAE,0FAA0F;IACnH,qBAAqB,EACnB,qIAAqI;IACvI,8BAA8B,EAAE,0EAA0E;IAC1G,iBAAiB,EAAE,4FAA4F;IAC/G,wBAAwB,EAAE,qFAAqF;IAC/G,2BAA2B,EACzB,kGAAkG;IACpG,eAAe,EAAE,sEAAsE;CACxF,CAAC;AAEF;;;;;;GAMG;AACI,MAAM,eAAe,GAAG,CAAC,IAAyB,EAAE,MAAe,EAAmB,EAAE,CAAC,CAAC;IAC/F,IAAI;IACJ,OAAO,EAAE,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG;CACxG,CAAC,CAAC;AAHU,QAAA,eAAe,mBAGzB","sourcesContent":["/**\n * Why invent/resolve declined to pick an ASA content shell. Surfaced in\n * migration console output and UnresolvedSurfaceReport so humans (and\n * third parties) can plan manual `p-content-space` placement.\n */\n\nexport type ShellSkipReasonCode =\n | \"entry-missing\"\n | \"parse-failed\"\n | \"no-root-jsx\"\n | \"empty-wrapper\"\n | \"cycle\"\n | \"dynamic-component\"\n | \"unresolvable-import\"\n | \"non-host-element\"\n | \"router-prop-unresolved\"\n | \"router-inline-arrow-components\"\n | \"router-no-analysable-leaves\"\n | \"no-editable-classname\"\n | \"no-overflow-on-host\"\n | \"multiple-overflow-candidates\"\n | \"header-on-shell\"\n | \"descendant-owns-scroll\"\n | \"clipping-overflow-on-host\"\n | \"unclear-graph\";\n\nexport type ShellSkipReason = {\n readonly code: ShellSkipReasonCode;\n /** Human-readable explanation (safe to print to the console). */\n readonly message: string;\n};\n\nconst MESSAGES: Record<ShellSkipReasonCode, string> = {\n \"entry-missing\": \"extension entry file was not found under sourceRoot\",\n \"parse-failed\": \"extension entry/source could not be parsed as TypeScript/TSX\",\n \"no-root-jsx\": \"could not find a root JSX return in the entry component\",\n \"empty-wrapper\": \"provider/Suspense/Fragment wrappers had no JSX child to walk into\",\n cycle: \"component graph walked into a cycle while resolving the content shell\",\n \"dynamic-component\": \"content shell is behind a dynamic import / lazy component (not followed)\",\n \"unresolvable-import\": \"could not resolve a static local import for the host component\",\n \"non-host-element\": \"leaf JSX is not a div/main/section with an inventable className host\",\n \"router-prop-unresolved\": \"RouterProvider router={...} prop was not a simple identifier\",\n \"router-inline-arrow-components\":\n \"TanStack routes use inline arrow `component: () => <...>` instead of a named component identifier — invent cannot follow them\",\n \"router-no-analysable-leaves\":\n \"router graph had no analysable named route leaves with a clear overflow content shell\",\n \"no-editable-classname\": \"div/main/section host has no editable className/class (literal or bound Tailwind helper)\",\n \"no-overflow-on-host\":\n \"host has a className but does not itself own scrollable overflow (overflow-auto/scroll/overlay) — invent only pads the scroll owner\",\n \"multiple-overflow-candidates\": \"host has more than one inventable overflow classname binding (ambiguous)\",\n \"header-on-shell\": \"host also renders PageHeader/Topbar/Header — pad the body below the header, not this shell\",\n \"descendant-owns-scroll\": \"a descendant owns overflow scrolling — pad that scroll owner, not the outer wrapper\",\n \"clipping-overflow-on-host\":\n \"host uses overflow-hidden/clip (full-bleed / clipping shell) — not inventable as a content inset\",\n \"unclear-graph\": \"content-shell graph was unclear; invent refused to guess a first-div\",\n};\n\n/**\n * Builds a structured skip reason for invent/resolve console + report output.\n *\n * @param code - Stable skip-reason code from the inventable-shell contract\n * @param detail - Optional path / leaf list / host name appended in parentheses\n * @returns {ShellSkipReason} Structured reason with a human-readable message\n */\nexport const shellSkipReason = (code: ShellSkipReasonCode, detail?: string): ShellSkipReason => ({\n code,\n message: detail === undefined || detail.length === 0 ? MESSAGES[code] : `${MESSAGES[code]} (${detail})`,\n});\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classname-ast-rewrite.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/utils/classname-ast-rewrite.ts"],"names":[],"mappings":"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","sourcesContent":["import { visitNotIgnoredFiles, type Tree } from \"@nx/devkit\";\nimport {\n findClassnameStringsInAttribute,\n findClassnameStringsInCall,\n findClassnameStringsInVariable,\n quoteString,\n type ClassnameLocation,\n} from \"@trackunit/css-classname-utils\";\nimport { AST_NODE_TYPES, type TSESTree } from \"@typescript-eslint/types\";\nimport { parse, simpleTraverse } from \"@typescript-eslint/typescript-estree\";\n\n/**\n * Shared TSESTree parsing/traversal/splice helpers for classname-rewriting Nx\n * migrations (the `p-content-space-codemod` and any future codemod that needs\n * to detect and rewrite Tailwind classnames across a Tree).\n *\n * `@trackunit/css-classname-utils`'s detection helpers\n * (`findClassnameStringsInAttribute`/`InCall`/`InVariable`) expect TSESTree AST\n * nodes, which today only ESLint's parser produces in this repo. Nx migrations\n * run outside of ESLint, so this module wraps\n * `@typescript-eslint/typescript-estree`'s `parse` (the same underlying parser\n * `@typescript-eslint/parser` delegates to) to turn a raw source string into an\n * equivalent TSESTree `Program`, then re-splices edits directly against the\n * original source string by AST node range (mirroring the range-splice\n * approach `insertAttributeIntoOpeningTag` in\n * `libs/react/components/migrations/utils/jsx-utils.ts` uses for the\n * TypeScript-compiler-API case).\n */\n\n/**\n * Parses raw TypeScript/TSX source into a TSESTree `Program` AST.\n *\n * `jsx: true` is always passed (harmless for plain `.ts` files) so callers\n * don't need to branch on file extension before parsing.\n */\nexport function parseTsestreeSource(content: string): TSESTree.Program {\n return parse(content, { jsx: true, loc: true, range: true });\n}\n\n/**\n * Finds every classname string location in a parsed source: JSX\n * `className`/`class` attributes, Tailwind-function calls (`cva`, `cn`,\n * `clsx`, etc. — see `TAILWIND_FUNCTIONS`), and\n * `*Class`/`*ClassName`/`*Classes`-suffixed variable declarators.\n *\n * Walks the AST with `simpleTraverse` (shipped by\n * `@typescript-eslint/typescript-estree`) instead of a hand-rolled\n * visitor-keys walker, since it already knows every node type's visitor keys\n * for the resolved parser version.\n */\nexport function findClassnameLocations(program: TSESTree.Program): Array<ClassnameLocation> {\n const locations: Array<ClassnameLocation> = [];\n\n simpleTraverse(program, {\n enter: node => {\n if (node.type === AST_NODE_TYPES.JSXAttribute) {\n locations.push(...findClassnameStringsInAttribute(node));\n } else if (node.type === AST_NODE_TYPES.CallExpression) {\n locations.push(...findClassnameStringsInCall(node));\n } else if (node.type === AST_NODE_TYPES.VariableDeclarator) {\n locations.push(...findClassnameStringsInVariable(node));\n }\n },\n });\n\n return locations;\n}\n\n/** A single range-based text splice against the original source string. */\nexport type ClassnameEdit = {\n range: TSESTree.Range;\n text: string;\n};\n\n/**\n * Builds the edit(s) needed to apply `transform` to a `ClassnameLocation`'s\n * `fixNode`, splicing by the node's own `.range` against the original source\n * (there is no ESLint `SourceCode`/fixer available outside of rule\n * execution).\n *\n * - `Literal`: one edit replacing the whole quoted literal, preserving the\n * original quote style via `quoteString`.\n * - `TemplateLiteral`: one edit per quasi whose raw text changes, splicing\n * only the text between the surrounding backtick/`${`/`}` delimiters so the\n * template's interpolated expressions are left untouched.\n *\n * Returns an empty array when `transform` doesn't change the value, so\n * callers can cheaply detect \"no-op\" locations.\n *\n * Prefer {@link buildEditsForLocation} when the caller has a full\n * `ClassnameLocation` — that path can drop an emptied JSX `className`\n * attribute entirely instead of leaving `className=\"\"`.\n */\nexport function buildClassnameEdits(\n fixNode: ClassnameLocation[\"fixNode\"],\n transform: (value: string) => string\n): Array<ClassnameEdit> {\n if (fixNode.type === AST_NODE_TYPES.Literal) {\n if (typeof fixNode.value !== \"string\") return [];\n const newValue = transform(fixNode.value);\n if (newValue === fixNode.value) return [];\n return [{ range: fixNode.range, text: quoteString(newValue, fixNode) }];\n }\n\n const edits: Array<ClassnameEdit> = [];\n for (const quasi of fixNode.quasis) {\n const newRaw = transform(quasi.value.raw);\n if (newRaw === quasi.value.raw) continue;\n const start = quasi.range[0] + 1;\n const end = quasi.range[1] - (quasi.tail ? 1 : 2);\n edits.push({ range: [start, end], text: newRaw });\n }\n return edits;\n}\n\n/**\n * Like {@link buildClassnameEdits}, but when a JSX `className`/`class`\n * attribute's token list becomes empty, removes the whole attribute\n * (including a single run of preceding horizontal whitespace) instead of\n * writing `className=\"\"`.\n *\n * Non-JSX locations (cva/cn/clsx calls, `*ClassName` variables) still fall\n * through to an empty-string literal — deleting those would require\n * statement-level surgery we deliberately do not attempt here.\n */\nexport function buildEditsForLocation(\n location: ClassnameLocation,\n transform: (value: string) => string,\n sourceContent: string\n): Array<ClassnameEdit> {\n const { fixNode, context, reportNode } = location;\n\n if (\n context.type === \"jsx-attribute\" &&\n reportNode.type === AST_NODE_TYPES.JSXAttribute &&\n fixNode.type === AST_NODE_TYPES.Literal &&\n typeof fixNode.value === \"string\"\n ) {\n const newValue = transform(fixNode.value);\n if (newValue === fixNode.value) return [];\n if (newValue === \"\") {\n return [buildJsxAttributeRemovalEdit(reportNode, sourceContent)];\n }\n return [{ range: fixNode.range, text: quoteString(newValue, fixNode) }];\n }\n\n return buildClassnameEdits(fixNode, transform);\n}\n\n/**\n * Removes a JSX attribute, swallowing the horizontal whitespace immediately\n * before it so `<div className=\"x\">` becomes `<div>` rather than `<div >`.\n */\nfunction buildJsxAttributeRemovalEdit(attribute: TSESTree.JSXAttribute, sourceContent: string): ClassnameEdit {\n let start = attribute.range[0];\n while (start > 0 && /[ \\t]/.test(sourceContent[start - 1] ?? \"\")) {\n start -= 1;\n }\n return { range: [start, attribute.range[1]], text: \"\" };\n}\n\n/**\n * Applies a batch of range-based edits to `content`, splicing in\n * reverse-offset order so that an earlier edit's range is never invalidated\n * by one applied after it.\n */\nexport function applyEdits(content: string, edits: ReadonlyArray<ClassnameEdit>): string {\n const byDescendingStart = [...edits].sort((a, b) => b.range[0] - a.range[0]);\n\n let result = content;\n for (const edit of byDescendingStart) {\n const [start, end] = edit.range;\n result = result.slice(0, start) + edit.text + result.slice(end);\n }\n return result;\n}\n\nconst REWRITABLE_EXTENSIONS: Array<string> = [\".ts\", \".tsx\"];\n\n/**\n * Manifest files must never be mutated by a classname-rewriting migration\n * (a hard Success Criterion of GLU-1570). No in-repo extension currently\n * declares a `sourceRoot` that overlaps its own manifest file, but this\n * filename guard is defense-in-depth so that invariant doesn't depend\n * entirely on that data convention holding forever.\n */\nconst MANIFEST_FILENAME_PATTERN = /(^|\\/)(iris-app-manifest|extension-manifest)\\.ts$/;\n\n/**\n * `true` for `.ts`/`.tsx` files a classname-rewriting migration is allowed\n * to read/write — excludes `iris-app-manifest.ts`/`extension-manifest.ts`\n * files. Shared by every transform/report module in this codemod so the\n * file-extension allowlist and manifest exclusion live in exactly one place.\n */\nexport const isRewritableFile = (filePath: string): boolean =>\n REWRITABLE_EXTENSIONS.some(ext => filePath.endsWith(ext)) && !MANIFEST_FILENAME_PATTERN.test(filePath);\n\n/**\n * Walks every rewritable file under `sourceRoot`, and for files passing the\n * cheap `shouldConsider` substring pre-check, parses them, finds every\n * classname location, applies `transform` to each, and writes back any file\n * that actually changed.\n *\n * Shared by `rewritePageContent` and `removeRedundantPadding` so the\n * walk → pre-filter → parse → find → edit → write skeleton lives in exactly\n * one place instead of being duplicated per transform.\n */\nexport function transformClassnamesUnderSourceRoot(\n tree: Tree,\n sourceRoot: string,\n shouldConsider: (content: string) => boolean,\n transform: (value: string) => string\n): { filesChanged: Array<string> } {\n const filesChanged: Array<string> = [];\n\n visitNotIgnoredFiles(tree, sourceRoot, filePath => {\n if (!isRewritableFile(filePath)) return;\n\n const content = tree.read(filePath, \"utf-8\");\n if (content === null || !shouldConsider(content)) return;\n\n const program = parseTsestreeSource(content);\n const locations = findClassnameLocations(program);\n const edits = locations.flatMap(location => buildEditsForLocation(location, transform, content));\n if (edits.length === 0) return;\n\n tree.write(filePath, applyEdits(content, edits));\n filesChanged.push(filePath);\n });\n\n return { filesChanged };\n}\n\n/**\n * Read-only walk of every rewritable file under `sourceRoot`, invoking\n * `visitor` with each file's path and content. Never writes. Shared by\n * `findUnresolvedSurface`'s detection pass, which only needs to inspect\n * content, not rewrite it.\n */\nexport function visitRewritableFiles(\n tree: Tree,\n sourceRoot: string,\n visitor: (filePath: string, content: string) => void\n): void {\n visitNotIgnoredFiles(tree, sourceRoot, filePath => {\n if (!isRewritableFile(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n visitor(filePath, content);\n });\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-extension-types.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/migrations/utils/resolve-extension-types.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, visitNotIgnoredFiles, type Tree } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\n\nexport type ResolvedExtension = {\n /** The extension manifest's `id` field. */\n id: string;\n /** SCREAMING_SNAKE extension type discriminator, e.g. \"ADMIN_EXTENSION\". */\n type: string;\n /** Repo-relative source root for the extension, e.g. \"libs/administration/api-keys/src\". */\n sourceRoot: string;\n /** Repo-relative path to the resolved `extension-manifest.ts` file. */\n extensionManifestPath: string;\n /**\n * The extension manifest's entry component file, e.g. \"index.tsx\".\n * Optional so hand-written fixtures/tests don't need to set it; when\n * produced by `resolveExtensionTypes` it is always populated, defaulting\n * to `\"index.tsx\"` per `AbstractExtensionManifest.main`'s own documented\n * default when the manifest doesn't set it explicitly.\n */\n main?: string;\n /** App names (`apps/<name>`) that import this extension. Lets callers verify dedup. */\n ownerApps: Array<string>;\n};\n\nexport type UnresolvedExtensionImport = {\n /** The app (`apps/<name>`) that references the unresolvable specifier. */\n app: string;\n /** The module specifier that could not be resolved via `tsconfig.base.json` paths. */\n specifier: string;\n};\n\nexport type ResolveExtensionTypesResult = {\n resolved: Array<ResolvedExtension>;\n /**\n * Extensions referenced by an app's `extensions` array whose import\n * specifier could not be resolved to a file via `tsconfig.base.json`'s\n * `compilerOptions.paths`. Surfaced here instead of thrown, so a single\n * unresolvable/renamed package doesn't abort the whole migration.\n */\n unresolved: Array<UnresolvedExtensionImport>;\n};\n\nconst APPS_MANIFEST_PATTERN = /^apps\\/([^/]+)\\/iris-app-manifest\\.ts$/;\nconst DEFAULT_ENTRY_COMPONENT_FILE = \"index.tsx\";\n\n/**\n * Statically resolves every `apps/*\\/iris-app-manifest.ts`'s declared\n * `extensions` to a concrete `type` + `sourceRoot`, deduping extensions\n * shared by multiple apps into a single entry.\n *\n * Uses the TypeScript compiler API against the Nx `Tree` (not `fs`/dynamic\n * `import()`), so uncommitted edits held only in the Tree are seen and the\n * migration stays deterministic.\n */\nexport function resolveExtensionTypes(tree: Tree): ResolveExtensionTypesResult {\n const tsconfigPaths = readTsconfigPaths(tree);\n const resolvedByPath = new Map<string, ResolvedExtension>();\n const unresolved: Array<UnresolvedExtensionImport> = [];\n\n visitNotIgnoredFiles(tree, \"apps\", filePath => {\n const match = APPS_MANIFEST_PATTERN.exec(filePath);\n if (match === null) return;\n const appName = match[1];\n if (appName === undefined) return;\n\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const manifestObject = resolveDefaultExportObjectLiteral(sourceFile);\n if (manifestObject === null) return;\n\n const extensionIdentifiers = getExtensionIdentifiers(manifestObject, filePath);\n if (extensionIdentifiers.length === 0) return;\n\n const importSpecifiersByLocalName = getImportSpecifiersByLocalName(sourceFile);\n\n for (const identifierName of extensionIdentifiers) {\n const specifier = importSpecifiersByLocalName.get(identifierName);\n if (specifier === undefined) {\n logger.warn(\n `[resolve-extension-types] Could not find an import for \"${identifierName}\" referenced in ${filePath}'s extensions array.`\n );\n continue;\n }\n\n const extensionManifestPath = tsconfigPaths.get(specifier);\n if (extensionManifestPath === undefined) {\n logger.warn(\n `[resolve-extension-types] Could not resolve module specifier \"${specifier}\" (from ${filePath}) via tsconfig.base.json paths.`\n );\n unresolved.push({ app: appName, specifier });\n continue;\n }\n\n const existing = resolvedByPath.get(extensionManifestPath);\n if (existing !== undefined) {\n if (!existing.ownerApps.includes(appName)) existing.ownerApps.push(appName);\n continue;\n }\n\n const resolvedExtension = resolveExtensionManifest(tree, extensionManifestPath);\n if (resolvedExtension === null) {\n logger.warn(\n `[resolve-extension-types] Could not resolve extension manifest fields from \"${extensionManifestPath}\" (imported as \"${specifier}\" in ${filePath}).`\n );\n continue;\n }\n\n resolvedByPath.set(extensionManifestPath, { ...resolvedExtension, ownerApps: [appName] });\n }\n });\n\n return { resolved: [...resolvedByPath.values()], unresolved };\n}\n\nfunction resolveExtensionManifest(\n tree: Tree,\n extensionManifestPath: string\n): Omit<ResolvedExtension, \"ownerApps\"> | null {\n const content = tree.read(extensionManifestPath, \"utf-8\");\n if (content === null) return null;\n\n const sourceFile = ts.createSourceFile(\n extensionManifestPath,\n content,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS\n );\n const extensionObject = resolveDefaultExportObjectLiteral(sourceFile);\n if (extensionObject === null) return null;\n\n const id = getStringLiteralProperty(extensionObject, \"id\");\n const type = getStringLiteralProperty(extensionObject, \"type\");\n const sourceRoot = getStringLiteralProperty(extensionObject, \"sourceRoot\");\n if (id === null || type === null || sourceRoot === null) return null;\n\n const main = getStringLiteralProperty(extensionObject, \"main\") ?? DEFAULT_ENTRY_COMPONENT_FILE;\n\n return { id, type, sourceRoot, extensionManifestPath, main };\n}\n\n/**\n * Finds the object literal behind `export default <expr>;`, following a\n * single level of identifier indirection (e.g. `const x = {...}; export\n * default x;`) since that's the shape every real manifest in this repo uses.\n */\nfunction resolveDefaultExportObjectLiteral(sourceFile: ts.SourceFile): ts.ObjectLiteralExpression | null {\n for (const statement of sourceFile.statements) {\n if (!ts.isExportAssignment(statement) || statement.isExportEquals) continue;\n const expr = statement.expression;\n if (ts.isObjectLiteralExpression(expr)) return expr;\n if (ts.isIdentifier(expr)) return findObjectLiteralVariable(sourceFile, expr.text);\n }\n return null;\n}\n\nfunction findObjectLiteralVariable(sourceFile: ts.SourceFile, name: string): ts.ObjectLiteralExpression | null {\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || declaration.name.text !== name) continue;\n if (declaration.initializer !== undefined && ts.isObjectLiteralExpression(declaration.initializer)) {\n return declaration.initializer;\n }\n }\n }\n return null;\n}\n\nfunction getExtensionIdentifiers(manifestObject: ts.ObjectLiteralExpression, filePath: string): Array<string> {\n for (const property of manifestObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue;\n if (!ts.isIdentifier(property.name) || property.name.text !== \"extensions\") continue;\n if (!ts.isArrayLiteralExpression(property.initializer)) return [];\n\n const identifiers: Array<string> = [];\n for (const element of property.initializer.elements) {\n if (ts.isIdentifier(element)) {\n identifiers.push(element.text);\n } else {\n logger.warn(\n `[resolve-extension-types] Skipping a non-identifier element of the \"extensions\" array in ${filePath} (only \\`import x from \"...\"\\`-style identifiers can be statically resolved).`\n );\n }\n }\n return identifiers;\n }\n return [];\n}\n\nfunction getImportSpecifiersByLocalName(sourceFile: ts.SourceFile): Map<string, string> {\n const result = new Map<string, string>();\n for (const statement of sourceFile.statements) {\n if (!ts.isImportDeclaration(statement)) continue;\n const moduleSpecifier = statement.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier)) continue;\n const specifier = moduleSpecifier.text;\n\n const importClause = statement.importClause;\n if (importClause === undefined) continue;\n\n if (importClause.name !== undefined) {\n result.set(importClause.name.text, specifier);\n }\n\n const namedBindings = importClause.namedBindings;\n if (namedBindings !== undefined && ts.isNamedImports(namedBindings)) {\n for (const element of namedBindings.elements) {\n result.set(element.name.text, specifier);\n }\n }\n }\n return result;\n}\n\nfunction getStringLiteralProperty(objectLiteral: ts.ObjectLiteralExpression, propertyName: string): string | null {\n for (const property of objectLiteral.properties) {\n if (!ts.isPropertyAssignment(property)) continue;\n if (!ts.isIdentifier(property.name) || property.name.text !== propertyName) continue;\n return ts.isStringLiteral(property.initializer) ? property.initializer.text : null;\n }\n return null;\n}\n\ntype TsconfigPaths = { compilerOptions?: { paths?: Record<string, Array<string>> } };\n\nfunction readTsconfigPaths(tree: Tree): Map<string, string> {\n const result = new Map<string, string>();\n const content = tree.read(\"tsconfig.base.json\", \"utf-8\");\n if (content === null) {\n logger.warn(\"[resolve-extension-types] tsconfig.base.json not found; no extension imports will resolve.\");\n return result;\n }\n\n let parsed: TsconfigPaths;\n try {\n parsed = JSON.parse(stripJsonComments(content));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn(`[resolve-extension-types] Failed to parse tsconfig.base.json: ${message}`);\n return result;\n }\n\n const paths = parsed.compilerOptions?.paths ?? {};\n for (const [specifier, targets] of Object.entries(paths)) {\n const target = targets[0];\n if (target === undefined) continue;\n result.set(specifier, normalizeRepoRelativePath(target));\n }\n return result;\n}\n\n/**\n * `tsconfig.base.json` is committed without comments today, but strip\n * line comments and block comments defensively in case that changes, so a\n * stray comment doesn't hard-fail `JSON.parse`. The line-comment regex\n * requires the preceding character not be `:` so it doesn't mangle URL-like\n * string values (e.g. `\"https://...\"`).\n */\nfunction stripJsonComments(content: string): string {\n return content.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/(^|[^:])\\/\\/.*$/gm, \"$1\");\n}\n\nfunction normalizeRepoRelativePath(pathValue: string): string {\n return pathValue.replace(/^\\.\\//, \"\");\n}\n"]}
package/migrations.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "generators": {
3
3
  "v2-5-12-p-content-space-codemod": {
4
- "version": "2.5.12",
4
+ "version": "2.5.13",
5
5
  "description": "Rewrite the legacy page-content Tailwind class to overflow-auto p-content-space, invent p-content-space on high-confidence Asset Home/Site Home/Admin content shells, and remove now-redundant bottom-inset classes.",
6
6
  "implementation": "./migrations/p-content-space-codemod/orchestrator"
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app",
3
- "version": "2.5.19-alpha-62031fc7c43.0",
3
+ "version": "2.5.20",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "main": "src/index.js",
6
6
  "generators": "./generators.json",
@@ -10,7 +10,7 @@
10
10
  "node": ">=24.x"
11
11
  },
12
12
  "dependencies": {
13
- "@trackunit/css-classname-utils": "0.0.22-alpha-62031fc7c43.0",
13
+ "@trackunit/css-classname-utils": "0.0.22",
14
14
  "@typescript-eslint/types": "8.58.1",
15
15
  "@typescript-eslint/typescript-estree": "8.58.1",
16
16
  "pacote": "^21.0.4",
@@ -26,10 +26,10 @@
26
26
  "@nx/react": "23.1.0",
27
27
  "@npmcli/arborist": "^9.1.9",
28
28
  "win-ca": "^3.5.1",
29
- "@trackunit/iris-app-build-utilities": "2.4.18-alpha-62031fc7c43.0",
30
- "@trackunit/react-graphql-tools": "1.16.2-alpha-62031fc7c43.0",
31
- "@trackunit/shared-utils": "1.16.22-alpha-62031fc7c43.0",
32
- "@trackunit/iris-app-api": "2.4.12-alpha-62031fc7c43.0",
29
+ "@trackunit/iris-app-build-utilities": "2.4.19",
30
+ "@trackunit/react-graphql-tools": "1.16.3",
31
+ "@trackunit/shared-utils": "1.16.22",
32
+ "@trackunit/iris-app-api": "2.4.13",
33
33
  "tslib": "^2.6.2",
34
34
  "@clack/prompts": "^1.0.0",
35
35
  "@npm/types": "^1.0.2",
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/submit/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport { PackageJson } from \"@npm/types\";\nimport { Arborist } from \"@npmcli/arborist\";\nimport { checkPackageVersion } from \"@trackunit/iris-app-build-utilities\";\nimport * as libpub from \"libnpmpublish\";\nimport * as pacote from \"pacote\";\nimport readline from \"readline\";\nimport { inject } from \"win-ca\";\nimport { getAccessToken } from \"../utils/authentication\";\nimport { getSettings, Settings } from \"../utils/irisAppServerSettings\";\nimport { SubmitExecutorSchema } from \"./schema\";\n\n// Inject Windows trusted certificates to support Zscalar and other traffic inspection systems.\ninject(\"+\");\n\ntype SubmitError = Error & {\n statusCode?: number;\n code?: string;\n type?: string;\n headers?: { [key: string]: string };\n};\n\nclass NpmConflictError extends Error {}\n\nclass NpmGeneralError extends Error {\n public constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly code?: string,\n public readonly type?: string\n ) {\n super(message);\n }\n}\n\nclass ApproveError extends Error {\n public constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly code?: string\n ) {\n super(message);\n }\n}\n\nfunction sleep(time: number) {\n return new Promise(resolve => setTimeout(resolve, time));\n}\n\n// Errno-style codes that indicate the request never reached the registry at all\n// (DNS/connection/timeout failures at the transport layer), as opposed to local\n// validation errors (e.g. libnpmpublish's EPRIVATE/EBADSEMVER/EUSAGE) which carry\n// a code but are permanent and can never succeed on retry. Kept aligned with\n// make-fetch-happen's own RETRY_ERRORS list (used by the submit path) plus the\n// undici error codes doApproveApp's native fetch can raise.\n//\n// ENOTFOUND (DNS failure) is deliberately included even though make-fetch-happen\n// itself excludes it as \"bad hostname, or offline\" - a DNS blip during a VPN/\n// network transition is common enough in practice that failing fast here would\n// trade one wasted-wait problem for developers hitting spurious permanent\n// failures on flaky networks. This is a judgment call, not a clear-cut default.\nconst RETRYABLE_TRANSPORT_CODES = new Set([\n \"ENOTFOUND\",\n \"ECONNRESET\",\n \"ECONNREFUSED\",\n \"ETIMEDOUT\",\n \"EAI_AGAIN\",\n \"ERR_SOCKET_TIMEOUT\",\n \"EADDRINUSE\",\n // from @npmcli/agent, surfaced through make-fetch-happen\n \"ECONNECTIONTIMEOUT\",\n \"EIDLETIMEOUT\",\n \"ERESPONSETIMEOUT\",\n \"ETRANSFERTIMEOUT\",\n // doApproveApp uses Node's native fetch (undici), which raises its own\n // codes distinct from the classic Node errno codes above.\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_HEADERS_TIMEOUT\",\n \"UND_ERR_BODY_TIMEOUT\",\n \"UND_ERR_SOCKET\", // e.g. \"other side closed\" on a reused keep-alive connection\n]);\n\n/**\n * Decide whether a failed submit/approve attempt is worth retrying.\n *\n * This is an allowlist, not a denylist: only failures with a real chance of\n * succeeding on a later attempt are retried - 5xx responses, 408/429 (timeout/\n * rate-limited), a transport-level failure that never reached the registry at\n * all (identified by a known transient errno code), or a minipass-fetch request\n * timeout (which surfaces with the generic code FETCH_ERROR, distinguishable\n * only via its `type: \"request-timeout\"`). Everything else - permanent 4xx\n * errors, local validation errors with an unrelated code (e.g. EBADSEMVER), or\n * any other unrecognized error shape - is treated as non-retryable by default.\n *\n * @param {number} [statusCode] The HTTP status code of the failed attempt, if any.\n * @param {string} [code] The error's errno-style code, if any (no statusCode implies no HTTP response was received).\n * @param {string} [type] The error's `type` field, if any. Only consulted when `code === \"FETCH_ERROR\"`, since that's the one code minipass-fetch's FetchError uses generically for several failure kinds - `type` is what distinguishes a timeout from the others.\n * @returns {boolean} Whether the attempt should be retried.\n */\nfunction isRetryableError(statusCode?: number, code?: string, type?: string): boolean {\n if (statusCode !== undefined) {\n return statusCode >= 500 || statusCode === 408 || statusCode === 429;\n }\n if (code === undefined) {\n return false;\n }\n return RETRYABLE_TRANSPORT_CODES.has(code) || (code === \"FETCH_ERROR\" && type === \"request-timeout\");\n}\n\n/**\n * Submit the package to the npm registry.\n *\n * @param {SubmitExecutorSchema} options The options provided to the executor.\n * @returns {Promise<{ success: boolean }>} The result of the submit.\n */\nexport default async function runExecutor(options: SubmitExecutorSchema) {\n await checkPackageVersion(true);\n const settings = getSettings();\n const linkToTerms = \"https://trackunit.com/terms-conditions-marketplace/\";\n\n try {\n if (options.devTermsAndConditions?.toLowerCase() !== \"accept\" && !settings.devTermsAccept) {\n // Ask user if they accept dev terms and conditions.\n const userInput = await promptUserForInput(\n `Do you accept the developer terms and conditions? \\n(${linkToTerms}) \\n\\n 📝 Type 'accept' to proceed: `\n );\n if (userInput.toLowerCase() !== \"accept\") {\n throw new Error(`You must accept the developer terms and conditions (${linkToTerms}) to continue.`);\n }\n }\n const tokenData = await getAccessToken(settings.env);\n\n if (\"access_token\" in tokenData) {\n console.log(\"🥳 Successfully authenticated.\");\n\n const manifest = (await pacote.manifest(options.inputPath)) as PackageJson;\n const tarData = await pacote.tarball(options.inputPath, { Arborist });\n\n return await doUploadAppWithRetry(tokenData.access_token, manifest, tarData, settings, 10);\n } else if (\"error\" in tokenData) {\n if (tokenData.error === \"expired_token\") {\n throw new Error(\"⌛️ Authentication attempt expired\");\n } else {\n throw new Error(`Error occurred: ${tokenData.error} ${tokenData.error_description}`);\n }\n } else {\n throw new Error(\"Unknown error occurred\");\n }\n } catch (e) {\n console.error(\"❌ \", e);\n return { success: false };\n }\n}\n\nasync function doUploadAppWithRetry(\n accessToken: string,\n manifest: PackageJson,\n tarData: Buffer & pacote.FetchResult,\n settings: Settings,\n retryCount: number\n): Promise<{ success: boolean }> {\n try {\n return await doUploadApp(accessToken, manifest, tarData, settings);\n } catch (e) {\n if (e instanceof NpmConflictError) {\n console.error(\"❌ Unable to ship app package. Cannot submit over existing version.\");\n return { success: false };\n }\n\n if (!(e instanceof NpmGeneralError)) {\n // An error shape we don't recognize (e.g. a bug elsewhere in this function) -\n // log the full error/stack rather than a bare message so it stays debuggable.\n console.error(\"❌ Unable to ship app package. Got error from Iris App SDK repository.\", e);\n return { success: false };\n }\n\n if (!isRetryableError(e.statusCode, e.code, e.type)) {\n console.error(\"❌ Unable to ship app package.\", e.message);\n return { success: false };\n }\n\n if (retryCount > 1) {\n console.error(\n \"⚠️ Unable to ship app package. Got error from Iris App SDK repository. Retrying submit...\",\n e.message\n );\n await sleep(30000);\n return await doUploadAppWithRetry(accessToken, manifest, tarData, settings, retryCount - 1);\n } else {\n console.error(\"❌ Unable to ship app package. Got error from Iris App SDK repository.\", e.message);\n return { success: false };\n }\n }\n}\n\nasync function doUploadApp(\n accessToken: string,\n manifest: PackageJson,\n tarData: Buffer & pacote.FetchResult,\n settings: Settings\n): Promise<{ success: boolean }> {\n const npmFetchOptions: { registry?: string } & Record<string, string | boolean> = {};\n npmFetchOptions.registry = settings.repoUrl.toString();\n const repoHostAndPort = settings.repoUrl.hostname + (settings.repoUrl.port ? `:${settings.repoUrl.port}` : \"\");\n npmFetchOptions[`//${repoHostAndPort}${settings.repoUrl.pathname}:_authToken`] = accessToken;\n npmFetchOptions[`//${repoHostAndPort}${settings.repoUrl.pathname}/repo/:always-auth`] = true;\n\n console.log(\"🚢 Shipping the app package...\");\n const submitResult = await libpub.publish(manifest, tarData, npmFetchOptions).catch((err: SubmitError) => {\n if (err.statusCode === 409 || err.code === \"E409\" || err.code === \"EPUBLISHCONFLICT\") {\n return {\n ok: false,\n submitConflict: true,\n };\n } else {\n return {\n ok: false,\n statusCode: err.statusCode,\n code: err.code,\n type: err.type,\n headers: new Headers(err.headers),\n statusText: `Error`,\n text: () => Promise.resolve(`${err.name} ${err.message}`),\n };\n }\n });\n\n const warningsText = submitResult.headers?.get(\"TU-IRIS-APP-WARNINGS\");\n if (warningsText) {\n console.log(`⚠️ ${decodeURI(warningsText)}`);\n }\n\n if (submitResult.ok) {\n console.log(`🚀 Uploaded the app package version ${manifest.version}`);\n\n return await doApproveAppWithRetry(accessToken, manifest, settings, 3);\n } else if (\"submitConflict\" in submitResult) {\n if (process.env.SKIP_EXISTING === \"true\") {\n console.log(`⏩ Skipped submitting ${manifest.version} because the version is already submitted`);\n return await doApproveAppWithRetry(accessToken, manifest, settings, 3);\n } else {\n throw new NpmConflictError();\n }\n } else {\n throw new NpmGeneralError(\n `${submitResult.statusText} ${await submitResult.text()}. Trace ID: ${submitResult.headers.get(\"trace-id\")}`,\n \"statusCode\" in submitResult ? submitResult.statusCode : undefined,\n \"code\" in submitResult ? submitResult.code : undefined,\n \"type\" in submitResult ? submitResult.type : undefined\n );\n }\n}\n\nasync function promptUserForInput(query: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise(resolve => {\n rl.question(query, (input: string) => {\n rl.close();\n resolve(input);\n });\n });\n}\n\nasync function doApproveAppWithRetry(\n token: string,\n manifest: PackageJson,\n settings: Settings,\n retryCount: number\n): Promise<{ success: boolean }> {\n try {\n return await doApproveApp(token, manifest, settings);\n } catch (e) {\n if (!(e instanceof ApproveError)) {\n console.error(\"❌ Unable to approve app package. Got error from Iris App SDK repository.\", e);\n return { success: false };\n }\n\n if (!isRetryableError(e.statusCode, e.code)) {\n console.error(\"❌ Unable to approve app package.\", e.message);\n return { success: false };\n }\n\n if (retryCount > 1) {\n console.error(\n \"⚠️ Unable to approve app package. Got approve error from Iris App SDK repository. Retrying approve...\",\n e.message\n );\n await sleep(30000);\n return await doApproveAppWithRetry(token, manifest, settings, retryCount - 1);\n } else {\n console.error(\"❌ Unable to approve app package. Got approve error from Iris App SDK repository.\", e.message);\n return { success: false };\n }\n }\n}\n\nasync function doApproveApp(token: string, manifest: PackageJson, settings: Settings) {\n if (process.env.TU_APPROVE === \"true\") {\n console.log(`🖋️ Approving the app...`);\n // A rejection here (e.g. DNS/connection/timeout failure) never produced an HTTP\n // response, so it's re-thrown as an ApproveError with no statusCode - carrying\n // the underlying cause's errno code (if any) so isRetryableError can recognize\n // genuine transport failures, and the cause's message so the log doesn't just\n // say \"fetch failed\" with no indication of what actually broke.\n const approveResult = await fetch(new URL(`${manifest.name}@${manifest.version}`, settings.approvalUrl), {\n method: \"PUT\",\n headers: {\n Authorization: `Bearer ${token}`,\n },\n }).catch((err: Error) => {\n const cause = err.cause instanceof Error ? err.cause : undefined;\n const causeCode = cause && \"code\" in cause ? (cause as NodeJS.ErrnoException).code : undefined;\n const code = typeof causeCode === \"string\" ? causeCode : undefined;\n const reason = cause ? `${err.message}: ${cause.message}` : err.message;\n throw new ApproveError(reason, undefined, code);\n });\n\n if (approveResult.ok) {\n console.log(`✅ Approved version ${manifest.version} of ${manifest.name}.`);\n return { success: true };\n } else {\n throw new ApproveError(\n `${approveResult.statusText}, ${await approveResult.text()}, Trace ID: ${approveResult.headers.get(\"trace-id\")}`,\n approveResult.status\n );\n }\n } else {\n return { success: true };\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/unpublish/executor.ts"],"names":[],"mappings":";;AAcA,8BAkDC;;AA9DD,uDAAiC;AACjC,kBAAgB;AAChB,4DAAyD;AACzD,0EAA6D;AAG7D;;;;;GAKG;AACY,KAAK,UAAU,WAAW,CAAC,OAAgC;IACxE,MAAM,QAAQ,GAAG,IAAA,mCAAW,GAAE,CAAC;IAE/B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,IAAA,+BAAc,EAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAErD,IAAI,cAAc,IAAI,SAAS,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAE9C,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAgB,CAAC;YAC3E,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;gBAC5E,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,SAAS,CAAC,YAAY,EAAE;iBAClD;aACF,CAAC,CAAC;YACH,IAAI,eAAe,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnC,QAAQ,eAAe,CAAC,MAAM,EAAE,CAAC;oBAC/B,KAAK,GAAG;wBACN,MAAM,IAAI,KAAK,CACb,6DAA6D,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CACvG,CAAC;oBACJ,KAAK,GAAG;wBACN,MAAM,IAAI,KAAK,CACb,wDAAwD,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAClG,CAAC;oBACJ,KAAK,GAAG;wBACN,MAAM,IAAI,KAAK,CACb,iEAAiE,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAC3G,CAAC;oBACJ;wBACE,MAAM,IAAI,KAAK,CAAC,GAAG,eAAe,CAAC,UAAU,eAAe,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBAC3G,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;YAChC,IAAI,SAAS,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC","sourcesContent":["/* eslint-disable no-console */\nimport { PackageJson } from \"nx/src/utils/package-json\";\nimport * as pacote from \"pacote\";\nimport \"win-ca\";\nimport { getAccessToken } from \"../utils/authentication\";\nimport { getSettings } from \"../utils/irisAppServerSettings\";\nimport { UnpublishExecutorSchema } from \"./schema\";\n\n/**\n * Unpublish an app from the Trackunit Marketplace.\n *\n * @param {UnpublishExecutorSchema} options options provided to the executor.\n * @returns {Promise<{ success: boolean }>} The result of the unpublish.\n */\nexport default async function runExecutor(options: UnpublishExecutorSchema) {\n const settings = getSettings();\n\n try {\n const tokenData = await getAccessToken(settings.env);\n\n if (\"access_token\" in tokenData) {\n console.log(\"🥳 Successfully authenticated.\");\n\n const manifest = (await pacote.manifest(options.inputPath)) as PackageJson;\n const unpublishResult = await fetch(new URL(manifest.name, settings.repoUrl), {\n method: \"DELETE\",\n headers: {\n Authorization: `Bearer ${tokenData.access_token}`,\n },\n });\n if (unpublishResult.status !== 200) {\n switch (unpublishResult.status) {\n case 401:\n throw new Error(\n `Unpublishing failed due to invalid credentials, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`\n );\n case 403:\n throw new Error(\n `You are not allowed to unpublish this app, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`\n );\n case 404:\n throw new Error(\n `The app you are trying to unpublish does not exist, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`\n );\n default:\n throw new Error(`${unpublishResult.statusText}, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`);\n }\n }\n\n console.log(\"🥳 Successfully unpublished app.\");\n return { success: true };\n } else if (\"error\" in tokenData) {\n if (tokenData.error === \"expired_token\") {\n throw new Error(\"⌛️ Authentication attempt expired\");\n } else {\n throw new Error(`Error occurred: ${tokenData.error} ${tokenData.error_description}`);\n }\n } else {\n throw new Error(\"Unknown error occurred\");\n }\n } catch (e) {\n console.error(\"❌ \", e);\n return { success: false };\n }\n}\n"]}
@@ -39,7 +39,11 @@ async function getAccessToken(env) {
39
39
  tokenParams.append("client_id", clientId);
40
40
  tokenParams.append("client_secret", clientSecret);
41
41
  tokenParams.append("grant_type", "client_credentials");
42
- tokenParams.append("scope", "core.iris.app.publish_for_all_accounts");
42
+ const scopes = ["core.iris.app.publish_for_all_accounts"];
43
+ if (process.env.TU_APPROVE === "true") {
44
+ scopes.push("core.iris.app.approve");
45
+ }
46
+ tokenParams.append("scope", scopes.join(" "));
43
47
  const tokenResponse = await fetch(`${settings.internalAuthorizationServerBaseUrl}/v1/token`, {
44
48
  method: "POST",
45
49
  body: tokenParams,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authentication.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/utils/authentication.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport openBrowser from \"open\";\n\nexport interface AuthSettings {\n env: string;\n publicAuthorizationServerBaseUrl: string;\n internalAuthorizationServerBaseUrl: string;\n apiTokensV2BaseUrl: string;\n clientId: string;\n}\n\ninterface OktaError {\n error: string;\n error_description: string;\n}\n\ninterface AuthorizeDataSuccess {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n}\n\ntype AuthorizeData = AuthorizeDataSuccess | OktaError;\n\nexport interface TokenDataSuccess {\n token_type: string;\n expires_in: number;\n access_token: string;\n scope: string;\n id_token: string;\n}\n\ntype TokenData = OktaError | TokenDataSuccess;\n\n/**\n * Authenticate and get access token\n *\n * @param {AuthSettings} env Settings used for authentication\n * @returns {*} {Promise<TokenData>}\n */\nexport async function getAccessToken(env: string): Promise<TokenData> {\n const settings = getAuthSettings(env);\n const clientId = process.env[`TU_CLIENT_ID_${settings.env}`];\n const clientSecret = process.env[`TU_CLIENT_SECRET_${settings.env}`];\n const apiTokenClientId = process.env.TU_API_TOKEN_CLIENT_ID;\n const apiTokenClientSecret = process.env.TU_API_TOKEN_CLIENT_SECRET;\n // use token provided as environment variable if available\n if (process.env.TU_TOKEN) {\n return {\n token_type: \"Bearer\",\n id_token: process.env.TU_TOKEN,\n access_token: process.env.TU_TOKEN,\n expires_in: 0,\n scope: \"unknown\",\n };\n // use client id and secret provided as environment variables to fetch a token directly\n // This is used for CI/CD pipelines\n } else if (clientId !== undefined) {\n if (clientId.trim() === \"\") {\n throw new Error(`Missing environment value: TU_CLIENT_ID_${settings.env}`);\n }\n if (clientSecret === undefined || clientSecret.trim() === \"\") {\n throw new Error(`Missing environment value: TU_CLIENT_SECRET_${settings.env}`);\n }\n\n const tokenParams = new URLSearchParams();\n tokenParams.append(\"client_id\", clientId);\n tokenParams.append(\"client_secret\", clientSecret);\n tokenParams.append(\"grant_type\", \"client_credentials\");\n const scopes = [\"core.iris.app.publish_for_all_accounts\"];\n if (process.env.TU_APPROVE === \"true\") {\n scopes.push(\"core.iris.app.approve\");\n }\n tokenParams.append(\"scope\", scopes.join(\" \"));\n const tokenResponse = await fetch(`${settings.internalAuthorizationServerBaseUrl}/v1/token`, {\n method: \"POST\",\n body: tokenParams,\n });\n return (await tokenResponse.json()) as TokenData;\n // use API Tokens v2 client credentials for external API key based publishing\n } else if (apiTokenClientId !== undefined) {\n if (apiTokenClientId.trim() === \"\") {\n throw new Error(\"Missing environment value: TU_API_TOKEN_CLIENT_ID\");\n }\n if (apiTokenClientSecret === undefined || apiTokenClientSecret.trim() === \"\") {\n throw new Error(\"Missing environment value: TU_API_TOKEN_CLIENT_SECRET\");\n }\n\n const tokenParams = new URLSearchParams();\n tokenParams.append(\"client_id\", apiTokenClientId);\n tokenParams.append(\"client_secret\", apiTokenClientSecret);\n tokenParams.append(\"grant_type\", \"client_credentials\");\n tokenParams.append(\"scope\", \"iris.app.submit\");\n const tokenResponse = await fetch(`${settings.apiTokensV2BaseUrl}/token/v2`, {\n method: \"POST\",\n body: tokenParams,\n });\n return (await tokenResponse.json()) as TokenData;\n // ask the user to authenticated using a browser\n // and fetch a token using the device code flow\n } else {\n const authorizeParams = new URLSearchParams();\n authorizeParams.append(\"client_id\", settings.clientId);\n authorizeParams.append(\"scope\", \"openid profile fms assume iris.app.submit\");\n const authorizeResponse = await fetch(`${settings.publicAuthorizationServerBaseUrl}/v1/device/authorize`, {\n method: \"POST\",\n body: authorizeParams,\n });\n const authorizeData = (await authorizeResponse.json()) as AuthorizeData;\n\n if (\"error\" in authorizeData) {\n throw new Error(`Error occurred: ${authorizeData.error} ${authorizeData.error_description}`);\n } else if (!authorizeData.verification_uri_complete) {\n throw new Error(`Missing verification URI: ${JSON.stringify(authorizeData)}`);\n }\n\n console.log(\n `🔐 Attempting to automatically open the Trackunit authentication page in your default browser...\\n If the browser does not open or you wish to use a different device to authorize this request, open the following URL:\\n\\n ${authorizeData.verification_uri_complete}`\n );\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await ((openBrowser as any).default ? (openBrowser as any).default : openBrowser)(\n authorizeData.verification_uri_complete\n );\n } catch {\n // safe to ignore, since we ask the user to open the URL manually above.\n }\n\n console.log(\"\\n⏳ Waiting for authentication in the browser...\");\n let tokenData: TokenData | null = null;\n do {\n await sleep(authorizeData.interval * 1000);\n if (tokenData && \"error\" in tokenData && tokenData.error === \"slow_down\") {\n await sleep(10000);\n }\n const tokenParams = new URLSearchParams();\n tokenParams.append(\"client_id\", settings.clientId);\n tokenParams.append(\"grant_type\", \"urn:ietf:params:oauth:grant-type:device_code\");\n tokenParams.append(\"device_code\", authorizeData.device_code);\n const tokenResponse = await fetch(`${settings.publicAuthorizationServerBaseUrl}/v1/token`, {\n method: \"POST\",\n body: tokenParams,\n });\n tokenData = (await tokenResponse.json()) as TokenData;\n } while (\n !(\"id_token\" in tokenData) &&\n !(\"error\" in tokenData && tokenData.error !== \"authorization_pending\" && tokenData.error !== \"slow_down\")\n );\n return tokenData;\n }\n}\n\n/**\n *\n */\nfunction getAuthSettings(env: string): AuthSettings {\n switch (env) {\n case \"PROD\":\n return {\n clientId: \"0oamfeklvodROR2ul357\",\n publicAuthorizationServerBaseUrl: \"https://identity.iris.trackunit.com/oauth2/aus2u3jix1dWU7fwt356\",\n internalAuthorizationServerBaseUrl: \"https://identity.iris.trackunit.com/oauth2/aushbxvmpdlWrMnO6357\",\n apiTokensV2BaseUrl: \"https://auth.trackunit.com\",\n env,\n };\n case \"STAGE\":\n return {\n clientId: \"0oa1q2vmx21NcFLOs0h8\",\n publicAuthorizationServerBaseUrl: \"https://identity.stage.iris.trackunit.com/oauth2/aus1owd7wny5YVsU00h8\",\n internalAuthorizationServerBaseUrl: \"https://identity.stage.iris.trackunit.com/oauth2/aus1o484n9xEHT7G50h8\",\n apiTokensV2BaseUrl: \"https://stage.auth.trackunit.com\",\n env,\n };\n case \"DEV\":\n return {\n clientId: \"0oamebigau4RkaqZ6357\",\n publicAuthorizationServerBaseUrl: \"https://identity.dev.iris.trackunit.com/oauth2/ausj7eh9zeiFhLk4m357\",\n internalAuthorizationServerBaseUrl: \"https://identity.dev.iris.trackunit.com/oauth2/aush09l7x4mDGKxLu357\",\n apiTokensV2BaseUrl: \"https://dev.auth.trackunit.com\",\n env,\n };\n case \"LOCAL\":\n return {\n clientId: \"0oamebigau4RkaqZ6357\",\n publicAuthorizationServerBaseUrl: \"https://identity.dev.iris.trackunit.com/oauth2/ausj7eh9zeiFhLk4m357\",\n internalAuthorizationServerBaseUrl: \"https://identity.dev.iris.trackunit.com/oauth2/aush09l7x4mDGKxLu357\",\n apiTokensV2BaseUrl: \"https://dev.auth.trackunit.com\",\n env,\n };\n default:\n throw new Error(`Unknown environment: ${env}`);\n }\n}\n\nfunction sleep(time: number) {\n return new Promise(resolve => setTimeout(resolve, time));\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"irisAppServerSettings.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/utils/irisAppServerSettings.ts"],"names":[],"mappings":";;AAWA,kCAaC;AAhBD;;GAEG;AACH,SAAgB,WAAW;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,MAAM,CAAC;IACxD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,WAAW,EAAE,KAAK,QAAQ,CAAC;IAE3F,OAAO;QACL,WAAW,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC;QACzC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QAClC,kBAAkB;QAClB,GAAG;QACH,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE;IACjC,QAAQ,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1B,KAAK,MAAM;YACT,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,6BAA6B,CAAC,CAAC;QACxE,KAAK,OAAO;YACV,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,mCAAmC,CAAC,CAAC;QAC9E,KAAK,KAAK;YACR,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,iCAAiC,CAAC,CAAC;QAC5E,KAAK,OAAO;YACV,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,wBAAwB,CAAC,CAAC;QACnE;YACE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,CAAC,GAAW,EAAE,EAAE;IAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACrC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC;IACD,QAAQ,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1B,KAAK,MAAM;YACT,OAAO,IAAI,GAAG,CAAC,gEAAgE,CAAC,CAAC;QACnF,KAAK,OAAO;YACV,OAAO,IAAI,GAAG,CAAC,iEAAiE,CAAC,CAAC;QACpF,KAAK,KAAK;YACR,OAAO,IAAI,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAClF,KAAK,OAAO;YACV,OAAO,IAAI,GAAG,CAAC,gCAAgC,CAAC,CAAC;QACnD;YACE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAC","sourcesContent":["export type Settings = {\n approvalUrl: URL;\n repoUrl: URL;\n graphqlInternalUrl: URL;\n env: string;\n devTermsAccept: boolean;\n};\n\n/**\n * Provides the settings for the Iris App server based on the environment.\n */\nexport function getSettings(): Settings {\n const env = process.env.TU_ENV?.toUpperCase() ?? \"PROD\";\n const baseUrl = getBaseUrl(env);\n const graphqlInternalUrl = getGraphqlInternalUrl(env);\n const devTermsAccept = process.env.TU_DEV_TERMS_AND_CONDITIONS?.toLowerCase() === \"accept\";\n\n return {\n approvalUrl: new URL(\"approve/\", baseUrl),\n repoUrl: new URL(\"repo/\", baseUrl),\n graphqlInternalUrl,\n env,\n devTermsAccept,\n };\n}\n\n/**\n * Provides the base URL for the Iris App server based on the environment.\n *\n * @param {string} env The environment to get the base URL for.\n * @returns {URL} The base URL for the Iris App server.\n */\nconst getBaseUrl = (env: string) => {\n switch (env.toUpperCase()) {\n case \"PROD\":\n return new URL(process.env.BASE_URL ?? \"https://iris.trackunit.app/\");\n case \"STAGE\":\n return new URL(process.env.BASE_URL ?? \"https://stage.iris.trackunit.app/\");\n case \"DEV\":\n return new URL(process.env.BASE_URL ?? \"https://dev.iris.trackunit.app/\");\n case \"LOCAL\":\n return new URL(process.env.BASE_URL ?? \"http://localhost:3003/\");\n default:\n throw new Error(`Unknown environment: ${env}`);\n }\n};\n\n/**\n * Provides the URL for the internal GraphQL endpoint based on the environment.\n * Can be overridden by the `GRAPHQL_INTERNAL_URL` environment variable.\n *\n * @param {string} env The environment to get the URL for.\n * @returns {URL} The internal GraphQL URL.\n */\nconst getGraphqlInternalUrl = (env: string) => {\n if (process.env.GRAPHQL_INTERNAL_URL) {\n return new URL(process.env.GRAPHQL_INTERNAL_URL);\n }\n switch (env.toUpperCase()) {\n case \"PROD\":\n return new URL(\"https://prod.awsapi.trackunit.com/public/api/graphql/internal/\");\n case \"STAGE\":\n return new URL(\"https://stage.awsapi.trackunit.com/public/api/graphql/internal/\");\n case \"DEV\":\n return new URL(\"https://dev.awsapi.trackunit.com/public/api/graphql/internal/\");\n case \"LOCAL\":\n return new URL(\"http://localhost:5011/internal\");\n default:\n throw new Error(`Unknown environment: ${env}`);\n }\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/iris-app-sdk/iris-app/src/executors/utils/src/index.js"],"names":[],"mappings":";AAAA,wFAAwF","sourcesContent":["// Empty ts file for webpack to be happy - we generate module federated js files instead\n"]}
@@ -20,19 +20,20 @@ nx g @trackunit/iris-app:ai-agent-sync
20
20
 
21
21
  ```mermaid
22
22
  flowchart TD
23
- A[Run ai-agent-sync generator] --> B[Ensure update:trackunit script exists]
24
- B --> C{Skip version check?}
23
+ A[Run ai-agent-sync generator] --> C{Skip version check?}
25
24
  C -->|Yes| G[Sync AI agent files]
26
25
  C -->|No| D[Get installed SDK version]
27
26
  D --> E[Fetch latest SDK version from npm]
28
27
  E --> F{SDK up to date?}
29
28
  F -->|Yes| G
30
29
  F -->|No| H[❌ Error: SDK outdated]
31
- H --> I[Show commands to update]
32
- I --> J["1. {pm} run update:trackunit<br>2. {pm} install<br>3. Run generator again"]
30
+ H --> I[Show commands to upgrade]
31
+ I --> J["1. {pm} add -D @trackunit/migrations<br>2. nx g @trackunit/migrations:migrate<br>3. nx g @trackunit/migrations:run-migrations<br>4. Run generator again"]
33
32
  G --> K[✅ Done]
34
33
  ```
35
34
 
35
+ Upgrading `@trackunit/*` dependencies is not this generator's job — `@trackunit/migrations:migrate` owns that, and it upgrades every `@trackunit/*` dependency whether or not the package ships codemods.
36
+
36
37
  ## Options
37
38
 
38
39
  | Option | Type | Default | Description |
@@ -4,13 +4,12 @@ exports.aiAgentSyncGenerator = aiAgentSyncGenerator;
4
4
  const tslib_1 = require("tslib");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const devkit_exports_1 = require("nx/src/devkit-exports");
7
- const pacote = tslib_1.__importStar(require("pacote"));
8
7
  const path = tslib_1.__importStar(require("path"));
9
8
  const semver = tslib_1.__importStar(require("semver"));
9
+ const get_package_manifest_1 = require("../utils/get-package-manifest");
10
10
  const link_claude_skills_1 = require("../utils/link-claude-skills");
11
11
  const IRIS_APP_PACKAGE = "@trackunit/iris-app";
12
- const UPDATE_SCRIPT_NAME = "update:trackunit";
13
- const UPDATE_SCRIPT_CMD = 'npx npm-check-updates "/@trackunit/" -u';
12
+ const MIGRATIONS_PACKAGE = "@trackunit/migrations";
14
13
  function getStringValue(obj, key) {
15
14
  if (typeof obj === "object" && obj !== null && key in obj) {
16
15
  const value = obj[key];
@@ -33,30 +32,28 @@ function getInstalledSdkVersion(tree) {
33
32
  * Fetches the latest version of @trackunit/iris-app from npm
34
33
  */
35
34
  async function getLatestSdkVersion() {
36
- const manifest = await pacote.manifest(IRIS_APP_PACKAGE);
35
+ const manifest = await (0, get_package_manifest_1.getPackageManifest)(IRIS_APP_PACKAGE);
37
36
  return manifest.version;
38
37
  }
39
38
  /**
40
- * Ensures the update:trackunit script exists in package.json
39
+ * The single supported way to bring every @trackunit/* dependency up to date.
40
+ * The install of the migrations package is spelled out because a workspace that
41
+ * has never upgraded does not have it, and without it the generator cannot be
42
+ * resolved at all.
41
43
  */
42
- function ensureUpdateScript(tree) {
43
- (0, devkit_1.updateJson)(tree, "package.json", pkgJson => {
44
- if (!pkgJson.scripts) {
45
- pkgJson.scripts = {};
46
- }
47
- if (!pkgJson.scripts[UPDATE_SCRIPT_NAME]) {
48
- pkgJson.scripts[UPDATE_SCRIPT_NAME] = UPDATE_SCRIPT_CMD;
49
- }
50
- return pkgJson;
51
- });
44
+ function upgradeInstructions() {
45
+ const pmc = (0, devkit_exports_1.getPackageManagerCommand)((0, devkit_exports_1.detectPackageManager)());
46
+ return [
47
+ ` ${pmc.addDev} ${MIGRATIONS_PACKAGE} # only needed once`,
48
+ ` ${pmc.exec} nx g ${MIGRATIONS_PACKAGE}:migrate`,
49
+ ` ${pmc.exec} nx g ${MIGRATIONS_PACKAGE}:run-migrations`,
50
+ ].join("\n");
52
51
  }
53
52
  /**
54
53
  * Syncs Cursor skills, AGENTS.md, CLAUDE.md, and AI agent configuration files.
55
54
  * Requires the SDK to be at the latest version before running.
56
55
  */
57
56
  async function aiAgentSyncGenerator(tree, options) {
58
- // Always ensure the update script exists
59
- ensureUpdateScript(tree);
60
57
  // Check SDK version unless skipped
61
58
  if (!options.skipVersionCheck) {
62
59
  const installedVersion = getInstalledSdkVersion(tree);
@@ -66,12 +63,9 @@ async function aiAgentSyncGenerator(tree, options) {
66
63
  }
67
64
  const installed = semver.minVersion(installedVersion);
68
65
  if (!installed || semver.lt(installed, latestVersion)) {
69
- const pm = (0, devkit_exports_1.detectPackageManager)();
70
- const pmCmd = (0, devkit_exports_1.getPackageManagerCommand)(pm);
71
66
  throw new Error(`${IRIS_APP_PACKAGE} is outdated (installed: ${installedVersion}, latest: ${latestVersion}).\n\n` +
72
- `Run the following commands first:\n` +
73
- ` ${pmCmd.run(UPDATE_SCRIPT_NAME)}\n` +
74
- ` ${pmCmd.install}\n\n` +
67
+ `Upgrade every @trackunit/* dependency first:\n` +
68
+ `${upgradeInstructions()}\n\n` +
75
69
  `Then run this generator again.`);
76
70
  }
77
71
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/ai-agent-sync/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import { GeneratorCallback, Tree, formatFiles, generateFiles, logger } from \"@nx/devkit\";\nimport { detectPackageManager, getPackageManagerCommand } from \"nx/src/devkit-exports\";\nimport * as path from \"path\";\nimport * as semver from \"semver\";\nimport { getPackageManifest } from \"../utils/get-package-manifest\";\nimport { linkClaudeSkills } from \"../utils/link-claude-skills\";\nimport { AiAgentSyncGeneratorSchema } from \"./schema\";\n\nconst IRIS_APP_PACKAGE = \"@trackunit/iris-app\";\nconst MIGRATIONS_PACKAGE = \"@trackunit/migrations\";\n\nfunction getStringValue(obj: unknown, key: string): string | undefined {\n if (typeof obj === \"object\" && obj !== null && key in obj) {\n const value = (obj as Record<string, unknown>)[key];\n return typeof value === \"string\" ? value : undefined;\n }\n return undefined;\n}\n\n/**\n * Gets the installed version of @trackunit/iris-app from workspace package.json\n */\nfunction getInstalledSdkVersion(tree: Tree): string | undefined {\n const pkgJson: unknown = JSON.parse(tree.read(\"package.json\", \"utf-8\") ?? \"{}\");\n if (typeof pkgJson !== \"object\" || pkgJson === null) {\n return undefined;\n }\n const pkg = pkgJson as Record<string, unknown>;\n return getStringValue(pkg.dependencies, IRIS_APP_PACKAGE) ?? getStringValue(pkg.devDependencies, IRIS_APP_PACKAGE);\n}\n\n/**\n * Fetches the latest version of @trackunit/iris-app from npm\n */\nasync function getLatestSdkVersion(): Promise<string> {\n const manifest = await getPackageManifest(IRIS_APP_PACKAGE);\n return manifest.version;\n}\n\n/**\n * The single supported way to bring every @trackunit/* dependency up to date.\n * The install of the migrations package is spelled out because a workspace that\n * has never upgraded does not have it, and without it the generator cannot be\n * resolved at all.\n */\nfunction upgradeInstructions(): string {\n const pmc = getPackageManagerCommand(detectPackageManager());\n\n return [\n ` ${pmc.addDev} ${MIGRATIONS_PACKAGE} # only needed once`,\n ` ${pmc.exec} nx g ${MIGRATIONS_PACKAGE}:migrate`,\n ` ${pmc.exec} nx g ${MIGRATIONS_PACKAGE}:run-migrations`,\n ].join(\"\\n\");\n}\n\n/**\n * Syncs Cursor skills, AGENTS.md, CLAUDE.md, and AI agent configuration files.\n * Requires the SDK to be at the latest version before running.\n */\nexport async function aiAgentSyncGenerator(\n tree: Tree,\n options: AiAgentSyncGeneratorSchema\n): Promise<GeneratorCallback> {\n // Check SDK version unless skipped\n if (!options.skipVersionCheck) {\n const installedVersion = getInstalledSdkVersion(tree);\n const latestVersion = await getLatestSdkVersion();\n\n if (!installedVersion) {\n throw new Error(`${IRIS_APP_PACKAGE} not found in package.json. Is this an Iris App SDK workspace?`);\n }\n\n const installed = semver.minVersion(installedVersion);\n if (!installed || semver.lt(installed, latestVersion)) {\n throw new Error(\n `${IRIS_APP_PACKAGE} is outdated (installed: ${installedVersion}, latest: ${latestVersion}).\\n\\n` +\n `Upgrade every @trackunit/* dependency first:\\n` +\n `${upgradeInstructions()}\\n\\n` +\n `Then run this generator again.`\n );\n }\n }\n\n // Clean up old .cursor files that were managed by previous versions.\n const oldManagedFiles = [\n \".cursor/rules/irisx-app-sdk.mdc\",\n \".cursor/rules/rules-index.mdc\",\n \".cursor/rules/structured-development.mdc\",\n \".cursor/rules/browser-irisx-development.mdc\",\n \".cursor/rules/graphql-timeseries.md\",\n \".cursor/rules/irisx-app-sdk-customfields.md\",\n \".cursor/rules/irisx-app-sdk-graphql.md\",\n \".cursor/rules/react-core-hooks.md\",\n \".cursor/rules/tables-and-sorting.mdc\",\n \".cursor/rules/widget-extensions.md\",\n \".cursor/commands/create-app.md\",\n ];\n for (const file of oldManagedFiles) {\n if (tree.exists(file)) {\n tree.delete(file);\n }\n }\n\n // Copy MCP configuration and agent skills shared with the preset generator.\n const managedFilesTemplatePath = path.join(__dirname, \"../preset/files\");\n generateFiles(tree, managedFilesTemplatePath, \".\", {});\n\n // Copy AGENTS.md and CLAUDE.md to workspace root\n const rootTemplatePath = path.join(__dirname, \"../preset/root-files\");\n generateFiles(tree, rootTemplatePath, \".\", {});\n\n await formatFiles(tree);\n\n // After tree flush, create a symlink at .claude/skills -> ../.agents/skills\n // so Claude Code auto-discovers the same skills Cursor and Codex consume.\n // The Tree API has no symlink primitive, so this runs as a post-generation\n // callback against the actual filesystem.\n return () => {\n const result = linkClaudeSkills(tree.root);\n if (result.status === \"skipped\") {\n logger.warn(\n `[iris-app:ai-agent-sync] Skipped creating .claude/skills symlink: ${result.reason}. ` +\n `Claude Code users may need to create it manually: ln -s ../.agents/skills .claude/skills`\n );\n }\n };\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/create/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addDependenciesToPackageJson,\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n getWorkspaceLayout,\n installPackagesTask,\n names,\n offsetFromRoot,\n readJsonFile,\n Tree,\n updateJson,\n} from \"@nx/devkit\";\nimport { getNpmScope } from \"@nx/js/internal\";\nimport { PackageJson as PackageJsonBase } from \"nx/src/utils/package-json\";\nimport * as path from \"path\";\nimport { getPackageManifest } from \"../utils/get-package-manifest\";\nimport { IrisAppGeneratorSchema } from \"./schema\";\n\ntype PackageJson = PackageJsonBase & {\n engines?: Record<string, string>;\n};\n\ninterface NormalizedSchema extends IrisAppGeneratorSchema {\n projectName: string;\n projectRoot: string;\n projectDirectory: string;\n toNxRoot: string;\n npmScope: string;\n}\n\nfunction normalizeOptions(tree: Tree, options: IrisAppGeneratorSchema): NormalizedSchema {\n const name = names(options.name).fileName;\n const projectDirectory = options.directory ? path.join(options.directory, name) : name;\n const toNxRoot = `../../${projectDirectory.indexOf(\"/\") !== -1 ? \"../\" : \"\"}`;\n const projectName = name.replace(new RegExp(\"/\", \"g\"), \"_\");\n const npmScope = getNpmScope(tree);\n if (!npmScope) {\n throw new Error(\"Could not find npm scope in package.json\");\n }\n const projectRoot = `${getWorkspaceLayout(tree).appsDir}/${projectDirectory}`;\n return {\n ...options,\n projectName,\n projectRoot,\n projectDirectory,\n toNxRoot,\n npmScope,\n };\n}\n\nfunction addFiles(tree: Tree, options: NormalizedSchema, packageJson: PackageJson | null) {\n const nodeVersion = packageJson?.engines?.node ?? \">=20.x\";\n const templateOptions = {\n ...options,\n ...names(options.name),\n offsetFromRoot: offsetFromRoot(options.projectRoot),\n template: \"\",\n nodeVersion,\n };\n generateFiles(tree, path.join(__dirname, \"files\"), options.projectRoot, templateOptions);\n}\n\n/**\n * Iris App Generator.\n * This generator will create a new iris app, you can call this from your own generator.\n *\n * @param tree the nx tree\n * @param options the generator options\n * @returns { Promise<void> } void\n */\nexport const IrisAppGenerator = async function (tree: Tree, options: IrisAppGeneratorSchema) {\n const normalizedOptions = normalizeOptions(tree, options);\n const packageJsonFromNpm = await getPackageManifest(\"@trackunit/iris-app\");\n\n const packageJsonLocally: PackageJson = readJsonFile(path.join(__dirname, \"..\", \"..\", \"..\", \"package.json\"));\n\n if (options.updatePackageJson) {\n if (packageJsonFromNpm.version !== packageJsonLocally.version) {\n // eslint-disable-next-line no-console\n console.warn(\n `⚠️ This version of the iris-app package does not match the version of the iris-app package from NPM JS. Please update using: npm i @trackunit/iris-app@${packageJsonFromNpm.version}`\n );\n }\n\n const reactComponentsPackageJsonFromNpm = getPackageManifest(\"@trackunit/react-components\");\n const reactCoreContextsPackageJsonFromNpm = getPackageManifest(\"@trackunit/react-core-contexts\");\n const cssCorePackageJsonFromNpm = getPackageManifest(\"@trackunit/css-core\");\n const irisAppApiPackageJsonFromNpm = getPackageManifest(\"@trackunit/iris-app-api\");\n\n const tuDependencies = {\n \"@trackunit/react-components\": (await reactComponentsPackageJsonFromNpm).version,\n \"@trackunit/react-core-contexts\": (await reactCoreContextsPackageJsonFromNpm).version,\n \"@trackunit/css-core\": (await cssCorePackageJsonFromNpm).version,\n \"@trackunit/iris-app-api\": (await irisAppApiPackageJsonFromNpm).version,\n };\n\n const irisAppSdkVitePackageJsonFromNpm = getPackageManifest(\"@trackunit/iris-app-sdk-vite\");\n const reactCoreContextsTestPackageJsonFromNpm = getPackageManifest(\"@trackunit/react-core-contexts-test\");\n const reactTestSetupPackageJsonFromNpm = getPackageManifest(\"@trackunit/react-test-setup\");\n\n const tuDevDependencies = {\n \"@trackunit/iris-app-sdk-vite\": (await irisAppSdkVitePackageJsonFromNpm).version,\n \"@trackunit/react-core-contexts-test\": (await reactCoreContextsTestPackageJsonFromNpm).version,\n \"@trackunit/react-test-setup\": (await reactTestSetupPackageJsonFromNpm).version,\n };\n\n addDependenciesToPackageJson(\n tree,\n {\n ...tuDependencies,\n \"@apollo/client\": \"3.14.1\",\n graphql: \"16.10.0\",\n \"@tanstack/react-router\": \"1.114.29\",\n tslib: \"2.4.0\",\n react: \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n \"single-spa-react\": \"5.1.4\",\n },\n {\n ...tuDevDependencies,\n nx: \"23.1.0\",\n \"@nx/react\": \"23.1.0\",\n \"@nx/workspace\": \"23.1.0\",\n \"@nx/devkit\": \"23.1.0\",\n \"@nx/eslint-plugin\": \"23.1.0\",\n \"@types/react\": \"19.0.8\",\n eslint: \"9.33.0\",\n \"eslint-plugin-react-hooks\": \"7.0.1\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-import\": \"2.32.0\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"typescript-eslint\": \"8.58.1\",\n typescript: \"6.0.2\",\n }\n );\n\n updateJson(tree, \"package.json\", packageJson => {\n packageJson.overrides = {\n react: \"19.0.0\", // to avoid resolution warnings when running npm install\n \"react-dom\": \"19.0.0\", // fix resolution warnings and test\n \"zod-validation-error\": \"4.0.2\",\n };\n return packageJson;\n });\n }\n addProjectConfiguration(tree, normalizedOptions.projectName, {\n root: normalizedOptions.projectRoot,\n projectType: \"application\",\n sourceRoot: `${normalizedOptions.projectRoot}/src`,\n targets: {\n build: {\n executor: \"@trackunit/iris-app-sdk-vite:build\",\n dependsOn: [\n {\n target: \"build\",\n params: \"forward\",\n dependencies: true,\n },\n ],\n options: {\n viteConfig: `${normalizedOptions.projectRoot}/vite.config.ts`,\n outputPath: `dist/${normalizedOptions.projectRoot}`,\n },\n outputs: [\"{options.outputPath}\"],\n },\n serve: {\n executor: \"@trackunit/iris-app-sdk-vite:serve\",\n options: {\n viteConfig: `${normalizedOptions.projectRoot}/vite.config.ts`,\n },\n outputs: [\"{options.outputPath}\"],\n },\n submitApp: {\n executor: \"@trackunit/iris-app:submit\",\n dependsOn: [\"build\"],\n options: {\n inputPath: `dist/${normalizedOptions.projectRoot}`,\n },\n outputs: [`{workspaceRoot}/dist/${normalizedOptions.projectRoot}`],\n },\n unpublishApp: {\n executor: \"@trackunit/iris-app:unpublish\",\n options: {\n inputPath: `dist/${normalizedOptions.projectRoot}`,\n },\n dependsOn: [\n {\n target: \"build\",\n },\n ],\n outputs: [`{workspaceRoot}/dist/${normalizedOptions.projectRoot}`],\n },\n },\n });\n addFiles(tree, normalizedOptions, packageJsonLocally);\n // enforcing engine versions specified in package.json\n tree.write(\".npmrc\", \"engine-strict=true\\n\");\n\n await formatFiles(tree);\n return () => {\n installPackagesTask(tree, true);\n\n // eslint-disable-next-line no-console\n console.log(\n \"🥳 Successfully created an Iris App - review the iris-app-manifest.ts and start adding app extensions!\"\n );\n };\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/extend/dependencies.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,eAAe,GAAG;IAC7B,wBAAwB,EAAE,UAAU;IACpC,YAAY,EAAE,QAAQ;IACtB,kBAAkB,EAAE,OAAO;CAC5B,CAAC;AAEW,QAAA,gBAAgB,GAAG;IAC9B,UAAU,EAAE,QAAQ;IACpB,wBAAwB,EAAE,QAAQ;IAClC,sBAAsB,EAAE,SAAS;IACjC,IAAI,EAAE,QAAQ;IACd,wBAAwB,EAAE,QAAQ;IAClC,qBAAqB,EAAE,QAAQ;IAC/B,iBAAiB,EAAE,QAAQ;IAC3B,SAAS,EAAE,QAAQ;CACpB,CAAC","sourcesContent":["/*\n * Use this file to maintain the version of single-spa and related dependencies.\n * Versions in here should be in sync with the versions in manager package.json.\n * If the test fails, update this file to reflect the version in manager package.json file.\n */\n\nexport const spaDependencies = {\n \"@tanstack/react-router\": \"1.114.29\",\n \"single-spa\": \"^5.9.5\",\n \"single-spa-react\": \"5.1.4\",\n};\n\nexport const testDependencies = {\n \"@nx/jest\": \"23.1.0\",\n \"@testing-library/react\": \"16.2.0\",\n \"@testing-library/dom\": \"^10.4.0\",\n jest: \"30.3.0\",\n \"jest-environment-jsdom\": \"30.0.5\",\n \"jest-transform-stub\": \"^2.0.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"ts-jest\": \"29.4.9\",\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/extend/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addDependenciesToPackageJson,\n formatFiles,\n generateFiles,\n getWorkspaceLayout,\n installPackagesTask,\n joinPathFragments,\n names,\n offsetFromRoot,\n Tree,\n updateJson,\n} from \"@nx/devkit\";\nimport { Linter } from \"@nx/eslint\";\nimport { getRootTsConfigPathInTree } from \"@nx/js\";\nimport { getNpmScope } from \"@nx/js/internal\";\nimport { libraryGenerator } from \"@nx/react\";\nimport { nonUiExtensionTypes, serverSideExtensionTypes } from \"@trackunit/iris-app-api\";\nimport { addGraphqlGenerator } from \"@trackunit/react-graphql-tools\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { camelCase } from \"string-ts\";\nimport { Project, SyntaxKind, VariableDeclaration } from \"ts-morph\";\nimport { addRequireStatement, addSpreadAssignment } from \"../../utils/ast/astUtils\";\nimport { getPackageManifest } from \"../utils/get-package-manifest\";\nimport { spaDependencies, testDependencies } from \"./dependencies\";\nimport { IrisAppExtensionGeneratorSchema } from \"./schema\";\n\ntype Schema = Parameters<typeof libraryGenerator>[1];\n\ninterface NormalizedSchema extends IrisAppExtensionGeneratorSchema {\n projectName: string;\n projectRoot: string;\n projectDirectory: string;\n projectCamelcase: string;\n importPath: string;\n sourceRoot: string;\n dependencyDefinitionFile: string;\n}\n\ntype ServersideGraphqlOptions = {\n readonly projectName: string;\n readonly projectRoot: string;\n readonly className: string;\n readonly serversideUtilsVersion: string;\n};\n\ntype ProjectTarget = {\n dependsOn?: Array<string | Record<string, unknown>>;\n};\n\ntype ProjectJson = {\n targets: Record<string, ProjectTarget>;\n};\n\ntype DependencyPackageJson = {\n dependencies?: Record<string, string>;\n};\n\nconst addGraphqlDependency = (target: ProjectTarget | undefined): void => {\n if (!target) {\n return;\n }\n\n const dependsOn = target.dependsOn ?? [];\n if (!dependsOn.includes(\"graphql-hooks\")) {\n target.dependsOn = [...dependsOn, \"graphql-hooks\"];\n }\n};\n\n/**\n * Adds public-schema codegen and a typed Hono example to a generated serverside extension.\n */\nexport const addServersideGraphql = async (tree: Tree, options: ServersideGraphqlOptions): Promise<void> => {\n await addGraphqlGenerator(tree, {\n project: options.projectName,\n schemaSource: \"public\",\n generateMocks: false,\n });\n\n generateFiles(tree, path.join(__dirname, \"files\", \"SERVERSIDE_API_EXTENSION_GRAPHQL\"), options.projectRoot, {\n ...options,\n template: \"\",\n });\n\n updateJson<ProjectJson>(tree, joinPathFragments(options.projectRoot, \"project.json\"), projectJson => {\n addGraphqlDependency(projectJson.targets.build);\n addGraphqlDependency(projectJson.targets.test);\n addGraphqlDependency(projectJson.targets.serve);\n addGraphqlDependency(projectJson.targets[\"tsc-validate\"]);\n return projectJson;\n });\n\n updateJson<DependencyPackageJson>(tree, joinPathFragments(options.projectRoot, \"package.json\"), packageJson => {\n packageJson.dependencies = {\n ...packageJson.dependencies,\n \"@trackunit/serverside-utils\": options.serversideUtilsVersion,\n };\n return packageJson;\n });\n};\n\nconst getPackageVersion = async (packageName: string): Promise<string> =>\n (await getPackageManifest(packageName)).version;\n\nfunction normalizeOptions(tree: Tree, options: IrisAppExtensionGeneratorSchema): NormalizedSchema {\n const name = names(options.name).fileName;\n const projectDirectory = options.directory ? `${names(options.directory).fileName}/${name}` : name;\n const projectName = projectDirectory.replace(new RegExp(\"/\", \"g\"), \"-\");\n const projectCamelcase = camelCase(projectName);\n const wsLayout = getWorkspaceLayout(tree);\n const projectRoot = `${wsLayout.libsDir}/${projectDirectory}`;\n const sourceRoot = `${wsLayout.libsDir}/${projectDirectory}/src`;\n const dependencyDefinitionFile = `${wsLayout.libsDir}/${projectDirectory}/package.json`;\n\n const npmScope = getNpmScope(tree);\n if (!npmScope) {\n throw new Error(\"Could not find npm scope in package.json\");\n }\n const importPath = `@${npmScope}/${projectName}`;\n\n return {\n ...options,\n projectName,\n projectRoot,\n projectDirectory,\n projectCamelcase,\n importPath,\n sourceRoot,\n dependencyDefinitionFile,\n };\n}\n\n/**\n * Ensures that jest.preset.js exists and includes the required @trackunit/react-test-setup preset.\n * If the file doesn't exist, creates it. If it exists but doesn't include the preset, updates it.\n */\nexport function ensureJestPresetConfiguration(tree: Tree, templateOptions?: object): void {\n const jestPresetPath = \"jest.preset.js\";\n\n if (!tree.exists(jestPresetPath)) {\n // File doesn't exist, generate it using the template\n generateFiles(tree, path.join(__dirname, \"files\", \"preset\"), \"/\", templateOptions || {});\n return;\n }\n\n // File exists, use AST utilities for reliable manipulation\n let currentContent = tree.read(jestPresetPath, \"utf-8\");\n if (!currentContent) {\n throw new Error(`Could not read ${jestPresetPath}`);\n }\n\n // Extract variable name from existing import if it exists\n let presetVariableName = \"irisPreset\"; // default name\n const existingImportMatch = currentContent.match(\n /const\\s+(\\w+)\\s*=\\s*require\\([\"']@trackunit\\/react-test-setup\\/preset[\"']\\)/\n );\n if (existingImportMatch && existingImportMatch[1]) {\n presetVariableName = existingImportMatch[1];\n }\n\n // Add the require statement if it doesn't exist\n currentContent = addRequireStatement(currentContent, presetVariableName, \"@trackunit/react-test-setup/preset\");\n\n // Add the spread assignment to the module.exports object\n currentContent = addSpreadAssignment(currentContent, presetVariableName);\n\n // Write the updated content back to the tree\n tree.write(jestPresetPath, currentContent);\n}\n\n/**\n * Iris App Extension Generator.\n *\n * @param tree the nx tree\n * @param options the generator options\n * @returns { Promise<void> } void\n */\nexport const IrisAppExtensionGenerator = async function (tree: Tree, options: IrisAppExtensionGeneratorSchema) {\n const adjustedOptions = await updateAppName(tree, options);\n\n const normalizedOptions = normalizeOptions(tree, adjustedOptions);\n\n const templateOptions = {\n ...normalizedOptions,\n ...names(normalizedOptions.name),\n offsetFromRoot: offsetFromRoot(normalizedOptions.projectRoot),\n template: \"\",\n };\n const irisAppExtensionType = normalizedOptions.type;\n\n if (normalizedOptions.graphql && irisAppExtensionType !== \"SERVERSIDE_API_EXTENSION\") {\n throw new Error(\"GraphQL setup is only supported for SERVERSIDE_API_EXTENSION\");\n }\n\n if (!tree.exists(`${getWorkspaceLayout(tree).appsDir}/${normalizedOptions.app}`)) {\n throw new Error(\n `The app does not exist: ${getWorkspaceLayout(tree).appsDir}/${\n normalizedOptions.app\n } make sure you enter the right app name`\n );\n }\n\n const manifestPath = `${getWorkspaceLayout(tree).appsDir}/${normalizedOptions.app}/iris-app-manifest.ts`;\n if (!tree.exists(manifestPath)) {\n throw new Error(\n `The app does not have an iris-app-manifest.ts: ${manifestPath} make sure you enter the right app name, which has an iris-app-manifest.ts`\n );\n }\n\n if (normalizedOptions.updatePackageJson) {\n addDependenciesToPackageJson(\n tree,\n {},\n {\n ...spaDependencies,\n ...testDependencies,\n }\n );\n }\n\n const schema: Schema = {\n name: normalizedOptions.projectName,\n style: \"none\",\n skipFormat: false,\n strict: true,\n // Nx 23 warns that \"jest\" emits the deprecated @nx/jest:jest target, but unlike\n // createSubgraph this generator has no jest.config/tsconfig.spec templates of its\n // own and updates the generated tsconfig.spec.json below. Switching to \"none\"\n // requires shipping those templates first.\n unitTestRunner: \"jest\",\n linter: Linter.EsLint,\n routing: false,\n directory: normalizedOptions.projectRoot,\n skipTsConfig: false,\n skipPackageJson: true,\n };\n\n await libraryGenerator(tree, schema);\n\n generateFiles(\n tree,\n path.join(__dirname, \"files\", irisAppExtensionType),\n normalizedOptions.projectRoot,\n templateOptions\n );\n\n if (!nonUiExtensionTypes.includes(irisAppExtensionType)) {\n generateFiles(tree, path.join(__dirname, \"files\", \"react-app\"), normalizedOptions.projectRoot, templateOptions);\n if (normalizedOptions.extendJestPreset) {\n ensureJestPresetConfiguration(tree, templateOptions);\n }\n }\n\n const rootTsConfigPath = getRootTsConfigPathInTree(tree);\n if (!rootTsConfigPath) {\n throw new Error(\"Could not find root tsconfig.json\");\n }\n updateJson(tree, rootTsConfigPath, tsConfigBase => {\n // For server side extension types, we need to add deno types to the tsconfig and make Typescript accept Deno import syntax\n if (serverSideExtensionTypes.includes(irisAppExtensionType)) {\n tsConfigBase.compilerOptions = {\n ...tsConfigBase.compilerOptions,\n types: [\"node\"],\n esModuleInterop: true,\n };\n }\n\n tsConfigBase.compilerOptions.paths[normalizedOptions.importPath] = [\n path.join(normalizedOptions.projectRoot, \"extension-manifest.ts\"),\n ];\n return tsConfigBase;\n });\n\n // Add working serve target to the project.json for DENO extensions\n if (serverSideExtensionTypes.includes(irisAppExtensionType)) {\n updateJson(tree, joinPathFragments(normalizedOptions.projectRoot, \"project.json\"), projectJson => {\n projectJson.targets.serve = {\n executor: \"@nx/js:node\",\n options: {\n buildTarget: `${normalizedOptions.projectName}:build:development`,\n inspect: true,\n },\n configurations: {\n breakOnStart: {\n inspect: \"inspect-brk\",\n },\n },\n };\n projectJson.targets.build = {\n executor: \"@nx/esbuild:esbuild\",\n outputs: [\"{options.outputPath}\"],\n defaultConfiguration: \"production\",\n options: {\n platform: \"node\",\n outputPath: `dist/${normalizedOptions.projectRoot}`,\n format: [\"cjs\"],\n bundle: true,\n thirdParty: true,\n external: [],\n main: `${normalizedOptions.sourceRoot}/index.ts`,\n tsConfig: `libs/${normalizedOptions.projectDirectory}/tsconfig.lib.json`,\n esbuildOptions: {\n sourcemap: true,\n outExtension: {\n \".js\": \".js\",\n },\n },\n },\n configurations: {\n development: {\n main: `${normalizedOptions.sourceRoot}/local-serve.ts`,\n },\n production: {\n esbuildOptions: {\n sourcemap: false,\n outExtension: {\n \".js\": \".js\",\n },\n },\n },\n },\n };\n return projectJson;\n });\n }\n\n if (normalizedOptions.graphql) {\n await addServersideGraphql(tree, {\n projectName: normalizedOptions.projectName,\n projectRoot: normalizedOptions.projectRoot,\n className: names(normalizedOptions.name).className,\n serversideUtilsVersion: await getPackageVersion(\"@trackunit/serverside-utils\"),\n });\n }\n\n //TODO: Change the following to update the manifest in the virtual Tree - not on the file system.\n const project = new Project({\n tsConfigFilePath: `${getWorkspaceLayout(tree).appsDir}/${normalizedOptions.app}/tsconfig.app.json`,\n });\n\n const manifest = project.getSourceFileOrThrow(manifestPath);\n\n manifest.addImportDeclaration({\n moduleSpecifier: normalizedOptions.importPath,\n defaultImport: normalizedOptions.projectCamelcase,\n });\n\n // Get the default export symbol from the manifest\n const defaultExportSymbol = manifest.getDefaultExportSymbolOrThrow();\n\n // Get the aliased symbol if the default export is an alias\n const aliasedSymbol = defaultExportSymbol.getAliasedSymbol() || defaultExportSymbol;\n\n // Get the declaration of the aliased symbol\n const declaration = aliasedSymbol.getDeclarations()[0];\n\n if (!VariableDeclaration.isVariableDeclaration(declaration)) {\n throw new Error(\"Expected variable declaration\");\n }\n const irisAppManifestObject = declaration.getInitializer()?.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);\n\n if (!irisAppManifestObject) {\n throw new Error(`irisAppManifest not exported from the file: ${manifestPath}`);\n }\n // Find the extensions property within the irisAppManifest object\n const extensionsProperty = irisAppManifestObject.getPropertyOrThrow(\"extensions\");\n\n if (extensionsProperty.getKind() === SyntaxKind.PropertyAssignment) {\n const extensionsArray = extensionsProperty.getFirstChildByKindOrThrow(SyntaxKind.ArrayLiteralExpression);\n extensionsArray.addElement(`${normalizedOptions.projectCamelcase}`);\n }\n\n await manifest.save();\n\n if (!serverSideExtensionTypes.includes(irisAppExtensionType)) {\n tree.delete(joinPathFragments(normalizedOptions.projectRoot, \"src\", \"index.ts\"));\n }\n\n updateJson(tree, joinPathFragments(normalizedOptions.projectRoot, \"tsconfig.spec.json\"), tsConfigSpec => {\n // extension-manifest.ts is a build time file, so we only need to include it in the spec file for type/lint checking\n tsConfigSpec.include = [...tsConfigSpec.include, \"**/jest.setup.ts*\", \"extension-manifest.ts\"];\n return tsConfigSpec;\n });\n\n await formatFiles(tree);\n installPackagesTask(tree, true);\n return () => {\n // eslint-disable-next-line no-console\n console.log(\"🥳 Successfully created an app extensions and it is already added to the Iris App!\");\n };\n};\nconst updateAppName = async (tree: Tree, options: IrisAppExtensionGeneratorSchema) => {\n if (!options.app) {\n const folders = fs\n .readdirSync(getWorkspaceLayout(tree).appsDir, { withFileTypes: true })\n .filter(item => item.isDirectory());\n\n const tileApps: Array<string> = [];\n\n folders.forEach(folder => {\n const irisAppManifest = fs\n .readdirSync(`${getWorkspaceLayout(tree).appsDir}/${folder.name}`, { withFileTypes: true })\n .find(item => item.name === \"iris-app-manifest.ts\");\n\n if (irisAppManifest) {\n tileApps.push(folder.name);\n } else {\n const subFolders = fs\n .readdirSync(path.join(getWorkspaceLayout(tree).appsDir, folder.name), { withFileTypes: true })\n .filter(item => item.isDirectory());\n subFolders.forEach(subFolder => {\n const subDirIrisAppManifest = fs\n .readdirSync(`${getWorkspaceLayout(tree).appsDir}/${folder.name}/${subFolder.name}`, {\n withFileTypes: true,\n })\n .find(item => item.name === \"iris-app-manifest.ts\");\n\n if (subDirIrisAppManifest) {\n tileApps.push(path.join(folder.name, subFolder.name));\n }\n });\n }\n });\n\n if (tileApps.length === 1) {\n options.app = tileApps[0] || \"<Missing iris app name>\";\n } else if (tileApps.length === 0) {\n throw new Error(\"Please add an iris-app using: nx g @trackunit/iris-app:create \");\n } else {\n // Dynamic import to avoid loading ESM module at test time when not needed\n const { autocomplete, isCancel, cancel } = await import(\"@clack/prompts\");\n\n const selectedApp = await autocomplete({\n message: \"Select the iris app that this extension should belong to (type to filter):\",\n options: tileApps.map(item => ({ value: item, label: item })),\n maxItems: 15,\n });\n\n if (isCancel(selectedApp)) {\n cancel(\"Operation cancelled.\");\n process.exit(0);\n }\n\n options.app = selectedApp;\n }\n }\n return options;\n};\n"]}
@@ -6,6 +6,7 @@ const devkit_1 = require("@nx/devkit");
6
6
  const js_1 = require("@nx/js");
7
7
  const react_1 = require("@nx/react");
8
8
  const path_1 = tslib_1.__importDefault(require("path"));
9
+ const get_package_manifest_1 = require("../utils/get-package-manifest");
9
10
  const link_claude_skills_1 = require("../utils/link-claude-skills");
10
11
  /**
11
12
  * Preset generator for Iris apps workspace.
@@ -44,17 +45,14 @@ async function presetGenerator(tree, options) {
44
45
  tsconfig.compilerOptions.moduleResolution = "bundler";
45
46
  return tsconfig;
46
47
  });
48
+ // Ships the generator that upgrades every @trackunit/* dependency, so a new
49
+ // workspace can run the documented upgrade flow without installing it first.
50
+ const migrationsVersion = (await (0, get_package_manifest_1.getPackageManifest)("@trackunit/migrations")).version;
47
51
  (0, devkit_1.addDependenciesToPackageJson)(tree, {
48
52
  react: "19.0.0",
49
53
  "react-dom": "19.0.0",
50
- }, {});
51
- // Add update script for @trackunit packages
52
- (0, devkit_1.updateJson)(tree, "package.json", (pkgJson) => {
53
- if (!pkgJson.scripts) {
54
- pkgJson.scripts = {};
55
- }
56
- pkgJson.scripts["update:trackunit"] = 'npx npm-check-updates "/@trackunit/" -u';
57
- return pkgJson;
54
+ }, {
55
+ "@trackunit/migrations": migrationsVersion,
58
56
  });
59
57
  // This react generator adds react 19 and react-dom 19 to the package.json if we don't add react 18 above.
60
58
  const initReact = await (0, react_1.reactInitGenerator)(tree, {});
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/preset/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Tree,\n addDependenciesToPackageJson,\n generateFiles,\n logger,\n readNxJson,\n runTasksInSerial,\n updateJson,\n updateNxJson,\n} from \"@nx/devkit\";\nimport { initGenerator as jsInitGenerator } from \"@nx/js\";\nimport { reactInitGenerator } from \"@nx/react\";\nimport path from \"path\";\nimport { getPackageManifest } from \"../utils/get-package-manifest\";\nimport { linkClaudeSkills } from \"../utils/link-claude-skills\";\nimport { PresetGeneratorSchema } from \"./schema\";\n\n/**\n * Preset generator for Iris apps workspace.\n * Use with create-nx-workspace to create a new workspace for developing Iris apps.\n * ```npx create-nx-workspace --preset=iris-app```\n */\nexport async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) {\n // setup workspace\n updateWorkspaceLayout(tree);\n tree.write(\n \"apps/readme.md\",\n `# Apps\\n\\nThis folder contains all apps in the workspace.\\n\\nApps are the main entry point for the Iris App SDK.\\nCreate an app by running \\`nx g @trackunit/iris-app:create <app-name>\\`.`\n );\n tree.write(\n \"libs/readme.md\",\n `# Libs\\n\\nThis folder contains all libs in the workspace.\\nCreate a lib by running \\`nx g @trackunit/iris-app:extend <lib-name>\\`.`\n );\n\n const extensionsPath = \".vscode/extensions.json\";\n\n if (!tree.exists(extensionsPath)) {\n tree.write(extensionsPath, \"{}\");\n }\n\n generateFiles(tree, path.join(__dirname, \"files\"), \".\", {});\n\n updateJson(tree, extensionsPath, value => {\n if (!value.recommendations) {\n value.recommendations = [];\n }\n value.recommendations.push(\n \"graphql.vscode-graphql\",\n \"graphql.vscode-graphql-syntax\",\n \"bradlc.vscode-tailwindcss\",\n \"firsttris.vscode-jest-runner\"\n );\n return value;\n });\n\n const jsInitTask = await jsInitGenerator(tree, {\n ...options,\n tsConfigName: \"tsconfig.base.json\",\n skipFormat: true,\n });\n\n updateJson(tree, \"tsconfig.base.json\", (tsconfig: { compilerOptions?: Record<string, unknown> }) => {\n if (!tsconfig.compilerOptions) {\n tsconfig.compilerOptions = {};\n }\n tsconfig.compilerOptions.ignoreDeprecations = \"6.0\";\n tsconfig.compilerOptions.esModuleInterop = true;\n tsconfig.compilerOptions.resolveJsonModule = true;\n tsconfig.compilerOptions.moduleResolution = \"bundler\";\n return tsconfig;\n });\n\n // Ships the generator that upgrades every @trackunit/* dependency, so a new\n // workspace can run the documented upgrade flow without installing it first.\n const migrationsVersion = (await getPackageManifest(\"@trackunit/migrations\")).version;\n\n addDependenciesToPackageJson(\n tree,\n {\n react: \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n },\n {\n \"@trackunit/migrations\": migrationsVersion,\n }\n );\n\n // This react generator adds react 19 and react-dom 19 to the package.json if we don't add react 18 above.\n const initReact = await reactInitGenerator(tree, {});\n\n // Post-flush task: symlink .claude/skills -> ../.agents/skills so Claude Code\n // auto-discovers the same skills as Cursor/Codex without manual setup.\n const linkSkillsTask = () => {\n const result = linkClaudeSkills(tree.root);\n if (result.status === \"skipped\") {\n logger.warn(\n `[iris-app:preset] Skipped creating .claude/skills symlink: ${result.reason}. ` +\n `Claude Code users may need to create it manually: ln -s ../.agents/skills .claude/skills`\n );\n }\n };\n\n return runTasksInSerial(jsInitTask, initReact, linkSkillsTask);\n}\n\nfunction updateWorkspaceLayout(tree: Tree) {\n const nxJson = readNxJson(tree) ?? {};\n nxJson.workspaceLayout = {\n libsDir: \"libs\",\n appsDir: \"apps\",\n };\n updateNxJson(tree, nxJson);\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-package-manifest.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/utils/get-package-manifest.ts"],"names":[],"mappings":";;;;AAAA,uDAAiC;AAEjC;;GAEG;AACI,MAAM,kBAAkB,GAAG,CAAC,WAAmB,EAAE,EAAE,CACxD,MAAM,CAAC,QAAQ,CACb,WAAW,EACX,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,SAAS,CACpF,CAAC;AAJS,QAAA,kBAAkB,sBAI3B","sourcesContent":["import * as pacote from \"pacote\";\n\n/**\n * Keeps Trackunit registry overrides consistent across package-consuming generators.\n */\nexport const getPackageManifest = (packageName: string) =>\n pacote.manifest(\n packageName,\n process.env.TU_NPM_REGISTRY ? { registry: process.env.TU_NPM_REGISTRY } : undefined\n );\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-claude-skills.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/utils/link-claude-skills.ts"],"names":[],"mappings":";;AAqBA,4CA0CC;;AA/DD,+CAAyB;AACzB,mDAA6B;AAE7B,MAAM,UAAU,GAAG,SAAS,CAAC;AAC7B,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AACpC,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAO/D;;;;;;;;GAQG;AACH,SAAgB,gBAAgB,CAAC,aAAqB;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEtE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;IACxE,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,aAAa,EAAE,cAAc,EAAE,EAAE,CAAC;QACpC,MAAM,aAAa,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAChD,IACE,oBAAoB,CAAC;YACnB,aAAa;YACb,cAAc,EAAE,SAAS;SAC1B,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EACpC,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACtC,CAAC;QACD,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,iDAAiD,aAAa,EAAE;SACzE,CAAC;IACJ,CAAC;SAAM,IAAI,aAAa,EAAE,CAAC;QACzB,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,sCAAsC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE;SACnG,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,EAAE,CAAC,WAAW,CAAC,iBAAiB,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QACnD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC9F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAOD,SAAS,oBAAoB,CAAC,EAAE,aAAa,EAAE,cAAc,EAA6B;IACxF,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;AACrD,CAAC","sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nconst CLAUDE_DIR = \".claude\";\nconst CLAUDE_SKILLS_NAME = \"skills\";\nconst AGENTS_SKILLS_REL = path.join(\"..\", \".agents\", \"skills\");\n\nexport type LinkClaudeSkillsResult =\n | { status: \"created\" }\n | { status: \"already-linked\" }\n | { status: \"skipped\"; reason: string };\n\n/**\n * Ensures `.claude/skills` is a symlink to `../.agents/skills` so Claude Code\n * auto-discovers skills shared via `.agents/skills`.\n *\n * Idempotent: leaves an existing valid symlink alone, refuses to overwrite a\n * real `.claude/skills` directory or file. Cross-platform-safe: catches\n * symlink permission errors (e.g. Windows without Developer Mode) and returns\n * a `skipped` result instead of throwing.\n */\nexport function linkClaudeSkills(workspaceRoot: string): LinkClaudeSkillsResult {\n const claudeDir = path.join(workspaceRoot, CLAUDE_DIR);\n const linkPath = path.join(claudeDir, CLAUDE_SKILLS_NAME);\n const agentsSkillsAbs = path.join(workspaceRoot, \".agents\", \"skills\");\n\n if (!fs.existsSync(agentsSkillsAbs)) {\n return { status: \"skipped\", reason: \".agents/skills does not exist\" };\n }\n\n fs.mkdirSync(claudeDir, { recursive: true });\n\n const existingLstat = safeLstat(linkPath);\n if (existingLstat?.isSymbolicLink()) {\n const currentTarget = fs.readlinkSync(linkPath);\n if (\n resolveSymlinkTarget({\n currentTarget,\n linkParentPath: claudeDir,\n }) === path.resolve(agentsSkillsAbs)\n ) {\n return { status: \"already-linked\" };\n }\n return {\n status: \"skipped\",\n reason: `.claude/skills already exists as a symlink to ${currentTarget}`,\n };\n } else if (existingLstat) {\n return {\n status: \"skipped\",\n reason: `.claude/skills already exists as a ${existingLstat.isDirectory() ? \"directory\" : \"file\"}`,\n };\n }\n\n try {\n fs.symlinkSync(AGENTS_SKILLS_REL, linkPath, \"dir\");\n return { status: \"created\" };\n } catch (error) {\n return {\n status: \"skipped\",\n reason: `failed to create symlink: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n}\n\nfunction safeLstat(p: string): fs.Stats | undefined {\n try {\n return fs.lstatSync(p);\n } catch {\n return undefined;\n }\n}\n\ntype ResolveSymlinkTargetInput = {\n readonly currentTarget: string;\n readonly linkParentPath: string;\n};\n\nfunction resolveSymlinkTarget({ currentTarget, linkParentPath }: ResolveSymlinkTargetInput): string {\n if (path.isAbsolute(currentTarget)) {\n return path.resolve(currentTarget);\n }\n\n return path.resolve(linkParentPath, currentTarget);\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app/src/index.ts"],"names":[],"mappings":";;;;AAAA,mEAAkE;AAAzD,gHAAA,cAAc,OAAA;AACvB,iFAAsE;AAA7D,oHAAA,WAAW,OAAA;AAEpB,2DAAiE;AAAxD,6GAAA,gBAAgB,OAAA;AAEzB,2DAA0E;AAAjE,sHAAA,yBAAyB,OAAA;AAElC,+DAAqC;AACrC,8DAAoC","sourcesContent":["export { getAccessToken } from \"./executors/utils/authentication\";\nexport { getSettings } from \"./executors/utils/irisAppServerSettings\";\nexport type { Settings } from \"./executors/utils/irisAppServerSettings\";\nexport { IrisAppGenerator } from \"./generators/create/generator\";\nexport type { IrisAppGeneratorSchema } from \"./generators/create/schema\";\nexport { IrisAppExtensionGenerator } from \"./generators/extend/generator\";\nexport type { IrisAppExtensionGeneratorSchema } from \"./generators/extend/schema\";\nexport * from \"./utils/ast/astUtils\";\nexport * from \"./utils/fileUpdater\";\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"astUtils.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/utils/ast/astUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import { tsquery } from \"@phenomnomnominal/tsquery\";\nimport { objectEntries } from \"@trackunit/shared-utils\";\nimport * as ts from \"typescript\";\n\n/**\n * This function removes a property with a given name from an object literal\n * provided as a text string.\n *\n * @param {string} fileContent The source code as text\n * @param {string} propertyNames The properties to remove from the object\n */\nexport function removePropertyWithName(fileContent: string, ...propertyNames: Array<string>) {\n const sourceFile = tsquery.ast(fileContent);\n const updatedSourceFile = tsquery.map(sourceFile, \"ObjectLiteralExpression\", node => {\n if (ts.isObjectLiteralExpression(node)) {\n // Filter out the given property\n const updatedProperties = node.properties.filter(property => {\n return !(\n ts.isPropertyAssignment(property) &&\n ts.isIdentifier(property.name) &&\n propertyNames.includes(property.name.text)\n );\n });\n return ts.factory.createObjectLiteralExpression(updatedProperties, true);\n }\n return node;\n });\n return ts.createPrinter().printFile(updatedSourceFile);\n}\n\n/**\n * This function adds a new property with a given name and value to an object literal\n * provided as a text string.\n *\n * @param {string} fileContent - the source code as text\n * @param {string} propertyName - the name of the property to add\n * @param {string | string[]} propertyValue - the value of the property to add\n */\nexport function addPropertyWithName(\n fileContent: string,\n propertyName: string,\n propertyValue: string | Array<string> | Record<string, string>\n) {\n const sourceFile = tsquery.ast(fileContent);\n const updatedSourceFile = tsquery.map(sourceFile, \"ObjectLiteralExpression\", node => {\n if (ts.isObjectLiteralExpression(node)) {\n // Add a new property to the object literal\n let updatedProperties;\n if (typeof propertyValue === \"string\") {\n updatedProperties = [\n ...node.properties,\n ts.factory.createPropertyAssignment(\n ts.factory.createIdentifier(propertyName),\n ts.factory.createStringLiteral(propertyValue)\n ),\n ];\n } else if (Array.isArray(propertyValue)) {\n const arrayLiteral = ts.factory.createArrayLiteralExpression(\n propertyValue.map(value => ts.factory.createStringLiteral(value))\n );\n updatedProperties = [\n ...node.properties,\n ts.factory.createPropertyAssignment(ts.factory.createIdentifier(propertyName), arrayLiteral),\n ];\n } else if (typeof propertyValue === \"object\") {\n updatedProperties = [\n ...node.properties,\n ts.factory.createPropertyAssignment(\n ts.factory.createIdentifier(propertyName),\n ts.factory.createObjectLiteralExpression(createObjectLiteralElementLike(propertyValue))\n ),\n ];\n }\n return ts.factory.createObjectLiteralExpression(updatedProperties, true);\n }\n return node;\n });\n return ts.createPrinter().printFile(updatedSourceFile);\n}\n\n/**\n * This function adds a spread assignment to an object literal.\n *\n * @param {string} fileContent - the source code as text\n * @param {string} variableName - the name of the variable to spread\n */\nexport function addSpreadAssignment(fileContent: string, variableName: string) {\n const sourceFile = tsquery.ast(fileContent);\n\n // First check if the spread already exists\n const existingSpreads = tsquery(sourceFile, \"SpreadAssignment\");\n const hasExistingSpread = existingSpreads.some(spread => {\n if (ts.isSpreadAssignment(spread)) {\n return spread.expression.getText() === variableName;\n }\n return false;\n });\n\n if (hasExistingSpread) {\n return fileContent; // Already has the spread, no changes needed\n }\n\n const updatedSourceFile = tsquery.map(sourceFile, \"ObjectLiteralExpression\", node => {\n if (ts.isObjectLiteralExpression(node)) {\n // Add the spread assignment to the object literal\n const spreadAssignment = ts.factory.createSpreadAssignment(ts.factory.createIdentifier(variableName));\n const updatedProperties = [...node.properties, spreadAssignment];\n return ts.factory.createObjectLiteralExpression(updatedProperties, true);\n }\n return node;\n });\n return ts.createPrinter().printFile(updatedSourceFile);\n}\n\n/**\n * This function adds a require statement to a file after existing require statements.\n *\n * @param {string} fileContent - the source code as text\n * @param {string} variableName - the name of the variable to assign to\n * @param {string} modulePath - the module path to require\n */\nexport function addRequireStatement(fileContent: string, variableName: string, modulePath: string) {\n const sourceFile = tsquery.ast(fileContent);\n\n // Check if the require statement already exists\n const existingRequires = tsquery(sourceFile, \"CallExpression\");\n const hasExistingRequire = existingRequires.some(call => {\n if (\n ts.isCallExpression(call) &&\n ts.isIdentifier(call.expression) &&\n call.expression.text === \"require\" &&\n call.arguments.length > 0\n ) {\n const firstArg = call.arguments[0];\n if (firstArg && ts.isStringLiteral(firstArg)) {\n return firstArg.text === modulePath;\n }\n }\n return false;\n });\n\n if (hasExistingRequire) {\n return fileContent; // Already has the require, no changes needed\n }\n\n // Find all variable statements with require calls\n const requireStatements = tsquery(sourceFile, \"VariableStatement\").filter(stmt =>\n stmt.getText().includes(\"require(\")\n );\n\n const requireStatement = `const ${variableName} = require(\"${modulePath}\").default;`;\n\n if (requireStatements.length > 0) {\n // Add after the last require statement\n const lastRequire = requireStatements[requireStatements.length - 1];\n if (lastRequire) {\n const lastRequireEnd = lastRequire.getEnd();\n\n return `${fileContent.slice(0, lastRequireEnd)}\\n${requireStatement}${fileContent.slice(lastRequireEnd)}`;\n }\n }\n\n // Add at the beginning if no require statements found\n return `${requireStatement}\\n${fileContent}`;\n}\n\nfunction createObjectLiteralElementLike(obj: Record<string, string>): Array<ts.ObjectLiteralElementLike> {\n const properties: Array<ts.ObjectLiteralElementLike> = [];\n for (const [key, value] of objectEntries(obj)) {\n properties.push(\n ts.factory.createPropertyAssignment(ts.factory.createStringLiteral(key), ts.factory.createStringLiteral(value))\n );\n }\n return properties;\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUpdater.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app/src/utils/fileUpdater.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACI,MAAM,gBAAgB,GAAG,CAAC,IAAU,EAAE,IAAY,EAAE,OAAwC,EAAE,EAAE;IACrG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEpC,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC;AAdW,QAAA,gBAAgB,oBAc3B","sourcesContent":["import { Tree } from \"@nx/devkit\";\n\n/**\n *\n * @param tree File system tree\n * @param path Path to source file in the Tree\n * @param updater Function that maps the current file content to a new to be written to the Tree\n */\nexport const updateFileInTree = (tree: Tree, path: string, updater: (fileContent: string) => string) => {\n if (!tree.exists(path)) {\n throw new Error(`File not found: ${path}`);\n }\n\n const fileContent = tree.read(path, \"utf-8\");\n if (!fileContent) {\n throw new Error(`File is empty: ${path}`);\n }\n const result = updater(fileContent);\n\n if (result !== fileContent) {\n tree.write(path, result);\n }\n};\n"]}