@aws/nx-plugin 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-THIRD-PARTY +11686 -23398
- package/README.md +18 -0
- package/generators.json +7 -0
- package/migrations.json +39 -1
- package/package.json +6 -6
- package/src/agentcore-gateway/agent-connection/generator.js +6 -0
- package/src/agentcore-gateway/agent-connection/generator.js.map +1 -1
- package/src/agentcore-gateway/schema.json +1 -0
- package/src/agentcore-harness/generator.d.ts +1 -1
- package/src/connection/scaffold-catalog.d.ts +21 -0
- package/src/connection/scaffold-catalog.js +14 -6
- package/src/connection/scaffold-catalog.js.map +1 -1
- package/src/infra/app/generator.d.ts +1 -1
- package/src/init/generator.d.ts +1 -1
- package/src/mcp-server/guide-pipeline.d.ts +2 -1
- package/src/mcp-server/guide-pipeline.js +6 -0
- package/src/mcp-server/guide-pipeline.js.map +1 -1
- package/src/mcp-server/mdx-ast.d.ts +7 -0
- package/src/mcp-server/mdx-ast.js +15 -0
- package/src/mcp-server/mdx-ast.js.map +1 -1
- package/src/mcp-server/schema-registry.d.ts +2 -2
- package/src/mcp-server/schema-registry.js +2 -2
- package/src/mcp-server/schema-registry.js.map +1 -1
- package/src/migrations/latest/terraform-harness-environment-variables/metadata.json +3 -0
- package/src/migrations/latest/terraform-harness-environment-variables/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-harness-environment-variables/migration.js +54 -0
- package/src/migrations/latest/terraform-harness-environment-variables/migration.js.map +1 -0
- package/src/open-api/py-client/__snapshots__/generator.additional-properties.spec.ts.snap +34 -0
- package/src/open-api/py-client/__snapshots__/generator.arrays.spec.ts.snap +1750 -0
- package/src/open-api/py-client/__snapshots__/generator.complex-types.spec.ts.snap +82 -0
- package/src/open-api/py-client/__snapshots__/generator.composite-types.spec.ts.snap +447 -0
- package/src/open-api/py-client/__snapshots__/generator.duplicate-types.spec.ts.snap +404 -0
- package/src/open-api/py-client/__snapshots__/generator.errors.spec.ts.snap +430 -0
- package/src/open-api/py-client/__snapshots__/generator.fast-api.spec.ts.snap +447 -0
- package/src/open-api/py-client/__snapshots__/generator.petstore.spec.ts.snap +3488 -0
- package/src/open-api/py-client/__snapshots__/generator.primitive-types.spec.ts.snap +1444 -0
- package/src/open-api/py-client/__snapshots__/generator.request.spec.ts.snap +390 -0
- package/src/open-api/py-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +364 -0
- package/src/open-api/py-client/__snapshots__/generator.response.spec.ts.snap +739 -0
- package/src/open-api/py-client/__snapshots__/generator.streaming.spec.ts.snap +384 -0
- package/src/open-api/py-client/__snapshots__/generator.tags.spec.ts.snap +414 -0
- package/src/open-api/py-client/files/client/__clientModuleName__.py.template +1076 -0
- package/src/open-api/py-client/files/shared/__init__.py.template +28 -0
- package/src/open-api/py-client/files/shared/errors.py.template +37 -0
- package/src/open-api/py-client/files/shared/types.py.template +319 -0
- package/src/open-api/py-client/generator.d.ts +53 -0
- package/src/open-api/py-client/generator.js +119 -0
- package/src/open-api/py-client/generator.js.map +1 -0
- package/src/open-api/py-client/schema.d.js +6 -0
- package/src/open-api/py-client/schema.d.js.map +1 -0
- package/src/open-api/py-client/schema.d.ts +12 -0
- package/src/open-api/py-client/schema.json +28 -0
- package/src/open-api/py-client/vessel-registry-spec.json +2716 -0
- package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +274 -0
- package/src/open-api/ts-client/petstore-spec.d.ts +6 -0
- package/src/open-api/ts-client/petstore-spec.js +1275 -0
- package/src/open-api/ts-client/petstore-spec.js.map +1 -0
- package/src/open-api/ts-hooks/generator.spec.tsx +1 -1
- package/src/open-api/utils/codegen-data/languages.d.ts +68 -2
- package/src/open-api/utils/codegen-data/languages.js +433 -21
- package/src/open-api/utils/codegen-data/languages.js.map +1 -1
- package/src/open-api/utils/codegen-data/types.d.ts +187 -0
- package/src/open-api/utils/codegen-data/types.js +10 -1
- package/src/open-api/utils/codegen-data/types.js.map +1 -1
- package/src/open-api/utils/codegen-data.d.ts +40 -1
- package/src/open-api/utils/codegen-data.js +622 -17
- package/src/open-api/utils/codegen-data.js.map +1 -1
- package/src/open-api/utils/normalise.js +175 -41
- package/src/open-api/utils/normalise.js.map +1 -1
- package/src/open-api/utils/parser.js +1 -1
- package/src/open-api/utils/parser.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/preset/generator.d.ts +1 -1
- package/src/py/agent/gateway-connection/generator.js +0 -3
- package/src/py/agent/gateway-connection/generator.js.map +1 -1
- package/src/py/agent/react-connection/generator.d.ts +1 -1
- package/src/py/agent/schema.json +2 -0
- package/src/py/fast-api/react/generator.d.ts +1 -1
- package/src/py/mcp-server/schema.json +1 -0
- package/src/sdk/open-api.d.ts +2 -0
- package/src/sdk/open-api.js +1 -0
- package/src/sdk/open-api.js.map +1 -1
- package/src/smithy/project/generator.d.ts +1 -1
- package/src/smithy/react-connection/generator.d.ts +1 -1
- package/src/terraform/project/generator.d.ts +1 -1
- package/src/trpc/react/generator.d.ts +1 -1
- package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
- package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
- package/src/ts/agent/gateway-connection/generator.js +0 -3
- package/src/ts/agent/gateway-connection/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
- package/src/ts/agent/react-connection/generator.d.ts +1 -1
- package/src/ts/agent/schema.json +1 -0
- package/src/ts/api/schema.json +2 -0
- package/src/ts/astro-docs/generator.d.ts +1 -1
- package/src/ts/dcr-proxy/generator.d.ts +1 -1
- package/src/ts/dynamodb/generator.d.ts +1 -1
- package/src/ts/lambda-function/generator.d.ts +1 -1
- package/src/ts/lib/generator.d.ts +1 -1
- package/src/ts/mcp-server/schema.json +1 -0
- package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.spec.ts.template +1 -1
- package/src/ts/nx-generator/generator.d.ts +1 -1
- package/src/ts/nx-migration/generator.d.ts +1 -1
- package/src/ts/nx-plugin/generator.d.ts +1 -1
- package/src/ts/rdb/generator.d.ts +1 -1
- package/src/ts/react-website/agui/generator.d.ts +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +10 -10
- package/src/ts/react-website/app/schema.json +1 -0
- package/src/ts/website/app/schema.json +1 -0
- package/src/utils/agent-core-constructs/files/terraform/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.tf.template +1 -1
- package/src/utils/metrics-assertions.d.ts +18 -0
- package/src/utils/metrics-assertions.js +42 -0
- package/src/utils/metrics-assertions.js.map +1 -0
- package/src/utils/test/python-dependencies.d.ts +8 -0
- package/src/utils/test/python-dependencies.js +14 -0
- package/src/utils/test/python-dependencies.js.map +1 -0
- package/src/utils/test/python-worker/worker.py +703 -0
- package/src/utils/test/warm-python-cache.d.ts +18 -0
- package/src/utils/test/warm-python-cache.js +46 -0
- package/src/utils/test/warm-python-cache.js.map +1 -0
- package/src/utils/versions.d.ts +10 -9
- package/src/utils/versions.js +9 -8
- package/src/utils/versions.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/guide-pipeline.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport fs from 'fs';\n/**\n * Unified + remark-mdx pipeline for the MCP `generator-guide` tool.\n *\n * Passes (in order, each over the already-transformed tree):\n * 1. Snippet inlining — `<Snippet name>` → recursive post-process.\n * 2. Filter transforms — `<OptionFilter>`, `<Infrastructure>` slot\n * selection, `<Tabs><TabItem _filter>` pruning.\n * 3. Component transforms — `<NxCommands>` / `<RunGenerator>` /\n * `<GeneratorParameters>` / `<CreateNxWorkspaceCommand>` /\n * `<InstallCommand>` / `<PackageManagerShortCommand>` /\n * `<PackageManagerExecCommand>` render down to markdown.\n */\nimport type { Root, RootContent } from 'mdast';\nimport type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';\nimport {\n buildCreateNxWorkspaceCommand,\n buildInstallCommand,\n buildNxInitCommand,\n buildPackageManagerExecCommand,\n buildPackageManagerShortCommand,\n} from '../utils/commands.js';\nimport type { NxGeneratorInfo } from '../utils/generators.js';\nimport {\n buildNxCommand,\n renderGeneratorCommand,\n renderSchema,\n} from './guide-render.js';\nimport {\n hasBareAttr,\n isJsxElement,\n type JsxElement,\n type JsxParent,\n readEstreeAttr,\n readExpressionAttr,\n readStringAttr,\n} from './mdx-ast.js';\nimport {\n describePredicate,\n evaluatePredicate,\n extractStringArrayExpression,\n type Predicate,\n parseWhenExpression,\n} from './option-filter.js';\n\nexport interface PipelineOptions {\n generators: NxGeneratorInfo[];\n packageManager?: string;\n snippetContentProvider?: (name: string) => Promise<string> | string;\n options?: Record<string, string>;\n}\n\n// unified v11 is ESM-only and this package is CJS; dynamic import + rolldown's\n// `codeSplitting: false` bundles everything into the published MCP binary.\ninterface RemarkDeps {\n unified: typeof import('unified').unified;\n remarkParse: typeof import('remark-parse').default;\n remarkMdx: typeof import('remark-mdx').default;\n remarkStringify: typeof import('remark-stringify').default;\n remarkFrontmatter: typeof import('remark-frontmatter').default;\n}\n\nlet depsPromise: Promise<RemarkDeps> | undefined;\nconst loadRemarkDeps = (): Promise<RemarkDeps> => {\n if (!depsPromise) {\n depsPromise = (async () => ({\n unified: (await import('unified')).unified,\n remarkParse: (await import('remark-parse')).default,\n remarkMdx: (await import('remark-mdx')).default,\n remarkStringify: (await import('remark-stringify')).default,\n remarkFrontmatter: (await import('remark-frontmatter')).default,\n }))();\n }\n return depsPromise;\n};\n\nconst parseMdxWithDeps = (source: string, deps: RemarkDeps): Root =>\n deps\n .unified()\n .use(deps.remarkParse)\n .use(deps.remarkFrontmatter)\n .use(deps.remarkMdx)\n .parse(source) as Root;\n\n/** Parse MDX (with frontmatter) into mdast. Exposed so callers like\n * `fetchGuideFrontmatters` don't need to re-load remark themselves. */\nexport const parseMdx = async (source: string): Promise<Root> => {\n const deps = await loadRemarkDeps();\n return parseMdxWithDeps(source, deps);\n};\n\nconst stringifyMdx = (tree: Root, deps: RemarkDeps): string =>\n String(\n deps\n .unified()\n .use(deps.remarkFrontmatter)\n .use(deps.remarkMdx)\n .use(deps.remarkStringify, {\n bullet: '-',\n fences: true,\n listItemIndent: 'one',\n })\n .stringify(tree),\n );\n\n/**\n * Remove nodes that are meaningless once the MDX is rendered to plain markdown\n * for an agent: the YAML frontmatter block and the `import`/`export` (ESM)\n * statements at the top of every docs page. They add noise and tokens without\n * conveying guidance.\n */\nconst stripFrontmatterAndEsm = (tree: Root): void => {\n tree.children = tree.children.filter(\n (node) => node.type !== 'yaml' && node.type !== 'mdxjsEsm',\n );\n};\n\nexport const postProcessGuideWithRemark = async (\n guide: string,\n opts: PipelineOptions,\n): Promise<string> => {\n const deps = await loadRemarkDeps();\n const tree = parseMdxWithDeps(guide, deps);\n\n await inlineSnippets(tree, opts, deps);\n applyFilterTransforms(tree, opts.options);\n applyComponentTransforms(tree, opts, deps);\n stripFrontmatterAndEsm(tree);\n\n return stringifyMdx(tree, deps);\n};\n\nconst inlineSnippets = async (\n tree: Root,\n opts: PipelineOptions,\n deps: RemarkDeps,\n): Promise<void> => {\n const provider = opts.snippetContentProvider;\n if (!provider) return;\n\n interface PendingSnippet {\n parent: JsxParent;\n index: number;\n name: string;\n node: JsxElement;\n }\n\n const pending: PendingSnippet[] = [];\n const walk = (parent: JsxParent): void => {\n const children = parent.children as RootContent[];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!isJsxElement(child)) continue;\n if (child.name === 'Snippet') {\n const name = readStringAttr(child, 'name');\n if (name) pending.push({ parent, index: i, name, node: child });\n continue;\n }\n walk(child);\n }\n };\n walk(tree);\n if (pending.length === 0) return;\n\n const fetched = await Promise.all(\n pending.map(async (p) => {\n let raw = '';\n try {\n raw = await provider(p.name);\n } catch {\n raw = '';\n }\n if (!raw) return { ...p, replacement: undefined };\n const processed = await postProcessGuideWithRemark(raw.trim(), opts);\n return { ...p, replacement: processed };\n }),\n );\n\n // Splice in descending index order per parent so earlier indices stay valid.\n const byParent = new Map<JsxParent, (typeof fetched)[number][]>();\n for (const f of fetched) {\n const bucket = byParent.get(f.parent) ?? [];\n bucket.push(f);\n byParent.set(f.parent, bucket);\n }\n for (const [parent, items] of byParent) {\n items.sort((a, b) => b.index - a.index);\n for (const { index, name, replacement, node } of items) {\n if (replacement === undefined) continue;\n const snippetTree = parseMdxWithDeps(replacement, deps);\n const wrapper: MdxJsxFlowElement = {\n type: 'mdxJsxFlowElement',\n name: 'Snippet',\n attributes: [{ type: 'mdxJsxAttribute', name: 'name', value: name }],\n children: snippetTree.children as MdxJsxFlowElement['children'],\n };\n if ('position' in node && node.position) {\n (wrapper as { position?: unknown }).position = node.position;\n }\n (parent.children as RootContent[]).splice(\n index,\n 1,\n wrapper as RootContent,\n );\n }\n }\n};\n\nconst applyFilterTransforms = (\n tree: Root,\n options: Record<string, string> | undefined,\n): void => {\n const iac = options?.iac;\n\n const transform = (parent: JsxParent): void => {\n const children = parent.children as RootContent[];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!isJsxElement(child)) continue;\n\n if (child.name === 'OptionFilter') {\n const when = parseWhenAttr(child);\n if (!when) continue; // malformed — leave alone\n // Recurse first so nested filters collapse before we replace this wrapper.\n transform(child);\n const not = hasBareAttr(child, 'not');\n if (options) {\n const replacement = evaluatePredicate(when, not, options)\n ? (child.children as RootContent[])\n : [];\n children.splice(i, 1, ...replacement);\n i += replacement.length - 1;\n } else {\n children.splice(i, 1, buildNoteQuote(child, when, not));\n }\n continue;\n }\n\n if (child.name === 'Infrastructure') {\n if (iac === 'cdk' || iac === 'terraform') {\n const body = selectInfrastructureSlot(child, iac);\n const pseudo: MdxJsxFlowElement = {\n type: 'mdxJsxFlowElement',\n name: 'tmp',\n attributes: [],\n children: body as MdxJsxFlowElement['children'],\n };\n transform(pseudo);\n children.splice(i, 1, ...(pseudo.children as RootContent[]));\n i--;\n continue;\n }\n // No iac → keep both slots so readers / agents see both variants.\n transform(child);\n continue;\n }\n\n if (child.name === 'Tabs' && child.type === 'mdxJsxFlowElement') {\n transform(child);\n const dropped = applyTabsFilter(child, options);\n if (dropped === 'empty') {\n children.splice(i, 1);\n i--;\n continue;\n }\n if (dropped === 'inline') {\n const survivor = (child.children as RootContent[]).find(\n (c): c is MdxJsxFlowElement =>\n isJsxElement(c) && c.name === 'TabItem',\n )!;\n const body = survivor.children as RootContent[];\n children.splice(i, 1, ...body);\n i += body.length - 1;\n continue;\n }\n continue;\n }\n\n transform(child);\n }\n };\n transform(tree);\n};\n\nconst selectInfrastructureSlot = (\n node: JsxElement,\n iac: 'cdk' | 'terraform',\n): RootContent[] => {\n const slotName = iac.toLowerCase();\n const frag = (node.children as RootContent[]).find(\n (c): c is MdxJsxFlowElement =>\n isJsxElement(c) &&\n c.name === 'Fragment' &&\n readStringAttr(c, 'slot') === slotName,\n );\n return (frag?.children as RootContent[]) ?? [];\n};\n\n/**\n * Prune TabItems whose `_filter` doesn't match `options`. Returns:\n * - `'empty'` if the <Tabs> now has no <TabItem>s — caller drops it.\n * - `'inline'` if exactly one filtered <TabItem> survived — caller\n * inlines the body so agents see just the picked variant.\n * - `'keep'` otherwise.\n */\nconst applyTabsFilter = (\n tabs: MdxJsxFlowElement,\n options: Record<string, string> | undefined,\n): 'empty' | 'inline' | 'keep' => {\n const children = tabs.children as RootContent[];\n const surviving: RootContent[] = [];\n let anyFiltered = false;\n for (const child of children) {\n if (!isJsxElement(child) || child.name !== 'TabItem') {\n surviving.push(child);\n continue;\n }\n const filterEstree = readEstreeAttr(child, '_filter');\n if (!filterEstree) {\n surviving.push(child);\n continue;\n }\n anyFiltered = true;\n let predicate: Predicate;\n try {\n predicate = parseWhenExpression(filterEstree as never);\n } catch {\n stripFilterAttr(child);\n surviving.push(child);\n continue;\n }\n if (!options || evaluatePredicate(predicate, false, options)) {\n stripFilterAttr(child);\n surviving.push(child);\n }\n }\n if (anyFiltered) {\n tabs.children = surviving as MdxJsxFlowElement['children'];\n }\n const tabItems = surviving.filter(\n (c) => isJsxElement(c) && c.name === 'TabItem',\n );\n if (tabItems.length === 0 && surviving.length === 0) return 'empty';\n if (anyFiltered && tabItems.length === 1) return 'inline';\n return 'keep';\n};\n\nconst stripFilterAttr = (el: JsxElement): void => {\n el.attributes = el.attributes.filter(\n (a) => !(a.type === 'mdxJsxAttribute' && a.name === '_filter'),\n );\n};\n\n/**\n * `> [!NOTE] Only when …` blockquote. The alert header goes through as an\n * `html` node so remark-stringify doesn't escape the `[`/`]` brackets —\n * downstream agents match on the literal GitHub alert syntax.\n */\nconst buildNoteQuote = (\n source: JsxElement,\n predicate: Predicate,\n not: boolean,\n): RootContent => {\n const marker = describePredicate(predicate, not);\n const description = readStringAttr(source, 'description');\n const headerLines = description\n ? [`[!NOTE] ${marker}`, description]\n : [`[!NOTE] ${marker}`];\n const headerNodes: RootContent[] = headerLines.map(\n (line) => ({ type: 'html', value: line }) as RootContent,\n );\n return {\n type: 'blockquote',\n children: [...headerNodes, ...(source.children as RootContent[])] as never,\n } as RootContent;\n};\n\nconst parseWhenAttr = (node: JsxElement): Predicate | undefined => {\n const estree = readEstreeAttr(node, 'when');\n if (!estree) return undefined;\n try {\n return parseWhenExpression(estree as never);\n } catch {\n return undefined;\n }\n};\n\nconst applyComponentTransforms = (\n tree: Root,\n opts: PipelineOptions,\n deps: RemarkDeps,\n): void => {\n const pm = opts.packageManager ?? 'pnpm';\n const transform = (parent: JsxParent): void => {\n const children = parent.children as RootContent[];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!isJsxElement(child)) continue;\n const replacement = renderComponent(child, opts, pm, deps);\n if (replacement !== undefined) {\n children.splice(i, 1, ...replacement);\n i += replacement.length - 1;\n continue;\n }\n transform(child);\n }\n };\n transform(tree);\n};\n\nconst renderComponent = (\n node: JsxElement,\n opts: PipelineOptions,\n pm: string,\n deps: RemarkDeps,\n): RootContent[] | undefined => {\n switch (node.name) {\n case 'NxCommands': {\n const commands = readCommandsAttr(node);\n if (!commands) return undefined;\n return [\n codeBlock(\n commands\n .map((c) => buildNxCommand(c, opts.packageManager))\n .join('\\n'),\n ),\n ];\n }\n case 'RunGenerator': {\n const generatorId = readStringAttr(node, 'generator');\n if (!generatorId) return undefined;\n const schema = findSchema(opts.generators, generatorId);\n if (!schema) return undefined;\n return parseMarkdownFragment(\n renderGeneratorCommand(generatorId, schema, opts.packageManager),\n deps,\n );\n }\n case 'GeneratorParameters': {\n const generatorId = readStringAttr(node, 'generator');\n if (!generatorId) return undefined;\n const schema = findSchema(opts.generators, generatorId);\n if (!schema) return undefined;\n return parseMarkdownFragment(renderSchema(schema), deps);\n }\n case 'CreateNxWorkspaceCommand': {\n const workspace = readStringAttr(node, 'workspace');\n if (!workspace) return undefined;\n const iac = readStringAttr(node, 'iac') as\n | 'cdk'\n | 'terraform'\n | undefined;\n return [codeBlock(buildCreateNxWorkspaceCommand(pm, workspace, iac))];\n }\n case 'NxInitCommand': {\n return [codeBlock(buildNxInitCommand(pm))];\n }\n case 'InstallCommand': {\n // Without `pkg`, installs the workspace's existing dependencies\n const pkg =\n readStringAttr(node, 'pkg') ?? readExpressionAttr(node, 'pkg');\n return [\n codeBlock(buildInstallCommand(pm, pkg, hasBareAttr(node, 'dev'))),\n ];\n }\n case 'PackageManagerShortCommand': {\n const commands = readCommandsAttr(node);\n if (!commands) return undefined;\n return [\n codeBlock(\n commands\n .map((c) => buildPackageManagerShortCommand(pm, c))\n .join('\\n'),\n ),\n ];\n }\n case 'PackageManagerExecCommand': {\n const commands = readCommandsAttr(node);\n if (!commands) return undefined;\n return [\n codeBlock(\n commands.map((c) => buildPackageManagerExecCommand(pm, c)).join('\\n'),\n ),\n ];\n }\n default:\n return undefined;\n }\n};\n\nconst codeBlock = (body: string): RootContent => ({\n type: 'code',\n lang: 'bash',\n value: body,\n});\n\nconst parseMarkdownFragment = (\n markdown: string,\n deps: RemarkDeps,\n): RootContent[] => {\n const fragTree = deps.unified().use(deps.remarkParse).parse(markdown) as Root;\n return fragTree.children as RootContent[];\n};\n\nconst findSchema = (\n generators: NxGeneratorInfo[],\n generatorId: string,\n):\n | { properties?: Record<string, unknown>; required?: string[] }\n | undefined => {\n const info = generators.find((g) => g.id === generatorId);\n if (!info) return undefined;\n try {\n return JSON.parse(fs.readFileSync(info.resolvedSchemaPath, 'utf-8'));\n } catch {\n return undefined;\n }\n};\n\n/** Parse the `commands={[…]}` attribute from the estree that remark-mdx\n * attaches to the JSX attribute value. */\nconst readCommandsAttr = (node: JsxElement): string[] | undefined => {\n const estree = readEstreeAttr(node, 'commands');\n if (!estree) return undefined;\n try {\n return extractStringArrayExpression(estree as never);\n } catch {\n return undefined;\n }\n};\n"],"names":["fs","buildCreateNxWorkspaceCommand","buildInstallCommand","buildNxInitCommand","buildPackageManagerExecCommand","buildPackageManagerShortCommand","buildNxCommand","renderGeneratorCommand","renderSchema","hasBareAttr","isJsxElement","readEstreeAttr","readExpressionAttr","readStringAttr","describePredicate","evaluatePredicate","extractStringArrayExpression","parseWhenExpression","depsPromise","loadRemarkDeps","unified","remarkParse","default","remarkMdx","remarkStringify","remarkFrontmatter","parseMdxWithDeps","source","deps","use","parse","parseMdx","stringifyMdx","tree","String","bullet","fences","listItemIndent","stringify","stripFrontmatterAndEsm","children","filter","node","type","postProcessGuideWithRemark","guide","opts","inlineSnippets","applyFilterTransforms","options","applyComponentTransforms","provider","snippetContentProvider","pending","walk","parent","i","length","child","name","push","index","fetched","Promise","all","map","p","raw","replacement","undefined","processed","trim","byParent","Map","f","bucket","get","set","items","sort","a","b","snippetTree","wrapper","attributes","value","position","splice","iac","transform","when","parseWhenAttr","not","buildNoteQuote","body","selectInfrastructureSlot","pseudo","dropped","applyTabsFilter","survivor","find","c","slotName","toLowerCase","frag","tabs","surviving","anyFiltered","filterEstree","predicate","stripFilterAttr","tabItems","el","marker","description","headerLines","headerNodes","line","estree","pm","packageManager","renderComponent","commands","readCommandsAttr","codeBlock","join","generatorId","schema","findSchema","generators","parseMarkdownFragment","workspace","pkg","lang","markdown","fragTree","info","g","id","JSON","readFileSync","resolvedSchemaPath"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/guide-pipeline.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport fs from 'fs';\n/**\n * Unified + remark-mdx pipeline for the MCP `generator-guide` tool.\n *\n * Passes (in order, each over the already-transformed tree):\n * 1. Snippet inlining — `<Snippet name>` → recursive post-process.\n * 2. Filter transforms — `<OptionFilter>`, `<Infrastructure>` slot\n * selection, `<Tabs><TabItem _filter>` pruning.\n * 3. Component transforms — `<NxCommands>` / `<RunGenerator>` /\n * `<GeneratorParameters>` / `<CreateNxWorkspaceCommand>` /\n * `<InstallCommand>` / `<PackageManagerShortCommand>` /\n * `<PackageManagerExecCommand>` render down to markdown, and\n * `<ArchitectureDiagram>` drops out as it has no text form.\n */\nimport type { Root, RootContent } from 'mdast';\nimport type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';\nimport {\n buildCreateNxWorkspaceCommand,\n buildInstallCommand,\n buildNxInitCommand,\n buildPackageManagerExecCommand,\n buildPackageManagerShortCommand,\n} from '../utils/commands.js';\nimport type { NxGeneratorInfo } from '../utils/generators.js';\nimport {\n buildNxCommand,\n renderGeneratorCommand,\n renderSchema,\n} from './guide-render.js';\nimport {\n hasBareAttr,\n isJsxElement,\n type JsxElement,\n type JsxParent,\n readEstreeAttr,\n readExpressionAttr,\n readStringAttr,\n} from './mdx-ast.js';\nimport {\n describePredicate,\n evaluatePredicate,\n extractStringArrayExpression,\n type Predicate,\n parseWhenExpression,\n} from './option-filter.js';\n\nexport interface PipelineOptions {\n generators: NxGeneratorInfo[];\n packageManager?: string;\n snippetContentProvider?: (name: string) => Promise<string> | string;\n options?: Record<string, string>;\n}\n\n// unified v11 is ESM-only and this package is CJS; dynamic import + rolldown's\n// `codeSplitting: false` bundles everything into the published MCP binary.\ninterface RemarkDeps {\n unified: typeof import('unified').unified;\n remarkParse: typeof import('remark-parse').default;\n remarkMdx: typeof import('remark-mdx').default;\n remarkStringify: typeof import('remark-stringify').default;\n remarkFrontmatter: typeof import('remark-frontmatter').default;\n}\n\nlet depsPromise: Promise<RemarkDeps> | undefined;\nconst loadRemarkDeps = (): Promise<RemarkDeps> => {\n if (!depsPromise) {\n depsPromise = (async () => ({\n unified: (await import('unified')).unified,\n remarkParse: (await import('remark-parse')).default,\n remarkMdx: (await import('remark-mdx')).default,\n remarkStringify: (await import('remark-stringify')).default,\n remarkFrontmatter: (await import('remark-frontmatter')).default,\n }))();\n }\n return depsPromise;\n};\n\nconst parseMdxWithDeps = (source: string, deps: RemarkDeps): Root =>\n deps\n .unified()\n .use(deps.remarkParse)\n .use(deps.remarkFrontmatter)\n .use(deps.remarkMdx)\n .parse(source) as Root;\n\n/** Parse MDX (with frontmatter) into mdast. Exposed so callers like\n * `fetchGuideFrontmatters` don't need to re-load remark themselves. */\nexport const parseMdx = async (source: string): Promise<Root> => {\n const deps = await loadRemarkDeps();\n return parseMdxWithDeps(source, deps);\n};\n\nconst stringifyMdx = (tree: Root, deps: RemarkDeps): string =>\n String(\n deps\n .unified()\n .use(deps.remarkFrontmatter)\n .use(deps.remarkMdx)\n .use(deps.remarkStringify, {\n bullet: '-',\n fences: true,\n listItemIndent: 'one',\n })\n .stringify(tree),\n );\n\n/**\n * Remove nodes that are meaningless once the MDX is rendered to plain markdown\n * for an agent: the YAML frontmatter block and the `import`/`export` (ESM)\n * statements at the top of every docs page. They add noise and tokens without\n * conveying guidance.\n */\nconst stripFrontmatterAndEsm = (tree: Root): void => {\n tree.children = tree.children.filter(\n (node) => node.type !== 'yaml' && node.type !== 'mdxjsEsm',\n );\n};\n\nexport const postProcessGuideWithRemark = async (\n guide: string,\n opts: PipelineOptions,\n): Promise<string> => {\n const deps = await loadRemarkDeps();\n const tree = parseMdxWithDeps(guide, deps);\n\n await inlineSnippets(tree, opts, deps);\n applyFilterTransforms(tree, opts.options);\n applyComponentTransforms(tree, opts, deps);\n stripFrontmatterAndEsm(tree);\n\n return stringifyMdx(tree, deps);\n};\n\nconst inlineSnippets = async (\n tree: Root,\n opts: PipelineOptions,\n deps: RemarkDeps,\n): Promise<void> => {\n const provider = opts.snippetContentProvider;\n if (!provider) return;\n\n interface PendingSnippet {\n parent: JsxParent;\n index: number;\n name: string;\n node: JsxElement;\n }\n\n const pending: PendingSnippet[] = [];\n const walk = (parent: JsxParent): void => {\n const children = parent.children as RootContent[];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!isJsxElement(child)) continue;\n if (child.name === 'Snippet') {\n const name = readStringAttr(child, 'name');\n if (name) pending.push({ parent, index: i, name, node: child });\n continue;\n }\n walk(child);\n }\n };\n walk(tree);\n if (pending.length === 0) return;\n\n const fetched = await Promise.all(\n pending.map(async (p) => {\n let raw = '';\n try {\n raw = await provider(p.name);\n } catch {\n raw = '';\n }\n if (!raw) return { ...p, replacement: undefined };\n const processed = await postProcessGuideWithRemark(raw.trim(), opts);\n return { ...p, replacement: processed };\n }),\n );\n\n // Splice in descending index order per parent so earlier indices stay valid.\n const byParent = new Map<JsxParent, (typeof fetched)[number][]>();\n for (const f of fetched) {\n const bucket = byParent.get(f.parent) ?? [];\n bucket.push(f);\n byParent.set(f.parent, bucket);\n }\n for (const [parent, items] of byParent) {\n items.sort((a, b) => b.index - a.index);\n for (const { index, name, replacement, node } of items) {\n if (replacement === undefined) continue;\n const snippetTree = parseMdxWithDeps(replacement, deps);\n const wrapper: MdxJsxFlowElement = {\n type: 'mdxJsxFlowElement',\n name: 'Snippet',\n attributes: [{ type: 'mdxJsxAttribute', name: 'name', value: name }],\n children: snippetTree.children as MdxJsxFlowElement['children'],\n };\n if ('position' in node && node.position) {\n (wrapper as { position?: unknown }).position = node.position;\n }\n (parent.children as RootContent[]).splice(\n index,\n 1,\n wrapper as RootContent,\n );\n }\n }\n};\n\nconst applyFilterTransforms = (\n tree: Root,\n options: Record<string, string> | undefined,\n): void => {\n const iac = options?.iac;\n\n const transform = (parent: JsxParent): void => {\n const children = parent.children as RootContent[];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!isJsxElement(child)) continue;\n\n if (child.name === 'OptionFilter') {\n const when = parseWhenAttr(child);\n if (!when) continue; // malformed — leave alone\n // Recurse first so nested filters collapse before we replace this wrapper.\n transform(child);\n const not = hasBareAttr(child, 'not');\n if (options) {\n const replacement = evaluatePredicate(when, not, options)\n ? (child.children as RootContent[])\n : [];\n children.splice(i, 1, ...replacement);\n i += replacement.length - 1;\n } else {\n children.splice(i, 1, buildNoteQuote(child, when, not));\n }\n continue;\n }\n\n if (child.name === 'Infrastructure') {\n if (iac === 'cdk' || iac === 'terraform') {\n const body = selectInfrastructureSlot(child, iac);\n const pseudo: MdxJsxFlowElement = {\n type: 'mdxJsxFlowElement',\n name: 'tmp',\n attributes: [],\n children: body as MdxJsxFlowElement['children'],\n };\n transform(pseudo);\n children.splice(i, 1, ...(pseudo.children as RootContent[]));\n i--;\n continue;\n }\n // No iac → keep both slots so readers / agents see both variants.\n transform(child);\n continue;\n }\n\n if (child.name === 'Tabs' && child.type === 'mdxJsxFlowElement') {\n transform(child);\n const dropped = applyTabsFilter(child, options);\n if (dropped === 'empty') {\n children.splice(i, 1);\n i--;\n continue;\n }\n if (dropped === 'inline') {\n const survivor = (child.children as RootContent[]).find(\n (c): c is MdxJsxFlowElement =>\n isJsxElement(c) && c.name === 'TabItem',\n )!;\n const body = survivor.children as RootContent[];\n children.splice(i, 1, ...body);\n i += body.length - 1;\n continue;\n }\n continue;\n }\n\n transform(child);\n }\n };\n transform(tree);\n};\n\nconst selectInfrastructureSlot = (\n node: JsxElement,\n iac: 'cdk' | 'terraform',\n): RootContent[] => {\n const slotName = iac.toLowerCase();\n const frag = (node.children as RootContent[]).find(\n (c): c is MdxJsxFlowElement =>\n isJsxElement(c) &&\n c.name === 'Fragment' &&\n readStringAttr(c, 'slot') === slotName,\n );\n return (frag?.children as RootContent[]) ?? [];\n};\n\n/**\n * Prune TabItems whose `_filter` doesn't match `options`. Returns:\n * - `'empty'` if the <Tabs> now has no <TabItem>s — caller drops it.\n * - `'inline'` if exactly one filtered <TabItem> survived — caller\n * inlines the body so agents see just the picked variant.\n * - `'keep'` otherwise.\n */\nconst applyTabsFilter = (\n tabs: MdxJsxFlowElement,\n options: Record<string, string> | undefined,\n): 'empty' | 'inline' | 'keep' => {\n const children = tabs.children as RootContent[];\n const surviving: RootContent[] = [];\n let anyFiltered = false;\n for (const child of children) {\n if (!isJsxElement(child) || child.name !== 'TabItem') {\n surviving.push(child);\n continue;\n }\n const filterEstree = readEstreeAttr(child, '_filter');\n if (!filterEstree) {\n surviving.push(child);\n continue;\n }\n anyFiltered = true;\n let predicate: Predicate;\n try {\n predicate = parseWhenExpression(filterEstree as never);\n } catch {\n stripFilterAttr(child);\n surviving.push(child);\n continue;\n }\n if (!options || evaluatePredicate(predicate, false, options)) {\n stripFilterAttr(child);\n surviving.push(child);\n }\n }\n if (anyFiltered) {\n tabs.children = surviving as MdxJsxFlowElement['children'];\n }\n const tabItems = surviving.filter(\n (c) => isJsxElement(c) && c.name === 'TabItem',\n );\n if (tabItems.length === 0 && surviving.length === 0) return 'empty';\n if (anyFiltered && tabItems.length === 1) return 'inline';\n return 'keep';\n};\n\nconst stripFilterAttr = (el: JsxElement): void => {\n el.attributes = el.attributes.filter(\n (a) => !(a.type === 'mdxJsxAttribute' && a.name === '_filter'),\n );\n};\n\n/**\n * `> [!NOTE] Only when …` blockquote. The alert header goes through as an\n * `html` node so remark-stringify doesn't escape the `[`/`]` brackets —\n * downstream agents match on the literal GitHub alert syntax.\n */\nconst buildNoteQuote = (\n source: JsxElement,\n predicate: Predicate,\n not: boolean,\n): RootContent => {\n const marker = describePredicate(predicate, not);\n const description = readStringAttr(source, 'description');\n const headerLines = description\n ? [`[!NOTE] ${marker}`, description]\n : [`[!NOTE] ${marker}`];\n const headerNodes: RootContent[] = headerLines.map(\n (line) => ({ type: 'html', value: line }) as RootContent,\n );\n return {\n type: 'blockquote',\n children: [...headerNodes, ...(source.children as RootContent[])] as never,\n } as RootContent;\n};\n\nconst parseWhenAttr = (node: JsxElement): Predicate | undefined => {\n const estree = readEstreeAttr(node, 'when');\n if (!estree) return undefined;\n try {\n return parseWhenExpression(estree as never);\n } catch {\n return undefined;\n }\n};\n\nconst applyComponentTransforms = (\n tree: Root,\n opts: PipelineOptions,\n deps: RemarkDeps,\n): void => {\n const pm = opts.packageManager ?? 'pnpm';\n const transform = (parent: JsxParent): void => {\n const children = parent.children as RootContent[];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!isJsxElement(child)) continue;\n const replacement = renderComponent(child, opts, pm, deps);\n if (replacement !== undefined) {\n children.splice(i, 1, ...replacement);\n i += replacement.length - 1;\n continue;\n }\n transform(child);\n }\n };\n transform(tree);\n};\n\nconst renderComponent = (\n node: JsxElement,\n opts: PipelineOptions,\n pm: string,\n deps: RemarkDeps,\n): RootContent[] | undefined => {\n switch (node.name) {\n case 'NxCommands': {\n const commands = readCommandsAttr(node);\n if (!commands) return undefined;\n return [\n codeBlock(\n commands\n .map((c) => buildNxCommand(c, opts.packageManager))\n .join('\\n'),\n ),\n ];\n }\n case 'RunGenerator': {\n const generatorId = readStringAttr(node, 'generator');\n if (!generatorId) return undefined;\n const schema = findSchema(opts.generators, generatorId);\n if (!schema) return undefined;\n return parseMarkdownFragment(\n renderGeneratorCommand(generatorId, schema, opts.packageManager),\n deps,\n );\n }\n case 'GeneratorParameters': {\n const generatorId = readStringAttr(node, 'generator');\n if (!generatorId) return undefined;\n const schema = findSchema(opts.generators, generatorId);\n if (!schema) return undefined;\n return parseMarkdownFragment(renderSchema(schema), deps);\n }\n case 'CreateNxWorkspaceCommand': {\n const workspace = readStringAttr(node, 'workspace');\n if (!workspace) return undefined;\n const iac = readStringAttr(node, 'iac') as\n | 'cdk'\n | 'terraform'\n | undefined;\n return [codeBlock(buildCreateNxWorkspaceCommand(pm, workspace, iac))];\n }\n case 'NxInitCommand': {\n return [codeBlock(buildNxInitCommand(pm))];\n }\n case 'InstallCommand': {\n // Without `pkg`, installs the workspace's existing dependencies\n const pkg =\n readStringAttr(node, 'pkg') ?? readExpressionAttr(node, 'pkg');\n return [\n codeBlock(buildInstallCommand(pm, pkg, hasBareAttr(node, 'dev'))),\n ];\n }\n case 'PackageManagerShortCommand': {\n const commands = readCommandsAttr(node);\n if (!commands) return undefined;\n return [\n codeBlock(\n commands\n .map((c) => buildPackageManagerShortCommand(pm, c))\n .join('\\n'),\n ),\n ];\n }\n case 'PackageManagerExecCommand': {\n const commands = readCommandsAttr(node);\n if (!commands) return undefined;\n return [\n codeBlock(\n commands.map((c) => buildPackageManagerExecCommand(pm, c)).join('\\n'),\n ),\n ];\n }\n // A diagram of the AWS resources a project deploys, drawn from the docs\n // site's own artwork. There is nothing to render as text — the prose beside\n // it describes the same architecture — so it is dropped rather than left as\n // a stray tag.\n case 'ArchitectureDiagram':\n return [];\n default:\n return undefined;\n }\n};\n\nconst codeBlock = (body: string): RootContent => ({\n type: 'code',\n lang: 'bash',\n value: body,\n});\n\nconst parseMarkdownFragment = (\n markdown: string,\n deps: RemarkDeps,\n): RootContent[] => {\n const fragTree = deps.unified().use(deps.remarkParse).parse(markdown) as Root;\n return fragTree.children as RootContent[];\n};\n\nconst findSchema = (\n generators: NxGeneratorInfo[],\n generatorId: string,\n):\n | { properties?: Record<string, unknown>; required?: string[] }\n | undefined => {\n const info = generators.find((g) => g.id === generatorId);\n if (!info) return undefined;\n try {\n return JSON.parse(fs.readFileSync(info.resolvedSchemaPath, 'utf-8'));\n } catch {\n return undefined;\n }\n};\n\n/** Parse the `commands={[…]}` attribute from the estree that remark-mdx\n * attaches to the JSX attribute value. */\nconst readCommandsAttr = (node: JsxElement): string[] | undefined => {\n const estree = readEstreeAttr(node, 'commands');\n if (!estree) return undefined;\n try {\n return extractStringArrayExpression(estree as never);\n } catch {\n return undefined;\n }\n};\n"],"names":["fs","buildCreateNxWorkspaceCommand","buildInstallCommand","buildNxInitCommand","buildPackageManagerExecCommand","buildPackageManagerShortCommand","buildNxCommand","renderGeneratorCommand","renderSchema","hasBareAttr","isJsxElement","readEstreeAttr","readExpressionAttr","readStringAttr","describePredicate","evaluatePredicate","extractStringArrayExpression","parseWhenExpression","depsPromise","loadRemarkDeps","unified","remarkParse","default","remarkMdx","remarkStringify","remarkFrontmatter","parseMdxWithDeps","source","deps","use","parse","parseMdx","stringifyMdx","tree","String","bullet","fences","listItemIndent","stringify","stripFrontmatterAndEsm","children","filter","node","type","postProcessGuideWithRemark","guide","opts","inlineSnippets","applyFilterTransforms","options","applyComponentTransforms","provider","snippetContentProvider","pending","walk","parent","i","length","child","name","push","index","fetched","Promise","all","map","p","raw","replacement","undefined","processed","trim","byParent","Map","f","bucket","get","set","items","sort","a","b","snippetTree","wrapper","attributes","value","position","splice","iac","transform","when","parseWhenAttr","not","buildNoteQuote","body","selectInfrastructureSlot","pseudo","dropped","applyTabsFilter","survivor","find","c","slotName","toLowerCase","frag","tabs","surviving","anyFiltered","filterEstree","predicate","stripFilterAttr","tabItems","el","marker","description","headerLines","headerNodes","line","estree","pm","packageManager","renderComponent","commands","readCommandsAttr","codeBlock","join","generatorId","schema","findSchema","generators","parseMarkdownFragment","workspace","pkg","lang","markdown","fragTree","info","g","id","JSON","readFileSync","resolvedSchemaPath"],"mappings":"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"}
|
|
@@ -28,3 +28,10 @@ export declare const extractFrontmatter: (tree: Root) => {
|
|
|
28
28
|
data: Record<string, unknown>;
|
|
29
29
|
bodyOffset: number;
|
|
30
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Remove the frontmatter and every ESM `import`/`export` statement from an MDX
|
|
33
|
+
* source, leaving the content behind. The statements are located through the
|
|
34
|
+
* parsed tree, so `import` and `export` lines that appear inside code samples
|
|
35
|
+
* or template literals are kept — they are content, not preamble.
|
|
36
|
+
*/
|
|
37
|
+
export declare const stripFrontmatterAndEsm: (raw: string, tree: Root) => string;
|
|
@@ -78,5 +78,20 @@ export const hasBareAttr = (node, name)=>node.attributes.some((a)=>a.type === 'm
|
|
|
78
78
|
bodyOffset: node.position?.end.offset ?? 0
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Remove the frontmatter and every ESM `import`/`export` statement from an MDX
|
|
83
|
+
* source, leaving the content behind. The statements are located through the
|
|
84
|
+
* parsed tree, so `import` and `export` lines that appear inside code samples
|
|
85
|
+
* or template literals are kept — they are content, not preamble.
|
|
86
|
+
*/ export const stripFrontmatterAndEsm = (raw, tree)=>{
|
|
87
|
+
const cuts = tree.children.filter((c)=>c.type === 'yaml' || c.type === 'mdxjsEsm').map((c)=>c.position).filter((p)=>p?.start.offset !== undefined && p?.end.offset !== undefined);
|
|
88
|
+
let result = '';
|
|
89
|
+
let cursor = 0;
|
|
90
|
+
for (const { start, end } of cuts){
|
|
91
|
+
result += raw.slice(cursor, start.offset);
|
|
92
|
+
cursor = end.offset;
|
|
93
|
+
}
|
|
94
|
+
return (result + raw.slice(cursor)).trim();
|
|
95
|
+
};
|
|
81
96
|
|
|
82
97
|
//# sourceMappingURL=mdx-ast.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/mdx-ast.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport yaml from 'js-yaml';\nimport type { Root, RootContent, Yaml } from 'mdast';\nimport type {\n MdxJsxAttribute,\n MdxJsxAttributeValueExpression,\n MdxJsxFlowElement,\n MdxJsxTextElement,\n} from 'mdast-util-mdx-jsx';\nimport { parseWhenExpression } from './option-filter.js';\n\nexport type JsxParent = Root | MdxJsxFlowElement | MdxJsxTextElement;\nexport type JsxElement = MdxJsxFlowElement | MdxJsxTextElement;\n\nexport const isJsxElement = (node: RootContent): node is JsxElement =>\n node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';\n\nconst findAttr = (\n node: JsxElement,\n name: string,\n): MdxJsxAttribute | undefined =>\n node.attributes.find(\n (a): a is MdxJsxAttribute =>\n a.type === 'mdxJsxAttribute' && a.name === name,\n );\n\nexport const readStringAttr = (\n node: JsxElement,\n name: string,\n): string | undefined => {\n const attr = findAttr(node, name);\n return typeof attr?.value === 'string' ? attr.value : undefined;\n};\n\nexport const readExpressionAttr = (\n node: JsxElement,\n name: string,\n): string | undefined => {\n const attr = findAttr(node, name);\n if (attr && typeof attr.value === 'object' && attr.value !== null) {\n return (attr.value as MdxJsxAttributeValueExpression).value;\n }\n return undefined;\n};\n\nexport const readEstreeAttr = (\n node: JsxElement,\n name: string,\n): unknown | undefined => {\n const attr = findAttr(node, name);\n if (attr && typeof attr.value === 'object' && attr.value !== null) {\n return (attr.value as MdxJsxAttributeValueExpression).data?.estree;\n }\n return undefined;\n};\n\nexport const hasBareAttr = (node: JsxElement, name: string): boolean =>\n node.attributes.some((a) => a.type === 'mdxJsxAttribute' && a.name === name);\n\n/** Walk every JSX element in the subtree, pre-order. */\nexport const walkJsx = (\n parent: JsxParent,\n visit: (node: JsxElement, parent: JsxParent) => void,\n): void => {\n const children = parent.children as RootContent[];\n for (const child of children) {\n if (!isJsxElement(child)) continue;\n visit(child, parent);\n walkJsx(child, visit);\n }\n};\n\n/**\n * Every option key referenced by `<OptionFilter when>` or\n * `<TabItem _filter>` in the subtree. Malformed predicates are skipped.\n */\nexport const collectFilterableKeysFromJsx = (tree: Root): Set<string> => {\n const keys = new Set<string>();\n walkJsx(tree, (node) => {\n const attrName =\n node.name === 'OptionFilter'\n ? 'when'\n : node.name === 'TabItem'\n ? '_filter'\n : undefined;\n if (!attrName) return;\n const estree = readEstreeAttr(node, attrName);\n if (!estree) return;\n try {\n for (const key of Object.keys(parseWhenExpression(estree as never))) {\n keys.add(key);\n }\n } catch {\n // Malformed / partially-typed — skip.\n }\n });\n return keys;\n};\n\n/**\n * Parse the leading `---…---` YAML frontmatter from an mdast Root produced\n * with `remark-frontmatter`. Returns `{ data, bodyOffset }` where\n * `bodyOffset` is the character index after the closing `---` — slice the\n * original source from it to get the body without re-stringifying the tree.\n */\nexport const extractFrontmatter = (\n tree: Root,\n): { data: Record<string, unknown>; bodyOffset: number } => {\n const node = tree.children.find((c): c is Yaml => c.type === 'yaml');\n if (!node) return { data: {}, bodyOffset: 0 };\n let parsed: unknown;\n try {\n parsed = yaml.load(node.value);\n } catch {\n return { data: {}, bodyOffset: node.position?.end.offset ?? 0 };\n }\n const data =\n parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n return { data, bodyOffset: node.position?.end.offset ?? 0 };\n};\n"],"names":["yaml","parseWhenExpression","isJsxElement","node","type","findAttr","name","attributes","find","a","readStringAttr","attr","value","undefined","readExpressionAttr","readEstreeAttr","data","estree","hasBareAttr","some","walkJsx","parent","visit","children","child","collectFilterableKeysFromJsx","tree","keys","Set","attrName","key","Object","add","extractFrontmatter","c","bodyOffset","parsed","load","position","end","offset","Array","isArray"],"mappings":"AAAA;;;CAGC,GAED,OAAOA,UAAU,UAAU;AAQ3B,SAASC,mBAAmB,QAAQ,qBAAqB;AAKzD,OAAO,MAAMC,eAAe,CAACC,OAC3BA,KAAKC,IAAI,KAAK,uBAAuBD,KAAKC,IAAI,KAAK,oBAAoB;AAEzE,MAAMC,WAAW,CACfF,MACAG,OAEAH,KAAKI,UAAU,CAACC,IAAI,CAClB,CAACC,IACCA,EAAEL,IAAI,KAAK,qBAAqBK,EAAEH,IAAI,KAAKA;AAGjD,OAAO,MAAMI,iBAAiB,CAC5BP,MACAG;IAEA,MAAMK,OAAON,SAASF,MAAMG;IAC5B,OAAO,OAAOK,MAAMC,UAAU,WAAWD,KAAKC,KAAK,GAAGC;AACxD,EAAE;AAEF,OAAO,MAAMC,qBAAqB,CAChCX,MACAG;IAEA,MAAMK,OAAON,SAASF,MAAMG;IAC5B,IAAIK,QAAQ,OAAOA,KAAKC,KAAK,KAAK,YAAYD,KAAKC,KAAK,KAAK,MAAM;QACjE,OAAO,AAACD,KAAKC,KAAK,CAAoCA,KAAK;IAC7D;IACA,OAAOC;AACT,EAAE;AAEF,OAAO,MAAME,iBAAiB,CAC5BZ,MACAG;IAEA,MAAMK,OAAON,SAASF,MAAMG;IAC5B,IAAIK,QAAQ,OAAOA,KAAKC,KAAK,KAAK,YAAYD,KAAKC,KAAK,KAAK,MAAM;QACjE,OAAO,AAACD,KAAKC,KAAK,CAAoCI,IAAI,EAAEC;IAC9D;IACA,OAAOJ;AACT,EAAE;AAEF,OAAO,MAAMK,cAAc,CAACf,MAAkBG,OAC5CH,KAAKI,UAAU,CAACY,IAAI,CAAC,CAACV,IAAMA,EAAEL,IAAI,KAAK,qBAAqBK,EAAEH,IAAI,KAAKA,MAAM;AAE/E,sDAAsD,GACtD,OAAO,MAAMc,UAAU,CACrBC,QACAC;IAEA,MAAMC,WAAWF,OAAOE,QAAQ;IAChC,KAAK,MAAMC,SAASD,SAAU;QAC5B,IAAI,CAACrB,aAAasB,QAAQ;QAC1BF,MAAME,OAAOH;QACbD,QAAQI,OAAOF;IACjB;AACF,EAAE;AAEF;;;CAGC,GACD,OAAO,MAAMG,+BAA+B,CAACC;IAC3C,MAAMC,OAAO,IAAIC;IACjBR,QAAQM,MAAM,CAACvB;QACb,MAAM0B,WACJ1B,KAAKG,IAAI,KAAK,iBACV,SACAH,KAAKG,IAAI,KAAK,YACZ,YACAO;QACR,IAAI,CAACgB,UAAU;QACf,MAAMZ,SAASF,eAAeZ,MAAM0B;QACpC,IAAI,CAACZ,QAAQ;QACb,IAAI;YACF,KAAK,MAAMa,OAAOC,OAAOJ,IAAI,CAAC1B,oBAAoBgB,SAAmB;gBACnEU,KAAKK,GAAG,CAACF;YACX;QACF,EAAE,OAAM;QACN,sCAAsC;QACxC;IACF;IACA,OAAOH;AACT,EAAE;AAEF;;;;;CAKC,GACD,OAAO,MAAMM,qBAAqB,CAChCP;IAEA,MAAMvB,OAAOuB,KAAKH,QAAQ,CAACf,IAAI,CAAC,CAAC0B,IAAiBA,EAAE9B,IAAI,KAAK;IAC7D,IAAI,CAACD,MAAM,OAAO;QAAEa,MAAM,CAAC;QAAGmB,YAAY;IAAE;IAC5C,IAAIC;IACJ,IAAI;QACFA,SAASpC,KAAKqC,IAAI,CAAClC,KAAKS,KAAK;IAC/B,EAAE,OAAM;QACN,OAAO;YAAEI,MAAM,CAAC;YAAGmB,YAAYhC,KAAKmC,QAAQ,EAAEC,IAAIC,UAAU;QAAE;IAChE;IACA,MAAMxB,OACJoB,UAAU,OAAOA,WAAW,YAAY,CAACK,MAAMC,OAAO,CAACN,UAClDA,SACD,CAAC;IACP,OAAO;QAAEpB;QAAMmB,YAAYhC,KAAKmC,QAAQ,EAAEC,IAAIC,UAAU;IAAE;AAC5D,EAAE"}
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/mdx-ast.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport yaml from 'js-yaml';\nimport type { Root, RootContent, Yaml } from 'mdast';\nimport type {\n MdxJsxAttribute,\n MdxJsxAttributeValueExpression,\n MdxJsxFlowElement,\n MdxJsxTextElement,\n} from 'mdast-util-mdx-jsx';\nimport { parseWhenExpression } from './option-filter.js';\n\nexport type JsxParent = Root | MdxJsxFlowElement | MdxJsxTextElement;\nexport type JsxElement = MdxJsxFlowElement | MdxJsxTextElement;\n\nexport const isJsxElement = (node: RootContent): node is JsxElement =>\n node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';\n\nconst findAttr = (\n node: JsxElement,\n name: string,\n): MdxJsxAttribute | undefined =>\n node.attributes.find(\n (a): a is MdxJsxAttribute =>\n a.type === 'mdxJsxAttribute' && a.name === name,\n );\n\nexport const readStringAttr = (\n node: JsxElement,\n name: string,\n): string | undefined => {\n const attr = findAttr(node, name);\n return typeof attr?.value === 'string' ? attr.value : undefined;\n};\n\nexport const readExpressionAttr = (\n node: JsxElement,\n name: string,\n): string | undefined => {\n const attr = findAttr(node, name);\n if (attr && typeof attr.value === 'object' && attr.value !== null) {\n return (attr.value as MdxJsxAttributeValueExpression).value;\n }\n return undefined;\n};\n\nexport const readEstreeAttr = (\n node: JsxElement,\n name: string,\n): unknown | undefined => {\n const attr = findAttr(node, name);\n if (attr && typeof attr.value === 'object' && attr.value !== null) {\n return (attr.value as MdxJsxAttributeValueExpression).data?.estree;\n }\n return undefined;\n};\n\nexport const hasBareAttr = (node: JsxElement, name: string): boolean =>\n node.attributes.some((a) => a.type === 'mdxJsxAttribute' && a.name === name);\n\n/** Walk every JSX element in the subtree, pre-order. */\nexport const walkJsx = (\n parent: JsxParent,\n visit: (node: JsxElement, parent: JsxParent) => void,\n): void => {\n const children = parent.children as RootContent[];\n for (const child of children) {\n if (!isJsxElement(child)) continue;\n visit(child, parent);\n walkJsx(child, visit);\n }\n};\n\n/**\n * Every option key referenced by `<OptionFilter when>` or\n * `<TabItem _filter>` in the subtree. Malformed predicates are skipped.\n */\nexport const collectFilterableKeysFromJsx = (tree: Root): Set<string> => {\n const keys = new Set<string>();\n walkJsx(tree, (node) => {\n const attrName =\n node.name === 'OptionFilter'\n ? 'when'\n : node.name === 'TabItem'\n ? '_filter'\n : undefined;\n if (!attrName) return;\n const estree = readEstreeAttr(node, attrName);\n if (!estree) return;\n try {\n for (const key of Object.keys(parseWhenExpression(estree as never))) {\n keys.add(key);\n }\n } catch {\n // Malformed / partially-typed — skip.\n }\n });\n return keys;\n};\n\n/**\n * Parse the leading `---…---` YAML frontmatter from an mdast Root produced\n * with `remark-frontmatter`. Returns `{ data, bodyOffset }` where\n * `bodyOffset` is the character index after the closing `---` — slice the\n * original source from it to get the body without re-stringifying the tree.\n */\nexport const extractFrontmatter = (\n tree: Root,\n): { data: Record<string, unknown>; bodyOffset: number } => {\n const node = tree.children.find((c): c is Yaml => c.type === 'yaml');\n if (!node) return { data: {}, bodyOffset: 0 };\n let parsed: unknown;\n try {\n parsed = yaml.load(node.value);\n } catch {\n return { data: {}, bodyOffset: node.position?.end.offset ?? 0 };\n }\n const data =\n parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n return { data, bodyOffset: node.position?.end.offset ?? 0 };\n};\n\n/**\n * Remove the frontmatter and every ESM `import`/`export` statement from an MDX\n * source, leaving the content behind. The statements are located through the\n * parsed tree, so `import` and `export` lines that appear inside code samples\n * or template literals are kept — they are content, not preamble.\n */\nexport const stripFrontmatterAndEsm = (raw: string, tree: Root): string => {\n const cuts = tree.children\n .filter((c) => c.type === 'yaml' || c.type === 'mdxjsEsm')\n .map((c) => c.position)\n .filter(\n (p): p is NonNullable<typeof p> =>\n p?.start.offset !== undefined && p?.end.offset !== undefined,\n );\n let result = '';\n let cursor = 0;\n for (const { start, end } of cuts) {\n result += raw.slice(cursor, start.offset);\n cursor = end.offset!;\n }\n return (result + raw.slice(cursor)).trim();\n};\n"],"names":["yaml","parseWhenExpression","isJsxElement","node","type","findAttr","name","attributes","find","a","readStringAttr","attr","value","undefined","readExpressionAttr","readEstreeAttr","data","estree","hasBareAttr","some","walkJsx","parent","visit","children","child","collectFilterableKeysFromJsx","tree","keys","Set","attrName","key","Object","add","extractFrontmatter","c","bodyOffset","parsed","load","position","end","offset","Array","isArray","stripFrontmatterAndEsm","raw","cuts","filter","map","p","start","result","cursor","slice","trim"],"mappings":"AAAA;;;CAGC,GAED,OAAOA,UAAU,UAAU;AAQ3B,SAASC,mBAAmB,QAAQ,qBAAqB;AAKzD,OAAO,MAAMC,eAAe,CAACC,OAC3BA,KAAKC,IAAI,KAAK,uBAAuBD,KAAKC,IAAI,KAAK,oBAAoB;AAEzE,MAAMC,WAAW,CACfF,MACAG,OAEAH,KAAKI,UAAU,CAACC,IAAI,CAClB,CAACC,IACCA,EAAEL,IAAI,KAAK,qBAAqBK,EAAEH,IAAI,KAAKA;AAGjD,OAAO,MAAMI,iBAAiB,CAC5BP,MACAG;IAEA,MAAMK,OAAON,SAASF,MAAMG;IAC5B,OAAO,OAAOK,MAAMC,UAAU,WAAWD,KAAKC,KAAK,GAAGC;AACxD,EAAE;AAEF,OAAO,MAAMC,qBAAqB,CAChCX,MACAG;IAEA,MAAMK,OAAON,SAASF,MAAMG;IAC5B,IAAIK,QAAQ,OAAOA,KAAKC,KAAK,KAAK,YAAYD,KAAKC,KAAK,KAAK,MAAM;QACjE,OAAO,AAACD,KAAKC,KAAK,CAAoCA,KAAK;IAC7D;IACA,OAAOC;AACT,EAAE;AAEF,OAAO,MAAME,iBAAiB,CAC5BZ,MACAG;IAEA,MAAMK,OAAON,SAASF,MAAMG;IAC5B,IAAIK,QAAQ,OAAOA,KAAKC,KAAK,KAAK,YAAYD,KAAKC,KAAK,KAAK,MAAM;QACjE,OAAO,AAACD,KAAKC,KAAK,CAAoCI,IAAI,EAAEC;IAC9D;IACA,OAAOJ;AACT,EAAE;AAEF,OAAO,MAAMK,cAAc,CAACf,MAAkBG,OAC5CH,KAAKI,UAAU,CAACY,IAAI,CAAC,CAACV,IAAMA,EAAEL,IAAI,KAAK,qBAAqBK,EAAEH,IAAI,KAAKA,MAAM;AAE/E,sDAAsD,GACtD,OAAO,MAAMc,UAAU,CACrBC,QACAC;IAEA,MAAMC,WAAWF,OAAOE,QAAQ;IAChC,KAAK,MAAMC,SAASD,SAAU;QAC5B,IAAI,CAACrB,aAAasB,QAAQ;QAC1BF,MAAME,OAAOH;QACbD,QAAQI,OAAOF;IACjB;AACF,EAAE;AAEF;;;CAGC,GACD,OAAO,MAAMG,+BAA+B,CAACC;IAC3C,MAAMC,OAAO,IAAIC;IACjBR,QAAQM,MAAM,CAACvB;QACb,MAAM0B,WACJ1B,KAAKG,IAAI,KAAK,iBACV,SACAH,KAAKG,IAAI,KAAK,YACZ,YACAO;QACR,IAAI,CAACgB,UAAU;QACf,MAAMZ,SAASF,eAAeZ,MAAM0B;QACpC,IAAI,CAACZ,QAAQ;QACb,IAAI;YACF,KAAK,MAAMa,OAAOC,OAAOJ,IAAI,CAAC1B,oBAAoBgB,SAAmB;gBACnEU,KAAKK,GAAG,CAACF;YACX;QACF,EAAE,OAAM;QACN,sCAAsC;QACxC;IACF;IACA,OAAOH;AACT,EAAE;AAEF;;;;;CAKC,GACD,OAAO,MAAMM,qBAAqB,CAChCP;IAEA,MAAMvB,OAAOuB,KAAKH,QAAQ,CAACf,IAAI,CAAC,CAAC0B,IAAiBA,EAAE9B,IAAI,KAAK;IAC7D,IAAI,CAACD,MAAM,OAAO;QAAEa,MAAM,CAAC;QAAGmB,YAAY;IAAE;IAC5C,IAAIC;IACJ,IAAI;QACFA,SAASpC,KAAKqC,IAAI,CAAClC,KAAKS,KAAK;IAC/B,EAAE,OAAM;QACN,OAAO;YAAEI,MAAM,CAAC;YAAGmB,YAAYhC,KAAKmC,QAAQ,EAAEC,IAAIC,UAAU;QAAE;IAChE;IACA,MAAMxB,OACJoB,UAAU,OAAOA,WAAW,YAAY,CAACK,MAAMC,OAAO,CAACN,UAClDA,SACD,CAAC;IACP,OAAO;QAAEpB;QAAMmB,YAAYhC,KAAKmC,QAAQ,EAAEC,IAAIC,UAAU;IAAE;AAC5D,EAAE;AAEF;;;;;CAKC,GACD,OAAO,MAAMG,yBAAyB,CAACC,KAAalB;IAClD,MAAMmB,OAAOnB,KAAKH,QAAQ,CACvBuB,MAAM,CAAC,CAACZ,IAAMA,EAAE9B,IAAI,KAAK,UAAU8B,EAAE9B,IAAI,KAAK,YAC9C2C,GAAG,CAAC,CAACb,IAAMA,EAAEI,QAAQ,EACrBQ,MAAM,CACL,CAACE,IACCA,GAAGC,MAAMT,WAAW3B,aAAamC,GAAGT,IAAIC,WAAW3B;IAEzD,IAAIqC,SAAS;IACb,IAAIC,SAAS;IACb,KAAK,MAAM,EAAEF,KAAK,EAAEV,GAAG,EAAE,IAAIM,KAAM;QACjCK,UAAUN,IAAIQ,KAAK,CAACD,QAAQF,MAAMT,MAAM;QACxCW,SAASZ,IAAIC,MAAM;IACrB;IACA,OAAO,AAACU,CAAAA,SAASN,IAAIQ,KAAK,CAACD,OAAM,EAAGE,IAAI;AAC1C,EAAE"}
|
|
@@ -23,13 +23,13 @@ export declare const filterableValuesForProperty: (prop: SchemaProperty) => stri
|
|
|
23
23
|
/**
|
|
24
24
|
* Pull out every filterable property (enum or boolean valued) as a
|
|
25
25
|
* `FilterableOption`. Shared between the MCP server (deriving options from a
|
|
26
|
-
* generator's schema) and the docs
|
|
26
|
+
* generator's schema) and the docs site (mapping user-referenced keys
|
|
27
27
|
* onto their values).
|
|
28
28
|
*/
|
|
29
29
|
export declare const filterableOptionsFromSchema: (schema: GeneratorSchema | undefined) => FilterableOption[];
|
|
30
30
|
/**
|
|
31
31
|
* Locate the monorepo's `packages/nx-plugin/generators.json` by walking
|
|
32
|
-
* upward from the caller's directory. Used by the docs
|
|
32
|
+
* upward from the caller's directory. Used by the docs site and
|
|
33
33
|
* remark-option-filter; the MCP server resolves schema paths per-generator
|
|
34
34
|
* via `NxGeneratorInfo.resolvedSchemaPath` instead.
|
|
35
35
|
*/
|
|
@@ -21,7 +21,7 @@ import path from "node:path";
|
|
|
21
21
|
/**
|
|
22
22
|
* Pull out every filterable property (enum or boolean valued) as a
|
|
23
23
|
* `FilterableOption`. Shared between the MCP server (deriving options from a
|
|
24
|
-
* generator's schema) and the docs
|
|
24
|
+
* generator's schema) and the docs site (mapping user-referenced keys
|
|
25
25
|
* onto their values).
|
|
26
26
|
*/ export const filterableOptionsFromSchema = (schema)=>{
|
|
27
27
|
const props = schema?.properties ?? {};
|
|
@@ -40,7 +40,7 @@ import path from "node:path";
|
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Locate the monorepo's `packages/nx-plugin/generators.json` by walking
|
|
43
|
-
* upward from the caller's directory. Used by the docs
|
|
43
|
+
* upward from the caller's directory. Used by the docs site and
|
|
44
44
|
* remark-option-filter; the MCP server resolves schema paths per-generator
|
|
45
45
|
* via `NxGeneratorInfo.resolvedSchemaPath` instead.
|
|
46
46
|
*/ export const resolveGeneratorsJson = (fromDir)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/schema-registry.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** A JSON-schema property narrowed to the bits we care about. */\ninterface SchemaProperty {\n type?: string;\n enum?: unknown[];\n default?: unknown;\n description?: string;\n}\n\nexport interface GeneratorSchema {\n properties?: Record<string, SchemaProperty>;\n required?: string[];\n}\n\nexport interface FilterableOption {\n key: string;\n enum: string[];\n default?: string;\n description?: string;\n}\n\ninterface GeneratorsJson {\n generators: Record<string, { schema: string }>;\n}\n\n/**\n * The values an option can be filtered on: its enum values, or true/false\n * for booleans. Returns undefined for non-filterable options.\n */\nexport const filterableValuesForProperty = (\n prop: SchemaProperty,\n): string[] | undefined => {\n if (Array.isArray(prop.enum) && prop.enum.length > 0) {\n return prop.enum.map((v) => String(v));\n }\n if (prop.type === 'boolean') {\n return ['true', 'false'];\n }\n return undefined;\n};\n\n/**\n * Pull out every filterable property (enum or boolean valued) as a\n * `FilterableOption`. Shared between the MCP server (deriving options from a\n * generator's schema) and the docs
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/schema-registry.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** A JSON-schema property narrowed to the bits we care about. */\ninterface SchemaProperty {\n type?: string;\n enum?: unknown[];\n default?: unknown;\n description?: string;\n}\n\nexport interface GeneratorSchema {\n properties?: Record<string, SchemaProperty>;\n required?: string[];\n}\n\nexport interface FilterableOption {\n key: string;\n enum: string[];\n default?: string;\n description?: string;\n}\n\ninterface GeneratorsJson {\n generators: Record<string, { schema: string }>;\n}\n\n/**\n * The values an option can be filtered on: its enum values, or true/false\n * for booleans. Returns undefined for non-filterable options.\n */\nexport const filterableValuesForProperty = (\n prop: SchemaProperty,\n): string[] | undefined => {\n if (Array.isArray(prop.enum) && prop.enum.length > 0) {\n return prop.enum.map((v) => String(v));\n }\n if (prop.type === 'boolean') {\n return ['true', 'false'];\n }\n return undefined;\n};\n\n/**\n * Pull out every filterable property (enum or boolean valued) as a\n * `FilterableOption`. Shared between the MCP server (deriving options from a\n * generator's schema) and the docs site (mapping user-referenced keys\n * onto their values).\n */\nexport const filterableOptionsFromSchema = (\n schema: GeneratorSchema | undefined,\n): FilterableOption[] => {\n const props = schema?.properties ?? {};\n const out: FilterableOption[] = [];\n for (const [key, prop] of Object.entries(props)) {\n const values = filterableValuesForProperty(prop);\n if (!values) continue;\n out.push({\n key,\n enum: values,\n default: prop.default !== undefined ? String(prop.default) : undefined,\n description: prop.description,\n });\n }\n return out;\n};\n\n/**\n * Locate the monorepo's `packages/nx-plugin/generators.json` by walking\n * upward from the caller's directory. Used by the docs site and\n * remark-option-filter; the MCP server resolves schema paths per-generator\n * via `NxGeneratorInfo.resolvedSchemaPath` instead.\n */\nexport const resolveGeneratorsJson = (fromDir: string): string | undefined => {\n let dir = fromDir;\n while (true) {\n const candidate = path.join(\n dir,\n 'packages',\n 'nx-plugin',\n 'generators.json',\n );\n if (fs.existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n};\n\n/**\n * Resolve a generator's schema path against a `generators.json` registry,\n * parse the schema file, and cache the result per-process.\n */\nexport const createSchemaLookup = (generatorsJsonPath: string) => {\n const packageDir = path.dirname(generatorsJsonPath);\n let registry: GeneratorsJson | undefined;\n const cache = new Map<string, GeneratorSchema>();\n\n const loadRegistry = (): GeneratorsJson => {\n if (!registry) {\n registry = JSON.parse(\n fs.readFileSync(generatorsJsonPath, 'utf-8'),\n ) as GeneratorsJson;\n }\n return registry;\n };\n\n return (generatorId: string): GeneratorSchema => {\n const cached = cache.get(generatorId);\n if (cached) return cached;\n const entry = loadRegistry().generators[generatorId];\n if (!entry) {\n throw new Error(`Unknown generator id '${generatorId}'`);\n }\n const schema = JSON.parse(\n fs.readFileSync(path.resolve(packageDir, entry.schema), 'utf-8'),\n ) as GeneratorSchema;\n cache.set(generatorId, schema);\n return schema;\n };\n};\n"],"names":["fs","path","filterableValuesForProperty","prop","Array","isArray","enum","length","map","v","String","type","undefined","filterableOptionsFromSchema","schema","props","properties","out","key","Object","entries","values","push","default","description","resolveGeneratorsJson","fromDir","dir","candidate","join","existsSync","parent","dirname","createSchemaLookup","generatorsJsonPath","packageDir","registry","cache","Map","loadRegistry","JSON","parse","readFileSync","generatorId","cached","get","entry","generators","Error","resolve","set"],"mappings":"AAAA;;;CAGC,GACD,OAAOA,QAAQ,UAAU;AACzB,OAAOC,UAAU,YAAY;AA0B7B;;;CAGC,GACD,OAAO,MAAMC,8BAA8B,CACzCC;IAEA,IAAIC,MAAMC,OAAO,CAACF,KAAKG,IAAI,KAAKH,KAAKG,IAAI,CAACC,MAAM,GAAG,GAAG;QACpD,OAAOJ,KAAKG,IAAI,CAACE,GAAG,CAAC,CAACC,IAAMC,OAAOD;IACrC;IACA,IAAIN,KAAKQ,IAAI,KAAK,WAAW;QAC3B,OAAO;YAAC;YAAQ;SAAQ;IAC1B;IACA,OAAOC;AACT,EAAE;AAEF;;;;;CAKC,GACD,OAAO,MAAMC,8BAA8B,CACzCC;IAEA,MAAMC,QAAQD,QAAQE,cAAc,CAAC;IACrC,MAAMC,MAA0B,EAAE;IAClC,KAAK,MAAM,CAACC,KAAKf,KAAK,IAAIgB,OAAOC,OAAO,CAACL,OAAQ;QAC/C,MAAMM,SAASnB,4BAA4BC;QAC3C,IAAI,CAACkB,QAAQ;QACbJ,IAAIK,IAAI,CAAC;YACPJ;YACAZ,MAAMe;YACNE,SAASpB,KAAKoB,OAAO,KAAKX,YAAYF,OAAOP,KAAKoB,OAAO,IAAIX;YAC7DY,aAAarB,KAAKqB,WAAW;QAC/B;IACF;IACA,OAAOP;AACT,EAAE;AAEF;;;;;CAKC,GACD,OAAO,MAAMQ,wBAAwB,CAACC;IACpC,IAAIC,MAAMD;IACV,MAAO,KAAM;QACX,MAAME,YAAY3B,KAAK4B,IAAI,CACzBF,KACA,YACA,aACA;QAEF,IAAI3B,GAAG8B,UAAU,CAACF,YAAY,OAAOA;QACrC,MAAMG,SAAS9B,KAAK+B,OAAO,CAACL;QAC5B,IAAII,WAAWJ,KAAK,OAAOf;QAC3Be,MAAMI;IACR;AACF,EAAE;AAEF;;;CAGC,GACD,OAAO,MAAME,qBAAqB,CAACC;IACjC,MAAMC,aAAalC,KAAK+B,OAAO,CAACE;IAChC,IAAIE;IACJ,MAAMC,QAAQ,IAAIC;IAElB,MAAMC,eAAe;QACnB,IAAI,CAACH,UAAU;YACbA,WAAWI,KAAKC,KAAK,CACnBzC,GAAG0C,YAAY,CAACR,oBAAoB;QAExC;QACA,OAAOE;IACT;IAEA,OAAO,CAACO;QACN,MAAMC,SAASP,MAAMQ,GAAG,CAACF;QACzB,IAAIC,QAAQ,OAAOA;QACnB,MAAME,QAAQP,eAAeQ,UAAU,CAACJ,YAAY;QACpD,IAAI,CAACG,OAAO;YACV,MAAM,IAAIE,MAAM,CAAC,sBAAsB,EAAEL,YAAY,CAAC,CAAC;QACzD;QACA,MAAM7B,SAAS0B,KAAKC,KAAK,CACvBzC,GAAG0C,YAAY,CAACzC,KAAKgD,OAAO,CAACd,YAAYW,MAAMhC,MAAM,GAAG;QAE1DuB,MAAMa,GAAG,CAACP,aAAa7B;QACvB,OAAOA;IACT;AACF,EAAE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { joinPathFragments } from "@nx/devkit";
|
|
5
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
6
|
+
import { PACKAGES_DIR, SHARED_TERRAFORM_DIR } from "../../../utils/shared-constructs-constants.js";
|
|
7
|
+
/**
|
|
8
|
+
* Stop each vended Terraform AgentCore Harness app module
|
|
9
|
+
* (`app/harnesses/<name>/<name>.tf`) sending a null `environment_variables`.
|
|
10
|
+
*
|
|
11
|
+
* The service stores no environment variables as an empty map and returns one,
|
|
12
|
+
* so a null fails the apply with "inconsistent values for sensitive attribute"
|
|
13
|
+
* once the Harness has already been created, leaving it tainted. Every
|
|
14
|
+
* subsequent apply fails the same way.
|
|
15
|
+
*
|
|
16
|
+
* Modules whose assignment has been edited are left untouched and reported via
|
|
17
|
+
* `nextSteps`.
|
|
18
|
+
*/ const TERRAFORM_HARNESS_APP_DIR = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/app/harnesses`;
|
|
19
|
+
/** The assignment the generator used to write. */ const NULLABLE_ASSIGNMENT = 'environment_variables = var.environment_variables';
|
|
20
|
+
/** What it becomes, so the value sent matches what the service returns. */ const COALESCED_ASSIGNMENT = 'environment_variables = coalesce(var.environment_variables, {})';
|
|
21
|
+
const divergedMessage = (filePath)=>`${filePath}: its environment_variables assignment has been edited, so it was left as it is. Change it to \`${COALESCED_ASSIGNMENT}\` — the AgentCore service returns an empty map when a Harness has no environment variables, and sending null fails the apply after the Harness has been created.`;
|
|
22
|
+
export default async function migration(tree) {
|
|
23
|
+
const nextSteps = [];
|
|
24
|
+
let migrated = false;
|
|
25
|
+
if (!tree.exists(TERRAFORM_HARNESS_APP_DIR)) {
|
|
26
|
+
return {
|
|
27
|
+
nextSteps
|
|
28
|
+
}; // This workspace has no Terraform harness modules.
|
|
29
|
+
}
|
|
30
|
+
for (const dirName of tree.children(TERRAFORM_HARNESS_APP_DIR)){
|
|
31
|
+
const filePath = joinPathFragments(TERRAFORM_HARNESS_APP_DIR, dirName, `${dirName}.tf`);
|
|
32
|
+
if (!tree.exists(filePath)) {
|
|
33
|
+
continue; // Not a harness app module directory.
|
|
34
|
+
}
|
|
35
|
+
const contents = tree.read(filePath, 'utf-8') ?? '';
|
|
36
|
+
if (contents.includes(COALESCED_ASSIGNMENT)) {
|
|
37
|
+
continue; // Already migrated, so a re-run is a no-op.
|
|
38
|
+
}
|
|
39
|
+
if (!contents.includes(NULLABLE_ASSIGNMENT)) {
|
|
40
|
+
nextSteps.push(divergedMessage(filePath));
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
tree.write(filePath, contents.replace(NULLABLE_ASSIGNMENT, COALESCED_ASSIGNMENT));
|
|
44
|
+
migrated = true;
|
|
45
|
+
}
|
|
46
|
+
if (migrated) {
|
|
47
|
+
await formatFilesInSubtree(tree, TERRAFORM_HARNESS_APP_DIR);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
nextSteps
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/terraform-harness-environment-variables/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n} from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport {\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../../../utils/shared-constructs-constants.js';\n\n/**\n * Stop each vended Terraform AgentCore Harness app module\n * (`app/harnesses/<name>/<name>.tf`) sending a null `environment_variables`.\n *\n * The service stores no environment variables as an empty map and returns one,\n * so a null fails the apply with \"inconsistent values for sensitive attribute\"\n * once the Harness has already been created, leaving it tainted. Every\n * subsequent apply fails the same way.\n *\n * Modules whose assignment has been edited are left untouched and reported via\n * `nextSteps`.\n */\n\nconst TERRAFORM_HARNESS_APP_DIR = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/app/harnesses`;\n\n/** The assignment the generator used to write. */\nconst NULLABLE_ASSIGNMENT = 'environment_variables = var.environment_variables';\n\n/** What it becomes, so the value sent matches what the service returns. */\nconst COALESCED_ASSIGNMENT =\n 'environment_variables = coalesce(var.environment_variables, {})';\n\nconst divergedMessage = (filePath: string) =>\n `${filePath}: its environment_variables assignment has been edited, so it was left as it is. Change it to \\`${COALESCED_ASSIGNMENT}\\` — the AgentCore service returns an empty map when a Harness has no environment variables, and sending null fails the apply after the Harness has been created.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n let migrated = false;\n\n if (!tree.exists(TERRAFORM_HARNESS_APP_DIR)) {\n return { nextSteps }; // This workspace has no Terraform harness modules.\n }\n\n for (const dirName of tree.children(TERRAFORM_HARNESS_APP_DIR)) {\n const filePath = joinPathFragments(\n TERRAFORM_HARNESS_APP_DIR,\n dirName,\n `${dirName}.tf`,\n );\n if (!tree.exists(filePath)) {\n continue; // Not a harness app module directory.\n }\n\n const contents = tree.read(filePath, 'utf-8') ?? '';\n\n if (contents.includes(COALESCED_ASSIGNMENT)) {\n continue; // Already migrated, so a re-run is a no-op.\n }\n\n if (!contents.includes(NULLABLE_ASSIGNMENT)) {\n nextSteps.push(divergedMessage(filePath));\n continue;\n }\n\n tree.write(\n filePath,\n contents.replace(NULLABLE_ASSIGNMENT, COALESCED_ASSIGNMENT),\n );\n migrated = true;\n }\n\n if (migrated) {\n await formatFilesInSubtree(tree, TERRAFORM_HARNESS_APP_DIR);\n }\n\n return { nextSteps };\n}\n"],"names":["joinPathFragments","formatFilesInSubtree","PACKAGES_DIR","SHARED_TERRAFORM_DIR","TERRAFORM_HARNESS_APP_DIR","NULLABLE_ASSIGNMENT","COALESCED_ASSIGNMENT","divergedMessage","filePath","migration","tree","nextSteps","migrated","exists","dirName","children","contents","read","includes","push","write","replace"],"mappings":"AAAA;;;CAGC,GACD,SACEA,iBAAiB,QAGZ,aAAa;AACpB,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SACEC,YAAY,EACZC,oBAAoB,QACf,gDAAgD;AAEvD;;;;;;;;;;;CAWC,GAED,MAAMC,4BAA4B,GAAGF,aAAa,CAAC,EAAEC,qBAAqB,kBAAkB,CAAC;AAE7F,gDAAgD,GAChD,MAAME,sBAAsB;AAE5B,yEAAyE,GACzE,MAAMC,uBACJ;AAEF,MAAMC,kBAAkB,CAACC,WACvB,GAAGA,SAAS,gGAAgG,EAAEF,qBAAqB,iKAAiK,CAAC;AAEvS,eAAe,eAAeG,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAC9B,IAAIC,WAAW;IAEf,IAAI,CAACF,KAAKG,MAAM,CAACT,4BAA4B;QAC3C,OAAO;YAAEO;QAAU,GAAG,mDAAmD;IAC3E;IAEA,KAAK,MAAMG,WAAWJ,KAAKK,QAAQ,CAACX,2BAA4B;QAC9D,MAAMI,WAAWR,kBACfI,2BACAU,SACA,GAAGA,QAAQ,GAAG,CAAC;QAEjB,IAAI,CAACJ,KAAKG,MAAM,CAACL,WAAW;YAC1B,UAAU,sCAAsC;QAClD;QAEA,MAAMQ,WAAWN,KAAKO,IAAI,CAACT,UAAU,YAAY;QAEjD,IAAIQ,SAASE,QAAQ,CAACZ,uBAAuB;YAC3C,UAAU,4CAA4C;QACxD;QAEA,IAAI,CAACU,SAASE,QAAQ,CAACb,sBAAsB;YAC3CM,UAAUQ,IAAI,CAACZ,gBAAgBC;YAC/B;QACF;QAEAE,KAAKU,KAAK,CACRZ,UACAQ,SAASK,OAAO,CAAChB,qBAAqBC;QAExCM,WAAW;IACb;IAEA,IAAIA,UAAU;QACZ,MAAMX,qBAAqBS,MAAMN;IACnC;IAEA,OAAO;QAAEO;IAAU;AACrB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`openApiPyClientGenerator - additional properties > should emit dict[str, T] for plain additionalProperties objects > types.py 1`] = `
|
|
4
|
+
""""Types for TestApi — AUTO-GENERATED, do not edit."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Never
|
|
9
|
+
|
|
10
|
+
Counts200Response = dict[str, int]
|
|
11
|
+
|
|
12
|
+
CountsError = Never
|
|
13
|
+
"
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
exports[`openApiPyClientGenerator - additional properties > should handle object models with a mixture of properties and additionalProperties > types.py 1`] = `
|
|
17
|
+
""""Types for TestApi — AUTO-GENERATED, do not edit."""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Never
|
|
22
|
+
|
|
23
|
+
from pydantic import BaseModel, ConfigDict
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Mixed(BaseModel):
|
|
27
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
28
|
+
|
|
29
|
+
id: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
MixedError = Never
|
|
33
|
+
"
|
|
34
|
+
`;
|