@codama/fragments 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +542 -0
  3. package/dist/index.browser.cjs +208 -0
  4. package/dist/index.browser.cjs.map +1 -0
  5. package/dist/index.browser.mjs +176 -0
  6. package/dist/index.browser.mjs.map +1 -0
  7. package/dist/index.node.cjs +195 -0
  8. package/dist/index.node.cjs.map +1 -0
  9. package/dist/index.node.mjs +163 -0
  10. package/dist/index.node.mjs.map +1 -0
  11. package/dist/index.react-native.mjs +176 -0
  12. package/dist/index.react-native.mjs.map +1 -0
  13. package/dist/javascript.browser.cjs +403 -0
  14. package/dist/javascript.browser.cjs.map +1 -0
  15. package/dist/javascript.browser.mjs +353 -0
  16. package/dist/javascript.browser.mjs.map +1 -0
  17. package/dist/javascript.node.cjs +390 -0
  18. package/dist/javascript.node.cjs.map +1 -0
  19. package/dist/javascript.node.mjs +340 -0
  20. package/dist/javascript.node.mjs.map +1 -0
  21. package/dist/javascript.react-native.mjs +353 -0
  22. package/dist/javascript.react-native.mjs.map +1 -0
  23. package/dist/rust.browser.cjs +371 -0
  24. package/dist/rust.browser.cjs.map +1 -0
  25. package/dist/rust.browser.mjs +322 -0
  26. package/dist/rust.browser.mjs.map +1 -0
  27. package/dist/rust.node.cjs +358 -0
  28. package/dist/rust.node.cjs.map +1 -0
  29. package/dist/rust.node.mjs +309 -0
  30. package/dist/rust.node.mjs.map +1 -0
  31. package/dist/rust.react-native.mjs +322 -0
  32. package/dist/rust.react-native.mjs.map +1 -0
  33. package/dist/types/core/BaseFragment.d.ts +21 -0
  34. package/dist/types/core/BaseFragment.d.ts.map +1 -0
  35. package/dist/types/core/casing.d.ts +52 -0
  36. package/dist/types/core/casing.d.ts.map +1 -0
  37. package/dist/types/core/createFragmentTemplate.d.ts +38 -0
  38. package/dist/types/core/createFragmentTemplate.d.ts.map +1 -0
  39. package/dist/types/core/fs.d.ts +28 -0
  40. package/dist/types/core/fs.d.ts.map +1 -0
  41. package/dist/types/core/index.d.ts +9 -0
  42. package/dist/types/core/index.d.ts.map +1 -0
  43. package/dist/types/core/mapFragmentContent.d.ts +43 -0
  44. package/dist/types/core/mapFragmentContent.d.ts.map +1 -0
  45. package/dist/types/core/path.d.ts +43 -0
  46. package/dist/types/core/path.d.ts.map +1 -0
  47. package/dist/types/core/renderMap.d.ts +61 -0
  48. package/dist/types/core/renderMap.d.ts.map +1 -0
  49. package/dist/types/core/setFragmentContent.d.ts +23 -0
  50. package/dist/types/core/setFragmentContent.d.ts.map +1 -0
  51. package/dist/types/index.d.ts +17 -0
  52. package/dist/types/index.d.ts.map +1 -0
  53. package/dist/types/javascript/ImportMap.d.ts +61 -0
  54. package/dist/types/javascript/ImportMap.d.ts.map +1 -0
  55. package/dist/types/javascript/addToImportMap.d.ts +25 -0
  56. package/dist/types/javascript/addToImportMap.d.ts.map +1 -0
  57. package/dist/types/javascript/fragment.d.ts +135 -0
  58. package/dist/types/javascript/fragment.d.ts.map +1 -0
  59. package/dist/types/javascript/getDocblockFragment.d.ts +53 -0
  60. package/dist/types/javascript/getDocblockFragment.d.ts.map +1 -0
  61. package/dist/types/javascript/getExportAllFragment.d.ts +21 -0
  62. package/dist/types/javascript/getExportAllFragment.d.ts.map +1 -0
  63. package/dist/types/javascript/getExternalDependencies.d.ts +29 -0
  64. package/dist/types/javascript/getExternalDependencies.d.ts.map +1 -0
  65. package/dist/types/javascript/importMapToString.d.ts +40 -0
  66. package/dist/types/javascript/importMapToString.d.ts.map +1 -0
  67. package/dist/types/javascript/index.d.ts +23 -0
  68. package/dist/types/javascript/index.d.ts.map +1 -0
  69. package/dist/types/javascript/mergeImportMaps.d.ts +34 -0
  70. package/dist/types/javascript/mergeImportMaps.d.ts.map +1 -0
  71. package/dist/types/javascript/removeFromImportMap.d.ts +21 -0
  72. package/dist/types/javascript/removeFromImportMap.d.ts.map +1 -0
  73. package/dist/types/javascript/resolveImportMap.d.ts +33 -0
  74. package/dist/types/javascript/resolveImportMap.d.ts.map +1 -0
  75. package/dist/types/rust/ImportMap.d.ts +52 -0
  76. package/dist/types/rust/ImportMap.d.ts.map +1 -0
  77. package/dist/types/rust/addAliasToImportMap.d.ts +24 -0
  78. package/dist/types/rust/addAliasToImportMap.d.ts.map +1 -0
  79. package/dist/types/rust/addToImportMap.d.ts +27 -0
  80. package/dist/types/rust/addToImportMap.d.ts.map +1 -0
  81. package/dist/types/rust/fragment.d.ts +118 -0
  82. package/dist/types/rust/fragment.d.ts.map +1 -0
  83. package/dist/types/rust/getDocblockFragment.d.ts +53 -0
  84. package/dist/types/rust/getDocblockFragment.d.ts.map +1 -0
  85. package/dist/types/rust/getExternalDependencies.d.ts +30 -0
  86. package/dist/types/rust/getExternalDependencies.d.ts.map +1 -0
  87. package/dist/types/rust/importMapToString.d.ts +30 -0
  88. package/dist/types/rust/importMapToString.d.ts.map +1 -0
  89. package/dist/types/rust/index.d.ts +23 -0
  90. package/dist/types/rust/index.d.ts.map +1 -0
  91. package/dist/types/rust/mergeImportMaps.d.ts +23 -0
  92. package/dist/types/rust/mergeImportMaps.d.ts.map +1 -0
  93. package/dist/types/rust/removeFromImportMap.d.ts +20 -0
  94. package/dist/types/rust/removeFromImportMap.d.ts.map +1 -0
  95. package/dist/types/rust/resolveImportMap.d.ts +32 -0
  96. package/dist/types/rust/resolveImportMap.d.ts.map +1 -0
  97. package/package.json +106 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/casing.ts","../src/core/createFragmentTemplate.ts","../src/core/path.ts","../src/core/fs.ts","../src/core/setFragmentContent.ts","../src/core/mapFragmentContent.ts","../src/core/renderMap.ts"],"names":["CodamaError","CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE","relativePath"],"mappings":"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","file":"index.react-native.mjs","sourcesContent":["/**\n * String-casing helpers used by code generators when emitting\n * identifiers. They normalise an arbitrary input string into a\n * conventional shape (camelCase, PascalCase, kebab-case, snake_case,\n * Title Case) by inserting word boundaries before uppercase letters and\n * splitting on any sequence of non-alphanumeric characters.\n *\n * Returned values are plain `string`. This package deliberately does\n * not depend on `@codama/node-types`, so the branded `CamelCaseString`\n * / `PascalCaseString` / … types are not applied here. Consumers that\n * want the brand (e.g. `@codama/nodes`) can wrap these helpers and\n * apply the cast at their own boundary.\n *\n * The implementations all run through {@link titleCase} as a common\n * intermediate form, so a single deterministic word-splitting policy\n * is shared across every output shape.\n */\n\n/**\n * Uppercase the first character and lowercase the rest. Returns the\n * input unchanged when it is empty.\n */\nexport function capitalize(str: string): string {\n if (str.length === 0) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into Title Case — a space-separated\n * sequence of {@link capitalize}d words. Inserts a space before each\n * uppercase letter, then splits on any run of non-alphanumeric\n * characters and re-joins with single spaces.\n */\nexport function titleCase(str: string): string {\n return str\n .replace(/([A-Z])/g, ' $1')\n .split(/[^a-zA-Z0-9]+/)\n .filter(word => word.length > 0)\n .map(capitalize)\n .join(' ');\n}\n\n/**\n * Normalise an arbitrary string into PascalCase by stripping the\n * spaces from its {@link titleCase} form.\n */\nexport function pascalCase(str: string): string {\n return titleCase(str).split(' ').join('');\n}\n\n/**\n * Normalise an arbitrary string into camelCase by lowercasing the\n * first character of its {@link pascalCase} form.\n */\nexport function camelCase(str: string): string {\n if (str.length === 0) return str;\n const pascalStr = pascalCase(str);\n return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);\n}\n\n/**\n * Normalise an arbitrary string into kebab-case — lowercase words\n * joined with `-` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function kebabCase(str: string): string {\n return titleCase(str).split(' ').join('-').toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into snake_case — lowercase words\n * joined with `_` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function snakeCase(str: string): string {\n return titleCase(str).split(' ').join('_').toLowerCase();\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Generic template-tag implementation used by every flavor's `fragment`\n * tagged template.\n *\n * Walks the template/items pair, interpolating fragments verbatim and\n * coercing other values to strings, then defers to the caller-provided\n * `mergeFragments` for combining the surviving sub-fragments. This keeps the\n * fragment shape (imports, features, etc.) opaque to the core layer; each\n * flavor plugs in its own merge logic.\n *\n * Most consumers never call this directly — they use the `fragment` tag\n * exported by `@codama/fragments/javascript` or `@codama/fragments/rust`,\n * which both wrap this helper.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param template - The template-strings array supplied by the tag call site.\n * @param items - The interpolated values, in order. May be fragments,\n * strings, numbers, booleans, `undefined`, or anything coercible to a string.\n * @param isFragment - A predicate that identifies values of the concrete\n * fragment type so they can be inlined and forwarded to the merger.\n * @param mergeFragments - The flavor-specific merger that knows how to\n * combine fragments' non-content fields (e.g. imports, features). Receives\n * only the sub-fragments found in the template, plus a callback that\n * produces the final merged content string from each sub-fragment's content.\n * @return The fragment produced by `mergeFragments`.\n *\n * @example\n * ```ts\n * import { createFragmentTemplate } from '@codama/fragments';\n *\n * function fragment(template: TemplateStringsArray, ...items: unknown[]) {\n * return createFragmentTemplate(template, items, isFragment, mergeFragments);\n * }\n * ```\n */\nexport function createFragmentTemplate<TFragment extends BaseFragment>(\n template: TemplateStringsArray,\n items: unknown[],\n isFragment: (value: unknown) => value is TFragment,\n mergeFragments: (fragments: TFragment[], mergeContent: (contents: string[]) => string) => TFragment,\n): TFragment {\n const fragments = items.filter(isFragment);\n const zippedItems = items.map((item, i) => {\n const itemPrefix = template[i];\n if (typeof item === 'undefined') return itemPrefix;\n if (isFragment(item)) return itemPrefix + item.content;\n return itemPrefix + String(item as string);\n });\n return mergeFragments(fragments, () => zippedItems.join('') + template[template.length - 1]);\n}\n","/**\n * Path manipulation helpers used by code generators to assemble output\n * file paths.\n *\n * The {@link Path} type is a thin documentation alias for `string` —\n * any place a generator stores or threads a filesystem-relative path,\n * use this name to communicate intent. The {@link joinPath} and\n * {@link pathDirectory} helpers delegate to `node:path` on Node and\n * fall back to lightweight string manipulation on non-Node platforms.\n */\n\nimport { basename, dirname, join, posix } from 'node:path';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\n/** A filesystem path inside the generator's output tree. */\nexport type Path = string;\n\n/**\n * Join two or more path segments together. Uses `node:path`'s\n * platform-aware {@link join} on Node; on other platforms (browser,\n * react-native) falls back to a `/`-joined form with consecutive\n * slashes collapsed.\n */\nexport function joinPath(...paths: Path[]): string {\n if (!__NODEJS__) {\n return paths.join('/').replace(/\\/+/g, '/');\n }\n\n return join(...paths);\n}\n\n/**\n * Return the directory portion of a path (i.e. everything up to the\n * last `/` segment). Uses `node:path`'s {@link dirname} on Node and a\n * plain `lastIndexOf` fallback on other platforms.\n */\nexport function pathDirectory(path: Path): Path {\n if (!__NODEJS__) {\n return path.substring(0, path.lastIndexOf('/'));\n }\n\n return dirname(path);\n}\n\n/**\n * Return the trailing segment of a path (everything after the last\n * `/`). Uses `node:path`'s {@link basename} on Node and a plain\n * `lastIndexOf` fallback on other platforms.\n */\nexport function pathBasename(path: Path): Path {\n if (!__NODEJS__) {\n const slash = path.lastIndexOf('/');\n return slash >= 0 ? path.substring(slash + 1) : path;\n }\n\n return basename(path);\n}\n\n/**\n * Compute the POSIX-style relative path from `from` to `to`. Both\n * arguments are treated as `/`-separated logical paths regardless of\n * platform, so the result is consistent across operating systems —\n * suitable for emitting into source code as an import specifier.\n *\n * Node only: non-Node platforms throw {@link CodamaError} because\n * implementing a correct POSIX relative-path algorithm without\n * `node:path` is non-trivial and no current consumer needs it.\n */\nexport function relativePath(from: Path, to: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'relative' });\n }\n\n return posix.relative(from, to);\n}\n","/**\n * Node-only filesystem helpers used by code generators to write their\n * output to disk. Each function checks the `__NODEJS__` build flag and\n * throws a structured {@link CodamaError} on non-Node platforms so\n * accidental calls from a browser bundle fail loudly rather than\n * silently no-oping.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\nimport { Path, pathDirectory } from './path';\n\n/** Create a directory (and any missing parents) at the given path. */\nexport function createDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'mkdirSync' });\n }\n\n mkdirSync(path, { recursive: true });\n}\n\n/** Recursively delete the directory at the given path, if it exists. */\nexport function deleteDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'rmSync' });\n }\n\n if (existsSync(path)) {\n rmSync(path, { recursive: true });\n }\n}\n\n/**\n * Write `content` to a file at `path`, creating intermediate\n * directories as needed.\n */\nexport function writeFile(path: Path, content: string): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'writeFileSync' });\n }\n\n const directory = pathDirectory(path);\n if (!existsSync(directory)) {\n createDirectory(directory);\n }\n writeFileSync(path, content);\n}\n\n/** Check whether a file or directory exists at the given path. */\nexport function fileExists(path: Path): boolean {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'existsSync' });\n }\n\n return existsSync(path);\n}\n\n/** Read the file at the given path as a UTF-8 string. */\nexport function readFile(path: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'readFileSync' });\n }\n\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Read the file at the given path as a UTF-8 string and parse it as\n * JSON. The result is typed as the caller-supplied `T`; no runtime\n * validation is performed.\n */\nexport function readJson<T>(path: Path): T {\n return JSON.parse(readFile(path)) as T;\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Return a new frozen fragment whose `content` field has been replaced with\n * `content`, preserving every other field of the input fragment.\n *\n * The output keeps the input's exact concrete type (`TFragment`) so callers\n * never lose any extra fields a flavored fragment may carry (imports,\n * features, etc.).\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment to copy.\n * @param content - The new code string.\n * @return A frozen fragment of the same shape as `fragment` with `content` replaced.\n *\n * @example\n * ```ts\n * import { setFragmentContent } from '@codama/fragments';\n *\n * const next = setFragmentContent(prev, prev.content.toUpperCase());\n * ```\n */\nexport function setFragmentContent<TFragment extends BaseFragment>(fragment: TFragment, content: string): TFragment {\n return Object.freeze({ ...fragment, content });\n}\n","import type { BaseFragment } from './BaseFragment';\nimport { setFragmentContent } from './setFragmentContent';\n\n/**\n * Apply a synchronous transformation to a fragment's `content`, returning a\n * new fragment with every other field preserved.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - A function that receives the current content and\n * returns the new content.\n * @return A frozen fragment with the transformed content.\n *\n * @example\n * ```ts\n * import { mapFragmentContent } from '@codama/fragments';\n *\n * const trimmed = mapFragmentContent(fragment, c => c.trimEnd());\n * ```\n *\n * @see {@link mapFragmentContentAsync} for the async variant.\n */\nexport function mapFragmentContent<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => string,\n): TFragment {\n return setFragmentContent(fragment, mapContent(fragment.content));\n}\n\n/**\n * Async variant of {@link mapFragmentContent}: apply an async transformation\n * to a fragment's `content`.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - An async function that receives the current content\n * and returns a promise resolving to the new content.\n * @return A promise that resolves to a frozen fragment with the transformed\n * content.\n *\n * @example\n * ```ts\n * import { mapFragmentContentAsync } from '@codama/fragments';\n *\n * const formatted = await mapFragmentContentAsync(fragment, formatWithPrettier);\n * ```\n *\n * @see {@link mapFragmentContent} for the sync variant.\n */\nexport async function mapFragmentContentAsync<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => Promise<string>,\n): Promise<TFragment> {\n return setFragmentContent(fragment, await mapContent(fragment.content));\n}\n","/**\n * A `RenderMap` is the in-memory data structure a code generator builds\n * up before writing anything to disk: a frozen `ReadonlyMap` keyed by\n * output path, with a `BaseFragment` (or a concrete subtype carrying\n * imports / features / …) as the value. The helpers in this module are\n * pure data operations — they construct, merge, transform, and query\n * render maps without touching the filesystem.\n *\n * {@link writeRenderMap} is the single filesystem-touching entry point\n * here: it walks a finished map and writes every entry. Renderers that\n * tie a render map to a `Visitor` (see `@codama/renderers-core`) layer\n * that on top.\n */\n\nimport { CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, CodamaError } from '@codama/errors';\n\nimport type { BaseFragment } from './BaseFragment';\nimport { writeFile } from './fs';\nimport { mapFragmentContent, mapFragmentContentAsync } from './mapFragmentContent';\nimport { joinPath, type Path } from './path';\n\n/**\n * A frozen map keyed by output {@link Path}, with each entry holding a\n * fragment that will be written to that path. `TFragment` defaults to\n * {@link BaseFragment} but generators typically pass a richer flavor\n * (e.g. `Fragment` from `@codama/fragments/javascript`) to carry\n * imports and other per-file metadata.\n */\nexport type RenderMap<TFragment extends BaseFragment> = ReadonlyMap<Path, TFragment>;\n\nexport function createRenderMap<TFragment extends BaseFragment = BaseFragment>(): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(path: Path, content: TFragment): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n entries: Record<Path, TFragment | undefined>,\n): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n pathOrEntries?: Path | Record<Path, TFragment | undefined>,\n content?: TFragment,\n): RenderMap<TFragment> {\n let entries: [Path, TFragment][] = [];\n if (typeof pathOrEntries === 'string' && content !== undefined) {\n entries = [[pathOrEntries, content]];\n } else if (typeof pathOrEntries === 'object' && pathOrEntries !== null) {\n entries = Object.entries(pathOrEntries).flatMap(([key, value]) =>\n value === undefined ? [] : ([[key, value]] as const),\n );\n }\n return Object.freeze(new Map(entries));\n}\n\n/** Add or overwrite a single `(path, fragment)` entry. */\nexport function addToRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n content: TFragment,\n): RenderMap<TFragment> {\n return mergeRenderMaps([renderMap, createRenderMap(path, content)]);\n}\n\n/** Remove the entry at `path`, returning a new frozen map. */\nexport function removeFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): RenderMap<TFragment> {\n const newMap = new Map(renderMap);\n newMap.delete(path);\n return Object.freeze(newMap);\n}\n\n/**\n * Combine multiple render maps into one. Later maps overwrite earlier\n * entries at the same path.\n */\nexport function mergeRenderMaps<TFragment extends BaseFragment>(\n renderMaps: RenderMap<TFragment>[],\n): RenderMap<TFragment> {\n if (renderMaps.length === 0) return createRenderMap();\n if (renderMaps.length === 1) return renderMaps[0];\n const merged = new Map(renderMaps[0]);\n for (const map of renderMaps.slice(1)) {\n for (const [key, value] of map) {\n merged.set(key, value);\n }\n }\n return Object.freeze(merged);\n}\n\n/** Transform every fragment in the map, preserving the keys. */\nexport function mapRenderMapFragment<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => TFragment,\n): RenderMap<TFragment> {\n return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)] as const)]));\n}\n\n/** Async variant of {@link mapRenderMapFragment}. */\nexport async function mapRenderMapFragmentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => Promise<TFragment>,\n): Promise<RenderMap<TFragment>> {\n return Object.freeze(\n new Map(\n await Promise.all([\n ...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)] as const),\n ]),\n ),\n );\n}\n\n/** Transform the `content` of every fragment in the map. */\nexport function mapRenderMapContent<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => string,\n): RenderMap<TFragment> {\n return mapRenderMapFragment(renderMap, (fragment, path) =>\n mapFragmentContent(fragment, content => fn(content, path)),\n );\n}\n\n/** Async variant of {@link mapRenderMapContent}. */\nexport async function mapRenderMapContentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => Promise<string>,\n): Promise<RenderMap<TFragment>> {\n return await mapRenderMapFragmentAsync(renderMap, (fragment, path) =>\n mapFragmentContentAsync(fragment, content => fn(content, path)),\n );\n}\n\n/**\n * Look up the fragment at `path`, throwing a structured\n * {@link CodamaError} when the key is missing.\n */\nexport function getFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): TFragment {\n const value = renderMap.get(path);\n if (value === undefined) {\n throw new CodamaError(CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });\n }\n return value;\n}\n\n/**\n * Test whether the fragment at `path` contains `value`. Accepts either\n * a plain substring or a regular expression.\n */\nexport function renderMapContains<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n value: RegExp | string,\n): boolean {\n const { content } = getFromRenderMap(renderMap, path);\n return typeof value === 'string' ? content.includes(value) : value.test(content);\n}\n\n/**\n * Walk the render map and write every entry to disk, rooted at\n * `basePath`. Each path is joined with `basePath` via {@link joinPath}\n * and written via {@link writeFile}; the directory structure is\n * created on demand.\n */\nexport function writeRenderMap<TFragment extends BaseFragment>(renderMap: RenderMap<TFragment>, basePath: Path): void {\n renderMap.forEach(({ content }, relativePath) => {\n writeFile(joinPath(basePath, relativePath), content);\n });\n}\n"]}
@@ -0,0 +1,403 @@
1
+ 'use strict';
2
+
3
+ require('fs');
4
+ var errors = require('@codama/errors');
5
+ require('path');
6
+
7
+ // src/core/casing.ts
8
+ function capitalize(str) {
9
+ if (str.length === 0) return str;
10
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
11
+ }
12
+ function titleCase(str) {
13
+ return str.replace(/([A-Z])/g, " $1").split(/[^a-zA-Z0-9]+/).filter((word) => word.length > 0).map(capitalize).join(" ");
14
+ }
15
+ function pascalCase(str) {
16
+ return titleCase(str).split(" ").join("");
17
+ }
18
+ function camelCase(str) {
19
+ if (str.length === 0) return str;
20
+ const pascalStr = pascalCase(str);
21
+ return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);
22
+ }
23
+ function kebabCase(str) {
24
+ return titleCase(str).split(" ").join("-").toLowerCase();
25
+ }
26
+ function snakeCase(str) {
27
+ return titleCase(str).split(" ").join("_").toLowerCase();
28
+ }
29
+
30
+ // src/core/createFragmentTemplate.ts
31
+ function createFragmentTemplate(template, items, isFragment2, mergeFragments2) {
32
+ const fragments = items.filter(isFragment2);
33
+ const zippedItems = items.map((item, i) => {
34
+ const itemPrefix = template[i];
35
+ if (typeof item === "undefined") return itemPrefix;
36
+ if (isFragment2(item)) return itemPrefix + item.content;
37
+ return itemPrefix + String(item);
38
+ });
39
+ return mergeFragments2(fragments, () => zippedItems.join("") + template[template.length - 1]);
40
+ }
41
+ function joinPath(...paths) {
42
+ {
43
+ return paths.join("/").replace(/\/+/g, "/");
44
+ }
45
+ }
46
+ function pathDirectory(path) {
47
+ {
48
+ return path.substring(0, path.lastIndexOf("/"));
49
+ }
50
+ }
51
+ function pathBasename(path) {
52
+ {
53
+ const slash = path.lastIndexOf("/");
54
+ return slash >= 0 ? path.substring(slash + 1) : path;
55
+ }
56
+ }
57
+ function relativePath(from, to) {
58
+ {
59
+ throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "relative" });
60
+ }
61
+ }
62
+
63
+ // src/core/fs.ts
64
+ function createDirectory(path) {
65
+ {
66
+ throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "mkdirSync" });
67
+ }
68
+ }
69
+ function deleteDirectory(path) {
70
+ {
71
+ throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "rmSync" });
72
+ }
73
+ }
74
+ function writeFile(path, content) {
75
+ {
76
+ throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "writeFileSync" });
77
+ }
78
+ }
79
+ function fileExists(path) {
80
+ {
81
+ throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "existsSync" });
82
+ }
83
+ }
84
+ function readFile(path) {
85
+ {
86
+ throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "readFileSync" });
87
+ }
88
+ }
89
+ function readJson(path) {
90
+ return JSON.parse(readFile());
91
+ }
92
+
93
+ // src/core/setFragmentContent.ts
94
+ function setFragmentContent(fragment2, content) {
95
+ return Object.freeze({ ...fragment2, content });
96
+ }
97
+
98
+ // src/core/mapFragmentContent.ts
99
+ function mapFragmentContent(fragment2, mapContent) {
100
+ return setFragmentContent(fragment2, mapContent(fragment2.content));
101
+ }
102
+ async function mapFragmentContentAsync(fragment2, mapContent) {
103
+ return setFragmentContent(fragment2, await mapContent(fragment2.content));
104
+ }
105
+ function createRenderMap(pathOrEntries, content) {
106
+ let entries = [];
107
+ if (typeof pathOrEntries === "string" && content !== void 0) {
108
+ entries = [[pathOrEntries, content]];
109
+ } else if (typeof pathOrEntries === "object" && pathOrEntries !== null) {
110
+ entries = Object.entries(pathOrEntries).flatMap(
111
+ ([key, value]) => value === void 0 ? [] : [[key, value]]
112
+ );
113
+ }
114
+ return Object.freeze(new Map(entries));
115
+ }
116
+ function addToRenderMap(renderMap, path, content) {
117
+ return mergeRenderMaps([renderMap, createRenderMap(path, content)]);
118
+ }
119
+ function removeFromRenderMap(renderMap, path) {
120
+ const newMap = new Map(renderMap);
121
+ newMap.delete(path);
122
+ return Object.freeze(newMap);
123
+ }
124
+ function mergeRenderMaps(renderMaps) {
125
+ if (renderMaps.length === 0) return createRenderMap();
126
+ if (renderMaps.length === 1) return renderMaps[0];
127
+ const merged = new Map(renderMaps[0]);
128
+ for (const map of renderMaps.slice(1)) {
129
+ for (const [key, value] of map) {
130
+ merged.set(key, value);
131
+ }
132
+ }
133
+ return Object.freeze(merged);
134
+ }
135
+ function mapRenderMapFragment(renderMap, fn) {
136
+ return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)])]));
137
+ }
138
+ async function mapRenderMapFragmentAsync(renderMap, fn) {
139
+ return Object.freeze(
140
+ new Map(
141
+ await Promise.all([
142
+ ...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)])
143
+ ])
144
+ )
145
+ );
146
+ }
147
+ function mapRenderMapContent(renderMap, fn) {
148
+ return mapRenderMapFragment(
149
+ renderMap,
150
+ (fragment2, path) => mapFragmentContent(fragment2, (content) => fn(content, path))
151
+ );
152
+ }
153
+ async function mapRenderMapContentAsync(renderMap, fn) {
154
+ return await mapRenderMapFragmentAsync(
155
+ renderMap,
156
+ (fragment2, path) => mapFragmentContentAsync(fragment2, (content) => fn(content, path))
157
+ );
158
+ }
159
+ function getFromRenderMap(renderMap, path) {
160
+ const value = renderMap.get(path);
161
+ if (value === void 0) {
162
+ throw new errors.CodamaError(errors.CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });
163
+ }
164
+ return value;
165
+ }
166
+ function renderMapContains(renderMap, path, value) {
167
+ const { content } = getFromRenderMap(renderMap, path);
168
+ return typeof value === "string" ? content.includes(value) : value.test(content);
169
+ }
170
+ function writeRenderMap(renderMap, basePath) {
171
+ renderMap.forEach(({ content }, relativePath2) => {
172
+ writeFile(joinPath(basePath, relativePath2));
173
+ });
174
+ }
175
+
176
+ // src/javascript/ImportMap.ts
177
+ function createImportMap() {
178
+ return Object.freeze(/* @__PURE__ */ new Map());
179
+ }
180
+ function parseImportInput(input) {
181
+ const matches = /^(type )?([^ ]+)(?: as (.+))?$/.exec(input);
182
+ if (!matches) {
183
+ return Object.freeze({
184
+ importedIdentifier: input,
185
+ isType: false,
186
+ usedIdentifier: input
187
+ });
188
+ }
189
+ const [, isType, name, alias] = matches;
190
+ return Object.freeze({
191
+ importedIdentifier: name,
192
+ isType: !!isType,
193
+ usedIdentifier: alias ?? name
194
+ });
195
+ }
196
+
197
+ // src/javascript/mergeImportMaps.ts
198
+ function mergeImportMaps(importMaps) {
199
+ if (importMaps.length === 0) return createImportMap();
200
+ if (importMaps.length === 1) return importMaps[0];
201
+ const merged = new Map(importMaps[0]);
202
+ for (const map of importMaps.slice(1)) {
203
+ for (const [module, imports] of map) {
204
+ const moduleMap = new Map(
205
+ merged.get(module) ?? /* @__PURE__ */ new Map()
206
+ );
207
+ for (const [usedIdentifier, info] of imports) {
208
+ const existing = moduleMap.get(usedIdentifier);
209
+ if (preferIncoming(existing, info)) {
210
+ moduleMap.set(usedIdentifier, info);
211
+ }
212
+ }
213
+ merged.set(module, moduleMap);
214
+ }
215
+ }
216
+ return Object.freeze(merged);
217
+ }
218
+ function preferIncoming(existing, incoming) {
219
+ if (!existing) return true;
220
+ return existing.importedIdentifier === incoming.importedIdentifier && existing.isType && !incoming.isType;
221
+ }
222
+
223
+ // src/javascript/addToImportMap.ts
224
+ function addToImportMap(importMap, module, imports) {
225
+ if (imports.length === 0) return importMap;
226
+ const moduleMap = /* @__PURE__ */ new Map();
227
+ for (const input of imports) {
228
+ const info = parseImportInput(input);
229
+ const existing = moduleMap.get(info.usedIdentifier);
230
+ if (preferIncoming(existing, info)) {
231
+ moduleMap.set(info.usedIdentifier, info);
232
+ }
233
+ }
234
+ return mergeImportMaps([importMap, /* @__PURE__ */ new Map([[module, moduleMap]])]);
235
+ }
236
+
237
+ // src/javascript/removeFromImportMap.ts
238
+ function removeFromImportMap(importMap, module, usedIdentifiers) {
239
+ const next = new Map(importMap);
240
+ const moduleMap = new Map(next.get(module));
241
+ for (const id of usedIdentifiers) moduleMap.delete(id);
242
+ if (moduleMap.size === 0) {
243
+ next.delete(module);
244
+ } else {
245
+ next.set(module, moduleMap);
246
+ }
247
+ return Object.freeze(next);
248
+ }
249
+
250
+ // src/javascript/resolveImportMap.ts
251
+ function resolveImportMap(importMap, dependencies) {
252
+ if (importMap.size === 0) return importMap;
253
+ const perModule = [...importMap.entries()].map(
254
+ ([module, identifiers]) => {
255
+ const resolvedModule = dependencies[module] ?? module;
256
+ return /* @__PURE__ */ new Map([[resolvedModule, identifiers]]);
257
+ }
258
+ );
259
+ return mergeImportMaps(perModule);
260
+ }
261
+
262
+ // src/javascript/getExternalDependencies.ts
263
+ function getExternalDependencies(importMap, dependencies = {}) {
264
+ const resolved = resolveImportMap(importMap, dependencies);
265
+ const roots = /* @__PURE__ */ new Set();
266
+ for (const module of resolved.keys()) {
267
+ if (module.startsWith(".")) continue;
268
+ const segments = module.split("/");
269
+ const rootSegmentCount = module.startsWith("@") ? 2 : 1;
270
+ roots.add(segments.slice(0, rootSegmentCount).join("/"));
271
+ }
272
+ return roots;
273
+ }
274
+
275
+ // src/javascript/importMapToString.ts
276
+ function importMapToString(importMap, dependencies = {}) {
277
+ const resolved = resolveImportMap(importMap, dependencies);
278
+ return [...resolved.entries()].sort(([a], [b]) => {
279
+ const aRelative = a.startsWith(".") ? 1 : 0;
280
+ const bRelative = b.startsWith(".") ? 1 : 0;
281
+ if (aRelative !== bRelative) return aRelative - bRelative;
282
+ return a.localeCompare(b);
283
+ }).map(([module, imports]) => {
284
+ const infos = [...imports.values()];
285
+ const allTypeOnly = infos.length > 0 && infos.every((info) => info.isType);
286
+ const renderedIds = infos.map((info) => formatImportInfo(info, allTypeOnly)).sort((a, b) => a.localeCompare(b)).join(", ");
287
+ const prefix = allTypeOnly ? "import type " : "import ";
288
+ return `${prefix}{ ${renderedIds} } from '${module}';`;
289
+ }).join("\n");
290
+ }
291
+ function formatImportInfo(info, blockIsTypeOnly) {
292
+ const alias = info.importedIdentifier !== info.usedIdentifier ? ` as ${info.usedIdentifier}` : "";
293
+ const typePrefix = info.isType && !blockIsTypeOnly ? "type " : "";
294
+ return `${typePrefix}${info.importedIdentifier}${alias}`;
295
+ }
296
+
297
+ // src/javascript/fragment.ts
298
+ function isFragment(value) {
299
+ return typeof value === "object" && value !== null && "content" in value && "imports" in value;
300
+ }
301
+ function fragment(template, ...items) {
302
+ return createFragmentTemplate(template, items, isFragment, mergeFragments);
303
+ }
304
+ function mergeFragments(fragments, mergeContent) {
305
+ const filtered = fragments.filter((f) => f !== void 0);
306
+ return Object.freeze({
307
+ content: mergeContent(filtered.map((f) => f.content)),
308
+ imports: mergeImportMaps(filtered.map((f) => f.imports))
309
+ });
310
+ }
311
+ function use(importInput, module) {
312
+ const info = parseImportInput(importInput);
313
+ const empty = Object.freeze({ content: info.usedIdentifier, imports: createImportMap() });
314
+ return addFragmentImports(empty, module, [importInput]);
315
+ }
316
+ function addFragmentImports(fragment2, module, imports) {
317
+ return Object.freeze({
318
+ ...fragment2,
319
+ imports: addToImportMap(fragment2.imports, module, imports)
320
+ });
321
+ }
322
+ function mergeFragmentImports(fragment2, importMaps) {
323
+ return Object.freeze({
324
+ ...fragment2,
325
+ imports: mergeImportMaps([fragment2.imports, ...importMaps])
326
+ });
327
+ }
328
+ function removeFragmentImports(fragment2, module, usedIdentifiers) {
329
+ return Object.freeze({
330
+ ...fragment2,
331
+ imports: removeFromImportMap(fragment2.imports, module, usedIdentifiers)
332
+ });
333
+ }
334
+
335
+ // src/javascript/getDocblockFragment.ts
336
+ function getDocblockFragment(lines, options = {}) {
337
+ if (!lines || lines.length === 0) return void 0;
338
+ const lineJump = options.withLineJump ? "\n" : "";
339
+ const safeLines = lines.map(defang);
340
+ if (safeLines.length === 1) return fragment`/** ${safeLines[0]} */${lineJump}`;
341
+ const prefixedLines = safeLines.map((line) => line ? ` * ${line}` : " *");
342
+ return fragment`/**\n${prefixedLines.join("\n")}\n */${lineJump}`;
343
+ }
344
+ function defang(line) {
345
+ return line.replace(/\*\//g, "*\\/");
346
+ }
347
+
348
+ // src/javascript/getExportAllFragment.ts
349
+ function getExportAllFragment(module) {
350
+ return fragment`export * from '${module}';`;
351
+ }
352
+
353
+ exports.addFragmentImports = addFragmentImports;
354
+ exports.addToImportMap = addToImportMap;
355
+ exports.addToRenderMap = addToRenderMap;
356
+ exports.camelCase = camelCase;
357
+ exports.capitalize = capitalize;
358
+ exports.createDirectory = createDirectory;
359
+ exports.createFragmentTemplate = createFragmentTemplate;
360
+ exports.createImportMap = createImportMap;
361
+ exports.createRenderMap = createRenderMap;
362
+ exports.deleteDirectory = deleteDirectory;
363
+ exports.fileExists = fileExists;
364
+ exports.fragment = fragment;
365
+ exports.getDocblockFragment = getDocblockFragment;
366
+ exports.getExportAllFragment = getExportAllFragment;
367
+ exports.getExternalDependencies = getExternalDependencies;
368
+ exports.getFromRenderMap = getFromRenderMap;
369
+ exports.importMapToString = importMapToString;
370
+ exports.isFragment = isFragment;
371
+ exports.joinPath = joinPath;
372
+ exports.kebabCase = kebabCase;
373
+ exports.mapFragmentContent = mapFragmentContent;
374
+ exports.mapFragmentContentAsync = mapFragmentContentAsync;
375
+ exports.mapRenderMapContent = mapRenderMapContent;
376
+ exports.mapRenderMapContentAsync = mapRenderMapContentAsync;
377
+ exports.mapRenderMapFragment = mapRenderMapFragment;
378
+ exports.mapRenderMapFragmentAsync = mapRenderMapFragmentAsync;
379
+ exports.mergeFragmentImports = mergeFragmentImports;
380
+ exports.mergeFragments = mergeFragments;
381
+ exports.mergeImportMaps = mergeImportMaps;
382
+ exports.mergeRenderMaps = mergeRenderMaps;
383
+ exports.parseImportInput = parseImportInput;
384
+ exports.pascalCase = pascalCase;
385
+ exports.pathBasename = pathBasename;
386
+ exports.pathDirectory = pathDirectory;
387
+ exports.preferIncoming = preferIncoming;
388
+ exports.readFile = readFile;
389
+ exports.readJson = readJson;
390
+ exports.relativePath = relativePath;
391
+ exports.removeFragmentImports = removeFragmentImports;
392
+ exports.removeFromImportMap = removeFromImportMap;
393
+ exports.removeFromRenderMap = removeFromRenderMap;
394
+ exports.renderMapContains = renderMapContains;
395
+ exports.resolveImportMap = resolveImportMap;
396
+ exports.setFragmentContent = setFragmentContent;
397
+ exports.snakeCase = snakeCase;
398
+ exports.titleCase = titleCase;
399
+ exports.use = use;
400
+ exports.writeFile = writeFile;
401
+ exports.writeRenderMap = writeRenderMap;
402
+ //# sourceMappingURL=javascript.browser.cjs.map
403
+ //# sourceMappingURL=javascript.browser.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/casing.ts","../src/core/createFragmentTemplate.ts","../src/core/path.ts","../src/core/fs.ts","../src/core/setFragmentContent.ts","../src/core/mapFragmentContent.ts","../src/core/renderMap.ts","../src/javascript/ImportMap.ts","../src/javascript/mergeImportMaps.ts","../src/javascript/addToImportMap.ts","../src/javascript/removeFromImportMap.ts","../src/javascript/resolveImportMap.ts","../src/javascript/getExternalDependencies.ts","../src/javascript/importMapToString.ts","../src/javascript/fragment.ts","../src/javascript/getDocblockFragment.ts","../src/javascript/getExportAllFragment.ts"],"names":["isFragment","mergeFragments","CodamaError","CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE","fragment","CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND","relativePath"],"mappings":"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","file":"javascript.browser.cjs","sourcesContent":["/**\n * String-casing helpers used by code generators when emitting\n * identifiers. They normalise an arbitrary input string into a\n * conventional shape (camelCase, PascalCase, kebab-case, snake_case,\n * Title Case) by inserting word boundaries before uppercase letters and\n * splitting on any sequence of non-alphanumeric characters.\n *\n * Returned values are plain `string`. This package deliberately does\n * not depend on `@codama/node-types`, so the branded `CamelCaseString`\n * / `PascalCaseString` / … types are not applied here. Consumers that\n * want the brand (e.g. `@codama/nodes`) can wrap these helpers and\n * apply the cast at their own boundary.\n *\n * The implementations all run through {@link titleCase} as a common\n * intermediate form, so a single deterministic word-splitting policy\n * is shared across every output shape.\n */\n\n/**\n * Uppercase the first character and lowercase the rest. Returns the\n * input unchanged when it is empty.\n */\nexport function capitalize(str: string): string {\n if (str.length === 0) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into Title Case — a space-separated\n * sequence of {@link capitalize}d words. Inserts a space before each\n * uppercase letter, then splits on any run of non-alphanumeric\n * characters and re-joins with single spaces.\n */\nexport function titleCase(str: string): string {\n return str\n .replace(/([A-Z])/g, ' $1')\n .split(/[^a-zA-Z0-9]+/)\n .filter(word => word.length > 0)\n .map(capitalize)\n .join(' ');\n}\n\n/**\n * Normalise an arbitrary string into PascalCase by stripping the\n * spaces from its {@link titleCase} form.\n */\nexport function pascalCase(str: string): string {\n return titleCase(str).split(' ').join('');\n}\n\n/**\n * Normalise an arbitrary string into camelCase by lowercasing the\n * first character of its {@link pascalCase} form.\n */\nexport function camelCase(str: string): string {\n if (str.length === 0) return str;\n const pascalStr = pascalCase(str);\n return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);\n}\n\n/**\n * Normalise an arbitrary string into kebab-case — lowercase words\n * joined with `-` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function kebabCase(str: string): string {\n return titleCase(str).split(' ').join('-').toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into snake_case — lowercase words\n * joined with `_` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function snakeCase(str: string): string {\n return titleCase(str).split(' ').join('_').toLowerCase();\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Generic template-tag implementation used by every flavor's `fragment`\n * tagged template.\n *\n * Walks the template/items pair, interpolating fragments verbatim and\n * coercing other values to strings, then defers to the caller-provided\n * `mergeFragments` for combining the surviving sub-fragments. This keeps the\n * fragment shape (imports, features, etc.) opaque to the core layer; each\n * flavor plugs in its own merge logic.\n *\n * Most consumers never call this directly — they use the `fragment` tag\n * exported by `@codama/fragments/javascript` or `@codama/fragments/rust`,\n * which both wrap this helper.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param template - The template-strings array supplied by the tag call site.\n * @param items - The interpolated values, in order. May be fragments,\n * strings, numbers, booleans, `undefined`, or anything coercible to a string.\n * @param isFragment - A predicate that identifies values of the concrete\n * fragment type so they can be inlined and forwarded to the merger.\n * @param mergeFragments - The flavor-specific merger that knows how to\n * combine fragments' non-content fields (e.g. imports, features). Receives\n * only the sub-fragments found in the template, plus a callback that\n * produces the final merged content string from each sub-fragment's content.\n * @return The fragment produced by `mergeFragments`.\n *\n * @example\n * ```ts\n * import { createFragmentTemplate } from '@codama/fragments';\n *\n * function fragment(template: TemplateStringsArray, ...items: unknown[]) {\n * return createFragmentTemplate(template, items, isFragment, mergeFragments);\n * }\n * ```\n */\nexport function createFragmentTemplate<TFragment extends BaseFragment>(\n template: TemplateStringsArray,\n items: unknown[],\n isFragment: (value: unknown) => value is TFragment,\n mergeFragments: (fragments: TFragment[], mergeContent: (contents: string[]) => string) => TFragment,\n): TFragment {\n const fragments = items.filter(isFragment);\n const zippedItems = items.map((item, i) => {\n const itemPrefix = template[i];\n if (typeof item === 'undefined') return itemPrefix;\n if (isFragment(item)) return itemPrefix + item.content;\n return itemPrefix + String(item as string);\n });\n return mergeFragments(fragments, () => zippedItems.join('') + template[template.length - 1]);\n}\n","/**\n * Path manipulation helpers used by code generators to assemble output\n * file paths.\n *\n * The {@link Path} type is a thin documentation alias for `string` —\n * any place a generator stores or threads a filesystem-relative path,\n * use this name to communicate intent. The {@link joinPath} and\n * {@link pathDirectory} helpers delegate to `node:path` on Node and\n * fall back to lightweight string manipulation on non-Node platforms.\n */\n\nimport { basename, dirname, join, posix } from 'node:path';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\n/** A filesystem path inside the generator's output tree. */\nexport type Path = string;\n\n/**\n * Join two or more path segments together. Uses `node:path`'s\n * platform-aware {@link join} on Node; on other platforms (browser,\n * react-native) falls back to a `/`-joined form with consecutive\n * slashes collapsed.\n */\nexport function joinPath(...paths: Path[]): string {\n if (!__NODEJS__) {\n return paths.join('/').replace(/\\/+/g, '/');\n }\n\n return join(...paths);\n}\n\n/**\n * Return the directory portion of a path (i.e. everything up to the\n * last `/` segment). Uses `node:path`'s {@link dirname} on Node and a\n * plain `lastIndexOf` fallback on other platforms.\n */\nexport function pathDirectory(path: Path): Path {\n if (!__NODEJS__) {\n return path.substring(0, path.lastIndexOf('/'));\n }\n\n return dirname(path);\n}\n\n/**\n * Return the trailing segment of a path (everything after the last\n * `/`). Uses `node:path`'s {@link basename} on Node and a plain\n * `lastIndexOf` fallback on other platforms.\n */\nexport function pathBasename(path: Path): Path {\n if (!__NODEJS__) {\n const slash = path.lastIndexOf('/');\n return slash >= 0 ? path.substring(slash + 1) : path;\n }\n\n return basename(path);\n}\n\n/**\n * Compute the POSIX-style relative path from `from` to `to`. Both\n * arguments are treated as `/`-separated logical paths regardless of\n * platform, so the result is consistent across operating systems —\n * suitable for emitting into source code as an import specifier.\n *\n * Node only: non-Node platforms throw {@link CodamaError} because\n * implementing a correct POSIX relative-path algorithm without\n * `node:path` is non-trivial and no current consumer needs it.\n */\nexport function relativePath(from: Path, to: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'relative' });\n }\n\n return posix.relative(from, to);\n}\n","/**\n * Node-only filesystem helpers used by code generators to write their\n * output to disk. Each function checks the `__NODEJS__` build flag and\n * throws a structured {@link CodamaError} on non-Node platforms so\n * accidental calls from a browser bundle fail loudly rather than\n * silently no-oping.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\nimport { Path, pathDirectory } from './path';\n\n/** Create a directory (and any missing parents) at the given path. */\nexport function createDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'mkdirSync' });\n }\n\n mkdirSync(path, { recursive: true });\n}\n\n/** Recursively delete the directory at the given path, if it exists. */\nexport function deleteDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'rmSync' });\n }\n\n if (existsSync(path)) {\n rmSync(path, { recursive: true });\n }\n}\n\n/**\n * Write `content` to a file at `path`, creating intermediate\n * directories as needed.\n */\nexport function writeFile(path: Path, content: string): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'writeFileSync' });\n }\n\n const directory = pathDirectory(path);\n if (!existsSync(directory)) {\n createDirectory(directory);\n }\n writeFileSync(path, content);\n}\n\n/** Check whether a file or directory exists at the given path. */\nexport function fileExists(path: Path): boolean {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'existsSync' });\n }\n\n return existsSync(path);\n}\n\n/** Read the file at the given path as a UTF-8 string. */\nexport function readFile(path: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'readFileSync' });\n }\n\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Read the file at the given path as a UTF-8 string and parse it as\n * JSON. The result is typed as the caller-supplied `T`; no runtime\n * validation is performed.\n */\nexport function readJson<T>(path: Path): T {\n return JSON.parse(readFile(path)) as T;\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Return a new frozen fragment whose `content` field has been replaced with\n * `content`, preserving every other field of the input fragment.\n *\n * The output keeps the input's exact concrete type (`TFragment`) so callers\n * never lose any extra fields a flavored fragment may carry (imports,\n * features, etc.).\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment to copy.\n * @param content - The new code string.\n * @return A frozen fragment of the same shape as `fragment` with `content` replaced.\n *\n * @example\n * ```ts\n * import { setFragmentContent } from '@codama/fragments';\n *\n * const next = setFragmentContent(prev, prev.content.toUpperCase());\n * ```\n */\nexport function setFragmentContent<TFragment extends BaseFragment>(fragment: TFragment, content: string): TFragment {\n return Object.freeze({ ...fragment, content });\n}\n","import type { BaseFragment } from './BaseFragment';\nimport { setFragmentContent } from './setFragmentContent';\n\n/**\n * Apply a synchronous transformation to a fragment's `content`, returning a\n * new fragment with every other field preserved.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - A function that receives the current content and\n * returns the new content.\n * @return A frozen fragment with the transformed content.\n *\n * @example\n * ```ts\n * import { mapFragmentContent } from '@codama/fragments';\n *\n * const trimmed = mapFragmentContent(fragment, c => c.trimEnd());\n * ```\n *\n * @see {@link mapFragmentContentAsync} for the async variant.\n */\nexport function mapFragmentContent<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => string,\n): TFragment {\n return setFragmentContent(fragment, mapContent(fragment.content));\n}\n\n/**\n * Async variant of {@link mapFragmentContent}: apply an async transformation\n * to a fragment's `content`.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - An async function that receives the current content\n * and returns a promise resolving to the new content.\n * @return A promise that resolves to a frozen fragment with the transformed\n * content.\n *\n * @example\n * ```ts\n * import { mapFragmentContentAsync } from '@codama/fragments';\n *\n * const formatted = await mapFragmentContentAsync(fragment, formatWithPrettier);\n * ```\n *\n * @see {@link mapFragmentContent} for the sync variant.\n */\nexport async function mapFragmentContentAsync<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => Promise<string>,\n): Promise<TFragment> {\n return setFragmentContent(fragment, await mapContent(fragment.content));\n}\n","/**\n * A `RenderMap` is the in-memory data structure a code generator builds\n * up before writing anything to disk: a frozen `ReadonlyMap` keyed by\n * output path, with a `BaseFragment` (or a concrete subtype carrying\n * imports / features / …) as the value. The helpers in this module are\n * pure data operations — they construct, merge, transform, and query\n * render maps without touching the filesystem.\n *\n * {@link writeRenderMap} is the single filesystem-touching entry point\n * here: it walks a finished map and writes every entry. Renderers that\n * tie a render map to a `Visitor` (see `@codama/renderers-core`) layer\n * that on top.\n */\n\nimport { CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, CodamaError } from '@codama/errors';\n\nimport type { BaseFragment } from './BaseFragment';\nimport { writeFile } from './fs';\nimport { mapFragmentContent, mapFragmentContentAsync } from './mapFragmentContent';\nimport { joinPath, type Path } from './path';\n\n/**\n * A frozen map keyed by output {@link Path}, with each entry holding a\n * fragment that will be written to that path. `TFragment` defaults to\n * {@link BaseFragment} but generators typically pass a richer flavor\n * (e.g. `Fragment` from `@codama/fragments/javascript`) to carry\n * imports and other per-file metadata.\n */\nexport type RenderMap<TFragment extends BaseFragment> = ReadonlyMap<Path, TFragment>;\n\nexport function createRenderMap<TFragment extends BaseFragment = BaseFragment>(): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(path: Path, content: TFragment): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n entries: Record<Path, TFragment | undefined>,\n): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n pathOrEntries?: Path | Record<Path, TFragment | undefined>,\n content?: TFragment,\n): RenderMap<TFragment> {\n let entries: [Path, TFragment][] = [];\n if (typeof pathOrEntries === 'string' && content !== undefined) {\n entries = [[pathOrEntries, content]];\n } else if (typeof pathOrEntries === 'object' && pathOrEntries !== null) {\n entries = Object.entries(pathOrEntries).flatMap(([key, value]) =>\n value === undefined ? [] : ([[key, value]] as const),\n );\n }\n return Object.freeze(new Map(entries));\n}\n\n/** Add or overwrite a single `(path, fragment)` entry. */\nexport function addToRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n content: TFragment,\n): RenderMap<TFragment> {\n return mergeRenderMaps([renderMap, createRenderMap(path, content)]);\n}\n\n/** Remove the entry at `path`, returning a new frozen map. */\nexport function removeFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): RenderMap<TFragment> {\n const newMap = new Map(renderMap);\n newMap.delete(path);\n return Object.freeze(newMap);\n}\n\n/**\n * Combine multiple render maps into one. Later maps overwrite earlier\n * entries at the same path.\n */\nexport function mergeRenderMaps<TFragment extends BaseFragment>(\n renderMaps: RenderMap<TFragment>[],\n): RenderMap<TFragment> {\n if (renderMaps.length === 0) return createRenderMap();\n if (renderMaps.length === 1) return renderMaps[0];\n const merged = new Map(renderMaps[0]);\n for (const map of renderMaps.slice(1)) {\n for (const [key, value] of map) {\n merged.set(key, value);\n }\n }\n return Object.freeze(merged);\n}\n\n/** Transform every fragment in the map, preserving the keys. */\nexport function mapRenderMapFragment<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => TFragment,\n): RenderMap<TFragment> {\n return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)] as const)]));\n}\n\n/** Async variant of {@link mapRenderMapFragment}. */\nexport async function mapRenderMapFragmentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => Promise<TFragment>,\n): Promise<RenderMap<TFragment>> {\n return Object.freeze(\n new Map(\n await Promise.all([\n ...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)] as const),\n ]),\n ),\n );\n}\n\n/** Transform the `content` of every fragment in the map. */\nexport function mapRenderMapContent<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => string,\n): RenderMap<TFragment> {\n return mapRenderMapFragment(renderMap, (fragment, path) =>\n mapFragmentContent(fragment, content => fn(content, path)),\n );\n}\n\n/** Async variant of {@link mapRenderMapContent}. */\nexport async function mapRenderMapContentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => Promise<string>,\n): Promise<RenderMap<TFragment>> {\n return await mapRenderMapFragmentAsync(renderMap, (fragment, path) =>\n mapFragmentContentAsync(fragment, content => fn(content, path)),\n );\n}\n\n/**\n * Look up the fragment at `path`, throwing a structured\n * {@link CodamaError} when the key is missing.\n */\nexport function getFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): TFragment {\n const value = renderMap.get(path);\n if (value === undefined) {\n throw new CodamaError(CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });\n }\n return value;\n}\n\n/**\n * Test whether the fragment at `path` contains `value`. Accepts either\n * a plain substring or a regular expression.\n */\nexport function renderMapContains<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n value: RegExp | string,\n): boolean {\n const { content } = getFromRenderMap(renderMap, path);\n return typeof value === 'string' ? content.includes(value) : value.test(content);\n}\n\n/**\n * Walk the render map and write every entry to disk, rooted at\n * `basePath`. Each path is joined with `basePath` via {@link joinPath}\n * and written via {@link writeFile}; the directory structure is\n * created on demand.\n */\nexport function writeRenderMap<TFragment extends BaseFragment>(renderMap: RenderMap<TFragment>, basePath: Path): void {\n renderMap.forEach(({ content }, relativePath) => {\n writeFile(joinPath(basePath, relativePath), content);\n });\n}\n","/**\n * The data model used by `@codama/fragments/javascript` to track imports\n * symbolically until they are stringified into actual `import { … } from '…';`\n * lines.\n *\n * Imports are accumulated as a `ReadonlyMap<Module, ReadonlyMap<UsedIdentifier, ImportInfo>>`:\n * outer key is the source module, inner key is the identifier used in the\n * consuming code (which may differ from the imported name via aliasing).\n *\n * The format accepted by {@link parseImportInput} is a single string with\n * the same shorthand TypeScript itself uses inside an `import { … }` block:\n *\n * `Foo` — value import; used as `Foo`\n * `type Foo` — type-only import; used as `Foo`\n * `Foo as Bar` — value import aliased; used as `Bar`\n * `type Foo as Bar` — type-only import aliased; used as `Bar`\n */\n\n/** A single import shorthand string. See the file-level docblock for the accepted forms. */\nexport type ImportInput = string;\n\n/** A module path: either an absolute (`@scope/pkg`, `pkg`, `pkg/sub`) or a relative (`./foo`, `../bar`) specifier. */\nexport type Module = string;\n\n/** The identifier as it appears in the consuming code (after aliasing). */\nexport type UsedIdentifier = string;\n\n/** A parsed import shorthand. */\nexport interface ImportInfo {\n readonly importedIdentifier: string;\n readonly isType: boolean;\n readonly usedIdentifier: UsedIdentifier;\n}\n\n/** A symbolic import map keyed by module, then by used identifier. */\nexport type ImportMap = ReadonlyMap<Module, ReadonlyMap<UsedIdentifier, ImportInfo>>;\n\n/**\n * Construct an empty, frozen import map.\n *\n * @return A new {@link ImportMap} with no entries.\n *\n * @example\n * ```ts\n * import { createImportMap } from '@codama/fragments/javascript';\n *\n * const empty = createImportMap();\n * ```\n */\nexport function createImportMap(): ImportMap {\n return Object.freeze(new Map());\n}\n\n/**\n * Parse a single import shorthand (e.g. `'type Foo as Bar'`) into a\n * structured {@link ImportInfo}.\n *\n * @param input - The shorthand string to parse.\n * @return The parsed info. If the shorthand can't be matched (e.g. it\n * contains illegal whitespace), the entire string is returned unchanged as\n * both the imported and used identifier, with `isType: false`.\n *\n * @example\n * ```ts\n * parseImportInput('Foo'); // { importedIdentifier: 'Foo', usedIdentifier: 'Foo', isType: false }\n * parseImportInput('type Foo as Bar'); // { importedIdentifier: 'Foo', usedIdentifier: 'Bar', isType: true }\n * ```\n */\nexport function parseImportInput(input: ImportInput): ImportInfo {\n const matches = /^(type )?([^ ]+)(?: as (.+))?$/.exec(input);\n if (!matches) {\n return Object.freeze({\n importedIdentifier: input,\n isType: false,\n usedIdentifier: input,\n });\n }\n const [, isType, name, alias] = matches;\n return Object.freeze({\n importedIdentifier: name,\n isType: !!isType,\n usedIdentifier: alias ?? name,\n });\n}\n","import type { ImportInfo, ImportMap, Module, UsedIdentifier } from './ImportMap';\nimport { createImportMap } from './ImportMap';\n\n/**\n * Merge multiple import maps into one. Modules and identifiers from later\n * maps are layered over earlier ones; collisions on the same `usedIdentifier`\n * are resolved by {@link preferIncoming}.\n *\n * The merge is a pure function: input maps are not mutated. The returned map\n * is frozen.\n *\n * @param importMaps - The import maps to merge, in priority order.\n * @return A frozen import map that contains every entry from every input.\n *\n * @example\n * ```ts\n * import { addToImportMap, createImportMap, mergeImportMaps } from '@codama/fragments/javascript';\n *\n * const a = addToImportMap(createImportMap(), './foo', ['Foo']);\n * const b = addToImportMap(createImportMap(), './bar', ['Bar']);\n * const merged = mergeImportMaps([a, b]);\n * ```\n */\nexport function mergeImportMaps(importMaps: readonly ImportMap[]): ImportMap {\n if (importMaps.length === 0) return createImportMap();\n if (importMaps.length === 1) return importMaps[0];\n const merged = new Map(importMaps[0]);\n for (const map of importMaps.slice(1)) {\n for (const [module, imports] of map) {\n const moduleMap = new Map<UsedIdentifier, ImportInfo>(\n merged.get(module) ?? new Map<UsedIdentifier, ImportInfo>(),\n );\n for (const [usedIdentifier, info] of imports) {\n const existing = moduleMap.get(usedIdentifier);\n if (preferIncoming(existing, info)) {\n moduleMap.set(usedIdentifier, info);\n }\n }\n merged.set(module, moduleMap);\n }\n }\n return Object.freeze(merged) as ReadonlyMap<Module, ReadonlyMap<UsedIdentifier, ImportInfo>>;\n}\n\n/**\n * Decide whether an incoming `ImportInfo` should replace an existing entry\n * for the same `usedIdentifier`.\n *\n * The single rule we apply: if both refer to the same source identifier and\n * one is type-only while the other is a value import, the value import wins.\n * In every other \"tied\" case the existing entry stays. This keeps a value\n * import from being silently downgraded to type-only when both are\n * encountered.\n */\nexport function preferIncoming(existing: ImportInfo | undefined, incoming: ImportInfo): boolean {\n if (!existing) return true;\n return existing.importedIdentifier === incoming.importedIdentifier && existing.isType && !incoming.isType;\n}\n","import type { ImportInfo, ImportInput, ImportMap, Module, UsedIdentifier } from './ImportMap';\nimport { parseImportInput } from './ImportMap';\nimport { mergeImportMaps, preferIncoming } from './mergeImportMaps';\n\n/**\n * Append imports to a module entry, returning a new frozen import map. The\n * input map is not mutated.\n *\n * Within a single batch, the same conflict-resolution rule that\n * {@link mergeImportMaps} uses is applied — a value import always wins over\n * a type-only import of the same identifier — so callers don't have to\n * worry about input order when passing both.\n *\n * @param importMap - The import map to extend.\n * @param module - The source module the imports come from.\n * @param imports - The shorthand strings to add. Empty array short-circuits\n * and returns `importMap` unchanged.\n * @return A frozen import map that includes the new entries.\n *\n * @example\n * ```ts\n * import { addToImportMap, createImportMap } from '@codama/fragments/javascript';\n *\n * const map = addToImportMap(createImportMap(), './foo', ['type Foo', 'Bar']);\n * ```\n */\nexport function addToImportMap(importMap: ImportMap, module: Module, imports: ImportInput[]): ImportMap {\n if (imports.length === 0) return importMap;\n const moduleMap = new Map<UsedIdentifier, ImportInfo>();\n for (const input of imports) {\n const info = parseImportInput(input);\n const existing = moduleMap.get(info.usedIdentifier);\n if (preferIncoming(existing, info)) {\n moduleMap.set(info.usedIdentifier, info);\n }\n }\n return mergeImportMaps([importMap, new Map([[module, moduleMap]])]);\n}\n","import type { ImportMap, Module, UsedIdentifier } from './ImportMap';\n\n/**\n * Remove identifiers from a module entry. If the module ends up with no\n * remaining identifiers, the module entry itself is dropped from the map.\n *\n * @param importMap - The import map to modify.\n * @param module - The source module to remove identifiers from.\n * @param usedIdentifiers - The used-identifier names to drop. Names that\n * aren't present in the module entry are silently ignored.\n * @return A new frozen import map without those identifiers.\n *\n * @example\n * ```ts\n * import { addToImportMap, createImportMap, removeFromImportMap } from '@codama/fragments/javascript';\n *\n * let map = addToImportMap(createImportMap(), './foo', ['Foo', 'Bar']);\n * map = removeFromImportMap(map, './foo', ['Foo']);\n * ```\n */\nexport function removeFromImportMap(\n importMap: ImportMap,\n module: Module,\n usedIdentifiers: UsedIdentifier[],\n): ImportMap {\n const next = new Map(importMap);\n const moduleMap = new Map(next.get(module));\n for (const id of usedIdentifiers) moduleMap.delete(id);\n if (moduleMap.size === 0) {\n next.delete(module);\n } else {\n next.set(module, moduleMap);\n }\n return Object.freeze(next);\n}\n","import type { ImportInfo, ImportMap, Module, UsedIdentifier } from './ImportMap';\nimport { mergeImportMaps } from './mergeImportMaps';\n\n/**\n * Rewrite a JavaScript import map's module keys against a dependency map.\n *\n * Resolution is by exact module-name lookup: a module key `'solanaAddresses'`\n * against `{ solanaAddresses: '@solana/kit' }` becomes `'@solana/kit'`.\n * Keys that aren't present in `dependencies` are kept unchanged. The\n * inner `UsedIdentifier → ImportInfo` map for each module is preserved\n * exactly. When two source modules resolve to the same target, their\n * inner maps are merged via {@link mergeImportMaps}.\n *\n * Renderers typically pre-define a base set of symbolic modules\n * (`solanaAddresses → @solana/kit`, `generated → ..`, etc.) and pass\n * them through this function just before calling\n * {@link importMapToString} or {@link getExternalDependencies}.\n *\n * @param importMap - The import map to resolve.\n * @param dependencies - A record mapping symbolic module names to\n * resolved module specifiers.\n * @return A new frozen import map with all module keys resolved.\n *\n * @example\n * ```ts\n * import { addToImportMap, createImportMap, resolveImportMap } from '@codama/fragments/javascript';\n *\n * let map = createImportMap();\n * map = addToImportMap(map, 'solanaAddresses', ['Address']);\n * const resolved = resolveImportMap(map, { solanaAddresses: '@solana/kit' });\n * // resolved keys: ['@solana/kit']\n * ```\n */\nexport function resolveImportMap(importMap: ImportMap, dependencies: Record<string, string>): ImportMap {\n if (importMap.size === 0) return importMap;\n const perModule: ReadonlyMap<Module, ReadonlyMap<UsedIdentifier, ImportInfo>>[] = [...importMap.entries()].map(\n ([module, identifiers]) => {\n const resolvedModule = dependencies[module] ?? module;\n return new Map([[resolvedModule, identifiers]]);\n },\n );\n return mergeImportMaps(perModule);\n}\n","import type { ImportMap } from './ImportMap';\nimport { resolveImportMap } from './resolveImportMap';\n\n/**\n * Compute the set of external (non-relative) module specifiers an import\n * map references, with dependency-map resolution applied first. The\n * returned values are *root* package names — for `'@scope/pkg/sub'` the\n * value is `'@scope/pkg'`, and for `'pkg/sub'` it is `'pkg'`.\n *\n * Useful for syncing a renderer's generated `package.json` from the\n * imports it ends up emitting.\n *\n * @param importMap - The import map to inspect.\n * @param dependencies - The dependency map to apply before extracting\n * names. Defaults to no resolution.\n * @return A {@link Set} of external root package names.\n *\n * @example\n * ```ts\n * import { addToImportMap, createImportMap, getExternalDependencies } from '@codama/fragments/javascript';\n *\n * let map = createImportMap();\n * map = addToImportMap(map, '@solana/kit', ['Address']);\n * map = addToImportMap(map, '@solana/kit/program-client-core', ['ProgramClient']);\n * map = addToImportMap(map, '../shared', ['Local']);\n * getExternalDependencies(map);\n * // → Set { '@solana/kit' }\n * ```\n */\nexport function getExternalDependencies(importMap: ImportMap, dependencies: Record<string, string> = {}): Set<string> {\n const resolved = resolveImportMap(importMap, dependencies);\n const roots = new Set<string>();\n for (const module of resolved.keys()) {\n if (module.startsWith('.')) continue;\n const segments = module.split('/');\n const rootSegmentCount = module.startsWith('@') ? 2 : 1;\n roots.add(segments.slice(0, rootSegmentCount).join('/'));\n }\n return roots;\n}\n","import type { ImportInfo, ImportMap } from './ImportMap';\nimport { resolveImportMap } from './resolveImportMap';\n\n/**\n * Render an import map as a block of TypeScript `import { … } from '…';`\n * statements.\n *\n * The map is first resolved against `dependencies` so symbolic module\n * names (e.g. `'solanaAddresses'`, `'generatedAccounts'`) expand to real\n * specifiers; renderers that don't use symbolic names can omit the\n * argument.\n *\n * Output rules:\n * - Modules are sorted with non-relative paths first, then relative;\n * within each group, alphabetical.\n * - Identifiers within each module are alphabetical.\n * - When every import from a given module is type-only, the line is\n * emitted as `import type { … } from '…';` rather than per-identifier\n * `type` — matching the `@solana/eslint-config-solana`\n * consolidate-type-imports convention used across the Codama\n * published surface.\n *\n * @param importMap - The import map to render.\n * @param dependencies - The dependency map to apply before rendering.\n * Defaults to no resolution.\n * @return The block of import lines, or the empty string if the map is\n * empty.\n *\n * @example\n * ```ts\n * import { addToImportMap, createImportMap, importMapToString } from '@codama/fragments/javascript';\n *\n * let map = createImportMap();\n * map = addToImportMap(map, '@codama/spec', ['type Spec']);\n * map = addToImportMap(map, '../shared', ['CamelCaseString']);\n * importMapToString(map);\n * // import type { Spec } from '@codama/spec';\n * // import { CamelCaseString } from '../shared';\n * ```\n */\nexport function importMapToString(importMap: ImportMap, dependencies: Record<string, string> = {}): string {\n const resolved = resolveImportMap(importMap, dependencies);\n return [...resolved.entries()]\n .sort(([a], [b]) => {\n const aRelative = a.startsWith('.') ? 1 : 0;\n const bRelative = b.startsWith('.') ? 1 : 0;\n if (aRelative !== bRelative) return aRelative - bRelative;\n return a.localeCompare(b);\n })\n .map(([module, imports]) => {\n const infos = [...imports.values()];\n const allTypeOnly = infos.length > 0 && infos.every(info => info.isType);\n const renderedIds = infos\n .map(info => formatImportInfo(info, allTypeOnly))\n .sort((a, b) => a.localeCompare(b))\n .join(', ');\n const prefix = allTypeOnly ? 'import type ' : 'import ';\n return `${prefix}{ ${renderedIds} } from '${module}';`;\n })\n .join('\\n');\n}\n\nfunction formatImportInfo(info: ImportInfo, blockIsTypeOnly: boolean): string {\n const alias = info.importedIdentifier !== info.usedIdentifier ? ` as ${info.usedIdentifier}` : '';\n // Drop the per-identifier `type` prefix when the whole block is already\n // declared as a type-only import.\n const typePrefix = info.isType && !blockIsTypeOnly ? 'type ' : '';\n return `${typePrefix}${info.importedIdentifier}${alias}`;\n}\n","import type { BaseFragment } from '../core/BaseFragment';\nimport { createFragmentTemplate } from '../core/createFragmentTemplate';\nimport { addToImportMap } from './addToImportMap';\nimport type { ImportInput, ImportMap, Module, UsedIdentifier } from './ImportMap';\nimport { createImportMap, parseImportInput } from './ImportMap';\nimport { mergeImportMaps } from './mergeImportMaps';\nimport { removeFromImportMap } from './removeFromImportMap';\n\n/**\n * The JavaScript-flavored fragment shape: {@link BaseFragment} plus a\n * symbolic {@link ImportMap} carrying the imports the content depends on.\n *\n * Fragments are frozen and composable — interpolating one into another\n * (via the {@link fragment} tag) propagates both content and imports, so\n * generators can build code top-down without threading import bookkeeping\n * through every helper.\n */\nexport type Fragment = BaseFragment & Readonly<{ imports: ImportMap }>;\n\n/**\n * Type guard for the JavaScript-flavored {@link Fragment} shape.\n *\n * @param value - The value to test.\n * @return `true` when `value` is an object carrying both `content` and\n * `imports` fields. The check is structural; downstream code that layers\n * extra fields on top (e.g. a renderer's `features` set) will still match.\n */\nexport function isFragment(value: unknown): value is Fragment {\n return typeof value === 'object' && value !== null && 'content' in value && 'imports' in value;\n}\n\n/**\n * Tagged-template helper for composing JavaScript-flavored fragments.\n * Interpolated values may be:\n *\n * - A {@link Fragment} — content is inlined and imports propagate.\n * - `undefined` — rendered as the empty string (handy for optional\n * sub-fragments).\n * - Anything else — coerced to a string via `String(value)`.\n *\n * @param template - The template-strings array supplied by the tag call site.\n * @param items - The interpolated values, in order.\n * @return A frozen {@link Fragment} with the merged content and imports.\n *\n * @example\n * ```ts\n * import { fragment, use } from '@codama/fragments/javascript';\n *\n * const pdaLink = use('type PdaLinkNode', '../linkNodes/PdaLinkNode');\n * const body = fragment`\n * export interface AccountNode {\n * readonly pda?: ${pdaLink};\n * }\n * `;\n * ```\n */\nexport function fragment(template: TemplateStringsArray, ...items: unknown[]): Fragment {\n return createFragmentTemplate(template, items, isFragment, mergeFragments);\n}\n\n/**\n * Combine multiple fragments into one. The merge strategy for content is\n * supplied by the caller (`mergeContent`); imports are merged automatically\n * via {@link mergeImportMaps}. Undefined inputs are skipped.\n *\n * @param fragments - The fragments to merge, in order.\n * @param mergeContent - A function that produces the final content string\n * from each surviving fragment's content.\n * @return A frozen merged {@link Fragment}.\n *\n * @example\n * ```ts\n * import { fragment, mergeFragments } from '@codama/fragments/javascript';\n *\n * const merged = mergeFragments(\n * [fragment`a`, fragment`b`, fragment`c`],\n * parts => parts.join(', '),\n * );\n * ```\n */\nexport function mergeFragments(\n fragments: readonly (Fragment | undefined)[],\n mergeContent: (contents: string[]) => string,\n): Fragment {\n const filtered = fragments.filter((f): f is Fragment => f !== undefined);\n return Object.freeze({\n content: mergeContent(filtered.map(f => f.content)),\n imports: mergeImportMaps(filtered.map(f => f.imports)),\n });\n}\n\n/**\n * Construct a fragment whose content is a single imported identifier and\n * whose import map carries the corresponding import statement.\n *\n * The shorthand accepted in `importInput` is the same as\n * {@link parseImportInput}'s — bare names, `type`-prefixed names, and\n * `as`-aliased names are all supported.\n *\n * @param importInput - The import shorthand (e.g. `'Foo'`, `'type Foo'`,\n * `'Foo as Bar'`).\n * @param module - The module the identifier comes from.\n * @return A frozen {@link Fragment} ready to be interpolated into other\n * fragments.\n *\n * @example\n * ```ts\n * import { use } from '@codama/fragments/javascript';\n *\n * use('PdaLinkNode', '../linkNodes/PdaLinkNode');\n * // → content: 'PdaLinkNode'\n * // imports: { '../linkNodes/PdaLinkNode' → PdaLinkNode (value) }\n *\n * use('type Foo as Bar', './foo');\n * // → content: 'Bar'\n * // imports: { './foo' → Foo as Bar (type-only) }\n * ```\n */\nexport function use(importInput: ImportInput, module: Module): Fragment {\n const info = parseImportInput(importInput);\n const empty: Fragment = Object.freeze({ content: info.usedIdentifier, imports: createImportMap() });\n return addFragmentImports(empty, module, [importInput]);\n}\n\n/**\n * Append imports to an existing fragment's import map. The fragment's\n * content and any other fields are preserved.\n *\n * @param fragment - The source fragment.\n * @param module - The module the new imports come from.\n * @param imports - The import shorthand strings to add.\n * @return A new frozen fragment with the extended import map.\n *\n * @example\n * ```ts\n * import { addFragmentImports, fragment } from '@codama/fragments/javascript';\n *\n * const f = addFragmentImports(fragment`hello`, './foo', ['Foo']);\n * ```\n */\nexport function addFragmentImports(fragment: Fragment, module: Module, imports: ImportInput[]): Fragment {\n return Object.freeze({\n ...fragment,\n imports: addToImportMap(fragment.imports, module, imports),\n });\n}\n\n/**\n * Merge additional import maps into an existing fragment's import map. The\n * fragment's content and any other fields are preserved.\n *\n * @param fragment - The source fragment.\n * @param importMaps - The additional maps to merge in.\n * @return A new frozen fragment with the merged import map.\n */\nexport function mergeFragmentImports(fragment: Fragment, importMaps: readonly ImportMap[]): Fragment {\n return Object.freeze({\n ...fragment,\n imports: mergeImportMaps([fragment.imports, ...importMaps]),\n });\n}\n\n/**\n * Drop identifiers from a fragment's import map. The fragment's content and\n * any other fields are preserved.\n *\n * @param fragment - The source fragment.\n * @param module - The module to remove identifiers from.\n * @param usedIdentifiers - The used-identifier names to drop.\n * @return A new frozen fragment with the trimmed import map.\n */\nexport function removeFragmentImports(fragment: Fragment, module: Module, usedIdentifiers: UsedIdentifier[]): Fragment {\n return Object.freeze({\n ...fragment,\n imports: removeFromImportMap(fragment.imports, module, usedIdentifiers),\n });\n}\n","import type { Fragment } from './fragment';\nimport { fragment } from './fragment';\n\n/**\n * Build a JSDoc-style docblock fragment from an array of lines.\n *\n * Empty or `undefined` input returns `undefined` so the helper composes\n * naturally with the {@link fragment} tag's optional-interpolation\n * behavior — a node's `docs` attribute can be threaded straight in\n * without a ternary guard:\n *\n * ```ts\n * fragment`${getDocblockFragment(node.docs)}\\nexport interface X {}`;\n * ```\n *\n * Single-line input renders as a one-line block (`/** line *\\/`);\n * multi-line input renders as a standard multi-line JSDoc block. Empty\n * elements in the array render as bare ` *` lines, useful for paragraph\n * breaks inside a docblock.\n *\n * The helper defangs any literal `*\\/` sequences inside the lines (they are\n * rewritten as `*\\\\/`) so that user-supplied content cannot accidentally\n * close the docblock early.\n *\n * @param lines - The lines of the docblock, or `undefined`. Empty array\n * and `undefined` both return `undefined`.\n * @param options - Optional settings.\n * @param options.withLineJump - When `true`, appends a trailing `\\n` after\n * the closing `*\\/`. Useful when the docblock is followed by a same-line\n * item like an enum variant.\n * @return A {@link Fragment} carrying the rendered docblock, or `undefined`\n * when `lines` is empty or `undefined`.\n *\n * @example\n * ```ts\n * import { getDocblockFragment } from '@codama/fragments/javascript';\n *\n * getDocblockFragment(['Greets the user.'])?.content;\n * // /** Greets the user. *\\/\n *\n * getDocblockFragment(['First line.', '', 'Second paragraph.'])?.content;\n * // /**\n * // * First line.\n * // *\n * // * Second paragraph.\n * // *\\/\n *\n * getDocblockFragment(undefined);\n * // undefined\n * ```\n */\nexport function getDocblockFragment(\n lines: readonly string[] | undefined,\n options: { withLineJump?: boolean } = {},\n): Fragment | undefined {\n if (!lines || lines.length === 0) return undefined;\n const lineJump = options.withLineJump ? '\\n' : '';\n const safeLines = lines.map(defang);\n if (safeLines.length === 1) return fragment`/** ${safeLines[0]} */${lineJump}`;\n const prefixedLines = safeLines.map(line => (line ? ` * ${line}` : ' *'));\n return fragment`/**\\n${prefixedLines.join('\\n')}\\n */${lineJump}`;\n}\n\n/** Escape any `*\\/` sequences in a docblock line so user input can't close the comment. */\nfunction defang(line: string): string {\n return line.replace(/\\*\\//g, '*\\\\/');\n}\n","import type { Fragment } from './fragment';\nimport { fragment } from './fragment';\n\n/**\n * Build a fragment that re-exports every binding from a module:\n * `export * from '<module>';`.\n *\n * The fragment carries no imports — `export * from` only forwards bindings\n * out, it does not bring `module` into local scope.\n *\n * @param module - The module specifier being re-exported.\n * @return A {@link Fragment} whose content is `export * from '<module>';`.\n *\n * @example\n * ```ts\n * import { getExportAllFragment } from '@codama/fragments/javascript';\n *\n * getExportAllFragment('./accounts').content;\n * // export * from './accounts';\n * ```\n */\nexport function getExportAllFragment(module: string): Fragment {\n return fragment`export * from '${module}';`;\n}\n"]}