@kosdev-code/kos-codegen-core 0.1.0-next.901 → 0.1.0-next.903

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/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../packages/kos-codegen-core/src/lib/codegen-filesystem.ts","../../../packages/kos-codegen-core/src/lib/logger.ts","../../../packages/kos-codegen-core/src/lib/generate-files.ts","../../../packages/kos-codegen-core/src/lib/project-discovery.ts","../../../packages/kos-codegen-core/src/lib/json-utils.ts","../../../packages/kos-codegen-core/src/lib/format-files.ts","../../../packages/kos-codegen-core/src/lib/name-utils.ts","../../../packages/kos-codegen-core/src/lib/normalize-values.ts","../../../packages/kos-codegen-core/src/lib/kos-config.ts","../../../packages/kos-codegen-core/src/lib/template-resolver.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-splash-project.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-model-project.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-init.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-polyglot-workspace.ts","../../../packages/kos-codegen-core/src/lib/generators/kab-targets.ts","../../../packages/kos-codegen-core/src/lib/generators/ci-sync.ts","../../../packages/kos-codegen-core/src/lib/generators/java-workspace.ts","../../../packages/kos-codegen-core/src/lib/generators/normalize-options.ts","../../../packages/kos-codegen-core/src/lib/generators/release-version-script.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/ts-toolkit.ts","../../../packages/kos-codegen-core/src/lib/generators/service-catalog.ts","../../../packages/kos-codegen-core/src/lib/generators/barrel-utils.ts","../../../packages/kos-codegen-core/src/lib/generators/update-model-index.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-companion-model.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-container-model.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-context.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-hook.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-model.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/find-model-declaration.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/resolve-model-file.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/resolve-child-model.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-view-model.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/model-services.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/normalize-options.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/model-transformer.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/service-transformer.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/registration-transformer.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/generate-add-future-to-model.ts","../../../packages/kos-codegen-core/src/lib/generators/add-container-support/generate-add-container-support.ts","../../../packages/kos-codegen-core/src/lib/generators/add-parent-aware/generate-add-parent-aware.ts","../../../packages/kos-codegen-core/src/lib/generators/describe/describe-model.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-model-effect.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-dependency.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-child.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-topic-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-config-property.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-property.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-computed.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/model-mocks.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-service-request.ts","../../../packages/kos-codegen-core/src/lib/generators/types/lookup-sdk-type.ts","../../../packages/kos-codegen-core/src/lib/generators/validate/validate-model.ts","../../../packages/kos-codegen-core/src/lib/generators/component/types.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/base.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/control-pour-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/cui-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/custom-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/default-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/nav-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/setting-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/setup-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/trouble-action-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/utility-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/factory.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/file-generator.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/kos-config-builder.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/localization.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/validation.ts","../../../packages/kos-codegen-core/src/lib/generators/component/generate-component.ts","../../../packages/kos-codegen-core/src/lib/generators/registration/upsert-chain-entry.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\n/**\n * Abstraction over a filesystem for code generation.\n *\n * Mirrors the subset of the Nx Tree API that generators actually use,\n * enabling the same generator logic to run against the real filesystem\n * (CLI, VS Code extension) or an in-memory tree (Nx adapter).\n */\nexport interface CodegenFileSystem {\n /** Workspace root directory (absolute path). */\n readonly root: string;\n\n /** Read a file relative to the workspace root. Returns null if not found. */\n read(filePath: string): string | null;\n\n /** Write a file relative to the workspace root. Creates parent dirs as needed. */\n write(filePath: string, content: string): void;\n\n /** Check whether a file exists relative to the workspace root. */\n exists(filePath: string): boolean;\n\n /** Delete a file relative to the workspace root. No-op if not found. */\n delete(filePath: string): void;\n\n /** List all files under a directory (relative to root), returned as root-relative paths. */\n listFiles(dirPath: string): string[];\n}\n\n/**\n * CodegenFileSystem wrapper that records absolute paths of every file written.\n * Wrap any CodegenFileSystem to collect written paths for post-generation steps\n * such as formatting.\n *\n * @example\n * const fs = new TrackingFileSystem(new DirectFileSystem(cwd));\n * generateModel({ codegenFs: fs, ... });\n * await formatFiles(fs.root, fs.writtenPaths);\n */\nexport class TrackingFileSystem implements CodegenFileSystem {\n private readonly inner: CodegenFileSystem;\n private readonly _writtenPaths: string[] = [];\n\n constructor(inner: CodegenFileSystem) {\n this.inner = inner;\n }\n\n get root(): string {\n return this.inner.root;\n }\n\n get writtenPaths(): string[] {\n return [...this._writtenPaths];\n }\n\n read(filePath: string): string | null {\n return this.inner.read(filePath);\n }\n\n write(filePath: string, content: string): void {\n this.inner.write(filePath, content);\n this._writtenPaths.push(\n path.isAbsolute(filePath)\n ? filePath\n : path.join(this.inner.root, filePath)\n );\n }\n\n exists(filePath: string): boolean {\n return this.inner.exists(filePath);\n }\n\n delete(filePath: string): void {\n this.inner.delete(filePath);\n }\n\n listFiles(dirPath: string): string[] {\n return this.inner.listFiles(dirPath);\n }\n}\n\n/**\n * CodegenFileSystem backed by the real Node.js filesystem.\n * All paths passed to interface methods are relative to the workspace root.\n */\nexport class DirectFileSystem implements CodegenFileSystem {\n readonly root: string;\n\n constructor(workspaceRoot: string) {\n this.root = path.resolve(workspaceRoot);\n }\n\n read(filePath: string): string | null {\n const abs = this.resolve(filePath);\n try {\n return fs.readFileSync(abs, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n write(filePath: string, content: string): void {\n const abs = this.resolve(filePath);\n fs.mkdirSync(path.dirname(abs), { recursive: true });\n fs.writeFileSync(abs, content, \"utf-8\");\n }\n\n exists(filePath: string): boolean {\n return fs.existsSync(this.resolve(filePath));\n }\n\n delete(filePath: string): void {\n const abs = this.resolve(filePath);\n try {\n fs.unlinkSync(abs);\n } catch {\n // no-op if file doesn't exist\n }\n }\n\n listFiles(dirPath: string): string[] {\n const abs = this.resolve(dirPath);\n if (!fs.existsSync(abs)) {\n return [];\n }\n return this.walkDir(abs).map((file) => path.relative(this.root, file));\n }\n\n private resolve(filePath: string): string {\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n return path.join(this.root, filePath);\n }\n\n private walkDir(dir: string): string[] {\n const results: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...this.walkDir(full));\n } else {\n results.push(full);\n }\n }\n return results;\n }\n}\n","/**\n * Settable logger interface for kos-codegen-core.\n *\n * Consumers (CLI, VS Code extension, Nx adapter) set their own logger\n * via setCodegenLogger(). Defaults to silent no-op.\n */\nexport interface CodegenLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst noopLogger: CodegenLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nlet activeLogger: CodegenLogger = noopLogger;\n\nexport function setCodegenLogger(logger: CodegenLogger): void {\n activeLogger = logger;\n}\n\nexport function getCodegenLogger(): CodegenLogger {\n return activeLogger;\n}\n","/**\n * EJS-based file generation — replaces @nx/devkit generateFiles().\n *\n * Walks a source template directory, processes each file through EJS,\n * interpolates __var__ tokens in filenames, strips .template suffixes,\n * and writes results via a CodegenFileSystem.\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as ejs from \"ejs\";\nimport type { CodegenFileSystem } from \"./codegen-filesystem\";\nimport { getCodegenLogger } from \"./logger\";\n\n/**\n * Generate files from a template directory into a destination path.\n *\n * Behavior matches @nx/devkit generateFiles():\n * - Walks `srcFolder` recursively\n * - For each file, replaces `__propName__` in the filename using `substitutions`\n * - Strips `.template` suffix from filenames\n * - Processes file contents through EJS with `substitutions` as data\n * - Writes the result to `destFolder` (relative to fs.root) via the CodegenFileSystem\n *\n * @param codegenFs - Target filesystem abstraction\n * @param srcFolder - Absolute path to the template directory\n * @param destFolder - Destination path relative to the filesystem root\n * @param substitutions - Key-value pairs for EJS and filename interpolation\n */\nexport function generateFilesFromTemplates(\n codegenFs: CodegenFileSystem,\n srcFolder: string,\n destFolder: string,\n substitutions: Record<string, any>\n): void {\n const logger = getCodegenLogger();\n const templateFiles = walkTemplateDir(srcFolder);\n\n for (const templateFile of templateFiles) {\n const relPath = path.relative(srcFolder, templateFile);\n\n // Interpolate __var__ tokens in the path segments\n let destRelPath = interpolateFilename(relPath, substitutions);\n\n // Strip .template suffix\n if (destRelPath.endsWith(\".template\")) {\n destRelPath = destRelPath.slice(0, -\".template\".length);\n }\n\n const destPath = path.join(destFolder, destRelPath);\n\n // Templates are read from the real filesystem (package assets),\n // while outputs are written through CodegenFileSystem.\n const rawContent = fs.readFileSync(templateFile, \"utf-8\");\n const rendered = ejs.render(rawContent, substitutions, {\n filename: templateFile, // for EJS error messages and includes\n });\n\n logger.debug(`Generating ${destPath}`);\n codegenFs.write(destPath, rendered);\n }\n}\n\n/**\n * Replace `__propName__` tokens in a file path with values from substitutions.\n * E.g., `__nameDashCase__-model.ts` with `{ nameDashCase: \"my-widget\" }` becomes\n * `my-widget-model.ts`.\n */\nfunction interpolateFilename(\n filePath: string,\n substitutions: Record<string, any>\n): string {\n return filePath.replace(/__([^_]+)__/g, (match, key: string) => {\n if (key in substitutions) {\n return String(substitutions[key]);\n }\n return match; // leave unmatched tokens as-is\n });\n}\n\nfunction walkTemplateDir(dir: string): string[] {\n const results: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...walkTemplateDir(full));\n } else {\n results.push(full);\n }\n }\n return results;\n}\n","/**\n * Nx-free project discovery — scans for project.json files in the workspace.\n *\n * Replaces @nx/devkit readProjectConfiguration, getProjects, readNxJson.\n * Based on the pattern in kos-model-extension/src/utils/workspace-scanner.ts.\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport fg from \"fast-glob\";\nimport { getCodegenLogger } from \"./logger\";\n\nexport interface ProjectConfiguration {\n name: string;\n root: string;\n sourceRoot: string;\n projectType?: \"library\" | \"application\";\n targets?: Record<string, unknown>;\n tags?: string[];\n}\n\n/**\n * Discover all projects in the workspace by scanning for project.json files.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @returns Map of project name to ProjectConfiguration\n */\nexport function discoverProjects(\n workspaceRoot: string\n): Map<string, ProjectConfiguration> {\n const logger = getCodegenLogger();\n const projects = new Map<string, ProjectConfiguration>();\n\n const projectJsonPaths = fg.sync(\"**/project.json\", {\n cwd: workspaceRoot,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\"],\n absolute: false,\n });\n\n for (const relPath of projectJsonPaths) {\n const absPath = path.join(workspaceRoot, relPath);\n try {\n const raw = fs.readFileSync(absPath, \"utf-8\");\n const json = JSON.parse(raw);\n const projectRoot = path.dirname(relPath);\n const name = json.name ?? path.basename(projectRoot);\n\n const config: ProjectConfiguration = {\n name,\n root: projectRoot,\n sourceRoot: json.sourceRoot ?? path.join(projectRoot, \"src\"),\n projectType: json.projectType,\n targets: json.targets,\n tags: json.tags,\n };\n\n projects.set(name, config);\n logger.debug(`Discovered project: ${name} at ${projectRoot}`);\n } catch (err) {\n logger.warn(`Failed to parse ${absPath}: ${err}`);\n }\n }\n\n logger.info(`Discovered ${projects.size} projects`);\n return projects;\n}\n\n/**\n * Find a single project by name.\n *\n * Note: This rescans the workspace on every call. If you need to look up\n * multiple projects, call discoverProjects() once and query the returned Map.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @param projectName - The project name to look up\n * @param projects - Optional pre-computed project map (avoids rescan)\n * @returns ProjectConfiguration or undefined if not found\n */\nexport function findProjectByName(\n workspaceRoot: string,\n projectName: string,\n projects?: Map<string, ProjectConfiguration>\n): ProjectConfiguration | undefined {\n const map = projects ?? discoverProjects(workspaceRoot);\n return map.get(projectName);\n}\n\n/**\n * Find the project that contains a given file path.\n * Walks up from the file path looking for the nearest project.json.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @param filePath - Absolute path to a file within the workspace\n * @returns ProjectConfiguration or undefined if not within any project\n */\nexport function findProjectForPath(\n workspaceRoot: string,\n filePath: string\n): ProjectConfiguration | undefined {\n const resolved = path.resolve(workspaceRoot);\n let dir = path.dirname(path.resolve(filePath));\n\n while (dir.startsWith(resolved) && dir !== resolved) {\n const projectJsonPath = path.join(dir, \"project.json\");\n if (fs.existsSync(projectJsonPath)) {\n try {\n const raw = fs.readFileSync(projectJsonPath, \"utf-8\");\n const json = JSON.parse(raw);\n const projectRoot = path.relative(resolved, dir);\n const name = json.name ?? path.basename(dir);\n\n return {\n name,\n root: projectRoot,\n sourceRoot: json.sourceRoot ?? path.join(projectRoot, \"src\"),\n projectType: json.projectType,\n targets: json.targets,\n tags: json.tags,\n };\n } catch {\n return undefined;\n }\n }\n dir = path.dirname(dir);\n }\n\n return undefined;\n}\n\n/**\n * Read the workspace-level nx.json configuration.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @returns Parsed nx.json contents, or empty object if not found\n */\nexport function readNxJson(workspaceRoot: string): Record<string, unknown> {\n const nxJsonPath = path.join(workspaceRoot, \"nx.json\");\n try {\n const raw = fs.readFileSync(nxJsonPath, \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return {};\n }\n}\n","/**\n * JSON read/write/update utilities operating on a CodegenFileSystem.\n *\n * Replaces @nx/devkit readJson, writeJson, updateJson.\n */\nimport type { CodegenFileSystem } from \"./codegen-filesystem\";\n\n/**\n * Read and parse a JSON file from the filesystem.\n *\n * @param codegenFs - Filesystem abstraction\n * @param filePath - Path relative to workspace root\n * @returns Parsed JSON object\n * @throws If the file does not exist or contains invalid JSON\n */\nexport function readJson<T = Record<string, unknown>>(\n codegenFs: CodegenFileSystem,\n filePath: string\n): T {\n const content = codegenFs.read(filePath);\n if (content === null) {\n throw new Error(`File not found: ${filePath}`);\n }\n return JSON.parse(content) as T;\n}\n\n/**\n * Serialize and write a JSON object to the filesystem.\n *\n * @param codegenFs - Filesystem abstraction\n * @param filePath - Path relative to workspace root\n * @param value - Object to serialize\n */\nexport function writeJson<T = Record<string, unknown>>(\n codegenFs: CodegenFileSystem,\n filePath: string,\n value: T\n): void {\n codegenFs.write(filePath, JSON.stringify(value, null, 2) + \"\\n\");\n}\n\n/**\n * Read a JSON file, apply a transformation, and write it back.\n *\n * @param codegenFs - Filesystem abstraction\n * @param filePath - Path relative to workspace root\n * @param updater - Function that receives the parsed object and returns the updated object\n */\nexport function updateJson<T = Record<string, unknown>>(\n codegenFs: CodegenFileSystem,\n filePath: string,\n updater: (json: T) => T\n): void {\n const current = readJson<T>(codegenFs, filePath);\n const updated = updater(current);\n writeJson(codegenFs, filePath, updated);\n}\n","/**\n * Format files using Prettier — replaces @nx/devkit formatFiles().\n *\n * Resolves the Prettier config from the workspace root and formats\n * all files tracked by a CodegenFileSystem that match supported extensions.\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport prettier from \"prettier\";\nimport { getCodegenLogger } from \"./logger\";\n\nconst FORMATTABLE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".css\",\n \".scss\",\n \".md\",\n \".yaml\",\n \".yml\",\n \".html\",\n]);\n\n/**\n * Format files at the given paths using Prettier.\n *\n * @param workspaceRoot - Absolute path to the workspace root (for Prettier config resolution)\n * @param filePaths - Absolute paths of files to format\n */\nexport async function formatFiles(\n workspaceRoot: string,\n filePaths: string[]\n): Promise<void> {\n const logger = getCodegenLogger();\n\n for (const filePath of filePaths) {\n const ext = path.extname(filePath);\n if (!FORMATTABLE_EXTENSIONS.has(ext)) {\n continue;\n }\n\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const options = await prettier.resolveConfig(filePath, {\n editorconfig: true,\n });\n const formatted = await prettier.format(content, {\n ...options,\n filepath: filePath,\n });\n fs.writeFileSync(filePath, formatted, \"utf-8\");\n logger.debug(`Formatted ${path.relative(workspaceRoot, filePath)}`);\n } catch (err) {\n logger.warn(`Failed to format ${filePath}: ${err}`);\n }\n }\n}\n","/**\n * String case-conversion utilities.\n *\n * Pure functions with no external dependencies.\n * Ported from kos-nx-plugin/src/utils/name-utils.ts (minus the logger calls).\n */\n\nexport function dashCase(input: string): string {\n return input\n .replace(/\\s+/g, \"-\")\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .toLowerCase();\n}\n\nexport function camelCase(input: string): string {\n if (input.length === 0) return \"\";\n const words = input.split(/-|\\s+/);\n if (words.length > 0 && words[0].length > 0) {\n words[0] = words[0].charAt(0).toLowerCase() + words[0].slice(1);\n }\n for (let i = 1; i < words.length; i++) {\n words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1);\n }\n return words.join(\"\");\n}\n\nexport function pascalCase(input: string): string {\n if (input.length === 0) return \"\";\n const cc = camelCase(input);\n return cc[0].toUpperCase() + cc.slice(1);\n}\n\nexport function properCase(input: string): string {\n const words = input\n .toLowerCase()\n .replaceAll(\"-\", \" \")\n .split(\" \")\n .filter(Boolean);\n for (let i = 0; i < words.length; i++) {\n words[i] = words[i][0].toUpperCase() + words[i].slice(1);\n }\n return words.join(\"\");\n}\n\n/**\n * Convert to CONSTANT_CASE. Expects space-separated or dash-separated input.\n * camelCase input is not split (e.g. \"myWidget\" becomes \"MYWIDGET\").\n */\nexport function constantCase(input: string): string {\n if (input.length === 0) return \"\";\n return input\n .toUpperCase()\n .split(/[\\s-]+/)\n .filter(Boolean)\n .join(\"_\");\n}\n","/**\n * Option normalization — generates all case variants for every string property.\n *\n * Given `{ name: \"my-widget\" }`, produces:\n * ```\n * {\n * name: \"my-widget\",\n * nameCamelCase: \"myWidget\",\n * namePascalCase: \"MyWidget\",\n * nameDashCase: \"my-widget\",\n * nameProperCase: \"MyWidget\",\n * nameConstantCase: \"MY_WIDGET\",\n * nameLowerCase: \"my-widget\",\n * }\n * ```\n *\n * Ported from kos-nx-plugin/src/utils/normalize-value.ts.\n */\nimport {\n camelCase,\n constantCase,\n dashCase,\n pascalCase,\n properCase,\n} from \"./name-utils\";\n\ntype NormalizedFunctions =\n | \"CamelCase\"\n | \"ConstantCase\"\n | \"DashCase\"\n | \"PascalCase\"\n | \"ProperCase\"\n | \"LowerCase\";\n\ntype NormalizedValue<Type extends Record<string, string>> = {\n [k in Type as `${Extract<keyof Type, string>}${NormalizedFunctions}`]: string;\n};\n\ntype Normalized<T extends string> = {\n [k in T as `${T}${NormalizedFunctions}`]: string;\n};\n\nconst normalizeValue = <T extends string>(\n optionsName: T,\n value: string\n): Normalized<T> & { [k in T]: string } =>\n ({\n [`${camelCase(optionsName)}CamelCase`]: camelCase(value),\n [`${camelCase(optionsName)}ConstantCase`]: constantCase(value),\n [`${camelCase(optionsName)}DashCase`]: dashCase(value),\n [`${camelCase(optionsName)}PascalCase`]: pascalCase(value),\n [`${camelCase(optionsName)}ProperCase`]: properCase(value),\n [`${camelCase(optionsName)}LowerCase`]: value.toLowerCase(),\n [`${optionsName}`]: value,\n } as Normalized<T> & { [k in T]: string });\n\nexport const normalizeAllValues = <T extends Record<string, any>>(\n options: T\n): NormalizedValue<T> & T => {\n let normalizedValues = {} as NormalizedValue<T> & T;\n for (const key in options) {\n if (Object.prototype.hasOwnProperty.call(options, key)) {\n const element = options[key];\n const newOptions =\n typeof element !== \"string\" || element === \"\"\n ? { [key]: element }\n : normalizeValue(key, element);\n\n normalizedValues = {\n ...normalizedValues,\n ...newOptions,\n };\n }\n }\n return normalizedValues;\n};\n","/**\n * KOS project and model configuration utilities.\n *\n * Reads and writes .kos.json files through CodegenFileSystem.\n * Ported from kos-nx-plugin/src/utils/project-utils.ts.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"./codegen-filesystem\";\nimport {\n findProjectByName,\n findProjectForPath,\n type ProjectConfiguration,\n} from \"./project-discovery\";\nimport { updateJson } from \"./json-utils\";\nimport { dashCase } from \"./name-utils\";\nimport { getCodegenLogger } from \"./logger\";\n\nexport interface KosModelConfiguration {\n name: string;\n type: string;\n singleton: boolean;\n container?: boolean;\n /**\n * Exported registration bean symbol (e.g. \"Board\") — the agent-facing handle.\n * Imported from the SDK root; `factory.type` is the modelType to depend on, and\n * models are auto-registered so consumers never instantiate it. Written\n * automatically by the generator (it names the bean). Links to the full shape\n * at `kos://types/{factory}`.\n */\n factory?: string;\n /**\n * One-line, human-curated purpose. The only genuinely authored field — set via\n * an optional prompt/slot at generation, never inferred.\n */\n purpose?: string;\n /**\n * `.kos.json` keys of the container/managing models that hold this model —\n * consume it THROUGH them (depend on the container, navigate), not by id. Set\n * only when generation establishes containment; never inferred.\n */\n managedBy?: string[];\n}\n\nexport interface KosProjectConfiguration {\n name: string;\n type: string;\n version: string;\n models: Record<string, KosModelConfiguration>;\n generator?: {\n internal?: boolean;\n defaults?: {\n model?: { folder?: string };\n component?: { folder?: string };\n };\n };\n}\n\nexport function getCurrentDirectoryName(cwd: string): string | undefined {\n return cwd.split(\"/\").pop();\n}\n\n/**\n * Find the project that contains the given working directory.\n */\nexport function getProject(\n codegenFs: CodegenFileSystem,\n cwd: string\n): ProjectConfiguration | undefined {\n return findProjectForPath(codegenFs.root, cwd);\n}\n\n/**\n * Read .kos.json for a project, creating a default if it doesn't exist.\n */\nexport function getKosProjectConfiguration(\n codegenFs: CodegenFileSystem,\n projectName: string,\n projects?: Map<string, ProjectConfiguration>\n): KosProjectConfiguration | undefined {\n const project = findProjectByName(codegenFs.root, projectName, projects);\n if (!project) return undefined;\n\n const configPath = path.join(project.root, \".kos.json\");\n if (!codegenFs.exists(configPath)) {\n const defaultConfig: KosProjectConfiguration = {\n name: `${dashCase(projectName)}-model`,\n type: \"kos.model\",\n version: \"0.1.0\",\n models: {},\n generator: { defaults: { model: { folder: \"\" } } },\n };\n codegenFs.write(configPath, JSON.stringify(defaultConfig, null, 2));\n }\n\n const content = codegenFs.read(configPath);\n return content ? JSON.parse(content) : undefined;\n}\n\n/**\n * Find the `.kos.json` model key for a model name. Keys are normally the model\n * name itself; fall back to matching the derived `<name>-model` type id so a\n * differently-cased name still resolves.\n */\nfunction findModelKey(\n models: Record<string, any>,\n name: string\n): string | undefined {\n if (models[name]) return name;\n const typeId = `${dashCase(name)}-model`;\n return Object.keys(models).find((k) => models[k]?.type === typeId);\n}\n\n/**\n * Record that an existing model gained in-place container support\n * (`@kosContainerAware`) in `.kos.json`: flag it `container: true`, and — when it\n * holds a concrete model type rather than the generic `IKosDataModel` — record\n * that child as `managedBy` this container so it is consumed THROUGH it.\n *\n * Containment is only recorded from this explicit generation step; nothing is\n * inferred. No-ops if the project or its `.kos.json` can't be found.\n */\nexport function recordContainerSupportInKosConfig(params: {\n codegenFs: CodegenFileSystem;\n projectName: string;\n modelName: string;\n childType?: string;\n projects?: Map<string, ProjectConfiguration>;\n}): void {\n const project = findProjectByName(\n params.codegenFs.root,\n params.projectName,\n params.projects\n );\n if (!project) return;\n const configPath = path.join(project.root, \".kos.json\");\n if (!params.codegenFs.exists(configPath)) return;\n\n updateJson(params.codegenFs, configPath, (json: any) => {\n const models: Record<string, any> = json.models ?? {};\n const selfKey = findModelKey(models, params.modelName);\n if (!selfKey) return json;\n\n models[selfKey] = { ...models[selfKey], container: true };\n\n const childType = params.childType?.trim();\n if (\n childType &&\n childType !== \"IKosDataModel\" &&\n /Model$/.test(childType)\n ) {\n const childTypeId = dashCase(childType);\n const childKey = Object.keys(models).find(\n (k) => models[k]?.type === childTypeId\n );\n if (childKey && childKey !== selfKey) {\n const managedBy = [\n ...new Set([...(models[childKey].managedBy ?? []), selfKey]),\n ];\n models[childKey] = { ...models[childKey], managedBy };\n }\n }\n\n json.models = models;\n return json;\n });\n}\n\n/**\n * Read a specific model's configuration from .kos.json.\n */\nexport function getKosModelConfiguration(\n codegenFs: CodegenFileSystem,\n projectName: string,\n modelName: string,\n projects?: Map<string, ProjectConfiguration>\n): KosModelConfiguration | undefined {\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectName,\n projects\n );\n return kosConfig?.models?.[modelName];\n}\n\n/**\n * Read a specific property from a model's configuration.\n */\nexport function getKosModelConfigProp(params: {\n codegenFs: CodegenFileSystem;\n project: string;\n modelName: string;\n prop: string;\n projects?: Map<string, ProjectConfiguration>;\n}): any {\n const config = getKosModelConfiguration(\n params.codegenFs,\n params.project,\n params.modelName,\n params.projects\n );\n return config ? (config as any)[params.prop] : undefined;\n}\n\n/**\n * Add a model entry to a project's .kos.json.\n */\nexport function addKosModelConfiguration(params: {\n codegenFs: CodegenFileSystem;\n projectName: string;\n projectRoot: string;\n modelName: string;\n singleton: boolean;\n container?: boolean;\n /** Exported registration bean symbol (the generator knows it). */\n factory?: string;\n}): void {\n const logger = getCodegenLogger();\n const kosConfigPath = path.join(params.projectRoot, \".kos.json\");\n\n if (!params.codegenFs.exists(kosConfigPath)) {\n logger.info(`Creating .kos.json in ${params.projectRoot}`);\n const defaultConfig = {\n name: params.projectName,\n type: \"kos.model\",\n version: \"0.1.0\",\n models: {},\n generator: { defaults: { model: { folder: \"\" } } },\n };\n params.codegenFs.write(\n kosConfigPath,\n JSON.stringify(defaultConfig, null, 2) + \"\\n\"\n );\n }\n\n updateJson(params.codegenFs, kosConfigPath, (json: any) => {\n const existing = json.models?.[params.modelName] ?? {};\n json.models = {\n ...json.models,\n [params.modelName]: {\n // Preserve any curated fields (purpose/managedBy) on re-generation.\n ...existing,\n name: params.modelName,\n type: `${params.modelName}-model`,\n singleton: !!params.singleton,\n container: !!params.container,\n ...(params.factory ? { factory: params.factory } : {}),\n },\n };\n return json;\n });\n}\n","import * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Finds the root directory containing the templates/ directory.\n *\n * Resolution order:\n * 1. KOS_TEMPLATE_BASE_DIR env var — set by kos-ui-cli when running as a\n * bundled ESM package (where __dirname is unavailable).\n * 2. Walk up from __dirname looking for this package's package.json — works\n * in CJS context (tsc-compiled output or direct Node.js require).\n */\nfunction findPackageRoot(): string {\n if (process.env.KOS_TEMPLATE_BASE_DIR) {\n return process.env.KOS_TEMPLATE_BASE_DIR;\n }\n\n // CJS context: walk up from __dirname to find our package.json\n let dir = __dirname;\n while (dir !== path.dirname(dir)) {\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n if (pkg.name === \"@kosdev-code/kos-codegen-core\") {\n return dir;\n }\n } catch {\n // Not valid JSON, keep looking\n }\n }\n dir = path.dirname(dir);\n }\n // Fallback: assume source layout (src/lib/ -> package root)\n return path.resolve(__dirname, \"..\", \"..\");\n}\n\n/**\n * Resolves the absolute path to a generator's template directory.\n * Templates are stored in the `templates/` directory at the package root.\n *\n * @param generatorName - The generator name matching a subdirectory under templates/\n * @returns Absolute path to the template directory for the given generator\n */\nexport function getTemplateDir(generatorName: string): string {\n return path.join(findPackageRoot(), \"templates\", generatorName);\n}\n","/**\n * Core generator: Splash project.\n *\n * Creates a splash screen project structure and associated tooling scripts.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { normalizeAllValues } from \"../normalize-values\";\n\nexport interface SplashProjectOptions {\n name: string;\n}\n\n/**\n * Generate a splash project with its associated tooling.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory containing\n * `project/` and `tools/` subdirectories\n * @param options - Generator options\n */\nexport function generateSplashProject(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: SplashProjectOptions\n): void {\n const normalized = normalizeAllValues(options);\n\n const projectRoot = `splash/${normalized.nameDashCase}`;\n const toolsRoot = path.join(\"tools\", \"scripts\");\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"project\"),\n projectRoot,\n normalized\n );\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"tools\"),\n toolsRoot,\n normalized\n );\n}\n","/**\n * Core generator: Model project.\n *\n * Owns the WHOLE output of a KOS model library — the buildable Nx library\n * skeleton (project.json, tsconfigs, vite.config.ts, package.json, eslint\n * config, source entry point) plus the KOS layer on top: the `.kos.json`\n * descriptor carrying `generator.projectType: \"model\"` (what `kosui model`\n * project discovery keys off) and the `api` target that fronts\n * `kosui api:generate`.\n *\n * Framework-agnostic — operates through CodegenFileSystem, with no @nx/*\n * involvement. The templates are the byte-for-byte output the workspace preset\n * used to obtain from `@nx/js`'s library generator, so a workspace scaffolded\n * by the preset and one grown later with `kosui project:model` are identical.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { readJson, updateJson, writeJson } from \"../json-utils\";\nimport { camelCase, dashCase } from \"../name-utils\";\n\n/** Suffix every KOS model library carries, so `kosui` can recognize one by name. */\nconst MODEL_PROJECT_SUFFIX = \"-models\";\n\n/** Directory model libraries live under when the workspace declares no libsDir. */\nexport const DEFAULT_MODEL_LIBS_DIR = \"libs\";\n\n/**\n * The model lib's own .eslintrc.json parses its package.json with\n * jsonc-eslint-parser for the @nx/dependency-checks rule. Nothing else in a KOS\n * workspace pulls that parser in, so the generator must guarantee it.\n */\nconst JSONC_ESLINT_PARSER_VERSION = \"^2.1.0\";\n\nexport interface ModelProjectOptions {\n /** Base name; the `-models` suffix is appended unless already present. */\n name: string;\n /** Workspace `workspaceLayout.libsDir`, when the workspace declares one. */\n libsDir?: string;\n}\n\nexport interface ModelProjectLayout {\n /** Nx project name, e.g. `acme-models`. */\n projectName: string;\n /** Project root relative to the workspace root, e.g. `libs/acme-models`. */\n projectRoot: string;\n /** TypeScript path alias the workspace maps to the lib, e.g. `@acme/acme-models`. */\n importPath: string;\n}\n\n/**\n * Resolve where a model project lands and what it is called.\n *\n * `importPath` needs the workspace's npm scope, so the root package.json is\n * read when one is reachable; a workspace without a scoped name maps the lib\n * under its bare project name, matching Nx's own import-path rule.\n */\nexport function resolveModelProjectLayout(\n codegenFs: CodegenFileSystem | null,\n options: ModelProjectOptions\n): ModelProjectLayout {\n const base = dashCase(options.name);\n const projectName = base.endsWith(MODEL_PROJECT_SUFFIX)\n ? base\n : `${base}${MODEL_PROJECT_SUFFIX}`;\n const libsDir = (options.libsDir || DEFAULT_MODEL_LIBS_DIR).replace(\n /\\\\/g,\n \"/\"\n );\n const scope = codegenFs ? readNpmScope(codegenFs) : undefined;\n return {\n projectName,\n projectRoot: `${libsDir}/${projectName}`.replace(/^\\/+/, \"\"),\n importPath: scope ? `@${scope}/${projectName}` : projectName,\n };\n}\n\n/** The npm scope of the workspace, derived from the root package.json name. */\nfunction readNpmScope(codegenFs: CodegenFileSystem): string | undefined {\n if (!codegenFs.exists(\"package.json\")) {\n return undefined;\n }\n const name = readJson<{ name?: string }>(codegenFs, \"package.json\").name;\n if (!name?.startsWith(\"@\")) {\n return undefined;\n }\n return name.split(\"/\")[0].slice(1);\n}\n\n/** Relative prefix that walks from the project root back to the workspace root. */\nfunction offsetFromRoot(projectRoot: string): string {\n return projectRoot\n .split(\"/\")\n .filter(Boolean)\n .map(() => \"../\")\n .join(\"\");\n}\n\n/**\n * Generate a KOS model project.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory containing a\n * `project/` subdirectory\n * @param options - Generator options\n * @returns Where the project landed, what it is named, and its import path\n */\nexport function generateModelProject(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ModelProjectOptions\n): ModelProjectLayout {\n const layout = resolveModelProjectLayout(codegenFs, options);\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"project\"),\n layout.projectRoot,\n {\n ...layout,\n projectNameCamelCase: camelCase(layout.projectName),\n offsetFromRoot: offsetFromRoot(layout.projectRoot),\n template: \"\",\n }\n );\n\n registerTsconfigPath(codegenFs, layout);\n ensureJsoncEslintParser(codegenFs);\n\n return layout;\n}\n\n/**\n * Map the lib's import path to its source entry in tsconfig.base.json — without\n * it nothing in the workspace can import the models by name.\n */\nfunction registerTsconfigPath(\n codegenFs: CodegenFileSystem,\n layout: ModelProjectLayout\n): void {\n if (!codegenFs.exists(\"tsconfig.base.json\")) {\n return;\n }\n updateJson(codegenFs, \"tsconfig.base.json\", (json: any) => {\n json.compilerOptions = json.compilerOptions ?? {};\n json.compilerOptions.paths = json.compilerOptions.paths ?? {};\n json.compilerOptions.paths[layout.importPath] = [\n `${layout.projectRoot}/src/index.ts`,\n ];\n return json;\n });\n}\n\nfunction ensureJsoncEslintParser(codegenFs: CodegenFileSystem): void {\n if (!codegenFs.exists(\"package.json\")) {\n return;\n }\n const pkg = readJson<Record<string, any>>(codegenFs, \"package.json\");\n const devDependencies = pkg.devDependencies ?? {};\n if (\"jsonc-eslint-parser\" in devDependencies) {\n return;\n }\n devDependencies[\"jsonc-eslint-parser\"] = JSONC_ESLINT_PARSER_VERSION;\n pkg.devDependencies = Object.fromEntries(\n // Codepoint order, matching what Nx's own dependency helper produces.\n Object.entries(devDependencies).sort(([a], [b]) =>\n a < b ? -1 : a > b ? 1 : 0\n )\n );\n writeJson(codegenFs, \"package.json\", pkg);\n}\n","/**\n * Core generator: KOS Init.\n *\n * Updates nx.json with default KOS generator configuration for the workspace.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { readJson, writeJson } from \"../json-utils\";\nimport { getCodegenLogger } from \"../logger\";\n\nexport interface KosInitOptions {\n appProject: string;\n modelProject: string;\n registrationProject?: string;\n}\n\n/**\n * Initialize KOS generator defaults in nx.json.\n *\n * Sets default project references for kos-model, kos-component,\n * kos-context, and kos-hook generators.\n *\n * @param codegenFs - Target filesystem\n * @param options - Generator options\n */\nexport function generateInit(\n codegenFs: CodegenFileSystem,\n options: KosInitOptions\n): void {\n const logger = getCodegenLogger();\n const { appProject, modelProject, registrationProject } = options;\n\n let nxConfig: Record<string, any>;\n try {\n nxConfig = readJson(codegenFs, \"nx.json\");\n } catch {\n logger.error(\"Unable to find nx.json\");\n return;\n }\n\n logger.info(\"Updating nx.json\");\n\n const defaultProjectConfig = {\n appProject,\n modelProject,\n registrationProject,\n modelDirectory: \"lib\",\n appDirectory: \"app\",\n components: true,\n internal: false,\n singleton: false,\n unitTests: true,\n };\n\n const generatorsConfig = nxConfig.generators || {};\n const kosConfig = generatorsConfig[\"@kosdev-code/kos-nx-plugin\"] || {};\n\n const updateConfig = (configName: string) => {\n const config = kosConfig[configName] || { ...defaultProjectConfig };\n config.appProject = appProject;\n config.modelProject = modelProject;\n config.registrationProject = registrationProject;\n kosConfig[configName] = config;\n };\n\n [\"kos-model\", \"kos-component\", \"kos-context\", \"kos-hook\"].forEach(\n updateConfig\n );\n\n nxConfig.generators = {\n ...generatorsConfig,\n \"@kosdev-code/kos-nx-plugin\": kosConfig,\n };\n\n writeJson(codegenFs, \"nx.json\", nxConfig);\n}\n","/**\n * Core generator: polyglot workspace repo root.\n *\n * Scaffolds the repo-level layer of a java + ui KOS application repository\n * (the tccc-rack-app pattern): build/ orchestration scripts, GitHub Actions\n * workflows, and kos_build_handler manifests. The ui/ interior is produced by\n * the Nx preset (create-nx-workspace) and java/ modules by the KOS Maven\n * archetypes — this generator only contributes the layer neither of them owns.\n *\n * Framework-agnostic — operates through CodegenFileSystem; the repo root is\n * deliberately NOT an Nx workspace.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { normalizeAllValues } from \"../normalize-values\";\n\nexport interface PolyglotWorkspaceOptions {\n /** Workspace/repo name (also determines the UI app name `<name>-ui`). */\n name: string;\n /**\n * The repo-root layer is IDENTICAL for every type — same scripts,\n * workflows, and manifests, all runtime-tolerant of a missing half — so a\n * repo can grow the other half later without restructuring. The type only\n * seeds the manifests: \"polyglot\"/\"ui\" (default) pre-register the UI app\n * artifact; \"java\" starts with empty artifact lists (ci:sync/java:add\n * fill them in).\n */\n type?: \"polyglot\" | \"ui\" | \"java\";\n /**\n * `default_keyset` for the kos_build_handler manifests. Org-specific;\n * changeable in .github/build-*.json afterward. Default: \"prod.kos\".\n */\n keyset?: string;\n /**\n * Node version build/nodew.sh pins and auto-provisions when the machine\n * has none. Defaults to the Node running this generator — grounded in a\n * version known to work with the scaffolded workspace.\n */\n nodeVersion?: string;\n /**\n * JDK major build/jdkw.sh pins. Default 21 (compiles the archetypes'\n * release-17 target; also what java discovery prefers).\n */\n jdkMajor?: string;\n /** Maven version build/jdkw.sh provisions when mvn is absent. */\n mavenVersion?: string;\n}\n\nexport interface PolyglotWorkspaceResult {\n /**\n * Root-relative paths the caller must mark executable (CodegenFileSystem\n * has no chmod; CI invokes these directly as ./build/<script>).\n */\n executablePaths: string[];\n}\n\nconst BUILD_SCRIPTS = [\n \"build/build-ui.sh\",\n \"build/build-java.sh\",\n \"build/build-release.sh\",\n \"build/release_version_prebuild.sh\",\n \"build/docker-build.sh\",\n];\n\nexport function generatePolyglotWorkspace(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: PolyglotWorkspaceOptions\n): PolyglotWorkspaceResult {\n const hasUi = (options.type ?? \"polyglot\") !== \"java\";\n const normalized = normalizeAllValues({ name: options.name });\n const vars = {\n ...normalized,\n hasUi,\n keyset: options.keyset || \"prod.kos\",\n appUiName: `${normalized.nameDashCase}-ui`,\n nodeVersion: options.nodeVersion || process.version.replace(/^v/, \"\"),\n jdkMajor: options.jdkMajor || \"21\",\n mavenVersion: options.mavenVersion || \"3.9.9\",\n };\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"root\"),\n \".\",\n vars\n );\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"build\"),\n \"build\",\n vars\n );\n // Template dir is named \"github\" (npm packs dot-directories unreliably);\n // emitted as .github.\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"github\"),\n \".github\",\n vars\n );\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"java\"),\n \"java\",\n vars\n );\n\n return { executablePaths: [...BUILD_SCRIPTS] };\n}\n","/**\n * Shared KOS artifact-target bundle.\n *\n * Every project that packages a KAB gets the same target family:\n * kab — kabtool build + list (dependsOn zip)\n * zip — archiver (dependsOn build, sbom [+ descriptor])\n * descriptor — descriptor.mjs (optional; apps/plugins/content/i18n)\n * version — stamps the release version into the project's `.kos.json`\n * sbom — SPDX SBOM (pruned lockfile), packaged inside the KAB\n *\n * ARTIFACT LAYOUT: the KAB and ui.zip land in `{projectRoot}/target/` — a peer\n * of the project's `src/`, the same place the Maven half of a polyglot repo\n * drops its KABs (`java/<module>/target/*.kab`). A project's artifacts sit\n * beside the sources that produced them rather than in a workspace-wide\n * `dist/archives/` tree.\n *\n * `descriptor` and `sbom` write to the project's BUILD output dir\n * (`dist/{projectRoot}`) instead, because archiver zips that directory\n * wholesale: both have to end up INSIDE ui.zip — and therefore inside the KAB\n * — rather than beside it. An SBOM that shipped next to the KAB would not\n * travel with the distribution, which is the entire reason it is generated.\n * That is also why `zip` (not `kab`) is what depends on `sbom`: by the time\n * kabtool runs, the zip it packages is already sealed.\n *\n * Paths are written as Nx `{projectRoot}` tokens so `nx move` needs no\n * rewrite. Nx does NOT interpolate arbitrary target options, so the scripts\n * that read these (kabtool.mjs, archiver.js, descriptor.mjs, splashtool.mjs)\n * and the sbom executor expand the token themselves against the project's\n * root — see `resolveTargetPath` in each script.\n *\n * The `version` target is KOS *artifact* versioning: it rewrites the\n * `version` field of the project's `.kos.json` (which kabtool/descriptor bake\n * into the KAB) and never touches `package.json`. Tag-based release pipelines\n * drive it via:\n * nx run-many --target=version --args=--ver=$KOSBUILD_VERSION\n *\n * kab and version are deliberately produced by ONE helper so no generator can\n * emit a KAB-packaging project that is not release-versionable.\n */\n\n/** Directory, under each project root, that holds the project's KAB artifacts. */\nexport const KAB_OUTPUT_DIR = \"target\";\n\n/**\n * Archive directory for every KAB-producing project — `{projectRoot}/target/`.\n *\n * Deliberately a token rather than a resolved path: a project that moves keeps\n * working without anyone rewriting its project.json. Consumers expand it with\n * `resolveKabPath` (or its per-script equivalent) before touching the disk.\n */\nexport const KAB_OUTPUT_PATH = `{projectRoot}/${KAB_OUTPUT_DIR}/`;\n\n/**\n * Expand the Nx path tokens KOS artifact targets use in their options.\n *\n * Nx interpolates `{projectRoot}`/`{workspaceRoot}` in a target's `outputs`,\n * never in arbitrary `options`, and the KAB scripts read those options straight\n * off the cached project graph — so expansion is on us. The result stays\n * workspace-root-relative (the cwd Nx runs commands from) unless the token was\n * `{workspaceRoot}`.\n */\nexport function resolveKabPath(value: string, projectRoot: string): string {\n const root = projectRoot.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n return value\n .replace(/\\{projectRoot\\}/g, root)\n .replace(/\\{workspaceRoot\\}\\/?/g, \"\");\n}\n\nexport interface KabTargetsOptions {\n /** Project name as Nx knows it (argument to kabtool/archiver/descriptor). */\n name: string;\n /**\n * Emit a `descriptor` target (and make `zip` depend on it). Its\n * descriptor.json is written into the build output dir so the zip contains\n * it. Omit for projects without a descriptor (themes).\n */\n descriptor?: boolean;\n /** Build target `zip` depends on. Default: \"build\" (plugins: \"build:production\"). */\n buildTarget?: string;\n}\n\nexport interface KabTargetDefinition {\n command?: string;\n executor?: string;\n outputs?: string[];\n cache?: boolean;\n inputs?: string[];\n options?: Record<string, unknown>;\n dependsOn?: string[];\n}\n\nexport const UPDATE_RELEASE_VERSION_SCRIPT_PATH =\n \"tools/scripts/update-release-version.mjs\";\n\nexport function buildKabTargets(\n options: KabTargetsOptions\n): Record<string, KabTargetDefinition> {\n const { name, descriptor = false, buildTarget = \"build\" } = options;\n const outputPath = KAB_OUTPUT_PATH;\n // Everything that must ride INSIDE ui.zip is written here, because archiver\n // zips the build output dir wholesale.\n const zipPayloadDir = \"dist/{projectRoot}\";\n\n const targets: Record<string, KabTargetDefinition> = {\n kab: {\n command: `node tools/scripts/kabtool.mjs build ${name} && node tools/scripts/kabtool.mjs list ${name} `,\n options: {\n outputPath,\n zipName: \"ui.zip\",\n kabName: `${name}.kab`,\n },\n dependsOn: [\"zip\"],\n },\n zip: {\n command: `node tools/scripts/archiver.js ${name}`,\n options: {\n outputPath,\n zipName: \"ui.zip\",\n },\n // `sbom` is a zip dependency, not a kab one: kabtool packages an\n // already-sealed ui.zip, so anything ordered after `zip` misses it.\n dependsOn: descriptor\n ? [buildTarget, \"descriptor\", \"sbom\"]\n : [buildTarget, \"sbom\"],\n },\n };\n\n if (descriptor) {\n targets.descriptor = {\n command: `node tools/scripts/descriptor.mjs ${name}`,\n options: {\n outputPath: zipPayloadDir,\n fileName: \"descriptor.json\",\n },\n dependsOn: [\"build\"],\n };\n }\n\n targets.version = {\n command: `node ${UPDATE_RELEASE_VERSION_SCRIPT_PATH} ${name} {args.ver}`,\n options: {},\n dependsOn: [],\n };\n\n // The SBOM ships inside the KAB so it travels with the distribution.\n targets.sbom = buildSbomTarget({ outputPath: zipPayloadDir });\n\n return targets;\n}\n\nexport interface SbomTargetOptions {\n /**\n * Directory the SBOM lands in. `dist/{projectRoot}` — the build output dir\n * archiver zips — so the SBOM ships inside the KAB.\n */\n outputPath: string;\n}\n\n/**\n * SBOM target for any artifact-producing project. Standalone so migrations\n * can retrofit it onto existing projects without rebuilding the kab bundle.\n *\n * Whatever consumes this must order it BEFORE `zip`; an SBOM written after the\n * zip is sealed never reaches the KAB.\n */\nexport function buildSbomTarget({\n outputPath,\n}: SbomTargetOptions): KabTargetDefinition {\n const dir = outputPath.replace(/\\/+$/, \"\");\n // `outputs` is one of the few places Nx expands tokens itself, so a\n // tokenized dir goes in as-is; a plain path still needs the root prefix.\n const outputDir = dir.startsWith(\"{\") ? dir : `{workspaceRoot}/${dir}`;\n return {\n executor: \"@kosdev-code/kos-nx-plugin:sbom\",\n outputs: [\n `${outputDir}/sbom.spdx.json`,\n `${outputDir}/sbom.cyclonedx.json`,\n ],\n cache: true,\n inputs: [\"production\", \"^production\", \"{workspaceRoot}/package-lock.json\"],\n options: { outputPath: dir, softFail: true },\n };\n}\n","/**\n * ci:sync — reconcile the kos_build_handler manifests of a polyglot\n * workspace with the artifacts the repo actually produces.\n *\n * MERGE-PRESERVE semantics (the design contract):\n * - Existing artifact entries whose file is still produced are kept\n * VERBATIM — ids and custom fields (layer, artifactstore, …) are the\n * user's, and manifest ids are often hand-chosen (tccc-rack-app's\n * \"tccc-rack-splash-endcap\" for the `splash` project).\n * - Newly discovered artifacts are appended with generated entries.\n * - Entries whose artifact is no longer discovered are reported as stale\n * and kept, unless prune is set.\n * - Nothing outside the artifacts arrays is ever touched, and a manifest\n * is only rewritten when its artifact set actually changed.\n * Consequence: running ci:sync on an already-correct repo is a no-op, and\n * hand-running a Maven archetype + ci:sync converges to the same manifests\n * as `kosui java:add`.\n *\n * Discovery:\n * - ui: project.json files under the KOS layout dirs (never a bare walk of\n * ui/ — listFiles has no node_modules exclusion). A `kab` target's own\n * outputPath/kabName options give the artifact path; projects with a\n * `splash` target produce layer KABs; ui/external/*.kab files are\n * prebuilt artifacts.\n * - java: modules listed in the java/pom.xml aggregator whose pom uses the\n * kos-kab-maven-plugin (same java/pom.xml contract as build-java.sh).\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { KAB_OUTPUT_DIR, resolveKabPath } from \"./kab-targets\";\n\nexport interface DiscoveredArtifact {\n id: string;\n filename: string;\n layer?: number;\n}\n\nexport interface CiSyncOptions {\n /** Remove stale entries instead of keeping and reporting them. */\n prune?: boolean;\n}\n\nexport interface CiSyncManifestResult {\n added: string[];\n stale: string[];\n pruned: string[];\n}\n\nexport interface CiSyncResult {\n manifests: Record<string, CiSyncManifestResult>;\n discovered: { ui: DiscoveredArtifact[]; java: DiscoveredArtifact[] };\n}\n\nconst UI_PROJECT_DIRS = [\n \"apps\",\n \"libs\",\n \"plugins\",\n \"splash\",\n \"themes\",\n \"content\",\n \"translations\",\n];\n\nfunction joinArtifactPath(outputPath: string, fileName: string): string {\n return `${outputPath.replace(/\\/+$/, \"\")}/${fileName}`;\n}\n\nexport function discoverUiArtifacts(\n codegenFs: CodegenFileSystem\n): DiscoveredArtifact[] {\n const artifacts: DiscoveredArtifact[] = [];\n\n for (const dir of UI_PROJECT_DIRS) {\n for (const file of codegenFs.listFiles(`ui/${dir}`)) {\n if (!file.endsWith(\"project.json\")) continue;\n const raw = codegenFs.read(file);\n if (raw === null) continue;\n let project: any;\n try {\n project = JSON.parse(raw);\n } catch {\n continue;\n }\n const name = project.name;\n if (!name) continue;\n\n // Artifact paths are {projectRoot}-tokenized so projects can move; the\n // build handler needs a literal path, and the project.json's own\n // location is the project root (Nx allows no other).\n const projectRoot = file.slice(\"ui/\".length, file.lastIndexOf(\"/\"));\n const resolve = (value: string) => resolveKabPath(value, projectRoot);\n\n const kabOptions = project.targets?.kab?.options;\n if (kabOptions?.outputPath && kabOptions?.kabName) {\n artifacts.push({\n id: name,\n filename: `ui/${joinArtifactPath(\n resolve(kabOptions.outputPath),\n kabOptions.kabName\n )}`,\n });\n } else if (project.targets?.splash) {\n // splashtool writes the layer KAB into its target's outputPath; fall\n // back to the standard <projectRoot>/target/ when it is unset.\n const splashOutput = project.targets.splash.options?.outputPath as\n | string\n | undefined;\n artifacts.push({\n id: name,\n filename: `ui/${joinArtifactPath(\n resolve(splashOutput ?? `{projectRoot}/${KAB_OUTPUT_DIR}`),\n `${name}.kab`\n )}`,\n layer: 1,\n });\n }\n }\n }\n\n for (const file of codegenFs.listFiles(\"ui/external\")) {\n if (!file.endsWith(\".kab\")) continue;\n const base = file.slice(file.lastIndexOf(\"/\") + 1, -\".kab\".length);\n artifacts.push({ id: base, filename: file });\n }\n\n return artifacts;\n}\n\nexport function discoverJavaArtifacts(\n codegenFs: CodegenFileSystem\n): DiscoveredArtifact[] {\n const aggregator = codegenFs.read(\"java/pom.xml\");\n if (aggregator === null) return [];\n\n const artifacts: DiscoveredArtifact[] = [];\n for (const match of aggregator.matchAll(/<module>([^<]+)<\\/module>/g)) {\n const moduleDir = match[1];\n const pom = codegenFs.read(`java/${moduleDir}/pom.xml`);\n if (pom === null || !pom.includes(\"kos-kab-maven-plugin\")) continue;\n // The project's own artifactId is the first one outside any <parent>.\n const withoutParent = pom.replace(/<parent>[\\s\\S]*?<\\/parent>/, \"\");\n const artifactId = withoutParent.match(\n /<artifactId>([^<]+)<\\/artifactId>/\n )?.[1];\n if (!artifactId) continue;\n artifacts.push({\n id: moduleDir,\n // eslint-disable-next-line no-template-curly-in-string\n filename: `java/${moduleDir}/target/${artifactId}-\\${KOS_STD_VERSION_REGEX}.kab`,\n });\n }\n return artifacts;\n}\n\nfunction syncManifest(\n codegenFs: CodegenFileSystem,\n manifestPath: string,\n discovered: DiscoveredArtifact[],\n prune: boolean\n): CiSyncManifestResult | null {\n const raw = codegenFs.read(manifestPath);\n if (raw === null) return null;\n const manifest = JSON.parse(raw);\n const existing: any[] = manifest.artifacts ?? [];\n\n const byFilename = new Map(discovered.map((d) => [d.filename, d]));\n const kept: any[] = [];\n const stale: string[] = [];\n const pruned: string[] = [];\n\n for (const entry of existing) {\n if (byFilename.has(entry.filename)) {\n kept.push(entry);\n byFilename.delete(entry.filename);\n } else if (prune) {\n pruned.push(entry.id ?? entry.filename);\n } else {\n kept.push(entry);\n stale.push(entry.id ?? entry.filename);\n }\n }\n\n const added: string[] = [];\n for (const artifact of byFilename.values()) {\n kept.push({\n id: artifact.id,\n filename: artifact.filename,\n artifactstore: \"kos-cdn\",\n marketplace: 1,\n ...(artifact.layer !== undefined ? { layer: artifact.layer } : {}),\n });\n added.push(artifact.id);\n }\n\n if (added.length > 0 || pruned.length > 0) {\n manifest.artifacts = kept;\n codegenFs.write(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n }\n\n return { added, stale, pruned };\n}\n\nexport function syncCiManifests(\n codegenFs: CodegenFileSystem,\n options: CiSyncOptions = {}\n): CiSyncResult {\n const prune = options.prune ?? false;\n const ui = discoverUiArtifacts(codegenFs);\n const java = discoverJavaArtifacts(codegenFs);\n\n const manifests: Record<string, CiSyncManifestResult> = {};\n const plan: Array<[string, DiscoveredArtifact[]]> = [\n [\".github/build-ui.json\", ui],\n [\".github/build-java.json\", java],\n [\".github/build-release.json\", [...ui, ...java]],\n ];\n for (const [manifestPath, discovered] of plan) {\n const result = syncManifest(codegenFs, manifestPath, discovered, prune);\n if (result) {\n manifests[manifestPath] = result;\n }\n }\n\n return { manifests, discovered: { ui, java } };\n}\n","/**\n * Helpers for the java/ half of a polyglot workspace (see\n * generate-polyglot-workspace.ts).\n *\n * The Java modules themselves come from the KOS Maven archetypes\n * (com.kos.archetypes — local-install via github.com/kosdev-code/\n * kos-maven-archetypes); these helpers contribute only the glue the\n * archetypes don't own:\n * - the java/pom.xml aggregator (archetype modules are standalone — no\n * parent link — so an aggregator is needed for `mvn` at java/ and for\n * build-java.sh's java/pom.xml check)\n * - repairs to the generated pom (the archetype references\n * ${kos-kab-maven-plugin.version} without defining it, and depends on\n * api-info which the kos-bom does not manage)\n * - registration of the module's KAB in the kos_build_handler manifests\n *\n * Version numbers are always passed in by the caller (derived from the KOS\n * Maven repo's maven-metadata.xml at run time) — nothing hardcoded here.\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\n\nexport interface EnsureJavaAggregatorOptions {\n groupId: string;\n /** Aggregator artifactId (typically the workspace name). */\n artifactId: string;\n moduleName: string;\n}\n\nexport function ensureJavaAggregatorPom(\n codegenFs: CodegenFileSystem,\n options: EnsureJavaAggregatorOptions\n): void {\n const pomPath = \"java/pom.xml\";\n const existing = codegenFs.read(pomPath);\n if (existing === null) {\n codegenFs.write(\n pomPath,\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n <modelVersion>4.0.0</modelVersion>\n <groupId>${options.groupId}</groupId>\n <artifactId>${options.artifactId}</artifactId>\n <version>0.0.0-SNAPSHOT</version>\n <packaging>pom</packaging>\n <modules>\n <module>${options.moduleName}</module>\n </modules>\n</project>\n`\n );\n return;\n }\n if (existing.includes(`<module>${options.moduleName}</module>`)) {\n return;\n }\n codegenFs.write(\n pomPath,\n existing.replace(\n \"</modules>\",\n ` <module>${options.moduleName}</module>\\n </modules>`\n )\n );\n}\n\nexport interface FinalizeArchetypeModuleOptions {\n moduleName: string;\n /** kos-bom version to pin (replaces the template's 0.0.0-SNAPSHOT). */\n kosVersion?: string;\n /** Fills the template's undefined ${kos-kab-maven-plugin.version}. */\n kabPluginVersion?: string;\n /** Explicit version for the api-info dep the kos-bom doesn't manage. */\n apiInfoVersion?: string;\n}\n\n/**\n * Repair a freshly archetype-generated module for use inside a polyglot\n * workspace. Returns human-readable notes about anything it could NOT fix\n * (missing versions the caller failed to derive) so the CLI can warn.\n */\nexport function finalizeArchetypeModule(\n codegenFs: CodegenFileSystem,\n options: FinalizeArchetypeModuleOptions\n): string[] {\n const { moduleName, kosVersion, kabPluginVersion, apiInfoVersion } = options;\n const notes: string[] = [];\n const pomPath = `java/${moduleName}/pom.xml`;\n let pom = codegenFs.read(pomPath);\n if (pom === null) {\n throw new Error(`Generated module pom not found: ${pomPath}`);\n }\n\n if (pom.includes(\"<kos.version>0.0.0-SNAPSHOT</kos.version>\")) {\n if (kosVersion) {\n pom = pom.replace(\n \"<kos.version>0.0.0-SNAPSHOT</kos.version>\",\n `<kos.version>${kosVersion}</kos.version>`\n );\n } else {\n notes.push(\n \"kos.version is 0.0.0-SNAPSHOT — set it to a released kos-bom version before building\"\n );\n }\n }\n\n if (\n pom.includes(\"${kos-kab-maven-plugin.version}\") &&\n !pom.includes(\"<kos-kab-maven-plugin.version>\")\n ) {\n if (kabPluginVersion) {\n pom = pom.replace(\n /(<kos\\.version>[^<]*<\\/kos\\.version>)/,\n `$1\\n <kos-kab-maven-plugin.version>${kabPluginVersion}</kos-kab-maven-plugin.version>`\n );\n } else {\n notes.push(\n \"the ${kos-kab-maven-plugin.version} property is referenced but undefined — add it before building\"\n );\n }\n }\n\n const unversionedApiInfo = /<artifactId>api-info<\\/artifactId>(\\s*)<\\/dependency>/;\n if (unversionedApiInfo.test(pom)) {\n if (apiInfoVersion) {\n pom = pom.replace(\n unversionedApiInfo,\n `<artifactId>api-info</artifactId>$1 <version>${apiInfoVersion}</version>$1</dependency>`\n );\n } else {\n notes.push(\n \"api-info has no version and is not managed by the kos-bom — add one before building\"\n );\n }\n }\n\n codegenFs.write(pomPath, pom);\n\n // Standalone-repo extras the archetype ships that are redundant inside a\n // polyglot workspace (the repo root owns CI):\n const githubDir = `java/${moduleName}/github`;\n if (codegenFs.exists(githubDir)) {\n for (const file of codegenFs.listFiles(githubDir)) {\n codegenFs.delete(file);\n }\n }\n const gitignore = codegenFs.read(`java/${moduleName}/gitignore`);\n if (gitignore !== null) {\n codegenFs.write(`java/${moduleName}/.gitignore`, gitignore);\n codegenFs.delete(`java/${moduleName}/gitignore`);\n }\n\n return notes;\n}\n\nexport interface AddJavaArtifactOptions {\n moduleName: string;\n}\n\n/**\n * Register the module's KAB in build-java.json and build-release.json.\n * Only the artifacts arrays are touched — keyset/build_cmd/etc. are the\n * user's (same contract as ci:sync).\n */\nexport function addJavaArtifactToManifests(\n codegenFs: CodegenFileSystem,\n options: AddJavaArtifactOptions\n): void {\n const { moduleName } = options;\n for (const manifestPath of [\n \".github/build-java.json\",\n \".github/build-release.json\",\n ]) {\n const raw = codegenFs.read(manifestPath);\n if (raw === null) {\n continue;\n }\n const manifest = JSON.parse(raw);\n manifest.artifacts = manifest.artifacts ?? [];\n if (\n manifest.artifacts.some(\n (artifact: { id?: string }) => artifact.id === moduleName\n )\n ) {\n continue;\n }\n manifest.artifacts.push({\n id: moduleName,\n // eslint-disable-next-line no-template-curly-in-string\n filename: `java/${moduleName}/target/${moduleName}-\\${KOS_STD_VERSION_REGEX}.kab`,\n artifactstore: \"kos-cdn\",\n marketplace: 1,\n });\n codegenFs.write(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n }\n}\n","/**\n * Normalize generator options — resolves project references and generates\n * all case variants for template substitution.\n *\n * Ported from kos-nx-plugin/src/generators/kos-model/lib/normalize-options.ts.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { readJson } from \"../json-utils\";\nimport { normalizeAllValues } from \"../normalize-values\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../project-discovery\";\n\nexport interface KosBaseGeneratorOptions {\n name: string;\n modelProject: string;\n registrationProject?: string;\n skipRegistration?: boolean;\n modelDirectory: string;\n companion?: boolean;\n companionModel?: string;\n companionModelProject?: string;\n companionPattern?: \"composition\" | \"decorator\";\n futureAware?: \"none\" | \"minimal\" | \"complete\";\n /** Absent is a legacy third state in @kosModel, so generated models always state it. */\n singleton?: boolean;\n}\n\nexport type NormalizedOptions<T extends KosBaseGeneratorOptions> = T & {\n nameDashCase: string;\n nameProperCase: string;\n nameCamelCase: string;\n namePascalCase: string;\n nameConstantCase: string;\n nameLowerCase: string;\n companionModelDashCase: string;\n companionModelProperCase: string;\n companionModelCamelCase: string;\n companionModelPascalCase: string;\n companionModelConstantCase: string;\n companionModelLowerCase: string;\n registrationProject: string;\n importPath: string;\n template: string;\n [key: string]: any;\n};\n\n/**\n * Normalize generator options by resolving the model project and generating\n * all name variants for template substitution.\n *\n * @param codegenFs - Filesystem abstraction\n * @param options - Raw generator options\n * @param projects - Optional pre-computed project map\n */\nexport function normalizeOptions<T extends KosBaseGeneratorOptions>(\n codegenFs: CodegenFileSystem,\n options: T,\n projects?: Map<string, ProjectConfiguration>\n): NormalizedOptions<T> {\n const toNormalize: Record<string, string> = {\n name: options.name,\n };\n\n if ((options as any).modelName) {\n toNormalize.modelName = (options as any).modelName;\n }\n\n if (options.companionModel) {\n toNormalize.companionModel = options.companionModel;\n }\n\n const normalizedValues = normalizeAllValues(toNormalize);\n const modelProject = options.modelProject;\n const registrationProject = options.registrationProject || \"\";\n const useModelProject = modelProject !== \"__NONE__\";\n\n let importPath = \"\";\n if (useModelProject) {\n const modelProjectConfig = findProjectByName(\n codegenFs.root,\n modelProject,\n projects\n );\n if (modelProjectConfig) {\n const pkgJsonPath = path.join(modelProjectConfig.root, \"package.json\");\n try {\n const pkgJson = readJson<{ name: string }>(codegenFs, pkgJsonPath);\n importPath = pkgJson.name || \"\";\n } catch {\n importPath = \"\";\n }\n }\n }\n\n // Provide safe defaults for optional boolean fields that templates reference\n // directly. Without explicit values, EJS throws ReferenceError for variables\n // that are simply absent from the options object (undefined keys are omitted\n // by the spread, which is different from being present-but-false).\n const booleanDefaults: Partial<KosBaseGeneratorOptions> = {\n companion: false,\n skipRegistration: false,\n futureAware: \"none\",\n singleton: false,\n };\n\n return {\n ...booleanDefaults,\n ...options,\n ...normalizedValues,\n modelProject,\n importPath,\n registrationProject,\n template: \"\",\n } as NormalizedOptions<T>;\n}\n","/**\n * Source of tools/scripts/update-release-version.mjs — the implementation of\n * the `version` target emitted by buildKabTargets (see kab-targets.ts).\n *\n * Kept as a constant (not a .template file) so the preset generator and the\n * add-version-targets migration emit byte-identical scripts and cannot drift.\n * The script has no template variables: the project name arrives via argv.\n */\nexport const UPDATE_RELEASE_VERSION_SCRIPT = `import devkit from \"@nx/devkit\";\nimport { resolve } from \"path\";\nimport { readFileSync, writeFileSync } from \"fs\";\nimport prettier from \"prettier\";\n\n// KOS artifact versioning: stamps the project's .kos.json \"version\" field\n// (which kabtool bakes into the KAB). Never touches package.json.\n// Driven by tag-based releases:\n// nx run-many --target=version --args=--ver=$KOSBUILD_VERSION\n\nconst { readCachedProjectGraph } = devkit;\nconst [, , name, versionArg] = process.argv;\n\n// \"{args.ver}\" arrives literally when the target runs without --args=--ver=<v>;\n// treat that (or a missing arg) as \"report current version, change nothing\".\nconst version =\n versionArg && !versionArg.startsWith(\"{args\") ? versionArg : undefined;\n\nif (!name) {\n console.error(\"usage: update-release-version.mjs <project> <version>\");\n process.exit(1);\n}\n\nconst graph = readCachedProjectGraph();\nconst project = graph.nodes[name];\nif (!project) {\n console.error(\"Unknown project: \" + name);\n process.exit(1);\n}\n\nconst kosJsonPath = resolve(process.cwd(), project.data.root, \".kos.json\");\nlet kosJson;\ntry {\n kosJson = JSON.parse(readFileSync(kosJsonPath, \"utf8\"));\n} catch {\n console.error(\"Missing or invalid .kos.json: \" + kosJsonPath);\n process.exit(1);\n}\n\nif (!version) {\n console.log(name + \": \" + kosJson.version + \" (no --ver given; unchanged)\");\n process.exit(0);\n}\n\nconst prettierOptions = await prettier.resolveConfig(kosJsonPath);\nconst output = await prettier.format(\n JSON.stringify({ ...kosJson, version }, null, 2),\n { ...prettierOptions, parser: \"json\" }\n);\nwriteFileSync(kosJsonPath, output);\nconsole.log(name + \": version -> \" + version);\n`;\n","/**\n * Shared model-augmentation toolkit (ts-morph / AST based).\n *\n * Primitives for the capability mutators (add-container-support, add-future, …)\n * that augment an EXISTING model with coordinated, multi-site edits — decorators,\n * declaration-merging interfaces, imports, methods — without the fragility of\n * regex string replacement.\n *\n * Bridged through CodegenFileSystem so the same dry-run overlay + formatFiles\n * pipeline used by the scaffolders applies unchanged: read content → in-memory\n * ts-morph SourceFile → mutate → getFullText() → write.\n *\n * ts-morph is confined to kos-codegen-core (build-time tooling) and must not leak\n * into any runtime SDK package.\n */\nimport {\n IndentationText,\n Node,\n Project,\n QuoteKind,\n Scope,\n VariableDeclarationKind,\n type ClassDeclaration,\n type ObjectLiteralExpression,\n type SourceFile,\n} from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\n\n/**\n * Read a file via the filesystem abstraction, apply an AST mutation, write it back.\n * The mutation operates on an in-memory ts-morph SourceFile — no disk access here,\n * so the caller's CodegenFileSystem (real or dry-run overlay) owns all I/O.\n */\nexport function transformSourceFile(\n codegenFs: CodegenFileSystem,\n filePath: string,\n mutate: (sf: SourceFile) => void\n): void {\n const content = codegenFs.read(filePath);\n if (content === null) {\n throw new Error(`File not found: ${filePath}`);\n }\n const project = new Project({\n useInMemoryFileSystem: true,\n manipulationSettings: {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: QuoteKind.Double,\n },\n });\n const sourceFile = project.createSourceFile(filePath, content, {\n overwrite: true,\n });\n mutate(sourceFile);\n codegenFs.write(filePath, sourceFile.getFullText());\n}\n\n/**\n * Read a file via the filesystem abstraction and inspect it as a ts-morph\n * SourceFile, writing nothing back. The read-only counterpart of\n * `transformSourceFile`, for discovery over generated declarations.\n */\nexport function readSourceFile<T>(\n codegenFs: CodegenFileSystem,\n filePath: string,\n inspect: (sf: SourceFile) => T\n): T {\n const content = codegenFs.read(filePath);\n if (content === null) {\n throw new Error(`File not found: ${filePath}`);\n }\n const project = new Project({ useInMemoryFileSystem: true });\n return inspect(\n project.createSourceFile(filePath, content, { overwrite: true })\n );\n}\n\n/**\n * The object-literal text of a class decorator's first argument, whether written\n * inline or passed as a same-file const. Generated models name the config so a\n * derived type can read it; hand-written ones inline it.\n */\nexport function decoratorConfigText(\n sourceFile: SourceFile,\n cls: ClassDeclaration,\n decoratorName: string\n): string | undefined {\n const arg = cls.getDecorator(decoratorName)?.getArguments()[0];\n if (!arg) return undefined;\n if (arg.getKindName() === \"ObjectLiteralExpression\") return arg.getText();\n\n // Anything that is not an identifier (a bare string literal, say) is its own\n // text; an identifier is followed to the const it names.\n const text = arg.getText().trim();\n if (!/^[A-Za-z_$][\\w$]*$/.test(text)) return text;\n const initializer = sourceFile\n .getVariableDeclaration(text)\n ?.getInitializer()\n ?.getText();\n return initializer ? initializer.replace(/\\s+as\\s+const\\s*$/, \"\") : text;\n}\n\n/** A named import to ensure on a module: the symbol and whether it is type-only. */\nexport interface NamedImportSpec {\n name: string;\n isTypeOnly?: boolean;\n}\n\n/**\n * Ensure the given named imports exist on an import from `moduleSpecifier`.\n * Idempotent: existing names are left untouched; the import declaration is created\n * if absent. Resolves to the same module the model already imports `kosModel` from\n * when `moduleSpecifier` matches, so internal vs. published paths are respected.\n */\nexport function ensureNamedImport(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n names: NamedImportSpec[]\n): void {\n const decls = sourceFile\n .getImportDeclarations()\n .filter((d) => d.getModuleSpecifierValue() === moduleSpecifier);\n\n // Dedup across ALL imports from this module (a file may have both a value\n // import and a separate `import type { … }` from the same specifier).\n const existing = new Set<string>();\n for (const d of decls) {\n for (const n of d.getNamedImports()) existing.add(n.getName());\n }\n\n // Always target a VALUE import declaration — adding a runtime symbol to an\n // `import type { … }` block would strip it at compile time. Type-only names go\n // in with an inline `type` modifier (the `import { kosX, type KosX }` idiom).\n let target = decls.find((d) => !d.isTypeOnly());\n if (!target) {\n target = sourceFile.addImportDeclaration({ moduleSpecifier });\n }\n\n for (const { name, isTypeOnly } of names) {\n if (existing.has(name)) continue;\n target.addNamedImport({ name, isTypeOnly: !!isTypeOnly });\n existing.add(name);\n }\n}\n\n/**\n * Resolve the module specifier the model imports `kosModel` from, so augmentation\n * imports land on the same line/source (internal `../../../core/core/decorators`\n * vs. published `@kosdev-code/kos-ui-sdk`). Falls back to the published package.\n */\nexport function resolveSdkModuleSpecifier(sourceFile: SourceFile): string {\n const decl = sourceFile\n .getImportDeclarations()\n .find((d) => d.getNamedImports().some((n) => n.getName() === \"kosModel\"));\n return decl?.getModuleSpecifierValue() ?? \"@kosdev-code/kos-ui-sdk\";\n}\n\n/**\n * Find the primary model class. Prefers `preferName`, then a class whose name ends\n * in `ModelImpl`, then the first exported class, then the first class.\n */\nexport function getModelClass(\n sourceFile: SourceFile,\n preferName?: string\n): ClassDeclaration {\n const classes = sourceFile.getClasses();\n const byName = preferName\n ? classes.find((c) => c.getName() === preferName)\n : undefined;\n if (byName) return byName;\n const impl = classes.find((c) => /ModelImpl$/.test(c.getName() ?? \"\"));\n if (impl) return impl;\n const exported = classes.find((c) => c.isExported());\n if (exported) return exported;\n if (classes.length > 0) return classes[0];\n throw new Error(\"No class declaration found in model file.\");\n}\n\n/**\n * Add a class decorator idempotently (matched by decorator name). Supports type\n * arguments (`@name<T>(args)`) which ts-morph's structured API can't express, by\n * writing the call expression as decorator text. Inserts directly after `@kosModel`\n * when present (matching KOS convention), otherwise nearest the class.\n */\nexport function addClassDecorator(\n cls: ClassDeclaration,\n name: string,\n opts?: { typeArgs?: string[]; argsText?: string }\n): void {\n if (cls.getDecorator(name)) return;\n const typeArgs = opts?.typeArgs?.length\n ? `<${opts.typeArgs.join(\", \")}>`\n : \"\";\n const args = opts?.argsText ?? \"\";\n\n const decorators = cls.getDecorators();\n const kosModelIdx = decorators.findIndex((d) => d.getName() === \"kosModel\");\n const insertIdx = kosModelIdx >= 0 ? kosModelIdx + 1 : decorators.length;\n cls.insertDecorator(insertIdx, {\n name: `${name}${typeArgs}`,\n arguments: args ? [args] : [],\n });\n}\n\n/**\n * Ensure a declaration-merging interface `export interface <name> extends <expr>`.\n * If the interface already exists (e.g. merged for another capability), adds the\n * extends expression to it; otherwise creates an empty exported interface with the\n * `no-empty-interface` lint suppression. Idempotent by base type name.\n */\nexport function ensureDeclarationMerge(\n sourceFile: SourceFile,\n interfaceName: string,\n extendsExpr: string,\n typeParameters: string[] = []\n): void {\n const baseType = extendsExpr.split(\"<\")[0].trim();\n let iface = sourceFile.getInterface(interfaceName);\n if (iface) {\n const already = iface\n .getExtends()\n .some((e) => e.getText().split(\"<\")[0].trim() === baseType);\n if (!already) iface.addExtends(extendsExpr);\n return;\n }\n // A merged interface must carry the SAME type parameters as the class it merges\n // with, or TS errors (\"all declarations must have identical type parameters\").\n iface = sourceFile.addInterface({\n name: interfaceName,\n isExported: true,\n typeParameters,\n extends: [extendsExpr],\n });\n // Prepend the empty-interface lint suppression line.\n sourceFile.insertText(\n iface.getStart(),\n \"// eslint-disable-next-line @typescript-eslint/no-empty-interface\\n\"\n );\n}\n\n/**\n * Ensure a file-level eslint-disable block comment for `rule` at the top of file.\n * Call LAST in a mutation — it uses raw text insertion and invalidates node refs.\n */\nexport function ensureFileEslintDisable(\n sourceFile: SourceFile,\n rule: string\n): void {\n if (sourceFile.getFullText().includes(rule)) return;\n sourceFile.insertText(0, `/* eslint-disable ${rule} */\\n`);\n}\n\n/**\n * Add a module-level `const` after the import block, idempotently. Returns true\n * if added. Used for endpoint descriptors, which must sit outside the class so\n * `typeof NAME` can be referenced from a parameter type.\n */\nexport function ensureModuleConst(\n sourceFile: SourceFile,\n spec: { name: string; initializer: string }\n): boolean {\n if (sourceFile.getVariableDeclaration(spec.name)) return false;\n const imports = sourceFile.getImportDeclarations();\n const index =\n imports.length > 0 ? imports[imports.length - 1].getChildIndex() + 1 : 0;\n sourceFile.insertVariableStatement(index, {\n declarationKind: VariableDeclarationKind.Const,\n declarations: [{ name: spec.name, initializer: spec.initializer }],\n });\n return true;\n}\n\n/** Index just past the last import, where module-level declarations belong. */\nfunction afterImports(sourceFile: SourceFile): number {\n const imports = sourceFile.getImportDeclarations();\n return imports.length > 0\n ? imports[imports.length - 1].getChildIndex() + 1\n : 0;\n}\n\n/** Strip the quotes ts-morph keeps on a quoted property name. */\nfunction unquote(name: string): string {\n return name.replace(/^[\"']|[\"']$/g, \"\");\n}\n\n/** The object literal an `export const X = { … } as const` declares, or null. */\nfunction getConstCatalogLiteral(\n sourceFile: SourceFile,\n name: string\n): ObjectLiteralExpression | null {\n const declaration = sourceFile.getVariableDeclaration(name);\n if (!declaration) return null;\n let initializer = declaration.getInitializer();\n if (Node.isAsExpression(initializer)) {\n initializer = initializer.getExpression();\n }\n if (!initializer || !Node.isObjectLiteralExpression(initializer)) {\n throw new Error(\n `\"${name}\" exists in ${sourceFile.getBaseName()} but is not an object literal.`\n );\n }\n return initializer;\n}\n\n/**\n * Ensure an exported `as const` catalog holds an entry with this initializer,\n * and report the key that holds it.\n *\n * An entry whose initializer already matches is REUSED rather than duplicated,\n * so one descriptor is declared once however many members reference it.\n * Equivalence is delegated to `equals` because equivalent initializers are not\n * always identical text — quote style and spacing vary by who wrote the file.\n */\nexport function ensureConstCatalogEntry(\n sourceFile: SourceFile,\n spec: {\n catalogName: string;\n key: string;\n initializer: string;\n equals?: (existing: string, candidate: string) => boolean;\n /** Doc comment for the new entry. Not applied when an entry is reused. */\n leadingTrivia?: string;\n }\n): { key: string; created: boolean } {\n const matches =\n spec.equals ??\n ((existing: string, candidate: string) => existing === candidate);\n\n let literal = getConstCatalogLiteral(sourceFile, spec.catalogName);\n if (!literal) {\n // Created empty and filled through the structured API, so the first entry\n // is indented by ts-morph exactly like every later one.\n sourceFile.insertVariableStatement(afterImports(sourceFile), {\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [{ name: spec.catalogName, initializer: \"{} as const\" }],\n });\n literal = getConstCatalogLiteral(sourceFile, spec.catalogName);\n if (!literal) {\n throw new Error(`Failed to create catalog \"${spec.catalogName}\".`);\n }\n literal.addPropertyAssignment({\n name: spec.key,\n initializer: spec.initializer,\n leadingTrivia: spec.leadingTrivia,\n });\n return { key: spec.key, created: true };\n }\n\n for (const property of literal\n .getProperties()\n .filter(Node.isPropertyAssignment)) {\n const existingKey = unquote(property.getName());\n const existingInitializer = property.getInitializerOrThrow().getText();\n if (matches(existingInitializer, spec.initializer)) {\n return { key: existingKey, created: false };\n }\n if (existingKey === spec.key) {\n throw new Error(\n `\"${spec.catalogName}.${spec.key}\" already exists with a different value ` +\n `(${existingInitializer}). Use a different methodName, or reconcile the catalog by hand.`\n );\n }\n }\n\n literal.addPropertyAssignment({\n name: spec.key,\n initializer: spec.initializer,\n leadingTrivia: spec.leadingTrivia,\n });\n return { key: spec.key, created: true };\n}\n\n/** Add an exported type alias unless one of that name already exists. */\nexport function ensureExportedTypeAlias(\n sourceFile: SourceFile,\n spec: { name: string; type: string; docs?: string }\n): boolean {\n if (sourceFile.getTypeAlias(spec.name)) return false;\n sourceFile.addTypeAlias({\n name: spec.name,\n type: spec.type,\n isExported: true,\n docs: spec.docs ? [spec.docs] : undefined,\n });\n return true;\n}\n\n/**\n * Add an exported identity mapper `raw -> data` unless one of that name exists.\n * Emitted as an identity so it compiles untouched; narrowing the data type is\n * what makes it a real boundary.\n */\nexport function ensureExportedMapper(\n sourceFile: SourceFile,\n spec: { name: string; rawType: string; dataType: string }\n): boolean {\n if (sourceFile.getVariableDeclaration(spec.name)) return false;\n sourceFile.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: spec.name,\n initializer: `(raw: ${spec.rawType}): ${spec.dataType} => raw`,\n },\n ],\n });\n return true;\n}\n\n/** Add `export * from \"<moduleSpecifier>\"` unless the barrel already has it. */\nexport function ensureBarrelExport(\n sourceFile: SourceFile,\n moduleSpecifier: string\n): boolean {\n const present = sourceFile\n .getExportDeclarations()\n .some((d) => d.getModuleSpecifierValue() === moduleSpecifier);\n if (present) return false;\n sourceFile.addExportDeclaration({ moduleSpecifier });\n return true;\n}\n\n/**\n * Add named exports for a module to a barrel, creating the export declaration\n * when the module is not exported yet and appending only the missing names when\n * it is. Value and type exports are kept as separate declarations so a type-only\n * export is not widened into a value export.\n *\n * Returns true if the file changed.\n */\nexport function ensureNamedExports(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n names: string[],\n isTypeOnly = false\n): boolean {\n const existing = sourceFile\n .getExportDeclarations()\n .find(\n (d) =>\n d.getModuleSpecifierValue() === moduleSpecifier &&\n d.isTypeOnly() === isTypeOnly\n );\n\n if (!existing) {\n sourceFile.addExportDeclaration({\n moduleSpecifier,\n isTypeOnly,\n namedExports: names.map((name) => {\n return { name };\n }),\n });\n return true;\n }\n\n const present = new Set(existing.getNamedExports().map((e) => e.getName()));\n const missing = names.filter((name) => !present.has(name));\n if (missing.length === 0) return false;\n\n existing.addNamedExports(\n missing.map((name) => {\n return { name };\n })\n );\n return true;\n}\n\n/**\n * Add an exported interface to a declarations file, leaving any existing\n * declaration untouched. Returns true if the interface was added.\n */\nexport function ensureExportedInterface(\n sourceFile: SourceFile,\n name: string,\n properties: { name: string; type: string; hasQuestionToken?: boolean }[] = [],\n extendsTypes: string[] = []\n): boolean {\n if (sourceFile.getInterface(name)) return false;\n\n sourceFile.addInterface({\n name,\n isExported: true,\n extends: extendsTypes,\n properties,\n });\n return true;\n}\n\n/** A decorated method to add to a model class. */\nexport interface DecoratedMethodSpec {\n name: string;\n decoratorName: string;\n /** Explicit decorator type arguments, e.g. `[\"RawType\", \"DataType\"]`. */\n decoratorTypeArgs?: string[];\n decoratorArgsText?: string;\n parameters?: { name: string; type?: string; optional?: boolean }[];\n returnType?: string;\n isAsync?: boolean;\n statements?: string;\n /** Doc comment emitted above the method. */\n docs?: string;\n}\n\n/**\n * Add a decorated method to a class idempotently (skips if a method of that name\n * already exists). Returns true if added.\n */\nexport function addDecoratedMethod(\n cls: ClassDeclaration,\n spec: DecoratedMethodSpec\n): boolean {\n if (cls.getMethod(spec.name)) return false;\n cls.addMethod({\n name: spec.name,\n isAsync: spec.isAsync,\n returnType: spec.returnType,\n docs: spec.docs ? [spec.docs] : undefined,\n parameters: spec.parameters?.map((p) => {\n return { name: p.name, type: p.type, hasQuestionToken: p.optional };\n }),\n statements: spec.statements,\n decorators: [\n {\n name: spec.decoratorName,\n typeArguments: spec.decoratorTypeArgs,\n arguments: spec.decoratorArgsText ? [spec.decoratorArgsText] : [],\n },\n ],\n });\n return true;\n}\n\n/** A plain (undecorated) property to add to a model class. */\nexport interface PlainPropertySpec {\n name: string;\n type?: string;\n /** Initializer expression text, e.g. `\"\"`, `0`, `false`. */\n initializer?: string;\n scope?: \"private\" | \"protected\" | \"public\";\n readonly?: boolean;\n /** Definite-assignment `!` (compiles under strictPropertyInitialization). */\n hasExclamation?: boolean;\n}\n\n/**\n * Member index for a new property: right after the last existing property, so\n * properties (basic fields, dependencies, config properties) stay grouped at the\n * TOP of the class — before the constructor and methods. Index 0 if none yet.\n */\nfunction propertyInsertIndex(cls: ClassDeclaration): number {\n const props = cls.getProperties();\n if (props.length === 0) return 0;\n return props[props.length - 1].getChildIndex() + 1;\n}\n\n/**\n * Add a plain class property (no decorator) idempotently. Returns true if added.\n * Used for basic model state fields (`prop1: string`) — distinct from the\n * decorator-backed config/dependency/etc. properties. Inserted at the top.\n */\nexport function addPlainProperty(\n cls: ClassDeclaration,\n spec: PlainPropertySpec\n): boolean {\n if (cls.getProperty(spec.name)) return false;\n cls.insertProperty(propertyInsertIndex(cls), {\n name: spec.name,\n type: spec.type,\n initializer: spec.initializer,\n isReadonly: !!spec.readonly,\n scope: spec.scope ? SCOPE_MAP[spec.scope] : undefined,\n hasExclamationToken: spec.initializer ? false : !!spec.hasExclamation,\n });\n return true;\n}\n\n/** A decorated property to add to a model class. */\nexport interface DecoratedPropertySpec {\n name: string;\n decoratorName: string;\n decoratorArgsText?: string;\n type?: string;\n scope?: \"private\" | \"protected\" | \"public\";\n hasExclamation?: boolean;\n /** Initializer expression text, e.g. `new KosModelContainer<X>()` or `[]`. */\n initializer?: string;\n /**\n * Emit the decorator WITHOUT call parens — a DIRECT (non-factory) decorator like\n * `@kosChild`. Default false (factory form `@name()` / `@name(args)`).\n */\n bare?: boolean;\n}\n\nconst SCOPE_MAP = {\n private: Scope.Private,\n protected: Scope.Protected,\n public: Scope.Public,\n} as const;\n\n/**\n * Add a decorated property to a class idempotently (skips if a property of that\n * name already exists). Returns true if added.\n */\nexport function addDecoratedProperty(\n cls: ClassDeclaration,\n spec: DecoratedPropertySpec\n): boolean {\n if (cls.getProperty(spec.name)) return false;\n cls.insertProperty(propertyInsertIndex(cls), {\n name: spec.name,\n type: spec.type,\n initializer: spec.initializer,\n scope: spec.scope ? SCOPE_MAP[spec.scope] : undefined,\n hasExclamationToken: spec.initializer ? false : !!spec.hasExclamation,\n decorators: [\n spec.bare && !spec.decoratorArgsText\n ? { name: spec.decoratorName } // no `arguments` key → bare `@name`, no parens\n : {\n name: spec.decoratorName,\n arguments: spec.decoratorArgsText ? [spec.decoratorArgsText] : [],\n },\n ],\n });\n return true;\n}\n\n/** A computed getter to add to a model class. */\nexport interface GetterSpec {\n name: string;\n returnType?: string;\n /** Body statements; default a TODO stub returning undefined. */\n statements?: string;\n}\n\n/**\n * Add a computed getter (`get name(): T { ... }`) idempotently — a derived,\n * read-only member. Returns true if added. Placed after the constructor (or after\n * the properties if there is none), ahead of regular methods.\n */\nexport function addGetter(cls: ClassDeclaration, spec: GetterSpec): boolean {\n if (cls.getGetAccessor(spec.name)) return false;\n const ctor = cls.getConstructors()[0];\n const index = ctor ? ctor.getChildIndex() + 1 : propertyInsertIndex(cls);\n cls.insertGetAccessor(index, {\n name: spec.name,\n returnType: spec.returnType,\n statements:\n spec.statements ?? \"// TODO: derive and return the computed value\",\n });\n return true;\n}\n","/**\n * Enumerate the service operations a project already has types for.\n *\n * NOT a substitute for the device. A connected device's live OpenAPI is the\n * source of truth about what endpoints exist, what they mean, and whether one\n * is debug-only — discover there first (kos-device: `search_services` →\n * `describe_endpoint` → `resolve_service_request`). This reads the types\n * `api:generate` already wrote into the project, which is a SNAPSHOT of that\n * truth: correct for the app/version it was generated from, silent about\n * anything added since, and empty until api:generate has run.\n *\n * It exists for the offline case — no device reachable, or a human picking from\n * a list rather than typing a path from memory.\n *\n * Everything here comes out of `openapi.d.ts`, which openapi-typescript emits in\n * a shape precise enough to read structurally: a method that exists is\n * `post: { … }` while an absent one is `post?: never`, the OpenAPI `summary`\n * survives as the method's JSDoc, and path parameters keep their names.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { readSourceFile } from \"./augment/ts-toolkit\";\n\n/** HTTP methods a response type can be derived for (lowercase, as spec'd). */\nconst CATALOG_METHODS = [\"get\", \"put\", \"post\", \"delete\", \"patch\"] as const;\nexport type CatalogMethod = (typeof CATALOG_METHODS)[number];\n\nexport interface ServiceOperation {\n /** OpenAPI path, e.g. `/api/board/{id}`. */\n path: string;\n method: CatalogMethod;\n /** The spec's `summary`, when it had one. */\n summary?: string;\n /** Names of the `{…}` placeholders the path declares, in order. */\n pathParams: string[];\n}\n\nexport interface ServiceCatalogEntry {\n /** App segment of the services dir, e.g. `dispense`. */\n app: string;\n /** Version segment, e.g. `daily` or `1.9.x`. */\n version: string;\n /** Root-relative path of the generated service module (with extension). */\n serviceModulePath: string;\n operations: ServiceOperation[];\n}\n\nconst SERVICE_MODULE_RE = /\\/utils\\/services\\/([^/]+)\\/([^/]+)\\/service\\.ts$/;\n\nexport interface ServiceCatalogQuery {\n /** Project whose generated types to read. */\n modelProject: string;\n /** Limit to one app segment (e.g. `dispense`). */\n app?: string;\n /** Limit to one version segment (e.g. `daily`). */\n version?: string;\n}\n\n/**\n * List every generated service module in a project and the operations it types.\n * Returns an empty array when the project has no generated types — the caller\n * should tell the user to run `api:generate`, not treat it as \"no endpoints\".\n */\nexport function listServiceCatalog(\n codegenFs: CodegenFileSystem,\n query: ServiceCatalogQuery,\n projects?: Map<string, ProjectConfiguration>\n): ServiceCatalogEntry[] {\n const project = findProjectByName(\n codegenFs.root,\n query.modelProject,\n projects\n );\n if (!project) {\n throw new Error(`Project not found: ${query.modelProject}`);\n }\n const sourceRoot = project.sourceRoot || path.join(project.root, \"src\");\n\n const entries: ServiceCatalogEntry[] = [];\n for (const file of codegenFs.listFiles(sourceRoot)) {\n const posix = file.split(path.sep).join(\"/\");\n const match = SERVICE_MODULE_RE.exec(posix);\n if (!match) continue;\n const [, app, version] = match;\n if (query.app && app !== query.app) continue;\n if (query.version && version !== query.version) continue;\n\n const openapiPath = posix.replace(/service\\.ts$/, \"openapi.d.ts\");\n if (!codegenFs.exists(openapiPath)) continue;\n\n entries.push({\n app,\n version,\n serviceModulePath: posix,\n operations: readOperations(codegenFs, openapiPath) ?? [],\n });\n }\n return entries.sort(\n (a, b) => a.app.localeCompare(b.app) || a.version.localeCompare(b.version)\n );\n}\n\n/**\n * The operations a generated service module types, for callers that hold the\n * module rather than a project name — path validation, above all.\n *\n * `paths` normally lives in the `openapi.d.ts` beside the module, but the module\n * may declare it inline instead. Returns null when NEITHER does: that is \"these\n * types cannot answer the question\", which a caller must not read as \"the\n * endpoint does not exist\".\n *\n * @param serviceModuleFile Root-relative path of the module, with or without `.ts`.\n */\nexport function readServiceModuleOperations(\n codegenFs: CodegenFileSystem,\n serviceModuleFile: string\n): ServiceOperation[] | null {\n const moduleFile = serviceModuleFile.endsWith(\".ts\")\n ? serviceModuleFile\n : `${serviceModuleFile}.ts`;\n const posix = moduleFile.split(path.sep).join(\"/\");\n const openapiPath = posix.replace(/service\\.ts$/, \"openapi.d.ts\");\n\n for (const candidate of [openapiPath, posix]) {\n if (!codegenFs.exists(candidate)) continue;\n const operations = readOperations(codegenFs, candidate);\n if (operations) return operations;\n }\n return null;\n}\n\n/** Parse one `openapi.d.ts` into its operations; null when it declares no `paths`. */\nfunction readOperations(\n codegenFs: CodegenFileSystem,\n openapiPath: string\n): ServiceOperation[] | null {\n return readSourceFile(codegenFs, openapiPath, (sf) => {\n const paths = sf.getInterface(\"paths\");\n if (!paths) return null;\n\n const operations: ServiceOperation[] = [];\n for (const pathProp of paths.getProperties()) {\n const servicePath = unquote(pathProp.getName());\n const literal = pathProp.getTypeNode();\n // Each path maps to a type literal of per-method members; anything else\n // is a shape this parser does not claim to understand.\n if (!literal || !(\"getProperties\" in literal)) continue;\n\n for (const methodProp of (literal as any).getProperties()) {\n const method = methodProp.getName();\n if (!isCatalogMethod(method)) continue;\n const typeText: string = methodProp.getTypeNode()?.getText() ?? \"\";\n // `post?: never` is the spec saying this path has no POST.\n if (methodProp.hasQuestionToken() && typeText === \"never\") continue;\n\n operations.push({\n path: servicePath,\n method,\n summary: readSummary(methodProp),\n pathParams: [...servicePath.matchAll(/\\{([^}]+)\\}/g)].map(\n (m) => m[1]\n ),\n });\n }\n }\n return operations;\n });\n}\n\nfunction isCatalogMethod(value: string): value is CatalogMethod {\n return (CATALOG_METHODS as readonly string[]).includes(value);\n}\n\n/** The OpenAPI `summary`, which openapi-typescript emits as leading JSDoc. */\nfunction readSummary(methodProp: {\n getLeadingCommentRanges: () => { getText: () => string }[];\n}): string | undefined {\n const text = methodProp\n .getLeadingCommentRanges()\n .map((c) => c.getText())\n .join(\" \")\n .replace(/^\\/\\*+/, \"\")\n .replace(/\\*+\\/$/, \"\")\n .replace(/^\\s*\\*\\s?/gm, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n return text || undefined;\n}\n\nfunction unquote(name: string): string {\n return name.replace(/^[\"']|[\"']$/g, \"\");\n}\n","/**\n * Barrel export manipulation utilities.\n *\n * Appends `export * from './path'` lines to index.ts files,\n * handling deduplication.\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\n\n/**\n * Append a barrel re-export to an index.ts file, creating it if necessary.\n * Skips the append if the export already exists.\n *\n * @param codegenFs - Filesystem abstraction\n * @param indexPath - Path to the index.ts file (relative to root)\n * @param exportPath - The module path to export (e.g. './my-hook')\n */\nexport function appendBarrelExport(\n codegenFs: CodegenFileSystem,\n indexPath: string,\n exportPath: string\n): void {\n const exportLine = `export * from '${exportPath}'`;\n const content = codegenFs.read(indexPath) ?? \"\";\n const lines = content.split(\"\\n\");\n\n if (lines.some((line) => line.includes(exportLine))) {\n return; // already present\n }\n\n lines.push(exportLine);\n codegenFs.write(indexPath, lines.join(\"\\n\"));\n}\n","/**\n * TypeScript AST-based index.ts updater.\n *\n * Adds `export * from './path'` declarations to a barrel file using\n * the TypeScript compiler API for proper AST manipulation.\n *\n * Ported from kos-nx-plugin/src/generators/kos-model/lib/utils/ts-visitor.ts.\n */\nimport * as ts from \"typescript\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { getCodegenLogger } from \"../logger\";\n\n/**\n * Add an export-all declaration to an index.ts file using TS AST.\n *\n * @param codegenFs - Filesystem abstraction\n * @param indexPath - Path to the index.ts file (relative to root)\n * @param modelPath - Relative path to export (e.g. 'models/my-model')\n */\nexport function updateModelIndex(\n codegenFs: CodegenFileSystem,\n indexPath: string,\n modelPath: string\n): void {\n const logger = getCodegenLogger();\n\n if (!indexPath) return;\n\n const content = codegenFs.read(indexPath);\n if (content === null) {\n logger.warn(`Index file not found: ${indexPath}`);\n return;\n }\n\n logger.info(`Updating ${indexPath} — adding export for ${modelPath}`);\n\n const sourceFile = ts.createSourceFile(\n indexPath,\n content,\n ts.ScriptTarget.Latest,\n true\n );\n\n // Idempotent: the model and container passes both target the same directory,\n // and generators may be re-run — never append a duplicate export.\n const alreadyExported = sourceFile.statements.some(\n (st) =>\n ts.isExportDeclaration(st) &&\n st.moduleSpecifier !== undefined &&\n ts.isStringLiteral(st.moduleSpecifier) &&\n st.moduleSpecifier.text === `./${modelPath}`\n );\n if (alreadyExported) {\n logger.info(`Export for ${modelPath} already present in ${indexPath}`);\n return;\n }\n\n const exportDeclaration = ts.factory.createExportDeclaration(\n undefined,\n false,\n undefined,\n ts.factory.createStringLiteral(`./${modelPath}`)\n );\n\n const updatedSourceFile = ts.factory.updateSourceFile(sourceFile, [\n ...sourceFile.statements,\n exportDeclaration,\n ]);\n\n const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n const newContents = printer.printFile(updatedSourceFile);\n\n codegenFs.write(indexPath, newContents);\n}\n","/**\n * Core generator: KOS Companion Model.\n *\n * Generates companion model files into a child project with references\n * to the parent model's package.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { readJson } from \"../json-utils\";\nimport { normalizeAllValues } from \"../normalize-values\";\nimport { getCodegenLogger } from \"../logger\";\nimport { getKosProjectConfiguration } from \"../kos-config\";\n\nexport interface CompanionModelOptions {\n companionModelName: string;\n companionModelProject: string;\n modelName: string;\n modelProject: string;\n companionPattern?: \"composition\" | \"decorator\";\n}\n\n/**\n * Generate a companion model.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory\n * @param options - Generator options\n * @param projects - Optional pre-computed project map\n */\nexport function generateCompanionModel(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: CompanionModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n const logger = getCodegenLogger();\n\n const normalized = normalizeAllValues({\n companionModelName: options.companionModelName,\n modelName: options.modelName,\n });\n\n const companionChildKosConfig = getKosProjectConfiguration(\n codegenFs,\n options.companionModelProject,\n projects\n );\n\n const parentProject = findProjectByName(\n codegenFs.root,\n options.modelProject,\n projects\n );\n const childProject = findProjectByName(\n codegenFs.root,\n options.companionModelProject,\n projects\n );\n\n const projectRoot = childProject?.sourceRoot;\n if (!projectRoot) {\n logger.warn(`Companion child project source root not found`);\n return;\n }\n\n let importPath = \"\";\n if (parentProject) {\n const pkgJsonPath = path.join(parentProject.root, \"package.json\");\n try {\n const pkgJson = readJson<{ name: string }>(codegenFs, pkgJsonPath);\n importPath = pkgJson.name || \"\";\n } catch {\n importPath = \"\";\n }\n }\n\n const modelLocation =\n companionChildKosConfig?.generator?.defaults?.model?.folder || \"\";\n const filePath = path.join(\n projectRoot,\n modelLocation,\n normalized.companionModelNameDashCase\n );\n\n logger.info(`Generating companion model in ${filePath}`);\n generateFilesFromTemplates(codegenFs, templateDir, filePath, {\n ...options,\n ...normalized,\n importPath,\n });\n}\n","/**\n * Core generator: KOS Container Model.\n *\n * Generates a container model within an existing model project.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as ejs from \"ejs\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport {\n addKosModelConfiguration,\n getCurrentDirectoryName,\n getKosProjectConfiguration,\n getProject,\n} from \"../kos-config\";\nimport { getCodegenLogger } from \"../logger\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport {\n ensureExportedInterface,\n ensureNamedExports,\n transformSourceFile,\n} from \"./augment/ts-toolkit\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { updateModelIndex } from \"./update-model-index\";\n\nexport interface ContainerModelOptions extends KosBaseGeneratorOptions {\n modelName?: string;\n singleton?: boolean;\n autoRegister?: boolean;\n /**\n * The model folder already exists and holds a written model, so the container\n * is ADDED to it: only the container model file is rendered, and the folder's\n * types and barrel are edited in place. Rendering the whole template set here\n * would overwrite the model's own options interface and barrel.\n */\n existingModel?: boolean;\n}\n\n/**\n * Generate a container model.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory (containing model/ and services/ subdirs)\n * @param options - Generator options (mutated to fill in defaults)\n * @param cwd - Current working directory for project resolution\n * @param projects - Optional pre-computed project map\n */\nexport function generateContainerModel(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ContainerModelOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): void {\n const logger = getCodegenLogger();\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n const modelName = options.modelName || getCurrentDirectoryName(cwd);\n if (!modelName) {\n throw new Error(\n \"No model name found. Please specify a model name with --name.\"\n );\n }\n\n options.modelName = modelName;\n options.name = `${modelName}-container`;\n\n const normalized = normalizeOptions(codegenFs, options, projects);\n const projectConfig = findProjectByName(\n codegenFs.root,\n normalized.modelProject,\n projects\n );\n if (!projectConfig) {\n throw new Error(`Model project '${normalized.modelProject}' not found`);\n }\n\n addKosModelConfiguration({\n codegenFs,\n modelName: normalized.nameDashCase,\n projectName: projectConfig.name,\n projectRoot: projectConfig.root,\n singleton: !!options.singleton,\n container: true,\n // The container's exported registration bean (`export const <ProperCase>`).\n factory: normalized.nameProperCase,\n });\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectConfig.name,\n projects\n );\n const modelLocation = kosConfig?.generator?.defaults?.model?.folder || \"\";\n const internal = !!kosConfig?.generator?.internal;\n options.modelDirectory = options.modelDirectory || modelLocation;\n\n const projectRoot = projectConfig.sourceRoot;\n if (projectRoot) {\n logger.info(\n `Generating container model ${normalized.nameDashCase} in ${projectRoot}`\n );\n\n const modelNameDashCase =\n (normalized as any).modelNameDashCase || normalized.nameDashCase;\n\n const modelFolder = path.join(\n projectRoot,\n options.modelDirectory || \"\",\n modelNameDashCase\n );\n\n if (options.existingModel) {\n addContainerToExistingModelFolder(codegenFs, templateDir, modelFolder, {\n ...normalized,\n internal,\n });\n } else {\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"model\"),\n modelFolder,\n { ...normalized, internal }\n );\n }\n\n const modelIndex = path.join(projectRoot, \"index.ts\");\n const modelPath = normalized.modelDirectory\n ? `${normalized.modelDirectory}/${modelNameDashCase}`\n : modelNameDashCase;\n updateModelIndex(codegenFs, modelIndex, modelPath);\n }\n}\n\n/**\n * Add a container to a model folder that already exists.\n *\n * Renders only the container model file from the template set, then edits the\n * folder's own files: the container's options interface is appended to the\n * types declarations (created when absent), and the container's value and type\n * exports are added to the barrel. Both edits go through the codegen filesystem,\n * so a dry run buffers them like any other write.\n */\nfunction addContainerToExistingModelFolder(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n modelFolder: string,\n substitutions: Record<string, any>\n): void {\n const containerFileName = `${substitutions.nameDashCase}-model.ts`;\n const containerTemplate = path.join(\n templateDir,\n \"model\",\n \"__nameDashCase__-model.ts.template\"\n );\n const rendered = ejs.render(\n fs.readFileSync(containerTemplate, \"utf-8\"),\n substitutions,\n { filename: containerTemplate }\n );\n codegenFs.write(path.join(modelFolder, containerFileName), rendered);\n\n const typesPath = path.join(modelFolder, \"types\", \"index.d.ts\");\n if (codegenFs.read(typesPath) === null) {\n codegenFs.write(typesPath, \"\");\n }\n transformSourceFile(codegenFs, typesPath, (sourceFile) => {\n ensureExportedInterface(\n sourceFile,\n `${substitutions.nameProperCase}Options`\n );\n });\n\n const barrelPath = path.join(modelFolder, \"index.ts\");\n if (codegenFs.read(barrelPath) === null) {\n codegenFs.write(barrelPath, \"\");\n }\n transformSourceFile(codegenFs, barrelPath, (sourceFile) => {\n const moduleSpecifier = `./${containerFileName.replace(/\\.ts$/, \"\")}`;\n ensureNamedExports(sourceFile, moduleSpecifier, [\n substitutions.nameProperCase,\n ]);\n ensureNamedExports(\n sourceFile,\n moduleSpecifier,\n [`${substitutions.nameProperCase}Model`],\n true\n );\n });\n}\n","/**\n * Core generator: KOS Context.\n *\n * Generates a context file set inside an app project and updates the barrel export.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport {\n getCurrentDirectoryName,\n getKosModelConfigProp,\n getProject,\n} from \"../kos-config\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { appendBarrelExport } from \"./barrel-utils\";\n\nexport interface ContextOptions extends KosBaseGeneratorOptions {\n appProject: string;\n appDirectory: string;\n singleton?: boolean;\n internal?: boolean;\n}\n\n/**\n * Generate a KOS context.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory\n * @param options - Generator options (mutated to fill in defaults)\n * @param cwd - Current working directory for project resolution\n * @param projects - Optional pre-computed project map\n */\nexport function generateContext(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ContextOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): void {\n if (!options.appProject) {\n throw new Error(\"No app project specified\");\n }\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n const modelName = options.name || getCurrentDirectoryName(cwd);\n if (!modelName) {\n throw new Error(\n \"No model name found. Please specify a model name with --name.\"\n );\n }\n\n const singletonProp = getKosModelConfigProp({\n codegenFs,\n project: modelProjectName,\n modelName,\n prop: \"singleton\",\n projects,\n });\n options.singleton = !!singletonProp;\n options.name = modelName;\n options.modelProject = modelProjectName;\n\n const normalized = normalizeOptions(codegenFs, options, projects);\n const appProject = findProjectByName(\n codegenFs.root,\n normalized.appProject,\n projects\n );\n if (!appProject) {\n throw new Error(`App project '${normalized.appProject}' not found`);\n }\n\n const projectRoot = appProject.sourceRoot;\n if (projectRoot) {\n const dir =\n appProject.projectType === \"application\" || options.internal\n ? options.appDirectory\n : options.appDirectory ?? \"lib\";\n\n generateFilesFromTemplates(\n codegenFs,\n templateDir,\n path.join(projectRoot, dir, \"contexts\", normalized.nameDashCase),\n normalized\n );\n\n appendBarrelExport(\n codegenFs,\n path.join(projectRoot, dir, \"contexts\", \"index.ts\"),\n `./${normalized.nameDashCase}`\n );\n }\n}\n","/**\n * Core generator: KOS Hook.\n *\n * Generates a hook file set inside an app project and updates the barrel export.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport {\n getCurrentDirectoryName,\n getKosModelConfiguration,\n getKosProjectConfiguration,\n getProject,\n} from \"../kos-config\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { appendBarrelExport } from \"./barrel-utils\";\n\nexport interface HookOptions extends KosBaseGeneratorOptions {\n appProject: string;\n appDirectory: string;\n singleton?: boolean;\n internal?: boolean;\n}\n\n/**\n * Generate a KOS hook.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory\n * @param options - Generator options (mutated to fill in defaults)\n * @param cwd - Current working directory for project resolution\n * @param projects - Optional pre-computed project map\n */\nexport function generateHook(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: HookOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): void {\n if (!options.appProject) {\n throw new Error(\"No app project specified\");\n }\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n const modelName = options.name || getCurrentDirectoryName(cwd);\n if (!modelName) {\n throw new Error(\n \"No model name found. Please specify a model name with --name.\"\n );\n }\n\n const kosModelConfig = getKosModelConfiguration(\n codegenFs,\n modelProjectName,\n modelName,\n projects\n );\n options.singleton = kosModelConfig ? !!kosModelConfig.singleton : false;\n options.name = modelName;\n options.modelProject = modelProjectName;\n\n const normalized = normalizeOptions(codegenFs, options, projects);\n const appProject = findProjectByName(\n codegenFs.root,\n normalized.appProject,\n projects\n );\n if (!appProject) {\n throw new Error(`App project '${normalized.appProject}' not found`);\n }\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n appProject.name,\n projects\n );\n const componentLocation =\n kosConfig?.generator?.defaults?.component?.folder || \"\";\n options.appDirectory = options.appDirectory || componentLocation;\n\n const projectRoot = appProject.sourceRoot;\n if (projectRoot) {\n generateFilesFromTemplates(\n codegenFs,\n templateDir,\n path.join(\n projectRoot,\n options.appDirectory,\n \"hooks\",\n normalized.nameDashCase\n ),\n normalized\n );\n\n appendBarrelExport(\n codegenFs,\n path.join(projectRoot, options.appDirectory, \"hooks\", \"index.ts\"),\n `./${normalized.nameDashCase}`\n );\n }\n}\n","/**\n * Core generator: KOS Model.\n *\n * Generates a model within a model project, optionally with container\n * and companion sub-generators.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { updateJson } from \"../json-utils\";\nimport { getCodegenLogger } from \"../logger\";\nimport { getKosProjectConfiguration, getProject } from \"../kos-config\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { updateModelIndex } from \"./update-model-index\";\nimport {\n generateContainerModel,\n type ContainerModelOptions,\n} from \"./generate-container-model\";\nimport {\n generateCompanionModel,\n type CompanionModelOptions,\n} from \"./generate-companion-model\";\n\nexport interface ModelOptions extends KosBaseGeneratorOptions {\n singleton?: boolean;\n isContainerSingleton?: boolean;\n unitTests?: boolean;\n container?: boolean;\n parentAware?: boolean;\n autoRegister?: boolean;\n /** One-line, human-curated purpose for the model catalog (optional). */\n purpose?: string;\n}\n\nexport interface GenerateModelParams {\n codegenFs: CodegenFileSystem;\n modelTemplateDir: string;\n containerTemplateDir?: string;\n companionTemplateDir?: string;\n options: ModelOptions;\n cwd: string;\n projects?: Map<string, ProjectConfiguration>;\n}\n\n/**\n * Generate a KOS model with optional container and companion.\n */\nexport function generateModel(params: GenerateModelParams): void {\n const {\n codegenFs,\n modelTemplateDir,\n containerTemplateDir,\n companionTemplateDir,\n options,\n cwd,\n projects,\n } = params;\n const logger = getCodegenLogger();\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n options.modelProject = modelProjectName;\n const normalized = normalizeOptions(codegenFs, options, projects);\n const projectConfig = findProjectByName(\n codegenFs.root,\n normalized.modelProject,\n projects\n );\n if (!projectConfig) {\n throw new Error(`Model project '${normalized.modelProject}' not found`);\n }\n\n const projectRoot = projectConfig.sourceRoot;\n if (!projectRoot) return;\n\n const kosConfigPath = path.join(projectConfig.root, \".kos.json\");\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectConfig.name,\n projects\n );\n const modelLocation = kosConfig?.generator?.defaults?.model?.folder || \"\";\n const internal = !!kosConfig?.generator?.internal;\n options.modelDirectory = options.modelDirectory || modelLocation;\n\n logger.info(`Generating model ${normalized.nameDashCase} in ${projectRoot}`);\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(modelTemplateDir, \"model\"),\n path.join(projectRoot, options.modelDirectory, normalized.nameDashCase),\n { ...normalized, internal }\n );\n\n const modelIndex = path.join(projectRoot, \"index.ts\");\n const modelPath = options.modelDirectory\n ? `${options.modelDirectory}/${normalized.nameDashCase}`\n : normalized.nameDashCase;\n updateModelIndex(codegenFs, modelIndex, modelPath);\n\n // The generator names the exported registration bean (`export const <ProperCase>`),\n // so it knows the catalog `factory` exactly — no inference. When a container is\n // also generated, this model is held by it: record that as `managedBy` so a\n // consumer depends on the container and navigates, rather than taking the model\n // by id. `purpose` is the only authored field (optional slot).\n const containerKey = normalized.container\n ? `${normalized.nameDashCase}-container`\n : undefined;\n updateJson(codegenFs, kosConfigPath, (json: any) => {\n const existing = json.models?.[normalized.name] ?? {};\n const managedBy = containerKey\n ? [...new Set([...(existing.managedBy ?? []), containerKey])]\n : existing.managedBy;\n json.models = {\n ...json.models,\n [normalized.name]: {\n ...existing,\n name: normalized.name,\n type: `${normalized.nameDashCase}-model`,\n singleton: !!normalized.singleton,\n factory: normalized.nameProperCase,\n ...(normalized.purpose ? { purpose: normalized.purpose } : {}),\n ...(managedBy?.length ? { managedBy } : {}),\n },\n };\n return json;\n });\n\n if (normalized.container && containerTemplateDir) {\n logger.info(`Generating container for ${normalized.name}`);\n generateContainerModel(\n codegenFs,\n containerTemplateDir,\n {\n ...options,\n name: `${normalized.name}-container`,\n modelName: normalized.name,\n singleton: normalized.isContainerSingleton,\n } as ContainerModelOptions,\n cwd,\n projects\n );\n }\n\n if (\n normalized.companion &&\n normalized.companionModel &&\n normalized.companionModelProject &&\n companionTemplateDir\n ) {\n generateCompanionModel(\n codegenFs,\n companionTemplateDir,\n {\n companionModelName: normalized.name,\n companionModelProject: normalized.modelProject,\n modelName: normalized.companionModel,\n modelProject: normalized.companionModelProject,\n companionPattern: normalized.companionPattern,\n } as CompanionModelOptions,\n projects\n );\n }\n}\n","/** Locate a model's file by its `@kosModel` declaration rather than its filename. */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { decoratorConfigText, readSourceFile } from \"./ts-toolkit\";\n\nconst DECLARATION_MARKER = \"@kosModel\";\n\n/** The single file declaring one of `typeIds`; null when none, throws on ambiguity. */\nexport function findModelDeclarationFile(\n codegenFs: CodegenFileSystem,\n searchRoot: string,\n typeIds: string[]\n): string | null {\n const wanted = new Set(typeIds.filter(Boolean));\n if (wanted.size === 0) return null;\n\n const matches: string[] = [];\n for (const filePath of codegenFs.listFiles(searchRoot)) {\n if (!filePath.endsWith(\".ts\") || filePath.endsWith(\".d.ts\")) continue;\n const content = codegenFs.read(filePath);\n if (!content || !content.includes(DECLARATION_MARKER)) continue;\n\n const declared = readDeclaredModelType(codegenFs, filePath);\n if (declared && wanted.has(declared)) matches.push(filePath);\n }\n\n if (matches.length === 0) return null;\n if (matches.length > 1) {\n throw new Error(\n `Model type '${[...wanted].join(\"' / '\")}' is declared in more than one file:\\n` +\n matches\n .sort()\n .map((c) => ` - ${c}`)\n .join(\"\\n\") +\n `\\nPass modelPath to pick one.`\n );\n }\n return matches[0];\n}\n\n/** The type id a file declares; undefined when absent or stated out of reach. */\nfunction readDeclaredModelType(\n codegenFs: CodegenFileSystem,\n filePath: string\n): string | undefined {\n try {\n return readSourceFile(codegenFs, filePath, (sf) => {\n const cls = sf.getClasses().find((c) => c.getDecorator(\"kosModel\"));\n if (!cls) return undefined;\n\n const config = decoratorConfigText(sf, cls, \"kosModel\");\n const inner = config?.startsWith(\"{\")\n ? modelTypeIdProperty(config)\n : config;\n if (!inner) return undefined;\n\n return resolveToStringLiteral(inner.trim(), sf.getFullText());\n });\n } catch {\n return undefined;\n }\n}\n\n/** The `modelTypeId:` value out of a `@kosModel({ … })` argument's text. */\nfunction modelTypeIdProperty(objectText: string): string | undefined {\n const m = objectText.match(/\\bmodelTypeId\\s*:\\s*([^,}]+)/);\n return m ? m[1] : undefined;\n}\n\n/** A string literal, or a const declared in the same file. */\nfunction resolveToStringLiteral(\n expression: string,\n fileText: string\n): string | undefined {\n const literal = expression.match(/^[\"'`](.*)[\"'`]$/);\n if (literal) return literal[1];\n\n if (!/^[A-Za-z_$][\\w$]*$/.test(expression)) return undefined;\n const declared = fileText.match(\n new RegExp(`\\\\b(?:const|let|var)\\\\s+${expression}\\\\s*(?::[^=]+)?=\\\\s*[\"'\\`]([^\"'\\`]+)[\"'\\`]`)\n );\n return declared ? declared[1] : undefined;\n}\n","/**\n * Shared model-file resolution for capability mutators, in three steps: the\n * conventional `<folder>/<name>/<name>-model.ts`, then a search of the model\n * folder for `<name>-model.ts`, then the file whose `@kosModel` declares the id.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { getKosProjectConfiguration } from \"../../kos-config\";\nimport { normalizeAllValues } from \"../../normalize-values\";\nimport { findModelDeclarationFile } from \"./find-model-declaration\";\n\nexport interface ModelFileQuery {\n modelName: string;\n modelProject: string;\n /** Explicit model file path (relative to root), overriding resolution. */\n modelPath?: string;\n}\n\nexport function resolveModelFilePath(\n codegenFs: CodegenFileSystem,\n query: ModelFileQuery,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string; internal: boolean; sourceRoot?: string } {\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n query.modelProject,\n projects\n );\n const internal = !!kosConfig?.generator?.internal;\n\n const project = findProjectByName(\n codegenFs.root,\n query.modelProject,\n projects\n );\n const sourceRoot = project\n ? project.sourceRoot || path.join(project.root, \"src\")\n : undefined;\n\n if (query.modelPath) {\n return { modelFilePath: query.modelPath, internal, sourceRoot };\n }\n\n if (!project) {\n throw new Error(\n `Project not found: ${query.modelProject}. Ensure a project.json exists.`\n );\n }\n const { modelNameDashCase } = normalizeAllValues({\n modelName: query.modelName,\n });\n const modelLocation = kosConfig?.generator?.defaults?.model?.folder || \"\";\n const modelFilePath = path.join(\n sourceRoot as string,\n modelLocation,\n modelNameDashCase,\n `${modelNameDashCase}-model.ts`\n );\n if (codegenFs.exists(modelFilePath)) {\n return { modelFilePath, internal, sourceRoot };\n }\n\n const searchRoot = path.join(sourceRoot as string, modelLocation);\n const discovered = findModelFileByName(\n codegenFs,\n searchRoot,\n modelNameDashCase\n );\n if (discovered) {\n return { modelFilePath: discovered, internal, sourceRoot };\n }\n\n // `.kos.json` records the registered type id separately from its key; callers pass either.\n const declaredType = kosConfig?.models?.[query.modelName]?.type;\n const byDeclaration = findModelDeclarationFile(codegenFs, searchRoot, [\n query.modelName,\n ...(declaredType ? [declaredType] : []),\n ]);\n if (byDeclaration) {\n return { modelFilePath: byDeclaration, internal, sourceRoot };\n }\n\n return { modelFilePath, internal, sourceRoot };\n}\n\n/**\n * Search a directory tree for `<name>-model.ts`. Returns the single match, null\n * when there is none (callers keep the conventional path so their not-found\n * error names the expected location), and throws on ambiguity — a wrong guess\n * would silently mutate the wrong model.\n */\nfunction findModelFileByName(\n codegenFs: CodegenFileSystem,\n searchRoot: string,\n modelNameDashCase: string\n): string | null {\n const fileName = `${modelNameDashCase}-model.ts`;\n const candidates = codegenFs\n .listFiles(searchRoot)\n .filter((f) => path.basename(f) === fileName)\n .sort();\n if (candidates.length === 0) return null;\n if (candidates.length > 1) {\n throw new Error(\n `Model name '${modelNameDashCase}' is ambiguous — multiple files match ${fileName}:\\n` +\n candidates.map((c) => ` - ${c}`).join(\"\\n\") +\n `\\nPass modelPath to pick one.`\n );\n }\n return candidates[0];\n}\n","/**\n * Resolve a child MODEL NAME to the TS type a mutator writes and the module that\n * type is imported from.\n *\n * A child in the same project is imported relatively — a project that imports\n * itself by package name breaks Nx's module boundaries — and one in another\n * project by that project's package name. Callers pass a model name; working out\n * which of those applies is not their job.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { readJson } from \"../../json-utils\";\nimport { properCase } from \"../../name-utils\";\nimport { resolveModelFilePath } from \"./resolve-model-file\";\n\nexport interface ChildModelQuery {\n /** Model the child is being added to; its file anchors a relative import. */\n modelFilePath: string;\n /** Project owning the model being edited. */\n modelProject: string;\n childModel: string;\n /** Project owning `childModel`. Defaults to `modelProject`. */\n childModelProject?: string;\n}\n\nexport function resolveChildModelType(\n codegenFs: CodegenFileSystem,\n query: ChildModelQuery,\n projects?: Map<string, ProjectConfiguration>\n): { childType: string; childTypeModule?: string } {\n const childProject = query.childModelProject || query.modelProject;\n const childType = `${properCase(query.childModel)}Model`;\n\n if (childProject !== query.modelProject) {\n const project = findProjectByName(codegenFs.root, childProject, projects);\n const pkgJson = project\n ? readJson<{ name?: string }>(\n codegenFs,\n path.join(project.root, \"package.json\")\n )\n : undefined;\n return { childType, childTypeModule: pkgJson?.name };\n }\n\n const { modelFilePath: childFilePath } = resolveModelFilePath(\n codegenFs,\n { modelName: query.childModel, modelProject: childProject },\n projects\n );\n const relative = path\n .relative(path.dirname(query.modelFilePath), childFilePath)\n .replace(/\\.ts$/, \"\");\n return {\n childType,\n childTypeModule: relative.startsWith(\".\") ? relative : `./${relative}`,\n };\n}\n","/**\n * Core generator: KOS ViewModel — a class holding UI-only state beside the KOS\n * data models it reads, which arrive through its constructor. Not registered and\n * not in the model graph, so no `.kos.json` entry, chain edit or hook is written.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { getKosProjectConfiguration, getProject } from \"../kos-config\";\nimport { getCodegenLogger } from \"../logger\";\nimport { camelCase } from \"../name-utils\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { resolveChildModelType } from \"./augment/resolve-child-model\";\nimport { resolveModelFilePath } from \"./augment/resolve-model-file\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { updateModelIndex } from \"./update-model-index\";\n\n/** A KOS data model the ViewModel is built over. */\nexport interface ViewModelSource {\n /** Model name, e.g. `beverage-container`. */\n model: string;\n /** Project owning the model. Defaults to the ViewModel's own project. */\n project?: string;\n}\n\nexport interface ViewModelOptions extends KosBaseGeneratorOptions {\n /** Models passed to the constructor, in declaration order. Empty is valid. */\n models?: ViewModelSource[];\n /** `@kosViewModel` typeId. Defaults to the dash-case name. */\n typeId?: string;\n /** Register the instance with KOS DevTools. */\n devToolsEnabled?: boolean;\n}\n\nexport interface ViewModelResult {\n /** Path of the ViewModel file, whether or not this call wrote it. */\n viewModelFilePath: string;\n /** False when the file already existed, in which case nothing was written. */\n created: boolean;\n}\n\ninterface ResolvedModel {\n /** Constructor parameter name. */\n name: string;\n /** Public model type, e.g. `BeverageContainerModel`. */\n type: string;\n /** Module exporting the type, absent when the owning project has no package name. */\n module?: string;\n}\n\n/** Generate a ViewModel. */\nexport function generateViewModel(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ViewModelOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): ViewModelResult {\n const logger = getCodegenLogger();\n\n if (!options.name) {\n throw new Error(\n \"No ViewModel name found. Please specify a name with --name.\"\n );\n }\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --project.\"\n );\n }\n\n const normalized = normalizeOptions(\n codegenFs,\n { ...options, modelProject: modelProjectName },\n projects\n );\n const projectConfig = findProjectByName(\n codegenFs.root,\n modelProjectName,\n projects\n );\n if (!projectConfig) {\n throw new Error(`Model project '${modelProjectName}' not found`);\n }\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectConfig.name,\n projects\n );\n const modelDirectory =\n options.modelDirectory ||\n kosConfig?.generator?.defaults?.model?.folder ||\n \"\";\n const internal = !!kosConfig?.generator?.internal;\n\n const projectRoot =\n projectConfig.sourceRoot || path.join(projectConfig.root, \"src\");\n const viewModelFolder = path.join(\n projectRoot,\n modelDirectory,\n normalized.nameDashCase\n );\n const viewModelFilePath = path.join(\n viewModelFolder,\n `${normalized.nameDashCase}-view-model.ts`\n );\n\n // The ViewModel is hand-written after generation, so regeneration must not overwrite.\n if (codegenFs.exists(viewModelFilePath)) {\n logger.info(`ViewModel already exists: ${viewModelFilePath}`);\n return { viewModelFilePath, created: false };\n }\n\n const resolved = (options.models || []).map((source) =>\n resolveSourceModel(\n codegenFs,\n source,\n viewModelFilePath,\n modelProjectName,\n projects\n )\n );\n\n logger.info(\n `Generating ViewModel ${normalized.nameDashCase} in ${projectRoot}`\n );\n\n const constructorParams = resolved.map(({ name, type }) => ({ name, type }));\n generateFilesFromTemplates(codegenFs, templateDir, viewModelFolder, {\n ...normalized,\n internal,\n typeId: options.typeId || normalized.nameDashCase,\n devToolsEnabled: !!options.devToolsEnabled,\n constructorParams,\n constructorArgs: constructorParams.map((param) => param.name).join(\", \"),\n modelImports: groupImports(resolved),\n });\n\n updateModelIndex(\n codegenFs,\n path.join(projectRoot, \"index.ts\"),\n modelDirectory\n ? `${modelDirectory}/${normalized.nameDashCase}`\n : normalized.nameDashCase\n );\n\n return { viewModelFilePath, created: true };\n}\n\n/** One model name to its constructor parameter and the module its type comes from. */\nfunction resolveSourceModel(\n codegenFs: CodegenFileSystem,\n source: ViewModelSource,\n viewModelFilePath: string,\n modelProject: string,\n projects?: Map<string, ProjectConfiguration>\n): ResolvedModel {\n const sourceProject = source.project || modelProject;\n\n if (sourceProject === modelProject) {\n const { modelFilePath } = resolveModelFilePath(\n codegenFs,\n { modelName: source.model, modelProject: sourceProject },\n projects\n );\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(\n `Model '${source.model}' not found in project '${sourceProject}' (looked for ${modelFilePath})`\n );\n }\n } else if (!findProjectByName(codegenFs.root, sourceProject, projects)) {\n throw new Error(`Model project '${sourceProject}' not found`);\n }\n\n const { childType, childTypeModule } = resolveChildModelType(\n codegenFs,\n {\n modelFilePath: viewModelFilePath,\n modelProject,\n childModel: source.model,\n childModelProject: sourceProject,\n },\n projects\n );\n\n return {\n name: camelCase(source.model),\n type: childType,\n module: childTypeModule,\n };\n}\n\n/** One type-only import per module, in declaration order. */\nfunction groupImports(\n resolved: ResolvedModel[]\n): { module: string; types: string[] }[] {\n const byModule = new Map<string, string[]>();\n for (const { type, module } of resolved) {\n if (!module) continue;\n const types = byModule.get(module);\n if (!types) {\n byModule.set(module, [type]);\n } else if (!types.includes(type)) {\n types.push(type);\n }\n }\n return [...byModule].map(([module, types]) => ({ module, types }));\n}\n","/**\n * The model's own `services/` module — where a model's data-transfer concerns\n * live: the endpoints it calls, the types derived from them, and standalone\n * service functions for callers outside a model context.\n *\n * Created on demand, at the point a capability actually has something to put in\n * it. Scaffolding it up front only produced a placeholder that had to be\n * replaced before the project could compile.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { transformSourceFile, ensureBarrelExport } from \"./ts-toolkit\";\n\n/** `board-model.ts` → `board`; falls back to the requested model name. */\nexport function modelBaseName(\n modelFilePath: string,\n modelName: string\n): string {\n const base = path.basename(modelFilePath);\n const match = base.match(/^(.*)-model\\.ts$/);\n return match ? match[1] : modelName;\n}\n\n/** Where a model's services module lives, whether or not it exists yet. */\nexport function servicesFilePathFor(\n modelFilePath: string,\n modelBase: string\n): string {\n return path.join(\n path.dirname(modelFilePath),\n \"services\",\n `${modelBase}-services.ts`\n );\n}\n\nfunction header(modelBase: string): string {\n return `/**\n * Service layer for the ${modelBase} model: the endpoints it calls and the\n * types derived from them. Standalone service functions for callers outside a\n * model context belong here too.\n */\n`;\n}\n\n/**\n * Ensure the model's services module and its barrel exist, and return the\n * module's path. Existing files are left alone — callers add to them.\n */\nexport function ensureServicesModule(\n codegenFs: CodegenFileSystem,\n modelFilePath: string,\n modelBase: string\n): string {\n const servicesFilePath = servicesFilePathFor(modelFilePath, modelBase);\n if (!codegenFs.exists(servicesFilePath)) {\n codegenFs.write(servicesFilePath, header(modelBase));\n }\n\n const barrelPath = path.join(path.dirname(servicesFilePath), \"index.ts\");\n if (!codegenFs.exists(barrelPath)) {\n codegenFs.write(barrelPath, \"\");\n }\n transformSourceFile(codegenFs, barrelPath, (sf) => {\n ensureBarrelExport(sf, `./${modelBase}-services`);\n });\n\n return servicesFilePath;\n}\n","/**\n * Option normalization for the add-future-to-model generator.\n *\n * Resolves project configuration, computes name case variants,\n * and determines file paths for model, services, and registration files.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { getKosProjectConfiguration } from \"../../kos-config\";\nimport { normalizeAllValues } from \"../../normalize-values\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { servicesFilePathFor } from \"../augment/model-services\";\nimport type {\n AddFutureToModelOptions,\n NormalizedAddFutureToModelOptions,\n} from \"./types\";\n\nexport function normalizeAddFutureOptions(\n codegenFs: CodegenFileSystem,\n options: AddFutureToModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): NormalizedAddFutureToModelOptions {\n const projectConfiguration = findProjectByName(\n codegenFs.root,\n options.modelProject,\n projects\n );\n\n if (!projectConfiguration) {\n throw new Error(\n `Project not found: ${options.modelProject}. Ensure a project.json exists for this project.`\n );\n }\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n options.modelProject,\n projects\n );\n const internal = !!kosConfig?.generator?.internal;\n\n // Normalize name variations\n const normalizedValues = normalizeAllValues({\n modelName: options.modelName,\n });\n\n const nameDashCase = normalizedValues.modelNameDashCase;\n const nameProperCase = normalizedValues.modelNameProperCase;\n const nameCamelCase = normalizedValues.modelNameCamelCase;\n const namePascalCase = normalizedValues.modelNamePascalCase;\n const nameConstantCase = normalizedValues.modelNameConstantCase;\n const nameLowerCase = normalizedValues.modelNameLowerCase;\n\n const projectRoot = projectConfiguration.root;\n const sourceRoot =\n projectConfiguration.sourceRoot || path.join(projectRoot, \"src\");\n\n // Determine model file path — shared resolution covers co-located containers\n // and shared-dir models, not just the conventional `<folder>/<name>/` layout.\n const { modelFilePath } = resolveModelFilePath(\n codegenFs,\n { modelName: options.modelName, modelProject: options.modelProject },\n projects\n );\n const modelDirectory = path.dirname(modelFilePath);\n\n // The services module is created on demand by the capability that needs it,\n // so this path is where it belongs, not proof that it already exists.\n const servicesFilePath = servicesFilePathFor(modelFilePath, nameDashCase);\n\n // Determine registration file path\n const registrationFilePath = path.join(\n modelDirectory,\n `${nameDashCase}-registration.ts`\n );\n\n return {\n ...options,\n nameDashCase,\n nameProperCase,\n nameCamelCase,\n namePascalCase,\n nameConstantCase,\n nameLowerCase,\n projectRoot,\n sourceRoot,\n modelFilePath,\n servicesFilePath,\n registrationFilePath: codegenFs.exists(registrationFilePath)\n ? registrationFilePath\n : undefined,\n internal,\n };\n}\n","/**\n * Transformer that updates existing models to use the @kosFutureAware\n * decorator pattern with TypeScript interface merging for type safety.\n *\n * AST-based (ts-morph via the augment toolkit): every edit anchors on a real\n * node — class, decorator list, import declaration, type alias — so a model\n * with existing decorated methods round-trips intact. The earlier regex\n * string-splice version doubled the class declaration and unbalanced braces\n * on any non-trivial model (G-111).\n */\nimport type { SourceFile, ClassDeclaration } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { NormalizedAddFutureToModelOptions } from \"./types\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addClassDecorator,\n ensureDeclarationMerge,\n ensureFileEslintDisable,\n} from \"../augment/ts-toolkit\";\n\n// Symbols from the legacy (pre-decorator) future pattern, scrubbed on sight.\nconst LEGACY_IMPORTS = new Set([\n \"setupCompleteFutureSupport\",\n \"setupMinimalFutureSupport\",\n \"FutureAwareContainer\",\n \"FutureHandlerContainer\",\n \"FutureStateAccessor\",\n \"FutureUpdateHandler\",\n]);\nconst LEGACY_IMPLEMENTS = new Set([\n \"FutureUpdateHandler\",\n \"FutureHandlerContainer\",\n \"FutureStateAccessor\",\n]);\n\nexport class ModelFileTransformer {\n constructor(\n private codegenFs: CodegenFileSystem,\n private options: NormalizedAddFutureToModelOptions\n ) {}\n\n private get progressType(): string {\n const { nameProperCase, updateServices } = this.options;\n return updateServices\n ? `${nameProperCase}OperationProgress`\n : \"Record<string, unknown>\";\n }\n\n transform(): void {\n const { modelFilePath } = this.options;\n\n if (!this.codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n transformSourceFile(this.codegenFs, modelFilePath, (sf) => {\n this.removeLegacyImports(sf);\n this.addImports(sf);\n\n const cls = getModelClass(sf, `${this.options.nameProperCase}ModelImpl`);\n this.removeLegacyClassMembers(cls);\n this.addDecorator(cls);\n this.addFutureMethod(cls);\n if (this.options.futureType === \"complete\") {\n this.addOnFutureUpdateMethod(cls);\n }\n\n this.updatePublicType(sf);\n\n // Raw-text insertions LAST — they invalidate node references.\n ensureDeclarationMerge(\n sf,\n `${this.options.nameProperCase}ModelImpl`,\n `${\n this.options.futureType === \"complete\"\n ? \"KosFutureAwareFull\"\n : \"KosFutureAwareMinimal\"\n }<${this.progressType}>`\n );\n ensureFileEslintDisable(\n sf,\n \"@typescript-eslint/no-unsafe-declaration-merging\"\n );\n });\n }\n\n private removeLegacyImports(sf: SourceFile): void {\n for (const decl of sf.getImportDeclarations()) {\n for (const named of decl.getNamedImports()) {\n if (LEGACY_IMPORTS.has(named.getName())) named.remove();\n }\n if (\n decl.getNamedImports().length === 0 &&\n !decl.getDefaultImport() &&\n !decl.getNamespaceImport()\n ) {\n decl.remove();\n }\n }\n }\n\n private addImports(sf: SourceFile): void {\n const { internal, futureType, updateServices, nameProperCase } =\n this.options;\n const isComplete = futureType === \"complete\";\n const sdkSpec = resolveSdkModuleSpecifier(sf);\n\n ensureNamedImport(sf, sdkSpec, [\n { name: \"kosFuture\" },\n { name: \"kosFutureAware\" },\n {\n name: isComplete ? \"KosFutureAwareFull\" : \"KosFutureAwareMinimal\",\n isTypeOnly: true,\n },\n ]);\n\n const typeSpec = internal\n ? \"../../../models/types/future-interfaces\"\n : sdkSpec;\n ensureNamedImport(sf, typeSpec, [\n { name: \"ExternalFutureInterface\", isTypeOnly: true },\n ...(isComplete ? [{ name: \"IFutureModel\", isTypeOnly: true }] : []),\n ]);\n\n if (updateServices) {\n ensureNamedImport(sf, \"./services\", [\n { name: `${nameProperCase}OperationProgress`, isTypeOnly: true },\n ]);\n }\n }\n\n private removeLegacyClassMembers(cls: ClassDeclaration): void {\n for (const ctor of cls.getConstructors()) {\n for (const stmt of ctor.getStatements()) {\n if (\n /setup(Complete|Minimal)FutureSupport\\s*\\(\\s*this\\s*\\)/.test(\n stmt.getText()\n )\n ) {\n stmt.remove();\n }\n }\n }\n\n const futureHandler = cls.getProperty(\"futureHandler\");\n if (\n futureHandler?.getTypeNode()?.getText().includes(\"FutureAwareContainer\")\n ) {\n futureHandler.remove();\n }\n const future = cls.getProperty(\"future\");\n if (future?.getTypeNode()?.getText().includes(\"IFutureModel\")) {\n future.remove();\n }\n\n const impls = cls.getImplements();\n for (let i = impls.length - 1; i >= 0; i--) {\n const base = impls[i].getText().split(\"<\")[0].trim();\n if (LEGACY_IMPLEMENTS.has(base)) cls.removeImplements(i);\n }\n }\n\n private addDecorator(cls: ClassDeclaration): void {\n const argsText =\n this.options.futureType === \"complete\" ? \"\" : `{ mode: \"minimal\" }`;\n addClassDecorator(cls, \"kosFutureAware\", { argsText });\n }\n\n private updatePublicType(sf: SourceFile): void {\n const { nameProperCase } = this.options;\n const alias = sf.getTypeAlias(`${nameProperCase}Model`);\n if (!alias) return;\n const text = alias.getTypeNode()?.getText() ?? \"\";\n if (\n !text.includes(`PublicModelInterface<${nameProperCase}ModelImpl>`) ||\n text.includes(\"ExternalFutureInterface\")\n ) {\n return;\n }\n alias.setType(\n `PublicModelInterface<${nameProperCase}ModelImpl> & ExternalFutureInterface<${this.progressType}>`\n );\n }\n\n private addFutureMethod(cls: ClassDeclaration): void {\n const { nameProperCase } = this.options;\n // A model that already has any @kosFuture method needs no placeholder.\n const hasFutureMethod = cls\n .getMethods()\n .some((m) => m.getDecorator(\"kosFuture\"));\n if (hasFutureMethod || cls.getMethod(\"performLongRunningOperation\")) return;\n\n cls.addMethod({\n name: \"performLongRunningOperation\",\n isAsync: true,\n returnType: \"Promise<void>\",\n decorators: [{ name: \"kosFuture\", arguments: [] }],\n docs: [\n {\n description:\n \"Placeholder method for Future operations\\nReplace this with your actual long-running operation\",\n },\n ],\n statements: [\n \"// TODO: Implement your long-running operation here\",\n \"// This method should use a service that returns a Future for progress tracking\",\n \"\",\n \"this.logger.debug(`Starting long-running operation for ${this.id}`);\",\n \"\",\n \"// Example implementation pattern using services:\",\n `// import { perform${nameProperCase}Operation } from './services';`,\n \"//\",\n `// const future = await perform${nameProperCase}Operation();`,\n \"// return this.futureHandler.setFuture(future);\",\n \"\",\n \"// Placeholder that doesn't actually do anything\",\n \"await new Promise((resolve) => setTimeout(resolve, 1000));\",\n \"\",\n \"this.logger.debug(`Completed long-running operation for ${this.id}`);\",\n ],\n });\n }\n\n private addOnFutureUpdateMethod(cls: ClassDeclaration): void {\n if (cls.getMethod(\"onFutureUpdate\")) return;\n\n cls.addMethod({\n name: \"onFutureUpdate\",\n hasQuestionToken: true,\n returnType: \"void\",\n parameters: [\n { name: \"update\", type: `IFutureModel<${this.progressType}>` },\n ],\n docs: [\n {\n description:\n \"Optional: Custom Future update handling\\nCalled whenever the Future state changes (progress, status, completion, etc.)\",\n },\n ],\n statements: [\n \"// Add custom Future update logic here\",\n \"// Examples:\",\n \"// - Log progress milestones\",\n \"// - Update derived state based on progress\",\n \"// - Handle specific error conditions\",\n \"// - Trigger notifications at certain thresholds\",\n \"\",\n \"this.logger.debug(`Future update for ${this.id}:`, {\",\n \" progress: update.progress,\",\n \" status: update.status,\",\n \" endState: update.endState,\",\n \" clientData: update.clientData,\",\n \"});\",\n ],\n });\n }\n}\n","/**\n * Adds Future-operation scaffolding to the model's services module: a\n * placeholder long-running operation and the progress/result types that go with\n * it, created on demand when the model has no services module yet.\n *\n * Every piece it needs — the SDK import, the logger, the function, the types —\n * is ensured independently, because the module it edits may have been created\n * by any capability (or by hand) and carries no guaranteed shape.\n */\nimport { VariableDeclarationKind, type SourceFile } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { NormalizedAddFutureToModelOptions } from \"./types\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n ensureModuleConst,\n ensureExportedTypeAlias,\n} from \"../augment/ts-toolkit\";\nimport { ensureServicesModule } from \"../augment/model-services\";\n\nconst SDK_MODULE = \"@kosdev-code/kos-ui-sdk\";\n\nexport class ServiceFileTransformer {\n constructor(\n private codegenFs: CodegenFileSystem,\n private options: NormalizedAddFutureToModelOptions\n ) {}\n\n transform(): void {\n const { modelFilePath, nameDashCase } = this.options;\n if (!modelFilePath) return;\n\n const servicesFilePath = ensureServicesModule(\n this.codegenFs,\n modelFilePath,\n nameDashCase\n );\n\n transformSourceFile(this.codegenFs, servicesFilePath, (sf) => {\n ensureNamedImport(sf, SDK_MODULE, [\n { name: \"KosLog\" },\n { name: \"FutureResponse\", isTypeOnly: true },\n ]);\n // The emitted operation logs through `log`; a services module written by\n // another capability has no logger of its own.\n ensureModuleConst(sf, {\n name: \"log\",\n initializer: `KosLog.createLogger({ name: \"${nameDashCase}-service\", group: \"Services\" })`,\n });\n this.addFutureOperation(sf);\n this.addProgressTypes(sf);\n });\n }\n\n private addFutureOperation(sf: SourceFile): void {\n const { nameProperCase, nameLowerCase } = this.options;\n const name = `perform${nameProperCase}Operation`;\n if (sf.getVariableDeclaration(name)) return;\n\n sf.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name,\n initializer: `async (): Promise<FutureResponse> => {\n log.debug(\"starting long-running ${nameLowerCase} operation\");\n throw new Error(\"${name} not yet implemented\");\n}`,\n },\n ],\n docs: [\n {\n description: `@category Service - Future Operation\\nA long-running operation returning a Future for progress tracking. Replace the body with the real service call.`,\n },\n ],\n });\n }\n\n private addProgressTypes(sf: SourceFile): void {\n const { nameProperCase } = this.options;\n ensureExportedTypeAlias(sf, {\n name: `${nameProperCase}OperationProgress`,\n type: `{\n stage: string;\n percentComplete: number;\n currentItem?: string;\n totalItems?: number;\n}`,\n });\n ensureExportedTypeAlias(sf, {\n name: `${nameProperCase}OperationResult`,\n type: `{\n success: boolean;\n message?: string;\n data?: unknown;\n}`,\n });\n }\n}\n","/**\n * Transformer that updates registration files to support Future-enabled models.\n *\n * Adds type casts and documentation for Future capabilities.\n *\n * Ported from kos-nx-plugin to use CodegenFileSystem instead of Nx Tree.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { getCodegenLogger } from \"../../logger\";\nimport type { NormalizedAddFutureToModelOptions } from \"./types\";\n\nexport class RegistrationFileTransformer {\n constructor(\n private codegenFs: CodegenFileSystem,\n private options: NormalizedAddFutureToModelOptions\n ) {}\n\n transform(): void {\n const logger = getCodegenLogger();\n const { registrationFilePath } = this.options;\n\n if (!registrationFilePath || !this.codegenFs.exists(registrationFilePath)) {\n logger.warn(\"Registration file not found, skipping registration updates\");\n return;\n }\n\n const original = this.codegenFs.read(registrationFilePath)!;\n\n let content = original;\n content = this.addTypeCast(content);\n content = this.updateDocumentation(content);\n\n // Only legacy registration patterns produce edits — writing unchanged\n // content makes dry-run predict a modification that never happens.\n if (content === original) {\n logger.info(\n \"Registration file has no legacy future patterns — leaving it untouched\"\n );\n return;\n }\n this.codegenFs.write(registrationFilePath, content);\n }\n\n private addTypeCast(content: string): string {\n const { nameProperCase } = this.options;\n\n // Find the registration factory instantiation and add type cast\n const factoryRegex = new RegExp(`class: ${nameProperCase}ModelImpl,`);\n\n const replacement = `class: ${nameProperCase}ModelImpl as any, // Type cast needed for Future intersection`;\n\n return content.replace(factoryRegex, replacement);\n }\n\n private updateDocumentation(content: string): string {\n const { nameProperCase, futureType } = this.options;\n\n // Add Future support documentation after the main description\n const descriptionRegex = new RegExp(\n `(\\\\* The registration bean includes convenience methods for creating and working with ${nameProperCase}Model instances\\\\.)`\n );\n\n const futureDocumentation = `$1\n *\n * ## Future Support\n * This model includes ${futureType} Future support for tracking long-running operations with:\n * - Progress tracking (0-1) with reactive updates\n * - Status messages during operation\n * - Cancellation support with bi-directional AbortController integration\n * - Reactive integration for UI updates${\n futureType === \"complete\"\n ? \"\\n * - Internal access to Future state for custom logic and computed properties\"\n : \"\"\n }`;\n\n if (content.match(descriptionRegex)) {\n content = content.replace(descriptionRegex, futureDocumentation);\n }\n\n // Add Future usage examples to factory documentation\n const factoryExampleRegex = /(\\*\\s+\\}\\);?\\s*\\*\\s+```)/;\n\n const futureExample = `$1\n *\n * // Example: Accessing Future state (when a Future is active)\n * const isRunning = model.futureIsRunning;\n * const progress = model.futureProgress; // 0-1\n * const status = model.futureStatus; // Current status message\n * \\`\\`\\``;\n\n if (content.match(factoryExampleRegex)) {\n content = content.replace(factoryExampleRegex, futureExample);\n }\n\n // Add Future capabilities to predicate examples\n const predicateExampleRegex =\n /(\\*\\s+model\\.updateAvailability\\(false\\);?\\s*\\*\\s+\\})/;\n\n const predicateFutureExample = `$1\n *\n * // Future capabilities are also available\n * const isRunning = model.futureIsRunning;\n * const progress = model.futureProgress;\n * }`;\n\n if (content.match(predicateExampleRegex)) {\n content = content.replace(predicateExampleRegex, predicateFutureExample);\n }\n\n return content;\n }\n}\n","/**\n * Framework-agnostic core logic for the add-future-to-model generator.\n *\n * Adds Future (long-running operation) support to an existing KOS model\n * by transforming model, service, and registration files. Works through\n * the CodegenFileSystem abstraction so it can run in any environment\n * (CLI, VS Code, Nx).\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { normalizeAddFutureOptions } from \"./normalize-options\";\nimport { ModelFileTransformer } from \"./model-transformer\";\nimport { ServiceFileTransformer } from \"./service-transformer\";\nimport { RegistrationFileTransformer } from \"./registration-transformer\";\nimport type { AddFutureToModelOptions } from \"./types\";\n\nexport function addFutureToModel(\n codegenFs: CodegenFileSystem,\n options: AddFutureToModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n const logger = getCodegenLogger();\n const normalized = normalizeAddFutureOptions(codegenFs, options, projects);\n\n logger.info(\n `Adding ${normalized.futureType} Future support to model: ${normalized.modelName}`\n );\n\n // Validate that model file exists\n if (!codegenFs.exists(normalized.modelFilePath)) {\n throw new Error(`Model file not found: ${normalized.modelFilePath}`);\n }\n\n if (options.dryRun) {\n logger.info(\"DRY RUN - No files will be modified\");\n logger.info(`Would modify model file: ${normalized.modelFilePath}`);\n if (normalized.servicesFilePath) {\n logger.info(\n `Would modify/create services file: ${normalized.servicesFilePath}`\n );\n }\n if (normalized.registrationFilePath) {\n logger.info(\n `Would update registration file (only if legacy patterns are present): ${normalized.registrationFilePath}`\n );\n }\n return;\n }\n\n try {\n // Transform model file\n logger.info(`Transforming model file: ${normalized.modelFilePath}`);\n const modelTransformer = new ModelFileTransformer(codegenFs, normalized);\n modelTransformer.transform();\n\n // Transform or create services file\n if (normalized.updateServices) {\n logger.info(\n `Transforming services file: ${\n normalized.servicesFilePath || \"creating new\"\n }`\n );\n const serviceTransformer = new ServiceFileTransformer(\n codegenFs,\n normalized\n );\n serviceTransformer.transform();\n }\n\n // Transform registration file\n if (normalized.registrationFilePath) {\n logger.info(\n `Transforming registration file: ${normalized.registrationFilePath}`\n );\n const registrationTransformer = new RegistrationFileTransformer(\n codegenFs,\n normalized\n );\n registrationTransformer.transform();\n }\n\n logger.info(\n `Successfully added ${normalized.futureType} Future support to ${normalized.modelName}`\n );\n logger.info(\"\");\n logger.info(\"Next steps:\");\n logger.info(\n \"1. Review the generated @kosFuture method and implement your actual operation\"\n );\n logger.info(\n \"2. Update the service method to return a proper FutureResponse\"\n );\n logger.info(\"3. Define your specific progress and result types\");\n if (normalized.futureType === \"complete\") {\n logger.info(\n \"4. Customize the onFutureUpdate method for your specific needs\"\n );\n }\n } catch (error) {\n logger.error(`Failed to add Future support: ${error}`);\n throw error;\n }\n}\n","/**\n * Capability mutator: add container support to an EXISTING model.\n *\n * Applies the `@kosContainerAware` capability (decorator + declaration-merging\n * interface + imports) to a model in place, so a model can manage a collection of\n * children directly — replacing the older pattern that forced a separate container\n * model plus an extra model-manager layer.\n *\n * AST-based via the shared ts-morph toolkit (no regex); routes all I/O through\n * CodegenFileSystem so dry-run + formatFiles apply unchanged.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { readJson } from \"../../json-utils\";\nimport { recordContainerSupportInKosConfig } from \"../../kos-config\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { properCase } from \"../../name-utils\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { resolveChildModelType } from \"../augment/resolve-child-model\";\nimport {\n addClassDecorator,\n ensureDeclarationMerge,\n ensureFileEslintDisable,\n ensureNamedImport,\n getModelClass,\n resolveSdkModuleSpecifier,\n transformSourceFile,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddContainerSupportOptions {\n modelName: string;\n modelProject: string;\n /** TS type the container holds. Default `IKosDataModel`. */\n childType?: string;\n /** Container property name on the instance. Default `container`. */\n containerProperty?: string;\n /** Optional `containerOptions.sortKey`. */\n sortKey?: string;\n /** Explicit model file path (relative to root), overriding resolution. */\n modelPath?: string;\n /**\n * Module the `childType` is imported from, when it is a model type rather\n * than the SDK default. Without it a caller naming a concrete child type\n * produces a file that references a type it never imports.\n */\n childTypeModule?: string;\n /**\n * Name of the model the container holds. Resolves to `<ProperCase>Model` and\n * to the module that exports it, so the caller does not have to know whether\n * that is a relative path or the child project's package name.\n */\n childModel?: string;\n /** Project owning `childModel`. Defaults to the container model's project. */\n childModelProject?: string;\n}\n\nfunction buildDecoratorArgs(options: AddContainerSupportOptions): string {\n const top: string[] = [];\n if (options.containerProperty) {\n top.push(`containerProperty: ${JSON.stringify(options.containerProperty)}`);\n }\n if (options.sortKey) {\n top.push(\n `containerOptions: { sortKey: ${JSON.stringify(options.sortKey)} }`\n );\n }\n return top.length ? `{ ${top.join(\", \")} }` : \"\";\n}\n\n/**\n * Add `@kosContainerAware` support to an existing model file.\n */\nexport function addContainerSupportToModel(\n codegenFs: CodegenFileSystem,\n options: AddContainerSupportOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const resolvedChild = options.childModel\n ? resolveChildModelType(\n codegenFs,\n {\n modelFilePath,\n modelProject: options.modelProject,\n childModel: options.childModel,\n childModelProject: options.childModelProject,\n },\n projects\n )\n : {\n childType: options.childType,\n childTypeModule: options.childTypeModule,\n };\n const childType = resolvedChild.childType?.trim() || \"IKosDataModel\";\n const childTypeModule = resolvedChild.childTypeModule;\n\n logger.info(\n `Adding container support (<${childType}>) to model: ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [\n { name: \"kosContainerAware\" },\n { name: \"KosContainerAware\", isTypeOnly: true },\n ]);\n // The default child type comes from the SDK; a named one comes from the\n // module the caller resolved it to.\n if (childType === \"IKosDataModel\") {\n ensureNamedImport(sf, sdk, [{ name: \"IKosDataModel\", isTypeOnly: true }]);\n } else if (childTypeModule) {\n ensureNamedImport(sf, childTypeModule, [\n { name: childType, isTypeOnly: true },\n ]);\n }\n\n const cls = getModelClass(sf);\n const className = cls.getName();\n if (!className) throw new Error(\"Model class has no name.\");\n // Capture the class's type parameters so the merged interface matches.\n const typeParams = cls.getTypeParameters().map((tp) => tp.getText());\n\n addClassDecorator(cls, \"kosContainerAware\", {\n typeArgs: [childType],\n argsText: buildDecoratorArgs(options),\n });\n\n ensureDeclarationMerge(\n sf,\n className,\n `KosContainerAware<${childType}>`,\n typeParams\n );\n ensureFileEslintDisable(\n sf,\n \"@typescript-eslint/no-unsafe-declaration-merging\"\n );\n });\n\n // The model now manages children directly — reflect that containment in the\n // catalog (`container: true`, and `managedBy` on a concrete held model).\n recordContainerSupportInKosConfig({\n codegenFs,\n projectName: options.modelProject,\n modelName: options.modelName,\n childType,\n projects,\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: make an EXISTING model aware of its parent.\n *\n * Applies `@kosParentAware()` to the model class and extends the model's options\n * interface with `KosParentAware`, so the parent is available immediately after\n * creation and the parent id is part of the options contract.\n *\n * Both edits belong together: the decorator sets the model's `optionsRequired`\n * flag, so an options type that does not carry the parent id describes a model\n * that cannot be constructed.\n *\n * AST-based via the shared ts-morph toolkit; routes all I/O through\n * CodegenFileSystem so dry-run and formatFiles apply unchanged.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { getCodegenLogger } from \"../../logger\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n addClassDecorator,\n ensureNamedImport,\n getModelClass,\n resolveSdkModuleSpecifier,\n transformSourceFile,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddParentAwareOptions {\n modelName: string;\n modelProject: string;\n /** Options key holding the parent id. Defaults to the SDK's own key. */\n parentId?: string;\n /** Explicit model file path (relative to root), overriding resolution. */\n modelPath?: string;\n}\n\nexport function addParentAwareToModel(\n codegenFs: CodegenFileSystem,\n options: AddParentAwareOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string; optionsFilePath?: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n logger.info(`Adding parent awareness to model: ${options.modelName}`);\n\n let optionsTypeName: string | undefined;\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [{ name: \"kosParentAware\" }]);\n\n const cls = getModelClass(sf);\n addClassDecorator(cls, \"kosParentAware\", {\n argsText: options.parentId\n ? `{ parentId: ${JSON.stringify(options.parentId)} }`\n : \"\",\n });\n\n // The options type is the one the constructor takes; it is what has to\n // carry the parent id.\n const ctor = cls.getConstructors()[0];\n optionsTypeName = ctor\n ?.getParameters()[1]\n ?.getTypeNode()\n ?.getText()\n ?.replace(/<.*$/, \"\");\n });\n\n const optionsFilePath = optionsTypeName\n ? extendOptionsInterface(codegenFs, modelFilePath, optionsTypeName, logger)\n : undefined;\n\n return { modelFilePath, optionsFilePath };\n}\n\n/**\n * Extend the model's options interface with `KosParentAware`, in whichever file\n * declares it — generated models keep it in the folder's `types/index.d.ts`.\n */\nfunction extendOptionsInterface(\n codegenFs: CodegenFileSystem,\n modelFilePath: string,\n optionsTypeName: string,\n logger: ReturnType<typeof getCodegenLogger>\n): string | undefined {\n const typesPath = path.join(\n path.dirname(modelFilePath),\n \"types\",\n \"index.d.ts\"\n );\n const target = codegenFs.exists(typesPath) ? typesPath : modelFilePath;\n\n let extended = false;\n transformSourceFile(codegenFs, target, (sf) => {\n const iface = sf.getInterface(optionsTypeName);\n if (!iface) return;\n\n const already = iface\n .getExtends()\n .some((clause) => clause.getText().includes(\"KosParentAware\"));\n if (already) {\n extended = true;\n return;\n }\n\n ensureNamedImport(sf, \"@kosdev-code/kos-ui-sdk\", [\n { name: \"KosParentAware\", isTypeOnly: true },\n ]);\n iface.addExtends(\"KosParentAware\");\n extended = true;\n });\n\n if (!extended) {\n logger.warn(\n `Could not find interface ${optionsTypeName}; add \"extends KosParentAware\" to it by hand.`\n );\n return undefined;\n }\n return target;\n}\n","/**\n * Read-only structural report of a KOS model. AST-based (ts-morph): surfaces the\n * model's type id, the @kos* decorators it carries, the capabilities already wired\n * (child collections, dependencies, topic handlers, config properties, service\n * requests, effects, futures), and whether it is itself a companion. Lets an agent\n * see what a model already has before deciding which mutator to apply — the\n * discovery counterpart to validate_model.\n */\nimport { Project, type ClassDeclaration } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { decoratorConfigText } from \"../augment/ts-toolkit\";\n\nexport interface DescribeModelOptions {\n modelName: string;\n modelProject: string;\n modelPath?: string;\n}\n\n/** A decorated member (method or property) and the bare argument text of its decorator. */\nexport interface DescribedMember {\n name: string;\n /** First decorator argument as written, trimmed (e.g. the topic or config path). */\n arg?: string;\n /** Property/return type as written, when present. */\n type?: string;\n}\n\nexport interface ModelDescription {\n modelFilePath: string;\n /** Value of the MODEL_TYPE constant, if declared. */\n modelType?: string;\n /** The impl class name (e.g. BoardModelImpl). */\n className?: string;\n /** Class-level @kos* decorators in source order (e.g. kosModel, kosLoggerAware). */\n classDecorators: string[];\n singleton: boolean;\n /** True when the class carries @kosCompanion — it augments a parent model. */\n isCompanion: boolean;\n /** @kosChild collection/child properties. */\n children: DescribedMember[];\n /** @kosDependency cross-model references. */\n dependencies: DescribedMember[];\n /** @kosTopicHandler subscription methods. */\n topicHandlers: DescribedMember[];\n /** @kosConfigProperty reactive config-bound properties. */\n configProperties: DescribedMember[];\n /** @kosServiceRequest backend-call methods. */\n serviceRequests: DescribedMember[];\n /** @kosModelEffect reaction methods. */\n effects: DescribedMember[];\n /** @kosFuture long-running-operation methods. */\n futures: DescribedMember[];\n}\n\n/** First decorator argument as written, whitespace-collapsed to one line, if any. */\nfunction firstDecoratorArg(decoratorText: string): string | undefined {\n const open = decoratorText.indexOf(\"(\");\n if (open === -1) return undefined;\n const inner = decoratorText\n .slice(open + 1, decoratorText.lastIndexOf(\")\"))\n .replace(/\\s+/g, \" \")\n .trim();\n return inner || undefined;\n}\n\nfunction collectDecorated(\n cls: ClassDeclaration,\n decoratorName: string\n): DescribedMember[] {\n const members: DescribedMember[] = [];\n const visit = (\n name: string,\n decoratorTextOf: () => string | undefined,\n typeText?: string\n ) => {\n const text = decoratorTextOf();\n if (text === undefined) return;\n members.push({\n name,\n arg: firstDecoratorArg(text),\n type: typeText || undefined,\n });\n };\n for (const m of cls.getMethods()) {\n const dec = m.getDecorator(decoratorName);\n if (dec) {\n visit(m.getName(), () => dec.getText(), m.getReturnTypeNode()?.getText());\n }\n }\n for (const p of cls.getProperties()) {\n const dec = p.getDecorator(decoratorName);\n if (dec) {\n visit(p.getName(), () => dec.getText(), p.getTypeNode()?.getText());\n }\n }\n return members;\n}\n\nexport function describeModel(\n codegenFs: CodegenFileSystem,\n options: DescribeModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): ModelDescription {\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n const content = codegenFs.read(modelFilePath);\n if (content === null) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const project = new Project({ useInMemoryFileSystem: true });\n const sf = project.createSourceFile(modelFilePath, content, {\n overwrite: true,\n });\n\n // MODEL_TYPE = \"...\" (the runtime model-type id).\n let modelType: string | undefined;\n const modelTypeDecl = sf.getVariableDeclaration(\"MODEL_TYPE\");\n if (modelTypeDecl) {\n const init = modelTypeDecl.getInitializer()?.getText();\n if (init) modelType = init.replace(/^[\"'`]|[\"'`]$/g, \"\");\n }\n\n // The model impl class is the one carrying @kosModel.\n const cls =\n sf.getClasses().find((c) => c.getDecorator(\"kosModel\")) ??\n sf.getClasses().find((c) => c.isExported()) ??\n sf.getClasses()[0];\n\n if (!cls) {\n return {\n modelFilePath,\n modelType,\n classDecorators: [],\n singleton: false,\n isCompanion: false,\n children: [],\n dependencies: [],\n topicHandlers: [],\n configProperties: [],\n serviceRequests: [],\n effects: [],\n futures: [],\n };\n }\n\n const classDecorators = cls.getDecorators().map((d) => d.getName());\n const kosModelArg = decoratorConfigText(sf, cls, \"kosModel\");\n const singleton = /\\bsingleton\\s*:\\s*true\\b/.test(kosModelArg ?? \"\");\n\n return {\n modelFilePath,\n modelType,\n className: cls.getName(),\n classDecorators,\n singleton,\n isCompanion: classDecorators.includes(\"kosCompanion\"),\n children: collectDecorated(cls, \"kosChild\"),\n dependencies: collectDecorated(cls, \"kosDependency\"),\n topicHandlers: collectDecorated(cls, \"kosTopicHandler\"),\n configProperties: collectDecorated(cls, \"kosConfigProperty\"),\n serviceRequests: collectDecorated(cls, \"kosServiceRequest\"),\n effects: collectDecorated(cls, \"kosModelEffect\"),\n futures: collectDecorated(cls, \"kosFuture\"),\n };\n}\n","/**\n * Capability mutator: add a `@kosModelEffect` reaction method to an existing model.\n * Generates an idiomatic skeleton (dependencies arrow + async handler) for the\n * developer/agent to fill in. AST-based via the shared toolkit.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedMethod,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddModelEffectOptions {\n modelName: string;\n modelProject: string;\n /** Effect handler method name, e.g. `handleSelectionChange`. */\n methodName: string;\n modelPath?: string;\n}\n\nexport function addModelEffectToModel(\n codegenFs: CodegenFileSystem,\n options: AddModelEffectOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosModelEffect \"${options.methodName}\" to ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [{ name: \"kosModelEffect\" }]);\n const cls = getModelClass(sf);\n const modelType = (cls.getName() ?? \"\").replace(/Impl$/, \"\");\n addDecoratedMethod(cls, {\n name: options.methodName,\n decoratorName: \"kosModelEffect\",\n decoratorArgsText: `{ dependencies: (model: ${modelType}) => [] }`,\n isAsync: true,\n returnType: \"Promise<void>\",\n statements: \"// TODO: react to the tracked dependencies\",\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosDependency` property (cross-model reference) to an\n * existing model. The dependency's TS type and `modelType` ref are caller-supplied.\n *\n * When `dependencyPackage` is given (the SDK that owns the dependency — exactly what\n * `describe_sdk_model` surfaces from the catalog), this also adds the import for the\n * registration bean (the `X` in `X.type`) and the model interface type from that\n * package, so wiring an SDK model is a single call. Without it, importing those\n * symbols stays the caller's responsibility (the mutator can't guess their origin).\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedProperty,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddDependencyOptions {\n modelName: string;\n modelProject: string;\n /** Property name to hold the dependency, e.g. `application`. */\n propertyName: string;\n /** TS type of the dependency, e.g. `ApplicationModel`. */\n dependencyType: string;\n /** Runtime model-type ref, e.g. `Application.type` or a string literal. */\n modelTypeRef: string;\n /** Optional dependency id. */\n id?: string;\n /**\n * The SDK package that owns the dependency (e.g. `@kosdev-code/kos-ui-sdk`). When\n * set, the registration bean and the model interface type are imported from it.\n */\n dependencyPackage?: string;\n modelPath?: string;\n}\n\n// Framework generics that come from the KOS SDK, not the dependency's own package —\n// never import these from `dependencyPackage`.\nconst FRAMEWORK_TYPES = new Set([\"IKosDataModel\", \"IKosIdentifiable\"]);\n\nexport function addDependencyToModel(\n codegenFs: CodegenFileSystem,\n options: AddDependencyOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosDependency \"${options.propertyName}\" to ${options.modelName}`\n );\n\n const argsParts = [`modelType: ${options.modelTypeRef}`];\n if (options.id) argsParts.push(`id: ${JSON.stringify(options.id)}`);\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [{ name: \"kosDependency\" }]);\n\n // Import the dependency's own symbols from the SDK root barrel (NOT a subpath —\n // every model/bean/type is re-exported from the package root).\n if (options.dependencyPackage) {\n const named: { name: string; isTypeOnly?: boolean }[] = [];\n // Registration bean: the `X` in `X.type` (skip string-literal refs).\n const bean = options.modelTypeRef.match(\n /^([A-Za-z_$][\\w$]*)\\.type$/\n )?.[1];\n if (bean) named.push({ name: bean });\n // Model interface type, unless it's a framework generic from the SDK.\n const depType = options.dependencyType?.trim();\n if (\n depType &&\n /^[A-Za-z_$][\\w$]*$/.test(depType) &&\n !FRAMEWORK_TYPES.has(depType)\n ) {\n named.push({ name: depType, isTypeOnly: true });\n }\n if (named.length) ensureNamedImport(sf, options.dependencyPackage, named);\n }\n\n const cls = getModelClass(sf);\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosDependency\",\n decoratorArgsText: `{ ${argsParts.join(\", \")} }`,\n type: options.dependencyType,\n scope: \"private\",\n hasExclamation: true,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosChild` property (owned sub-model enrollment) to an\n * existing model. Enrolls the child(ren) into the parent's model graph, lifecycle\n * cascade, and context scope-chain (a key the parent sets on its context bean resolves\n * down the whole subtree — see kos://guide/model-context). Three shapes:\n * single → `@kosChild private {prop}!: {Child};`\n * container → `@kosChild private {prop} = new KosModelContainer<{Child}>();`\n * array → `@kosChild private {prop}: {Child}[] = [];`\n *\n * When `childPackage` is given (the SDK/package that owns the child model — exactly\n * what `describe_sdk_model` surfaces), the child type is imported from it; without it,\n * importing the child type stays the caller's responsibility (the mutator can't guess\n * its origin). `KosModelContainer` (container shape) always imports from the SDK.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { resolveChildModelType } from \"../augment/resolve-child-model\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedProperty,\n} from \"../augment/ts-toolkit\";\n\nexport type ChildShape = \"single\" | \"container\" | \"array\";\n\nexport interface AddChildOptions {\n modelName: string;\n modelProject: string;\n /** Property name that holds the child(ren), e.g. `pages`, `pump`, `sensors`. */\n propertyName: string;\n /** Child model TS type, e.g. `PageModel`. Derived when `childModel` is given. */\n childType?: string;\n /**\n * Name of the child model. Resolves to `<ProperCase>Model` and to the module\n * that exports it, so the caller does not have to know whether that is a\n * relative path or the child project's package name.\n */\n childModel?: string;\n /** Project owning `childModel`. Defaults to the parent model's project. */\n childModelProject?: string;\n /** How the child(ren) are held. Default `single`. */\n shape?: ChildShape;\n /** Package that owns the child model; when set, its type is imported from the root. */\n childPackage?: string;\n modelPath?: string;\n}\n\n// Framework generics that come from the KOS SDK, not the child's own package — never\n// import these from `childPackage`.\nconst FRAMEWORK_TYPES = new Set([\"IKosDataModel\", \"IKosIdentifiable\"]);\n\nexport function addChildToModel(\n codegenFs: CodegenFileSystem,\n options: AddChildOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const shape: ChildShape = options.shape ?? \"single\";\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosChild \"${options.propertyName}\" (${shape}) to ${options.modelName}`\n );\n\n const resolvedChild = options.childModel\n ? resolveChildModelType(\n codegenFs,\n {\n modelFilePath,\n modelProject: options.modelProject,\n childModel: options.childModel,\n childModelProject: options.childModelProject,\n },\n projects\n )\n : { childType: options.childType, childTypeModule: options.childPackage };\n const childType = resolvedChild.childType?.trim();\n const childTypeModule = resolvedChild.childTypeModule;\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n const sdkImports: { name: string; isTypeOnly?: boolean }[] = [\n { name: \"kosChild\" },\n ];\n // The container shape uses KosModelContainer as a VALUE (`new …`) — import it.\n if (shape === \"container\") sdkImports.push({ name: \"KosModelContainer\" });\n ensureNamedImport(sf, sdk, sdkImports);\n\n // Import the child model type from its owning package when known. In every shape\n // the child type appears only in TYPE position (annotation or generic arg), so a\n // type-only import is correct.\n if (\n childTypeModule &&\n childType &&\n /^[A-Za-z_$][\\w$]*$/.test(childType) &&\n !FRAMEWORK_TYPES.has(childType)\n ) {\n ensureNamedImport(sf, childTypeModule, [\n { name: childType, isTypeOnly: true },\n ]);\n }\n\n const cls = getModelClass(sf);\n if (shape === \"container\") {\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosChild\",\n bare: true,\n initializer: `new KosModelContainer<${childType}>()`,\n scope: \"private\",\n });\n } else if (shape === \"array\") {\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosChild\",\n bare: true,\n type: `${childType}[]`,\n initializer: \"[]\",\n scope: \"private\",\n });\n } else {\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosChild\",\n bare: true,\n type: childType,\n scope: \"private\",\n hasExclamation: true,\n });\n }\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosTopicHandler` subscription method to an existing\n * model. Generates an idiomatic INIT/websocket handler skeleton. The `topic` and\n * event type are caller-supplied (the caller ensures the topic constant is defined).\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedMethod,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddTopicHandlerOptions {\n modelName: string;\n modelProject: string;\n /** Handler method name, e.g. `handleBoardLinked`. */\n handlerName: string;\n /** Topic expression — a constant ref (e.g. `TOPIC_BOARD_LINKED`) or string literal. */\n topic: string;\n /** Event payload TS type for the handler parameter. Default `unknown`. */\n eventType?: string;\n /** Subscribe over websocket. Default true. */\n websocket?: boolean;\n modelPath?: string;\n}\n\nexport function addTopicHandlerToModel(\n codegenFs: CodegenFileSystem,\n options: AddTopicHandlerOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosTopicHandler \"${options.handlerName}\" to ${options.modelName}`\n );\n\n const websocket = options.websocket ?? true;\n const eventType = options.eventType || \"unknown\";\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [\n { name: \"kosTopicHandler\" },\n { name: \"DependencyLifecycle\" },\n ]);\n const cls = getModelClass(sf);\n addDecoratedMethod(cls, {\n name: options.handlerName,\n decoratorName: \"kosTopicHandler\",\n decoratorArgsText: `{ lifecycle: DependencyLifecycle.INIT, topic: ${options.topic}, websocket: ${websocket} }`,\n parameters: [{ name: \"event\", type: eventType }],\n statements: \"// TODO: handle the topic event\",\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosConfigProperty` reactive config-bound property to an\n * existing model. The `path` (config path ref/literal) and `attribute` are caller\n * supplied; the value is exposed as `KosConfigProperty<T>`.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedProperty,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddConfigPropertyOptions {\n modelName: string;\n modelProject: string;\n /** Property name to hold the config value, e.g. `remoteTrayEnabled`. */\n propertyName: string;\n /** Config path expression — a constant ref (e.g. `PROP_CONFIG_PATH`) or string literal. */\n path: string;\n /** Config attribute name, e.g. `enabled` or `settings.volWithoutIceMl`. */\n attribute: string;\n /** Value TS type inside `KosConfigProperty<…>`. Default `unknown`. */\n valueType?: string;\n modelPath?: string;\n}\n\nexport function addConfigPropertyToModel(\n codegenFs: CodegenFileSystem,\n options: AddConfigPropertyOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosConfigProperty \"${options.propertyName}\" to ${options.modelName}`\n );\n\n const valueType = options.valueType || \"unknown\";\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [\n { name: \"kosConfigProperty\" },\n { name: \"KosConfigProperty\", isTypeOnly: true },\n ]);\n const cls = getModelClass(sf);\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosConfigProperty\",\n decoratorArgsText: `{ path: ${options.path}, attribute: ${JSON.stringify(\n options.attribute\n )} }`,\n type: `KosConfigProperty<${valueType}>`,\n hasExclamation: true,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a basic (plain) typed property to an existing model —\n * just a TypeScript field like `prop1: string`. This is local model state, NOT a\n * device-config-bound reactive value (that's `addConfigPropertyToModel`) nor a\n * cross-model reference (`addDependencyToModel`). Use for simple state the model\n * holds and sets itself.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n getModelClass,\n addPlainProperty,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddPropertyOptions {\n modelName: string;\n modelProject: string;\n /** Property name, e.g. `prop1`. */\n propertyName: string;\n /** TS type of the field, e.g. `string`, `number`, `boolean`. Default `string`. */\n type?: string;\n /** Optional initializer expression (e.g. `\"\"`, `0`, `false`). */\n initializer?: string;\n /** Mark the field `readonly`. */\n readonly?: boolean;\n modelPath?: string;\n}\n\n/** Sensible default initializer per primitive so the field compiles under strict mode. */\nfunction defaultInitializer(type: string): string | undefined {\n switch (type) {\n case \"string\":\n return '\"\"';\n case \"number\":\n return \"0\";\n case \"boolean\":\n return \"false\";\n default:\n return undefined; // non-primitive → definite-assignment `!`\n }\n}\n\nexport function addPropertyToModel(\n codegenFs: CodegenFileSystem,\n options: AddPropertyOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const type = options.type || \"string\";\n // Caller initializer wins; else a primitive default; else definite-assignment.\n const initializer =\n options.initializer !== undefined\n ? options.initializer\n : defaultInitializer(type);\n\n logger.info(\n `Adding property \"${options.propertyName}: ${type}\" to ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const cls = getModelClass(sf);\n addPlainProperty(cls, {\n name: options.propertyName,\n type,\n initializer,\n readonly: options.readonly,\n hasExclamation: initializer === undefined,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a COMPUTED member to a model — a read-only getter\n * (`get name(): T { ... }`) that derives its value from other model state. Distinct\n * from a stored field (`addPropertyToModel`): a computed member holds no state, it\n * recomputes on access.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n getModelClass,\n addGetter,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddComputedOptions {\n modelName: string;\n modelProject: string;\n /** Getter name, e.g. `displayName`. */\n name: string;\n /** Return TS type, e.g. `string`. Default inferred (omitted). */\n returnType?: string;\n /** Body statements; default a TODO stub. */\n body?: string;\n modelPath?: string;\n}\n\nexport function addComputedToModel(\n codegenFs: CodegenFileSystem,\n options: AddComputedOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding computed getter \"${options.name}\" to ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const cls = getModelClass(sf);\n addGetter(cls, {\n name: options.name,\n returnType: options.returnType,\n statements: options.body,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * The model's `mocks/` module — KosMock routes standing in for endpoints the\n * generated OpenAPI types do not declare yet.\n *\n * Deliberately OUTSIDE the model's `services/` barrel and outside the project\n * index: nothing imports it, so it cannot reach a production bundle by accident.\n * Arming it is one explicit call from the app, which is also the only place that\n * decision belongs.\n *\n * Its whole purpose is to be deleted. Everything else the provisional form emits\n * — decorator, lifecycle, error-first handler, transform — is real code that\n * survives the endpoint landing; only the wire response is synthetic, and it\n * lives here.\n */\nimport * as path from \"path\";\nimport { VariableDeclarationKind, type SourceFile } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { constantCase, dashCase, pascalCase } from \"../../name-utils\";\nimport { transformSourceFile, ensureNamedImport } from \"./ts-toolkit\";\n\n/** Where a model's mocks module lives, whether or not it exists yet. */\nexport function mocksFilePathFor(\n modelFilePath: string,\n modelBase: string\n): string {\n return path.join(\n path.dirname(modelFilePath),\n \"mocks\",\n `${modelBase}-mocks.ts`\n );\n}\n\n/** The function an app calls to arm this model's provisional routes. */\nexport function mockRegisterFunctionName(modelBase: string): string {\n return `register${pascalCase(modelBase)}Mocks`;\n}\n\n/**\n * KosMock matches `:name` segments; OpenAPI writes `{name}`. Same meaning, one\n * translation — so the route pattern and the endpoint stay recognizably the\n * same string.\n */\nexport function toMockRoutePattern(servicePath: string): string {\n return servicePath.replace(/\\{([^}]+)\\}/g, \":$1\");\n}\n\n/**\n * The KosMock call for a method. `del` because `delete` is a reserved word, and\n * PATCH has no shorthand at all — both facts belong here rather than in the\n * caller.\n */\nfunction mockRouteCall(method: string, pattern: string, body: string): string {\n const shorthand: Record<string, string> = {\n get: \"get\",\n post: \"post\",\n put: \"put\",\n delete: \"del\",\n };\n const fn = shorthand[method];\n return fn\n ? `KosMock.${fn}(${JSON.stringify(pattern)}, ${body});`\n : `KosMock.route(${JSON.stringify(method.toUpperCase())}, ${JSON.stringify(\n pattern\n )}, ${body});`;\n}\n\nfunction header(modelBase: string, registerFn: string): string {\n return `/**\n * KosMock routes for the ${modelBase} model's PROVISIONAL endpoints — the ones\n * this project's generated OpenAPI types do not declare.\n *\n * NOTHING IMPORTS THIS FILE. Call \\`${registerFn}()\\` from the app's dev entry,\n * gated so it cannot run in a production build (\\`import.meta.env.DEV\\`, a\n * dev-only entry module, or behind your own switch). Registering a route enables\n * KosMock, and a mock that shipped would shadow the real endpoint once it exists.\n *\n * Unmatched requests still pass through to the real device (KosMock's hybrid\n * default), so these routes shadow only the paths named below. Every mocked\n * response carries the \\`kos-mocked: true\\` wire header, so mock-fed data is\n * identifiable in devtools.\n *\n * DELETE THIS FILE once every endpoint below is in the generated types.\n */\n`;\n}\n\nexport interface EnsureMockRouteOptions {\n modelFilePath: string;\n /** `board-model.ts` → `board`. */\n modelBase: string;\n /** Specifier the MODEL imports the SDK from, e.g. `@kosdev-code/kos-ui-sdk`. */\n sdkModuleSpecifier: string;\n /** Raw wire type exported by the model's services module. */\n rawAlias: string;\n /** Endpoint the route stands in for. */\n servicePath: string;\n method: string;\n /** Catalog key, used to name the sample payload. */\n endpointKey: string;\n /**\n * Sample payload as TypeScript expression text. Omitted when the caller\n * supplied none, and a placeholder + TODO is emitted instead.\n */\n sampleText?: string;\n}\n\nexport interface EnsureMockRouteResult {\n mocksFilePath: string;\n registerFunction: string;\n routePattern: string;\n sampleName: string;\n /** False when a route for this (method, pattern) was already registered. */\n routeCreated: boolean;\n /** True when no sample was supplied, so the route serves a placeholder. */\n samplePlaceholder: boolean;\n}\n\n/**\n * Ensure the model's mocks module registers a route for one provisional\n * endpoint. Idempotent on (method, pattern): a second call for the same\n * endpoint adds nothing.\n */\nexport function ensureMockRoute(\n codegenFs: CodegenFileSystem,\n options: EnsureMockRouteOptions\n): EnsureMockRouteResult {\n const mocksFilePath = mocksFilePathFor(\n options.modelFilePath,\n options.modelBase\n );\n const registerFunction = mockRegisterFunctionName(options.modelBase);\n const routePattern = toMockRoutePattern(options.servicePath);\n const sampleName = `SAMPLE_${constantCase(dashCase(options.endpointKey))}`;\n const samplePlaceholder = !options.sampleText;\n\n if (!codegenFs.exists(mocksFilePath)) {\n codegenFs.write(mocksFilePath, header(options.modelBase, registerFunction));\n }\n\n // The mocks module sits one directory deeper than the model, so a relative SDK\n // specifier (the in-SDK case) needs one more hop; a package specifier does not.\n const sdkSpecifier = options.sdkModuleSpecifier.startsWith(\".\")\n ? `../${options.sdkModuleSpecifier}`\n : options.sdkModuleSpecifier;\n\n let routeCreated = false;\n\n transformSourceFile(codegenFs, mocksFilePath, (sf) => {\n ensureNamedImport(sf, sdkSpecifier, [{ name: \"KosMock\" }]);\n ensureNamedImport(sf, \"../services\", [\n { name: options.rawAlias, isTypeOnly: true },\n ]);\n\n ensureSample(sf, {\n name: sampleName,\n type: options.rawAlias,\n servicePath: options.servicePath,\n method: options.method,\n sampleText: options.sampleText,\n });\n\n const statement = mockRouteCall(\n options.method,\n routePattern,\n `{ data: ${sampleName} }`\n );\n routeCreated = ensureRegisteredRoute(sf, {\n registerFunction,\n modelBase: options.modelBase,\n statement,\n // Matching on the pattern literal alone would collide across methods.\n marker: `${options.method.toUpperCase()} ${routePattern}`,\n matches: (existing) =>\n existing.includes(JSON.stringify(routePattern)) &&\n existing.includes(shorthandOrMethod(options.method)),\n });\n });\n\n return {\n mocksFilePath,\n registerFunction,\n routePattern,\n sampleName,\n routeCreated,\n samplePlaceholder,\n };\n}\n\n/** The token a route statement carries for its method, for match-on-reuse. */\nfunction shorthandOrMethod(method: string): string {\n const shorthand: Record<string, string> = {\n get: \"KosMock.get(\",\n post: \"KosMock.post(\",\n put: \"KosMock.put(\",\n delete: \"KosMock.del(\",\n };\n return shorthand[method] ?? `\"${method.toUpperCase()}\"`;\n}\n\nfunction ensureSample(\n sf: SourceFile,\n spec: {\n name: string;\n type: string;\n servicePath: string;\n method: string;\n sampleText?: string;\n }\n): void {\n if (sf.getVariableDeclaration(spec.name)) return;\n\n // What the transform receives, not what the socket carries: the client strips\n // the `{status, data}` envelope before the decorator's transform runs, and\n // KosMock's `{ data: … }` puts the envelope back. Saying so here is the\n // difference between a sample that exercises the mapper and one that doesn't.\n const lines = [\n `Sample payload for \\`${spec.method.toUpperCase()} ${\n spec.servicePath\n }\\` — the`,\n \"UNWRAPPED `data` payload, i.e. exactly what the transform receives.\",\n ];\n if (!spec.sampleText) {\n lines.push(\n \"\",\n \"TODO: replace the placeholder with something the backend would actually\",\n \"serve. Until then the route answers with nothing and the transform is\",\n \"never exercised.\"\n );\n }\n const docs = lines.join(\"\\n\");\n\n sf.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n docs: [docs],\n declarations: [\n {\n name: spec.name,\n type: spec.type,\n initializer: spec.sampleText ?? `null as unknown as ${spec.type}`,\n },\n ],\n });\n}\n\n/**\n * Ensure the register function exists and contains this route statement.\n * Returns false when an equivalent route was already registered.\n */\nfunction ensureRegisteredRoute(\n sf: SourceFile,\n spec: {\n registerFunction: string;\n modelBase: string;\n statement: string;\n marker: string;\n matches: (existingStatementText: string) => boolean;\n }\n): boolean {\n let fn = sf.getFunction(spec.registerFunction);\n if (!fn) {\n fn = sf.addFunction({\n name: spec.registerFunction,\n isExported: true,\n returnType: \"void\",\n docs: [\n `Arm the ${spec.modelBase} model's provisional endpoints. Call this from a dev-only entry point — never from code that ships.`,\n ],\n });\n }\n\n const already = fn\n .getStatements()\n .some((statement) => spec.matches(statement.getText()));\n if (already) return false;\n\n fn.addStatements(`// ${spec.marker}\\n${spec.statement}`);\n return true;\n}\n","/**\n * Capability mutator: add a `@kosServiceRequest` method to an existing model.\n *\n * Uses the TYPED decorator generated by `api:generate` (imported from the project's\n * `…/utils/services/<app>/<version>/service.ts`), so `path` is validated against the\n * OpenAPI-derived `openapi.d.ts` at compile time. Purely mechanical: device query,\n * path discovery, and live-spec validation are a separate discovery orchestration.\n *\n * THE PATH IS CHECKED BEFORE ANYTHING IS WRITTEN. Leaving it to the compiler was\n * worse than no check at all: TS2820 answers \"not assignable to keyof paths\" with\n * a nearest-string suggestion, and the nearest string to an endpoint that does not\n * exist is some unrelated feature's endpoint. Following it wires the model to the\n * wrong API and compiles. So a miss fails here, and the alternatives it offers are\n * labelled as other endpoints rather than as corrections.\n *\n * A path the generated types do not declare has exactly two supported answers, and\n * falling back to pre-codegen request patterns is neither of them:\n *\n * generate — the endpoint exists on the device but this project has not pulled\n * types for it. Re-run api:generate; nothing here changes.\n * mock — the endpoint does not exist yet. `mock` emits the PROVISIONAL form:\n * every piece of plumbing real (decorator, lifecycle, error-first handler,\n * transform) and only the wire response synthetic, served by a KosMock route in\n * the model's `mocks/` module. The switch, when the endpoint lands, is deleting\n * the mock and the `as ApiPath` cast.\n *\n * WHERE THE DESCRIPTOR LIVES: the endpoint catalog and the types derived from it\n * belong to the model's own `services/` module, alongside the standalone service\n * functions that serve callers outside a model context. The model file only\n * IMPORTS from there — it declares no paths of its own, so data-transfer concerns\n * stay in one place and one path is described once however many methods use it.\n * The catalog is keyed by handler name but matched by (path, method): a second\n * method on an endpoint already in the catalog reuses that entry.\n *\n * Emits ONE OF TWO SHAPES, because @kosServiceRequest has two, and they are not\n * interchangeable:\n *\n * lifecycle — the framework performs the request during the phase and calls the\n * method back error-first as `(error, data)`. No execution context exists.\n * method — the method performs the request when called, through the `$ctx`\n * the decorator injects as the last parameter.\n *\n * The decorator itself decides by the presence of `lifecycle` (it only wraps the\n * handler to inject `$ctx` when `lifecycle` is absent), so this mutator derives\n * the mode the same way rather than defaulting to one of them.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { pascalCase } from \"../../name-utils\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n ensureServicesModule,\n modelBaseName,\n servicesFilePathFor,\n} from \"../augment/model-services\";\nimport { ensureMockRoute } from \"../augment/model-mocks\";\nimport {\n readServiceModuleOperations,\n type ServiceOperation,\n} from \"../service-catalog\";\nimport {\n transformSourceFile,\n readSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedMethod,\n addClassDecorator,\n ensureDeclarationMerge,\n ensureFileEslintDisable,\n ensureConstCatalogEntry,\n ensureExportedTypeAlias,\n ensureExportedMapper,\n} from \"../augment/ts-toolkit\";\n\nexport type ServiceRequestMode = \"lifecycle\" | \"method\";\n\n/**\n * What to do when the generated types do not declare the requested endpoint.\n *\n * `auto` never silently substitutes mocking for a real request — the result says\n * plainly that it did, and why, so the caller reports a missing endpoint rather\n * than a finished feature.\n */\nexport type ServiceRequestMockMode = \"auto\" | \"always\" | \"never\";\n\nexport interface AddServiceRequestOptions {\n modelName: string;\n modelProject: string;\n /** Handler method name, e.g. `onDataLoaded`. */\n methodName: string;\n /** OpenAPI path string, validated by the generated types, e.g. `/api/board/{id}`. */\n servicePath: string;\n /** HTTP method. Default `get`. */\n method?: string;\n /**\n * Which form to emit. Defaults to `lifecycle` when `lifecycle` is supplied and\n * `method` otherwise — the same rule @kosServiceRequest applies at runtime.\n */\n mode?: ServiceRequestMode;\n /**\n * DependencyLifecycle member name (LOAD, INIT, …). Only meaningful in\n * `lifecycle` mode; defaults to `LOAD` there.\n */\n lifecycle?: string;\n /**\n * What to do about an endpoint the generated types do not declare.\n *\n * `never` — a hard error; nothing is written.\n * `auto` — (default) emit the provisional, mock-backed form and say so.\n * `always` — emit a KosMock route even for an endpoint that IS typed, for\n * developing against something the spec declares but the device does not\n * serve yet. A typed endpoint keeps its typed request; only the mock is added.\n */\n mock?: ServiceRequestMockMode;\n /**\n * The raw wire shape a PROVISIONAL endpoint is expected to serve, as TypeScript\n * type text (`DeviceGrantSyncBean[]`, `{ id: string; label: string }`). This is\n * the UNWRAPPED `data` payload: the client strips the `{status, data}` envelope\n * before the transform runs. Defaults to `unknown`, which compiles but leaves\n * the response boundary undescribed.\n */\n rawType?: string;\n /**\n * Sample payload for the mock route, as TypeScript expression text. Typed\n * against the raw wire shape, so a sample that does not match it fails the\n * build rather than the demo. Without one the route answers with a placeholder\n * and the transform is never exercised.\n */\n sample?: string;\n /** Import specifier for the generated typed service module (relative to the model\n * file). If omitted, auto-resolved when the project has exactly one. */\n serviceModule?: string;\n /**\n * Root-relative path of the service module, as `listServiceCatalog` reports\n * it. Converted to an import specifier here, so a caller that picked an\n * operation from the catalog does not have to compute one — and does not trip\n * the \"multiple service modules\" error when a project types several versions.\n */\n serviceModulePath?: string;\n modelPath?: string;\n}\n\nexport interface AddServiceRequestResult {\n modelFilePath: string;\n /** The model's services module the descriptor was written to. */\n servicesFilePath: string;\n serviceModule: string;\n mode: ServiceRequestMode;\n /** Catalog entry the method points at — reused when the endpoint was known. */\n endpointKey: string;\n /** False when an existing catalog entry for this (path, method) was reused. */\n endpointCreated: boolean;\n /**\n * Whether the path was actually checked. False when the generated module\n * exposes no `paths` this can read — which is not evidence the endpoint exists.\n */\n pathValidated: boolean;\n /** True when the endpoint is absent from the generated types and was mocked. */\n provisional: boolean;\n /** The mock module, when one was written. */\n mocksFilePath?: string;\n /** Function the app must call to arm the routes, when one was written. */\n mockRegisterFunction?: string;\n /** `GET /api/board/grants`, when a route was registered. */\n mockRoute?: string;\n /** True when no sample was supplied, so the mock serves a placeholder. */\n mockSamplePlaceholder?: boolean;\n /** Exactly what to undo when the endpoint lands, in order. */\n removalSteps?: string[];\n}\n\n/**\n * Everything needed to report a rejected path, carried on the error rather than\n * flattened into its message — so a tool surface can present the alternatives\n * with their warning attached instead of as a list of corrections.\n */\nexport interface UntypedEndpointDetails {\n servicePath: string;\n method: string;\n /** True when the path is typed, but not for this method. */\n pathTypedForOtherMethods: boolean;\n /** Methods this path DOES support, when it is typed at all. */\n methodsForPath: string[];\n /** Nearest paths in the same API — alternatives to rule out, not to adopt. */\n otherEndpointsInThisApi: string[];\n warning: string;\n waysForward: string[];\n}\n\n/** A rejected path, with the alternatives kept apart from the verdict. */\nexport interface UntypedEndpointError extends Error {\n details: UntypedEndpointDetails;\n}\n\nconst SERVICE_MODULE_RE = /\\/utils\\/services\\/.*\\/service\\.ts$/;\n\n/** Find generated service modules under the project source root (root-relative paths). */\nfunction findServiceModules(\n codegenFs: CodegenFileSystem,\n sourceRoot: string\n): string[] {\n return codegenFs\n .listFiles(sourceRoot)\n .filter((f) => SERVICE_MODULE_RE.test(f.split(path.sep).join(\"/\")));\n}\n\n/** Build a relative import specifier (posix, no extension) from one file to another. */\nfunction toImportSpecifier(fromFile: string, toFileNoExt: string): string {\n let rel = path\n .relative(path.dirname(fromFile), toFileNoExt)\n .split(path.sep)\n .join(\"/\");\n if (!rel.startsWith(\".\")) rel = `./${rel}`;\n return rel;\n}\n\n/** Resolve a specifier stated relative to one file into a root-relative path. */\nfunction fromImportSpecifier(fromFile: string, specifier: string): string {\n return path.join(path.dirname(fromFile), specifier);\n}\n\n/**\n * The emitted method passes a transformed type to `EndpointCtx` and to\n * `serviceRequest`, which only the current `api:generate` output declares. A\n * module generated before that would accept the code and then fail to compile,\n * so refuse up front rather than write something that cannot build.\n *\n * A module that does not declare `EndpointCtx` at all is left alone — that is a\n * shape this check does not claim to understand.\n */\nfunction assertServiceModuleAcceptsTransform(\n codegenFs: CodegenFileSystem,\n serviceModuleFile: string,\n modelProject: string\n): void {\n const file = `${serviceModuleFile}.ts`;\n if (!codegenFs.exists(file)) return;\n\n const typeParams = readSourceFile(codegenFs, file, (sf) => {\n const alias = sf.getTypeAlias(\"EndpointCtx\");\n return alias ? alias.getTypeParameters().length : null;\n });\n if (typeParams === null || typeParams >= 2) return;\n\n throw new Error(\n `${file} predates the transform-aware service layer (EndpointCtx takes ${typeParams} type parameter). ` +\n `Run \\`kosui api:generate --project ${modelProject} --helpers-only\\` to refresh the helper layer ` +\n `in place (no spec fetch, openapi.d.ts untouched), then add the service request.`\n );\n}\n\nconst MUTATING_METHODS = new Set([\"post\", \"put\", \"delete\", \"patch\"]);\n\n/** A lifecycle request runs on phase, so a mutating verb must not carry one. */\nfunction assertLifecycleSuitsMethod(\n method: string,\n mode: ServiceRequestMode,\n methodName: string\n): void {\n if (mode !== \"lifecycle\" || !MUTATING_METHODS.has(method)) return;\n\n throw new Error(\n `${methodName} is a ${method.toUpperCase()} with a lifecycle, so it would run every time the model ` +\n `reaches that phase rather than when something calls it — a mutation on every load. ` +\n `Drop \\`lifecycle\\` to get the method-driven form (the default for ${method.toUpperCase()}), ` +\n `or pass \\`mode: \"method\"\\`. If the phase really is the trigger, the model calls the method from ` +\n `its own lifecycle hook, where the call is visible.`\n );\n}\n\n/**\n * The provisional form is emitted against `provisionalServiceRequest`, which\n * only the current helper layer declares. Same refusal, same fix as the\n * transform check above — and for the same reason: writing code the project\n * cannot compile is worse than not writing it.\n */\nfunction assertServiceModuleAcceptsProvisional(\n codegenFs: CodegenFileSystem,\n serviceModuleFile: string,\n modelProject: string\n): void {\n const file = `${serviceModuleFile}.ts`;\n if (!codegenFs.exists(file)) return;\n\n const declared = readSourceFile(codegenFs, file, (sf) =>\n Boolean(sf.getFunction(\"provisionalServiceRequest\"))\n );\n if (declared) return;\n\n throw new Error(\n `${file} has no \\`provisionalServiceRequest\\` — the helper layer predates provisional endpoints. ` +\n `Run \\`kosui api:generate --project ${modelProject} --helpers-only\\` to refresh it in place ` +\n `(no spec fetch, openapi.d.ts untouched), then add the service request.`\n );\n}\n\n/**\n * The two `endpoint(...)` initializers describe the same endpoint when their\n * path and method arguments match. Compared as parsed literals rather than as\n * text so quote style and spacing in a hand-edited catalog do not defeat reuse.\n *\n * The optional `as ApiPath` is the provisional marker, and it is deliberately\n * ignored here: an endpoint that has since been typed is still the same\n * endpoint, so dropping the cast must not orphan the entry that used it.\n */\nfunction sameEndpoint(existing: string, candidate: string): boolean {\n const args = (text: string) => {\n const match = text.match(\n /^endpoint\\s*\\(\\s*(['\"])(.*?)\\1(?:\\s+as\\s+ApiPath)?\\s*,\\s*(['\"])(.*?)\\3\\s*,?\\s*\\)$/\n );\n return match ? [match[2], match[4].toLowerCase()] : null;\n };\n const a = args(existing.trim());\n const b = args(candidate.trim());\n return !!a && !!b && a[0] === b[0] && a[1] === b[1];\n}\n\n/** Levenshtein distance, for ranking what else this API offers. */\nfunction editDistance(a: string, b: string): number {\n let previous = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n previous[j] + 1,\n current[j - 1] + 1,\n previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)\n );\n }\n previous = current;\n }\n return previous[b.length];\n}\n\nconst NEAREST_SHOWN = 5;\n\n/**\n * The comment that sits on the provisional catalog entry — the durable flag,\n * next to the cast, in the file a later reader opens to find out what this model\n * calls. Names the removal steps so nobody has to reconstruct them.\n */\nfunction provisionalEntryComment(\n servicePath: string,\n method: string,\n catalogName: string\n): string {\n return `/**\n * PROVISIONAL — \\`${method.toUpperCase()} ${servicePath}\\` is NOT in this project's\n * generated OpenAPI types. \\`as ApiPath\\` is standing in for a \\`paths\\` entry that\n * does not exist, so nothing about this endpoint is checked against a spec and\n * its response cannot be derived from one. Do not read this as a real endpoint.\n *\n * WHEN THE ENDPOINT LANDS:\n * 1. regenerate this project's API types (\\`kosui api:generate\\`)\n * 2. delete \\` as ApiPath\\` from the entry below\n * 3. point the endpoint's \\`…Raw\\` alias at\n * \\`EndpointResponse<typeof ${catalogName}.…>\\`\n * 4. swap \\`provisionalServiceRequest\\` for \\`serviceRequest\\` in the model\n * 5. delete the model's \\`mocks/\\` module\n * 6. KEEP the transform — it is real code and survives all of the above\n */\n`;\n}\n\n/** The flag on the method itself, where the request is read. */\nfunction provisionalMethodDocs(servicePath: string, method: string): string {\n return [\n `PROVISIONAL — \\`${method.toUpperCase()} ${servicePath}\\` is not in the`,\n \"generated OpenAPI types, so this request is served by a KosMock route, not\",\n \"by the device. The feature it backs is NOT complete: report the missing\",\n \"endpoint rather than treating this as finished.\",\n \"\",\n \"See the endpoint's entry in `./services` for what to undo when it lands.\",\n ].join(\"\\n\");\n}\n\n/** Doc for the hand-written wire type a provisional endpoint has to declare. */\nfunction rawTypeDocs(\n servicePath: string,\n method: string,\n rawType?: string\n): string {\n const shape = rawType\n ? [\n \"Stated by hand and unverified: there is no spec entry to check it\",\n \"against.\",\n ]\n : [\n \"TODO: state the shape the backend is expected to serve. `unknown`\",\n \"compiles, but leaves the response boundary undescribed and the\",\n \"transform with nothing to narrow.\",\n ];\n return [\n `Raw wire shape of \\`${method.toUpperCase()} ${servicePath}\\` — the UNWRAPPED`,\n \"`data` payload, since the client strips the `{status, data}` envelope\",\n \"before the transform runs.\",\n \"\",\n ...shape,\n \"\",\n \"Replace with `EndpointResponse<…>` once the endpoint is in the generated\",\n \"types.\",\n ].join(\"\\n\");\n}\n\n/**\n * What has to be undone, in order, once the endpoint exists. Returned rather\n * than only written into comments so the caller can put it in front of whoever\n * asked, at the moment they still remember why the mock is there.\n */\nfunction removalSteps(spec: {\n modelProject: string;\n servicePath: string;\n method: string;\n catalogName: string;\n endpointKey: string;\n servicesFilePath: string;\n mocksFilePath?: string;\n mapperName: string;\n}): string[] {\n return [\n `Regenerate the API types for ${\n spec.modelProject\n } (generate_api_types), and confirm ${spec.method.toUpperCase()} ${\n spec.servicePath\n } is now in them.`,\n `In ${spec.servicesFilePath}: delete \\` as ApiPath\\` from \\`${spec.catalogName}.${spec.endpointKey}\\`.`,\n `In ${spec.servicesFilePath}: point the endpoint's \\`…Raw\\` alias at \\`EndpointResponse<typeof ${spec.catalogName}.${spec.endpointKey}>\\` and drop the hand-written shape.`,\n `In the model: swap \\`provisionalServiceRequest\\` for \\`serviceRequest\\` and drop its explicit type arguments — the response type comes from the spec again.`,\n spec.mocksFilePath\n ? `Delete ${spec.mocksFilePath} (and the call to its register function in the app) once no provisional endpoint is left in it.`\n : `Delete the model's mocks module once no provisional endpoint is left in it.`,\n `KEEP \\`${spec.mapperName}\\` and the data type it produces. The transform is real code; it is what let the model read the final shape all along.`,\n ];\n}\n\n/**\n * Refuse a path the generated types do not declare.\n *\n * The nearest paths are listed because \"which of these did you mean\" is\n * occasionally the answer — but they are labelled as OTHER endpoints, because\n * usually it is not. TypeScript's own TS2820 makes the opposite bet, offering\n * the nearest string as a correction, and an agent that takes it wires the model\n * to an unrelated feature's API and compiles clean.\n */\nfunction untypedEndpointError(spec: {\n servicePath: string;\n method: string;\n modelProject: string;\n operations: ServiceOperation[];\n}): UntypedEndpointError {\n const methodsForPath = spec.operations\n .filter((op) => op.path === spec.servicePath)\n .map((op) => op.method);\n const pathTypedForOtherMethods = methodsForPath.length > 0;\n\n const nearest = [...new Set(spec.operations.map((op) => op.path))]\n .sort(\n (a, b) =>\n editDistance(a, spec.servicePath) - editDistance(b, spec.servicePath)\n )\n .slice(0, NEAREST_SHOWN);\n\n const waysForward = [\n `The endpoint EXISTS on the device but this project has not pulled types for it: re-run api:generate (generate_api_types) for ${spec.modelProject}, then add the request unchanged. Confirm on the device first — kos-device search_services / describe_endpoint — since the live OpenAPI is what says whether it exists.`,\n `The endpoint DOES NOT EXIST yet: pass mock:\"auto\" (the default) or mock:\"always\" to emit the provisional, mock-backed form — real decorator, lifecycle, error-first handler and transform, with a KosMock route standing in for the wire response.`,\n `What is NOT supported: falling back to resolveServiceUrl / ServiceFactory.build / getAll to make the UI render. That compiles and looks finished, which is worse than the hole. A missing endpoint is a blocker to report, not a licence to route around the generated service layer.`,\n ];\n\n const message = pathTypedForOtherMethods\n ? `${spec.method.toUpperCase()} ${\n spec.servicePath\n } is not in the generated OpenAPI types for ${\n spec.modelProject\n } — the path is typed, but only for: ${methodsForPath\n .map((m) => m.toUpperCase())\n .join(\", \")}.`\n : `${spec.method.toUpperCase()} ${\n spec.servicePath\n } is not in the generated OpenAPI types for ${\n spec.modelProject\n } — the path is absent entirely. Nothing was written.`;\n\n const error = new Error(message) as UntypedEndpointError;\n error.details = {\n servicePath: spec.servicePath,\n method: spec.method,\n pathTypedForOtherMethods,\n methodsForPath,\n otherEndpointsInThisApi: nearest,\n warning:\n \"These are OTHER endpoints in this API, listed only so they can be ruled out — they are almost certainly NOT what you want. Do not substitute one for the requested path because the strings look similar.\",\n waysForward,\n };\n return error;\n}\n\nexport function addServiceRequestToModel(\n codegenFs: CodegenFileSystem,\n options: AddServiceRequestOptions,\n projects?: Map<string, ProjectConfiguration>\n): AddServiceRequestResult {\n const logger = getCodegenLogger();\n const { modelFilePath, sourceRoot } = resolveModelFilePath(\n codegenFs,\n options,\n projects\n );\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n // Resolve the generated service module as a ROOT-RELATIVE path first: the\n // model and the services module sit at different depths, so each needs its own\n // specifier and neither can be derived from the other's.\n let serviceModuleFile: string | undefined;\n if (options.serviceModulePath) {\n serviceModuleFile = options.serviceModulePath.replace(/\\.ts$/, \"\");\n } else if (options.serviceModule) {\n serviceModuleFile = fromImportSpecifier(\n modelFilePath,\n options.serviceModule\n );\n } else {\n if (!sourceRoot) {\n throw new Error(\n \"Cannot auto-resolve the service module without a project source root. Pass serviceModule.\"\n );\n }\n const modules = findServiceModules(codegenFs, sourceRoot);\n if (modules.length === 0) {\n throw new Error(\n \"No generated service module found. Run `kosui api:generate` for this project first.\"\n );\n }\n if (modules.length > 1) {\n const specifiers = modules.map((m) =>\n toImportSpecifier(modelFilePath, m.replace(/\\.ts$/, \"\"))\n );\n throw new Error(\n `Multiple service modules found — pass serviceModule (one of): ${specifiers.join(\n \", \"\n )}`\n );\n }\n serviceModuleFile = modules[0].replace(/\\.ts$/, \"\");\n }\n\n assertServiceModuleAcceptsTransform(\n codegenFs,\n serviceModuleFile,\n options.modelProject\n );\n\n const modelBase = modelBaseName(modelFilePath, options.modelName);\n const servicesFilePath = servicesFilePathFor(modelFilePath, modelBase);\n\n const serviceImportFromModel = toImportSpecifier(\n modelFilePath,\n serviceModuleFile\n );\n const serviceImportFromServices = toImportSpecifier(\n servicesFilePath,\n serviceModuleFile\n );\n\n const method = (options.method || \"get\").toLowerCase();\n const mode: ServiceRequestMode =\n options.mode ?? (options.lifecycle ? \"lifecycle\" : \"method\");\n assertLifecycleSuitsMethod(method, mode, options.methodName);\n const lifecycle = options.lifecycle || \"LOAD\";\n const catalogName = `${pascalCase(modelBase)}Endpoints`;\n\n // ---- does the endpoint exist? --------------------------------------------\n // Two independent questions, deliberately not conflated: whether the endpoint\n // is TYPED decides the shape of the request, and whether to MOCK decides\n // whether a route is written. A typed endpoint asked to mock keeps its typed\n // request and merely gains a stand-in response.\n const mockMode: ServiceRequestMockMode = options.mock ?? \"auto\";\n const operations = readServiceModuleOperations(codegenFs, serviceModuleFile);\n const pathValidated = operations !== null;\n const operationTyped =\n operations === null ||\n operations.some(\n (op) => op.path === options.servicePath && op.method === method\n );\n\n if (!operationTyped && mockMode === \"never\") {\n throw untypedEndpointError({\n servicePath: options.servicePath,\n method,\n modelProject: options.modelProject,\n operations: operations ?? [],\n });\n }\n\n const provisional = !operationTyped;\n const writeMock = provisional || mockMode === \"always\";\n\n if (provisional) {\n assertServiceModuleAcceptsProvisional(\n codegenFs,\n serviceModuleFile,\n options.modelProject\n );\n }\n\n logger.info(\n `Adding ${mode}-driven ${\n provisional ? \"PROVISIONAL \" : \"\"\n }@kosServiceRequest \"${options.methodName}\" (${method} ${\n options.servicePath\n }) to ${options.modelName}`\n );\n if (provisional) {\n logger.warn(\n `${method.toUpperCase()} ${options.servicePath} is not in ${\n options.modelProject\n }'s generated OpenAPI types — emitting the ` +\n `provisional, mock-backed form. The feature is NOT complete until the endpoint lands.`\n );\n }\n\n // ---- the model's services module: the endpoint and the types from it ----\n ensureServicesModule(codegenFs, modelFilePath, modelBase);\n\n let endpointKey = options.methodName;\n let endpointCreated = true;\n // Everything the endpoint implies — its normalized shape, the mapper that\n // normalizes it, and the context type carrying that shape — belongs to the\n // ENDPOINT, not to whichever method happens to call it. Normalization is a\n // property of the service response, so a second method on the same endpoint\n // shares all three rather than declaring a parallel set that could drift.\n // These are keyed off the resolved catalog entry, so they are filled in once\n // it is known.\n let dataAlias = \"\";\n let mapperName = \"\";\n let ctxAlias = \"\";\n let rawAlias = \"\";\n\n transformSourceFile(codegenFs, servicesFilePath, (sf) => {\n ensureNamedImport(sf, serviceImportFromServices, [{ name: \"endpoint\" }]);\n if (provisional) {\n ensureNamedImport(sf, serviceImportFromServices, [\n { name: \"ApiPath\", isTypeOnly: true },\n ]);\n }\n\n // The cast is the whole marker: one token, in the one place the path is\n // written, that says the generated types do not back this. Deleting it is\n // the first step of undoing the provisional form, and it is what fails to\n // compile if the path is still absent when someone tries.\n const pathText = provisional\n ? `${JSON.stringify(options.servicePath)} as ApiPath`\n : JSON.stringify(options.servicePath);\n\n const entry = ensureConstCatalogEntry(sf, {\n catalogName,\n key: options.methodName,\n initializer: `endpoint(${pathText}, ${JSON.stringify(method)})`,\n equals: sameEndpoint,\n leadingTrivia: provisional\n ? provisionalEntryComment(options.servicePath, method, catalogName)\n : undefined,\n });\n endpointKey = entry.key;\n endpointCreated = entry.created;\n dataAlias = `${pascalCase(endpointKey)}Data`;\n mapperName = `to${pascalCase(endpointKey)}Data`;\n ctxAlias = `${pascalCase(endpointKey)}Ctx`;\n rawAlias = `${pascalCase(endpointKey)}Raw`;\n\n // Everything below reads the path back through `typeof`, so no type can\n // drift from the descriptor even though each is declared separately — except\n // for a provisional endpoint, where there is no schema entry to read back\n // and the wire shape is stated by hand instead.\n let rawType: string;\n if (provisional) {\n ensureExportedTypeAlias(sf, {\n name: rawAlias,\n type: options.rawType || \"unknown\",\n docs: rawTypeDocs(options.servicePath, method, options.rawType),\n });\n rawType = rawAlias;\n } else {\n rawType = `EndpointResponse<typeof ${catalogName}.${endpointKey}>`;\n ensureNamedImport(sf, serviceImportFromServices, [\n { name: \"EndpointResponse\", isTypeOnly: true },\n ]);\n // A mock has to be typed by what the WIRE carries, never by the mapper's\n // output — the two are the same only until someone narrows the data type,\n // and a sample typed by the narrowed shape would stop matching the\n // endpoint it stands in for. So a typed endpoint being mocked gets the\n // raw shape named too, and the mock imports that.\n if (writeMock) {\n ensureExportedTypeAlias(sf, {\n name: rawAlias,\n type: rawType,\n docs: `Raw wire shape of \\`${method.toUpperCase()} ${\n options.servicePath\n }\\`, as the spec declares it — what a mock for this endpoint must serve.`,\n });\n }\n }\n\n // The mapper is where the response stops being the wire shape and starts\n // being the model's. It is emitted as an identity so the project compiles\n // untouched; narrowing the data type is what turns it into a real boundary,\n // and the compiler then walks the author through filling it in.\n //\n // It is also the one thing that survives the endpoint landing untouched,\n // which is why the model reads its output and never the raw bean.\n ensureExportedTypeAlias(sf, { name: dataAlias, type: rawType });\n ensureExportedMapper(sf, {\n name: mapperName,\n rawType,\n dataType: dataAlias,\n });\n\n if (mode === \"method\") {\n ensureNamedImport(sf, serviceImportFromServices, [\n { name: \"EndpointCtx\", isTypeOnly: true },\n ]);\n ensureExportedTypeAlias(sf, {\n name: ctxAlias,\n type: `EndpointCtx<typeof ${catalogName}.${endpointKey}, ${dataAlias}>`,\n });\n }\n });\n\n // ---- the model: imports and the decorated method, nothing declared ----\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n // EVERY file-level write below (eslint pragma, imports, the merged\n // interface) re-writes the file text, which makes ts-morph forget nodes\n // captured before it. So all of them happen first, and the class is looked\n // up only once nothing else will move underneath it.\n const className = getModelClass(sf).getName();\n if (!className) throw new Error(\"Model class has no name.\");\n const typeParams = getModelClass(sf)\n .getTypeParameters()\n .map((tp) => tp.getText());\n\n // A provisional endpoint has no schema to derive a response from, so the\n // request goes through `provisionalServiceRequest` with the wire shape\n // stated explicitly. The decorator's NAME is the flag at the call site: a\n // later reader (or agent) cannot mistake this method for one backed by the\n // spec, and `grep provisionalServiceRequest` finds every such debt.\n const decoratorName = provisional\n ? \"provisionalServiceRequest\"\n : \"serviceRequest\";\n const decoratorTypeArgs = provisional ? [rawAlias, dataAlias] : undefined;\n ensureNamedImport(sf, serviceImportFromModel, [{ name: decoratorName }]);\n\n if (mode === \"lifecycle\") {\n ensureNamedImport(sf, \"./services\", [\n { name: catalogName },\n { name: mapperName },\n { name: dataAlias, isTypeOnly: true },\n ...(provisional ? [{ name: rawAlias, isTypeOnly: true }] : []),\n ]);\n ensureNamedImport(sf, resolveSdkModuleSpecifier(sf), [\n { name: \"DependencyLifecycle\" },\n ]);\n addDecoratedMethod(getModelClass(sf), {\n name: options.methodName,\n decoratorName,\n decoratorTypeArgs,\n decoratorArgsText: `${catalogName}.${endpointKey}, { lifecycle: DependencyLifecycle.${lifecycle}, transform: ${mapperName} }`,\n docs: provisional\n ? provisionalMethodDocs(options.servicePath, method)\n : undefined,\n // The manager invokes phase handlers error-first, passing (null, data)\n // on success. The `error` half is only ever reached because\n // `serviceRequest` supplies an errorHandler — the bare decorator\n // defaults to `throw`, which fails the phase instead of calling back.\n parameters: [\n { name: \"error\", type: \"string | null\" },\n { name: \"data\", type: dataAlias },\n ],\n returnType: \"void\",\n statements: \"// TODO: apply `data` to the model\",\n });\n return;\n }\n\n ensureNamedImport(sf, \"./services\", [\n { name: catalogName },\n { name: mapperName },\n { name: ctxAlias, isTypeOnly: true },\n ...(provisional\n ? [\n { name: rawAlias, isTypeOnly: true },\n { name: dataAlias, isTypeOnly: true },\n ]\n : []),\n ]);\n ensureNamedImport(sf, resolveSdkModuleSpecifier(sf), [\n { name: \"executeServiceRequest\" },\n { name: \"kosLoggerAware\" },\n { name: \"KosLoggerAware\", isTypeOnly: true },\n ]);\n\n // executeServiceRequest reports failures through the model's logger, so the\n // model has to be logger-aware for the emitted call to compile at all.\n ensureFileEslintDisable(\n sf,\n \"@typescript-eslint/no-unsafe-declaration-merging\"\n );\n ensureDeclarationMerge(sf, className, \"KosLoggerAware\", typeParams);\n addClassDecorator(getModelClass(sf), \"kosLoggerAware\", { argsText: \"\" });\n\n addDecoratedMethod(getModelClass(sf), {\n name: options.methodName,\n decoratorName,\n decoratorTypeArgs,\n decoratorArgsText: `${catalogName}.${endpointKey}, { transform: ${mapperName} }`,\n docs: provisional\n ? provisionalMethodDocs(options.servicePath, method)\n : undefined,\n // Optional: the framework appends the context, callers never pass it.\n parameters: [{ name: \"$ctx\", type: ctxAlias, optional: true }],\n isAsync: true,\n returnType: \"Promise<void>\",\n statements: [\n \"const data = await executeServiceRequest(this, $ctx);\",\n \"if (!data) return;\",\n \"// TODO: apply `data` to the model\",\n ].join(\"\\n\"),\n });\n });\n\n // ---- the mock route, when the wire response has to be stood in for --------\n const mock = writeMock\n ? ensureMockRoute(codegenFs, {\n modelFilePath,\n modelBase,\n sdkModuleSpecifier: readSourceFile(\n codegenFs,\n modelFilePath,\n resolveSdkModuleSpecifier\n ),\n rawAlias,\n servicePath: options.servicePath,\n method,\n endpointKey,\n sampleText: options.sample,\n })\n : undefined;\n\n return {\n modelFilePath,\n servicesFilePath,\n serviceModule: serviceImportFromModel,\n mode,\n endpointKey,\n endpointCreated,\n pathValidated,\n provisional,\n mocksFilePath: mock?.mocksFilePath,\n mockRegisterFunction: mock?.registerFunction,\n mockRoute: mock && `${method.toUpperCase()} ${mock.routePattern}`,\n mockSamplePlaceholder: mock?.samplePlaceholder,\n removalSteps: provisional\n ? removalSteps({\n modelProject: options.modelProject,\n servicePath: options.servicePath,\n method,\n catalogName,\n endpointKey,\n servicesFilePath,\n mocksFilePath: mock?.mocksFilePath,\n mapperName,\n })\n : undefined,\n };\n}\n","/**\n * Resolve an exported SDK symbol to its signature, so an agent (especially a\n * consumer building models) never hallucinates a type's shape. AST-based\n * (ts-morph); confined here in codegen-core, never a runtime SDK dep.\n *\n * Graceful resolution, in priority order:\n * 1. Monorepo SOURCE — the SDK project's `src/index.ts` (source of truth).\n * 2. Installed DECLARATIONS — `node_modules/<pkg>` `exports[\".\"].*.types` /\n * `types` entry (a consumer workspace only has this built `.d.ts`).\n * 3. Neither present → a clear \"not resolvable\" result (no throw).\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { Project, Node, type ExportedDeclarations } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\n\nconst DEFAULT_SDK_PACKAGE = \"@kosdev-code/kos-ui-sdk\";\nconst MAX_SIGNATURE_CHARS = 2000;\n\nexport interface LookupSdkTypeOptions {\n symbol: string;\n /** SDK package name. Default @kosdev-code/kos-ui-sdk. */\n sdkPackage?: string;\n /** Explicit entry file (absolute or workspace-relative), overriding resolution. */\n entryFile?: string;\n}\n\nexport interface SdkSymbolDeclaration {\n kind: string;\n /** Declaring file, workspace-relative when under root. */\n file: string;\n /** Signature text (bodies stripped, length-capped). */\n signature: string;\n}\n\nexport interface SdkTypeLookupResult {\n symbol: string;\n resolved: boolean;\n /** Which surface answered: the SDK source tree or the installed declarations. */\n mode?: \"source\" | \"declarations\";\n entryFile?: string;\n declarations: SdkSymbolDeclaration[];\n /** Set when not resolved (or partially) — explains what was tried. */\n message?: string;\n triedEntries: string[];\n}\n\n/** Read a package's TS-declaration entry from its package.json exports/types. */\nfunction declarationEntryFromPackageJson(pkgDir: string): string | undefined {\n const pkgJsonPath = path.join(pkgDir, \"package.json\");\n if (!fs.existsSync(pkgJsonPath)) return undefined;\n let pkg: any;\n try {\n pkg = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf-8\"));\n } catch {\n return undefined;\n }\n const candidates: Array<string | undefined> = [\n pkg.exports?.[\".\"]?.import?.types,\n pkg.exports?.[\".\"]?.require?.types,\n pkg.exports?.[\".\"]?.types,\n pkg.types,\n pkg.typings,\n ];\n for (const rel of candidates) {\n if (typeof rel === \"string\") {\n const abs = path.join(pkgDir, rel);\n if (fs.existsSync(abs)) return abs;\n }\n }\n return undefined;\n}\n\n/** Build the ordered list of candidate entry files (absolute paths). */\nfunction resolveCandidateEntries(\n codegenFs: CodegenFileSystem,\n options: LookupSdkTypeOptions,\n projects?: Map<string, ProjectConfiguration>\n): Array<{ file: string; mode: \"source\" | \"declarations\" }> {\n const root = codegenFs.root;\n const sdkPackage = options.sdkPackage || DEFAULT_SDK_PACKAGE;\n const out: Array<{ file: string; mode: \"source\" | \"declarations\" }> = [];\n\n if (options.entryFile) {\n const abs = path.isAbsolute(options.entryFile)\n ? options.entryFile\n : path.join(root, options.entryFile);\n out.push({\n file: abs,\n mode: abs.endsWith(\".d.ts\") ? \"declarations\" : \"source\",\n });\n }\n\n // 1. Monorepo source — the SDK project's src/index.ts.\n const sdkProject = findProjectByName(root, sdkPackage, projects);\n const sourceRoot = sdkProject\n ? sdkProject.sourceRoot || path.join(sdkProject.root, \"src\")\n : undefined;\n for (const srcDir of [\n sourceRoot && path.join(root, sourceRoot),\n path.join(root, \"packages\", \"kos-ui-sdk\", \"src\"),\n ]) {\n if (!srcDir) continue;\n const entry = path.join(srcDir, \"index.ts\");\n if (fs.existsSync(entry) && !out.some((c) => c.file === entry)) {\n out.push({ file: entry, mode: \"source\" });\n }\n }\n\n // 2. Installed declarations — node_modules/<pkg> types entry.\n const dts = declarationEntryFromPackageJson(\n path.join(root, \"node_modules\", ...sdkPackage.split(\"/\"))\n );\n if (dts && !out.some((c) => c.file === dts)) {\n out.push({ file: dts, mode: \"declarations\" });\n }\n\n return out;\n}\n\n/**\n * Render an object-like type as a member list via the type checker. KOS model\n * interfaces are utility-wrapped aliases — e.g. `type KosTimeModel =\n * PublicModelInterface<KosTimeModelImpl>` — so the verbatim declaration text is\n * just the unevaluated alias and carries NO members. Resolving the type expands\n * the projection (public members, private/@internal already stripped by\n * `PublicModelInterface<T>`) into the real surface: `timezone`,\n * `updateSystemTimezone(...)`, etc. Returns undefined for non-object types\n * (unions, primitives, generics with unresolved params) so the caller falls back\n * to the literal text, which is clearer for those.\n */\nfunction renderTypeMembers(\n decl: ExportedDeclarations & { getType: () => import(\"ts-morph\").Type }\n): string | undefined {\n const props = decl.getType().getProperties();\n if (props.length === 0) return undefined;\n const lines: string[] = [];\n for (const p of props) {\n const at = p.getDeclarations()[0] ?? decl;\n let pt: string;\n try {\n pt = p.getTypeAtLocation(at).getText(at);\n } catch {\n pt = \"unknown\";\n }\n lines.push(` ${p.getName()}: ${pt};`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Strip method/function bodies and length-cap a declaration's text. */\nfunction signatureText(decl: ExportedDeclarations): string {\n let text: string;\n if (Node.isTypeAliasDeclaration(decl) || Node.isInterfaceDeclaration(decl)) {\n // Resolve to members so utility-wrapped model interfaces yield their real\n // shape in ONE lookup (no jump from the bean to the model alias to the impl).\n const members = renderTypeMembers(decl);\n if (members) {\n const name = decl.getName();\n const tps = decl.getTypeParameters().map((t) => t.getText());\n const head = tps.length ? `${name}<${tps.join(\", \")}>` : name;\n const kw = Node.isInterfaceDeclaration(decl) ? \"interface\" : \"type\";\n const open = Node.isInterfaceDeclaration(decl) ? \" {\" : \" = {\";\n text = `${kw} ${head}${open}\\n${members}\\n}`;\n } else {\n text = decl.getText();\n }\n } else if (Node.isEnumDeclaration(decl)) {\n text = decl.getText();\n } else if (Node.isVariableDeclaration(decl)) {\n // Avoid dumping a large initializer — show the inferred type instead.\n const name = decl.getName();\n const typeText = decl.getType().getText(decl);\n text = `const ${name}: ${typeText}`;\n } else if (Node.isFunctionDeclaration(decl)) {\n if (decl.getBody()) decl.removeBody();\n text = decl.getText();\n } else if (Node.isClassDeclaration(decl)) {\n // Show the PUBLIC surface — drop private/protected members so the useful\n // public API fits the cap, and strip method/constructor bodies.\n const isHidden = (member: { getScope?: () => string }): boolean =>\n typeof member.getScope === \"function\" && member.getScope() !== \"public\";\n for (const p of decl.getProperties()) if (isHidden(p)) p.remove();\n for (const a of [...decl.getGetAccessors(), ...decl.getSetAccessors()]) {\n if (isHidden(a)) a.remove();\n }\n for (const m of decl.getMethods()) {\n if (isHidden(m)) {\n m.remove();\n continue;\n }\n if (m.getBody()) m.removeBody();\n }\n for (const c of decl.getConstructors()) {\n if (c.getBody()) c.removeBody();\n }\n text = decl.getText();\n } else {\n text = decl.getText();\n }\n text = text.replace(/\\s+$/, \"\");\n if (text.length > MAX_SIGNATURE_CHARS) {\n text = text.slice(0, MAX_SIGNATURE_CHARS) + \"\\n/* … truncated */\";\n }\n return text;\n}\n\nexport function lookupSdkType(\n codegenFs: CodegenFileSystem,\n options: LookupSdkTypeOptions,\n projects?: Map<string, ProjectConfiguration>\n): SdkTypeLookupResult {\n const symbol = options.symbol;\n const candidates = resolveCandidateEntries(codegenFs, options, projects);\n const triedEntries = candidates.map((c) =>\n path.relative(codegenFs.root, c.file)\n );\n\n if (candidates.length === 0) {\n return {\n symbol,\n resolved: false,\n declarations: [],\n triedEntries,\n message:\n \"No SDK entry found — neither the SDK source (packages/kos-ui-sdk/src/index.ts) nor an installed declaration file (node_modules/@kosdev-code/kos-ui-sdk) is present. Build or install the SDK, or pass entryFile.\",\n };\n }\n\n const project = new Project({\n skipAddingFilesFromTsConfig: true,\n compilerOptions: { allowJs: false, skipLibCheck: true },\n });\n\n for (const candidate of candidates) {\n let sf;\n try {\n sf = project.addSourceFileAtPath(candidate.file);\n } catch {\n continue;\n }\n let exported: ReadonlyMap<string, ExportedDeclarations[]>;\n try {\n exported = sf.getExportedDeclarations();\n } catch {\n continue;\n }\n const decls = exported.get(symbol);\n if (!decls || decls.length === 0) continue;\n\n return {\n symbol,\n resolved: true,\n mode: candidate.mode,\n entryFile: path.relative(codegenFs.root, candidate.file),\n triedEntries,\n declarations: decls.map((d) => {\n return {\n kind: d.getKindName(),\n file: path.relative(codegenFs.root, d.getSourceFile().getFilePath()),\n signature: signatureText(d),\n };\n }),\n };\n }\n\n return {\n symbol,\n resolved: false,\n declarations: [],\n triedEntries,\n message: `Symbol '${symbol}' is not an export of the SDK entry (${triedEntries.join(\n \", \"\n )}). Check the name, or it may be internal / not part of the public surface.`,\n };\n}\n","/**\n * Read-only static validation of a KOS model against best-practice guardrails.\n * AST-based (ts-morph), high-signal / low-false-positive — a few reliable checks\n * beat many noisy ones. Mirrors the AGENTS.md guardrails + anti-patterns guide.\n */\nimport { Project } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\n\nexport interface ValidateModelOptions {\n modelName: string;\n modelProject: string;\n modelPath?: string;\n}\n\nexport interface ValidationFinding {\n level: \"error\" | \"warning\";\n rule: string;\n message: string;\n}\n\nexport interface ValidationResult {\n modelFilePath: string;\n ok: boolean; // no errors (warnings allowed)\n findings: ValidationFinding[];\n}\n\n/** Extract a `*Model`-named element type from a raw collection type, else null. */\nfunction modelElementType(typeText: string): string | null {\n let m: RegExpMatchArray | null;\n if ((m = typeText.match(/^([A-Za-z_]\\w*Model)\\s*\\[\\]$/))) return m[1];\n if ((m = typeText.match(/^Array<\\s*([A-Za-z_]\\w*Model)\\s*>$/))) return m[1];\n if ((m = typeText.match(/^(?:Map|Set)<[^>]*?\\b([A-Za-z_]\\w*Model)\\b[^>]*>$/)))\n return m[1];\n return null;\n}\n\nexport function validateModel(\n codegenFs: CodegenFileSystem,\n options: ValidateModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): ValidationResult {\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n const content = codegenFs.read(modelFilePath);\n if (content === null) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const project = new Project({ useInMemoryFileSystem: true });\n const sf = project.createSourceFile(modelFilePath, content, {\n overwrite: true,\n });\n const findings: ValidationFinding[] = [];\n\n // 1. Must be a KOS model.\n const hasKosModel = sf.getClasses().some((c) => c.getDecorator(\"kosModel\"));\n if (!hasKosModel) {\n findings.push({\n level: \"error\",\n rule: \"missing-kosModel\",\n message: \"No @kosModel decorator found — this is not a KOS model.\",\n });\n }\n\n const imports = sf.getImportDeclarations();\n\n // 2. No direct MobX — reactivity is internal to KOS.\n const mobxImport = imports.find((d) =>\n /^mobx(-react-lite)?$/.test(d.getModuleSpecifierValue())\n );\n if (mobxImport) {\n findings.push({\n level: \"error\",\n rule: \"mobx-import\",\n message:\n \"Imports mobx directly. Reactivity is internal to KOS — remove the mobx import and use KOS reactivity / container models.\",\n });\n }\n\n // 3. Service requests should use the typed decorator from the api:generate'd\n // service module, not the untyped one from the SDK barrel.\n const barrelServiceRequest = imports.find(\n (d) =>\n d.getModuleSpecifierValue() === \"@kosdev-code/kos-ui-sdk\" &&\n d.getNamedImports().some((n) => n.getName() === \"kosServiceRequest\")\n );\n if (barrelServiceRequest) {\n findings.push({\n level: \"warning\",\n rule: \"untyped-service-request\",\n message:\n \"kosServiceRequest imported from the SDK barrel. Use the typed decorator from the api:generate'd service module so paths are validated against the OpenAPI types.\",\n });\n }\n\n // 4. Model collections should be KOS containers + enrolled as children.\n for (const cls of sf.getClasses()) {\n for (const prop of cls.getProperties()) {\n const name = prop.getName();\n const typeText = (prop.getTypeNode()?.getText() ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n const initText = prop.getInitializer()?.getText() ?? \"\";\n const hasChild = !!prop.getDecorator(\"kosChild\");\n\n const isModelContainer =\n /\\bI?KosModelContainer\\s*</.test(typeText) ||\n /new\\s+KosModelContainer\\b/.test(initText);\n\n if (isModelContainer && !hasChild) {\n findings.push({\n level: \"warning\",\n rule: \"container-missing-kosChild\",\n message: `Property '${name}' is a model container but is not marked @kosChild — add @kosChild so its models join the model graph and lifecycle.`,\n });\n continue;\n }\n\n const elem = modelElementType(typeText);\n if (elem && !isModelContainer) {\n findings.push({\n level: \"warning\",\n rule: \"raw-model-collection\",\n message: `Property '${name}' is a raw ${typeText} of models — prefer a KosModelContainer<${elem}> (indexing, sorting, lifecycle, delta handling) marked @kosChild.`,\n });\n }\n }\n }\n\n const hasError = findings.some((f) => f.level === \"error\");\n return { modelFilePath, ok: !hasError, findings };\n}\n","/**\n * Type definitions for KOS Component Generator\n */\n\n// Plugin type constants\nexport const PLUGIN_TYPES = {\n CUI: \"cui\",\n UTILITY: \"utility\",\n TROUBLE_ACTION: \"troubleAction\",\n SETUP: \"setup\",\n SETTING: \"setting\",\n NAV: \"nav\",\n CONTROL_POUR: \"controlPour\",\n CUSTOM: \"custom\",\n} as const;\n\nexport type PluginType = (typeof PLUGIN_TYPES)[keyof typeof PLUGIN_TYPES];\n\n// Contribution type mapping\nexport const CONTRIBUTION_TYPE_MAP: Record<string, string> = {\n [PLUGIN_TYPES.SETUP]: \"setup\",\n [PLUGIN_TYPES.CUI]: \"cui\",\n [PLUGIN_TYPES.UTILITY]: \"utility\",\n [PLUGIN_TYPES.SETTING]: \"setting\",\n [PLUGIN_TYPES.NAV]: \"nav\",\n [PLUGIN_TYPES.TROUBLE_ACTION]: \"trouble-action\",\n [PLUGIN_TYPES.CONTROL_POUR]: \"control-pour\",\n [PLUGIN_TYPES.CUSTOM]: \"custom\",\n};\n\n// Plugin types that require localization\nexport const LOCALIZED_PLUGIN_TYPES: ReadonlySet<string> = new Set([\n PLUGIN_TYPES.CUI,\n PLUGIN_TYPES.UTILITY,\n PLUGIN_TYPES.SETUP,\n PLUGIN_TYPES.SETTING,\n PLUGIN_TYPES.NAV,\n PLUGIN_TYPES.CONTROL_POUR,\n PLUGIN_TYPES.TROUBLE_ACTION,\n PLUGIN_TYPES.CUSTOM,\n]);\n\n// Configuration interfaces\nexport interface ExperienceConfig {\n id: string;\n component: string;\n location: string;\n}\n\nexport interface PluginContribution {\n id: string;\n title: string;\n namespace: string;\n experienceId?: string;\n [key: string]: any; // Allow plugin-specific properties\n}\n\nexport interface PluginConfiguration {\n contributions: Record<string, PluginContribution[]>;\n experiences: Record<string, ExperienceConfig>;\n views?: Record<string, any[]>;\n}\n\nexport interface NormalizedComponentOptions {\n name: string;\n nameDashCase: string;\n nameCamelCase: string;\n namePascalCase: string;\n nameLowerCase: string;\n appProject: string;\n group?: string;\n pluginType?: string;\n type: string;\n appDirectory: string;\n useEmotionCss?: boolean;\n contributionKey?: string; // User-specified contribution key for custom plugins\n}\n\n// Component generator input options\nexport interface ComponentOptions {\n name: string;\n type: \"components\" | \"features\";\n useEmotionCss: boolean;\n appProject: string;\n appDirectory: string;\n modelDirectory: string;\n group?: string;\n pluginType?: string;\n contributionKey?: string;\n registrationProject?: string;\n skipRegistration?: boolean;\n companion?: boolean;\n companionModel?: string;\n companionModelProject?: string;\n companionPattern?: \"composition\" | \"decorator\";\n}\n\n// JSON path constants for .kos.json structure\nexport const KOS_JSON_PATHS = {\n PLUGIN_ROOT: \"kosdev.ddk.ncui.plugin\",\n CONTRIBUTES: \"kosdev.ddk.ncui.plugin.contributes\",\n EXPERIENCES: \"kosdev.ddk.ncui.plugin.contributes.experiences\",\n VIEWS: \"kosdev.ddk.ncui.plugin.contributes.views\",\n TAB_VIEW: \"ddk.ncui.settings.tabView\",\n} as const;\n","import {\n ExperienceConfig,\n NormalizedComponentOptions,\n PluginConfiguration,\n} from \"../types\";\n\n/**\n * Base interface for plugin-specific handlers\n */\nexport interface PluginHandler {\n /**\n * Creates the plugin-specific configuration\n */\n createConfiguration(options: NormalizedComponentOptions): PluginConfiguration;\n\n /**\n * Returns the contribution key for this plugin type\n */\n getContributionKey(): string;\n\n /**\n * Checks if this plugin type requires localization\n */\n requiresLocalization(): boolean;\n\n /**\n * Gets the template source path for this plugin type\n */\n getTemplatePath(): string;\n}\n\n/**\n * Base implementation with common functionality\n */\nexport abstract class BasePluginHandler implements PluginHandler {\n protected abstract pluginType: string;\n protected abstract contributionKey: string;\n protected abstract requiresI18n: boolean;\n\n abstract createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration;\n\n getContributionKey(): string {\n return this.contributionKey;\n }\n\n requiresLocalization(): boolean {\n return this.requiresI18n;\n }\n\n getTemplatePath(): string {\n return this.contributionKey;\n }\n\n /**\n * Helper to create experience configuration\n */\n protected createExperience(\n options: NormalizedComponentOptions,\n experienceId: string\n ): ExperienceConfig {\n const compPath = this.getComponentPath(options);\n\n return {\n id: experienceId,\n component: options.namePascalCase,\n location: `./src/${compPath}`,\n };\n }\n\n /**\n * Helper to get component path\n */\n protected getComponentPath(options: NormalizedComponentOptions): string {\n return `${options.appDirectory}/${this.contributionKey}/${options.nameDashCase}/${options.nameDashCase}.tsx`;\n }\n\n /**\n * Helper to create config prefix\n */\n protected getConfigPrefix(options: NormalizedComponentOptions): string {\n return `${options.appProject}.${options.nameCamelCase}`;\n }\n}\n","import {\n NormalizedComponentOptions,\n PLUGIN_TYPES,\n PluginConfiguration,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class ControlPourPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.CONTROL_POUR;\n protected contributionKey = \"control-pour\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.controlPour.experience`;\n\n const contribution = {\n id: `${configPrefix}.controlPour`,\n title: `${configPrefix}.controlPour.title`,\n namespace: options.appProject,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n controlPour: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PLUGIN_TYPES,\n PluginConfiguration,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class CuiPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.CUI;\n protected contributionKey = \"cui\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.cui.experience`;\n\n const contribution = {\n id: configPrefix,\n title: `${configPrefix}.cui.title`,\n namespace: options.appProject,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n cui: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PLUGIN_TYPES,\n PluginConfiguration,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class CustomPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.CUSTOM;\n protected contributionKey = \"custom\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.${\n options.contributionKey || \"custom\"\n }.experience`;\n\n // Get the user-specified contribution key or default to 'custom'\n const userContributionKey = options.contributionKey || \"custom\";\n\n const contribution = {\n id: configPrefix,\n title: `${configPrefix}.${userContributionKey}.title`,\n namespace: options.appProject,\n experienceId,\n // TODO: Add additional fields as required by the plugin-explorer specification\n // Refer to the plugin-explorer documentation for your specific contribution type\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n [userContributionKey]: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n\n override getTemplatePath(): string {\n // Use the generic 'custom' template path\n return this.contributionKey || \"custom\";\n }\n\n protected override getComponentPath(\n options: NormalizedComponentOptions\n ): string {\n // Use the user-specified contribution key for the path if available\n const pathKey = options.contributionKey || \"custom\";\n return `${options.appDirectory}/${pathKey}/${options.nameDashCase}/${options.nameDashCase}.tsx`;\n }\n}\n","import { NormalizedComponentOptions, PluginConfiguration } from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\n/**\n * Default handler for non-plugin components\n */\nexport class DefaultComponentHandler extends BasePluginHandler {\n protected pluginType = \"component\";\n protected contributionKey = \"components\";\n protected requiresI18n = false;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const compPath = this.getComponentPath(options);\n\n const viewConfig = {\n id: `${options.appProject}.${options.nameCamelCase}`,\n title: \"ddk.ncui.config.title\",\n namespace: options.appProject,\n component: options.namePascalCase,\n location: `./src/${compPath}`,\n };\n\n return {\n contributions: {},\n experiences: {},\n views: {\n [this.getTabViewKey()]: [viewConfig],\n },\n };\n }\n\n private getTabViewKey(): string {\n return \"ddk.ncui.settings.tabView\";\n }\n\n override getTemplatePath(): string {\n return \"files\"; // Default template path\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class NavPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.NAV;\n protected contributionKey = \"nav\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.nav.experience`;\n\n const contribution = {\n id: `${configPrefix}.nav`,\n title: `${configPrefix}.nav.title`,\n namespace: options.appProject,\n navDescriptor: options.nameLowerCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n navViews: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class SettingPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.SETTING;\n protected contributionKey = \"setting\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.settings.experience`;\n\n const contribution = {\n id: `${configPrefix}.setting`,\n title: `${configPrefix}.setting.title`,\n namespace: options.appProject,\n settingsGroup: options.group || \"general\",\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n settings: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class SetupPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.SETUP;\n protected contributionKey = \"setup\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.setup.experience`;\n\n const contribution = {\n id: `${configPrefix}.setup`,\n title: `${configPrefix}.setup.title`,\n namespace: options.appProject,\n setupDescriptor: options.nameCamelCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n setupStep: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class TroubleActionPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.TROUBLE_ACTION;\n protected contributionKey = \"trouble-action\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.troubleAction.experience`;\n\n const contribution = {\n id: `${configPrefix}.troubleAction`,\n title: `${configPrefix}.troubleAction.title`,\n namespace: options.appProject,\n troubleType: options.nameCamelCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n troubleActions: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class UtilityPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.UTILITY;\n protected contributionKey = \"utility\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.util.experience`;\n\n const contribution = {\n id: `${configPrefix}.util`,\n title: `${configPrefix}.utility.title`,\n namespace: options.appProject,\n utilDescriptor: options.nameCamelCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n utilities: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import { PLUGIN_TYPES } from \"../types\";\nimport { PluginHandler } from \"./base\";\nimport { ControlPourPluginHandler } from \"./control-pour-handler\";\nimport { CuiPluginHandler } from \"./cui-handler\";\nimport { CustomPluginHandler } from \"./custom-handler\";\nimport { DefaultComponentHandler } from \"./default-handler\";\nimport { NavPluginHandler } from \"./nav-handler\";\nimport { SettingPluginHandler } from \"./setting-handler\";\nimport { SetupPluginHandler } from \"./setup-handler\";\nimport { TroubleActionPluginHandler } from \"./trouble-action-handler\";\nimport { UtilityPluginHandler } from \"./utility-handler\";\n\n/**\n * Factory for creating plugin-specific handlers\n */\nexport class PluginHandlerFactory {\n private static handlers: Map<string, new () => PluginHandler> = new Map<\n string,\n new () => PluginHandler\n >([\n [PLUGIN_TYPES.CUI, CuiPluginHandler],\n [PLUGIN_TYPES.UTILITY, UtilityPluginHandler],\n [PLUGIN_TYPES.SETTING, SettingPluginHandler],\n [PLUGIN_TYPES.SETUP, SetupPluginHandler],\n [PLUGIN_TYPES.NAV, NavPluginHandler],\n [PLUGIN_TYPES.CONTROL_POUR, ControlPourPluginHandler],\n [PLUGIN_TYPES.TROUBLE_ACTION, TroubleActionPluginHandler],\n [PLUGIN_TYPES.CUSTOM, CustomPluginHandler],\n ]);\n\n static createHandler(pluginType?: string): PluginHandler {\n if (!pluginType) {\n return new DefaultComponentHandler();\n }\n\n const HandlerClass = this.handlers.get(pluginType);\n\n if (!HandlerClass) {\n console.warn(\n `No handler found for plugin type: ${pluginType}. Using default handler.`\n );\n return new DefaultComponentHandler();\n }\n\n return new HandlerClass();\n }\n\n static isValidPluginType(type: string): boolean {\n return this.handlers.has(type);\n }\n}\n","import * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../../../generate-files\";\nimport { NormalizedComponentOptions } from \"../types\";\n\n/**\n * Generates component files from templates.\n *\n * @param codegenFs - Filesystem abstraction\n * @param templateBaseDir - Absolute path to the base template directory\n * @param templateSubPath - Sub-path from handler (e.g., \"cui\", \"files\")\n * @param targetPath - Destination path relative to workspace root\n * @param options - Normalized component options for template substitution\n */\nexport function generateComponentFiles(\n codegenFs: CodegenFileSystem,\n templateBaseDir: string,\n templateSubPath: string,\n targetPath: string,\n options: NormalizedComponentOptions\n): void {\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateBaseDir, templateSubPath),\n targetPath,\n options\n );\n\n // Handle CSS file deletion if needed\n if (options.useEmotionCss) {\n deleteCssFile(codegenFs, targetPath, options);\n }\n}\n\n/**\n * Deletes the CSS file when using Emotion CSS\n */\nfunction deleteCssFile(\n codegenFs: CodegenFileSystem,\n targetPath: string,\n options: NormalizedComponentOptions\n): void {\n const cssPath = path.join(targetPath, `${options.nameDashCase}.css`);\n\n if (codegenFs.exists(cssPath)) {\n codegenFs.delete(cssPath);\n }\n}\n","import type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport { updateJson } from \"../../../json-utils\";\nimport { PluginConfiguration } from \"../types\";\n\n/**\n * Builder for constructing and updating .kos.json configuration\n */\nexport class KosConfigBuilder {\n private contributions: Record<string, any[]> = {};\n private experiences: Record<string, any> = {};\n private views: Record<string, any[]> = {};\n\n /**\n * Adds plugin configuration to the builder\n */\n addPluginConfiguration(config: PluginConfiguration): this {\n // Merge contributions\n Object.entries(config.contributions).forEach(([key, value]) => {\n this.contributions[key] = [...(this.contributions[key] || []), ...value];\n });\n\n // Merge experiences\n Object.assign(this.experiences, config.experiences);\n\n // Merge views\n if (config.views) {\n Object.entries(config.views).forEach(([key, value]) => {\n this.views[key] = [...(this.views[key] || []), ...value];\n });\n }\n\n return this;\n }\n\n /**\n * Applies the built configuration to the .kos.json file\n */\n applyToFile(codegenFs: CodegenFileSystem, kosConfigPath: string): void {\n updateJson(codegenFs, kosConfigPath, (json: any) => {\n // Initialize the deep structure if it doesn't exist\n const structure = this.initializeStructure(json);\n\n // Merge contributions\n Object.entries(this.contributions).forEach(([key, value]) => {\n structure.contributes[key] = [\n ...(structure.contributes[key] || []),\n ...value,\n ];\n });\n\n // Merge experiences\n structure.contributes.experiences = {\n ...structure.contributes.experiences,\n ...this.experiences,\n };\n\n // Merge views\n if (Object.keys(this.views).length > 0) {\n structure.contributes.views = structure.contributes.views || {};\n\n Object.entries(this.views).forEach(([key, value]) => {\n structure.contributes.views[key] = [\n ...(structure.contributes.views[key] || []),\n ...value,\n ];\n });\n }\n\n return json;\n });\n }\n\n /**\n * Initializes the deep JSON structure\n */\n private initializeStructure(json: any): any {\n json.kos ??= {};\n json.kos.ui ??= {};\n json.kos.ui.plugin ??= {};\n json.kos.ui.plugin.contributes ??= {};\n\n return json.kos.ui.plugin;\n }\n\n /**\n * Creates a new builder instance\n */\n static create(): KosConfigBuilder {\n return new KosConfigBuilder();\n }\n}\n","import * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport { updateJson } from \"../../../json-utils\";\nimport { NormalizedComponentOptions } from \"../types\";\n\n/**\n * Updates localization files for plugin components\n */\nexport function updateLocalization(\n codegenFs: CodegenFileSystem,\n projectRoot: string,\n options: NormalizedComponentOptions,\n pluginType: string\n): void {\n const localePath = path.join(\n projectRoot,\n \"assets\",\n \"locales\",\n \"en\",\n `${options.appProject}.json`\n );\n\n if (!codegenFs.exists(localePath)) {\n console.warn(`Locale file not found: ${localePath}`);\n return;\n }\n\n updateJson(codegenFs, localePath, (json: any) => {\n // Ensure nested structure exists\n json[options.appProject] = json[options.appProject] || {};\n json[options.appProject][options.nameCamelCase] =\n json[options.appProject][options.nameCamelCase] || {};\n\n // Add localization entry\n json[options.appProject][options.nameCamelCase][pluginType] = {\n ...json[options.appProject][options.nameCamelCase][pluginType],\n title: options.nameCamelCase,\n };\n\n return json;\n });\n}\n","import type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../../project-discovery\";\nimport { PluginHandlerFactory } from \"../plugin-handlers/factory\";\nimport type { ComponentOptions } from \"../types\";\n\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Validates generator options\n */\nexport function validateOptions(\n codegenFs: CodegenFileSystem,\n options: ComponentOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n // Validate required fields\n if (!options.name) {\n throw new ValidationError(\"Component name is required\");\n }\n\n if (!options.appProject) {\n throw new ValidationError(\"App project is required\");\n }\n\n // Validate project exists\n const project = findProjectByName(\n codegenFs.root,\n options.appProject,\n projects\n );\n if (!project) {\n throw new ValidationError(\n `Project \"${options.appProject}\" not found in workspace`\n );\n }\n\n // Validate plugin type if provided\n if (\n options.pluginType &&\n !PluginHandlerFactory.isValidPluginType(options.pluginType)\n ) {\n console.warn(\n `Unknown plugin type \"${options.pluginType}\". ` +\n `Component will be generated with default configuration.`\n );\n }\n\n // Validate group is provided for setting type\n if (options.pluginType === \"setting\" && !options.group) {\n throw new ValidationError(\n \"Settings group is required for setting plugin type\"\n );\n }\n}\n\n/**\n * Validates file paths\n */\nexport function validateFilePath(\n codegenFs: CodegenFileSystem,\n filePath: string\n): boolean {\n return codegenFs.exists(filePath);\n}\n\n/**\n * Safe JSON update with error handling\n */\nexport function safeJsonUpdate<T = any>(\n operation: () => T,\n fallback: T,\n errorMessage?: string\n): T {\n try {\n return operation();\n } catch (error) {\n if (errorMessage) {\n console.error(errorMessage, error);\n }\n return fallback;\n }\n}\n","/**\n * Core component generator — framework-agnostic.\n *\n * Replaces the Nx-coupled logic from kos-nx-plugin kos-component generator.\n * Uses CodegenFileSystem instead of @nx/devkit Tree.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { getKosProjectConfiguration } from \"../../kos-config\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { findProjectByName } from \"../../project-discovery\";\nimport { normalizeOptions } from \"../normalize-options\";\nimport { PluginHandlerFactory } from \"./plugin-handlers/factory\";\nimport {\n ComponentOptions,\n CONTRIBUTION_TYPE_MAP,\n NormalizedComponentOptions,\n} from \"./types\";\nimport { generateComponentFiles } from \"./utils/file-generator\";\nimport { KosConfigBuilder } from \"./utils/kos-config-builder\";\nimport { updateLocalization } from \"./utils/localization\";\nimport { validateOptions } from \"./utils/validation\";\n\nexport type { ComponentOptions } from \"./types\";\n\n/**\n * Generate a KOS component using the framework-agnostic CodegenFileSystem.\n *\n * @param codegenFs - Filesystem abstraction (NxTreeAdapter or DirectFileSystem)\n * @param templateDir - Absolute path to the template base directory\n * @param options - Component generator options\n * @param projects - Optional pre-computed project map (avoids rescan)\n */\nexport function generateComponent(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ComponentOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n // Step 1: Validate options\n validateOptions(codegenFs, options, projects);\n\n // Step 2: Normalize options\n const normalized = prepareOptions(codegenFs, options, projects);\n\n // Step 3: Get project configuration\n const projectConfig = findProjectByName(\n codegenFs.root,\n normalized.appProject,\n projects\n );\n\n if (!projectConfig) {\n throw new Error(\n `Project \"${normalized.appProject}\" not found in workspace`\n );\n }\n\n const projectRoot = projectConfig.sourceRoot;\n\n if (!projectRoot) {\n throw new Error(\n `No source root found for project ${normalized.appProject}`\n );\n }\n\n // Step 4: Generate component files\n generateFiles(codegenFs, templateDir, projectRoot, normalized);\n\n // Step 5: Update plugin configuration if needed\n if (options.pluginType) {\n updatePluginConfiguration(codegenFs, projectConfig, normalized);\n }\n}\n\n/**\n * Prepares and normalizes options\n */\nfunction prepareOptions(\n codegenFs: CodegenFileSystem,\n options: ComponentOptions,\n projects?: Map<string, ProjectConfiguration>\n): NormalizedComponentOptions {\n const normalized = normalizeOptions(\n codegenFs,\n {\n ...options,\n modelProject: \"__NONE__\",\n },\n projects\n ) as unknown as NormalizedComponentOptions;\n\n // Get KOS configuration for component location\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n options.appProject,\n projects\n );\n\n const componentLocation =\n (kosConfig?.generator?.defaults as any)?.component?.folder || \"\";\n\n // Set component directory and type\n normalized.appDirectory = options.appDirectory || componentLocation;\n normalized.type =\n CONTRIBUTION_TYPE_MAP[options.pluginType || \"\"] || options.type;\n\n // Pass through contributionKey for custom plugin types\n if (options.contributionKey) {\n normalized.contributionKey = options.contributionKey;\n }\n\n return normalized;\n}\n\n/**\n * Generates component files from templates\n */\nfunction generateFiles(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n projectRoot: string,\n options: NormalizedComponentOptions\n): void {\n // Get appropriate handler\n const handler = PluginHandlerFactory.createHandler(options.pluginType);\n const templatePath = handler.getTemplatePath();\n\n // Determine target path\n const targetPath = path.join(\n projectRoot,\n options.appDirectory,\n options.type,\n options.nameDashCase\n );\n\n // Generate files\n generateComponentFiles(\n codegenFs,\n templateDir,\n templatePath,\n targetPath,\n options\n );\n}\n\n/**\n * Updates plugin configuration in .kos.json\n */\nfunction updatePluginConfiguration(\n codegenFs: CodegenFileSystem,\n projectConfig: ProjectConfiguration,\n options: NormalizedComponentOptions\n): void {\n const kosConfigPath = path.join(projectConfig.root, \".kos.json\");\n\n if (!codegenFs.exists(kosConfigPath)) {\n console.warn(`No .kos.json found at ${kosConfigPath}`);\n return;\n }\n\n // Get handler and create configuration\n const handler = PluginHandlerFactory.createHandler(options.pluginType);\n const pluginConfig = handler.createConfiguration(options);\n\n // Update .kos.json using builder\n const builder = KosConfigBuilder.create();\n builder.addPluginConfiguration(pluginConfig);\n builder.applyToFile(codegenFs, kosConfigPath);\n\n // Update localization if needed\n if (handler.requiresLocalization() && projectConfig.sourceRoot) {\n updateLocalization(\n codegenFs,\n projectConfig.sourceRoot,\n options,\n handler.getContributionKey()\n );\n }\n}\n","/**\n * Upsert a `.model(Bean)` entry and its import into an imperative registration\n * chain (`KosModelRegistry.<ns>.models().model(A)...`), on the AST.\n */\nimport {\n IndentationText,\n Project,\n QuoteKind,\n SyntaxKind,\n type CallExpression,\n type SourceFile,\n} from \"ts-morph\";\nimport { ensureNamedImport } from \"../augment/ts-toolkit\";\n\nexport interface UpsertChainEntryResult {\n changed: boolean;\n /** The full file text after the edit (only when `changed`). */\n content?: string;\n /** Whether an import for the bean had to be added (only when `changed`). */\n importAdded?: boolean;\n note?: string;\n error?: string;\n}\n\nfunction parse(content: string): SourceFile {\n // Match the file's own quote style for any import this adds.\n const singleQuoted = /^\\s*import\\b[^\"']*'/m.test(content);\n const project = new Project({\n useInMemoryFileSystem: true,\n manipulationSettings: {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: singleQuoted ? QuoteKind.Single : QuoteKind.Double,\n },\n });\n return project.createSourceFile(\"registration-chain.ts\", content, {\n overwrite: true,\n });\n}\n\n/** Every `<expr>.<name>(...)` call in the file, in source order. */\nfunction chainCalls(sf: SourceFile, name: string): CallExpression[] {\n return sf.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => {\n const callee = call.getExpression();\n return (\n callee.getKind() === SyntaxKind.PropertyAccessExpression &&\n callee.asKindOrThrow(SyntaxKind.PropertyAccessExpression).getName() ===\n name\n );\n });\n}\n\n/** Leading whitespace of the line the call's `.name` token sits on. */\nfunction indentOfCall(sf: SourceFile, call: CallExpression): string {\n const text = sf.getFullText();\n const nameNode = call\n .getExpression()\n .asKindOrThrow(SyntaxKind.PropertyAccessExpression)\n .getNameNode();\n const lineStart = text.lastIndexOf(\"\\n\", nameNode.getStart()) + 1;\n return text.slice(lineStart).match(/^[ \\t]*/)?.[0] ?? \"\";\n}\n\n/** Number of `.model(...)` entries in a chain file. */\nexport function countChainEntries(content: string): number {\n return chainCalls(parse(content), \"model\").length;\n}\n\nexport function upsertChainEntry(\n content: string,\n bean: string,\n importSpec: string\n): UpsertChainEntryResult {\n const sf = parse(content);\n\n const modelCalls = chainCalls(sf, \"model\");\n const registered = modelCalls.some((call) => {\n const [arg, ...rest] = call.getArguments();\n return rest.length === 0 && arg?.getText() === bean;\n });\n if (registered) return { changed: false, note: \"already registered\" };\n\n // Outermost entry of the last chain in the file; a trailing .companion() wraps it.\n let anchor: CallExpression | undefined;\n let indent: string;\n if (modelCalls.length > 0) {\n anchor = modelCalls.reduce((last, call) =>\n call.getEnd() > last.getEnd() ? call : last\n );\n indent = indentOfCall(sf, anchor);\n } else {\n // Empty chain: the first entry goes right after .models().\n const starts = chainCalls(sf, \"models\").filter(\n (call) => call.getArguments().length === 0\n );\n anchor = starts[starts.length - 1];\n if (!anchor) {\n return {\n changed: false,\n error: \"no .models() chain found in the registration file\",\n };\n }\n const text = sf.getFullText();\n const lineStart = text.lastIndexOf(\"\\n\", anchor.getStart()) + 1;\n indent = (text.slice(lineStart).match(/^[ \\t]*/)?.[0] ?? \"\") + \" \";\n }\n anchor.replaceWithText(`${anchor.getText()}\\n${indent}.model(${bean})`);\n\n const imported = sf\n .getImportDeclarations()\n .some((decl) =>\n decl.getNamedImports().some((named) => named.getName() === bean)\n );\n if (!imported) ensureNamedImport(sf, importSpec, [{ name: bean }]);\n\n return { changed: true, content: sf.getFullText(), importAdded: !imported };\n}\n"],"names":["unquote","SERVICE_MODULE_RE","header","FRAMEWORK_TYPES"],"mappings":";;;;;;;AAwCO,MAAM,mBAAgD;AAAA,EAC1C;AAAA,EACA,gBAA0B,CAAA;AAAA,EAE3C,YAAY,OAA0B;AACpC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,IAAI,eAAyB;AAC3B,WAAO,CAAC,GAAG,KAAK,aAAa;AAAA,EAC/B;AAAA,EAEA,KAAK,UAAiC;AACpC,WAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,EACjC;AAAA,EAEA,MAAM,UAAkB,SAAuB;AAC7C,SAAK,MAAM,MAAM,UAAU,OAAO;AAClC,SAAK,cAAc;AAAA,MACjB,KAAK,WAAW,QAAQ,IACpB,WACA,KAAK,KAAK,KAAK,MAAM,MAAM,QAAQ;AAAA,IAAA;AAAA,EAE3C;AAAA,EAEA,OAAO,UAA2B;AAChC,WAAO,KAAK,MAAM,OAAO,QAAQ;AAAA,EACnC;AAAA,EAEA,OAAO,UAAwB;AAC7B,SAAK,MAAM,OAAO,QAAQ;AAAA,EAC5B;AAAA,EAEA,UAAU,SAA2B;AACnC,WAAO,KAAK,MAAM,UAAU,OAAO;AAAA,EACrC;AACF;AAMO,MAAM,iBAA8C;AAAA,EAChD;AAAA,EAET,YAAY,eAAuB;AACjC,SAAK,OAAO,KAAK,QAAQ,aAAa;AAAA,EACxC;AAAA,EAEA,KAAK,UAAiC;AACpC,UAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,QAAI;AACF,aAAO,GAAG,aAAa,KAAK,OAAO;AAAA,IACrC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,UAAkB,SAAuB;AAC7C,UAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,OAAG,UAAU,KAAK,QAAQ,GAAG,GAAG,EAAE,WAAW,MAAM;AACnD,OAAG,cAAc,KAAK,SAAS,OAAO;AAAA,EACxC;AAAA,EAEA,OAAO,UAA2B;AAChC,WAAO,GAAG,WAAW,KAAK,QAAQ,QAAQ,CAAC;AAAA,EAC7C;AAAA,EAEA,OAAO,UAAwB;AAC7B,UAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,QAAI;AACF,SAAG,WAAW,GAAG;AAAA,IACnB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,UAAU,SAA2B;AACnC,UAAM,MAAM,KAAK,QAAQ,OAAO;AAChC,QAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,aAAO,CAAA;AAAA,IACT;AACA,WAAO,KAAK,QAAQ,GAAG,EAAE,IAAI,CAAC,SAAS,KAAK,SAAS,KAAK,MAAM,IAAI,CAAC;AAAA,EACvE;AAAA,EAEQ,QAAQ,UAA0B;AACxC,QAAI,KAAK,WAAW,QAAQ,GAAG;AAC7B,aAAO;AAAA,IACT;AACA,WAAO,KAAK,KAAK,KAAK,MAAM,QAAQ;AAAA,EACtC;AAAA,EAEQ,QAAQ,KAAuB;AACrC,UAAM,UAAoB,CAAA;AAC1B,UAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM;AAC3D,eAAW,SAAS,SAAS;AAC3B,YAAM,OAAO,KAAK,KAAK,KAAK,MAAM,IAAI;AACtC,UAAI,MAAM,eAAe;AACvB,gBAAQ,KAAK,GAAG,KAAK,QAAQ,IAAI,CAAC;AAAA,MACpC,OAAO;AACL,gBAAQ,KAAK,IAAI;AAAA,MACnB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;ACxIA,MAAM,aAA4B;AAAA,EAChC,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAChB;AAEA,IAAI,eAA8B;AAE3B,SAAS,iBAAiB,QAA6B;AAC5D,iBAAe;AACjB;AAEO,SAAS,mBAAkC;AAChD,SAAO;AACT;ACAO,SAAS,2BACd,WACA,WACA,YACA,eACM;AACN,QAAM,SAAS,iBAAA;AACf,QAAM,gBAAgB,gBAAgB,SAAS;AAE/C,aAAW,gBAAgB,eAAe;AACxC,UAAM,UAAU,KAAK,SAAS,WAAW,YAAY;AAGrD,QAAI,cAAc,oBAAoB,SAAS,aAAa;AAG5D,QAAI,YAAY,SAAS,WAAW,GAAG;AACrC,oBAAc,YAAY,MAAM,GAAG,CAAC,YAAY,MAAM;AAAA,IACxD;AAEA,UAAM,WAAW,KAAK,KAAK,YAAY,WAAW;AAIlD,UAAM,aAAa,GAAG,aAAa,cAAc,OAAO;AACxD,UAAM,WAAW,IAAI,OAAO,YAAY,eAAe;AAAA,MACrD,UAAU;AAAA;AAAA,IAAA,CACX;AAED,WAAO,MAAM,cAAc,QAAQ,EAAE;AACrC,cAAU,MAAM,UAAU,QAAQ;AAAA,EACpC;AACF;AAOA,SAAS,oBACP,UACA,eACQ;AACR,SAAO,SAAS,QAAQ,gBAAgB,CAAC,OAAO,QAAgB;AAC9D,QAAI,OAAO,eAAe;AACxB,aAAO,OAAO,cAAc,GAAG,CAAC;AAAA,IAClC;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,gBAAgB,KAAuB;AAC9C,QAAM,UAAoB,CAAA;AAC1B,QAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM;AAC3D,aAAW,SAAS,SAAS;AAC3B,UAAM,OAAO,KAAK,KAAK,KAAK,MAAM,IAAI;AACtC,QAAI,MAAM,eAAe;AACvB,cAAQ,KAAK,GAAG,gBAAgB,IAAI,CAAC;AAAA,IACvC,OAAO;AACL,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;ACjEO,SAAS,iBACd,eACmC;AACnC,QAAM,SAAS,iBAAA;AACf,QAAM,+BAAe,IAAA;AAErB,QAAM,mBAAmB,GAAG,KAAK,mBAAmB;AAAA,IAClD,KAAK;AAAA,IACL,QAAQ,CAAC,sBAAsB,cAAc,YAAY;AAAA,IACzD,UAAU;AAAA,EAAA,CACX;AAED,aAAW,WAAW,kBAAkB;AACtC,UAAM,UAAU,KAAK,KAAK,eAAe,OAAO;AAChD,QAAI;AACF,YAAM,MAAM,GAAG,aAAa,SAAS,OAAO;AAC5C,YAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,YAAM,cAAc,KAAK,QAAQ,OAAO;AACxC,YAAM,OAAO,KAAK,QAAQ,KAAK,SAAS,WAAW;AAEnD,YAAM,SAA+B;AAAA,QACnC;AAAA,QACA,MAAM;AAAA,QACN,YAAY,KAAK,cAAc,KAAK,KAAK,aAAa,KAAK;AAAA,QAC3D,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK;AAAA,QACd,MAAM,KAAK;AAAA,MAAA;AAGb,eAAS,IAAI,MAAM,MAAM;AACzB,aAAO,MAAM,uBAAuB,IAAI,OAAO,WAAW,EAAE;AAAA,IAC9D,SAAS,KAAK;AACZ,aAAO,KAAK,mBAAmB,OAAO,KAAK,GAAG,EAAE;AAAA,IAClD;AAAA,EACF;AAEA,SAAO,KAAK,cAAc,SAAS,IAAI,WAAW;AAClD,SAAO;AACT;AAaO,SAAS,kBACd,eACA,aACA,UACkC;AAClC,QAAM,MAAM,YAAY,iBAAiB,aAAa;AACtD,SAAO,IAAI,IAAI,WAAW;AAC5B;AAUO,SAAS,mBACd,eACA,UACkC;AAClC,QAAM,WAAW,KAAK,QAAQ,aAAa;AAC3C,MAAI,MAAM,KAAK,QAAQ,KAAK,QAAQ,QAAQ,CAAC;AAE7C,SAAO,IAAI,WAAW,QAAQ,KAAK,QAAQ,UAAU;AACnD,UAAM,kBAAkB,KAAK,KAAK,KAAK,cAAc;AACrD,QAAI,GAAG,WAAW,eAAe,GAAG;AAClC,UAAI;AACF,cAAM,MAAM,GAAG,aAAa,iBAAiB,OAAO;AACpD,cAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,cAAM,cAAc,KAAK,SAAS,UAAU,GAAG;AAC/C,cAAM,OAAO,KAAK,QAAQ,KAAK,SAAS,GAAG;AAE3C,eAAO;AAAA,UACL;AAAA,UACA,MAAM;AAAA,UACN,YAAY,KAAK,cAAc,KAAK,KAAK,aAAa,KAAK;AAAA,UAC3D,aAAa,KAAK;AAAA,UAClB,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,QAAA;AAAA,MAEf,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,KAAK,QAAQ,GAAG;AAAA,EACxB;AAEA,SAAO;AACT;AAQO,SAAS,WAAW,eAAgD;AACzE,QAAM,aAAa,KAAK,KAAK,eAAe,SAAS;AACrD,MAAI;AACF,UAAM,MAAM,GAAG,aAAa,YAAY,OAAO;AAC/C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AC/HO,SAAS,SACd,WACA,UACG;AACH,QAAM,UAAU,UAAU,KAAK,QAAQ;AACvC,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE;AAAA,EAC/C;AACA,SAAO,KAAK,MAAM,OAAO;AAC3B;AASO,SAAS,UACd,WACA,UACA,OACM;AACN,YAAU,MAAM,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,IAAI;AACjE;AASO,SAAS,WACd,WACA,UACA,SACM;AACN,QAAM,UAAU,SAAY,WAAW,QAAQ;AAC/C,QAAM,UAAU,QAAQ,OAAO;AAC/B,YAAU,WAAW,UAAU,OAAO;AACxC;AC7CA,MAAM,6CAA6B,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQD,eAAsB,YACpB,eACA,WACe;AACf,QAAM,SAAS,iBAAA;AAEf,aAAW,YAAY,WAAW;AAChC,UAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,QAAI,CAAC,uBAAuB,IAAI,GAAG,GAAG;AACpC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,GAAG,aAAa,UAAU,OAAO;AACjD,YAAM,UAAU,MAAM,SAAS,cAAc,UAAU;AAAA,QACrD,cAAc;AAAA,MAAA,CACf;AACD,YAAM,YAAY,MAAM,SAAS,OAAO,SAAS;AAAA,QAC/C,GAAG;AAAA,QACH,UAAU;AAAA,MAAA,CACX;AACD,SAAG,cAAc,UAAU,WAAW,OAAO;AAC7C,aAAO,MAAM,aAAa,KAAK,SAAS,eAAe,QAAQ,CAAC,EAAE;AAAA,IACpE,SAAS,KAAK;AACZ,aAAO,KAAK,oBAAoB,QAAQ,KAAK,GAAG,EAAE;AAAA,IACpD;AAAA,EACF;AACF;ACnDO,SAAS,SAAS,OAAuB;AAC9C,SAAO,MACJ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,mBAAmB,OAAO,EAClC,YAAA;AACL;AAEO,SAAS,UAAU,OAAuB;AAC/C,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,MAAM,OAAO;AACjC,MAAI,MAAM,SAAS,KAAK,MAAM,CAAC,EAAE,SAAS,GAAG;AAC3C,UAAM,CAAC,IAAI,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,YAAA,IAAgB,MAAM,CAAC,EAAE,MAAM,CAAC;AAAA,EAChE;AACA,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,CAAC,IAAI,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,YAAA,IAAgB,MAAM,CAAC,EAAE,MAAM,CAAC;AAAA,EAChE;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAEO,SAAS,WAAW,OAAuB;AAChD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,KAAK,UAAU,KAAK;AAC1B,SAAO,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAAC;AACzC;AAEO,SAAS,WAAW,OAAuB;AAChD,QAAM,QAAQ,MACX,YAAA,EACA,WAAW,KAAK,GAAG,EACnB,MAAM,GAAG,EACT,OAAO,OAAO;AACjB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,EAAE,YAAA,IAAgB,MAAM,CAAC,EAAE,MAAM,CAAC;AAAA,EACzD;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAMO,SAAS,aAAa,OAAuB;AAClD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MACJ,YAAA,EACA,MAAM,QAAQ,EACd,OAAO,OAAO,EACd,KAAK,GAAG;AACb;ACbA,MAAM,iBAAiB,CACrB,aACA,WAEC;AAAA,EACC,CAAC,GAAG,UAAU,WAAW,CAAC,WAAW,GAAG,UAAU,KAAK;AAAA,EACvD,CAAC,GAAG,UAAU,WAAW,CAAC,cAAc,GAAG,aAAa,KAAK;AAAA,EAC7D,CAAC,GAAG,UAAU,WAAW,CAAC,UAAU,GAAG,SAAS,KAAK;AAAA,EACrD,CAAC,GAAG,UAAU,WAAW,CAAC,YAAY,GAAG,WAAW,KAAK;AAAA,EACzD,CAAC,GAAG,UAAU,WAAW,CAAC,YAAY,GAAG,WAAW,KAAK;AAAA,EACzD,CAAC,GAAG,UAAU,WAAW,CAAC,WAAW,GAAG,MAAM,YAAA;AAAA,EAC9C,CAAC,GAAG,WAAW,EAAE,GAAG;AACtB;AAEK,MAAM,qBAAqB,CAChC,YAC2B;AAC3B,MAAI,mBAAmB,CAAA;AACvB,aAAW,OAAO,SAAS;AACzB,QAAI,OAAO,UAAU,eAAe,KAAK,SAAS,GAAG,GAAG;AACtD,YAAM,UAAU,QAAQ,GAAG;AAC3B,YAAM,aACJ,OAAO,YAAY,YAAY,YAAY,KACvC,EAAE,CAAC,GAAG,GAAG,QAAA,IACT,eAAe,KAAK,OAAO;AAEjC,yBAAmB;AAAA,QACjB,GAAG;AAAA,QACH,GAAG;AAAA,MAAA;AAAA,IAEP;AAAA,EACF;AACA,SAAO;AACT;AClBO,SAAS,wBAAwB,KAAiC;AACvE,SAAO,IAAI,MAAM,GAAG,EAAE,IAAA;AACxB;AAKO,SAAS,WACd,WACA,KACkC;AAClC,SAAO,mBAAmB,UAAU,MAAM,GAAG;AAC/C;AAKO,SAAS,2BACd,WACA,aACA,UACqC;AACrC,QAAM,UAAU,kBAAkB,UAAU,MAAM,aAAa,QAAQ;AACvE,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,aAAa,KAAK,KAAK,QAAQ,MAAM,WAAW;AACtD,MAAI,CAAC,UAAU,OAAO,UAAU,GAAG;AACjC,UAAM,gBAAyC;AAAA,MAC7C,MAAM,GAAG,SAAS,WAAW,CAAC;AAAA,MAC9B,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ,CAAA;AAAA,MACR,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,KAAG,EAAE;AAAA,IAAE;AAEnD,cAAU,MAAM,YAAY,KAAK,UAAU,eAAe,MAAM,CAAC,CAAC;AAAA,EACpE;AAEA,QAAM,UAAU,UAAU,KAAK,UAAU;AACzC,SAAO,UAAU,KAAK,MAAM,OAAO,IAAI;AACzC;AAOA,SAAS,aACP,QACA,MACoB;AACpB,MAAI,OAAO,IAAI,EAAG,QAAO;AACzB,QAAM,SAAS,GAAG,SAAS,IAAI,CAAC;AAChC,SAAO,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,MAAM;AACnE;AAWO,SAAS,kCAAkC,QAMzC;AACP,QAAM,UAAU;AAAA,IACd,OAAO,UAAU;AAAA,IACjB,OAAO;AAAA,IACP,OAAO;AAAA,EAAA;AAET,MAAI,CAAC,QAAS;AACd,QAAM,aAAa,KAAK,KAAK,QAAQ,MAAM,WAAW;AACtD,MAAI,CAAC,OAAO,UAAU,OAAO,UAAU,EAAG;AAE1C,aAAW,OAAO,WAAW,YAAY,CAAC,SAAc;AACtD,UAAM,SAA8B,KAAK,UAAU,CAAA;AACnD,UAAM,UAAU,aAAa,QAAQ,OAAO,SAAS;AACrD,QAAI,CAAC,QAAS,QAAO;AAErB,WAAO,OAAO,IAAI,EAAE,GAAG,OAAO,OAAO,GAAG,WAAW,KAAA;AAEnD,UAAM,YAAY,OAAO,WAAW,KAAA;AACpC,QACE,aACA,cAAc,mBACd,SAAS,KAAK,SAAS,GACvB;AACA,YAAM,cAAc,SAAS,SAAS;AACtC,YAAM,WAAW,OAAO,KAAK,MAAM,EAAE;AAAA,QACnC,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS;AAAA,MAAA;AAE7B,UAAI,YAAY,aAAa,SAAS;AACpC,cAAM,YAAY;AAAA,UAChB,GAAG,oBAAI,IAAI,CAAC,GAAI,OAAO,QAAQ,EAAE,aAAa,CAAA,GAAK,OAAO,CAAC;AAAA,QAAA;AAE7D,eAAO,QAAQ,IAAI,EAAE,GAAG,OAAO,QAAQ,GAAG,UAAA;AAAA,MAC5C;AAAA,IACF;AAEA,SAAK,SAAS;AACd,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,yBACd,WACA,aACA,WACA,UACmC;AACnC,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,SAAO,WAAW,SAAS,SAAS;AACtC;AAKO,SAAS,sBAAsB,QAM9B;AACN,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EAAA;AAET,SAAO,SAAU,OAAe,OAAO,IAAI,IAAI;AACjD;AAKO,SAAS,yBAAyB,QAShC;AACP,QAAM,SAAS,iBAAA;AACf,QAAM,gBAAgB,KAAK,KAAK,OAAO,aAAa,WAAW;AAE/D,MAAI,CAAC,OAAO,UAAU,OAAO,aAAa,GAAG;AAC3C,WAAO,KAAK,yBAAyB,OAAO,WAAW,EAAE;AACzD,UAAM,gBAAgB;AAAA,MACpB,MAAM,OAAO;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ,CAAA;AAAA,MACR,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,KAAG,EAAE;AAAA,IAAE;AAEnD,WAAO,UAAU;AAAA,MACf;AAAA,MACA,KAAK,UAAU,eAAe,MAAM,CAAC,IAAI;AAAA,IAAA;AAAA,EAE7C;AAEA,aAAW,OAAO,WAAW,eAAe,CAAC,SAAc;AACzD,UAAM,WAAW,KAAK,SAAS,OAAO,SAAS,KAAK,CAAA;AACpD,SAAK,SAAS;AAAA,MACZ,GAAG,KAAK;AAAA,MACR,CAAC,OAAO,SAAS,GAAG;AAAA;AAAA,QAElB,GAAG;AAAA,QACH,MAAM,OAAO;AAAA,QACb,MAAM,GAAG,OAAO,SAAS;AAAA,QACzB,WAAW,CAAC,CAAC,OAAO;AAAA,QACpB,WAAW,CAAC,CAAC,OAAO;AAAA,QACpB,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,QAAA,IAAY,CAAA;AAAA,MAAC;AAAA,IACtD;AAEF,WAAO;AAAA,EACT,CAAC;AACH;AC9OA,SAAS,kBAA0B;AACjC,MAAI,QAAQ,IAAI,uBAAuB;AACrC,WAAO,QAAQ,IAAI;AAAA,EACrB;AAGA,MAAI,MAAM;AACV,SAAO,QAAQ,KAAK,QAAQ,GAAG,GAAG;AAChC,UAAM,UAAU,KAAK,KAAK,KAAK,cAAc;AAC7C,QAAI,GAAG,WAAW,OAAO,GAAG;AAC1B,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,GAAG,aAAa,SAAS,OAAO,CAAC;AACxD,YAAI,IAAI,SAAS,iCAAiC;AAChD,iBAAO;AAAA,QACT;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,KAAK,QAAQ,GAAG;AAAA,EACxB;AAEA,SAAO,KAAK,QAAQ,WAAW,MAAM,IAAI;AAC3C;AASO,SAAS,eAAe,eAA+B;AAC5D,SAAO,KAAK,KAAK,gBAAA,GAAmB,aAAa,aAAa;AAChE;ACvBO,SAAS,sBACd,WACA,aACA,SACM;AACN,QAAM,aAAa,mBAAmB,OAAO;AAE7C,QAAM,cAAc,UAAU,WAAW,YAAY;AACrD,QAAM,YAAY,KAAK,KAAK,SAAS,SAAS;AAE9C;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,SAAS;AAAA,IAChC;AAAA,IACA;AAAA,EAAA;AAGF;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,OAAO;AAAA,IAC9B;AAAA,IACA;AAAA,EAAA;AAEJ;ACxBA,MAAM,uBAAuB;AAGtB,MAAM,yBAAyB;AAOtC,MAAM,8BAA8B;AAyB7B,SAAS,0BACd,WACA,SACoB;AACpB,QAAM,OAAO,SAAS,QAAQ,IAAI;AAClC,QAAM,cAAc,KAAK,SAAS,oBAAoB,IAClD,OACA,GAAG,IAAI,GAAG,oBAAoB;AAClC,QAAM,WAAW,QAAQ,WAAW,wBAAwB;AAAA,IAC1D;AAAA,IACA;AAAA,EAAA;AAEF,QAAM,QAAQ,YAAY,aAAa,SAAS,IAAI;AACpD,SAAO;AAAA,IACL;AAAA,IACA,aAAa,GAAG,OAAO,IAAI,WAAW,GAAG,QAAQ,QAAQ,EAAE;AAAA,IAC3D,YAAY,QAAQ,IAAI,KAAK,IAAI,WAAW,KAAK;AAAA,EAAA;AAErD;AAGA,SAAS,aAAa,WAAkD;AACtE,MAAI,CAAC,UAAU,OAAO,cAAc,GAAG;AACrC,WAAO;AAAA,EACT;AACA,QAAM,OAAO,SAA4B,WAAW,cAAc,EAAE;AACpE,MAAI,CAAC,MAAM,WAAW,GAAG,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC;AACnC;AAGA,SAAS,eAAe,aAA6B;AACnD,SAAO,YACJ,MAAM,GAAG,EACT,OAAO,OAAO,EACd,IAAI,MAAM,KAAK,EACf,KAAK,EAAE;AACZ;AAWO,SAAS,qBACd,WACA,aACA,SACoB;AACpB,QAAM,SAAS,0BAA0B,WAAW,OAAO;AAE3D;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,SAAS;AAAA,IAChC,OAAO;AAAA,IACP;AAAA,MACE,GAAG;AAAA,MACH,sBAAsB,UAAU,OAAO,WAAW;AAAA,MAClD,gBAAgB,eAAe,OAAO,WAAW;AAAA,MACjD,UAAU;AAAA,IAAA;AAAA,EACZ;AAGF,uBAAqB,WAAW,MAAM;AACtC,0BAAwB,SAAS;AAEjC,SAAO;AACT;AAMA,SAAS,qBACP,WACA,QACM;AACN,MAAI,CAAC,UAAU,OAAO,oBAAoB,GAAG;AAC3C;AAAA,EACF;AACA,aAAW,WAAW,sBAAsB,CAAC,SAAc;AACzD,SAAK,kBAAkB,KAAK,mBAAmB,CAAA;AAC/C,SAAK,gBAAgB,QAAQ,KAAK,gBAAgB,SAAS,CAAA;AAC3D,SAAK,gBAAgB,MAAM,OAAO,UAAU,IAAI;AAAA,MAC9C,GAAG,OAAO,WAAW;AAAA,IAAA;AAEvB,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,wBAAwB,WAAoC;AACnE,MAAI,CAAC,UAAU,OAAO,cAAc,GAAG;AACrC;AAAA,EACF;AACA,QAAM,MAAM,SAA8B,WAAW,cAAc;AACnE,QAAM,kBAAkB,IAAI,mBAAmB,CAAA;AAC/C,MAAI,yBAAyB,iBAAiB;AAC5C;AAAA,EACF;AACA,kBAAgB,qBAAqB,IAAI;AACzC,MAAI,kBAAkB,OAAO;AAAA;AAAA,IAE3B,OAAO,QAAQ,eAAe,EAAE;AAAA,MAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAC3C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,IAAA;AAAA,EAC3B;AAEF,YAAU,WAAW,gBAAgB,GAAG;AAC1C;ACjJO,SAAS,aACd,WACA,SACM;AACN,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,YAAY,cAAc,oBAAA,IAAwB;AAE1D,MAAI;AACJ,MAAI;AACF,eAAW,SAAS,WAAW,SAAS;AAAA,EAC1C,QAAQ;AACN,WAAO,MAAM,wBAAwB;AACrC;AAAA,EACF;AAEA,SAAO,KAAK,kBAAkB;AAE9B,QAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,WAAW;AAAA,EAAA;AAGb,QAAM,mBAAmB,SAAS,cAAc,CAAA;AAChD,QAAM,YAAY,iBAAiB,4BAA4B,KAAK,CAAA;AAEpE,QAAM,eAAe,CAAC,eAAuB;AAC3C,UAAM,SAAS,UAAU,UAAU,KAAK,EAAE,GAAG,qBAAA;AAC7C,WAAO,aAAa;AACpB,WAAO,eAAe;AACtB,WAAO,sBAAsB;AAC7B,cAAU,UAAU,IAAI;AAAA,EAC1B;AAEA,GAAC,aAAa,iBAAiB,eAAe,UAAU,EAAE;AAAA,IACxD;AAAA,EAAA;AAGF,WAAS,aAAa;AAAA,IACpB,GAAG;AAAA,IACH,8BAA8B;AAAA,EAAA;AAGhC,YAAU,WAAW,WAAW,QAAQ;AAC1C;AClBA,MAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,0BACd,WACA,aACA,SACyB;AACzB,QAAM,SAAS,QAAQ,QAAQ,gBAAgB;AAC/C,QAAM,aAAa,mBAAmB,EAAE,MAAM,QAAQ,MAAM;AAC5D,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH;AAAA,IACA,QAAQ,QAAQ,UAAU;AAAA,IAC1B,WAAW,GAAG,WAAW,YAAY;AAAA,IACrC,aAAa,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,MAAM,EAAE;AAAA,IACpE,UAAU,QAAQ,YAAY;AAAA,IAC9B,cAAc,QAAQ,gBAAgB;AAAA,EAAA;AAGxC;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,MAAM;AAAA,IAC7B;AAAA,IACA;AAAA,EAAA;AAEF;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,OAAO;AAAA,IAC9B;AAAA,IACA;AAAA,EAAA;AAIF;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,QAAQ;AAAA,IAC/B;AAAA,IACA;AAAA,EAAA;AAEF;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,MAAM;AAAA,IAC7B;AAAA,IACA;AAAA,EAAA;AAGF,SAAO,EAAE,iBAAiB,CAAC,GAAG,aAAa,EAAA;AAC7C;ACrEO,MAAM,iBAAiB;AASvB,MAAM,kBAAkB,iBAAiB,cAAc;AAWvD,SAAS,eAAe,OAAe,aAA6B;AACzE,QAAM,OAAO,YAAY,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,SAAO,MACJ,QAAQ,oBAAoB,IAAI,EAChC,QAAQ,yBAAyB,EAAE;AACxC;AAyBO,MAAM,qCACX;AAEK,SAAS,gBACd,SACqC;AACrC,QAAM,EAAE,MAAM,aAAa,OAAO,cAAc,YAAY;AAC5D,QAAM,aAAa;AAGnB,QAAM,gBAAgB;AAEtB,QAAM,UAA+C;AAAA,IACnD,KAAK;AAAA,MACH,SAAS,wCAAwC,IAAI,2CAA2C,IAAI;AAAA,MACpG,SAAS;AAAA,QACP;AAAA,QACA,SAAS;AAAA,QACT,SAAS,GAAG,IAAI;AAAA,MAAA;AAAA,MAElB,WAAW,CAAC,KAAK;AAAA,IAAA;AAAA,IAEnB,KAAK;AAAA,MACH,SAAS,kCAAkC,IAAI;AAAA,MAC/C,SAAS;AAAA,QACP;AAAA,QACA,SAAS;AAAA,MAAA;AAAA;AAAA;AAAA,MAIX,WAAW,aACP,CAAC,aAAa,cAAc,MAAM,IAClC,CAAC,aAAa,MAAM;AAAA,IAAA;AAAA,EAC1B;AAGF,MAAI,YAAY;AACd,YAAQ,aAAa;AAAA,MACnB,SAAS,qCAAqC,IAAI;AAAA,MAClD,SAAS;AAAA,QACP,YAAY;AAAA,QACZ,UAAU;AAAA,MAAA;AAAA,MAEZ,WAAW,CAAC,OAAO;AAAA,IAAA;AAAA,EAEvB;AAEA,UAAQ,UAAU;AAAA,IAChB,SAAS,QAAQ,kCAAkC,IAAI,IAAI;AAAA,IAC3D,SAAS,CAAA;AAAA,IACT,WAAW,CAAA;AAAA,EAAC;AAId,UAAQ,OAAO,gBAAgB,EAAE,YAAY,eAAe;AAE5D,SAAO;AACT;AAiBO,SAAS,gBAAgB;AAAA,EAC9B;AACF,GAA2C;AACzC,QAAM,MAAM,WAAW,QAAQ,QAAQ,EAAE;AAGzC,QAAM,YAAY,IAAI,WAAW,GAAG,IAAI,MAAM,mBAAmB,GAAG;AACpE,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS;AAAA,MACP,GAAG,SAAS;AAAA,MACZ,GAAG,SAAS;AAAA,IAAA;AAAA,IAEd,OAAO;AAAA,IACP,QAAQ,CAAC,cAAc,eAAe,mCAAmC;AAAA,IACzE,SAAS,EAAE,YAAY,KAAK,UAAU,KAAA;AAAA,EAAK;AAE/C;AClIA,MAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,iBAAiB,YAAoB,UAA0B;AACtE,SAAO,GAAG,WAAW,QAAQ,QAAQ,EAAE,CAAC,IAAI,QAAQ;AACtD;AAEO,SAAS,oBACd,WACsB;AACtB,QAAM,YAAkC,CAAA;AAExC,aAAW,OAAO,iBAAiB;AACjC,eAAW,QAAQ,UAAU,UAAU,MAAM,GAAG,EAAE,GAAG;AACnD,UAAI,CAAC,KAAK,SAAS,cAAc,EAAG;AACpC,YAAM,MAAM,UAAU,KAAK,IAAI;AAC/B,UAAI,QAAQ,KAAM;AAClB,UAAI;AACJ,UAAI;AACF,kBAAU,KAAK,MAAM,GAAG;AAAA,MAC1B,QAAQ;AACN;AAAA,MACF;AACA,YAAM,OAAO,QAAQ;AACrB,UAAI,CAAC,KAAM;AAKX,YAAM,cAAc,KAAK,MAAM,MAAM,QAAQ,KAAK,YAAY,GAAG,CAAC;AAClE,YAAM,UAAU,CAAC,UAAkB,eAAe,OAAO,WAAW;AAEpE,YAAM,aAAa,QAAQ,SAAS,KAAK;AACzC,UAAI,YAAY,cAAc,YAAY,SAAS;AACjD,kBAAU,KAAK;AAAA,UACb,IAAI;AAAA,UACJ,UAAU,MAAM;AAAA,YACd,QAAQ,WAAW,UAAU;AAAA,YAC7B,WAAW;AAAA,UAAA,CACZ;AAAA,QAAA,CACF;AAAA,MACH,WAAW,QAAQ,SAAS,QAAQ;AAGlC,cAAM,eAAe,QAAQ,QAAQ,OAAO,SAAS;AAGrD,kBAAU,KAAK;AAAA,UACb,IAAI;AAAA,UACJ,UAAU,MAAM;AAAA,YACd,QAAQ,gBAAgB,iBAAiB,cAAc,EAAE;AAAA,YACzD,GAAG,IAAI;AAAA,UAAA,CACR;AAAA,UACD,OAAO;AAAA,QAAA,CACR;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,aAAW,QAAQ,UAAU,UAAU,aAAa,GAAG;AACrD,QAAI,CAAC,KAAK,SAAS,MAAM,EAAG;AAC5B,UAAM,OAAO,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,MAAM;AACjE,cAAU,KAAK,EAAE,IAAI,MAAM,UAAU,MAAM;AAAA,EAC7C;AAEA,SAAO;AACT;AAEO,SAAS,sBACd,WACsB;AACtB,QAAM,aAAa,UAAU,KAAK,cAAc;AAChD,MAAI,eAAe,KAAM,QAAO,CAAA;AAEhC,QAAM,YAAkC,CAAA;AACxC,aAAW,SAAS,WAAW,SAAS,4BAA4B,GAAG;AACrE,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,MAAM,UAAU,KAAK,QAAQ,SAAS,UAAU;AACtD,QAAI,QAAQ,QAAQ,CAAC,IAAI,SAAS,sBAAsB,EAAG;AAE3D,UAAM,gBAAgB,IAAI,QAAQ,8BAA8B,EAAE;AAClE,UAAM,aAAa,cAAc;AAAA,MAC/B;AAAA,IAAA,IACE,CAAC;AACL,QAAI,CAAC,WAAY;AACjB,cAAU,KAAK;AAAA,MACb,IAAI;AAAA;AAAA,MAEJ,UAAU,QAAQ,SAAS,WAAW,UAAU;AAAA,IAAA,CACjD;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,aACP,WACA,cACA,YACA,OAC6B;AAC7B,QAAM,MAAM,UAAU,KAAK,YAAY;AACvC,MAAI,QAAQ,KAAM,QAAO;AACzB,QAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,QAAM,WAAkB,SAAS,aAAa,CAAA;AAE9C,QAAM,aAAa,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AACjE,QAAM,OAAc,CAAA;AACpB,QAAM,QAAkB,CAAA;AACxB,QAAM,SAAmB,CAAA;AAEzB,aAAW,SAAS,UAAU;AAC5B,QAAI,WAAW,IAAI,MAAM,QAAQ,GAAG;AAClC,WAAK,KAAK,KAAK;AACf,iBAAW,OAAO,MAAM,QAAQ;AAAA,IAClC,WAAW,OAAO;AAChB,aAAO,KAAK,MAAM,MAAM,MAAM,QAAQ;AAAA,IACxC,OAAO;AACL,WAAK,KAAK,KAAK;AACf,YAAM,KAAK,MAAM,MAAM,MAAM,QAAQ;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,QAAkB,CAAA;AACxB,aAAW,YAAY,WAAW,UAAU;AAC1C,SAAK,KAAK;AAAA,MACR,IAAI,SAAS;AAAA,MACb,UAAU,SAAS;AAAA,MACnB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,GAAI,SAAS,UAAU,SAAY,EAAE,OAAO,SAAS,UAAU,CAAA;AAAA,IAAC,CACjE;AACD,UAAM,KAAK,SAAS,EAAE;AAAA,EACxB;AAEA,MAAI,MAAM,SAAS,KAAK,OAAO,SAAS,GAAG;AACzC,aAAS,YAAY;AACrB,cAAU,MAAM,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,EACxE;AAEA,SAAO,EAAE,OAAO,OAAO,OAAA;AACzB;AAEO,SAAS,gBACd,WACA,UAAyB,IACX;AACd,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,KAAK,oBAAoB,SAAS;AACxC,QAAM,OAAO,sBAAsB,SAAS;AAE5C,QAAM,YAAkD,CAAA;AACxD,QAAM,OAA8C;AAAA,IAClD,CAAC,yBAAyB,EAAE;AAAA,IAC5B,CAAC,2BAA2B,IAAI;AAAA,IAChC,CAAC,8BAA8B,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAAA,EAAA;AAEjD,aAAW,CAAC,cAAc,UAAU,KAAK,MAAM;AAC7C,UAAM,SAAS,aAAa,WAAW,cAAc,YAAY,KAAK;AACtE,QAAI,QAAQ;AACV,gBAAU,YAAY,IAAI;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO,EAAE,WAAW,YAAY,EAAE,IAAI,OAAK;AAC7C;ACnMO,SAAS,wBACd,WACA,SACM;AACN,QAAM,UAAU;AAChB,QAAM,WAAW,UAAU,KAAK,OAAO;AACvC,MAAI,aAAa,MAAM;AACrB,cAAU;AAAA,MACR;AAAA,MACA;AAAA;AAAA;AAAA,aAGO,QAAQ,OAAO;AAAA,gBACZ,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA,cAIpB,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA,IAAA;AAK5B;AAAA,EACF;AACA,MAAI,SAAS,SAAS,WAAW,QAAQ,UAAU,WAAW,GAAG;AAC/D;AAAA,EACF;AACA,YAAU;AAAA,IACR;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA,aAAa,QAAQ,UAAU;AAAA;AAAA,IAAA;AAAA,EACjC;AAEJ;AAiBO,SAAS,wBACd,WACA,SACU;AACV,QAAM,EAAE,YAAY,YAAY,kBAAkB,mBAAmB;AACrE,QAAM,QAAkB,CAAA;AACxB,QAAM,UAAU,QAAQ,UAAU;AAClC,MAAI,MAAM,UAAU,KAAK,OAAO;AAChC,MAAI,QAAQ,MAAM;AAChB,UAAM,IAAI,MAAM,mCAAmC,OAAO,EAAE;AAAA,EAC9D;AAEA,MAAI,IAAI,SAAS,2CAA2C,GAAG;AAC7D,QAAI,YAAY;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA,gBAAgB,UAAU;AAAA,MAAA;AAAA,IAE9B,OAAO;AACL,YAAM;AAAA,QACJ;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAEA,MACE,IAAI,SAAS,iCAAiC,KAC9C,CAAC,IAAI,SAAS,gCAAgC,GAC9C;AACA,QAAI,kBAAkB;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,wCAA6C,gBAAgB;AAAA,MAAA;AAAA,IAEjE,OAAO;AACL,YAAM;AAAA,QACJ;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAEA,QAAM,qBAAqB;AAC3B,MAAI,mBAAmB,KAAK,GAAG,GAAG;AAChC,QAAI,gBAAgB;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,iDAAiD,cAAc;AAAA,MAAA;AAAA,IAEnE,OAAO;AACL,YAAM;AAAA,QACJ;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAEA,YAAU,MAAM,SAAS,GAAG;AAI5B,QAAM,YAAY,QAAQ,UAAU;AACpC,MAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,eAAW,QAAQ,UAAU,UAAU,SAAS,GAAG;AACjD,gBAAU,OAAO,IAAI;AAAA,IACvB;AAAA,EACF;AACA,QAAM,YAAY,UAAU,KAAK,QAAQ,UAAU,YAAY;AAC/D,MAAI,cAAc,MAAM;AACtB,cAAU,MAAM,QAAQ,UAAU,eAAe,SAAS;AAC1D,cAAU,OAAO,QAAQ,UAAU,YAAY;AAAA,EACjD;AAEA,SAAO;AACT;AAWO,SAAS,2BACd,WACA,SACM;AACN,QAAM,EAAE,eAAe;AACvB,aAAW,gBAAgB;AAAA,IACzB;AAAA,IACA;AAAA,EAAA,GACC;AACD,UAAM,MAAM,UAAU,KAAK,YAAY;AACvC,QAAI,QAAQ,MAAM;AAChB;AAAA,IACF;AACA,UAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,aAAS,YAAY,SAAS,aAAa,CAAA;AAC3C,QACE,SAAS,UAAU;AAAA,MACjB,CAAC,aAA8B,SAAS,OAAO;AAAA,IAAA,GAEjD;AACA;AAAA,IACF;AACA,aAAS,UAAU,KAAK;AAAA,MACtB,IAAI;AAAA;AAAA,MAEJ,UAAU,QAAQ,UAAU,WAAW,UAAU;AAAA,MACjD,eAAe;AAAA,MACf,aAAa;AAAA,IAAA,CACd;AACD,cAAU,MAAM,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,EACxE;AACF;ACxIO,SAAS,iBACd,WACA,SACA,UACsB;AACtB,QAAM,cAAsC;AAAA,IAC1C,MAAM,QAAQ;AAAA,EAAA;AAGhB,MAAK,QAAgB,WAAW;AAC9B,gBAAY,YAAa,QAAgB;AAAA,EAC3C;AAEA,MAAI,QAAQ,gBAAgB;AAC1B,gBAAY,iBAAiB,QAAQ;AAAA,EACvC;AAEA,QAAM,mBAAmB,mBAAmB,WAAW;AACvD,QAAM,eAAe,QAAQ;AAC7B,QAAM,sBAAsB,QAAQ,uBAAuB;AAC3D,QAAM,kBAAkB,iBAAiB;AAEzC,MAAI,aAAa;AACjB,MAAI,iBAAiB;AACnB,UAAM,qBAAqB;AAAA,MACzB,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IAAA;AAEF,QAAI,oBAAoB;AACtB,YAAM,cAAc,KAAK,KAAK,mBAAmB,MAAM,cAAc;AACrE,UAAI;AACF,cAAM,UAAU,SAA2B,WAAW,WAAW;AACjE,qBAAa,QAAQ,QAAQ;AAAA,MAC/B,QAAQ;AACN,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAMA,QAAM,kBAAoD;AAAA,IACxD,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,WAAW;AAAA,EAAA;AAGb,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EAAA;AAEd;AC7GO,MAAM,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACyBtC,SAAS,oBACd,WACA,UACA,QACM;AACN,QAAM,UAAU,UAAU,KAAK,QAAQ;AACvC,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE;AAAA,EAC/C;AACA,QAAM,UAAU,IAAI,QAAQ;AAAA,IAC1B,uBAAuB;AAAA,IACvB,sBAAsB;AAAA,MACpB,iBAAiB,gBAAgB;AAAA,MACjC,WAAW,UAAU;AAAA,IAAA;AAAA,EACvB,CACD;AACD,QAAM,aAAa,QAAQ,iBAAiB,UAAU,SAAS;AAAA,IAC7D,WAAW;AAAA,EAAA,CACZ;AACD,SAAO,UAAU;AACjB,YAAU,MAAM,UAAU,WAAW,YAAA,CAAa;AACpD;AAOO,SAAS,eACd,WACA,UACA,SACG;AACH,QAAM,UAAU,UAAU,KAAK,QAAQ;AACvC,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE;AAAA,EAC/C;AACA,QAAM,UAAU,IAAI,QAAQ,EAAE,uBAAuB,MAAM;AAC3D,SAAO;AAAA,IACL,QAAQ,iBAAiB,UAAU,SAAS,EAAE,WAAW,MAAM;AAAA,EAAA;AAEnE;AAOO,SAAS,oBACd,YACA,KACA,eACoB;AACpB,QAAM,MAAM,IAAI,aAAa,aAAa,GAAG,aAAA,EAAe,CAAC;AAC7D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,YAAA,MAAkB,0BAA2B,QAAO,IAAI,QAAA;AAIhE,QAAM,OAAO,IAAI,QAAA,EAAU,KAAA;AAC3B,MAAI,CAAC,qBAAqB,KAAK,IAAI,EAAG,QAAO;AAC7C,QAAM,cAAc,WACjB,uBAAuB,IAAI,GAC1B,eAAA,GACA,QAAA;AACJ,SAAO,cAAc,YAAY,QAAQ,qBAAqB,EAAE,IAAI;AACtE;AAcO,SAAS,kBACd,YACA,iBACA,OACM;AACN,QAAM,QAAQ,WACX,wBACA,OAAO,CAAC,MAAM,EAAE,wBAAA,MAA8B,eAAe;AAIhE,QAAM,+BAAe,IAAA;AACrB,aAAW,KAAK,OAAO;AACrB,eAAW,KAAK,EAAE,gBAAA,YAA4B,IAAI,EAAE,SAAS;AAAA,EAC/D;AAKA,MAAI,SAAS,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY;AAC9C,MAAI,CAAC,QAAQ;AACX,aAAS,WAAW,qBAAqB,EAAE,gBAAA,CAAiB;AAAA,EAC9D;AAEA,aAAW,EAAE,MAAM,WAAA,KAAgB,OAAO;AACxC,QAAI,SAAS,IAAI,IAAI,EAAG;AACxB,WAAO,eAAe,EAAE,MAAM,YAAY,CAAC,CAAC,YAAY;AACxD,aAAS,IAAI,IAAI;AAAA,EACnB;AACF;AAOO,SAAS,0BAA0B,YAAgC;AACxE,QAAM,OAAO,WACV,sBAAA,EACA,KAAK,CAAC,MAAM,EAAE,gBAAA,EAAkB,KAAK,CAAC,MAAM,EAAE,QAAA,MAAc,UAAU,CAAC;AAC1E,SAAO,MAAM,6BAA6B;AAC5C;AAMO,SAAS,cACd,YACA,YACkB;AAClB,QAAM,UAAU,WAAW,WAAA;AAC3B,QAAM,SAAS,aACX,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAA,MAAc,UAAU,IAC9C;AACJ,MAAI,OAAQ,QAAO;AACnB,QAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,aAAa,KAAK,EAAE,QAAA,KAAa,EAAE,CAAC;AACrE,MAAI,KAAM,QAAO;AACjB,QAAM,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY;AACnD,MAAI,SAAU,QAAO;AACrB,MAAI,QAAQ,SAAS,EAAG,QAAO,QAAQ,CAAC;AACxC,QAAM,IAAI,MAAM,2CAA2C;AAC7D;AAQO,SAAS,kBACd,KACA,MACA,MACM;AACN,MAAI,IAAI,aAAa,IAAI,EAAG;AAC5B,QAAM,WAAW,MAAM,UAAU,SAC7B,IAAI,KAAK,SAAS,KAAK,IAAI,CAAC,MAC5B;AACJ,QAAM,OAAO,MAAM,YAAY;AAE/B,QAAM,aAAa,IAAI,cAAA;AACvB,QAAM,cAAc,WAAW,UAAU,CAAC,MAAM,EAAE,QAAA,MAAc,UAAU;AAC1E,QAAM,YAAY,eAAe,IAAI,cAAc,IAAI,WAAW;AAClE,MAAI,gBAAgB,WAAW;AAAA,IAC7B,MAAM,GAAG,IAAI,GAAG,QAAQ;AAAA,IACxB,WAAW,OAAO,CAAC,IAAI,IAAI,CAAA;AAAA,EAAC,CAC7B;AACH;AAQO,SAAS,uBACd,YACA,eACA,aACA,iBAA2B,CAAA,GACrB;AACN,QAAM,WAAW,YAAY,MAAM,GAAG,EAAE,CAAC,EAAE,KAAA;AAC3C,MAAI,QAAQ,WAAW,aAAa,aAAa;AACjD,MAAI,OAAO;AACT,UAAM,UAAU,MACb,WAAA,EACA,KAAK,CAAC,MAAM,EAAE,QAAA,EAAU,MAAM,GAAG,EAAE,CAAC,EAAE,KAAA,MAAW,QAAQ;AAC5D,QAAI,CAAC,QAAS,OAAM,WAAW,WAAW;AAC1C;AAAA,EACF;AAGA,UAAQ,WAAW,aAAa;AAAA,IAC9B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ;AAAA,IACA,SAAS,CAAC,WAAW;AAAA,EAAA,CACtB;AAED,aAAW;AAAA,IACT,MAAM,SAAA;AAAA,IACN;AAAA,EAAA;AAEJ;AAMO,SAAS,wBACd,YACA,MACM;AACN,MAAI,WAAW,YAAA,EAAc,SAAS,IAAI,EAAG;AAC7C,aAAW,WAAW,GAAG,qBAAqB,IAAI;AAAA,CAAO;AAC3D;AAOO,SAAS,kBACd,YACA,MACS;AACT,MAAI,WAAW,uBAAuB,KAAK,IAAI,EAAG,QAAO;AACzD,QAAM,UAAU,WAAW,sBAAA;AAC3B,QAAM,QACJ,QAAQ,SAAS,IAAI,QAAQ,QAAQ,SAAS,CAAC,EAAE,cAAA,IAAkB,IAAI;AACzE,aAAW,wBAAwB,OAAO;AAAA,IACxC,iBAAiB,wBAAwB;AAAA,IACzC,cAAc,CAAC,EAAE,MAAM,KAAK,MAAM,aAAa,KAAK,YAAA,CAAa;AAAA,EAAA,CAClE;AACD,SAAO;AACT;AAGA,SAAS,aAAa,YAAgC;AACpD,QAAM,UAAU,WAAW,sBAAA;AAC3B,SAAO,QAAQ,SAAS,IACpB,QAAQ,QAAQ,SAAS,CAAC,EAAE,cAAA,IAAkB,IAC9C;AACN;AAGA,SAASA,UAAQ,MAAsB;AACrC,SAAO,KAAK,QAAQ,gBAAgB,EAAE;AACxC;AAGA,SAAS,uBACP,YACA,MACgC;AAChC,QAAM,cAAc,WAAW,uBAAuB,IAAI;AAC1D,MAAI,CAAC,YAAa,QAAO;AACzB,MAAI,cAAc,YAAY,eAAA;AAC9B,MAAI,KAAK,eAAe,WAAW,GAAG;AACpC,kBAAc,YAAY,cAAA;AAAA,EAC5B;AACA,MAAI,CAAC,eAAe,CAAC,KAAK,0BAA0B,WAAW,GAAG;AAChE,UAAM,IAAI;AAAA,MACR,IAAI,IAAI,eAAe,WAAW,aAAa;AAAA,IAAA;AAAA,EAEnD;AACA,SAAO;AACT;AAWO,SAAS,wBACd,YACA,MAQmC;AACnC,QAAM,UACJ,KAAK,WACJ,CAAC,UAAkB,cAAsB,aAAa;AAEzD,MAAI,UAAU,uBAAuB,YAAY,KAAK,WAAW;AACjE,MAAI,CAAC,SAAS;AAGZ,eAAW,wBAAwB,aAAa,UAAU,GAAG;AAAA,MAC3D,YAAY;AAAA,MACZ,iBAAiB,wBAAwB;AAAA,MACzC,cAAc,CAAC,EAAE,MAAM,KAAK,aAAa,aAAa,eAAe;AAAA,IAAA,CACtE;AACD,cAAU,uBAAuB,YAAY,KAAK,WAAW;AAC7D,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,6BAA6B,KAAK,WAAW,IAAI;AAAA,IACnE;AACA,YAAQ,sBAAsB;AAAA,MAC5B,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,eAAe,KAAK;AAAA,IAAA,CACrB;AACD,WAAO,EAAE,KAAK,KAAK,KAAK,SAAS,KAAA;AAAA,EACnC;AAEA,aAAW,YAAY,QACpB,cAAA,EACA,OAAO,KAAK,oBAAoB,GAAG;AACpC,UAAM,cAAcA,UAAQ,SAAS,QAAA,CAAS;AAC9C,UAAM,sBAAsB,SAAS,sBAAA,EAAwB,QAAA;AAC7D,QAAI,QAAQ,qBAAqB,KAAK,WAAW,GAAG;AAClD,aAAO,EAAE,KAAK,aAAa,SAAS,MAAA;AAAA,IACtC;AACA,QAAI,gBAAgB,KAAK,KAAK;AAC5B,YAAM,IAAI;AAAA,QACR,IAAI,KAAK,WAAW,IAAI,KAAK,GAAG,4CAC1B,mBAAmB;AAAA,MAAA;AAAA,IAE7B;AAAA,EACF;AAEA,UAAQ,sBAAsB;AAAA,IAC5B,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,eAAe,KAAK;AAAA,EAAA,CACrB;AACD,SAAO,EAAE,KAAK,KAAK,KAAK,SAAS,KAAA;AACnC;AAGO,SAAS,wBACd,YACA,MACS;AACT,MAAI,WAAW,aAAa,KAAK,IAAI,EAAG,QAAO;AAC/C,aAAW,aAAa;AAAA,IACtB,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA,IACX,YAAY;AAAA,IACZ,MAAM,KAAK,OAAO,CAAC,KAAK,IAAI,IAAI;AAAA,EAAA,CACjC;AACD,SAAO;AACT;AAOO,SAAS,qBACd,YACA,MACS;AACT,MAAI,WAAW,uBAAuB,KAAK,IAAI,EAAG,QAAO;AACzD,aAAW,qBAAqB;AAAA,IAC9B,YAAY;AAAA,IACZ,iBAAiB,wBAAwB;AAAA,IACzC,cAAc;AAAA,MACZ;AAAA,QACE,MAAM,KAAK;AAAA,QACX,aAAa,SAAS,KAAK,OAAO,MAAM,KAAK,QAAQ;AAAA,MAAA;AAAA,IACvD;AAAA,EACF,CACD;AACD,SAAO;AACT;AAGO,SAAS,mBACd,YACA,iBACS;AACT,QAAM,UAAU,WACb,wBACA,KAAK,CAAC,MAAM,EAAE,wBAAA,MAA8B,eAAe;AAC9D,MAAI,QAAS,QAAO;AACpB,aAAW,qBAAqB,EAAE,iBAAiB;AACnD,SAAO;AACT;AAUO,SAAS,mBACd,YACA,iBACA,OACA,aAAa,OACJ;AACT,QAAM,WAAW,WACd,sBAAA,EACA;AAAA,IACC,CAAC,MACC,EAAE,wBAAA,MAA8B,mBAChC,EAAE,iBAAiB;AAAA,EAAA;AAGzB,MAAI,CAAC,UAAU;AACb,eAAW,qBAAqB;AAAA,MAC9B;AAAA,MACA;AAAA,MACA,cAAc,MAAM,IAAI,CAAC,SAAS;AAChC,eAAO,EAAE,KAAA;AAAA,MACX,CAAC;AAAA,IAAA,CACF;AACD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,IAAI,IAAI,SAAS,gBAAA,EAAkB,IAAI,CAAC,MAAM,EAAE,QAAA,CAAS,CAAC;AAC1E,QAAM,UAAU,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,IAAI,IAAI,CAAC;AACzD,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,WAAS;AAAA,IACP,QAAQ,IAAI,CAAC,SAAS;AACpB,aAAO,EAAE,KAAA;AAAA,IACX,CAAC;AAAA,EAAA;AAEH,SAAO;AACT;AAMO,SAAS,wBACd,YACA,MACA,aAA2E,CAAA,GAC3E,eAAyB,IAChB;AACT,MAAI,WAAW,aAAa,IAAI,EAAG,QAAO;AAE1C,aAAW,aAAa;AAAA,IACtB;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,EAAA,CACD;AACD,SAAO;AACT;AAqBO,SAAS,mBACd,KACA,MACS;AACT,MAAI,IAAI,UAAU,KAAK,IAAI,EAAG,QAAO;AACrC,MAAI,UAAU;AAAA,IACZ,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,YAAY,KAAK;AAAA,IACjB,MAAM,KAAK,OAAO,CAAC,KAAK,IAAI,IAAI;AAAA,IAChC,YAAY,KAAK,YAAY,IAAI,CAAC,MAAM;AACtC,aAAO,EAAE,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,kBAAkB,EAAE,SAAA;AAAA,IAC3D,CAAC;AAAA,IACD,YAAY,KAAK;AAAA,IACjB,YAAY;AAAA,MACV;AAAA,QACE,MAAM,KAAK;AAAA,QACX,eAAe,KAAK;AAAA,QACpB,WAAW,KAAK,oBAAoB,CAAC,KAAK,iBAAiB,IAAI,CAAA;AAAA,MAAC;AAAA,IAClE;AAAA,EACF,CACD;AACD,SAAO;AACT;AAmBA,SAAS,oBAAoB,KAA+B;AAC1D,QAAM,QAAQ,IAAI,cAAA;AAClB,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,MAAM,SAAS,CAAC,EAAE,kBAAkB;AACnD;AAOO,SAAS,iBACd,KACA,MACS;AACT,MAAI,IAAI,YAAY,KAAK,IAAI,EAAG,QAAO;AACvC,MAAI,eAAe,oBAAoB,GAAG,GAAG;AAAA,IAC3C,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,YAAY,CAAC,CAAC,KAAK;AAAA,IACnB,OAAO,KAAK,QAAQ,UAAU,KAAK,KAAK,IAAI;AAAA,IAC5C,qBAAqB,KAAK,cAAc,QAAQ,CAAC,CAAC,KAAK;AAAA,EAAA,CACxD;AACD,SAAO;AACT;AAmBA,MAAM,YAAY;AAAA,EAChB,SAAS,MAAM;AAAA,EACf,WAAW,MAAM;AAAA,EACjB,QAAQ,MAAM;AAChB;AAMO,SAAS,qBACd,KACA,MACS;AACT,MAAI,IAAI,YAAY,KAAK,IAAI,EAAG,QAAO;AACvC,MAAI,eAAe,oBAAoB,GAAG,GAAG;AAAA,IAC3C,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,OAAO,KAAK,QAAQ,UAAU,KAAK,KAAK,IAAI;AAAA,IAC5C,qBAAqB,KAAK,cAAc,QAAQ,CAAC,CAAC,KAAK;AAAA,IACvD,YAAY;AAAA,MACV,KAAK,QAAQ,CAAC,KAAK,oBACf,EAAE,MAAM,KAAK,kBACb;AAAA,QACE,MAAM,KAAK;AAAA,QACX,WAAW,KAAK,oBAAoB,CAAC,KAAK,iBAAiB,IAAI,CAAA;AAAA,MAAC;AAAA,IAClE;AAAA,EACN,CACD;AACD,SAAO;AACT;AAeO,SAAS,UAAU,KAAuB,MAA2B;AAC1E,MAAI,IAAI,eAAe,KAAK,IAAI,EAAG,QAAO;AAC1C,QAAM,OAAO,IAAI,gBAAA,EAAkB,CAAC;AACpC,QAAM,QAAQ,OAAO,KAAK,kBAAkB,IAAI,oBAAoB,GAAG;AACvE,MAAI,kBAAkB,OAAO;AAAA,IAC3B,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,IACjB,YACE,KAAK,cAAc;AAAA,EAAA,CACtB;AACD,SAAO;AACT;ACjnBA,MAAM,kBAAkB,CAAC,OAAO,OAAO,QAAQ,UAAU,OAAO;AAuBhE,MAAMC,sBAAoB;AAgBnB,SAAS,mBACd,WACA,OACA,UACuB;AACvB,QAAM,UAAU;AAAA,IACd,UAAU;AAAA,IACV,MAAM;AAAA,IACN;AAAA,EAAA;AAEF,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,sBAAsB,MAAM,YAAY,EAAE;AAAA,EAC5D;AACA,QAAM,aAAa,QAAQ,cAAc,KAAK,KAAK,QAAQ,MAAM,KAAK;AAEtE,QAAM,UAAiC,CAAA;AACvC,aAAW,QAAQ,UAAU,UAAU,UAAU,GAAG;AAClD,UAAM,QAAQ,KAAK,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AAC3C,UAAM,QAAQA,oBAAkB,KAAK,KAAK;AAC1C,QAAI,CAAC,MAAO;AACZ,UAAM,CAAA,EAAG,KAAK,OAAO,IAAI;AACzB,QAAI,MAAM,OAAO,QAAQ,MAAM,IAAK;AACpC,QAAI,MAAM,WAAW,YAAY,MAAM,QAAS;AAEhD,UAAM,cAAc,MAAM,QAAQ,gBAAgB,cAAc;AAChE,QAAI,CAAC,UAAU,OAAO,WAAW,EAAG;AAEpC,YAAQ,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB,YAAY,eAAe,WAAW,WAAW,KAAK,CAAA;AAAA,IAAC,CACxD;AAAA,EACH;AACA,SAAO,QAAQ;AAAA,IACb,CAAC,GAAG,MAAM,EAAE,IAAI,cAAc,EAAE,GAAG,KAAK,EAAE,QAAQ,cAAc,EAAE,OAAO;AAAA,EAAA;AAE7E;AAaO,SAAS,4BACd,WACA,mBAC2B;AAC3B,QAAM,aAAa,kBAAkB,SAAS,KAAK,IAC/C,oBACA,GAAG,iBAAiB;AACxB,QAAM,QAAQ,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AACjD,QAAM,cAAc,MAAM,QAAQ,gBAAgB,cAAc;AAEhE,aAAW,aAAa,CAAC,aAAa,KAAK,GAAG;AAC5C,QAAI,CAAC,UAAU,OAAO,SAAS,EAAG;AAClC,UAAM,aAAa,eAAe,WAAW,SAAS;AACtD,QAAI,WAAY,QAAO;AAAA,EACzB;AACA,SAAO;AACT;AAGA,SAAS,eACP,WACA,aAC2B;AAC3B,SAAO,eAAe,WAAW,aAAa,CAAC,OAAO;AACpD,UAAM,QAAQ,GAAG,aAAa,OAAO;AACrC,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,aAAiC,CAAA;AACvC,eAAW,YAAY,MAAM,iBAAiB;AAC5C,YAAM,cAAc,QAAQ,SAAS,QAAA,CAAS;AAC9C,YAAM,UAAU,SAAS,YAAA;AAGzB,UAAI,CAAC,WAAW,EAAE,mBAAmB,SAAU;AAE/C,iBAAW,cAAe,QAAgB,iBAAiB;AACzD,cAAM,SAAS,WAAW,QAAA;AAC1B,YAAI,CAAC,gBAAgB,MAAM,EAAG;AAC9B,cAAM,WAAmB,WAAW,YAAA,GAAe,aAAa;AAEhE,YAAI,WAAW,sBAAsB,aAAa,QAAS;AAE3D,mBAAW,KAAK;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,SAAS,YAAY,UAAU;AAAA,UAC/B,YAAY,CAAC,GAAG,YAAY,SAAS,cAAc,CAAC,EAAE;AAAA,YACpD,CAAC,MAAM,EAAE,CAAC;AAAA,UAAA;AAAA,QACZ,CACD;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,gBAAgB,OAAuC;AAC9D,SAAQ,gBAAsC,SAAS,KAAK;AAC9D;AAGA,SAAS,YAAY,YAEE;AACrB,QAAM,OAAO,WACV,wBAAA,EACA,IAAI,CAAC,MAAM,EAAE,QAAA,CAAS,EACtB,KAAK,GAAG,EACR,QAAQ,UAAU,EAAE,EACpB,QAAQ,UAAU,EAAE,EACpB,QAAQ,eAAe,EAAE,EACzB,QAAQ,QAAQ,GAAG,EACnB,KAAA;AACH,SAAO,QAAQ;AACjB;AAEA,SAAS,QAAQ,MAAsB;AACrC,SAAO,KAAK,QAAQ,gBAAgB,EAAE;AACxC;ACjLO,SAAS,mBACd,WACA,WACA,YACM;AACN,QAAM,aAAa,kBAAkB,UAAU;AAC/C,QAAM,UAAU,UAAU,KAAK,SAAS,KAAK;AAC7C,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,MAAI,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,UAAU,CAAC,GAAG;AACnD;AAAA,EACF;AAEA,QAAM,KAAK,UAAU;AACrB,YAAU,MAAM,WAAW,MAAM,KAAK,IAAI,CAAC;AAC7C;ACZO,SAAS,iBACd,WACA,WACA,WACM;AACN,QAAM,SAAS,iBAAA;AAEf,MAAI,CAAC,UAAW;AAEhB,QAAM,UAAU,UAAU,KAAK,SAAS;AACxC,MAAI,YAAY,MAAM;AACpB,WAAO,KAAK,yBAAyB,SAAS,EAAE;AAChD;AAAA,EACF;AAEA,SAAO,KAAK,YAAY,SAAS,wBAAwB,SAAS,EAAE;AAEpE,QAAM,aAAa,GAAG;AAAA,IACpB;AAAA,IACA;AAAA,IACA,GAAG,aAAa;AAAA,IAChB;AAAA,EAAA;AAKF,QAAM,kBAAkB,WAAW,WAAW;AAAA,IAC5C,CAAC,OACC,GAAG,oBAAoB,EAAE,KACzB,GAAG,oBAAoB,UACvB,GAAG,gBAAgB,GAAG,eAAe,KACrC,GAAG,gBAAgB,SAAS,KAAK,SAAS;AAAA,EAAA;AAE9C,MAAI,iBAAiB;AACnB,WAAO,KAAK,cAAc,SAAS,uBAAuB,SAAS,EAAE;AACrE;AAAA,EACF;AAEA,QAAM,oBAAoB,GAAG,QAAQ;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,QAAQ,oBAAoB,KAAK,SAAS,EAAE;AAAA,EAAA;AAGjD,QAAM,oBAAoB,GAAG,QAAQ,iBAAiB,YAAY;AAAA,IAChE,GAAG,WAAW;AAAA,IACd;AAAA,EAAA,CACD;AAED,QAAM,UAAU,GAAG,cAAc,EAAE,SAAS,GAAG,YAAY,UAAU;AACrE,QAAM,cAAc,QAAQ,UAAU,iBAAiB;AAEvD,YAAU,MAAM,WAAW,WAAW;AACxC;ACxCO,SAAS,uBACd,WACA,aACA,SACA,UACM;AACN,QAAM,SAAS,iBAAA;AAEf,QAAM,aAAa,mBAAmB;AAAA,IACpC,oBAAoB,QAAQ;AAAA,IAC5B,WAAW,QAAQ;AAAA,EAAA,CACpB;AAED,QAAM,0BAA0B;AAAA,IAC9B;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EAAA;AAGF,QAAM,gBAAgB;AAAA,IACpB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EAAA;AAEF,QAAM,eAAe;AAAA,IACnB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EAAA;AAGF,QAAM,cAAc,cAAc;AAClC,MAAI,CAAC,aAAa;AAChB,WAAO,KAAK,+CAA+C;AAC3D;AAAA,EACF;AAEA,MAAI,aAAa;AACjB,MAAI,eAAe;AACjB,UAAM,cAAc,KAAK,KAAK,cAAc,MAAM,cAAc;AAChE,QAAI;AACF,YAAM,UAAU,SAA2B,WAAW,WAAW;AACjE,mBAAa,QAAQ,QAAQ;AAAA,IAC/B,QAAQ;AACN,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,QAAM,gBACJ,yBAAyB,WAAW,UAAU,OAAO,UAAU;AACjE,QAAM,WAAW,KAAK;AAAA,IACpB;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EAAA;AAGb,SAAO,KAAK,iCAAiC,QAAQ,EAAE;AACvD,6BAA2B,WAAW,aAAa,UAAU;AAAA,IAC3D,GAAG;AAAA,IACH,GAAG;AAAA,IACH;AAAA,EAAA,CACD;AACH;ACzCO,SAAS,uBACd,WACA,aACA,SACA,KACA,UACM;AACN,QAAM,SAAS,iBAAA;AAEf,QAAM,iBAAiB,WAAW,WAAW,GAAG;AAChD,QAAM,mBAAmB,QAAQ,gBAAgB,gBAAgB;AACjE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,YAAY,QAAQ,aAAa,wBAAwB,GAAG;AAClE,MAAI,CAAC,WAAW;AACd,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,UAAQ,YAAY;AACpB,UAAQ,OAAO,GAAG,SAAS;AAE3B,QAAM,aAAa,iBAAiB,WAAW,SAAS,QAAQ;AAChE,QAAM,gBAAgB;AAAA,IACpB,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EAAA;AAEF,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,kBAAkB,WAAW,YAAY,aAAa;AAAA,EACxE;AAEA,2BAAyB;AAAA,IACvB;AAAA,IACA,WAAW,WAAW;AAAA,IACtB,aAAa,cAAc;AAAA,IAC3B,aAAa,cAAc;AAAA,IAC3B,WAAW,CAAC,CAAC,QAAQ;AAAA,IACrB,WAAW;AAAA;AAAA,IAEX,SAAS,WAAW;AAAA,EAAA,CACrB;AAED,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EAAA;AAEF,QAAM,gBAAgB,WAAW,WAAW,UAAU,OAAO,UAAU;AACvE,QAAM,WAAW,CAAC,CAAC,WAAW,WAAW;AACzC,UAAQ,iBAAiB,QAAQ,kBAAkB;AAEnD,QAAM,cAAc,cAAc;AAClC,MAAI,aAAa;AACf,WAAO;AAAA,MACL,8BAA8B,WAAW,YAAY,OAAO,WAAW;AAAA,IAAA;AAGzE,UAAM,oBACH,WAAmB,qBAAqB,WAAW;AAEtD,UAAM,cAAc,KAAK;AAAA,MACvB;AAAA,MACA,QAAQ,kBAAkB;AAAA,MAC1B;AAAA,IAAA;AAGF,QAAI,QAAQ,eAAe;AACzB,wCAAkC,WAAW,aAAa,aAAa;AAAA,QACrE,GAAG;AAAA,QACH;AAAA,MAAA,CACD;AAAA,IACH,OAAO;AACL;AAAA,QACE;AAAA,QACA,KAAK,KAAK,aAAa,OAAO;AAAA,QAC9B;AAAA,QACA,EAAE,GAAG,YAAY,SAAA;AAAA,MAAS;AAAA,IAE9B;AAEA,UAAM,aAAa,KAAK,KAAK,aAAa,UAAU;AACpD,UAAM,YAAY,WAAW,iBACzB,GAAG,WAAW,cAAc,IAAI,iBAAiB,KACjD;AACJ,qBAAiB,WAAW,YAAY,SAAS;AAAA,EACnD;AACF;AAWA,SAAS,kCACP,WACA,aACA,aACA,eACM;AACN,QAAM,oBAAoB,GAAG,cAAc,YAAY;AACvD,QAAM,oBAAoB,KAAK;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,QAAM,WAAW,IAAI;AAAA,IACnB,GAAG,aAAa,mBAAmB,OAAO;AAAA,IAC1C;AAAA,IACA,EAAE,UAAU,kBAAA;AAAA,EAAkB;AAEhC,YAAU,MAAM,KAAK,KAAK,aAAa,iBAAiB,GAAG,QAAQ;AAEnE,QAAM,YAAY,KAAK,KAAK,aAAa,SAAS,YAAY;AAC9D,MAAI,UAAU,KAAK,SAAS,MAAM,MAAM;AACtC,cAAU,MAAM,WAAW,EAAE;AAAA,EAC/B;AACA,sBAAoB,WAAW,WAAW,CAAC,eAAe;AACxD;AAAA,MACE;AAAA,MACA,GAAG,cAAc,cAAc;AAAA,IAAA;AAAA,EAEnC,CAAC;AAED,QAAM,aAAa,KAAK,KAAK,aAAa,UAAU;AACpD,MAAI,UAAU,KAAK,UAAU,MAAM,MAAM;AACvC,cAAU,MAAM,YAAY,EAAE;AAAA,EAChC;AACA,sBAAoB,WAAW,YAAY,CAAC,eAAe;AACzD,UAAM,kBAAkB,KAAK,kBAAkB,QAAQ,SAAS,EAAE,CAAC;AACnE,uBAAmB,YAAY,iBAAiB;AAAA,MAC9C,cAAc;AAAA,IAAA,CACf;AACD;AAAA,MACE;AAAA,MACA;AAAA,MACA,CAAC,GAAG,cAAc,cAAc,OAAO;AAAA,MACvC;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH;ACpKO,SAAS,gBACd,WACA,aACA,SACA,KACA,UACM;AACN,MAAI,CAAC,QAAQ,YAAY;AACvB,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,QAAM,iBAAiB,WAAW,WAAW,GAAG;AAChD,QAAM,mBAAmB,QAAQ,gBAAgB,gBAAgB;AACjE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,YAAY,QAAQ,QAAQ,wBAAwB,GAAG;AAC7D,MAAI,CAAC,WAAW;AACd,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,gBAAgB,sBAAsB;AAAA,IAC1C;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EAAA,CACD;AACD,UAAQ,YAAY,CAAC,CAAC;AACtB,UAAQ,OAAO;AACf,UAAQ,eAAe;AAEvB,QAAM,aAAa,iBAAiB,WAAW,SAAS,QAAQ;AAChE,QAAM,aAAa;AAAA,IACjB,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EAAA;AAEF,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,gBAAgB,WAAW,UAAU,aAAa;AAAA,EACpE;AAEA,QAAM,cAAc,WAAW;AAC/B,MAAI,aAAa;AACf,UAAM,MACJ,WAAW,gBAAgB,iBAAiB,QAAQ,WAChD,QAAQ,eACR,QAAQ,gBAAgB;AAE9B;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,KAAK,aAAa,KAAK,YAAY,WAAW,YAAY;AAAA,MAC/D;AAAA,IAAA;AAGF;AAAA,MACE;AAAA,MACA,KAAK,KAAK,aAAa,KAAK,YAAY,UAAU;AAAA,MAClD,KAAK,WAAW,YAAY;AAAA,IAAA;AAAA,EAEhC;AACF;AClEO,SAAS,aACd,WACA,aACA,SACA,KACA,UACM;AACN,MAAI,CAAC,QAAQ,YAAY;AACvB,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,QAAM,iBAAiB,WAAW,WAAW,GAAG;AAChD,QAAM,mBAAmB,QAAQ,gBAAgB,gBAAgB;AACjE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,YAAY,QAAQ,QAAQ,wBAAwB,GAAG;AAC7D,MAAI,CAAC,WAAW;AACd,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ,YAAY,iBAAiB,CAAC,CAAC,eAAe,YAAY;AAClE,UAAQ,OAAO;AACf,UAAQ,eAAe;AAEvB,QAAM,aAAa,iBAAiB,WAAW,SAAS,QAAQ;AAChE,QAAM,aAAa;AAAA,IACjB,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EAAA;AAEF,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,gBAAgB,WAAW,UAAU,aAAa;AAAA,EACpE;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,WAAW;AAAA,IACX;AAAA,EAAA;AAEF,QAAM,oBACJ,WAAW,WAAW,UAAU,WAAW,UAAU;AACvD,UAAQ,eAAe,QAAQ,gBAAgB;AAE/C,QAAM,cAAc,WAAW;AAC/B,MAAI,aAAa;AACf;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,IAAA;AAGF;AAAA,MACE;AAAA,MACA,KAAK,KAAK,aAAa,QAAQ,cAAc,SAAS,UAAU;AAAA,MAChE,KAAK,WAAW,YAAY;AAAA,IAAA;AAAA,EAEhC;AACF;AC7DO,SAAS,cAAc,QAAmC;AAC/D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AACJ,QAAM,SAAS,iBAAA;AAEf,QAAM,iBAAiB,WAAW,WAAW,GAAG;AAChD,QAAM,mBAAmB,QAAQ,gBAAgB,gBAAgB;AACjE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,UAAQ,eAAe;AACvB,QAAM,aAAa,iBAAiB,WAAW,SAAS,QAAQ;AAChE,QAAM,gBAAgB;AAAA,IACpB,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EAAA;AAEF,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,kBAAkB,WAAW,YAAY,aAAa;AAAA,EACxE;AAEA,QAAM,cAAc,cAAc;AAClC,MAAI,CAAC,YAAa;AAElB,QAAM,gBAAgB,KAAK,KAAK,cAAc,MAAM,WAAW;AAC/D,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EAAA;AAEF,QAAM,gBAAgB,WAAW,WAAW,UAAU,OAAO,UAAU;AACvE,QAAM,WAAW,CAAC,CAAC,WAAW,WAAW;AACzC,UAAQ,iBAAiB,QAAQ,kBAAkB;AAEnD,SAAO,KAAK,oBAAoB,WAAW,YAAY,OAAO,WAAW,EAAE;AAE3E;AAAA,IACE;AAAA,IACA,KAAK,KAAK,kBAAkB,OAAO;AAAA,IACnC,KAAK,KAAK,aAAa,QAAQ,gBAAgB,WAAW,YAAY;AAAA,IACtE,EAAE,GAAG,YAAY,SAAA;AAAA,EAAS;AAG5B,QAAM,aAAa,KAAK,KAAK,aAAa,UAAU;AACpD,QAAM,YAAY,QAAQ,iBACtB,GAAG,QAAQ,cAAc,IAAI,WAAW,YAAY,KACpD,WAAW;AACf,mBAAiB,WAAW,YAAY,SAAS;AAOjD,QAAM,eAAe,WAAW,YAC5B,GAAG,WAAW,YAAY,eAC1B;AACJ,aAAW,WAAW,eAAe,CAAC,SAAc;AAClD,UAAM,WAAW,KAAK,SAAS,WAAW,IAAI,KAAK,CAAA;AACnD,UAAM,YAAY,eACd,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAI,SAAS,aAAa,CAAA,GAAK,YAAY,CAAC,CAAC,IAC1D,SAAS;AACb,SAAK,SAAS;AAAA,MACZ,GAAG,KAAK;AAAA,MACR,CAAC,WAAW,IAAI,GAAG;AAAA,QACjB,GAAG;AAAA,QACH,MAAM,WAAW;AAAA,QACjB,MAAM,GAAG,WAAW,YAAY;AAAA,QAChC,WAAW,CAAC,CAAC,WAAW;AAAA,QACxB,SAAS,WAAW;AAAA,QACpB,GAAI,WAAW,UAAU,EAAE,SAAS,WAAW,QAAA,IAAY,CAAA;AAAA,QAC3D,GAAI,WAAW,SAAS,EAAE,cAAc,CAAA;AAAA,MAAC;AAAA,IAC3C;AAEF,WAAO;AAAA,EACT,CAAC;AAED,MAAI,WAAW,aAAa,sBAAsB;AAChD,WAAO,KAAK,4BAA4B,WAAW,IAAI,EAAE;AACzD;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE,GAAG;AAAA,QACH,MAAM,GAAG,WAAW,IAAI;AAAA,QACxB,WAAW,WAAW;AAAA,QACtB,WAAW,WAAW;AAAA,MAAA;AAAA,MAExB;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAEA,MACE,WAAW,aACX,WAAW,kBACX,WAAW,yBACX,sBACA;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE,oBAAoB,WAAW;AAAA,QAC/B,uBAAuB,WAAW;AAAA,QAClC,WAAW,WAAW;AAAA,QACtB,cAAc,WAAW;AAAA,QACzB,kBAAkB,WAAW;AAAA,MAAA;AAAA,MAE/B;AAAA,IAAA;AAAA,EAEJ;AACF;AC3KA,MAAM,qBAAqB;AAGpB,SAAS,yBACd,WACA,YACA,SACe;AACf,QAAM,SAAS,IAAI,IAAI,QAAQ,OAAO,OAAO,CAAC;AAC9C,MAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,QAAM,UAAoB,CAAA;AAC1B,aAAW,YAAY,UAAU,UAAU,UAAU,GAAG;AACtD,QAAI,CAAC,SAAS,SAAS,KAAK,KAAK,SAAS,SAAS,OAAO,EAAG;AAC7D,UAAM,UAAU,UAAU,KAAK,QAAQ;AACvC,QAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,kBAAkB,EAAG;AAEvD,UAAM,WAAW,sBAAsB,WAAW,QAAQ;AAC1D,QAAI,YAAY,OAAO,IAAI,QAAQ,EAAG,SAAQ,KAAK,QAAQ;AAAA,EAC7D;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,eAAe,CAAC,GAAG,MAAM,EAAE,KAAK,OAAO,CAAC;AAAA,IACtC,QACG,OACA,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EACrB,KAAK,IAAI,IACZ;AAAA;AAAA,IAAA;AAAA,EAEN;AACA,SAAO,QAAQ,CAAC;AAClB;AAGA,SAAS,sBACP,WACA,UACoB;AACpB,MAAI;AACF,WAAO,eAAe,WAAW,UAAU,CAAC,OAAO;AACjD,YAAM,MAAM,GAAG,aAAa,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,CAAC;AAClE,UAAI,CAAC,IAAK,QAAO;AAEjB,YAAM,SAAS,oBAAoB,IAAI,KAAK,UAAU;AACtD,YAAM,QAAQ,QAAQ,WAAW,GAAG,IAChC,oBAAoB,MAAM,IAC1B;AACJ,UAAI,CAAC,MAAO,QAAO;AAEnB,aAAO,uBAAuB,MAAM,KAAA,GAAQ,GAAG,aAAa;AAAA,IAC9D,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,oBAAoB,YAAwC;AACnE,QAAM,IAAI,WAAW,MAAM,8BAA8B;AACzD,SAAO,IAAI,EAAE,CAAC,IAAI;AACpB;AAGA,SAAS,uBACP,YACA,UACoB;AACpB,QAAM,UAAU,WAAW,MAAM,kBAAkB;AACnD,MAAI,QAAS,QAAO,QAAQ,CAAC;AAE7B,MAAI,CAAC,qBAAqB,KAAK,UAAU,EAAG,QAAO;AACnD,QAAM,WAAW,SAAS;AAAA,IACxB,IAAI,OAAO,2BAA2B,UAAU,4CAA4C;AAAA,EAAA;AAE9F,SAAO,WAAW,SAAS,CAAC,IAAI;AAClC;AC3DO,SAAS,qBACd,WACA,OACA,UACmE;AACnE,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EAAA;AAEF,QAAM,WAAW,CAAC,CAAC,WAAW,WAAW;AAEzC,QAAM,UAAU;AAAA,IACd,UAAU;AAAA,IACV,MAAM;AAAA,IACN;AAAA,EAAA;AAEF,QAAM,aAAa,UACf,QAAQ,cAAc,KAAK,KAAK,QAAQ,MAAM,KAAK,IACnD;AAEJ,MAAI,MAAM,WAAW;AACnB,WAAO,EAAE,eAAe,MAAM,WAAW,UAAU,WAAA;AAAA,EACrD;AAEA,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR,sBAAsB,MAAM,YAAY;AAAA,IAAA;AAAA,EAE5C;AACA,QAAM,EAAE,kBAAA,IAAsB,mBAAmB;AAAA,IAC/C,WAAW,MAAM;AAAA,EAAA,CAClB;AACD,QAAM,gBAAgB,WAAW,WAAW,UAAU,OAAO,UAAU;AACvE,QAAM,gBAAgB,KAAK;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,iBAAiB;AAAA,EAAA;AAEtB,MAAI,UAAU,OAAO,aAAa,GAAG;AACnC,WAAO,EAAE,eAAe,UAAU,WAAA;AAAA,EACpC;AAEA,QAAM,aAAa,KAAK,KAAK,YAAsB,aAAa;AAChE,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,YAAY;AACd,WAAO,EAAE,eAAe,YAAY,UAAU,WAAA;AAAA,EAChD;AAGA,QAAM,eAAe,WAAW,SAAS,MAAM,SAAS,GAAG;AAC3D,QAAM,gBAAgB,yBAAyB,WAAW,YAAY;AAAA,IACpE,MAAM;AAAA,IACN,GAAI,eAAe,CAAC,YAAY,IAAI,CAAA;AAAA,EAAC,CACtC;AACD,MAAI,eAAe;AACjB,WAAO,EAAE,eAAe,eAAe,UAAU,WAAA;AAAA,EACnD;AAEA,SAAO,EAAE,eAAe,UAAU,WAAA;AACpC;AAQA,SAAS,oBACP,WACA,YACA,mBACe;AACf,QAAM,WAAW,GAAG,iBAAiB;AACrC,QAAM,aAAa,UAChB,UAAU,UAAU,EACpB,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,QAAQ,EAC3C,KAAA;AACH,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,IAAI;AAAA,MACR,eAAe,iBAAiB,yCAAyC,QAAQ;AAAA,IAC/E,WAAW,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,IAC3C;AAAA;AAAA,IAAA;AAAA,EAEN;AACA,SAAO,WAAW,CAAC;AACrB;ACrFO,SAAS,sBACd,WACA,OACA,UACiD;AACjD,QAAM,eAAe,MAAM,qBAAqB,MAAM;AACtD,QAAM,YAAY,GAAG,WAAW,MAAM,UAAU,CAAC;AAEjD,MAAI,iBAAiB,MAAM,cAAc;AACvC,UAAM,UAAU,kBAAkB,UAAU,MAAM,cAAc,QAAQ;AACxE,UAAM,UAAU,UACZ;AAAA,MACE;AAAA,MACA,KAAK,KAAK,QAAQ,MAAM,cAAc;AAAA,IAAA,IAExC;AACJ,WAAO,EAAE,WAAW,iBAAiB,SAAS,KAAA;AAAA,EAChD;AAEA,QAAM,EAAE,eAAe,cAAA,IAAkB;AAAA,IACvC;AAAA,IACA,EAAE,WAAW,MAAM,YAAY,cAAc,aAAA;AAAA,IAC7C;AAAA,EAAA;AAEF,QAAM,WAAW,KACd,SAAS,KAAK,QAAQ,MAAM,aAAa,GAAG,aAAa,EACzD,QAAQ,SAAS,EAAE;AACtB,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,SAAS,WAAW,GAAG,IAAI,WAAW,KAAK,QAAQ;AAAA,EAAA;AAExE;ACLO,SAAS,kBACd,WACA,aACA,SACA,KACA,UACiB;AACjB,QAAM,SAAS,iBAAA;AAEf,MAAI,CAAC,QAAQ,MAAM;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,iBAAiB,WAAW,WAAW,GAAG;AAChD,QAAM,mBAAmB,QAAQ,gBAAgB,gBAAgB;AACjE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,EAAE,GAAG,SAAS,cAAc,iBAAA;AAAA,IAC5B;AAAA,EAAA;AAEF,QAAM,gBAAgB;AAAA,IACpB,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,kBAAkB,gBAAgB,aAAa;AAAA,EACjE;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EAAA;AAEF,QAAM,iBACJ,QAAQ,kBACR,WAAW,WAAW,UAAU,OAAO,UACvC;AACF,QAAM,WAAW,CAAC,CAAC,WAAW,WAAW;AAEzC,QAAM,cACJ,cAAc,cAAc,KAAK,KAAK,cAAc,MAAM,KAAK;AACjE,QAAM,kBAAkB,KAAK;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EAAA;AAEb,QAAM,oBAAoB,KAAK;AAAA,IAC7B;AAAA,IACA,GAAG,WAAW,YAAY;AAAA,EAAA;AAI5B,MAAI,UAAU,OAAO,iBAAiB,GAAG;AACvC,WAAO,KAAK,6BAA6B,iBAAiB,EAAE;AAC5D,WAAO,EAAE,mBAAmB,SAAS,MAAA;AAAA,EACvC;AAEA,QAAM,YAAY,QAAQ,UAAU,CAAA,GAAI;AAAA,IAAI,CAAC,WAC3C;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAGF,SAAO;AAAA,IACL,wBAAwB,WAAW,YAAY,OAAO,WAAW;AAAA,EAAA;AAGnE,QAAM,oBAAoB,SAAS,IAAI,CAAC,EAAE,MAAM,KAAA,OAAY,EAAE,MAAM,KAAA,EAAO;AAC3E,6BAA2B,WAAW,aAAa,iBAAiB;AAAA,IAClE,GAAG;AAAA,IACH;AAAA,IACA,QAAQ,QAAQ,UAAU,WAAW;AAAA,IACrC,iBAAiB,CAAC,CAAC,QAAQ;AAAA,IAC3B;AAAA,IACA,iBAAiB,kBAAkB,IAAI,CAAC,UAAU,MAAM,IAAI,EAAE,KAAK,IAAI;AAAA,IACvE,cAAc,aAAa,QAAQ;AAAA,EAAA,CACpC;AAED;AAAA,IACE;AAAA,IACA,KAAK,KAAK,aAAa,UAAU;AAAA,IACjC,iBACI,GAAG,cAAc,IAAI,WAAW,YAAY,KAC5C,WAAW;AAAA,EAAA;AAGjB,SAAO,EAAE,mBAAmB,SAAS,KAAA;AACvC;AAGA,SAAS,mBACP,WACA,QACA,mBACA,cACA,UACe;AACf,QAAM,gBAAgB,OAAO,WAAW;AAExC,MAAI,kBAAkB,cAAc;AAClC,UAAM,EAAE,kBAAkB;AAAA,MACxB;AAAA,MACA,EAAE,WAAW,OAAO,OAAO,cAAc,cAAA;AAAA,MACzC;AAAA,IAAA;AAEF,QAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,UAAU,OAAO,KAAK,2BAA2B,aAAa,iBAAiB,aAAa;AAAA,MAAA;AAAA,IAEhG;AAAA,EACF,WAAW,CAAC,kBAAkB,UAAU,MAAM,eAAe,QAAQ,GAAG;AACtE,UAAM,IAAI,MAAM,kBAAkB,aAAa,aAAa;AAAA,EAC9D;AAEA,QAAM,EAAE,WAAW,gBAAA,IAAoB;AAAA,IACrC;AAAA,IACA;AAAA,MACE,eAAe;AAAA,MACf;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,mBAAmB;AAAA,IAAA;AAAA,IAErB;AAAA,EAAA;AAGF,SAAO;AAAA,IACL,MAAM,UAAU,OAAO,KAAK;AAAA,IAC5B,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAEZ;AAGA,SAAS,aACP,UACuC;AACvC,QAAM,+BAAe,IAAA;AACrB,aAAW,EAAE,MAAM,OAAA,KAAY,UAAU;AACvC,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,SAAS,IAAI,MAAM;AACjC,QAAI,CAAC,OAAO;AACV,eAAS,IAAI,QAAQ,CAAC,IAAI,CAAC;AAAA,IAC7B,WAAW,CAAC,MAAM,SAAS,IAAI,GAAG;AAChC,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO,CAAC,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,QAAQ,QAAQ;AACnE;ACzMO,SAAS,cACd,eACA,WACQ;AACR,QAAM,OAAO,KAAK,SAAS,aAAa;AACxC,QAAM,QAAQ,KAAK,MAAM,kBAAkB;AAC3C,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC5B;AAGO,SAAS,oBACd,eACA,WACQ;AACR,SAAO,KAAK;AAAA,IACV,KAAK,QAAQ,aAAa;AAAA,IAC1B;AAAA,IACA,GAAG,SAAS;AAAA,EAAA;AAEhB;AAEA,SAASC,SAAO,WAA2B;AACzC,SAAO;AAAA,2BACkB,SAAS;AAAA;AAAA;AAAA;AAAA;AAKpC;AAMO,SAAS,qBACd,WACA,eACA,WACQ;AACR,QAAM,mBAAmB,oBAAoB,eAAe,SAAS;AACrE,MAAI,CAAC,UAAU,OAAO,gBAAgB,GAAG;AACvC,cAAU,MAAM,kBAAkBA,SAAO,SAAS,CAAC;AAAA,EACrD;AAEA,QAAM,aAAa,KAAK,KAAK,KAAK,QAAQ,gBAAgB,GAAG,UAAU;AACvE,MAAI,CAAC,UAAU,OAAO,UAAU,GAAG;AACjC,cAAU,MAAM,YAAY,EAAE;AAAA,EAChC;AACA,sBAAoB,WAAW,YAAY,CAAC,OAAO;AACjD,uBAAmB,IAAI,KAAK,SAAS,WAAW;AAAA,EAClD,CAAC;AAED,SAAO;AACT;AC9CO,SAAS,0BACd,WACA,SACA,UACmC;AACnC,QAAM,uBAAuB;AAAA,IAC3B,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EAAA;AAGF,MAAI,CAAC,sBAAsB;AACzB,UAAM,IAAI;AAAA,MACR,sBAAsB,QAAQ,YAAY;AAAA,IAAA;AAAA,EAE9C;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EAAA;AAEF,QAAM,WAAW,CAAC,CAAC,WAAW,WAAW;AAGzC,QAAM,mBAAmB,mBAAmB;AAAA,IAC1C,WAAW,QAAQ;AAAA,EAAA,CACpB;AAED,QAAM,eAAe,iBAAiB;AACtC,QAAM,iBAAiB,iBAAiB;AACxC,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,iBAAiB,iBAAiB;AACxC,QAAM,mBAAmB,iBAAiB;AAC1C,QAAM,gBAAgB,iBAAiB;AAEvC,QAAM,cAAc,qBAAqB;AACzC,QAAM,aACJ,qBAAqB,cAAc,KAAK,KAAK,aAAa,KAAK;AAIjE,QAAM,EAAE,kBAAkB;AAAA,IACxB;AAAA,IACA,EAAE,WAAW,QAAQ,WAAW,cAAc,QAAQ,aAAA;AAAA,IACtD;AAAA,EAAA;AAEF,QAAM,iBAAiB,KAAK,QAAQ,aAAa;AAIjD,QAAM,mBAAmB,oBAAoB,eAAe,YAAY;AAGxE,QAAM,uBAAuB,KAAK;AAAA,IAChC;AAAA,IACA,GAAG,YAAY;AAAA,EAAA;AAGjB,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAsB,UAAU,OAAO,oBAAoB,IACvD,uBACA;AAAA,IACJ;AAAA,EAAA;AAEJ;ACzEA,MAAM,qCAAqB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,MAAM,wCAAwB,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,MAAM,qBAAqB;AAAA,EAChC,YACU,WACA,SACR;AAFQ,SAAA,YAAA;AACA,SAAA,UAAA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGV,IAAY,eAAuB;AACjC,UAAM,EAAE,gBAAgB,eAAA,IAAmB,KAAK;AAChD,WAAO,iBACH,GAAG,cAAc,sBACjB;AAAA,EACN;AAAA,EAEA,YAAkB;AAChB,UAAM,EAAE,kBAAkB,KAAK;AAE/B,QAAI,CAAC,KAAK,UAAU,OAAO,aAAa,GAAG;AACzC,YAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,IAC1D;AAEA,wBAAoB,KAAK,WAAW,eAAe,CAAC,OAAO;AACzD,WAAK,oBAAoB,EAAE;AAC3B,WAAK,WAAW,EAAE;AAElB,YAAM,MAAM,cAAc,IAAI,GAAG,KAAK,QAAQ,cAAc,WAAW;AACvE,WAAK,yBAAyB,GAAG;AACjC,WAAK,aAAa,GAAG;AACrB,WAAK,gBAAgB,GAAG;AACxB,UAAI,KAAK,QAAQ,eAAe,YAAY;AAC1C,aAAK,wBAAwB,GAAG;AAAA,MAClC;AAEA,WAAK,iBAAiB,EAAE;AAGxB;AAAA,QACE;AAAA,QACA,GAAG,KAAK,QAAQ,cAAc;AAAA,QAC9B,GACE,KAAK,QAAQ,eAAe,aACxB,uBACA,uBACN,IAAI,KAAK,YAAY;AAAA,MAAA;AAEvB;AAAA,QACE;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAoB,IAAsB;AAChD,eAAW,QAAQ,GAAG,yBAAyB;AAC7C,iBAAW,SAAS,KAAK,mBAAmB;AAC1C,YAAI,eAAe,IAAI,MAAM,SAAS,SAAS,OAAA;AAAA,MACjD;AACA,UACE,KAAK,kBAAkB,WAAW,KAClC,CAAC,KAAK,iBAAA,KACN,CAAC,KAAK,mBAAA,GACN;AACA,aAAK,OAAA;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,WAAW,IAAsB;AACvC,UAAM,EAAE,UAAU,YAAY,gBAAgB,eAAA,IAC5C,KAAK;AACP,UAAM,aAAa,eAAe;AAClC,UAAM,UAAU,0BAA0B,EAAE;AAE5C,sBAAkB,IAAI,SAAS;AAAA,MAC7B,EAAE,MAAM,YAAA;AAAA,MACR,EAAE,MAAM,iBAAA;AAAA,MACR;AAAA,QACE,MAAM,aAAa,uBAAuB;AAAA,QAC1C,YAAY;AAAA,MAAA;AAAA,IACd,CACD;AAED,UAAM,WAAW,WACb,4CACA;AACJ,sBAAkB,IAAI,UAAU;AAAA,MAC9B,EAAE,MAAM,2BAA2B,YAAY,KAAA;AAAA,MAC/C,GAAI,aAAa,CAAC,EAAE,MAAM,gBAAgB,YAAY,KAAA,CAAM,IAAI,CAAA;AAAA,IAAC,CAClE;AAED,QAAI,gBAAgB;AAClB,wBAAkB,IAAI,cAAc;AAAA,QAClC,EAAE,MAAM,GAAG,cAAc,qBAAqB,YAAY,KAAA;AAAA,MAAK,CAChE;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,yBAAyB,KAA6B;AAC5D,eAAW,QAAQ,IAAI,mBAAmB;AACxC,iBAAW,QAAQ,KAAK,iBAAiB;AACvC,YACE,wDAAwD;AAAA,UACtD,KAAK,QAAA;AAAA,QAAQ,GAEf;AACA,eAAK,OAAA;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAEA,UAAM,gBAAgB,IAAI,YAAY,eAAe;AACrD,QACE,eAAe,YAAA,GAAe,UAAU,SAAS,sBAAsB,GACvE;AACA,oBAAc,OAAA;AAAA,IAChB;AACA,UAAM,SAAS,IAAI,YAAY,QAAQ;AACvC,QAAI,QAAQ,YAAA,GAAe,UAAU,SAAS,cAAc,GAAG;AAC7D,aAAO,OAAA;AAAA,IACT;AAEA,UAAM,QAAQ,IAAI,cAAA;AAClB,aAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC1C,YAAM,OAAO,MAAM,CAAC,EAAE,QAAA,EAAU,MAAM,GAAG,EAAE,CAAC,EAAE,KAAA;AAC9C,UAAI,kBAAkB,IAAI,IAAI,EAAG,KAAI,iBAAiB,CAAC;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,aAAa,KAA6B;AAChD,UAAM,WACJ,KAAK,QAAQ,eAAe,aAAa,KAAK;AAChD,sBAAkB,KAAK,kBAAkB,EAAE,SAAA,CAAU;AAAA,EACvD;AAAA,EAEQ,iBAAiB,IAAsB;AAC7C,UAAM,EAAE,mBAAmB,KAAK;AAChC,UAAM,QAAQ,GAAG,aAAa,GAAG,cAAc,OAAO;AACtD,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,MAAM,YAAA,GAAe,aAAa;AAC/C,QACE,CAAC,KAAK,SAAS,wBAAwB,cAAc,YAAY,KACjE,KAAK,SAAS,yBAAyB,GACvC;AACA;AAAA,IACF;AACA,UAAM;AAAA,MACJ,wBAAwB,cAAc,wCAAwC,KAAK,YAAY;AAAA,IAAA;AAAA,EAEnG;AAAA,EAEQ,gBAAgB,KAA6B;AACnD,UAAM,EAAE,mBAAmB,KAAK;AAEhC,UAAM,kBAAkB,IACrB,aACA,KAAK,CAAC,MAAM,EAAE,aAAa,WAAW,CAAC;AAC1C,QAAI,mBAAmB,IAAI,UAAU,6BAA6B,EAAG;AAErE,QAAI,UAAU;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY,CAAC,EAAE,MAAM,aAAa,WAAW,CAAA,GAAI;AAAA,MACjD,MAAM;AAAA,QACJ;AAAA,UACE,aACE;AAAA,QAAA;AAAA,MACJ;AAAA,MAEF,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,cAAc;AAAA,QACpC;AAAA,QACA,kCAAkC,cAAc;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IACF,CACD;AAAA,EACH;AAAA,EAEQ,wBAAwB,KAA6B;AAC3D,QAAI,IAAI,UAAU,gBAAgB,EAAG;AAErC,QAAI,UAAU;AAAA,MACZ,MAAM;AAAA,MACN,kBAAkB;AAAA,MAClB,YAAY;AAAA,MACZ,YAAY;AAAA,QACV,EAAE,MAAM,UAAU,MAAM,gBAAgB,KAAK,YAAY,IAAA;AAAA,MAAI;AAAA,MAE/D,MAAM;AAAA,QACJ;AAAA,UACE,aACE;AAAA,QAAA;AAAA,MACJ;AAAA,MAEF,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IACF,CACD;AAAA,EACH;AACF;AC/OA,MAAM,aAAa;AAEZ,MAAM,uBAAuB;AAAA,EAClC,YACU,WACA,SACR;AAFQ,SAAA,YAAA;AACA,SAAA,UAAA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGV,YAAkB;AAChB,UAAM,EAAE,eAAe,aAAA,IAAiB,KAAK;AAC7C,QAAI,CAAC,cAAe;AAEpB,UAAM,mBAAmB;AAAA,MACvB,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IAAA;AAGF,wBAAoB,KAAK,WAAW,kBAAkB,CAAC,OAAO;AAC5D,wBAAkB,IAAI,YAAY;AAAA,QAChC,EAAE,MAAM,SAAA;AAAA,QACR,EAAE,MAAM,kBAAkB,YAAY,KAAA;AAAA,MAAK,CAC5C;AAGD,wBAAkB,IAAI;AAAA,QACpB,MAAM;AAAA,QACN,aAAa,gCAAgC,YAAY;AAAA,MAAA,CAC1D;AACD,WAAK,mBAAmB,EAAE;AAC1B,WAAK,iBAAiB,EAAE;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEQ,mBAAmB,IAAsB;AAC/C,UAAM,EAAE,gBAAgB,cAAA,IAAkB,KAAK;AAC/C,UAAM,OAAO,UAAU,cAAc;AACrC,QAAI,GAAG,uBAAuB,IAAI,EAAG;AAErC,OAAG,qBAAqB;AAAA,MACtB,YAAY;AAAA,MACZ,iBAAiB,wBAAwB;AAAA,MACzC,cAAc;AAAA,QACZ;AAAA,UACE;AAAA,UACA,aAAa;AAAA,qCACc,aAAa;AAAA,qBAC7B,IAAI;AAAA;AAAA,QAAA;AAAA,MAEjB;AAAA,MAEF,MAAM;AAAA,QACJ;AAAA,UACE,aAAa;AAAA;AAAA,QAAA;AAAA,MACf;AAAA,IACF,CACD;AAAA,EACH;AAAA,EAEQ,iBAAiB,IAAsB;AAC7C,UAAM,EAAE,mBAAmB,KAAK;AAChC,4BAAwB,IAAI;AAAA,MAC1B,MAAM,GAAG,cAAc;AAAA,MACvB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAMP;AACD,4BAAwB,IAAI;AAAA,MAC1B,MAAM,GAAG,cAAc;AAAA,MACvB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAKP;AAAA,EACH;AACF;ACxFO,MAAM,4BAA4B;AAAA,EACvC,YACU,WACA,SACR;AAFQ,SAAA,YAAA;AACA,SAAA,UAAA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGV,YAAkB;AAChB,UAAM,SAAS,iBAAA;AACf,UAAM,EAAE,yBAAyB,KAAK;AAEtC,QAAI,CAAC,wBAAwB,CAAC,KAAK,UAAU,OAAO,oBAAoB,GAAG;AACzE,aAAO,KAAK,4DAA4D;AACxE;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,UAAU,KAAK,oBAAoB;AAEzD,QAAI,UAAU;AACd,cAAU,KAAK,YAAY,OAAO;AAClC,cAAU,KAAK,oBAAoB,OAAO;AAI1C,QAAI,YAAY,UAAU;AACxB,aAAO;AAAA,QACL;AAAA,MAAA;AAEF;AAAA,IACF;AACA,SAAK,UAAU,MAAM,sBAAsB,OAAO;AAAA,EACpD;AAAA,EAEQ,YAAY,SAAyB;AAC3C,UAAM,EAAE,mBAAmB,KAAK;AAGhC,UAAM,eAAe,IAAI,OAAO,UAAU,cAAc,YAAY;AAEpE,UAAM,cAAc,UAAU,cAAc;AAE5C,WAAO,QAAQ,QAAQ,cAAc,WAAW;AAAA,EAClD;AAAA,EAEQ,oBAAoB,SAAyB;AACnD,UAAM,EAAE,gBAAgB,WAAA,IAAe,KAAK;AAG5C,UAAM,mBAAmB,IAAI;AAAA,MAC3B,yFAAyF,cAAc;AAAA,IAAA;AAGzG,UAAM,sBAAsB;AAAA;AAAA;AAAA,yBAGP,UAAU;AAAA;AAAA;AAAA;AAAA,0CAKhC,eAAe,aACX,oFACA,EACN;AAEG,QAAI,QAAQ,MAAM,gBAAgB,GAAG;AACnC,gBAAU,QAAQ,QAAQ,kBAAkB,mBAAmB;AAAA,IACjE;AAGA,UAAM,sBAAsB;AAE5B,UAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQtB,QAAI,QAAQ,MAAM,mBAAmB,GAAG;AACtC,gBAAU,QAAQ,QAAQ,qBAAqB,aAAa;AAAA,IAC9D;AAGA,UAAM,wBACJ;AAEF,UAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAO/B,QAAI,QAAQ,MAAM,qBAAqB,GAAG;AACxC,gBAAU,QAAQ,QAAQ,uBAAuB,sBAAsB;AAAA,IACzE;AAEA,WAAO;AAAA,EACT;AACF;AC9FO,SAAS,iBACd,WACA,SACA,UACM;AACN,QAAM,SAAS,iBAAA;AACf,QAAM,aAAa,0BAA0B,WAAW,SAAS,QAAQ;AAEzE,SAAO;AAAA,IACL,UAAU,WAAW,UAAU,6BAA6B,WAAW,SAAS;AAAA,EAAA;AAIlF,MAAI,CAAC,UAAU,OAAO,WAAW,aAAa,GAAG;AAC/C,UAAM,IAAI,MAAM,yBAAyB,WAAW,aAAa,EAAE;AAAA,EACrE;AAEA,MAAI,QAAQ,QAAQ;AAClB,WAAO,KAAK,qCAAqC;AACjD,WAAO,KAAK,4BAA4B,WAAW,aAAa,EAAE;AAClE,QAAI,WAAW,kBAAkB;AAC/B,aAAO;AAAA,QACL,sCAAsC,WAAW,gBAAgB;AAAA,MAAA;AAAA,IAErE;AACA,QAAI,WAAW,sBAAsB;AACnC,aAAO;AAAA,QACL,yEAAyE,WAAW,oBAAoB;AAAA,MAAA;AAAA,IAE5G;AACA;AAAA,EACF;AAEA,MAAI;AAEF,WAAO,KAAK,4BAA4B,WAAW,aAAa,EAAE;AAClE,UAAM,mBAAmB,IAAI,qBAAqB,WAAW,UAAU;AACvE,qBAAiB,UAAA;AAGjB,QAAI,WAAW,gBAAgB;AAC7B,aAAO;AAAA,QACL,+BACE,WAAW,oBAAoB,cACjC;AAAA,MAAA;AAEF,YAAM,qBAAqB,IAAI;AAAA,QAC7B;AAAA,QACA;AAAA,MAAA;AAEF,yBAAmB,UAAA;AAAA,IACrB;AAGA,QAAI,WAAW,sBAAsB;AACnC,aAAO;AAAA,QACL,mCAAmC,WAAW,oBAAoB;AAAA,MAAA;AAEpE,YAAM,0BAA0B,IAAI;AAAA,QAClC;AAAA,QACA;AAAA,MAAA;AAEF,8BAAwB,UAAA;AAAA,IAC1B;AAEA,WAAO;AAAA,MACL,sBAAsB,WAAW,UAAU,sBAAsB,WAAW,SAAS;AAAA,IAAA;AAEvF,WAAO,KAAK,EAAE;AACd,WAAO,KAAK,aAAa;AACzB,WAAO;AAAA,MACL;AAAA,IAAA;AAEF,WAAO;AAAA,MACL;AAAA,IAAA;AAEF,WAAO,KAAK,mDAAmD;AAC/D,QAAI,WAAW,eAAe,YAAY;AACxC,aAAO;AAAA,QACL;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF,SAAS,OAAO;AACd,WAAO,MAAM,iCAAiC,KAAK,EAAE;AACrD,UAAM;AAAA,EACR;AACF;AC3CA,SAAS,mBAAmB,SAA6C;AACvE,QAAM,MAAgB,CAAA;AACtB,MAAI,QAAQ,mBAAmB;AAC7B,QAAI,KAAK,sBAAsB,KAAK,UAAU,QAAQ,iBAAiB,CAAC,EAAE;AAAA,EAC5E;AACA,MAAI,QAAQ,SAAS;AACnB,QAAI;AAAA,MACF,gCAAgC,KAAK,UAAU,QAAQ,OAAO,CAAC;AAAA,IAAA;AAAA,EAEnE;AACA,SAAO,IAAI,SAAS,KAAK,IAAI,KAAK,IAAI,CAAC,OAAO;AAChD;AAKO,SAAS,2BACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAE3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AAEA,QAAM,gBAAgB,QAAQ,aAC1B;AAAA,IACE;AAAA,IACA;AAAA,MACE;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB,YAAY,QAAQ;AAAA,MACpB,mBAAmB,QAAQ;AAAA,IAAA;AAAA,IAE7B;AAAA,EAAA,IAEF;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ;AAAA,EAAA;AAE/B,QAAM,YAAY,cAAc,WAAW,KAAA,KAAU;AACrD,QAAM,kBAAkB,cAAc;AAEtC,SAAO;AAAA,IACL,8BAA8B,SAAS,gBAAgB,QAAQ,SAAS;AAAA,EAAA;AAG1E,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,sBAAkB,IAAI,KAAK;AAAA,MACzB,EAAE,MAAM,oBAAA;AAAA,MACR,EAAE,MAAM,qBAAqB,YAAY,KAAA;AAAA,IAAK,CAC/C;AAGD,QAAI,cAAc,iBAAiB;AACjC,wBAAkB,IAAI,KAAK,CAAC,EAAE,MAAM,iBAAiB,YAAY,KAAA,CAAM,CAAC;AAAA,IAC1E,WAAW,iBAAiB;AAC1B,wBAAkB,IAAI,iBAAiB;AAAA,QACrC,EAAE,MAAM,WAAW,YAAY,KAAA;AAAA,MAAK,CACrC;AAAA,IACH;AAEA,UAAM,MAAM,cAAc,EAAE;AAC5B,UAAM,YAAY,IAAI,QAAA;AACtB,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,0BAA0B;AAE1D,UAAM,aAAa,IAAI,kBAAA,EAAoB,IAAI,CAAC,OAAO,GAAG,SAAS;AAEnE,sBAAkB,KAAK,qBAAqB;AAAA,MAC1C,UAAU,CAAC,SAAS;AAAA,MACpB,UAAU,mBAAmB,OAAO;AAAA,IAAA,CACrC;AAED;AAAA,MACE;AAAA,MACA;AAAA,MACA,qBAAqB,SAAS;AAAA,MAC9B;AAAA,IAAA;AAEF;AAAA,MACE;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ,CAAC;AAID,oCAAkC;AAAA,IAChC;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,EAAA,CACD;AAED,SAAO,EAAE,cAAA;AACX;AC5HO,SAAS,sBACd,WACA,SACA,UACqD;AACrD,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAE3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AAEA,SAAO,KAAK,qCAAqC,QAAQ,SAAS,EAAE;AAEpE,MAAI;AAEJ,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,sBAAkB,IAAI,KAAK,CAAC,EAAE,MAAM,iBAAA,CAAkB,CAAC;AAEvD,UAAM,MAAM,cAAc,EAAE;AAC5B,sBAAkB,KAAK,kBAAkB;AAAA,MACvC,UAAU,QAAQ,WACd,eAAe,KAAK,UAAU,QAAQ,QAAQ,CAAC,OAC/C;AAAA,IAAA,CACL;AAID,UAAM,OAAO,IAAI,gBAAA,EAAkB,CAAC;AACpC,sBAAkB,MACd,cAAA,EAAgB,CAAC,GACjB,YAAA,GACA,QAAA,GACA,QAAQ,QAAQ,EAAE;AAAA,EACxB,CAAC;AAED,QAAM,kBAAkB,kBACpB,uBAAuB,WAAW,eAAe,iBAAiB,MAAM,IACxE;AAEJ,SAAO,EAAE,eAAe,gBAAA;AAC1B;AAMA,SAAS,uBACP,WACA,eACA,iBACA,QACoB;AACpB,QAAM,YAAY,KAAK;AAAA,IACrB,KAAK,QAAQ,aAAa;AAAA,IAC1B;AAAA,IACA;AAAA,EAAA;AAEF,QAAM,SAAS,UAAU,OAAO,SAAS,IAAI,YAAY;AAEzD,MAAI,WAAW;AACf,sBAAoB,WAAW,QAAQ,CAAC,OAAO;AAC7C,UAAM,QAAQ,GAAG,aAAa,eAAe;AAC7C,QAAI,CAAC,MAAO;AAEZ,UAAM,UAAU,MACb,WAAA,EACA,KAAK,CAAC,WAAW,OAAO,QAAA,EAAU,SAAS,gBAAgB,CAAC;AAC/D,QAAI,SAAS;AACX,iBAAW;AACX;AAAA,IACF;AAEA,sBAAkB,IAAI,2BAA2B;AAAA,MAC/C,EAAE,MAAM,kBAAkB,YAAY,KAAA;AAAA,IAAK,CAC5C;AACD,UAAM,WAAW,gBAAgB;AACjC,eAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,MACL,4BAA4B,eAAe;AAAA,IAAA;AAE7C,WAAO;AAAA,EACT;AACA,SAAO;AACT;ACnEA,SAAS,kBAAkB,eAA2C;AACpE,QAAM,OAAO,cAAc,QAAQ,GAAG;AACtC,MAAI,SAAS,GAAI,QAAO;AACxB,QAAM,QAAQ,cACX,MAAM,OAAO,GAAG,cAAc,YAAY,GAAG,CAAC,EAC9C,QAAQ,QAAQ,GAAG,EACnB,KAAA;AACH,SAAO,SAAS;AAClB;AAEA,SAAS,iBACP,KACA,eACmB;AACnB,QAAM,UAA6B,CAAA;AACnC,QAAM,QAAQ,CACZ,MACA,iBACA,aACG;AACH,UAAM,OAAO,gBAAA;AACb,QAAI,SAAS,OAAW;AACxB,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,KAAK,kBAAkB,IAAI;AAAA,MAC3B,MAAM,YAAY;AAAA,IAAA,CACnB;AAAA,EACH;AACA,aAAW,KAAK,IAAI,cAAc;AAChC,UAAM,MAAM,EAAE,aAAa,aAAa;AACxC,QAAI,KAAK;AACP,YAAM,EAAE,QAAA,GAAW,MAAM,IAAI,QAAA,GAAW,EAAE,qBAAqB,SAAS;AAAA,IAC1E;AAAA,EACF;AACA,aAAW,KAAK,IAAI,iBAAiB;AACnC,UAAM,MAAM,EAAE,aAAa,aAAa;AACxC,QAAI,KAAK;AACP,YAAM,EAAE,QAAA,GAAW,MAAM,IAAI,QAAA,GAAW,EAAE,eAAe,SAAS;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,cACd,WACA,SACA,UACkB;AAClB,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,QAAM,UAAU,UAAU,KAAK,aAAa;AAC5C,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AAEA,QAAM,UAAU,IAAI,QAAQ,EAAE,uBAAuB,MAAM;AAC3D,QAAM,KAAK,QAAQ,iBAAiB,eAAe,SAAS;AAAA,IAC1D,WAAW;AAAA,EAAA,CACZ;AAGD,MAAI;AACJ,QAAM,gBAAgB,GAAG,uBAAuB,YAAY;AAC5D,MAAI,eAAe;AACjB,UAAM,OAAO,cAAc,eAAA,GAAkB,QAAA;AAC7C,QAAI,KAAM,aAAY,KAAK,QAAQ,kBAAkB,EAAE;AAAA,EACzD;AAGA,QAAM,MACJ,GAAG,aAAa,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,CAAC,KACtD,GAAG,aAAa,KAAK,CAAC,MAAM,EAAE,WAAA,CAAY,KAC1C,GAAG,WAAA,EAAa,CAAC;AAEnB,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,iBAAiB,CAAA;AAAA,MACjB,WAAW;AAAA,MACX,aAAa;AAAA,MACb,UAAU,CAAA;AAAA,MACV,cAAc,CAAA;AAAA,MACd,eAAe,CAAA;AAAA,MACf,kBAAkB,CAAA;AAAA,MAClB,iBAAiB,CAAA;AAAA,MACjB,SAAS,CAAA;AAAA,MACT,SAAS,CAAA;AAAA,IAAC;AAAA,EAEd;AAEA,QAAM,kBAAkB,IAAI,cAAA,EAAgB,IAAI,CAAC,MAAM,EAAE,SAAS;AAClE,QAAM,cAAc,oBAAoB,IAAI,KAAK,UAAU;AAC3D,QAAM,YAAY,2BAA2B,KAAK,eAAe,EAAE;AAEnE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,IAAI,QAAA;AAAA,IACf;AAAA,IACA;AAAA,IACA,aAAa,gBAAgB,SAAS,cAAc;AAAA,IACpD,UAAU,iBAAiB,KAAK,UAAU;AAAA,IAC1C,cAAc,iBAAiB,KAAK,eAAe;AAAA,IACnD,eAAe,iBAAiB,KAAK,iBAAiB;AAAA,IACtD,kBAAkB,iBAAiB,KAAK,mBAAmB;AAAA,IAC3D,iBAAiB,iBAAiB,KAAK,mBAAmB;AAAA,IAC1D,SAAS,iBAAiB,KAAK,gBAAgB;AAAA,IAC/C,SAAS,iBAAiB,KAAK,WAAW;AAAA,EAAA;AAE9C;AC7IO,SAAS,sBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AACA,SAAO;AAAA,IACL,2BAA2B,QAAQ,UAAU,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAGxE,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,sBAAkB,IAAI,KAAK,CAAC,EAAE,MAAM,iBAAA,CAAkB,CAAC;AACvD,UAAM,MAAM,cAAc,EAAE;AAC5B,UAAM,aAAa,IAAI,QAAA,KAAa,IAAI,QAAQ,SAAS,EAAE;AAC3D,uBAAmB,KAAK;AAAA,MACtB,MAAM,QAAQ;AAAA,MACd,eAAe;AAAA,MACf,mBAAmB,2BAA2B,SAAS;AAAA,MACvD,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,IAAA,CACb;AAAA,EACH,CAAC;AAED,SAAO,EAAE,cAAA;AACX;ACZA,MAAMC,oBAAkB,oBAAI,IAAI,CAAC,iBAAiB,kBAAkB,CAAC;AAE9D,SAAS,qBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AACA,SAAO;AAAA,IACL,0BAA0B,QAAQ,YAAY,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAGzE,QAAM,YAAY,CAAC,cAAc,QAAQ,YAAY,EAAE;AACvD,MAAI,QAAQ,GAAI,WAAU,KAAK,OAAO,KAAK,UAAU,QAAQ,EAAE,CAAC,EAAE;AAElE,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,sBAAkB,IAAI,KAAK,CAAC,EAAE,MAAM,gBAAA,CAAiB,CAAC;AAItD,QAAI,QAAQ,mBAAmB;AAC7B,YAAM,QAAkD,CAAA;AAExD,YAAM,OAAO,QAAQ,aAAa;AAAA,QAChC;AAAA,MAAA,IACE,CAAC;AACL,UAAI,KAAM,OAAM,KAAK,EAAE,MAAM,MAAM;AAEnC,YAAM,UAAU,QAAQ,gBAAgB,KAAA;AACxC,UACE,WACA,qBAAqB,KAAK,OAAO,KACjC,CAACA,kBAAgB,IAAI,OAAO,GAC5B;AACA,cAAM,KAAK,EAAE,MAAM,SAAS,YAAY,MAAM;AAAA,MAChD;AACA,UAAI,MAAM,OAAQ,mBAAkB,IAAI,QAAQ,mBAAmB,KAAK;AAAA,IAC1E;AAEA,UAAM,MAAM,cAAc,EAAE;AAC5B,yBAAqB,KAAK;AAAA,MACxB,MAAM,QAAQ;AAAA,MACd,eAAe;AAAA,MACf,mBAAmB,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,MAC5C,MAAM,QAAQ;AAAA,MACd,OAAO;AAAA,MACP,gBAAgB;AAAA,IAAA,CACjB;AAAA,EACH,CAAC;AAED,SAAO,EAAE,cAAA;AACX;AC9CA,MAAM,kBAAkB,oBAAI,IAAI,CAAC,iBAAiB,kBAAkB,CAAC;AAE9D,SAAS,gBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,QAAoB,QAAQ,SAAS;AAC3C,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AACA,SAAO;AAAA,IACL,qBAAqB,QAAQ,YAAY,MAAM,KAAK,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAG/E,QAAM,gBAAgB,QAAQ,aAC1B;AAAA,IACE;AAAA,IACA;AAAA,MACE;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB,YAAY,QAAQ;AAAA,MACpB,mBAAmB,QAAQ;AAAA,IAAA;AAAA,IAE7B;AAAA,EAAA,IAEF,EAAE,WAAW,QAAQ,WAAW,iBAAiB,QAAQ,aAAA;AAC7D,QAAM,YAAY,cAAc,WAAW,KAAA;AAC3C,QAAM,kBAAkB,cAAc;AAEtC,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,UAAM,aAAuD;AAAA,MAC3D,EAAE,MAAM,WAAA;AAAA,IAAW;AAGrB,QAAI,UAAU,YAAa,YAAW,KAAK,EAAE,MAAM,qBAAqB;AACxE,sBAAkB,IAAI,KAAK,UAAU;AAKrC,QACE,mBACA,aACA,qBAAqB,KAAK,SAAS,KACnC,CAAC,gBAAgB,IAAI,SAAS,GAC9B;AACA,wBAAkB,IAAI,iBAAiB;AAAA,QACrC,EAAE,MAAM,WAAW,YAAY,KAAA;AAAA,MAAK,CACrC;AAAA,IACH;AAEA,UAAM,MAAM,cAAc,EAAE;AAC5B,QAAI,UAAU,aAAa;AACzB,2BAAqB,KAAK;AAAA,QACxB,MAAM,QAAQ;AAAA,QACd,eAAe;AAAA,QACf,MAAM;AAAA,QACN,aAAa,yBAAyB,SAAS;AAAA,QAC/C,OAAO;AAAA,MAAA,CACR;AAAA,IACH,WAAW,UAAU,SAAS;AAC5B,2BAAqB,KAAK;AAAA,QACxB,MAAM,QAAQ;AAAA,QACd,eAAe;AAAA,QACf,MAAM;AAAA,QACN,MAAM,GAAG,SAAS;AAAA,QAClB,aAAa;AAAA,QACb,OAAO;AAAA,MAAA,CACR;AAAA,IACH,OAAO;AACL,2BAAqB,KAAK;AAAA,QACxB,MAAM,QAAQ;AAAA,QACd,eAAe;AAAA,QACf,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,gBAAgB;AAAA,MAAA,CACjB;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO,EAAE,cAAA;AACX;AC5GO,SAAS,uBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AACA,SAAO;AAAA,IACL,4BAA4B,QAAQ,WAAW,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAG1E,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YAAY,QAAQ,aAAa;AAEvC,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,sBAAkB,IAAI,KAAK;AAAA,MACzB,EAAE,MAAM,kBAAA;AAAA,MACR,EAAE,MAAM,sBAAA;AAAA,IAAsB,CAC/B;AACD,UAAM,MAAM,cAAc,EAAE;AAC5B,uBAAmB,KAAK;AAAA,MACtB,MAAM,QAAQ;AAAA,MACd,eAAe;AAAA,MACf,mBAAmB,iDAAiD,QAAQ,KAAK,gBAAgB,SAAS;AAAA,MAC1G,YAAY,CAAC,EAAE,MAAM,SAAS,MAAM,WAAW;AAAA,MAC/C,YAAY;AAAA,IAAA,CACb;AAAA,EACH,CAAC;AAED,SAAO,EAAE,cAAA;AACX;AClCO,SAAS,yBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AACA,SAAO;AAAA,IACL,8BAA8B,QAAQ,YAAY,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAG7E,QAAM,YAAY,QAAQ,aAAa;AAEvC,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,0BAA0B,EAAE;AACxC,sBAAkB,IAAI,KAAK;AAAA,MACzB,EAAE,MAAM,oBAAA;AAAA,MACR,EAAE,MAAM,qBAAqB,YAAY,KAAA;AAAA,IAAK,CAC/C;AACD,UAAM,MAAM,cAAc,EAAE;AAC5B,yBAAqB,KAAK;AAAA,MACxB,MAAM,QAAQ;AAAA,MACd,eAAe;AAAA,MACf,mBAAmB,WAAW,QAAQ,IAAI,gBAAgB,KAAK;AAAA,QAC7D,QAAQ;AAAA,MAAA,CACT;AAAA,MACD,MAAM,qBAAqB,SAAS;AAAA,MACpC,gBAAgB;AAAA,IAAA,CACjB;AAAA,EACH,CAAC;AAED,SAAO,EAAE,cAAA;AACX;AClCA,SAAS,mBAAmB,MAAkC;AAC5D,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;AAEO,SAAS,mBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AAEA,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,cACJ,QAAQ,gBAAgB,SACpB,QAAQ,cACR,mBAAmB,IAAI;AAE7B,SAAO;AAAA,IACL,oBAAoB,QAAQ,YAAY,KAAK,IAAI,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAG5E,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,cAAc,EAAE;AAC5B,qBAAiB,KAAK;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB,gBAAgB,gBAAgB;AAAA,IAAA,CACjC;AAAA,EACH,CAAC;AAED,SAAO,EAAE,cAAA;AACX;ACnDO,SAAS,mBACd,WACA,SACA,UAC2B;AAC3B,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AACA,SAAO;AAAA,IACL,2BAA2B,QAAQ,IAAI,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAGlE,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,UAAM,MAAM,cAAc,EAAE;AAC5B,cAAU,KAAK;AAAA,MACb,MAAM,QAAQ;AAAA,MACd,YAAY,QAAQ;AAAA,MACpB,YAAY,QAAQ;AAAA,IAAA,CACrB;AAAA,EACH,CAAC;AAED,SAAO,EAAE,cAAA;AACX;AC/BO,SAAS,iBACd,eACA,WACQ;AACR,SAAO,KAAK;AAAA,IACV,KAAK,QAAQ,aAAa;AAAA,IAC1B;AAAA,IACA,GAAG,SAAS;AAAA,EAAA;AAEhB;AAGO,SAAS,yBAAyB,WAA2B;AAClE,SAAO,WAAW,WAAW,SAAS,CAAC;AACzC;AAOO,SAAS,mBAAmB,aAA6B;AAC9D,SAAO,YAAY,QAAQ,gBAAgB,KAAK;AAClD;AAOA,SAAS,cAAc,QAAgB,SAAiB,MAAsB;AAC5E,QAAM,YAAoC;AAAA,IACxC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,EAAA;AAEV,QAAM,KAAK,UAAU,MAAM;AAC3B,SAAO,KACH,WAAW,EAAE,IAAI,KAAK,UAAU,OAAO,CAAC,KAAK,IAAI,OACjD,iBAAiB,KAAK,UAAU,OAAO,aAAa,CAAC,KAAK,KAAK;AAAA,IAC7D;AAAA,EAAA,CACD,KAAK,IAAI;AAChB;AAEA,SAAS,OAAO,WAAmB,YAA4B;AAC7D,SAAO;AAAA,4BACmB,SAAS;AAAA;AAAA;AAAA,uCAGE,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAajD;AAsCO,SAAS,gBACd,WACA,SACuB;AACvB,QAAM,gBAAgB;AAAA,IACpB,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAEV,QAAM,mBAAmB,yBAAyB,QAAQ,SAAS;AACnE,QAAM,eAAe,mBAAmB,QAAQ,WAAW;AAC3D,QAAM,aAAa,UAAU,aAAa,SAAS,QAAQ,WAAW,CAAC,CAAC;AACxE,QAAM,oBAAoB,CAAC,QAAQ;AAEnC,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,cAAU,MAAM,eAAe,OAAO,QAAQ,WAAW,gBAAgB,CAAC;AAAA,EAC5E;AAIA,QAAM,eAAe,QAAQ,mBAAmB,WAAW,GAAG,IAC1D,MAAM,QAAQ,kBAAkB,KAChC,QAAQ;AAEZ,MAAI,eAAe;AAEnB,sBAAoB,WAAW,eAAe,CAAC,OAAO;AACpD,sBAAkB,IAAI,cAAc,CAAC,EAAE,MAAM,UAAA,CAAW,CAAC;AACzD,sBAAkB,IAAI,eAAe;AAAA,MACnC,EAAE,MAAM,QAAQ,UAAU,YAAY,KAAA;AAAA,IAAK,CAC5C;AAED,iBAAa,IAAI;AAAA,MACf,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,IAAA,CACrB;AAED,UAAM,YAAY;AAAA,MAChB,QAAQ;AAAA,MACR;AAAA,MACA,WAAW,UAAU;AAAA,IAAA;AAEvB,mBAAe,sBAAsB,IAAI;AAAA,MACvC;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB;AAAA;AAAA,MAEA,QAAQ,GAAG,QAAQ,OAAO,aAAa,IAAI,YAAY;AAAA,MACvD,SAAS,CAAC,aACR,SAAS,SAAS,KAAK,UAAU,YAAY,CAAC,KAC9C,SAAS,SAAS,kBAAkB,QAAQ,MAAM,CAAC;AAAA,IAAA,CACtD;AAAA,EACH,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAGA,SAAS,kBAAkB,QAAwB;AACjD,QAAM,YAAoC;AAAA,IACxC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,EAAA;AAEV,SAAO,UAAU,MAAM,KAAK,IAAI,OAAO,aAAa;AACtD;AAEA,SAAS,aACP,IACA,MAOM;AACN,MAAI,GAAG,uBAAuB,KAAK,IAAI,EAAG;AAM1C,QAAM,QAAQ;AAAA,IACZ,wBAAwB,KAAK,OAAO,aAAa,IAC/C,KAAK,WACP;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,CAAC,KAAK,YAAY;AACpB,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACA,QAAM,OAAO,MAAM,KAAK,IAAI;AAE5B,KAAG,qBAAqB;AAAA,IACtB,YAAY;AAAA,IACZ,iBAAiB,wBAAwB;AAAA,IACzC,MAAM,CAAC,IAAI;AAAA,IACX,cAAc;AAAA,MACZ;AAAA,QACE,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,cAAc,sBAAsB,KAAK,IAAI;AAAA,MAAA;AAAA,IACjE;AAAA,EACF,CACD;AACH;AAMA,SAAS,sBACP,IACA,MAOS;AACT,MAAI,KAAK,GAAG,YAAY,KAAK,gBAAgB;AAC7C,MAAI,CAAC,IAAI;AACP,SAAK,GAAG,YAAY;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,WAAW,KAAK,SAAS;AAAA,MAAA;AAAA,IAC3B,CACD;AAAA,EACH;AAEA,QAAM,UAAU,GACb,cAAA,EACA,KAAK,CAAC,cAAc,KAAK,QAAQ,UAAU,QAAA,CAAS,CAAC;AACxD,MAAI,QAAS,QAAO;AAEpB,KAAG,cAAc,MAAM,KAAK,MAAM;AAAA,EAAK,KAAK,SAAS,EAAE;AACvD,SAAO;AACT;ACjFA,MAAM,oBAAoB;AAG1B,SAAS,mBACP,WACA,YACU;AACV,SAAO,UACJ,UAAU,UAAU,EACpB,OAAO,CAAC,MAAM,kBAAkB,KAAK,EAAE,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC;AACtE;AAGA,SAAS,kBAAkB,UAAkB,aAA6B;AACxE,MAAI,MAAM,KACP,SAAS,KAAK,QAAQ,QAAQ,GAAG,WAAW,EAC5C,MAAM,KAAK,GAAG,EACd,KAAK,GAAG;AACX,MAAI,CAAC,IAAI,WAAW,GAAG,EAAG,OAAM,KAAK,GAAG;AACxC,SAAO;AACT;AAGA,SAAS,oBAAoB,UAAkB,WAA2B;AACxE,SAAO,KAAK,KAAK,KAAK,QAAQ,QAAQ,GAAG,SAAS;AACpD;AAWA,SAAS,oCACP,WACA,mBACA,cACM;AACN,QAAM,OAAO,GAAG,iBAAiB;AACjC,MAAI,CAAC,UAAU,OAAO,IAAI,EAAG;AAE7B,QAAM,aAAa,eAAe,WAAW,MAAM,CAAC,OAAO;AACzD,UAAM,QAAQ,GAAG,aAAa,aAAa;AAC3C,WAAO,QAAQ,MAAM,kBAAA,EAAoB,SAAS;AAAA,EACpD,CAAC;AACD,MAAI,eAAe,QAAQ,cAAc,EAAG;AAE5C,QAAM,IAAI;AAAA,IACR,GAAG,IAAI,kEAAkE,UAAU,wDAC3C,YAAY;AAAA,EAAA;AAGxD;AAEA,MAAM,uCAAuB,IAAI,CAAC,QAAQ,OAAO,UAAU,OAAO,CAAC;AAGnE,SAAS,2BACP,QACA,MACA,YACM;AACN,MAAI,SAAS,eAAe,CAAC,iBAAiB,IAAI,MAAM,EAAG;AAE3D,QAAM,IAAI;AAAA,IACR,GAAG,UAAU,SAAS,OAAO,aAAa,gNAE6B,OAAO,YAAA,CAAa;AAAA,EAAA;AAI/F;AAQA,SAAS,sCACP,WACA,mBACA,cACM;AACN,QAAM,OAAO,GAAG,iBAAiB;AACjC,MAAI,CAAC,UAAU,OAAO,IAAI,EAAG;AAE7B,QAAM,WAAW;AAAA,IAAe;AAAA,IAAW;AAAA,IAAM,CAAC,OAChD,QAAQ,GAAG,YAAY,2BAA2B,CAAC;AAAA,EAAA;AAErD,MAAI,SAAU;AAEd,QAAM,IAAI;AAAA,IACR,GAAG,IAAI,+HACiC,YAAY;AAAA,EAAA;AAGxD;AAWA,SAAS,aAAa,UAAkB,WAA4B;AAClE,QAAM,OAAO,CAAC,SAAiB;AAC7B,UAAM,QAAQ,KAAK;AAAA,MACjB;AAAA,IAAA;AAEF,WAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,YAAA,CAAa,IAAI;AAAA,EACtD;AACA,QAAM,IAAI,KAAK,SAAS,KAAA,CAAM;AAC9B,QAAM,IAAI,KAAK,UAAU,KAAA,CAAM;AAC/B,SAAO,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC;AACpD;AAGA,SAAS,aAAa,GAAW,GAAmB;AAClD,MAAI,WAAW,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAA,GAAK,CAAC,GAAG,MAAM,CAAC;AAC/D,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,UAAM,UAAU,CAAC,CAAC;AAClB,aAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,cAAQ,CAAC,IAAI,KAAK;AAAA,QAChB,SAAS,CAAC,IAAI;AAAA,QACd,QAAQ,IAAI,CAAC,IAAI;AAAA,QACjB,SAAS,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,MAAA;AAAA,IAEnD;AACA,eAAW;AAAA,EACb;AACA,SAAO,SAAS,EAAE,MAAM;AAC1B;AAEA,MAAM,gBAAgB;AAOtB,SAAS,wBACP,aACA,QACA,aACQ;AACR,SAAO;AAAA,qBACY,OAAO,aAAa,IAAI,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCASpB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAM/C;AAGA,SAAS,sBAAsB,aAAqB,QAAwB;AAC1E,SAAO;AAAA,IACL,mBAAmB,OAAO,YAAA,CAAa,IAAI,WAAW;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,IAAI;AACb;AAGA,SAAS,YACP,aACA,QACA,SACQ;AACR,QAAM,QAAQ,UACV;AAAA,IACE;AAAA,IACA;AAAA,EAAA,IAEF;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEN,SAAO;AAAA,IACL,uBAAuB,OAAO,YAAA,CAAa,IAAI,WAAW;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,IAAI;AACb;AAOA,SAAS,aAAa,MAST;AACX,SAAO;AAAA,IACL,gCACE,KAAK,YACP,sCAAsC,KAAK,OAAO,YAAA,CAAa,IAC7D,KAAK,WACP;AAAA,IACA,MAAM,KAAK,gBAAgB,mCAAmC,KAAK,WAAW,IAAI,KAAK,WAAW;AAAA,IAClG,MAAM,KAAK,gBAAgB,sEAAsE,KAAK,WAAW,IAAI,KAAK,WAAW;AAAA,IACrI;AAAA,IACA,KAAK,gBACD,UAAU,KAAK,aAAa,oGAC5B;AAAA,IACJ,UAAU,KAAK,UAAU;AAAA,EAAA;AAE7B;AAWA,SAAS,qBAAqB,MAKL;AACvB,QAAM,iBAAiB,KAAK,WACzB,OAAO,CAAC,OAAO,GAAG,SAAS,KAAK,WAAW,EAC3C,IAAI,CAAC,OAAO,GAAG,MAAM;AACxB,QAAM,2BAA2B,eAAe,SAAS;AAEzD,QAAM,UAAU,CAAC,GAAG,IAAI,IAAI,KAAK,WAAW,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,EAC9D;AAAA,IACC,CAAC,GAAG,MACF,aAAa,GAAG,KAAK,WAAW,IAAI,aAAa,GAAG,KAAK,WAAW;AAAA,EAAA,EAEvE,MAAM,GAAG,aAAa;AAEzB,QAAM,cAAc;AAAA,IAClB,gIAAgI,KAAK,YAAY;AAAA,IACjJ;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,UAAU,2BACZ,GAAG,KAAK,OAAO,aAAa,IAC1B,KAAK,WACP,8CACE,KAAK,YACP,uCAAuC,eACpC,IAAI,CAAC,MAAM,EAAE,YAAA,CAAa,EAC1B,KAAK,IAAI,CAAC,MACb,GAAG,KAAK,OAAO,YAAA,CAAa,IAC1B,KAAK,WACP,8CACE,KAAK,YACP;AAEJ,QAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,QAAM,UAAU;AAAA,IACd,aAAa,KAAK;AAAA,IAClB,QAAQ,KAAK;AAAA,IACb;AAAA,IACA;AAAA,IACA,yBAAyB;AAAA,IACzB,SACE;AAAA,IACF;AAAA,EAAA;AAEF,SAAO;AACT;AAEO,SAAS,yBACd,WACA,SACA,UACyB;AACzB,QAAM,SAAS,iBAAA;AACf,QAAM,EAAE,eAAe,WAAA,IAAe;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AAKA,MAAI;AACJ,MAAI,QAAQ,mBAAmB;AAC7B,wBAAoB,QAAQ,kBAAkB,QAAQ,SAAS,EAAE;AAAA,EACnE,WAAW,QAAQ,eAAe;AAChC,wBAAoB;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,IAAA;AAAA,EAEZ,OAAO;AACL,QAAI,CAAC,YAAY;AACf,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,UAAU,mBAAmB,WAAW,UAAU;AACxD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,aAAa,QAAQ;AAAA,QAAI,CAAC,MAC9B,kBAAkB,eAAe,EAAE,QAAQ,SAAS,EAAE,CAAC;AAAA,MAAA;AAEzD,YAAM,IAAI;AAAA,QACR,iEAAiE,WAAW;AAAA,UAC1E;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IAEL;AACA,wBAAoB,QAAQ,CAAC,EAAE,QAAQ,SAAS,EAAE;AAAA,EACpD;AAEA;AAAA,IACE;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EAAA;AAGV,QAAM,YAAY,cAAc,eAAe,QAAQ,SAAS;AAChE,QAAM,mBAAmB,oBAAoB,eAAe,SAAS;AAErE,QAAM,yBAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,EAAA;AAEF,QAAM,4BAA4B;AAAA,IAChC;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,UAAU,QAAQ,UAAU,OAAO,YAAA;AACzC,QAAM,OACJ,QAAQ,SAAS,QAAQ,YAAY,cAAc;AACrD,6BAA2B,QAAQ,MAAM,QAAQ,UAAU;AAC3D,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,cAAc,GAAG,WAAW,SAAS,CAAC;AAO5C,QAAM,WAAmC,QAAQ,QAAQ;AACzD,QAAM,aAAa,4BAA4B,WAAW,iBAAiB;AAC3E,QAAM,gBAAgB,eAAe;AACrC,QAAM,iBACJ,eAAe,QACf,WAAW;AAAA,IACT,CAAC,OAAO,GAAG,SAAS,QAAQ,eAAe,GAAG,WAAW;AAAA,EAAA;AAG7D,MAAI,CAAC,kBAAkB,aAAa,SAAS;AAC3C,UAAM,qBAAqB;AAAA,MACzB,aAAa,QAAQ;AAAA,MACrB;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB,YAAY,cAAc,CAAA;AAAA,IAAC,CAC5B;AAAA,EACH;AAEA,QAAM,cAAc,CAAC;AACrB,QAAM,YAAY,eAAe,aAAa;AAE9C,MAAI,aAAa;AACf;AAAA,MACE;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IAAA;AAAA,EAEZ;AAEA,SAAO;AAAA,IACL,UAAU,IAAI,WACZ,cAAc,iBAAiB,EACjC,uBAAuB,QAAQ,UAAU,MAAM,MAAM,IACnD,QAAQ,WACV,QAAQ,QAAQ,SAAS;AAAA,EAAA;AAE3B,MAAI,aAAa;AACf,WAAO;AAAA,MACL,GAAG,OAAO,YAAA,CAAa,IAAI,QAAQ,WAAW,cAC5C,QAAQ,YACV;AAAA,IAAA;AAAA,EAGJ;AAGA,uBAAqB,WAAW,eAAe,SAAS;AAExD,MAAI,cAAc,QAAQ;AAC1B,MAAI,kBAAkB;AAQtB,MAAI,YAAY;AAChB,MAAI,aAAa;AACjB,MAAI,WAAW;AACf,MAAI,WAAW;AAEf,sBAAoB,WAAW,kBAAkB,CAAC,OAAO;AACvD,sBAAkB,IAAI,2BAA2B,CAAC,EAAE,MAAM,WAAA,CAAY,CAAC;AACvE,QAAI,aAAa;AACf,wBAAkB,IAAI,2BAA2B;AAAA,QAC/C,EAAE,MAAM,WAAW,YAAY,KAAA;AAAA,MAAK,CACrC;AAAA,IACH;AAMA,UAAM,WAAW,cACb,GAAG,KAAK,UAAU,QAAQ,WAAW,CAAC,gBACtC,KAAK,UAAU,QAAQ,WAAW;AAEtC,UAAM,QAAQ,wBAAwB,IAAI;AAAA,MACxC;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,aAAa,YAAY,QAAQ,KAAK,KAAK,UAAU,MAAM,CAAC;AAAA,MAC5D,QAAQ;AAAA,MACR,eAAe,cACX,wBAAwB,QAAQ,aAAa,QAAQ,WAAW,IAChE;AAAA,IAAA,CACL;AACD,kBAAc,MAAM;AACpB,sBAAkB,MAAM;AACxB,gBAAY,GAAG,WAAW,WAAW,CAAC;AACtC,iBAAa,KAAK,WAAW,WAAW,CAAC;AACzC,eAAW,GAAG,WAAW,WAAW,CAAC;AACrC,eAAW,GAAG,WAAW,WAAW,CAAC;AAMrC,QAAI;AACJ,QAAI,aAAa;AACf,8BAAwB,IAAI;AAAA,QAC1B,MAAM;AAAA,QACN,MAAM,QAAQ,WAAW;AAAA,QACzB,MAAM,YAAY,QAAQ,aAAa,QAAQ,QAAQ,OAAO;AAAA,MAAA,CAC/D;AACD,gBAAU;AAAA,IACZ,OAAO;AACL,gBAAU,2BAA2B,WAAW,IAAI,WAAW;AAC/D,wBAAkB,IAAI,2BAA2B;AAAA,QAC/C,EAAE,MAAM,oBAAoB,YAAY,KAAA;AAAA,MAAK,CAC9C;AAMD,UAAI,WAAW;AACb,gCAAwB,IAAI;AAAA,UAC1B,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM,uBAAuB,OAAO,aAAa,IAC/C,QAAQ,WACV;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IACF;AASA,4BAAwB,IAAI,EAAE,MAAM,WAAW,MAAM,SAAS;AAC9D,yBAAqB,IAAI;AAAA,MACvB,MAAM;AAAA,MACN;AAAA,MACA,UAAU;AAAA,IAAA,CACX;AAED,QAAI,SAAS,UAAU;AACrB,wBAAkB,IAAI,2BAA2B;AAAA,QAC/C,EAAE,MAAM,eAAe,YAAY,KAAA;AAAA,MAAK,CACzC;AACD,8BAAwB,IAAI;AAAA,QAC1B,MAAM;AAAA,QACN,MAAM,sBAAsB,WAAW,IAAI,WAAW,KAAK,SAAS;AAAA,MAAA,CACrE;AAAA,IACH;AAAA,EACF,CAAC;AAGD,sBAAoB,WAAW,eAAe,CAAC,OAAO;AAKpD,UAAM,YAAY,cAAc,EAAE,EAAE,QAAA;AACpC,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,0BAA0B;AAC1D,UAAM,aAAa,cAAc,EAAE,EAChC,kBAAA,EACA,IAAI,CAAC,OAAO,GAAG,SAAS;AAO3B,UAAM,gBAAgB,cAClB,8BACA;AACJ,UAAM,oBAAoB,cAAc,CAAC,UAAU,SAAS,IAAI;AAChE,sBAAkB,IAAI,wBAAwB,CAAC,EAAE,MAAM,cAAA,CAAe,CAAC;AAEvE,QAAI,SAAS,aAAa;AACxB,wBAAkB,IAAI,cAAc;AAAA,QAClC,EAAE,MAAM,YAAA;AAAA,QACR,EAAE,MAAM,WAAA;AAAA,QACR,EAAE,MAAM,WAAW,YAAY,KAAA;AAAA,QAC/B,GAAI,cAAc,CAAC,EAAE,MAAM,UAAU,YAAY,KAAA,CAAM,IAAI,CAAA;AAAA,MAAC,CAC7D;AACD,wBAAkB,IAAI,0BAA0B,EAAE,GAAG;AAAA,QACnD,EAAE,MAAM,sBAAA;AAAA,MAAsB,CAC/B;AACD,yBAAmB,cAAc,EAAE,GAAG;AAAA,QACpC,MAAM,QAAQ;AAAA,QACd;AAAA,QACA;AAAA,QACA,mBAAmB,GAAG,WAAW,IAAI,WAAW,sCAAsC,SAAS,gBAAgB,UAAU;AAAA,QACzH,MAAM,cACF,sBAAsB,QAAQ,aAAa,MAAM,IACjD;AAAA;AAAA;AAAA;AAAA;AAAA,QAKJ,YAAY;AAAA,UACV,EAAE,MAAM,SAAS,MAAM,gBAAA;AAAA,UACvB,EAAE,MAAM,QAAQ,MAAM,UAAA;AAAA,QAAU;AAAA,QAElC,YAAY;AAAA,QACZ,YAAY;AAAA,MAAA,CACb;AACD;AAAA,IACF;AAEA,sBAAkB,IAAI,cAAc;AAAA,MAClC,EAAE,MAAM,YAAA;AAAA,MACR,EAAE,MAAM,WAAA;AAAA,MACR,EAAE,MAAM,UAAU,YAAY,KAAA;AAAA,MAC9B,GAAI,cACA;AAAA,QACE,EAAE,MAAM,UAAU,YAAY,KAAA;AAAA,QAC9B,EAAE,MAAM,WAAW,YAAY,KAAA;AAAA,MAAK,IAEtC,CAAA;AAAA,IAAC,CACN;AACD,sBAAkB,IAAI,0BAA0B,EAAE,GAAG;AAAA,MACnD,EAAE,MAAM,wBAAA;AAAA,MACR,EAAE,MAAM,iBAAA;AAAA,MACR,EAAE,MAAM,kBAAkB,YAAY,KAAA;AAAA,IAAK,CAC5C;AAID;AAAA,MACE;AAAA,MACA;AAAA,IAAA;AAEF,2BAAuB,IAAI,WAAW,kBAAkB,UAAU;AAClE,sBAAkB,cAAc,EAAE,GAAG,kBAAkB,EAAE,UAAU,IAAI;AAEvE,uBAAmB,cAAc,EAAE,GAAG;AAAA,MACpC,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,MACA,mBAAmB,GAAG,WAAW,IAAI,WAAW,kBAAkB,UAAU;AAAA,MAC5E,MAAM,cACF,sBAAsB,QAAQ,aAAa,MAAM,IACjD;AAAA;AAAA,MAEJ,YAAY,CAAC,EAAE,MAAM,QAAQ,MAAM,UAAU,UAAU,MAAM;AAAA,MAC7D,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MAAA,EACA,KAAK,IAAI;AAAA,IAAA,CACZ;AAAA,EACH,CAAC;AAGD,QAAM,OAAO,YACT,gBAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IAEF;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA;AAAA,IACA,YAAY,QAAQ;AAAA,EAAA,CACrB,IACD;AAEJ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,MAAM;AAAA,IACrB,sBAAsB,MAAM;AAAA,IAC5B,WAAW,QAAQ,GAAG,OAAO,aAAa,IAAI,KAAK,YAAY;AAAA,IAC/D,uBAAuB,MAAM;AAAA,IAC7B,cAAc,cACV,aAAa;AAAA,MACX,cAAc,QAAQ;AAAA,MACtB,aAAa,QAAQ;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,MAAM;AAAA,MACrB;AAAA,IAAA,CACD,IACD;AAAA,EAAA;AAER;ACz1BA,MAAM,sBAAsB;AAC5B,MAAM,sBAAsB;AA+B5B,SAAS,gCAAgC,QAAoC;AAC3E,QAAM,cAAc,KAAK,KAAK,QAAQ,cAAc;AACpD,MAAI,CAAC,GAAG,WAAW,WAAW,EAAG,QAAO;AACxC,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,GAAG,aAAa,aAAa,OAAO,CAAC;AAAA,EACxD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,aAAwC;AAAA,IAC5C,IAAI,UAAU,GAAG,GAAG,QAAQ;AAAA,IAC5B,IAAI,UAAU,GAAG,GAAG,SAAS;AAAA,IAC7B,IAAI,UAAU,GAAG,GAAG;AAAA,IACpB,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAEN,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,MAAM,KAAK,KAAK,QAAQ,GAAG;AACjC,UAAI,GAAG,WAAW,GAAG,EAAG,QAAO;AAAA,IACjC;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,wBACP,WACA,SACA,UAC0D;AAC1D,QAAM,OAAO,UAAU;AACvB,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,MAAgE,CAAA;AAEtE,MAAI,QAAQ,WAAW;AACrB,UAAM,MAAM,KAAK,WAAW,QAAQ,SAAS,IACzC,QAAQ,YACR,KAAK,KAAK,MAAM,QAAQ,SAAS;AACrC,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN,MAAM,IAAI,SAAS,OAAO,IAAI,iBAAiB;AAAA,IAAA,CAChD;AAAA,EACH;AAGA,QAAM,aAAa,kBAAkB,MAAM,YAAY,QAAQ;AAC/D,QAAM,aAAa,aACf,WAAW,cAAc,KAAK,KAAK,WAAW,MAAM,KAAK,IACzD;AACJ,aAAW,UAAU;AAAA,IACnB,cAAc,KAAK,KAAK,MAAM,UAAU;AAAA,IACxC,KAAK,KAAK,MAAM,YAAY,cAAc,KAAK;AAAA,EAAA,GAC9C;AACD,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,KAAK,KAAK,QAAQ,UAAU;AAC1C,QAAI,GAAG,WAAW,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,GAAG;AAC9D,UAAI,KAAK,EAAE,MAAM,OAAO,MAAM,UAAU;AAAA,IAC1C;AAAA,EACF;AAGA,QAAM,MAAM;AAAA,IACV,KAAK,KAAK,MAAM,gBAAgB,GAAG,WAAW,MAAM,GAAG,CAAC;AAAA,EAAA;AAE1D,MAAI,OAAO,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG;AAC3C,QAAI,KAAK,EAAE,MAAM,KAAK,MAAM,gBAAgB;AAAA,EAC9C;AAEA,SAAO;AACT;AAaA,SAAS,kBACP,MACoB;AACpB,QAAM,QAAQ,KAAK,QAAA,EAAU,cAAA;AAC7B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAkB,CAAA;AACxB,aAAW,KAAK,OAAO;AACrB,UAAM,KAAK,EAAE,gBAAA,EAAkB,CAAC,KAAK;AACrC,QAAI;AACJ,QAAI;AACF,WAAK,EAAE,kBAAkB,EAAE,EAAE,QAAQ,EAAE;AAAA,IACzC,QAAQ;AACN,WAAK;AAAA,IACP;AACA,UAAM,KAAK,KAAK,EAAE,SAAS,KAAK,EAAE,GAAG;AAAA,EACvC;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGA,SAAS,cAAc,MAAoC;AACzD,MAAI;AACJ,MAAI,KAAK,uBAAuB,IAAI,KAAK,KAAK,uBAAuB,IAAI,GAAG;AAG1E,UAAM,UAAU,kBAAkB,IAAI;AACtC,QAAI,SAAS;AACX,YAAM,OAAO,KAAK,QAAA;AAClB,YAAM,MAAM,KAAK,kBAAA,EAAoB,IAAI,CAAC,MAAM,EAAE,SAAS;AAC3D,YAAM,OAAO,IAAI,SAAS,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM;AACzD,YAAM,KAAK,KAAK,uBAAuB,IAAI,IAAI,cAAc;AAC7D,YAAM,OAAO,KAAK,uBAAuB,IAAI,IAAI,OAAO;AACxD,aAAO,GAAG,EAAE,IAAI,IAAI,GAAG,IAAI;AAAA,EAAK,OAAO;AAAA;AAAA,IACzC,OAAO;AACL,aAAO,KAAK,QAAA;AAAA,IACd;AAAA,EACF,WAAW,KAAK,kBAAkB,IAAI,GAAG;AACvC,WAAO,KAAK,QAAA;AAAA,EACd,WAAW,KAAK,sBAAsB,IAAI,GAAG;AAE3C,UAAM,OAAO,KAAK,QAAA;AAClB,UAAM,WAAW,KAAK,QAAA,EAAU,QAAQ,IAAI;AAC5C,WAAO,SAAS,IAAI,KAAK,QAAQ;AAAA,EACnC,WAAW,KAAK,sBAAsB,IAAI,GAAG;AAC3C,QAAI,KAAK,UAAW,MAAK,WAAA;AACzB,WAAO,KAAK,QAAA;AAAA,EACd,WAAW,KAAK,mBAAmB,IAAI,GAAG;AAGxC,UAAM,WAAW,CAAC,WAChB,OAAO,OAAO,aAAa,cAAc,OAAO,SAAA,MAAe;AACjE,eAAW,KAAK,KAAK,cAAA,OAAqB,SAAS,CAAC,EAAG,GAAE,OAAA;AACzD,eAAW,KAAK,CAAC,GAAG,KAAK,gBAAA,GAAmB,GAAG,KAAK,gBAAA,CAAiB,GAAG;AACtE,UAAI,SAAS,CAAC,EAAG,GAAE,OAAA;AAAA,IACrB;AACA,eAAW,KAAK,KAAK,cAAc;AACjC,UAAI,SAAS,CAAC,GAAG;AACf,UAAE,OAAA;AACF;AAAA,MACF;AACA,UAAI,EAAE,UAAW,GAAE,WAAA;AAAA,IACrB;AACA,eAAW,KAAK,KAAK,mBAAmB;AACtC,UAAI,EAAE,UAAW,GAAE,WAAA;AAAA,IACrB;AACA,WAAO,KAAK,QAAA;AAAA,EACd,OAAO;AACL,WAAO,KAAK,QAAA;AAAA,EACd;AACA,SAAO,KAAK,QAAQ,QAAQ,EAAE;AAC9B,MAAI,KAAK,SAAS,qBAAqB;AACrC,WAAO,KAAK,MAAM,GAAG,mBAAmB,IAAI;AAAA,EAC9C;AACA,SAAO;AACT;AAEO,SAAS,cACd,WACA,SACA,UACqB;AACrB,QAAM,SAAS,QAAQ;AACvB,QAAM,aAAa,wBAAwB,WAAW,SAAS,QAAQ;AACvE,QAAM,eAAe,WAAW;AAAA,IAAI,CAAC,MACnC,KAAK,SAAS,UAAU,MAAM,EAAE,IAAI;AAAA,EAAA;AAGtC,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV,cAAc,CAAA;AAAA,MACd;AAAA,MACA,SACE;AAAA,IAAA;AAAA,EAEN;AAEA,QAAM,UAAU,IAAI,QAAQ;AAAA,IAC1B,6BAA6B;AAAA,IAC7B,iBAAiB,EAAE,SAAS,OAAO,cAAc,KAAA;AAAA,EAAK,CACvD;AAED,aAAW,aAAa,YAAY;AAClC,QAAI;AACJ,QAAI;AACF,WAAK,QAAQ,oBAAoB,UAAU,IAAI;AAAA,IACjD,QAAQ;AACN;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,iBAAW,GAAG,wBAAA;AAAA,IAChB,QAAQ;AACN;AAAA,IACF;AACA,UAAM,QAAQ,SAAS,IAAI,MAAM;AACjC,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAElC,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV,MAAM,UAAU;AAAA,MAChB,WAAW,KAAK,SAAS,UAAU,MAAM,UAAU,IAAI;AAAA,MACvD;AAAA,MACA,cAAc,MAAM,IAAI,CAAC,MAAM;AAC7B,eAAO;AAAA,UACL,MAAM,EAAE,YAAA;AAAA,UACR,MAAM,KAAK,SAAS,UAAU,MAAM,EAAE,gBAAgB,aAAa;AAAA,UACnE,WAAW,cAAc,CAAC;AAAA,QAAA;AAAA,MAE9B,CAAC;AAAA,IAAA;AAAA,EAEL;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV,cAAc,CAAA;AAAA,IACd;AAAA,IACA,SAAS,WAAW,MAAM,wCAAwC,aAAa;AAAA,MAC7E;AAAA,IAAA,CACD;AAAA,EAAA;AAEL;AC1PA,SAAS,iBAAiB,UAAiC;AACzD,MAAI;AACJ,MAAK,IAAI,SAAS,MAAM,8BAA8B,EAAI,QAAO,EAAE,CAAC;AACpE,MAAK,IAAI,SAAS,MAAM,oCAAoC,EAAI,QAAO,EAAE,CAAC;AAC1E,MAAK,IAAI,SAAS,MAAM,mDAAmD;AACzE,WAAO,EAAE,CAAC;AACZ,SAAO;AACT;AAEO,SAAS,cACd,WACA,SACA,UACkB;AAClB,QAAM,EAAE,cAAA,IAAkB,qBAAqB,WAAW,SAAS,QAAQ;AAC3E,QAAM,UAAU,UAAU,KAAK,aAAa;AAC5C,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,yBAAyB,aAAa,EAAE;AAAA,EAC1D;AAEA,QAAM,UAAU,IAAI,QAAQ,EAAE,uBAAuB,MAAM;AAC3D,QAAM,KAAK,QAAQ,iBAAiB,eAAe,SAAS;AAAA,IAC1D,WAAW;AAAA,EAAA,CACZ;AACD,QAAM,WAAgC,CAAA;AAGtC,QAAM,cAAc,GAAG,aAAa,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,CAAC;AAC1E,MAAI,CAAC,aAAa;AAChB,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAEA,QAAM,UAAU,GAAG,sBAAA;AAGnB,QAAM,aAAa,QAAQ;AAAA,IAAK,CAAC,MAC/B,uBAAuB,KAAK,EAAE,yBAAyB;AAAA,EAAA;AAEzD,MAAI,YAAY;AACd,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SACE;AAAA,IAAA,CACH;AAAA,EACH;AAIA,QAAM,uBAAuB,QAAQ;AAAA,IACnC,CAAC,MACC,EAAE,wBAAA,MAA8B,6BAChC,EAAE,gBAAA,EAAkB,KAAK,CAAC,MAAM,EAAE,QAAA,MAAc,mBAAmB;AAAA,EAAA;AAEvE,MAAI,sBAAsB;AACxB,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SACE;AAAA,IAAA,CACH;AAAA,EACH;AAGA,aAAW,OAAO,GAAG,cAAc;AACjC,eAAW,QAAQ,IAAI,iBAAiB;AACtC,YAAM,OAAO,KAAK,QAAA;AAClB,YAAM,YAAY,KAAK,YAAA,GAAe,QAAA,KAAa,IAChD,QAAQ,QAAQ,GAAG,EACnB,KAAA;AACH,YAAM,WAAW,KAAK,eAAA,GAAkB,aAAa;AACrD,YAAM,WAAW,CAAC,CAAC,KAAK,aAAa,UAAU;AAE/C,YAAM,mBACJ,4BAA4B,KAAK,QAAQ,KACzC,4BAA4B,KAAK,QAAQ;AAE3C,UAAI,oBAAoB,CAAC,UAAU;AACjC,iBAAS,KAAK;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS,aAAa,IAAI;AAAA,QAAA,CAC3B;AACD;AAAA,MACF;AAEA,YAAM,OAAO,iBAAiB,QAAQ;AACtC,UAAI,QAAQ,CAAC,kBAAkB;AAC7B,iBAAS,KAAK;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS,aAAa,IAAI,cAAc,QAAQ,2CAA2C,IAAI;AAAA,QAAA,CAChG;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO;AACzD,SAAO,EAAE,eAAe,IAAI,CAAC,UAAU,SAAA;AACzC;AC/HO,MAAM,eAAe;AAAA,EAC1B,KAAK;AAAA,EACL,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,KAAK;AAAA,EACL,cAAc;AAAA,EACd,QAAQ;AACV;AAKO,MAAM,wBAAgD;AAAA,EAC3D,CAAC,aAAa,KAAK,GAAG;AAAA,EACtB,CAAC,aAAa,GAAG,GAAG;AAAA,EACpB,CAAC,aAAa,OAAO,GAAG;AAAA,EACxB,CAAC,aAAa,OAAO,GAAG;AAAA,EACxB,CAAC,aAAa,GAAG,GAAG;AAAA,EACpB,CAAC,aAAa,cAAc,GAAG;AAAA,EAC/B,CAAC,aAAa,YAAY,GAAG;AAAA,EAC7B,CAAC,aAAa,MAAM,GAAG;AACzB;AAGO,MAAM,6CAAkD,IAAI;AAAA,EACjE,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AACf,CAAC;AA0DM,MAAM,iBAAiB;AAAA,EAC5B,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,OAAO;AAAA,EACP,UAAU;AACZ;ACtEO,MAAe,kBAA2C;AAAA,EAS/D,qBAA6B;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,uBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKU,iBACR,SACA,cACkB;AAClB,UAAM,WAAW,KAAK,iBAAiB,OAAO;AAE9C,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,WAAW,QAAQ;AAAA,MACnB,UAAU,SAAS,QAAQ;AAAA,IAAA;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA,EAKU,iBAAiB,SAA6C;AACtE,WAAO,GAAG,QAAQ,YAAY,IAAI,KAAK,eAAe,IAAI,QAAQ,YAAY,IAAI,QAAQ,YAAY;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA,EAKU,gBAAgB,SAA6C;AACrE,WAAO,GAAG,QAAQ,UAAU,IAAI,QAAQ,aAAa;AAAA,EACvD;AACF;AC7EO,MAAM,iCAAiC,kBAAkB;AAAA,EACpD,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI,GAAG,YAAY;AAAA,MACnB,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,aAAa,CAAC,YAAY;AAAA,MAAA;AAAA,MAE5B,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;AC7BO,MAAM,yBAAyB,kBAAkB;AAAA,EAC5C,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI;AAAA,MACJ,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,KAAK,CAAC,YAAY;AAAA,MAAA;AAAA,MAEpB,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;AC7BO,MAAM,4BAA4B,kBAAkB;AAAA,EAC/C,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY,IAClC,QAAQ,mBAAmB,QAC7B;AAGA,UAAM,sBAAsB,QAAQ,mBAAmB;AAEvD,UAAM,eAAe;AAAA,MACnB,IAAI;AAAA,MACJ,OAAO,GAAG,YAAY,IAAI,mBAAmB;AAAA,MAC7C,WAAW,QAAQ;AAAA,MACnB;AAAA;AAAA;AAAA,IAAA;AAKF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,CAAC,mBAAmB,GAAG,CAAC,YAAY;AAAA,MAAA;AAAA,MAEtC,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AAAA,EAES,kBAA0B;AAEjC,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA,EAEmB,iBACjB,SACQ;AAER,UAAM,UAAU,QAAQ,mBAAmB;AAC3C,WAAO,GAAG,QAAQ,YAAY,IAAI,OAAO,IAAI,QAAQ,YAAY,IAAI,QAAQ,YAAY;AAAA,EAC3F;AACF;AClDO,MAAM,gCAAgC,kBAAkB;AAAA,EACnD,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,WAAW,KAAK,iBAAiB,OAAO;AAE9C,UAAM,aAAa;AAAA,MACjB,IAAI,GAAG,QAAQ,UAAU,IAAI,QAAQ,aAAa;AAAA,MAClD,OAAO;AAAA,MACP,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB,UAAU,SAAS,QAAQ;AAAA,IAAA;AAG7B,WAAO;AAAA,MACL,eAAe,CAAA;AAAA,MACf,aAAa,CAAA;AAAA,MACb,OAAO;AAAA,QACL,CAAC,KAAK,cAAA,CAAe,GAAG,CAAC,UAAU;AAAA,MAAA;AAAA,IACrC;AAAA,EAEJ;AAAA,EAEQ,gBAAwB;AAC9B,WAAO;AAAA,EACT;AAAA,EAES,kBAA0B;AACjC,WAAO;AAAA,EACT;AACF;ACjCO,MAAM,yBAAyB,kBAAkB;AAAA,EAC5C,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI,GAAG,YAAY;AAAA,MACnB,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,eAAe,QAAQ;AAAA,MACvB;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,UAAU,CAAC,YAAY;AAAA,MAAA;AAAA,MAEzB,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;AC9BO,MAAM,6BAA6B,kBAAkB;AAAA,EAChD,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI,GAAG,YAAY;AAAA,MACnB,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,eAAe,QAAQ,SAAS;AAAA,MAChC;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,UAAU,CAAC,YAAY;AAAA,MAAA;AAAA,MAEzB,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;AC9BO,MAAM,2BAA2B,kBAAkB;AAAA,EAC9C,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI,GAAG,YAAY;AAAA,MACnB,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,iBAAiB,QAAQ;AAAA,MACzB;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,WAAW,CAAC,YAAY;AAAA,MAAA;AAAA,MAE1B,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;AC9BO,MAAM,mCAAmC,kBAAkB;AAAA,EACtD,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI,GAAG,YAAY;AAAA,MACnB,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,aAAa,QAAQ;AAAA,MACrB;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,gBAAgB,CAAC,YAAY;AAAA,MAAA;AAAA,MAE/B,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;AC9BO,MAAM,6BAA6B,kBAAkB;AAAA,EAChD,aAAa,aAAa;AAAA,EAC1B,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAEzB,oBACE,SACqB;AACrB,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,UAAM,eAAe,GAAG,YAAY;AAEpC,UAAM,eAAe;AAAA,MACnB,IAAI,GAAG,YAAY;AAAA,MACnB,OAAO,GAAG,YAAY;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,gBAAgB,QAAQ;AAAA,MACxB;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK,iBAAiB,SAAS,YAAY;AAE9D,WAAO;AAAA,MACL,eAAe;AAAA,QACb,WAAW,CAAC,YAAY;AAAA,MAAA;AAAA,MAE1B,aAAa;AAAA,QACX,CAAC,YAAY,GAAG;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AACF;ACtBO,MAAM,qBAAqB;AAAA,EAChC,OAAe,WAAiD,oBAAI,IAGlE;AAAA,IACA,CAAC,aAAa,KAAK,gBAAgB;AAAA,IACnC,CAAC,aAAa,SAAS,oBAAoB;AAAA,IAC3C,CAAC,aAAa,SAAS,oBAAoB;AAAA,IAC3C,CAAC,aAAa,OAAO,kBAAkB;AAAA,IACvC,CAAC,aAAa,KAAK,gBAAgB;AAAA,IACnC,CAAC,aAAa,cAAc,wBAAwB;AAAA,IACpD,CAAC,aAAa,gBAAgB,0BAA0B;AAAA,IACxD,CAAC,aAAa,QAAQ,mBAAmB;AAAA,EAAA,CAC1C;AAAA,EAED,OAAO,cAAc,YAAoC;AACvD,QAAI,CAAC,YAAY;AACf,aAAO,IAAI,wBAAA;AAAA,IACb;AAEA,UAAM,eAAe,KAAK,SAAS,IAAI,UAAU;AAEjD,QAAI,CAAC,cAAc;AACjB,cAAQ;AAAA,QACN,qCAAqC,UAAU;AAAA,MAAA;AAEjD,aAAO,IAAI,wBAAA;AAAA,IACb;AAEA,WAAO,IAAI,aAAA;AAAA,EACb;AAAA,EAEA,OAAO,kBAAkB,MAAuB;AAC9C,WAAO,KAAK,SAAS,IAAI,IAAI;AAAA,EAC/B;AACF;ACpCO,SAAS,uBACd,WACA,iBACA,iBACA,YACA,SACM;AACN;AAAA,IACE;AAAA,IACA,KAAK,KAAK,iBAAiB,eAAe;AAAA,IAC1C;AAAA,IACA;AAAA,EAAA;AAIF,MAAI,QAAQ,eAAe;AACzB,kBAAc,WAAW,YAAY,OAAO;AAAA,EAC9C;AACF;AAKA,SAAS,cACP,WACA,YACA,SACM;AACN,QAAM,UAAU,KAAK,KAAK,YAAY,GAAG,QAAQ,YAAY,MAAM;AAEnE,MAAI,UAAU,OAAO,OAAO,GAAG;AAC7B,cAAU,OAAO,OAAO;AAAA,EAC1B;AACF;ACxCO,MAAM,iBAAiB;AAAA,EACpB,gBAAuC,CAAA;AAAA,EACvC,cAAmC,CAAA;AAAA,EACnC,QAA+B,CAAA;AAAA;AAAA;AAAA;AAAA,EAKvC,uBAAuB,QAAmC;AAExD,WAAO,QAAQ,OAAO,aAAa,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC7D,WAAK,cAAc,GAAG,IAAI,CAAC,GAAI,KAAK,cAAc,GAAG,KAAK,IAAK,GAAG,KAAK;AAAA,IACzE,CAAC;AAGD,WAAO,OAAO,KAAK,aAAa,OAAO,WAAW;AAGlD,QAAI,OAAO,OAAO;AAChB,aAAO,QAAQ,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACrD,aAAK,MAAM,GAAG,IAAI,CAAC,GAAI,KAAK,MAAM,GAAG,KAAK,IAAK,GAAG,KAAK;AAAA,MACzD,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,WAA8B,eAA6B;AACrE,eAAW,WAAW,eAAe,CAAC,SAAc;AAElD,YAAM,YAAY,KAAK,oBAAoB,IAAI;AAG/C,aAAO,QAAQ,KAAK,aAAa,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC3D,kBAAU,YAAY,GAAG,IAAI;AAAA,UAC3B,GAAI,UAAU,YAAY,GAAG,KAAK,CAAA;AAAA,UAClC,GAAG;AAAA,QAAA;AAAA,MAEP,CAAC;AAGD,gBAAU,YAAY,cAAc;AAAA,QAClC,GAAG,UAAU,YAAY;AAAA,QACzB,GAAG,KAAK;AAAA,MAAA;AAIV,UAAI,OAAO,KAAK,KAAK,KAAK,EAAE,SAAS,GAAG;AACtC,kBAAU,YAAY,QAAQ,UAAU,YAAY,SAAS,CAAA;AAE7D,eAAO,QAAQ,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACnD,oBAAU,YAAY,MAAM,GAAG,IAAI;AAAA,YACjC,GAAI,UAAU,YAAY,MAAM,GAAG,KAAK,CAAA;AAAA,YACxC,GAAG;AAAA,UAAA;AAAA,QAEP,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,MAAgB;AAC1C,SAAK,QAAQ,CAAA;AACb,SAAK,IAAI,OAAO,CAAA;AAChB,SAAK,IAAI,GAAG,WAAW,CAAA;AACvB,SAAK,IAAI,GAAG,OAAO,gBAAgB,CAAA;AAEnC,WAAO,KAAK,IAAI,GAAG;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAA2B;AAChC,WAAO,IAAI,iBAAA;AAAA,EACb;AACF;AClFO,SAAS,mBACd,WACA,aACA,SACA,YACM;AACN,QAAM,aAAa,KAAK;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,QAAQ,UAAU;AAAA,EAAA;AAGvB,MAAI,CAAC,UAAU,OAAO,UAAU,GAAG;AACjC,YAAQ,KAAK,0BAA0B,UAAU,EAAE;AACnD;AAAA,EACF;AAEA,aAAW,WAAW,YAAY,CAAC,SAAc;AAE/C,SAAK,QAAQ,UAAU,IAAI,KAAK,QAAQ,UAAU,KAAK,CAAA;AACvD,SAAK,QAAQ,UAAU,EAAE,QAAQ,aAAa,IAC5C,KAAK,QAAQ,UAAU,EAAE,QAAQ,aAAa,KAAK,CAAA;AAGrD,SAAK,QAAQ,UAAU,EAAE,QAAQ,aAAa,EAAE,UAAU,IAAI;AAAA,MAC5D,GAAG,KAAK,QAAQ,UAAU,EAAE,QAAQ,aAAa,EAAE,UAAU;AAAA,MAC7D,OAAO,QAAQ;AAAA,IAAA;AAGjB,WAAO;AAAA,EACT,CAAC;AACH;ACjCO,MAAM,wBAAwB,MAAM;AAAA,EACzC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,SAAS,gBACd,WACA,SACA,UACM;AAEN,MAAI,CAAC,QAAQ,MAAM;AACjB,UAAM,IAAI,gBAAgB,4BAA4B;AAAA,EACxD;AAEA,MAAI,CAAC,QAAQ,YAAY;AACvB,UAAM,IAAI,gBAAgB,yBAAyB;AAAA,EACrD;AAGA,QAAM,UAAU;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EAAA;AAEF,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR,YAAY,QAAQ,UAAU;AAAA,IAAA;AAAA,EAElC;AAGA,MACE,QAAQ,cACR,CAAC,qBAAqB,kBAAkB,QAAQ,UAAU,GAC1D;AACA,YAAQ;AAAA,MACN,wBAAwB,QAAQ,UAAU;AAAA,IAAA;AAAA,EAG9C;AAGA,MAAI,QAAQ,eAAe,aAAa,CAAC,QAAQ,OAAO;AACtD,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;AC5BO,SAAS,kBACd,WACA,aACA,SACA,UACM;AAEN,kBAAgB,WAAW,SAAS,QAAQ;AAG5C,QAAM,aAAa,eAAe,WAAW,SAAS,QAAQ;AAG9D,QAAM,gBAAgB;AAAA,IACpB,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EAAA;AAGF,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI;AAAA,MACR,YAAY,WAAW,UAAU;AAAA,IAAA;AAAA,EAErC;AAEA,QAAM,cAAc,cAAc;AAElC,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR,oCAAoC,WAAW,UAAU;AAAA,IAAA;AAAA,EAE7D;AAGA,gBAAc,WAAW,aAAa,aAAa,UAAU;AAG7D,MAAI,QAAQ,YAAY;AACtB,8BAA0B,WAAW,eAAe,UAAU;AAAA,EAChE;AACF;AAKA,SAAS,eACP,WACA,SACA,UAC4B;AAC5B,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,cAAc;AAAA,IAAA;AAAA,IAEhB;AAAA,EAAA;AAIF,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EAAA;AAGF,QAAM,oBACH,WAAW,WAAW,UAAkB,WAAW,UAAU;AAGhE,aAAW,eAAe,QAAQ,gBAAgB;AAClD,aAAW,OACT,sBAAsB,QAAQ,cAAc,EAAE,KAAK,QAAQ;AAG7D,MAAI,QAAQ,iBAAiB;AAC3B,eAAW,kBAAkB,QAAQ;AAAA,EACvC;AAEA,SAAO;AACT;AAKA,SAAS,cACP,WACA,aACA,aACA,SACM;AAEN,QAAM,UAAU,qBAAqB,cAAc,QAAQ,UAAU;AACrE,QAAM,eAAe,QAAQ,gBAAA;AAG7B,QAAM,aAAa,KAAK;AAAA,IACtB;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAIV;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAKA,SAAS,0BACP,WACA,eACA,SACM;AACN,QAAM,gBAAgB,KAAK,KAAK,cAAc,MAAM,WAAW;AAE/D,MAAI,CAAC,UAAU,OAAO,aAAa,GAAG;AACpC,YAAQ,KAAK,yBAAyB,aAAa,EAAE;AACrD;AAAA,EACF;AAGA,QAAM,UAAU,qBAAqB,cAAc,QAAQ,UAAU;AACrE,QAAM,eAAe,QAAQ,oBAAoB,OAAO;AAGxD,QAAM,UAAU,iBAAiB,OAAA;AACjC,UAAQ,uBAAuB,YAAY;AAC3C,UAAQ,YAAY,WAAW,aAAa;AAG5C,MAAI,QAAQ,0BAA0B,cAAc,YAAY;AAC9D;AAAA,MACE;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,QAAQ,mBAAA;AAAA,IAAmB;AAAA,EAE/B;AACF;AC3JA,SAAS,MAAM,SAA6B;AAE1C,QAAM,eAAe,uBAAuB,KAAK,OAAO;AACxD,QAAM,UAAU,IAAI,QAAQ;AAAA,IAC1B,uBAAuB;AAAA,IACvB,sBAAsB;AAAA,MACpB,iBAAiB,gBAAgB;AAAA,MACjC,WAAW,eAAe,UAAU,SAAS,UAAU;AAAA,IAAA;AAAA,EACzD,CACD;AACD,SAAO,QAAQ,iBAAiB,yBAAyB,SAAS;AAAA,IAChE,WAAW;AAAA,EAAA,CACZ;AACH;AAGA,SAAS,WAAW,IAAgB,MAAgC;AAClE,SAAO,GAAG,qBAAqB,WAAW,cAAc,EAAE,OAAO,CAAC,SAAS;AACzE,UAAM,SAAS,KAAK,cAAA;AACpB,WACE,OAAO,cAAc,WAAW,4BAChC,OAAO,cAAc,WAAW,wBAAwB,EAAE,QAAA,MACxD;AAAA,EAEN,CAAC;AACH;AAGA,SAAS,aAAa,IAAgB,MAA8B;AAClE,QAAM,OAAO,GAAG,YAAA;AAChB,QAAM,WAAW,KACd,cAAA,EACA,cAAc,WAAW,wBAAwB,EACjD,YAAA;AACH,QAAM,YAAY,KAAK,YAAY,MAAM,SAAS,SAAA,CAAU,IAAI;AAChE,SAAO,KAAK,MAAM,SAAS,EAAE,MAAM,SAAS,IAAI,CAAC,KAAK;AACxD;AAGO,SAAS,kBAAkB,SAAyB;AACzD,SAAO,WAAW,MAAM,OAAO,GAAG,OAAO,EAAE;AAC7C;AAEO,SAAS,iBACd,SACA,MACA,YACwB;AACxB,QAAM,KAAK,MAAM,OAAO;AAExB,QAAM,aAAa,WAAW,IAAI,OAAO;AACzC,QAAM,aAAa,WAAW,KAAK,CAAC,SAAS;AAC3C,UAAM,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,aAAA;AAC5B,WAAO,KAAK,WAAW,KAAK,KAAK,cAAc;AAAA,EACjD,CAAC;AACD,MAAI,WAAY,QAAO,EAAE,SAAS,OAAO,MAAM,qBAAA;AAG/C,MAAI;AACJ,MAAI;AACJ,MAAI,WAAW,SAAS,GAAG;AACzB,aAAS,WAAW;AAAA,MAAO,CAAC,MAAM,SAChC,KAAK,WAAW,KAAK,OAAA,IAAW,OAAO;AAAA,IAAA;AAEzC,aAAS,aAAa,IAAI,MAAM;AAAA,EAClC,OAAO;AAEL,UAAM,SAAS,WAAW,IAAI,QAAQ,EAAE;AAAA,MACtC,CAAC,SAAS,KAAK,aAAA,EAAe,WAAW;AAAA,IAAA;AAE3C,aAAS,OAAO,OAAO,SAAS,CAAC;AACjC,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,MAAA;AAAA,IAEX;AACA,UAAM,OAAO,GAAG,YAAA;AAChB,UAAM,YAAY,KAAK,YAAY,MAAM,OAAO,SAAA,CAAU,IAAI;AAC9D,cAAU,KAAK,MAAM,SAAS,EAAE,MAAM,SAAS,IAAI,CAAC,KAAK,MAAM;AAAA,EACjE;AACA,SAAO,gBAAgB,GAAG,OAAO,QAAA,CAAS;AAAA,EAAK,MAAM,UAAU,IAAI,GAAG;AAEtE,QAAM,WAAW,GACd,sBAAA,EACA;AAAA,IAAK,CAAC,SACL,KAAK,kBAAkB,KAAK,CAAC,UAAU,MAAM,QAAA,MAAc,IAAI;AAAA,EAAA;AAEnE,MAAI,CAAC,SAAU,mBAAkB,IAAI,YAAY,CAAC,EAAE,MAAM,KAAA,CAAM,CAAC;AAEjE,SAAO,EAAE,SAAS,MAAM,SAAS,GAAG,YAAA,GAAe,aAAa,CAAC,SAAA;AACnE;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../packages/kos-codegen-core/src/lib/codegen-filesystem.ts","../../../packages/kos-codegen-core/src/lib/logger.ts","../../../packages/kos-codegen-core/src/lib/generate-files.ts","../../../packages/kos-codegen-core/src/lib/project-discovery.ts","../../../packages/kos-codegen-core/src/lib/json-utils.ts","../../../packages/kos-codegen-core/src/lib/format-files.ts","../../../packages/kos-codegen-core/src/lib/name-utils.ts","../../../packages/kos-codegen-core/src/lib/normalize-values.ts","../../../packages/kos-codegen-core/src/lib/kos-config.ts","../../../packages/kos-codegen-core/src/lib/template-resolver.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-splash-project.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-model-project.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-init.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-polyglot-workspace.ts","../../../packages/kos-codegen-core/src/lib/generators/kab-targets.ts","../../../packages/kos-codegen-core/src/lib/generators/ci-sync.ts","../../../packages/kos-codegen-core/src/lib/generators/java-workspace.ts","../../../packages/kos-codegen-core/src/lib/generators/normalize-options.ts","../../../packages/kos-codegen-core/src/lib/generators/release-version-script.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/ts-toolkit.ts","../../../packages/kos-codegen-core/src/lib/generators/service-catalog.ts","../../../packages/kos-codegen-core/src/lib/generators/barrel-utils.ts","../../../packages/kos-codegen-core/src/lib/generators/update-model-index.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-companion-model.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-container-model.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-context.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-hook.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-model.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/find-model-declaration.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/resolve-model-file.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/resolve-child-model.ts","../../../packages/kos-codegen-core/src/lib/generators/generate-view-model.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/model-services.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/normalize-options.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/model-transformer.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/service-transformer.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/registration-transformer.ts","../../../packages/kos-codegen-core/src/lib/generators/add-future-to-model/generate-add-future-to-model.ts","../../../packages/kos-codegen-core/src/lib/generators/add-container-support/generate-add-container-support.ts","../../../packages/kos-codegen-core/src/lib/generators/add-parent-aware/generate-add-parent-aware.ts","../../../packages/kos-codegen-core/src/lib/generators/describe/describe-model.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-model-effect.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-dependency.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-child.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-topic-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-config-property.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-property.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-computed.ts","../../../packages/kos-codegen-core/src/lib/generators/augment/model-mocks.ts","../../../packages/kos-codegen-core/src/lib/generators/member-mutators/add-service-request.ts","../../../packages/kos-codegen-core/src/lib/generators/types/lookup-sdk-type.ts","../../../packages/kos-codegen-core/src/lib/generators/validate/validate-model.ts","../../../packages/kos-codegen-core/src/lib/generators/component/types.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/base.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/control-pour-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/cui-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/custom-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/default-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/nav-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/setting-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/setup-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/trouble-action-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/utility-handler.ts","../../../packages/kos-codegen-core/src/lib/generators/component/plugin-handlers/factory.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/file-generator.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/kos-config-builder.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/localization.ts","../../../packages/kos-codegen-core/src/lib/generators/component/utils/validation.ts","../../../packages/kos-codegen-core/src/lib/generators/component/generate-component.ts","../../../packages/kos-codegen-core/src/lib/generators/registration/upsert-chain-entry.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\n/**\n * Abstraction over a filesystem for code generation.\n *\n * Mirrors the subset of the Nx Tree API that generators actually use,\n * enabling the same generator logic to run against the real filesystem\n * (CLI, VS Code extension) or an in-memory tree (Nx adapter).\n */\nexport interface CodegenFileSystem {\n /** Workspace root directory (absolute path). */\n readonly root: string;\n\n /** Read a file relative to the workspace root. Returns null if not found. */\n read(filePath: string): string | null;\n\n /** Write a file relative to the workspace root. Creates parent dirs as needed. */\n write(filePath: string, content: string): void;\n\n /** Check whether a file exists relative to the workspace root. */\n exists(filePath: string): boolean;\n\n /** Delete a file relative to the workspace root. No-op if not found. */\n delete(filePath: string): void;\n\n /** List all files under a directory (relative to root), returned as root-relative paths. */\n listFiles(dirPath: string): string[];\n}\n\n/**\n * CodegenFileSystem wrapper that records absolute paths of every file written.\n * Wrap any CodegenFileSystem to collect written paths for post-generation steps\n * such as formatting.\n *\n * @example\n * const fs = new TrackingFileSystem(new DirectFileSystem(cwd));\n * generateModel({ codegenFs: fs, ... });\n * await formatFiles(fs.root, fs.writtenPaths);\n */\nexport class TrackingFileSystem implements CodegenFileSystem {\n private readonly inner: CodegenFileSystem;\n private readonly _writtenPaths: string[] = [];\n\n constructor(inner: CodegenFileSystem) {\n this.inner = inner;\n }\n\n get root(): string {\n return this.inner.root;\n }\n\n get writtenPaths(): string[] {\n return [...this._writtenPaths];\n }\n\n read(filePath: string): string | null {\n return this.inner.read(filePath);\n }\n\n write(filePath: string, content: string): void {\n this.inner.write(filePath, content);\n this._writtenPaths.push(\n path.isAbsolute(filePath)\n ? filePath\n : path.join(this.inner.root, filePath)\n );\n }\n\n exists(filePath: string): boolean {\n return this.inner.exists(filePath);\n }\n\n delete(filePath: string): void {\n this.inner.delete(filePath);\n }\n\n listFiles(dirPath: string): string[] {\n return this.inner.listFiles(dirPath);\n }\n}\n\n/**\n * CodegenFileSystem backed by the real Node.js filesystem.\n * All paths passed to interface methods are relative to the workspace root.\n */\nexport class DirectFileSystem implements CodegenFileSystem {\n readonly root: string;\n\n constructor(workspaceRoot: string) {\n this.root = path.resolve(workspaceRoot);\n }\n\n read(filePath: string): string | null {\n const abs = this.resolve(filePath);\n try {\n return fs.readFileSync(abs, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n write(filePath: string, content: string): void {\n const abs = this.resolve(filePath);\n fs.mkdirSync(path.dirname(abs), { recursive: true });\n fs.writeFileSync(abs, content, \"utf-8\");\n }\n\n exists(filePath: string): boolean {\n return fs.existsSync(this.resolve(filePath));\n }\n\n delete(filePath: string): void {\n const abs = this.resolve(filePath);\n try {\n fs.unlinkSync(abs);\n } catch {\n // no-op if file doesn't exist\n }\n }\n\n listFiles(dirPath: string): string[] {\n const abs = this.resolve(dirPath);\n if (!fs.existsSync(abs)) {\n return [];\n }\n return this.walkDir(abs).map((file) => path.relative(this.root, file));\n }\n\n private resolve(filePath: string): string {\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n return path.join(this.root, filePath);\n }\n\n private walkDir(dir: string): string[] {\n const results: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...this.walkDir(full));\n } else {\n results.push(full);\n }\n }\n return results;\n }\n}\n","/**\n * Settable logger interface for kos-codegen-core.\n *\n * Consumers (CLI, VS Code extension, Nx adapter) set their own logger\n * via setCodegenLogger(). Defaults to silent no-op.\n */\nexport interface CodegenLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst noopLogger: CodegenLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nlet activeLogger: CodegenLogger = noopLogger;\n\nexport function setCodegenLogger(logger: CodegenLogger): void {\n activeLogger = logger;\n}\n\nexport function getCodegenLogger(): CodegenLogger {\n return activeLogger;\n}\n","/**\n * EJS-based file generation — replaces @nx/devkit generateFiles().\n *\n * Walks a source template directory, processes each file through EJS,\n * interpolates __var__ tokens in filenames, strips .template suffixes,\n * and writes results via a CodegenFileSystem.\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as ejs from \"ejs\";\nimport type { CodegenFileSystem } from \"./codegen-filesystem\";\nimport { getCodegenLogger } from \"./logger\";\n\n/**\n * Generate files from a template directory into a destination path.\n *\n * Behavior matches @nx/devkit generateFiles():\n * - Walks `srcFolder` recursively\n * - For each file, replaces `__propName__` in the filename using `substitutions`\n * - Strips `.template` suffix from filenames\n * - Processes file contents through EJS with `substitutions` as data\n * - Writes the result to `destFolder` (relative to fs.root) via the CodegenFileSystem\n *\n * @param codegenFs - Target filesystem abstraction\n * @param srcFolder - Absolute path to the template directory\n * @param destFolder - Destination path relative to the filesystem root\n * @param substitutions - Key-value pairs for EJS and filename interpolation\n */\nexport function generateFilesFromTemplates(\n codegenFs: CodegenFileSystem,\n srcFolder: string,\n destFolder: string,\n substitutions: Record<string, any>\n): void {\n const logger = getCodegenLogger();\n const templateFiles = walkTemplateDir(srcFolder);\n\n for (const templateFile of templateFiles) {\n const relPath = path.relative(srcFolder, templateFile);\n\n // Interpolate __var__ tokens in the path segments\n let destRelPath = interpolateFilename(relPath, substitutions);\n\n // Strip .template suffix\n if (destRelPath.endsWith(\".template\")) {\n destRelPath = destRelPath.slice(0, -\".template\".length);\n }\n\n const destPath = path.join(destFolder, destRelPath);\n\n // Templates are read from the real filesystem (package assets),\n // while outputs are written through CodegenFileSystem.\n const rawContent = fs.readFileSync(templateFile, \"utf-8\");\n const rendered = ejs.render(rawContent, substitutions, {\n filename: templateFile, // for EJS error messages and includes\n });\n\n logger.debug(`Generating ${destPath}`);\n codegenFs.write(destPath, rendered);\n }\n}\n\n/**\n * Replace `__propName__` tokens in a file path with values from substitutions.\n * E.g., `__nameDashCase__-model.ts` with `{ nameDashCase: \"my-widget\" }` becomes\n * `my-widget-model.ts`.\n */\nfunction interpolateFilename(\n filePath: string,\n substitutions: Record<string, any>\n): string {\n return filePath.replace(/__([^_]+)__/g, (match, key: string) => {\n if (key in substitutions) {\n return String(substitutions[key]);\n }\n return match; // leave unmatched tokens as-is\n });\n}\n\nfunction walkTemplateDir(dir: string): string[] {\n const results: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...walkTemplateDir(full));\n } else {\n results.push(full);\n }\n }\n return results;\n}\n","/**\n * Nx-free project discovery — scans for project.json files in the workspace.\n *\n * Replaces @nx/devkit readProjectConfiguration, getProjects, readNxJson.\n * Based on the pattern in kos-model-extension/src/utils/workspace-scanner.ts.\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport fg from \"fast-glob\";\nimport { getCodegenLogger } from \"./logger\";\n\nexport interface ProjectConfiguration {\n name: string;\n root: string;\n sourceRoot: string;\n projectType?: \"library\" | \"application\";\n targets?: Record<string, unknown>;\n tags?: string[];\n}\n\n/**\n * Discover all projects in the workspace by scanning for project.json files.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @returns Map of project name to ProjectConfiguration\n */\nexport function discoverProjects(\n workspaceRoot: string\n): Map<string, ProjectConfiguration> {\n const logger = getCodegenLogger();\n const projects = new Map<string, ProjectConfiguration>();\n\n const projectJsonPaths = fg.sync(\"**/project.json\", {\n cwd: workspaceRoot,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\"],\n absolute: false,\n });\n\n for (const relPath of projectJsonPaths) {\n const absPath = path.join(workspaceRoot, relPath);\n try {\n const raw = fs.readFileSync(absPath, \"utf-8\");\n const json = JSON.parse(raw);\n const projectRoot = path.dirname(relPath);\n const name = json.name ?? path.basename(projectRoot);\n\n const config: ProjectConfiguration = {\n name,\n root: projectRoot,\n sourceRoot: json.sourceRoot ?? path.join(projectRoot, \"src\"),\n projectType: json.projectType,\n targets: json.targets,\n tags: json.tags,\n };\n\n projects.set(name, config);\n logger.debug(`Discovered project: ${name} at ${projectRoot}`);\n } catch (err) {\n logger.warn(`Failed to parse ${absPath}: ${err}`);\n }\n }\n\n logger.info(`Discovered ${projects.size} projects`);\n return projects;\n}\n\n/**\n * Find a single project by name.\n *\n * Note: This rescans the workspace on every call. If you need to look up\n * multiple projects, call discoverProjects() once and query the returned Map.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @param projectName - The project name to look up\n * @param projects - Optional pre-computed project map (avoids rescan)\n * @returns ProjectConfiguration or undefined if not found\n */\nexport function findProjectByName(\n workspaceRoot: string,\n projectName: string,\n projects?: Map<string, ProjectConfiguration>\n): ProjectConfiguration | undefined {\n const map = projects ?? discoverProjects(workspaceRoot);\n return map.get(projectName);\n}\n\n/**\n * Find the project that contains a given file path.\n * Walks up from the file path looking for the nearest project.json.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @param filePath - Absolute path to a file within the workspace\n * @returns ProjectConfiguration or undefined if not within any project\n */\nexport function findProjectForPath(\n workspaceRoot: string,\n filePath: string\n): ProjectConfiguration | undefined {\n const resolved = path.resolve(workspaceRoot);\n let dir = path.dirname(path.resolve(filePath));\n\n while (dir.startsWith(resolved) && dir !== resolved) {\n const projectJsonPath = path.join(dir, \"project.json\");\n if (fs.existsSync(projectJsonPath)) {\n try {\n const raw = fs.readFileSync(projectJsonPath, \"utf-8\");\n const json = JSON.parse(raw);\n const projectRoot = path.relative(resolved, dir);\n const name = json.name ?? path.basename(dir);\n\n return {\n name,\n root: projectRoot,\n sourceRoot: json.sourceRoot ?? path.join(projectRoot, \"src\"),\n projectType: json.projectType,\n targets: json.targets,\n tags: json.tags,\n };\n } catch {\n return undefined;\n }\n }\n dir = path.dirname(dir);\n }\n\n return undefined;\n}\n\n/**\n * Read the workspace-level nx.json configuration.\n *\n * @param workspaceRoot - Absolute path to the workspace root\n * @returns Parsed nx.json contents, or empty object if not found\n */\nexport function readNxJson(workspaceRoot: string): Record<string, unknown> {\n const nxJsonPath = path.join(workspaceRoot, \"nx.json\");\n try {\n const raw = fs.readFileSync(nxJsonPath, \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return {};\n }\n}\n","/**\n * JSON read/write/update utilities operating on a CodegenFileSystem.\n *\n * Replaces @nx/devkit readJson, writeJson, updateJson.\n */\nimport type { CodegenFileSystem } from \"./codegen-filesystem\";\n\n/**\n * Read and parse a JSON file from the filesystem.\n *\n * @param codegenFs - Filesystem abstraction\n * @param filePath - Path relative to workspace root\n * @returns Parsed JSON object\n * @throws If the file does not exist or contains invalid JSON\n */\nexport function readJson<T = Record<string, unknown>>(\n codegenFs: CodegenFileSystem,\n filePath: string\n): T {\n const content = codegenFs.read(filePath);\n if (content === null) {\n throw new Error(`File not found: ${filePath}`);\n }\n return JSON.parse(content) as T;\n}\n\n/**\n * Serialize and write a JSON object to the filesystem.\n *\n * @param codegenFs - Filesystem abstraction\n * @param filePath - Path relative to workspace root\n * @param value - Object to serialize\n */\nexport function writeJson<T = Record<string, unknown>>(\n codegenFs: CodegenFileSystem,\n filePath: string,\n value: T\n): void {\n codegenFs.write(filePath, JSON.stringify(value, null, 2) + \"\\n\");\n}\n\n/**\n * Read a JSON file, apply a transformation, and write it back.\n *\n * @param codegenFs - Filesystem abstraction\n * @param filePath - Path relative to workspace root\n * @param updater - Function that receives the parsed object and returns the updated object\n */\nexport function updateJson<T = Record<string, unknown>>(\n codegenFs: CodegenFileSystem,\n filePath: string,\n updater: (json: T) => T\n): void {\n const current = readJson<T>(codegenFs, filePath);\n const updated = updater(current);\n writeJson(codegenFs, filePath, updated);\n}\n","/**\n * Format files using Prettier — replaces @nx/devkit formatFiles().\n *\n * Resolves the Prettier config from the workspace root and formats\n * all files tracked by a CodegenFileSystem that match supported extensions.\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport prettier from \"prettier\";\nimport { getCodegenLogger } from \"./logger\";\n\nconst FORMATTABLE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".css\",\n \".scss\",\n \".md\",\n \".yaml\",\n \".yml\",\n \".html\",\n]);\n\n/**\n * Format files at the given paths using Prettier.\n *\n * @param workspaceRoot - Absolute path to the workspace root (for Prettier config resolution)\n * @param filePaths - Absolute paths of files to format\n */\nexport async function formatFiles(\n workspaceRoot: string,\n filePaths: string[]\n): Promise<void> {\n const logger = getCodegenLogger();\n\n for (const filePath of filePaths) {\n const ext = path.extname(filePath);\n if (!FORMATTABLE_EXTENSIONS.has(ext)) {\n continue;\n }\n\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const options = await prettier.resolveConfig(filePath, {\n editorconfig: true,\n });\n const formatted = await prettier.format(content, {\n ...options,\n filepath: filePath,\n });\n fs.writeFileSync(filePath, formatted, \"utf-8\");\n logger.debug(`Formatted ${path.relative(workspaceRoot, filePath)}`);\n } catch (err) {\n logger.warn(`Failed to format ${filePath}: ${err}`);\n }\n }\n}\n","/**\n * String case-conversion utilities.\n *\n * Pure functions with no external dependencies.\n * Ported from kos-nx-plugin/src/utils/name-utils.ts (minus the logger calls).\n */\n\nexport function dashCase(input: string): string {\n return input\n .replace(/\\s+/g, \"-\")\n .replace(/([a-z])([A-Z])/g, \"$1-$2\")\n .toLowerCase();\n}\n\nexport function camelCase(input: string): string {\n if (input.length === 0) return \"\";\n const words = input.split(/-|\\s+/);\n if (words.length > 0 && words[0].length > 0) {\n words[0] = words[0].charAt(0).toLowerCase() + words[0].slice(1);\n }\n for (let i = 1; i < words.length; i++) {\n words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1);\n }\n return words.join(\"\");\n}\n\nexport function pascalCase(input: string): string {\n if (input.length === 0) return \"\";\n const cc = camelCase(input);\n return cc[0].toUpperCase() + cc.slice(1);\n}\n\nexport function properCase(input: string): string {\n const words = input\n .toLowerCase()\n .replaceAll(\"-\", \" \")\n .split(\" \")\n .filter(Boolean);\n for (let i = 0; i < words.length; i++) {\n words[i] = words[i][0].toUpperCase() + words[i].slice(1);\n }\n return words.join(\"\");\n}\n\n/**\n * Convert to CONSTANT_CASE. Expects space-separated or dash-separated input.\n * camelCase input is not split (e.g. \"myWidget\" becomes \"MYWIDGET\").\n */\nexport function constantCase(input: string): string {\n if (input.length === 0) return \"\";\n return input\n .toUpperCase()\n .split(/[\\s-]+/)\n .filter(Boolean)\n .join(\"_\");\n}\n","/**\n * Option normalization — generates all case variants for every string property.\n *\n * Given `{ name: \"my-widget\" }`, produces:\n * ```\n * {\n * name: \"my-widget\",\n * nameCamelCase: \"myWidget\",\n * namePascalCase: \"MyWidget\",\n * nameDashCase: \"my-widget\",\n * nameProperCase: \"MyWidget\",\n * nameConstantCase: \"MY_WIDGET\",\n * nameLowerCase: \"my-widget\",\n * }\n * ```\n *\n * Ported from kos-nx-plugin/src/utils/normalize-value.ts.\n */\nimport {\n camelCase,\n constantCase,\n dashCase,\n pascalCase,\n properCase,\n} from \"./name-utils\";\n\ntype NormalizedFunctions =\n | \"CamelCase\"\n | \"ConstantCase\"\n | \"DashCase\"\n | \"PascalCase\"\n | \"ProperCase\"\n | \"LowerCase\";\n\ntype NormalizedValue<Type extends Record<string, string>> = {\n [k in Type as `${Extract<keyof Type, string>}${NormalizedFunctions}`]: string;\n};\n\ntype Normalized<T extends string> = {\n [k in T as `${T}${NormalizedFunctions}`]: string;\n};\n\nconst normalizeValue = <T extends string>(\n optionsName: T,\n value: string\n): Normalized<T> & { [k in T]: string } =>\n ({\n [`${camelCase(optionsName)}CamelCase`]: camelCase(value),\n [`${camelCase(optionsName)}ConstantCase`]: constantCase(value),\n [`${camelCase(optionsName)}DashCase`]: dashCase(value),\n [`${camelCase(optionsName)}PascalCase`]: pascalCase(value),\n [`${camelCase(optionsName)}ProperCase`]: properCase(value),\n [`${camelCase(optionsName)}LowerCase`]: value.toLowerCase(),\n [`${optionsName}`]: value,\n } as Normalized<T> & { [k in T]: string });\n\nexport const normalizeAllValues = <T extends Record<string, any>>(\n options: T\n): NormalizedValue<T> & T => {\n let normalizedValues = {} as NormalizedValue<T> & T;\n for (const key in options) {\n if (Object.prototype.hasOwnProperty.call(options, key)) {\n const element = options[key];\n const newOptions =\n typeof element !== \"string\" || element === \"\"\n ? { [key]: element }\n : normalizeValue(key, element);\n\n normalizedValues = {\n ...normalizedValues,\n ...newOptions,\n };\n }\n }\n return normalizedValues;\n};\n","/**\n * KOS project and model configuration utilities.\n *\n * Reads and writes .kos.json files through CodegenFileSystem.\n * Ported from kos-nx-plugin/src/utils/project-utils.ts.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"./codegen-filesystem\";\nimport {\n findProjectByName,\n findProjectForPath,\n type ProjectConfiguration,\n} from \"./project-discovery\";\nimport { updateJson } from \"./json-utils\";\nimport { dashCase } from \"./name-utils\";\nimport { getCodegenLogger } from \"./logger\";\n\nexport interface KosModelConfiguration {\n name: string;\n type: string;\n singleton: boolean;\n container?: boolean;\n /**\n * Exported registration bean symbol (e.g. \"Board\") — the agent-facing handle.\n * Imported from the SDK root; `factory.type` is the modelType to depend on, and\n * models are auto-registered so consumers never instantiate it. Written\n * automatically by the generator (it names the bean). Links to the full shape\n * at `kos://types/{factory}`.\n */\n factory?: string;\n /**\n * One-line, human-curated purpose. The only genuinely authored field — set via\n * an optional prompt/slot at generation, never inferred.\n */\n purpose?: string;\n /**\n * `.kos.json` keys of the container/managing models that hold this model —\n * consume it THROUGH them (depend on the container, navigate), not by id. Set\n * only when generation establishes containment; never inferred.\n */\n managedBy?: string[];\n}\n\nexport interface KosProjectConfiguration {\n name: string;\n type: string;\n version: string;\n models: Record<string, KosModelConfiguration>;\n generator?: {\n internal?: boolean;\n defaults?: {\n model?: { folder?: string };\n component?: { folder?: string };\n };\n };\n}\n\nexport function getCurrentDirectoryName(cwd: string): string | undefined {\n return cwd.split(\"/\").pop();\n}\n\n/**\n * Find the project that contains the given working directory.\n */\nexport function getProject(\n codegenFs: CodegenFileSystem,\n cwd: string\n): ProjectConfiguration | undefined {\n return findProjectForPath(codegenFs.root, cwd);\n}\n\n/**\n * Read .kos.json for a project, creating a default if it doesn't exist.\n */\nexport function getKosProjectConfiguration(\n codegenFs: CodegenFileSystem,\n projectName: string,\n projects?: Map<string, ProjectConfiguration>\n): KosProjectConfiguration | undefined {\n const project = findProjectByName(codegenFs.root, projectName, projects);\n if (!project) return undefined;\n\n const configPath = path.join(project.root, \".kos.json\");\n if (!codegenFs.exists(configPath)) {\n const defaultConfig: KosProjectConfiguration = {\n name: `${dashCase(projectName)}-model`,\n type: \"kos.model\",\n version: \"0.1.0\",\n models: {},\n generator: { defaults: { model: { folder: \"\" } } },\n };\n codegenFs.write(configPath, JSON.stringify(defaultConfig, null, 2));\n }\n\n const content = codegenFs.read(configPath);\n return content ? JSON.parse(content) : undefined;\n}\n\n/**\n * Find the `.kos.json` model key for a model name. Keys are normally the model\n * name itself; fall back to matching the derived `<name>-model` type id so a\n * differently-cased name still resolves.\n */\nfunction findModelKey(\n models: Record<string, any>,\n name: string\n): string | undefined {\n if (models[name]) return name;\n const typeId = `${dashCase(name)}-model`;\n return Object.keys(models).find((k) => models[k]?.type === typeId);\n}\n\n/**\n * Record that an existing model gained in-place container support\n * (`@kosContainerAware`) in `.kos.json`: flag it `container: true`, and — when it\n * holds a concrete model type rather than the generic `IKosDataModel` — record\n * that child as `managedBy` this container so it is consumed THROUGH it.\n *\n * Containment is only recorded from this explicit generation step; nothing is\n * inferred. No-ops if the project or its `.kos.json` can't be found.\n */\nexport function recordContainerSupportInKosConfig(params: {\n codegenFs: CodegenFileSystem;\n projectName: string;\n modelName: string;\n childType?: string;\n projects?: Map<string, ProjectConfiguration>;\n}): void {\n const project = findProjectByName(\n params.codegenFs.root,\n params.projectName,\n params.projects\n );\n if (!project) return;\n const configPath = path.join(project.root, \".kos.json\");\n if (!params.codegenFs.exists(configPath)) return;\n\n updateJson(params.codegenFs, configPath, (json: any) => {\n const models: Record<string, any> = json.models ?? {};\n const selfKey = findModelKey(models, params.modelName);\n if (!selfKey) return json;\n\n models[selfKey] = { ...models[selfKey], container: true };\n\n const childType = params.childType?.trim();\n if (\n childType &&\n childType !== \"IKosDataModel\" &&\n /Model$/.test(childType)\n ) {\n const childTypeId = dashCase(childType);\n const childKey = Object.keys(models).find(\n (k) => models[k]?.type === childTypeId\n );\n if (childKey && childKey !== selfKey) {\n const managedBy = [\n ...new Set([...(models[childKey].managedBy ?? []), selfKey]),\n ];\n models[childKey] = { ...models[childKey], managedBy };\n }\n }\n\n json.models = models;\n return json;\n });\n}\n\n/**\n * Read a specific model's configuration from .kos.json.\n */\nexport function getKosModelConfiguration(\n codegenFs: CodegenFileSystem,\n projectName: string,\n modelName: string,\n projects?: Map<string, ProjectConfiguration>\n): KosModelConfiguration | undefined {\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectName,\n projects\n );\n return kosConfig?.models?.[modelName];\n}\n\n/**\n * Read a specific property from a model's configuration.\n */\nexport function getKosModelConfigProp(params: {\n codegenFs: CodegenFileSystem;\n project: string;\n modelName: string;\n prop: string;\n projects?: Map<string, ProjectConfiguration>;\n}): any {\n const config = getKosModelConfiguration(\n params.codegenFs,\n params.project,\n params.modelName,\n params.projects\n );\n return config ? (config as any)[params.prop] : undefined;\n}\n\n/**\n * Add a model entry to a project's .kos.json.\n */\nexport function addKosModelConfiguration(params: {\n codegenFs: CodegenFileSystem;\n projectName: string;\n projectRoot: string;\n modelName: string;\n singleton: boolean;\n container?: boolean;\n /** Exported registration bean symbol (the generator knows it). */\n factory?: string;\n}): void {\n const logger = getCodegenLogger();\n const kosConfigPath = path.join(params.projectRoot, \".kos.json\");\n\n if (!params.codegenFs.exists(kosConfigPath)) {\n logger.info(`Creating .kos.json in ${params.projectRoot}`);\n const defaultConfig = {\n name: params.projectName,\n type: \"kos.model\",\n version: \"0.1.0\",\n models: {},\n generator: { defaults: { model: { folder: \"\" } } },\n };\n params.codegenFs.write(\n kosConfigPath,\n JSON.stringify(defaultConfig, null, 2) + \"\\n\"\n );\n }\n\n updateJson(params.codegenFs, kosConfigPath, (json: any) => {\n const existing = json.models?.[params.modelName] ?? {};\n json.models = {\n ...json.models,\n [params.modelName]: {\n // Preserve any curated fields (purpose/managedBy) on re-generation.\n ...existing,\n name: params.modelName,\n type: `${params.modelName}-model`,\n singleton: !!params.singleton,\n container: !!params.container,\n ...(params.factory ? { factory: params.factory } : {}),\n },\n };\n return json;\n });\n}\n","import * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Finds the root directory containing the templates/ directory.\n *\n * Resolution order:\n * 1. KOS_TEMPLATE_BASE_DIR env var — set by kos-ui-cli when running as a\n * bundled ESM package (where __dirname is unavailable).\n * 2. Walk up from __dirname looking for this package's package.json — works\n * in CJS context (tsc-compiled output or direct Node.js require).\n */\nfunction findPackageRoot(): string {\n if (process.env.KOS_TEMPLATE_BASE_DIR) {\n return process.env.KOS_TEMPLATE_BASE_DIR;\n }\n\n // CJS context: walk up from __dirname to find our package.json\n let dir = __dirname;\n while (dir !== path.dirname(dir)) {\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n if (pkg.name === \"@kosdev-code/kos-codegen-core\") {\n return dir;\n }\n } catch {\n // Not valid JSON, keep looking\n }\n }\n dir = path.dirname(dir);\n }\n // Fallback: assume source layout (src/lib/ -> package root)\n return path.resolve(__dirname, \"..\", \"..\");\n}\n\n/**\n * Resolves the absolute path to a generator's template directory.\n * Templates are stored in the `templates/` directory at the package root.\n *\n * @param generatorName - The generator name matching a subdirectory under templates/\n * @returns Absolute path to the template directory for the given generator\n */\nexport function getTemplateDir(generatorName: string): string {\n return path.join(findPackageRoot(), \"templates\", generatorName);\n}\n","/**\n * Core generator: Splash project.\n *\n * Creates a splash screen project structure and associated tooling scripts.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { normalizeAllValues } from \"../normalize-values\";\n\nexport interface SplashProjectOptions {\n name: string;\n}\n\n/**\n * Generate a splash project with its associated tooling.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory containing\n * `project/` and `tools/` subdirectories\n * @param options - Generator options\n */\nexport function generateSplashProject(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: SplashProjectOptions\n): void {\n const normalized = normalizeAllValues(options);\n\n const projectRoot = `splash/${normalized.nameDashCase}`;\n const toolsRoot = path.join(\"tools\", \"scripts\");\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"project\"),\n projectRoot,\n normalized\n );\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"tools\"),\n toolsRoot,\n normalized\n );\n}\n","/**\n * Core generator: Model project.\n *\n * Owns the WHOLE output of a KOS model library — the buildable Nx library\n * skeleton (project.json, tsconfigs, vite.config.ts, package.json, eslint\n * config, source entry point) plus the KOS layer on top: the `.kos.json`\n * descriptor carrying `generator.projectType: \"model\"` (what `kosui model`\n * project discovery keys off) and the `api` target that fronts\n * `kosui api:generate`.\n *\n * Framework-agnostic — operates through CodegenFileSystem, with no @nx/*\n * involvement. The templates are the byte-for-byte output the workspace preset\n * used to obtain from `@nx/js`'s library generator, so a workspace scaffolded\n * by the preset and one grown later with `kosui project:model` are identical.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { readJson, updateJson, writeJson } from \"../json-utils\";\nimport { camelCase, dashCase } from \"../name-utils\";\n\n/** Suffix every KOS model library carries, so `kosui` can recognize one by name. */\nconst MODEL_PROJECT_SUFFIX = \"-models\";\n\n/** Directory model libraries live under when the workspace declares no libsDir. */\nexport const DEFAULT_MODEL_LIBS_DIR = \"libs\";\n\n/**\n * The model lib's own .eslintrc.json parses its package.json with\n * jsonc-eslint-parser for the @nx/dependency-checks rule. Nothing else in a KOS\n * workspace pulls that parser in, so the generator must guarantee it.\n */\nconst JSONC_ESLINT_PARSER_VERSION = \"^2.1.0\";\n\nexport interface ModelProjectOptions {\n /** Base name; the `-models` suffix is appended unless already present. */\n name: string;\n /** Workspace `workspaceLayout.libsDir`, when the workspace declares one. */\n libsDir?: string;\n}\n\nexport interface ModelProjectLayout {\n /** Nx project name, e.g. `acme-models`. */\n projectName: string;\n /** Project root relative to the workspace root, e.g. `libs/acme-models`. */\n projectRoot: string;\n /** TypeScript path alias the workspace maps to the lib, e.g. `@acme/acme-models`. */\n importPath: string;\n}\n\n/**\n * Resolve where a model project lands and what it is called.\n *\n * `importPath` needs the workspace's npm scope, so the root package.json is\n * read when one is reachable; a workspace without a scoped name maps the lib\n * under its bare project name, matching Nx's own import-path rule.\n */\nexport function resolveModelProjectLayout(\n codegenFs: CodegenFileSystem | null,\n options: ModelProjectOptions\n): ModelProjectLayout {\n const base = dashCase(options.name);\n const projectName = base.endsWith(MODEL_PROJECT_SUFFIX)\n ? base\n : `${base}${MODEL_PROJECT_SUFFIX}`;\n const libsDir = (options.libsDir || DEFAULT_MODEL_LIBS_DIR).replace(\n /\\\\/g,\n \"/\"\n );\n const scope = codegenFs ? readNpmScope(codegenFs) : undefined;\n return {\n projectName,\n projectRoot: `${libsDir}/${projectName}`.replace(/^\\/+/, \"\"),\n importPath: scope ? `@${scope}/${projectName}` : projectName,\n };\n}\n\n/** The npm scope of the workspace, derived from the root package.json name. */\nfunction readNpmScope(codegenFs: CodegenFileSystem): string | undefined {\n if (!codegenFs.exists(\"package.json\")) {\n return undefined;\n }\n const name = readJson<{ name?: string }>(codegenFs, \"package.json\").name;\n if (!name?.startsWith(\"@\")) {\n return undefined;\n }\n return name.split(\"/\")[0].slice(1);\n}\n\n/** Relative prefix that walks from the project root back to the workspace root. */\nfunction offsetFromRoot(projectRoot: string): string {\n return projectRoot\n .split(\"/\")\n .filter(Boolean)\n .map(() => \"../\")\n .join(\"\");\n}\n\n/**\n * Generate a KOS model project.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory containing a\n * `project/` subdirectory\n * @param options - Generator options\n * @returns Where the project landed, what it is named, and its import path\n */\nexport function generateModelProject(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ModelProjectOptions\n): ModelProjectLayout {\n const layout = resolveModelProjectLayout(codegenFs, options);\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"project\"),\n layout.projectRoot,\n {\n ...layout,\n projectNameCamelCase: camelCase(layout.projectName),\n offsetFromRoot: offsetFromRoot(layout.projectRoot),\n template: \"\",\n }\n );\n\n registerTsconfigPath(codegenFs, layout);\n ensureJsoncEslintParser(codegenFs);\n\n return layout;\n}\n\n/**\n * Map the lib's import path to its source entry in tsconfig.base.json — without\n * it nothing in the workspace can import the models by name.\n */\nfunction registerTsconfigPath(\n codegenFs: CodegenFileSystem,\n layout: ModelProjectLayout\n): void {\n if (!codegenFs.exists(\"tsconfig.base.json\")) {\n return;\n }\n updateJson(codegenFs, \"tsconfig.base.json\", (json: any) => {\n json.compilerOptions = json.compilerOptions ?? {};\n json.compilerOptions.paths = json.compilerOptions.paths ?? {};\n json.compilerOptions.paths[layout.importPath] = [\n `${layout.projectRoot}/src/index.ts`,\n ];\n return json;\n });\n}\n\nfunction ensureJsoncEslintParser(codegenFs: CodegenFileSystem): void {\n if (!codegenFs.exists(\"package.json\")) {\n return;\n }\n const pkg = readJson<Record<string, any>>(codegenFs, \"package.json\");\n const devDependencies = pkg.devDependencies ?? {};\n if (\"jsonc-eslint-parser\" in devDependencies) {\n return;\n }\n devDependencies[\"jsonc-eslint-parser\"] = JSONC_ESLINT_PARSER_VERSION;\n pkg.devDependencies = Object.fromEntries(\n // Codepoint order, matching what Nx's own dependency helper produces.\n Object.entries(devDependencies).sort(([a], [b]) =>\n a < b ? -1 : a > b ? 1 : 0\n )\n );\n writeJson(codegenFs, \"package.json\", pkg);\n}\n","/**\n * Core generator: KOS Init.\n *\n * Updates nx.json with default KOS generator configuration for the workspace.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { readJson, writeJson } from \"../json-utils\";\nimport { getCodegenLogger } from \"../logger\";\n\nexport interface KosInitOptions {\n appProject: string;\n modelProject: string;\n registrationProject?: string;\n}\n\n/**\n * Initialize KOS generator defaults in nx.json.\n *\n * Sets default project references for kos-model, kos-component,\n * kos-context, and kos-hook generators.\n *\n * @param codegenFs - Target filesystem\n * @param options - Generator options\n */\nexport function generateInit(\n codegenFs: CodegenFileSystem,\n options: KosInitOptions\n): void {\n const logger = getCodegenLogger();\n const { appProject, modelProject, registrationProject } = options;\n\n let nxConfig: Record<string, any>;\n try {\n nxConfig = readJson(codegenFs, \"nx.json\");\n } catch {\n logger.error(\"Unable to find nx.json\");\n return;\n }\n\n logger.info(\"Updating nx.json\");\n\n const defaultProjectConfig = {\n appProject,\n modelProject,\n registrationProject,\n modelDirectory: \"lib\",\n appDirectory: \"app\",\n components: true,\n internal: false,\n singleton: false,\n unitTests: true,\n };\n\n const generatorsConfig = nxConfig.generators || {};\n const kosConfig = generatorsConfig[\"@kosdev-code/kos-nx-plugin\"] || {};\n\n const updateConfig = (configName: string) => {\n const config = kosConfig[configName] || { ...defaultProjectConfig };\n config.appProject = appProject;\n config.modelProject = modelProject;\n config.registrationProject = registrationProject;\n kosConfig[configName] = config;\n };\n\n [\"kos-model\", \"kos-component\", \"kos-context\", \"kos-hook\"].forEach(\n updateConfig\n );\n\n nxConfig.generators = {\n ...generatorsConfig,\n \"@kosdev-code/kos-nx-plugin\": kosConfig,\n };\n\n writeJson(codegenFs, \"nx.json\", nxConfig);\n}\n","/**\n * Core generator: polyglot workspace repo root.\n *\n * Scaffolds the repo-level layer of a java + ui KOS application repository\n * (the tccc-rack-app pattern): build/ orchestration scripts, GitHub Actions\n * workflows, and kos_build_handler manifests. The ui/ interior is produced by\n * the Nx preset (create-nx-workspace) and java/ modules by the KOS Maven\n * archetypes — this generator only contributes the layer neither of them owns.\n *\n * Framework-agnostic — operates through CodegenFileSystem; the repo root is\n * deliberately NOT an Nx workspace.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { normalizeAllValues } from \"../normalize-values\";\n\nexport interface PolyglotWorkspaceOptions {\n /** Workspace/repo name (also determines the UI app name `<name>-ui`). */\n name: string;\n /**\n * The repo-root layer is IDENTICAL for every type — same scripts,\n * workflows, and manifests, all runtime-tolerant of a missing half — so a\n * repo can grow the other half later without restructuring. The type only\n * seeds the manifests: \"polyglot\"/\"ui\" (default) pre-register the UI app\n * artifact; \"java\" starts with empty artifact lists (ci:sync/java:add\n * fill them in).\n */\n type?: \"polyglot\" | \"ui\" | \"java\";\n /**\n * `default_keyset` for the kos_build_handler manifests. Org-specific;\n * changeable in .github/build-*.json afterward. Default: \"prod.kos\".\n */\n keyset?: string;\n /**\n * Node version build/nodew.sh pins and auto-provisions when the machine\n * has none. Defaults to the Node running this generator — grounded in a\n * version known to work with the scaffolded workspace.\n */\n nodeVersion?: string;\n /**\n * JDK major build/jdkw.sh pins. Default 21 (compiles the archetypes'\n * release-17 target; also what java discovery prefers).\n */\n jdkMajor?: string;\n /** Maven version build/jdkw.sh provisions when mvn is absent. */\n mavenVersion?: string;\n}\n\nexport interface PolyglotWorkspaceResult {\n /**\n * Root-relative paths the caller must mark executable (CodegenFileSystem\n * has no chmod; CI invokes these directly as ./build/<script>).\n */\n executablePaths: string[];\n}\n\nconst BUILD_SCRIPTS = [\n \"build/build-ui.sh\",\n \"build/build-java.sh\",\n \"build/build-release.sh\",\n \"build/release_version_prebuild.sh\",\n \"build/docker-build.sh\",\n];\n\nexport function generatePolyglotWorkspace(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: PolyglotWorkspaceOptions\n): PolyglotWorkspaceResult {\n const hasUi = (options.type ?? \"polyglot\") !== \"java\";\n const normalized = normalizeAllValues({ name: options.name });\n const vars = {\n ...normalized,\n hasUi,\n keyset: options.keyset || \"prod.kos\",\n appUiName: `${normalized.nameDashCase}-ui`,\n nodeVersion: options.nodeVersion || process.version.replace(/^v/, \"\"),\n jdkMajor: options.jdkMajor || \"21\",\n mavenVersion: options.mavenVersion || \"3.9.9\",\n };\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"root\"),\n \".\",\n vars\n );\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"build\"),\n \"build\",\n vars\n );\n // Template dir is named \"github\" (npm packs dot-directories unreliably);\n // emitted as .github.\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"github\"),\n \".github\",\n vars\n );\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"java\"),\n \"java\",\n vars\n );\n\n return { executablePaths: [...BUILD_SCRIPTS] };\n}\n","/**\n * Shared KOS artifact-target bundle.\n *\n * Every project that packages a KAB gets the same target family:\n * kab — kabtool build + list (dependsOn zip)\n * zip — archiver (dependsOn build, sbom [+ descriptor])\n * descriptor — descriptor.mjs (optional; apps/plugins/content/i18n)\n * version — stamps the release version into the project's `.kos.json`\n * sbom — SPDX SBOM (pruned lockfile), packaged inside the KAB\n *\n * ARTIFACT LAYOUT: the KAB and ui.zip land in `{projectRoot}/target/` — a peer\n * of the project's `src/`, the same place the Maven half of a polyglot repo\n * drops its KABs (`java/<module>/target/*.kab`). A project's artifacts sit\n * beside the sources that produced them rather than in a workspace-wide\n * `dist/archives/` tree.\n *\n * `descriptor` and `sbom` write to the project's BUILD output dir\n * (`dist/{projectRoot}`) instead, because archiver zips that directory\n * wholesale: both have to end up INSIDE ui.zip — and therefore inside the KAB\n * — rather than beside it. An SBOM that shipped next to the KAB would not\n * travel with the distribution, which is the entire reason it is generated.\n * That is also why `zip` (not `kab`) is what depends on `sbom`: by the time\n * kabtool runs, the zip it packages is already sealed.\n *\n * Paths are written as Nx `{projectRoot}` tokens so `nx move` needs no\n * rewrite. Nx does NOT interpolate arbitrary target options, so the scripts\n * that read these (kabtool.mjs, archiver.js, descriptor.mjs, splashtool.mjs)\n * and the sbom executor expand the token themselves against the project's\n * root — see `resolveTargetPath` in each script.\n *\n * The `version` target is KOS *artifact* versioning: it rewrites the\n * `version` field of the project's `.kos.json` (which kabtool/descriptor bake\n * into the KAB) and never touches `package.json`. Tag-based release pipelines\n * drive it via:\n * nx run-many --target=version --args=--ver=$KOSBUILD_VERSION\n *\n * kab and version are deliberately produced by ONE helper so no generator can\n * emit a KAB-packaging project that is not release-versionable.\n */\n\n/** Directory, under each project root, that holds the project's KAB artifacts. */\nexport const KAB_OUTPUT_DIR = \"target\";\n\n/**\n * Archive directory for every KAB-producing project — `{projectRoot}/target/`.\n *\n * Deliberately a token rather than a resolved path: a project that moves keeps\n * working without anyone rewriting its project.json. Consumers expand it with\n * `resolveKabPath` (or its per-script equivalent) before touching the disk.\n */\nexport const KAB_OUTPUT_PATH = `{projectRoot}/${KAB_OUTPUT_DIR}/`;\n\n/**\n * Expand the Nx path tokens KOS artifact targets use in their options.\n *\n * Nx interpolates `{projectRoot}`/`{workspaceRoot}` in a target's `outputs`,\n * never in arbitrary `options`, and the KAB scripts read those options straight\n * off the cached project graph — so expansion is on us. The result stays\n * workspace-root-relative (the cwd Nx runs commands from) unless the token was\n * `{workspaceRoot}`.\n */\nexport function resolveKabPath(value: string, projectRoot: string): string {\n const root = projectRoot.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n return value\n .replace(/\\{projectRoot\\}/g, root)\n .replace(/\\{workspaceRoot\\}\\/?/g, \"\");\n}\n\nexport interface KabTargetsOptions {\n /** Project name as Nx knows it (argument to kabtool/archiver/descriptor). */\n name: string;\n /**\n * Emit a `descriptor` target (and make `zip` depend on it). Its\n * descriptor.json is written into the build output dir so the zip contains\n * it. Omit for projects without a descriptor (themes).\n */\n descriptor?: boolean;\n /** Build target `zip` depends on. Default: \"build\" (plugins: \"build:production\"). */\n buildTarget?: string;\n}\n\nexport interface KabTargetDefinition {\n command?: string;\n executor?: string;\n outputs?: string[];\n cache?: boolean;\n inputs?: string[];\n options?: Record<string, unknown>;\n dependsOn?: string[];\n}\n\nexport const UPDATE_RELEASE_VERSION_SCRIPT_PATH =\n \"tools/scripts/update-release-version.mjs\";\n\nexport function buildKabTargets(\n options: KabTargetsOptions\n): Record<string, KabTargetDefinition> {\n const { name, descriptor = false, buildTarget = \"build\" } = options;\n const outputPath = KAB_OUTPUT_PATH;\n // Everything that must ride INSIDE ui.zip is written here, because archiver\n // zips the build output dir wholesale.\n const zipPayloadDir = \"dist/{projectRoot}\";\n\n const targets: Record<string, KabTargetDefinition> = {\n kab: {\n command: `node tools/scripts/kabtool.mjs build ${name} && node tools/scripts/kabtool.mjs list ${name} `,\n options: {\n outputPath,\n zipName: \"ui.zip\",\n kabName: `${name}.kab`,\n },\n dependsOn: [\"zip\"],\n },\n zip: {\n command: `node tools/scripts/archiver.js ${name}`,\n options: {\n outputPath,\n zipName: \"ui.zip\",\n },\n // `sbom` is a zip dependency, not a kab one: kabtool packages an\n // already-sealed ui.zip, so anything ordered after `zip` misses it.\n dependsOn: descriptor\n ? [buildTarget, \"descriptor\", \"sbom\"]\n : [buildTarget, \"sbom\"],\n },\n };\n\n if (descriptor) {\n targets.descriptor = {\n command: `node tools/scripts/descriptor.mjs ${name}`,\n options: {\n outputPath: zipPayloadDir,\n fileName: \"descriptor.json\",\n },\n dependsOn: [\"build\"],\n };\n }\n\n targets.version = {\n command: `node ${UPDATE_RELEASE_VERSION_SCRIPT_PATH} ${name} {args.ver}`,\n options: {},\n dependsOn: [],\n };\n\n // The SBOM ships inside the KAB so it travels with the distribution.\n targets.sbom = buildSbomTarget({ outputPath: zipPayloadDir });\n\n return targets;\n}\n\nexport interface SbomTargetOptions {\n /**\n * Directory the SBOM lands in. `dist/{projectRoot}` — the build output dir\n * archiver zips — so the SBOM ships inside the KAB.\n */\n outputPath: string;\n}\n\n/**\n * SBOM target for any artifact-producing project. Standalone so migrations\n * can retrofit it onto existing projects without rebuilding the kab bundle.\n *\n * Whatever consumes this must order it BEFORE `zip`; an SBOM written after the\n * zip is sealed never reaches the KAB.\n */\nexport function buildSbomTarget({\n outputPath,\n}: SbomTargetOptions): KabTargetDefinition {\n const dir = outputPath.replace(/\\/+$/, \"\");\n // `outputs` is one of the few places Nx expands tokens itself, so a\n // tokenized dir goes in as-is; a plain path still needs the root prefix.\n const outputDir = dir.startsWith(\"{\") ? dir : `{workspaceRoot}/${dir}`;\n return {\n executor: \"@kosdev-code/kos-nx-plugin:sbom\",\n outputs: [\n `${outputDir}/sbom.spdx.json`,\n `${outputDir}/sbom.cyclonedx.json`,\n ],\n cache: true,\n inputs: [\"production\", \"^production\", \"{workspaceRoot}/package-lock.json\"],\n options: { outputPath: dir, softFail: true },\n };\n}\n","/**\n * ci:sync — reconcile the kos_build_handler manifests of a polyglot\n * workspace with the artifacts the repo actually produces.\n *\n * MERGE-PRESERVE semantics (the design contract):\n * - Existing artifact entries whose file is still produced are kept\n * VERBATIM — ids and custom fields (layer, artifactstore, …) are the\n * user's, and manifest ids are often hand-chosen (tccc-rack-app's\n * \"tccc-rack-splash-endcap\" for the `splash` project).\n * - Newly discovered artifacts are appended with generated entries.\n * - Entries whose artifact is no longer discovered are reported as stale\n * and kept, unless prune is set.\n * - Nothing outside the artifacts arrays is ever touched, and a manifest\n * is only rewritten when its artifact set actually changed.\n * Consequence: running ci:sync on an already-correct repo is a no-op, and\n * hand-running a Maven archetype + ci:sync converges to the same manifests\n * as `kosui java:add`.\n *\n * Discovery:\n * - ui: project.json files under the KOS layout dirs (never a bare walk of\n * ui/ — listFiles has no node_modules exclusion). A `kab` target's own\n * outputPath/kabName options give the artifact path; projects with a\n * `splash` target produce layer KABs; ui/external/*.kab files are\n * prebuilt artifacts.\n * - java: modules listed in the java/pom.xml aggregator whose pom uses the\n * kos-kab-maven-plugin (same java/pom.xml contract as build-java.sh).\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { KAB_OUTPUT_DIR, resolveKabPath } from \"./kab-targets\";\n\nexport interface DiscoveredArtifact {\n id: string;\n filename: string;\n layer?: number;\n}\n\nexport interface CiSyncOptions {\n /** Remove stale entries instead of keeping and reporting them. */\n prune?: boolean;\n}\n\nexport interface CiSyncManifestResult {\n added: string[];\n stale: string[];\n pruned: string[];\n}\n\nexport interface CiSyncResult {\n manifests: Record<string, CiSyncManifestResult>;\n discovered: { ui: DiscoveredArtifact[]; java: DiscoveredArtifact[] };\n}\n\nconst UI_PROJECT_DIRS = [\n \"apps\",\n \"libs\",\n \"plugins\",\n \"splash\",\n \"themes\",\n \"content\",\n \"translations\",\n];\n\nfunction joinArtifactPath(outputPath: string, fileName: string): string {\n return `${outputPath.replace(/\\/+$/, \"\")}/${fileName}`;\n}\n\nexport function discoverUiArtifacts(\n codegenFs: CodegenFileSystem\n): DiscoveredArtifact[] {\n const artifacts: DiscoveredArtifact[] = [];\n\n for (const dir of UI_PROJECT_DIRS) {\n for (const file of codegenFs.listFiles(`ui/${dir}`)) {\n if (!file.endsWith(\"project.json\")) continue;\n const raw = codegenFs.read(file);\n if (raw === null) continue;\n let project: any;\n try {\n project = JSON.parse(raw);\n } catch {\n continue;\n }\n const name = project.name;\n if (!name) continue;\n\n // Artifact paths are {projectRoot}-tokenized so projects can move; the\n // build handler needs a literal path, and the project.json's own\n // location is the project root (Nx allows no other).\n const projectRoot = file.slice(\"ui/\".length, file.lastIndexOf(\"/\"));\n const resolve = (value: string) => resolveKabPath(value, projectRoot);\n\n const kabOptions = project.targets?.kab?.options;\n if (kabOptions?.outputPath && kabOptions?.kabName) {\n artifacts.push({\n id: name,\n filename: `ui/${joinArtifactPath(\n resolve(kabOptions.outputPath),\n kabOptions.kabName\n )}`,\n });\n } else if (project.targets?.splash) {\n // splashtool writes the layer KAB into its target's outputPath; fall\n // back to the standard <projectRoot>/target/ when it is unset.\n const splashOutput = project.targets.splash.options?.outputPath as\n | string\n | undefined;\n artifacts.push({\n id: name,\n filename: `ui/${joinArtifactPath(\n resolve(splashOutput ?? `{projectRoot}/${KAB_OUTPUT_DIR}`),\n `${name}.kab`\n )}`,\n layer: 1,\n });\n }\n }\n }\n\n for (const file of codegenFs.listFiles(\"ui/external\")) {\n if (!file.endsWith(\".kab\")) continue;\n const base = file.slice(file.lastIndexOf(\"/\") + 1, -\".kab\".length);\n artifacts.push({ id: base, filename: file });\n }\n\n return artifacts;\n}\n\nexport function discoverJavaArtifacts(\n codegenFs: CodegenFileSystem\n): DiscoveredArtifact[] {\n const aggregator = codegenFs.read(\"java/pom.xml\");\n if (aggregator === null) return [];\n\n const artifacts: DiscoveredArtifact[] = [];\n for (const match of aggregator.matchAll(/<module>([^<]+)<\\/module>/g)) {\n const moduleDir = match[1];\n const pom = codegenFs.read(`java/${moduleDir}/pom.xml`);\n if (pom === null || !pom.includes(\"kos-kab-maven-plugin\")) continue;\n // The project's own artifactId is the first one outside any <parent>.\n const withoutParent = pom.replace(/<parent>[\\s\\S]*?<\\/parent>/, \"\");\n const artifactId = withoutParent.match(\n /<artifactId>([^<]+)<\\/artifactId>/\n )?.[1];\n if (!artifactId) continue;\n artifacts.push({\n id: moduleDir,\n // eslint-disable-next-line no-template-curly-in-string\n filename: `java/${moduleDir}/target/${artifactId}-\\${KOS_STD_VERSION_REGEX}.kab`,\n });\n }\n return artifacts;\n}\n\nfunction syncManifest(\n codegenFs: CodegenFileSystem,\n manifestPath: string,\n discovered: DiscoveredArtifact[],\n prune: boolean\n): CiSyncManifestResult | null {\n const raw = codegenFs.read(manifestPath);\n if (raw === null) return null;\n const manifest = JSON.parse(raw);\n const existing: any[] = manifest.artifacts ?? [];\n\n const byFilename = new Map(discovered.map((d) => [d.filename, d]));\n const kept: any[] = [];\n const stale: string[] = [];\n const pruned: string[] = [];\n\n for (const entry of existing) {\n if (byFilename.has(entry.filename)) {\n kept.push(entry);\n byFilename.delete(entry.filename);\n } else if (prune) {\n pruned.push(entry.id ?? entry.filename);\n } else {\n kept.push(entry);\n stale.push(entry.id ?? entry.filename);\n }\n }\n\n const added: string[] = [];\n for (const artifact of byFilename.values()) {\n kept.push({\n id: artifact.id,\n filename: artifact.filename,\n artifactstore: \"kos-cdn\",\n marketplace: 1,\n ...(artifact.layer !== undefined ? { layer: artifact.layer } : {}),\n });\n added.push(artifact.id);\n }\n\n if (added.length > 0 || pruned.length > 0) {\n manifest.artifacts = kept;\n codegenFs.write(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n }\n\n return { added, stale, pruned };\n}\n\nexport function syncCiManifests(\n codegenFs: CodegenFileSystem,\n options: CiSyncOptions = {}\n): CiSyncResult {\n const prune = options.prune ?? false;\n const ui = discoverUiArtifacts(codegenFs);\n const java = discoverJavaArtifacts(codegenFs);\n\n const manifests: Record<string, CiSyncManifestResult> = {};\n const plan: Array<[string, DiscoveredArtifact[]]> = [\n [\".github/build-ui.json\", ui],\n [\".github/build-java.json\", java],\n [\".github/build-release.json\", [...ui, ...java]],\n ];\n for (const [manifestPath, discovered] of plan) {\n const result = syncManifest(codegenFs, manifestPath, discovered, prune);\n if (result) {\n manifests[manifestPath] = result;\n }\n }\n\n return { manifests, discovered: { ui, java } };\n}\n","/**\n * Helpers for the java/ half of a polyglot workspace (see\n * generate-polyglot-workspace.ts).\n *\n * The Java modules themselves come from the KOS Maven archetypes\n * (com.kos.archetypes — local-install via github.com/kosdev-code/\n * kos-maven-archetypes); these helpers contribute only the glue the\n * archetypes don't own:\n * - the java/pom.xml aggregator (archetype modules are standalone — no\n * parent link — so an aggregator is needed for `mvn` at java/ and for\n * build-java.sh's java/pom.xml check)\n * - repairs to the generated pom (the archetype references\n * ${kos-kab-maven-plugin.version} without defining it, and depends on\n * api-info which the kos-bom does not manage)\n * - registration of the module's KAB in the kos_build_handler manifests\n *\n * Version numbers are always passed in by the caller (derived from the KOS\n * Maven repo's maven-metadata.xml at run time) — nothing hardcoded here.\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\n\nexport interface EnsureJavaAggregatorOptions {\n groupId: string;\n /** Aggregator artifactId (typically the workspace name). */\n artifactId: string;\n moduleName: string;\n}\n\nexport function ensureJavaAggregatorPom(\n codegenFs: CodegenFileSystem,\n options: EnsureJavaAggregatorOptions\n): void {\n const pomPath = \"java/pom.xml\";\n const existing = codegenFs.read(pomPath);\n if (existing === null) {\n codegenFs.write(\n pomPath,\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n <modelVersion>4.0.0</modelVersion>\n <groupId>${options.groupId}</groupId>\n <artifactId>${options.artifactId}</artifactId>\n <version>0.0.0-SNAPSHOT</version>\n <packaging>pom</packaging>\n <modules>\n <module>${options.moduleName}</module>\n </modules>\n</project>\n`\n );\n return;\n }\n if (existing.includes(`<module>${options.moduleName}</module>`)) {\n return;\n }\n codegenFs.write(\n pomPath,\n existing.replace(\n \"</modules>\",\n ` <module>${options.moduleName}</module>\\n </modules>`\n )\n );\n}\n\nexport interface FinalizeArchetypeModuleOptions {\n moduleName: string;\n /** kos-bom version to pin (replaces the template's 0.0.0-SNAPSHOT). */\n kosVersion?: string;\n /** Fills the template's undefined ${kos-kab-maven-plugin.version}. */\n kabPluginVersion?: string;\n /** Explicit version for the api-info dep the kos-bom doesn't manage. */\n apiInfoVersion?: string;\n}\n\n/**\n * Repair a freshly archetype-generated module for use inside a polyglot\n * workspace. Returns human-readable notes about anything it could NOT fix\n * (missing versions the caller failed to derive) so the CLI can warn.\n */\nexport function finalizeArchetypeModule(\n codegenFs: CodegenFileSystem,\n options: FinalizeArchetypeModuleOptions\n): string[] {\n const { moduleName, kosVersion, kabPluginVersion, apiInfoVersion } = options;\n const notes: string[] = [];\n const pomPath = `java/${moduleName}/pom.xml`;\n let pom = codegenFs.read(pomPath);\n if (pom === null) {\n throw new Error(`Generated module pom not found: ${pomPath}`);\n }\n\n if (pom.includes(\"<kos.version>0.0.0-SNAPSHOT</kos.version>\")) {\n if (kosVersion) {\n pom = pom.replace(\n \"<kos.version>0.0.0-SNAPSHOT</kos.version>\",\n `<kos.version>${kosVersion}</kos.version>`\n );\n } else {\n notes.push(\n \"kos.version is 0.0.0-SNAPSHOT — set it to a released kos-bom version before building\"\n );\n }\n }\n\n if (\n pom.includes(\"${kos-kab-maven-plugin.version}\") &&\n !pom.includes(\"<kos-kab-maven-plugin.version>\")\n ) {\n if (kabPluginVersion) {\n pom = pom.replace(\n /(<kos\\.version>[^<]*<\\/kos\\.version>)/,\n `$1\\n <kos-kab-maven-plugin.version>${kabPluginVersion}</kos-kab-maven-plugin.version>`\n );\n } else {\n notes.push(\n \"the ${kos-kab-maven-plugin.version} property is referenced but undefined — add it before building\"\n );\n }\n }\n\n const unversionedApiInfo =\n /<artifactId>api-info<\\/artifactId>(\\s*)<\\/dependency>/;\n if (unversionedApiInfo.test(pom)) {\n if (apiInfoVersion) {\n pom = pom.replace(\n unversionedApiInfo,\n `<artifactId>api-info</artifactId>$1 <version>${apiInfoVersion}</version>$1</dependency>`\n );\n } else {\n notes.push(\n \"api-info has no version and is not managed by the kos-bom — add one before building\"\n );\n }\n }\n\n codegenFs.write(pomPath, pom);\n\n // Standalone-repo extras the archetype ships that are redundant inside a\n // polyglot workspace (the repo root owns CI):\n const githubDir = `java/${moduleName}/github`;\n if (codegenFs.exists(githubDir)) {\n for (const file of codegenFs.listFiles(githubDir)) {\n codegenFs.delete(file);\n }\n }\n const gitignore = codegenFs.read(`java/${moduleName}/gitignore`);\n if (gitignore !== null) {\n codegenFs.write(`java/${moduleName}/.gitignore`, gitignore);\n codegenFs.delete(`java/${moduleName}/gitignore`);\n }\n\n return notes;\n}\n\nexport interface AddJavaArtifactOptions {\n moduleName: string;\n}\n\n/**\n * Register the module's KAB in build-java.json and build-release.json.\n * Only the artifacts arrays are touched — keyset/build_cmd/etc. are the\n * user's (same contract as ci:sync).\n */\nexport function addJavaArtifactToManifests(\n codegenFs: CodegenFileSystem,\n options: AddJavaArtifactOptions\n): void {\n const { moduleName } = options;\n for (const manifestPath of [\n \".github/build-java.json\",\n \".github/build-release.json\",\n ]) {\n const raw = codegenFs.read(manifestPath);\n if (raw === null) {\n continue;\n }\n const manifest = JSON.parse(raw);\n manifest.artifacts = manifest.artifacts ?? [];\n if (\n manifest.artifacts.some(\n (artifact: { id?: string }) => artifact.id === moduleName\n )\n ) {\n continue;\n }\n manifest.artifacts.push({\n id: moduleName,\n // eslint-disable-next-line no-template-curly-in-string\n filename: `java/${moduleName}/target/${moduleName}-\\${KOS_STD_VERSION_REGEX}.kab`,\n artifactstore: \"kos-cdn\",\n marketplace: 1,\n });\n codegenFs.write(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n }\n}\n","/**\n * Normalize generator options — resolves project references and generates\n * all case variants for template substitution.\n *\n * Ported from kos-nx-plugin/src/generators/kos-model/lib/normalize-options.ts.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { readJson } from \"../json-utils\";\nimport { normalizeAllValues } from \"../normalize-values\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../project-discovery\";\n\nexport interface KosBaseGeneratorOptions {\n name: string;\n modelProject: string;\n registrationProject?: string;\n skipRegistration?: boolean;\n modelDirectory: string;\n companion?: boolean;\n companionModel?: string;\n companionModelProject?: string;\n companionPattern?: \"composition\" | \"decorator\";\n futureAware?: \"none\" | \"minimal\" | \"complete\";\n /** Absent is a legacy third state in @kosModel, so generated models always state it. */\n singleton?: boolean;\n}\n\nexport type NormalizedOptions<T extends KosBaseGeneratorOptions> = T & {\n nameDashCase: string;\n nameProperCase: string;\n nameCamelCase: string;\n namePascalCase: string;\n nameConstantCase: string;\n nameLowerCase: string;\n companionModelDashCase: string;\n companionModelProperCase: string;\n companionModelCamelCase: string;\n companionModelPascalCase: string;\n companionModelConstantCase: string;\n companionModelLowerCase: string;\n registrationProject: string;\n importPath: string;\n template: string;\n [key: string]: any;\n};\n\n/**\n * Normalize generator options by resolving the model project and generating\n * all name variants for template substitution.\n *\n * @param codegenFs - Filesystem abstraction\n * @param options - Raw generator options\n * @param projects - Optional pre-computed project map\n */\nexport function normalizeOptions<T extends KosBaseGeneratorOptions>(\n codegenFs: CodegenFileSystem,\n options: T,\n projects?: Map<string, ProjectConfiguration>\n): NormalizedOptions<T> {\n const toNormalize: Record<string, string> = {\n name: options.name,\n };\n\n if ((options as any).modelName) {\n toNormalize.modelName = (options as any).modelName;\n }\n\n if (options.companionModel) {\n toNormalize.companionModel = options.companionModel;\n }\n\n const normalizedValues = normalizeAllValues(toNormalize);\n const modelProject = options.modelProject;\n const registrationProject = options.registrationProject || \"\";\n const useModelProject = modelProject !== \"__NONE__\";\n\n let importPath = \"\";\n if (useModelProject) {\n const modelProjectConfig = findProjectByName(\n codegenFs.root,\n modelProject,\n projects\n );\n if (modelProjectConfig) {\n const pkgJsonPath = path.join(modelProjectConfig.root, \"package.json\");\n try {\n const pkgJson = readJson<{ name: string }>(codegenFs, pkgJsonPath);\n importPath = pkgJson.name || \"\";\n } catch {\n importPath = \"\";\n }\n }\n }\n\n // Provide safe defaults for optional boolean fields that templates reference\n // directly. Without explicit values, EJS throws ReferenceError for variables\n // that are simply absent from the options object (undefined keys are omitted\n // by the spread, which is different from being present-but-false).\n const booleanDefaults: Partial<KosBaseGeneratorOptions> = {\n companion: false,\n skipRegistration: false,\n futureAware: \"none\",\n singleton: false,\n };\n\n return {\n ...booleanDefaults,\n ...options,\n ...normalizedValues,\n modelProject,\n importPath,\n registrationProject,\n template: \"\",\n } as NormalizedOptions<T>;\n}\n","/**\n * Source of tools/scripts/update-release-version.mjs — the implementation of\n * the `version` target emitted by buildKabTargets (see kab-targets.ts).\n *\n * Kept as a constant (not a .template file) so the preset generator and the\n * add-version-targets migration emit byte-identical scripts and cannot drift.\n * The script has no template variables: the project name arrives via argv.\n */\nexport const UPDATE_RELEASE_VERSION_SCRIPT = `import devkit from \"@nx/devkit\";\nimport { resolve } from \"path\";\nimport { readFileSync, writeFileSync } from \"fs\";\nimport prettier from \"prettier\";\n\n// KOS artifact versioning: stamps the project's .kos.json \"version\" field\n// (which kabtool bakes into the KAB). Never touches package.json.\n// Driven by tag-based releases:\n// nx run-many --target=version --args=--ver=$KOSBUILD_VERSION\n\nconst { readCachedProjectGraph } = devkit;\nconst [, , name, versionArg] = process.argv;\n\n// \"{args.ver}\" arrives literally when the target runs without --args=--ver=<v>;\n// treat that (or a missing arg) as \"report current version, change nothing\".\nconst version =\n versionArg && !versionArg.startsWith(\"{args\") ? versionArg : undefined;\n\nif (!name) {\n console.error(\"usage: update-release-version.mjs <project> <version>\");\n process.exit(1);\n}\n\nconst graph = readCachedProjectGraph();\nconst project = graph.nodes[name];\nif (!project) {\n console.error(\"Unknown project: \" + name);\n process.exit(1);\n}\n\nconst kosJsonPath = resolve(process.cwd(), project.data.root, \".kos.json\");\nlet kosJson;\ntry {\n kosJson = JSON.parse(readFileSync(kosJsonPath, \"utf8\"));\n} catch {\n console.error(\"Missing or invalid .kos.json: \" + kosJsonPath);\n process.exit(1);\n}\n\nif (!version) {\n console.log(name + \": \" + kosJson.version + \" (no --ver given; unchanged)\");\n process.exit(0);\n}\n\nconst prettierOptions = await prettier.resolveConfig(kosJsonPath);\nconst output = await prettier.format(\n JSON.stringify({ ...kosJson, version }, null, 2),\n { ...prettierOptions, parser: \"json\" }\n);\nwriteFileSync(kosJsonPath, output);\nconsole.log(name + \": version -> \" + version);\n`;\n","/**\n * Shared model-augmentation toolkit (ts-morph / AST based).\n *\n * Primitives for the capability mutators (add-container-support, add-future, …)\n * that augment an EXISTING model with coordinated, multi-site edits — decorators,\n * declaration-merging interfaces, imports, methods — without the fragility of\n * regex string replacement.\n *\n * Bridged through CodegenFileSystem so the same dry-run overlay + formatFiles\n * pipeline used by the scaffolders applies unchanged: read content → in-memory\n * ts-morph SourceFile → mutate → getFullText() → write.\n *\n * ts-morph is confined to kos-codegen-core (build-time tooling) and must not leak\n * into any runtime SDK package.\n */\nimport {\n IndentationText,\n Node,\n Project,\n QuoteKind,\n Scope,\n VariableDeclarationKind,\n type ClassDeclaration,\n type ObjectLiteralExpression,\n type SourceFile,\n} from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\n\n/**\n * Read a file via the filesystem abstraction, apply an AST mutation, write it back.\n * The mutation operates on an in-memory ts-morph SourceFile — no disk access here,\n * so the caller's CodegenFileSystem (real or dry-run overlay) owns all I/O.\n */\nexport function transformSourceFile(\n codegenFs: CodegenFileSystem,\n filePath: string,\n mutate: (sf: SourceFile) => void\n): void {\n const content = codegenFs.read(filePath);\n if (content === null) {\n throw new Error(`File not found: ${filePath}`);\n }\n const project = new Project({\n useInMemoryFileSystem: true,\n manipulationSettings: {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: QuoteKind.Double,\n },\n });\n const sourceFile = project.createSourceFile(filePath, content, {\n overwrite: true,\n });\n mutate(sourceFile);\n codegenFs.write(filePath, sourceFile.getFullText());\n}\n\n/**\n * Read a file via the filesystem abstraction and inspect it as a ts-morph\n * SourceFile, writing nothing back. The read-only counterpart of\n * `transformSourceFile`, for discovery over generated declarations.\n */\nexport function readSourceFile<T>(\n codegenFs: CodegenFileSystem,\n filePath: string,\n inspect: (sf: SourceFile) => T\n): T {\n const content = codegenFs.read(filePath);\n if (content === null) {\n throw new Error(`File not found: ${filePath}`);\n }\n const project = new Project({ useInMemoryFileSystem: true });\n return inspect(\n project.createSourceFile(filePath, content, { overwrite: true })\n );\n}\n\n/**\n * The object-literal text of a class decorator's first argument, whether written\n * inline or passed as a same-file const. Generated models name the config so a\n * derived type can read it; hand-written ones inline it.\n */\nexport function decoratorConfigText(\n sourceFile: SourceFile,\n cls: ClassDeclaration,\n decoratorName: string\n): string | undefined {\n const arg = cls.getDecorator(decoratorName)?.getArguments()[0];\n if (!arg) return undefined;\n if (arg.getKindName() === \"ObjectLiteralExpression\") return arg.getText();\n\n // Anything that is not an identifier (a bare string literal, say) is its own\n // text; an identifier is followed to the const it names.\n const text = arg.getText().trim();\n if (!/^[A-Za-z_$][\\w$]*$/.test(text)) return text;\n const initializer = sourceFile\n .getVariableDeclaration(text)\n ?.getInitializer()\n ?.getText();\n return initializer ? initializer.replace(/\\s+as\\s+const\\s*$/, \"\") : text;\n}\n\n/** A named import to ensure on a module: the symbol and whether it is type-only. */\nexport interface NamedImportSpec {\n name: string;\n isTypeOnly?: boolean;\n}\n\n/**\n * Ensure the given named imports exist on an import from `moduleSpecifier`.\n * Idempotent: existing names are left untouched; the import declaration is created\n * if absent. Resolves to the same module the model already imports `kosModel` from\n * when `moduleSpecifier` matches, so internal vs. published paths are respected.\n */\nexport function ensureNamedImport(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n names: NamedImportSpec[]\n): void {\n const decls = sourceFile\n .getImportDeclarations()\n .filter((d) => d.getModuleSpecifierValue() === moduleSpecifier);\n\n // Dedup across ALL imports from this module (a file may have both a value\n // import and a separate `import type { … }` from the same specifier).\n const existing = new Set<string>();\n for (const d of decls) {\n for (const n of d.getNamedImports()) existing.add(n.getName());\n }\n\n // Always target a VALUE import declaration — adding a runtime symbol to an\n // `import type { … }` block would strip it at compile time. Type-only names go\n // in with an inline `type` modifier (the `import { kosX, type KosX }` idiom).\n let target = decls.find((d) => !d.isTypeOnly());\n if (!target) {\n target = sourceFile.addImportDeclaration({ moduleSpecifier });\n }\n\n for (const { name, isTypeOnly } of names) {\n if (existing.has(name)) continue;\n target.addNamedImport({ name, isTypeOnly: !!isTypeOnly });\n existing.add(name);\n }\n}\n\n/**\n * Resolve the module specifier the model imports `kosModel` from, so augmentation\n * imports land on the same line/source (internal `../../../core/core/decorators`\n * vs. published `@kosdev-code/kos-ui-sdk`). Falls back to the published package.\n */\nexport function resolveSdkModuleSpecifier(sourceFile: SourceFile): string {\n const decl = sourceFile\n .getImportDeclarations()\n .find((d) => d.getNamedImports().some((n) => n.getName() === \"kosModel\"));\n return decl?.getModuleSpecifierValue() ?? \"@kosdev-code/kos-ui-sdk\";\n}\n\n/**\n * Find the primary model class. Prefers `preferName`, then a class whose name ends\n * in `ModelImpl`, then the first exported class, then the first class.\n */\nexport function getModelClass(\n sourceFile: SourceFile,\n preferName?: string\n): ClassDeclaration {\n const classes = sourceFile.getClasses();\n const byName = preferName\n ? classes.find((c) => c.getName() === preferName)\n : undefined;\n if (byName) return byName;\n const impl = classes.find((c) => /ModelImpl$/.test(c.getName() ?? \"\"));\n if (impl) return impl;\n const exported = classes.find((c) => c.isExported());\n if (exported) return exported;\n if (classes.length > 0) return classes[0];\n throw new Error(\"No class declaration found in model file.\");\n}\n\n/**\n * Add a class decorator idempotently (matched by decorator name). Supports type\n * arguments (`@name<T>(args)`) which ts-morph's structured API can't express, by\n * writing the call expression as decorator text. Inserts directly after `@kosModel`\n * when present (matching KOS convention), otherwise nearest the class.\n */\nexport function addClassDecorator(\n cls: ClassDeclaration,\n name: string,\n opts?: { typeArgs?: string[]; argsText?: string }\n): void {\n if (cls.getDecorator(name)) return;\n const typeArgs = opts?.typeArgs?.length\n ? `<${opts.typeArgs.join(\", \")}>`\n : \"\";\n const args = opts?.argsText ?? \"\";\n\n const decorators = cls.getDecorators();\n const kosModelIdx = decorators.findIndex((d) => d.getName() === \"kosModel\");\n const insertIdx = kosModelIdx >= 0 ? kosModelIdx + 1 : decorators.length;\n cls.insertDecorator(insertIdx, {\n name: `${name}${typeArgs}`,\n arguments: args ? [args] : [],\n });\n}\n\n/**\n * Ensure a declaration-merging interface `export interface <name> extends <expr>`.\n * If the interface already exists (e.g. merged for another capability), adds the\n * extends expression to it; otherwise creates an empty exported interface with the\n * `no-empty-interface` lint suppression. Idempotent by base type name.\n */\nexport function ensureDeclarationMerge(\n sourceFile: SourceFile,\n interfaceName: string,\n extendsExpr: string,\n typeParameters: string[] = []\n): void {\n const baseType = extendsExpr.split(\"<\")[0].trim();\n let iface = sourceFile.getInterface(interfaceName);\n if (iface) {\n const already = iface\n .getExtends()\n .some((e) => e.getText().split(\"<\")[0].trim() === baseType);\n if (!already) iface.addExtends(extendsExpr);\n return;\n }\n // A merged interface must carry the SAME type parameters as the class it merges\n // with, or TS errors (\"all declarations must have identical type parameters\").\n iface = sourceFile.addInterface({\n name: interfaceName,\n isExported: true,\n typeParameters,\n extends: [extendsExpr],\n });\n // Prepend the empty-interface lint suppression line.\n sourceFile.insertText(\n iface.getStart(),\n \"// eslint-disable-next-line @typescript-eslint/no-empty-interface\\n\"\n );\n}\n\n/**\n * Ensure a file-level eslint-disable block comment for `rule` at the top of file.\n * Call LAST in a mutation — it uses raw text insertion and invalidates node refs.\n */\nexport function ensureFileEslintDisable(\n sourceFile: SourceFile,\n rule: string\n): void {\n if (sourceFile.getFullText().includes(rule)) return;\n sourceFile.insertText(0, `/* eslint-disable ${rule} */\\n`);\n}\n\n/**\n * Add a module-level `const` after the import block, idempotently. Returns true\n * if added. Used for endpoint descriptors, which must sit outside the class so\n * `typeof NAME` can be referenced from a parameter type.\n */\nexport function ensureModuleConst(\n sourceFile: SourceFile,\n spec: { name: string; initializer: string }\n): boolean {\n if (sourceFile.getVariableDeclaration(spec.name)) return false;\n const imports = sourceFile.getImportDeclarations();\n const index =\n imports.length > 0 ? imports[imports.length - 1].getChildIndex() + 1 : 0;\n sourceFile.insertVariableStatement(index, {\n declarationKind: VariableDeclarationKind.Const,\n declarations: [{ name: spec.name, initializer: spec.initializer }],\n });\n return true;\n}\n\n/** Index just past the last import, where module-level declarations belong. */\nfunction afterImports(sourceFile: SourceFile): number {\n const imports = sourceFile.getImportDeclarations();\n return imports.length > 0\n ? imports[imports.length - 1].getChildIndex() + 1\n : 0;\n}\n\n/** Strip the quotes ts-morph keeps on a quoted property name. */\nfunction unquote(name: string): string {\n return name.replace(/^[\"']|[\"']$/g, \"\");\n}\n\n/** The object literal an `export const X = { … } as const` declares, or null. */\nfunction getConstCatalogLiteral(\n sourceFile: SourceFile,\n name: string\n): ObjectLiteralExpression | null {\n const declaration = sourceFile.getVariableDeclaration(name);\n if (!declaration) return null;\n let initializer = declaration.getInitializer();\n if (Node.isAsExpression(initializer)) {\n initializer = initializer.getExpression();\n }\n if (!initializer || !Node.isObjectLiteralExpression(initializer)) {\n throw new Error(\n `\"${name}\" exists in ${sourceFile.getBaseName()} but is not an object literal.`\n );\n }\n return initializer;\n}\n\n/**\n * Ensure an exported `as const` catalog holds an entry with this initializer,\n * and report the key that holds it.\n *\n * An entry whose initializer already matches is REUSED rather than duplicated,\n * so one descriptor is declared once however many members reference it.\n * Equivalence is delegated to `equals` because equivalent initializers are not\n * always identical text — quote style and spacing vary by who wrote the file.\n */\nexport function ensureConstCatalogEntry(\n sourceFile: SourceFile,\n spec: {\n catalogName: string;\n key: string;\n initializer: string;\n equals?: (existing: string, candidate: string) => boolean;\n /** Doc comment for the new entry. Not applied when an entry is reused. */\n leadingTrivia?: string;\n }\n): { key: string; created: boolean } {\n const matches =\n spec.equals ??\n ((existing: string, candidate: string) => existing === candidate);\n\n let literal = getConstCatalogLiteral(sourceFile, spec.catalogName);\n if (!literal) {\n // Created empty and filled through the structured API, so the first entry\n // is indented by ts-morph exactly like every later one.\n sourceFile.insertVariableStatement(afterImports(sourceFile), {\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [{ name: spec.catalogName, initializer: \"{} as const\" }],\n });\n literal = getConstCatalogLiteral(sourceFile, spec.catalogName);\n if (!literal) {\n throw new Error(`Failed to create catalog \"${spec.catalogName}\".`);\n }\n literal.addPropertyAssignment({\n name: spec.key,\n initializer: spec.initializer,\n leadingTrivia: spec.leadingTrivia,\n });\n return { key: spec.key, created: true };\n }\n\n for (const property of literal\n .getProperties()\n .filter(Node.isPropertyAssignment)) {\n const existingKey = unquote(property.getName());\n const existingInitializer = property.getInitializerOrThrow().getText();\n if (matches(existingInitializer, spec.initializer)) {\n return { key: existingKey, created: false };\n }\n if (existingKey === spec.key) {\n throw new Error(\n `\"${spec.catalogName}.${spec.key}\" already exists with a different value ` +\n `(${existingInitializer}). Use a different methodName, or reconcile the catalog by hand.`\n );\n }\n }\n\n literal.addPropertyAssignment({\n name: spec.key,\n initializer: spec.initializer,\n leadingTrivia: spec.leadingTrivia,\n });\n return { key: spec.key, created: true };\n}\n\n/** Add an exported type alias unless one of that name already exists. */\nexport function ensureExportedTypeAlias(\n sourceFile: SourceFile,\n spec: { name: string; type: string; docs?: string }\n): boolean {\n if (sourceFile.getTypeAlias(spec.name)) return false;\n sourceFile.addTypeAlias({\n name: spec.name,\n type: spec.type,\n isExported: true,\n docs: spec.docs ? [spec.docs] : undefined,\n });\n return true;\n}\n\n/**\n * Add an exported identity mapper `raw -> data` unless one of that name exists.\n * Emitted as an identity so it compiles untouched; narrowing the data type is\n * what makes it a real boundary.\n */\nexport function ensureExportedMapper(\n sourceFile: SourceFile,\n spec: { name: string; rawType: string; dataType: string }\n): boolean {\n if (sourceFile.getVariableDeclaration(spec.name)) return false;\n sourceFile.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: spec.name,\n initializer: `(raw: ${spec.rawType}): ${spec.dataType} => raw`,\n },\n ],\n });\n return true;\n}\n\n/** Add `export * from \"<moduleSpecifier>\"` unless the barrel already has it. */\nexport function ensureBarrelExport(\n sourceFile: SourceFile,\n moduleSpecifier: string\n): boolean {\n const present = sourceFile\n .getExportDeclarations()\n .some((d) => d.getModuleSpecifierValue() === moduleSpecifier);\n if (present) return false;\n sourceFile.addExportDeclaration({ moduleSpecifier });\n return true;\n}\n\n/**\n * Add named exports for a module to a barrel, creating the export declaration\n * when the module is not exported yet and appending only the missing names when\n * it is. Value and type exports are kept as separate declarations so a type-only\n * export is not widened into a value export.\n *\n * Returns true if the file changed.\n */\nexport function ensureNamedExports(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n names: string[],\n isTypeOnly = false\n): boolean {\n const existing = sourceFile\n .getExportDeclarations()\n .find(\n (d) =>\n d.getModuleSpecifierValue() === moduleSpecifier &&\n d.isTypeOnly() === isTypeOnly\n );\n\n if (!existing) {\n sourceFile.addExportDeclaration({\n moduleSpecifier,\n isTypeOnly,\n namedExports: names.map((name) => {\n return { name };\n }),\n });\n return true;\n }\n\n const present = new Set(existing.getNamedExports().map((e) => e.getName()));\n const missing = names.filter((name) => !present.has(name));\n if (missing.length === 0) return false;\n\n existing.addNamedExports(\n missing.map((name) => {\n return { name };\n })\n );\n return true;\n}\n\n/**\n * Add an exported interface to a declarations file, leaving any existing\n * declaration untouched. Returns true if the interface was added.\n */\nexport function ensureExportedInterface(\n sourceFile: SourceFile,\n name: string,\n properties: { name: string; type: string; hasQuestionToken?: boolean }[] = [],\n extendsTypes: string[] = []\n): boolean {\n if (sourceFile.getInterface(name)) return false;\n\n sourceFile.addInterface({\n name,\n isExported: true,\n extends: extendsTypes,\n properties,\n });\n return true;\n}\n\n/** A decorated method to add to a model class. */\nexport interface DecoratedMethodSpec {\n name: string;\n decoratorName: string;\n /** Explicit decorator type arguments, e.g. `[\"RawType\", \"DataType\"]`. */\n decoratorTypeArgs?: string[];\n decoratorArgsText?: string;\n parameters?: { name: string; type?: string; optional?: boolean }[];\n returnType?: string;\n isAsync?: boolean;\n statements?: string;\n /** Doc comment emitted above the method. */\n docs?: string;\n}\n\n/**\n * Add a decorated method to a class idempotently (skips if a method of that name\n * already exists). Returns true if added.\n */\nexport function addDecoratedMethod(\n cls: ClassDeclaration,\n spec: DecoratedMethodSpec\n): boolean {\n if (cls.getMethod(spec.name)) return false;\n cls.addMethod({\n name: spec.name,\n isAsync: spec.isAsync,\n returnType: spec.returnType,\n docs: spec.docs ? [spec.docs] : undefined,\n parameters: spec.parameters?.map((p) => {\n return { name: p.name, type: p.type, hasQuestionToken: p.optional };\n }),\n statements: spec.statements,\n decorators: [\n {\n name: spec.decoratorName,\n typeArguments: spec.decoratorTypeArgs,\n arguments: spec.decoratorArgsText ? [spec.decoratorArgsText] : [],\n },\n ],\n });\n return true;\n}\n\n/** A plain (undecorated) property to add to a model class. */\nexport interface PlainPropertySpec {\n name: string;\n type?: string;\n /** Initializer expression text, e.g. `\"\"`, `0`, `false`. */\n initializer?: string;\n scope?: \"private\" | \"protected\" | \"public\";\n readonly?: boolean;\n /** Definite-assignment `!` (compiles under strictPropertyInitialization). */\n hasExclamation?: boolean;\n}\n\n/**\n * Member index for a new property: right after the last existing property, so\n * properties (basic fields, dependencies, config properties) stay grouped at the\n * TOP of the class — before the constructor and methods. Index 0 if none yet.\n */\nfunction propertyInsertIndex(cls: ClassDeclaration): number {\n const props = cls.getProperties();\n if (props.length === 0) return 0;\n return props[props.length - 1].getChildIndex() + 1;\n}\n\n/**\n * Add a plain class property (no decorator) idempotently. Returns true if added.\n * Used for basic model state fields (`prop1: string`) — distinct from the\n * decorator-backed config/dependency/etc. properties. Inserted at the top.\n */\nexport function addPlainProperty(\n cls: ClassDeclaration,\n spec: PlainPropertySpec\n): boolean {\n if (cls.getProperty(spec.name)) return false;\n cls.insertProperty(propertyInsertIndex(cls), {\n name: spec.name,\n type: spec.type,\n initializer: spec.initializer,\n isReadonly: !!spec.readonly,\n scope: spec.scope ? SCOPE_MAP[spec.scope] : undefined,\n hasExclamationToken: spec.initializer ? false : !!spec.hasExclamation,\n });\n return true;\n}\n\n/** A decorated property to add to a model class. */\nexport interface DecoratedPropertySpec {\n name: string;\n decoratorName: string;\n decoratorArgsText?: string;\n type?: string;\n scope?: \"private\" | \"protected\" | \"public\";\n hasExclamation?: boolean;\n /** Initializer expression text, e.g. `new KosModelContainer<X>()` or `[]`. */\n initializer?: string;\n /**\n * Emit the decorator WITHOUT call parens — a DIRECT (non-factory) decorator like\n * `@kosChild`. Default false (factory form `@name()` / `@name(args)`).\n */\n bare?: boolean;\n}\n\nconst SCOPE_MAP = {\n private: Scope.Private,\n protected: Scope.Protected,\n public: Scope.Public,\n} as const;\n\n/**\n * Add a decorated property to a class idempotently (skips if a property of that\n * name already exists). Returns true if added.\n */\nexport function addDecoratedProperty(\n cls: ClassDeclaration,\n spec: DecoratedPropertySpec\n): boolean {\n if (cls.getProperty(spec.name)) return false;\n cls.insertProperty(propertyInsertIndex(cls), {\n name: spec.name,\n type: spec.type,\n initializer: spec.initializer,\n scope: spec.scope ? SCOPE_MAP[spec.scope] : undefined,\n hasExclamationToken: spec.initializer ? false : !!spec.hasExclamation,\n decorators: [\n spec.bare && !spec.decoratorArgsText\n ? { name: spec.decoratorName } // no `arguments` key → bare `@name`, no parens\n : {\n name: spec.decoratorName,\n arguments: spec.decoratorArgsText ? [spec.decoratorArgsText] : [],\n },\n ],\n });\n return true;\n}\n\n/** A computed getter to add to a model class. */\nexport interface GetterSpec {\n name: string;\n returnType?: string;\n /** Body statements; default a TODO stub returning undefined. */\n statements?: string;\n}\n\n/**\n * Add a computed getter (`get name(): T { ... }`) idempotently — a derived,\n * read-only member. Returns true if added. Placed after the constructor (or after\n * the properties if there is none), ahead of regular methods.\n */\nexport function addGetter(cls: ClassDeclaration, spec: GetterSpec): boolean {\n if (cls.getGetAccessor(spec.name)) return false;\n const ctor = cls.getConstructors()[0];\n const index = ctor ? ctor.getChildIndex() + 1 : propertyInsertIndex(cls);\n cls.insertGetAccessor(index, {\n name: spec.name,\n returnType: spec.returnType,\n statements:\n spec.statements ?? \"// TODO: derive and return the computed value\",\n });\n return true;\n}\n","/**\n * Enumerate the service operations a project already has types for.\n *\n * NOT a substitute for the device. A connected device's live OpenAPI is the\n * source of truth about what endpoints exist, what they mean, and whether one\n * is debug-only — discover there first (kos-device: `search_services` →\n * `describe_endpoint` → `resolve_service_request`). This reads the types\n * `api:generate` already wrote into the project, which is a SNAPSHOT of that\n * truth: correct for the app/version it was generated from, silent about\n * anything added since, and empty until api:generate has run.\n *\n * It exists for the offline case — no device reachable, or a human picking from\n * a list rather than typing a path from memory.\n *\n * Everything here comes out of `openapi.d.ts`, which openapi-typescript emits in\n * a shape precise enough to read structurally: a method that exists is\n * `post: { … }` while an absent one is `post?: never`, the OpenAPI `summary`\n * survives as the method's JSDoc, and path parameters keep their names.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { readSourceFile } from \"./augment/ts-toolkit\";\n\n/** HTTP methods a response type can be derived for (lowercase, as spec'd). */\nconst CATALOG_METHODS = [\"get\", \"put\", \"post\", \"delete\", \"patch\"] as const;\nexport type CatalogMethod = (typeof CATALOG_METHODS)[number];\n\nexport interface ServiceOperation {\n /** OpenAPI path, e.g. `/api/board/{id}`. */\n path: string;\n method: CatalogMethod;\n /** The spec's `summary`, when it had one. */\n summary?: string;\n /** Names of the `{…}` placeholders the path declares, in order. */\n pathParams: string[];\n}\n\nexport interface ServiceCatalogEntry {\n /** App segment of the services dir, e.g. `dispense`. */\n app: string;\n /** Version segment, e.g. `daily` or `1.9.x`. */\n version: string;\n /** Root-relative path of the generated service module (with extension). */\n serviceModulePath: string;\n operations: ServiceOperation[];\n}\n\nconst SERVICE_MODULE_RE = /\\/utils\\/services\\/([^/]+)\\/([^/]+)\\/service\\.ts$/;\n\nexport interface ServiceCatalogQuery {\n /** Project whose generated types to read. */\n modelProject: string;\n /** Limit to one app segment (e.g. `dispense`). */\n app?: string;\n /** Limit to one version segment (e.g. `daily`). */\n version?: string;\n}\n\n/**\n * List every generated service module in a project and the operations it types.\n * Returns an empty array when the project has no generated types — the caller\n * should tell the user to run `api:generate`, not treat it as \"no endpoints\".\n */\nexport function listServiceCatalog(\n codegenFs: CodegenFileSystem,\n query: ServiceCatalogQuery,\n projects?: Map<string, ProjectConfiguration>\n): ServiceCatalogEntry[] {\n const project = findProjectByName(\n codegenFs.root,\n query.modelProject,\n projects\n );\n if (!project) {\n throw new Error(`Project not found: ${query.modelProject}`);\n }\n const sourceRoot = project.sourceRoot || path.join(project.root, \"src\");\n\n const entries: ServiceCatalogEntry[] = [];\n for (const file of codegenFs.listFiles(sourceRoot)) {\n const posix = file.split(path.sep).join(\"/\");\n const match = SERVICE_MODULE_RE.exec(posix);\n if (!match) continue;\n const [, app, version] = match;\n if (query.app && app !== query.app) continue;\n if (query.version && version !== query.version) continue;\n\n const openapiPath = posix.replace(/service\\.ts$/, \"openapi.d.ts\");\n if (!codegenFs.exists(openapiPath)) continue;\n\n entries.push({\n app,\n version,\n serviceModulePath: posix,\n operations: readOperations(codegenFs, openapiPath) ?? [],\n });\n }\n return entries.sort(\n (a, b) => a.app.localeCompare(b.app) || a.version.localeCompare(b.version)\n );\n}\n\n/**\n * The operations a generated service module types, for callers that hold the\n * module rather than a project name — path validation, above all.\n *\n * `paths` normally lives in the `openapi.d.ts` beside the module, but the module\n * may declare it inline instead. Returns null when NEITHER does: that is \"these\n * types cannot answer the question\", which a caller must not read as \"the\n * endpoint does not exist\".\n *\n * @param serviceModuleFile Root-relative path of the module, with or without `.ts`.\n */\nexport function readServiceModuleOperations(\n codegenFs: CodegenFileSystem,\n serviceModuleFile: string\n): ServiceOperation[] | null {\n const moduleFile = serviceModuleFile.endsWith(\".ts\")\n ? serviceModuleFile\n : `${serviceModuleFile}.ts`;\n const posix = moduleFile.split(path.sep).join(\"/\");\n const openapiPath = posix.replace(/service\\.ts$/, \"openapi.d.ts\");\n\n for (const candidate of [openapiPath, posix]) {\n if (!codegenFs.exists(candidate)) continue;\n const operations = readOperations(codegenFs, candidate);\n if (operations) return operations;\n }\n return null;\n}\n\n/** Parse one `openapi.d.ts` into its operations; null when it declares no `paths`. */\nfunction readOperations(\n codegenFs: CodegenFileSystem,\n openapiPath: string\n): ServiceOperation[] | null {\n return readSourceFile(codegenFs, openapiPath, (sf) => {\n const paths = sf.getInterface(\"paths\");\n if (!paths) return null;\n\n const operations: ServiceOperation[] = [];\n for (const pathProp of paths.getProperties()) {\n const servicePath = unquote(pathProp.getName());\n const literal = pathProp.getTypeNode();\n // Each path maps to a type literal of per-method members; anything else\n // is a shape this parser does not claim to understand.\n if (!literal || !(\"getProperties\" in literal)) continue;\n\n for (const methodProp of (literal as any).getProperties()) {\n const method = methodProp.getName();\n if (!isCatalogMethod(method)) continue;\n const typeText: string = methodProp.getTypeNode()?.getText() ?? \"\";\n // `post?: never` is the spec saying this path has no POST.\n if (methodProp.hasQuestionToken() && typeText === \"never\") continue;\n\n operations.push({\n path: servicePath,\n method,\n summary: readSummary(methodProp),\n pathParams: [...servicePath.matchAll(/\\{([^}]+)\\}/g)].map(\n (m) => m[1]\n ),\n });\n }\n }\n return operations;\n });\n}\n\nfunction isCatalogMethod(value: string): value is CatalogMethod {\n return (CATALOG_METHODS as readonly string[]).includes(value);\n}\n\n/** The OpenAPI `summary`, which openapi-typescript emits as leading JSDoc. */\nfunction readSummary(methodProp: {\n getLeadingCommentRanges: () => { getText: () => string }[];\n}): string | undefined {\n const text = methodProp\n .getLeadingCommentRanges()\n .map((c) => c.getText())\n .join(\" \")\n .replace(/^\\/\\*+/, \"\")\n .replace(/\\*+\\/$/, \"\")\n .replace(/^\\s*\\*\\s?/gm, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n return text || undefined;\n}\n\nfunction unquote(name: string): string {\n return name.replace(/^[\"']|[\"']$/g, \"\");\n}\n","/**\n * Barrel export manipulation utilities.\n *\n * Appends `export * from './path'` lines to index.ts files,\n * handling deduplication.\n */\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\n\n/**\n * Append a barrel re-export to an index.ts file, creating it if necessary.\n * Skips the append if the export already exists.\n *\n * @param codegenFs - Filesystem abstraction\n * @param indexPath - Path to the index.ts file (relative to root)\n * @param exportPath - The module path to export (e.g. './my-hook')\n */\nexport function appendBarrelExport(\n codegenFs: CodegenFileSystem,\n indexPath: string,\n exportPath: string\n): void {\n const exportLine = `export * from '${exportPath}'`;\n const content = codegenFs.read(indexPath) ?? \"\";\n const lines = content.split(\"\\n\");\n\n if (lines.some((line) => line.includes(exportLine))) {\n return; // already present\n }\n\n lines.push(exportLine);\n codegenFs.write(indexPath, lines.join(\"\\n\"));\n}\n","/**\n * TypeScript AST-based index.ts updater.\n *\n * Adds `export * from './path'` declarations to a barrel file using\n * the TypeScript compiler API for proper AST manipulation.\n *\n * Ported from kos-nx-plugin/src/generators/kos-model/lib/utils/ts-visitor.ts.\n */\nimport * as ts from \"typescript\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { getCodegenLogger } from \"../logger\";\n\n/**\n * Add an export-all declaration to an index.ts file using TS AST.\n *\n * @param codegenFs - Filesystem abstraction\n * @param indexPath - Path to the index.ts file (relative to root)\n * @param modelPath - Relative path to export (e.g. 'models/my-model')\n */\nexport function updateModelIndex(\n codegenFs: CodegenFileSystem,\n indexPath: string,\n modelPath: string\n): void {\n const logger = getCodegenLogger();\n\n if (!indexPath) return;\n\n const content = codegenFs.read(indexPath);\n if (content === null) {\n logger.warn(`Index file not found: ${indexPath}`);\n return;\n }\n\n logger.info(`Updating ${indexPath} — adding export for ${modelPath}`);\n\n const sourceFile = ts.createSourceFile(\n indexPath,\n content,\n ts.ScriptTarget.Latest,\n true\n );\n\n // Idempotent: the model and container passes both target the same directory,\n // and generators may be re-run — never append a duplicate export.\n const alreadyExported = sourceFile.statements.some(\n (st) =>\n ts.isExportDeclaration(st) &&\n st.moduleSpecifier !== undefined &&\n ts.isStringLiteral(st.moduleSpecifier) &&\n st.moduleSpecifier.text === `./${modelPath}`\n );\n if (alreadyExported) {\n logger.info(`Export for ${modelPath} already present in ${indexPath}`);\n return;\n }\n\n const exportDeclaration = ts.factory.createExportDeclaration(\n undefined,\n false,\n undefined,\n ts.factory.createStringLiteral(`./${modelPath}`)\n );\n\n const updatedSourceFile = ts.factory.updateSourceFile(sourceFile, [\n ...sourceFile.statements,\n exportDeclaration,\n ]);\n\n const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n const newContents = printer.printFile(updatedSourceFile);\n\n codegenFs.write(indexPath, newContents);\n}\n","/**\n * Core generator: KOS Companion Model.\n *\n * Generates companion model files into a child project with references\n * to the parent model's package.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { readJson } from \"../json-utils\";\nimport { normalizeAllValues } from \"../normalize-values\";\nimport { getCodegenLogger } from \"../logger\";\nimport { getKosProjectConfiguration } from \"../kos-config\";\n\nexport interface CompanionModelOptions {\n companionModelName: string;\n companionModelProject: string;\n modelName: string;\n modelProject: string;\n companionPattern?: \"composition\" | \"decorator\";\n}\n\n/**\n * Generate a companion model.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory\n * @param options - Generator options\n * @param projects - Optional pre-computed project map\n */\nexport function generateCompanionModel(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: CompanionModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n const logger = getCodegenLogger();\n\n const normalized = normalizeAllValues({\n companionModelName: options.companionModelName,\n modelName: options.modelName,\n });\n\n const companionChildKosConfig = getKosProjectConfiguration(\n codegenFs,\n options.companionModelProject,\n projects\n );\n\n const parentProject = findProjectByName(\n codegenFs.root,\n options.modelProject,\n projects\n );\n const childProject = findProjectByName(\n codegenFs.root,\n options.companionModelProject,\n projects\n );\n\n const projectRoot = childProject?.sourceRoot;\n if (!projectRoot) {\n logger.warn(`Companion child project source root not found`);\n return;\n }\n\n let importPath = \"\";\n if (parentProject) {\n const pkgJsonPath = path.join(parentProject.root, \"package.json\");\n try {\n const pkgJson = readJson<{ name: string }>(codegenFs, pkgJsonPath);\n importPath = pkgJson.name || \"\";\n } catch {\n importPath = \"\";\n }\n }\n\n const modelLocation =\n companionChildKosConfig?.generator?.defaults?.model?.folder || \"\";\n const filePath = path.join(\n projectRoot,\n modelLocation,\n normalized.companionModelNameDashCase\n );\n\n logger.info(`Generating companion model in ${filePath}`);\n generateFilesFromTemplates(codegenFs, templateDir, filePath, {\n ...options,\n ...normalized,\n importPath,\n });\n}\n","/**\n * Core generator: KOS Container Model.\n *\n * Generates a container model within an existing model project.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as ejs from \"ejs\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport {\n addKosModelConfiguration,\n getCurrentDirectoryName,\n getKosProjectConfiguration,\n getProject,\n} from \"../kos-config\";\nimport { getCodegenLogger } from \"../logger\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport {\n ensureExportedInterface,\n ensureNamedExports,\n transformSourceFile,\n} from \"./augment/ts-toolkit\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { updateModelIndex } from \"./update-model-index\";\n\nexport interface ContainerModelOptions extends KosBaseGeneratorOptions {\n modelName?: string;\n singleton?: boolean;\n autoRegister?: boolean;\n /**\n * The model folder already exists and holds a written model, so the container\n * is ADDED to it: only the container model file is rendered, and the folder's\n * types and barrel are edited in place. Rendering the whole template set here\n * would overwrite the model's own options interface and barrel.\n */\n existingModel?: boolean;\n}\n\n/**\n * Generate a container model.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory (containing model/ and services/ subdirs)\n * @param options - Generator options (mutated to fill in defaults)\n * @param cwd - Current working directory for project resolution\n * @param projects - Optional pre-computed project map\n */\nexport function generateContainerModel(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ContainerModelOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): void {\n const logger = getCodegenLogger();\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n const modelName = options.modelName || getCurrentDirectoryName(cwd);\n if (!modelName) {\n throw new Error(\n \"No model name found. Please specify a model name with --name.\"\n );\n }\n\n options.modelName = modelName;\n options.name = `${modelName}-container`;\n\n const normalized = normalizeOptions(codegenFs, options, projects);\n const projectConfig = findProjectByName(\n codegenFs.root,\n normalized.modelProject,\n projects\n );\n if (!projectConfig) {\n throw new Error(`Model project '${normalized.modelProject}' not found`);\n }\n\n addKosModelConfiguration({\n codegenFs,\n modelName: normalized.nameDashCase,\n projectName: projectConfig.name,\n projectRoot: projectConfig.root,\n singleton: !!options.singleton,\n container: true,\n // The container's exported registration bean (`export const <ProperCase>`).\n factory: normalized.nameProperCase,\n });\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectConfig.name,\n projects\n );\n const modelLocation = kosConfig?.generator?.defaults?.model?.folder || \"\";\n const internal = !!kosConfig?.generator?.internal;\n options.modelDirectory = options.modelDirectory || modelLocation;\n\n const projectRoot = projectConfig.sourceRoot;\n if (projectRoot) {\n logger.info(\n `Generating container model ${normalized.nameDashCase} in ${projectRoot}`\n );\n\n const modelNameDashCase =\n (normalized as any).modelNameDashCase || normalized.nameDashCase;\n\n const modelFolder = path.join(\n projectRoot,\n options.modelDirectory || \"\",\n modelNameDashCase\n );\n\n if (options.existingModel) {\n addContainerToExistingModelFolder(codegenFs, templateDir, modelFolder, {\n ...normalized,\n internal,\n });\n } else {\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateDir, \"model\"),\n modelFolder,\n { ...normalized, internal }\n );\n }\n\n const modelIndex = path.join(projectRoot, \"index.ts\");\n const modelPath = normalized.modelDirectory\n ? `${normalized.modelDirectory}/${modelNameDashCase}`\n : modelNameDashCase;\n updateModelIndex(codegenFs, modelIndex, modelPath);\n }\n}\n\n/**\n * Add a container to a model folder that already exists.\n *\n * Renders only the container model file from the template set, then edits the\n * folder's own files: the container's options interface is appended to the\n * types declarations (created when absent), and the container's value and type\n * exports are added to the barrel. Both edits go through the codegen filesystem,\n * so a dry run buffers them like any other write.\n */\nfunction addContainerToExistingModelFolder(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n modelFolder: string,\n substitutions: Record<string, any>\n): void {\n const containerFileName = `${substitutions.nameDashCase}-model.ts`;\n const containerTemplate = path.join(\n templateDir,\n \"model\",\n \"__nameDashCase__-model.ts.template\"\n );\n const rendered = ejs.render(\n fs.readFileSync(containerTemplate, \"utf-8\"),\n substitutions,\n { filename: containerTemplate }\n );\n codegenFs.write(path.join(modelFolder, containerFileName), rendered);\n\n const typesPath = path.join(modelFolder, \"types\", \"index.d.ts\");\n if (codegenFs.read(typesPath) === null) {\n codegenFs.write(typesPath, \"\");\n }\n transformSourceFile(codegenFs, typesPath, (sourceFile) => {\n ensureExportedInterface(\n sourceFile,\n `${substitutions.nameProperCase}Options`\n );\n });\n\n const barrelPath = path.join(modelFolder, \"index.ts\");\n if (codegenFs.read(barrelPath) === null) {\n codegenFs.write(barrelPath, \"\");\n }\n transformSourceFile(codegenFs, barrelPath, (sourceFile) => {\n const moduleSpecifier = `./${containerFileName.replace(/\\.ts$/, \"\")}`;\n ensureNamedExports(sourceFile, moduleSpecifier, [\n substitutions.nameProperCase,\n ]);\n ensureNamedExports(\n sourceFile,\n moduleSpecifier,\n [`${substitutions.nameProperCase}Model`],\n true\n );\n });\n}\n","/**\n * Core generator: KOS Context.\n *\n * Generates a context file set inside an app project and updates the barrel export.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport {\n getCurrentDirectoryName,\n getKosModelConfigProp,\n getProject,\n} from \"../kos-config\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { appendBarrelExport } from \"./barrel-utils\";\n\nexport interface ContextOptions extends KosBaseGeneratorOptions {\n appProject: string;\n appDirectory: string;\n singleton?: boolean;\n internal?: boolean;\n}\n\n/**\n * Generate a KOS context.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory\n * @param options - Generator options (mutated to fill in defaults)\n * @param cwd - Current working directory for project resolution\n * @param projects - Optional pre-computed project map\n */\nexport function generateContext(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ContextOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): void {\n if (!options.appProject) {\n throw new Error(\"No app project specified\");\n }\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n const modelName = options.name || getCurrentDirectoryName(cwd);\n if (!modelName) {\n throw new Error(\n \"No model name found. Please specify a model name with --name.\"\n );\n }\n\n const singletonProp = getKosModelConfigProp({\n codegenFs,\n project: modelProjectName,\n modelName,\n prop: \"singleton\",\n projects,\n });\n options.singleton = !!singletonProp;\n options.name = modelName;\n options.modelProject = modelProjectName;\n\n const normalized = normalizeOptions(codegenFs, options, projects);\n const appProject = findProjectByName(\n codegenFs.root,\n normalized.appProject,\n projects\n );\n if (!appProject) {\n throw new Error(`App project '${normalized.appProject}' not found`);\n }\n\n const projectRoot = appProject.sourceRoot;\n if (projectRoot) {\n const dir =\n appProject.projectType === \"application\" || options.internal\n ? options.appDirectory\n : options.appDirectory ?? \"lib\";\n\n generateFilesFromTemplates(\n codegenFs,\n templateDir,\n path.join(projectRoot, dir, \"contexts\", normalized.nameDashCase),\n normalized\n );\n\n appendBarrelExport(\n codegenFs,\n path.join(projectRoot, dir, \"contexts\", \"index.ts\"),\n `./${normalized.nameDashCase}`\n );\n }\n}\n","/**\n * Core generator: KOS Hook.\n *\n * Generates a hook file set inside an app project and updates the barrel export.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport {\n getCurrentDirectoryName,\n getKosModelConfiguration,\n getKosProjectConfiguration,\n getProject,\n} from \"../kos-config\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { appendBarrelExport } from \"./barrel-utils\";\n\nexport interface HookOptions extends KosBaseGeneratorOptions {\n appProject: string;\n appDirectory: string;\n singleton?: boolean;\n internal?: boolean;\n}\n\n/**\n * Generate a KOS hook.\n *\n * @param codegenFs - Target filesystem\n * @param templateDir - Absolute path to the template directory\n * @param options - Generator options (mutated to fill in defaults)\n * @param cwd - Current working directory for project resolution\n * @param projects - Optional pre-computed project map\n */\nexport function generateHook(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: HookOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): void {\n if (!options.appProject) {\n throw new Error(\"No app project specified\");\n }\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n const modelName = options.name || getCurrentDirectoryName(cwd);\n if (!modelName) {\n throw new Error(\n \"No model name found. Please specify a model name with --name.\"\n );\n }\n\n const kosModelConfig = getKosModelConfiguration(\n codegenFs,\n modelProjectName,\n modelName,\n projects\n );\n options.singleton = kosModelConfig ? !!kosModelConfig.singleton : false;\n options.name = modelName;\n options.modelProject = modelProjectName;\n\n const normalized = normalizeOptions(codegenFs, options, projects);\n const appProject = findProjectByName(\n codegenFs.root,\n normalized.appProject,\n projects\n );\n if (!appProject) {\n throw new Error(`App project '${normalized.appProject}' not found`);\n }\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n appProject.name,\n projects\n );\n const componentLocation =\n kosConfig?.generator?.defaults?.component?.folder || \"\";\n options.appDirectory = options.appDirectory || componentLocation;\n\n const projectRoot = appProject.sourceRoot;\n if (projectRoot) {\n generateFilesFromTemplates(\n codegenFs,\n templateDir,\n path.join(\n projectRoot,\n options.appDirectory,\n \"hooks\",\n normalized.nameDashCase\n ),\n normalized\n );\n\n appendBarrelExport(\n codegenFs,\n path.join(projectRoot, options.appDirectory, \"hooks\", \"index.ts\"),\n `./${normalized.nameDashCase}`\n );\n }\n}\n","/**\n * Core generator: KOS Model.\n *\n * Generates a model within a model project, optionally with container\n * and companion sub-generators.\n * Framework-agnostic — operates through CodegenFileSystem.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { updateJson } from \"../json-utils\";\nimport { getCodegenLogger } from \"../logger\";\nimport { getKosProjectConfiguration, getProject } from \"../kos-config\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { updateModelIndex } from \"./update-model-index\";\nimport {\n generateContainerModel,\n type ContainerModelOptions,\n} from \"./generate-container-model\";\nimport {\n generateCompanionModel,\n type CompanionModelOptions,\n} from \"./generate-companion-model\";\n\nexport interface ModelOptions extends KosBaseGeneratorOptions {\n singleton?: boolean;\n isContainerSingleton?: boolean;\n unitTests?: boolean;\n container?: boolean;\n parentAware?: boolean;\n autoRegister?: boolean;\n /** One-line, human-curated purpose for the model catalog (optional). */\n purpose?: string;\n}\n\nexport interface GenerateModelParams {\n codegenFs: CodegenFileSystem;\n modelTemplateDir: string;\n containerTemplateDir?: string;\n companionTemplateDir?: string;\n options: ModelOptions;\n cwd: string;\n projects?: Map<string, ProjectConfiguration>;\n}\n\n/**\n * Generate a KOS model with optional container and companion.\n */\nexport function generateModel(params: GenerateModelParams): void {\n const {\n codegenFs,\n modelTemplateDir,\n containerTemplateDir,\n companionTemplateDir,\n options,\n cwd,\n projects,\n } = params;\n const logger = getCodegenLogger();\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --modelProject.\"\n );\n }\n\n options.modelProject = modelProjectName;\n const normalized = normalizeOptions(codegenFs, options, projects);\n const projectConfig = findProjectByName(\n codegenFs.root,\n normalized.modelProject,\n projects\n );\n if (!projectConfig) {\n throw new Error(`Model project '${normalized.modelProject}' not found`);\n }\n\n const projectRoot = projectConfig.sourceRoot;\n if (!projectRoot) return;\n\n const kosConfigPath = path.join(projectConfig.root, \".kos.json\");\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectConfig.name,\n projects\n );\n const modelLocation = kosConfig?.generator?.defaults?.model?.folder || \"\";\n const internal = !!kosConfig?.generator?.internal;\n options.modelDirectory = options.modelDirectory || modelLocation;\n\n logger.info(`Generating model ${normalized.nameDashCase} in ${projectRoot}`);\n\n generateFilesFromTemplates(\n codegenFs,\n path.join(modelTemplateDir, \"model\"),\n path.join(projectRoot, options.modelDirectory, normalized.nameDashCase),\n { ...normalized, internal }\n );\n\n const modelIndex = path.join(projectRoot, \"index.ts\");\n const modelPath = options.modelDirectory\n ? `${options.modelDirectory}/${normalized.nameDashCase}`\n : normalized.nameDashCase;\n updateModelIndex(codegenFs, modelIndex, modelPath);\n\n // The generator names the exported registration bean (`export const <ProperCase>`),\n // so it knows the catalog `factory` exactly — no inference. When a container is\n // also generated, this model is held by it: record that as `managedBy` so a\n // consumer depends on the container and navigates, rather than taking the model\n // by id. `purpose` is the only authored field (optional slot).\n const containerKey = normalized.container\n ? `${normalized.nameDashCase}-container`\n : undefined;\n updateJson(codegenFs, kosConfigPath, (json: any) => {\n const existing = json.models?.[normalized.name] ?? {};\n const managedBy = containerKey\n ? [...new Set([...(existing.managedBy ?? []), containerKey])]\n : existing.managedBy;\n json.models = {\n ...json.models,\n [normalized.name]: {\n ...existing,\n name: normalized.name,\n type: `${normalized.nameDashCase}-model`,\n singleton: !!normalized.singleton,\n factory: normalized.nameProperCase,\n ...(normalized.purpose ? { purpose: normalized.purpose } : {}),\n ...(managedBy?.length ? { managedBy } : {}),\n },\n };\n return json;\n });\n\n if (normalized.container && containerTemplateDir) {\n logger.info(`Generating container for ${normalized.name}`);\n generateContainerModel(\n codegenFs,\n containerTemplateDir,\n {\n ...options,\n name: `${normalized.name}-container`,\n modelName: normalized.name,\n singleton: normalized.isContainerSingleton,\n } as ContainerModelOptions,\n cwd,\n projects\n );\n }\n\n if (\n normalized.companion &&\n normalized.companionModel &&\n normalized.companionModelProject &&\n companionTemplateDir\n ) {\n generateCompanionModel(\n codegenFs,\n companionTemplateDir,\n {\n companionModelName: normalized.name,\n companionModelProject: normalized.modelProject,\n modelName: normalized.companionModel,\n modelProject: normalized.companionModelProject,\n companionPattern: normalized.companionPattern,\n } as CompanionModelOptions,\n projects\n );\n }\n}\n","/** Locate a model's file by its `@kosModel` declaration rather than its filename. */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { decoratorConfigText, readSourceFile } from \"./ts-toolkit\";\n\nconst DECLARATION_MARKER = \"@kosModel\";\n\n/** What a `@kosModel` file declares: the registered type id and the class carrying it. */\nexport interface ModelDeclaration {\n filePath: string;\n /** The decorator's argument, when it resolves to a string in this file. */\n typeId?: string;\n /** The decorated class's name. */\n className?: string;\n}\n\n/** Every `@kosModel` declaration under `searchRoot`, for matching and for suggestions. */\nexport function collectModelDeclarations(\n codegenFs: CodegenFileSystem,\n searchRoot: string\n): ModelDeclaration[] {\n const found: ModelDeclaration[] = [];\n for (const filePath of codegenFs.listFiles(searchRoot)) {\n if (!filePath.endsWith(\".ts\") || filePath.endsWith(\".d.ts\")) continue;\n const content = codegenFs.read(filePath);\n if (!content || !content.includes(DECLARATION_MARKER)) continue;\n\n const declared = readModelDeclaration(codegenFs, filePath);\n if (declared) found.push(declared);\n }\n return found;\n}\n\n/**\n * The single file declaring one of `identifiers`; null when none, throws on ambiguity.\n * An identifier matches either the declared type id or the decorated class name.\n */\nexport function findModelDeclarationFile(\n codegenFs: CodegenFileSystem,\n searchRoot: string,\n identifiers: string[]\n): string | null {\n const wanted = new Set(identifiers.filter(Boolean));\n if (wanted.size === 0) return null;\n\n const matches = collectModelDeclarations(codegenFs, searchRoot)\n .filter(\n (d) =>\n (d.typeId && wanted.has(d.typeId)) ||\n (d.className && wanted.has(d.className))\n )\n .map((d) => d.filePath);\n\n if (matches.length === 0) return null;\n if (matches.length > 1) {\n throw new Error(\n `Model '${[...wanted].join(\n \"' / '\"\n )}' is declared in more than one file:\\n` +\n matches\n .sort()\n .map((c) => ` - ${c}`)\n .join(\"\\n\") +\n `\\nPass modelPath to pick one.`\n );\n }\n return matches[0];\n}\n\n/** The type id and class name a file declares; undefined when it has no `@kosModel` class. */\nfunction readModelDeclaration(\n codegenFs: CodegenFileSystem,\n filePath: string\n): ModelDeclaration | undefined {\n try {\n return readSourceFile(codegenFs, filePath, (sf) => {\n const cls = sf.getClasses().find((c) => c.getDecorator(\"kosModel\"));\n if (!cls) return undefined;\n\n const config = decoratorConfigText(sf, cls, \"kosModel\");\n const inner = config?.startsWith(\"{\")\n ? modelTypeIdProperty(config)\n : config;\n // An unfollowable type id still leaves a usable class name.\n const typeId = inner\n ? resolveToStringLiteral(inner.trim(), sf.getFullText())\n : undefined;\n\n return { filePath, typeId, className: cls.getName() };\n });\n } catch {\n return undefined;\n }\n}\n\n/** The `modelTypeId:` value out of a `@kosModel({ … })` argument's text. */\nfunction modelTypeIdProperty(objectText: string): string | undefined {\n const m = objectText.match(/\\bmodelTypeId\\s*:\\s*([^,}]+)/);\n return m ? m[1] : undefined;\n}\n\n/** A string literal, or a const declared in the same file. */\nfunction resolveToStringLiteral(\n expression: string,\n fileText: string\n): string | undefined {\n const literal = expression.match(/^[\"'`](.*)[\"'`]$/);\n if (literal) return literal[1];\n\n if (!/^[A-Za-z_$][\\w$]*$/.test(expression)) return undefined;\n const declared = fileText.match(\n new RegExp(\n `\\\\b(?:const|let|var)\\\\s+${expression}\\\\s*(?::[^=]+)?=\\\\s*[\"'\\`]([^\"'\\`]+)[\"'\\`]`\n )\n );\n return declared ? declared[1] : undefined;\n}\n","/**\n * Shared model-file resolution for capability mutators, in four steps: the\n * conventional `<folder>/<name>/<name>-model.ts`, a search of the model folder\n * for `<name>-model.ts`, the file whose `@kosModel` declares the id, and the\n * file whose `@kosModel` class carries the name. Throws when none match, naming\n * the closest models the project declares — a path built from a name that does\n * not resolve only restates it.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { getKosProjectConfiguration } from \"../../kos-config\";\nimport { normalizeAllValues } from \"../../normalize-values\";\nimport {\n collectModelDeclarations,\n findModelDeclarationFile,\n type ModelDeclaration,\n} from \"./find-model-declaration\";\n\nexport interface ModelFileQuery {\n modelName: string;\n modelProject: string;\n /** Explicit model file path (relative to root), overriding resolution. */\n modelPath?: string;\n}\n\nexport function resolveModelFilePath(\n codegenFs: CodegenFileSystem,\n query: ModelFileQuery,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string; internal: boolean; sourceRoot?: string } {\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n query.modelProject,\n projects\n );\n const internal = !!kosConfig?.generator?.internal;\n\n const project = findProjectByName(\n codegenFs.root,\n query.modelProject,\n projects\n );\n const sourceRoot = project\n ? project.sourceRoot || path.join(project.root, \"src\")\n : undefined;\n\n if (query.modelPath) {\n return { modelFilePath: query.modelPath, internal, sourceRoot };\n }\n\n if (!project) {\n throw new Error(\n `Project not found: ${query.modelProject}. Ensure a project.json exists.`\n );\n }\n const { modelNameDashCase } = normalizeAllValues({\n modelName: query.modelName,\n });\n const modelLocation = kosConfig?.generator?.defaults?.model?.folder || \"\";\n const modelFilePath = path.join(\n sourceRoot as string,\n modelLocation,\n modelNameDashCase,\n `${modelNameDashCase}-model.ts`\n );\n if (codegenFs.exists(modelFilePath)) {\n return { modelFilePath, internal, sourceRoot };\n }\n\n const searchRoot = path.join(sourceRoot as string, modelLocation);\n const discovered = findModelFileByName(\n codegenFs,\n searchRoot,\n modelNameDashCase\n );\n if (discovered) {\n return { modelFilePath: discovered, internal, sourceRoot };\n }\n\n // `.kos.json` records the registered type id separately from its key; callers\n // pass either, or the class name off the source.\n const declaredType = kosConfig?.models?.[query.modelName]?.type;\n const byDeclaration = findModelDeclarationFile(codegenFs, searchRoot, [\n query.modelName,\n ...(declaredType ? [declaredType] : []),\n ]);\n if (byDeclaration) {\n return { modelFilePath: byDeclaration, internal, sourceRoot };\n }\n\n throw new ModelFileNotFoundError(\n query.modelName,\n query.modelProject,\n modelFilePath,\n collectModelDeclarations(codegenFs, searchRoot)\n );\n}\n\n/** Not-found that names the models the project DOES declare. */\nexport class ModelFileNotFoundError extends Error {\n constructor(\n readonly modelName: string,\n readonly modelProject: string,\n readonly conventionalPath: string,\n readonly candidates: ModelDeclaration[]\n ) {\n super(\n buildNotFoundMessage(\n modelName,\n modelProject,\n conventionalPath,\n candidates\n )\n );\n this.name = \"ModelFileNotFoundError\";\n }\n}\n\nfunction buildNotFoundMessage(\n modelName: string,\n modelProject: string,\n conventionalPath: string,\n candidates: ModelDeclaration[]\n): string {\n const lines = [\n `Model '${modelName}' not found in project '${modelProject}'.`,\n `Looked for ${conventionalPath}, any '*-model.ts' under the model folder, ` +\n `and any '@kosModel' class named or typed '${modelName}'.`,\n ];\n\n if (candidates.length === 0) {\n lines.push(\n `This project declares no '@kosModel' classes under its model folder.`\n );\n return lines.join(\"\\n\");\n }\n\n // A project declares hundreds of models; listing them all buries the answer, so\n // rank by closeness to what was asked and show only the near misses.\n const ranked = [...candidates].sort(\n (a, b) => closeness(modelName, b) - closeness(modelName, a)\n );\n const shown = ranked.slice(0, NOT_FOUND_SUGGESTIONS);\n\n lines.push(\n ``,\n `Closest of the ${candidates.length} models this project declares:`\n );\n for (const c of shown) {\n const names = [c.typeId, c.className].filter(Boolean).join(\" | \");\n lines.push(` ${names || \"(name unresolved)\"}\\n ${c.filePath}`);\n }\n if (ranked.length > shown.length) {\n lines.push(` …and ${ranked.length - shown.length} more.`);\n }\n lines.push(``, `Or pass modelPath to name the file directly.`);\n return lines.join(\"\\n\");\n}\n\nconst NOT_FOUND_SUGGESTIONS = 8;\n\n/** Cheap similarity: shared normalized substring, then shared prefix length. */\nfunction closeness(wanted: string, candidate: ModelDeclaration): number {\n const norm = (v: string) => v.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n const target = norm(wanted);\n let best = 0;\n for (const name of [candidate.typeId, candidate.className]) {\n if (!name) continue;\n const n = norm(name);\n if (n === target) return 1000;\n if (n.includes(target) || target.includes(n)) {\n best = Math.max(best, 500 + Math.min(n.length, target.length));\n continue;\n }\n let i = 0;\n while (i < n.length && i < target.length && n[i] === target[i]) i++;\n best = Math.max(best, i);\n }\n return best;\n}\n\n/**\n * Search a directory tree for `<name>-model.ts`. Returns the single match, null\n * when there is none (resolution then falls through to declaration matching),\n * and throws on ambiguity — a wrong guess would silently mutate the wrong model.\n */\nfunction findModelFileByName(\n codegenFs: CodegenFileSystem,\n searchRoot: string,\n modelNameDashCase: string\n): string | null {\n const fileName = `${modelNameDashCase}-model.ts`;\n const candidates = codegenFs\n .listFiles(searchRoot)\n .filter((f) => path.basename(f) === fileName)\n .sort();\n if (candidates.length === 0) return null;\n if (candidates.length > 1) {\n throw new Error(\n `Model name '${modelNameDashCase}' is ambiguous — multiple files match ${fileName}:\\n` +\n candidates.map((c) => ` - ${c}`).join(\"\\n\") +\n `\\nPass modelPath to pick one.`\n );\n }\n return candidates[0];\n}\n","/**\n * Resolve a child MODEL NAME to the TS type a mutator writes and the module that\n * type is imported from.\n *\n * A child in the same project is imported relatively — a project that imports\n * itself by package name breaks Nx's module boundaries — and one in another\n * project by that project's package name. Callers pass a model name; working out\n * which of those applies is not their job.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { readJson } from \"../../json-utils\";\nimport { properCase } from \"../../name-utils\";\nimport { resolveModelFilePath } from \"./resolve-model-file\";\n\nexport interface ChildModelQuery {\n /** Model the child is being added to; its file anchors a relative import. */\n modelFilePath: string;\n /** Project owning the model being edited. */\n modelProject: string;\n childModel: string;\n /** Project owning `childModel`. Defaults to `modelProject`. */\n childModelProject?: string;\n}\n\nexport function resolveChildModelType(\n codegenFs: CodegenFileSystem,\n query: ChildModelQuery,\n projects?: Map<string, ProjectConfiguration>\n): { childType: string; childTypeModule?: string } {\n const childProject = query.childModelProject || query.modelProject;\n const childType = `${properCase(query.childModel)}Model`;\n\n if (childProject !== query.modelProject) {\n const project = findProjectByName(codegenFs.root, childProject, projects);\n const pkgJson = project\n ? readJson<{ name?: string }>(\n codegenFs,\n path.join(project.root, \"package.json\")\n )\n : undefined;\n return { childType, childTypeModule: pkgJson?.name };\n }\n\n const { modelFilePath: childFilePath } = resolveModelFilePath(\n codegenFs,\n { modelName: query.childModel, modelProject: childProject },\n projects\n );\n const relative = path\n .relative(path.dirname(query.modelFilePath), childFilePath)\n .replace(/\\.ts$/, \"\");\n return {\n childType,\n childTypeModule: relative.startsWith(\".\") ? relative : `./${relative}`,\n };\n}\n","/**\n * Core generator: KOS ViewModel — a class holding UI-only state beside the KOS\n * data models it reads, which arrive through its constructor. Not registered and\n * not in the model graph, so no `.kos.json` entry, chain edit or hook is written.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../generate-files\";\nimport { getKosProjectConfiguration, getProject } from \"../kos-config\";\nimport { getCodegenLogger } from \"../logger\";\nimport { camelCase } from \"../name-utils\";\nimport type { ProjectConfiguration } from \"../project-discovery\";\nimport { findProjectByName } from \"../project-discovery\";\nimport { resolveChildModelType } from \"./augment/resolve-child-model\";\nimport { resolveModelFilePath } from \"./augment/resolve-model-file\";\nimport {\n normalizeOptions,\n type KosBaseGeneratorOptions,\n} from \"./normalize-options\";\nimport { updateModelIndex } from \"./update-model-index\";\n\n/** A KOS data model the ViewModel is built over. */\nexport interface ViewModelSource {\n /** Model name, e.g. `beverage-container`. */\n model: string;\n /** Project owning the model. Defaults to the ViewModel's own project. */\n project?: string;\n}\n\nexport interface ViewModelOptions extends KosBaseGeneratorOptions {\n /** Models passed to the constructor, in declaration order. Empty is valid. */\n models?: ViewModelSource[];\n /** `@kosViewModel` typeId. Defaults to the dash-case name. */\n typeId?: string;\n /** Register the instance with KOS DevTools. */\n devToolsEnabled?: boolean;\n}\n\nexport interface ViewModelResult {\n /** Path of the ViewModel file, whether or not this call wrote it. */\n viewModelFilePath: string;\n /** False when the file already existed, in which case nothing was written. */\n created: boolean;\n}\n\ninterface ResolvedModel {\n /** Constructor parameter name. */\n name: string;\n /** Public model type, e.g. `BeverageContainerModel`. */\n type: string;\n /** Module exporting the type, absent when the owning project has no package name. */\n module?: string;\n}\n\n/** Generate a ViewModel. */\nexport function generateViewModel(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ViewModelOptions,\n cwd: string,\n projects?: Map<string, ProjectConfiguration>\n): ViewModelResult {\n const logger = getCodegenLogger();\n\n if (!options.name) {\n throw new Error(\n \"No ViewModel name found. Please specify a name with --name.\"\n );\n }\n\n const currentProject = getProject(codegenFs, cwd);\n const modelProjectName = options.modelProject || currentProject?.name;\n if (!modelProjectName) {\n throw new Error(\n \"No model project found. Please specify a model project with --project.\"\n );\n }\n\n const normalized = normalizeOptions(\n codegenFs,\n { ...options, modelProject: modelProjectName },\n projects\n );\n const projectConfig = findProjectByName(\n codegenFs.root,\n modelProjectName,\n projects\n );\n if (!projectConfig) {\n throw new Error(`Model project '${modelProjectName}' not found`);\n }\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n projectConfig.name,\n projects\n );\n const modelDirectory =\n options.modelDirectory ||\n kosConfig?.generator?.defaults?.model?.folder ||\n \"\";\n const internal = !!kosConfig?.generator?.internal;\n\n const projectRoot =\n projectConfig.sourceRoot || path.join(projectConfig.root, \"src\");\n const viewModelFolder = path.join(\n projectRoot,\n modelDirectory,\n normalized.nameDashCase\n );\n const viewModelFilePath = path.join(\n viewModelFolder,\n `${normalized.nameDashCase}-view-model.ts`\n );\n\n // The ViewModel is hand-written after generation, so regeneration must not overwrite.\n if (codegenFs.exists(viewModelFilePath)) {\n logger.info(`ViewModel already exists: ${viewModelFilePath}`);\n return { viewModelFilePath, created: false };\n }\n\n const resolved = (options.models || []).map((source) =>\n resolveSourceModel(\n codegenFs,\n source,\n viewModelFilePath,\n modelProjectName,\n projects\n )\n );\n\n logger.info(\n `Generating ViewModel ${normalized.nameDashCase} in ${projectRoot}`\n );\n\n const constructorParams = resolved.map(({ name, type }) => {\n return { name, type };\n });\n generateFilesFromTemplates(codegenFs, templateDir, viewModelFolder, {\n ...normalized,\n internal,\n typeId: options.typeId || normalized.nameDashCase,\n devToolsEnabled: !!options.devToolsEnabled,\n constructorParams,\n constructorArgs: constructorParams.map((param) => param.name).join(\", \"),\n modelImports: groupImports(resolved),\n });\n\n updateModelIndex(\n codegenFs,\n path.join(projectRoot, \"index.ts\"),\n modelDirectory\n ? `${modelDirectory}/${normalized.nameDashCase}`\n : normalized.nameDashCase\n );\n\n return { viewModelFilePath, created: true };\n}\n\n/** One model name to its constructor parameter and the module its type comes from. */\nfunction resolveSourceModel(\n codegenFs: CodegenFileSystem,\n source: ViewModelSource,\n viewModelFilePath: string,\n modelProject: string,\n projects?: Map<string, ProjectConfiguration>\n): ResolvedModel {\n const sourceProject = source.project || modelProject;\n\n if (sourceProject === modelProject) {\n const { modelFilePath } = resolveModelFilePath(\n codegenFs,\n { modelName: source.model, modelProject: sourceProject },\n projects\n );\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(\n `Model '${source.model}' not found in project '${sourceProject}' (looked for ${modelFilePath})`\n );\n }\n } else if (!findProjectByName(codegenFs.root, sourceProject, projects)) {\n throw new Error(`Model project '${sourceProject}' not found`);\n }\n\n const { childType, childTypeModule } = resolveChildModelType(\n codegenFs,\n {\n modelFilePath: viewModelFilePath,\n modelProject,\n childModel: source.model,\n childModelProject: sourceProject,\n },\n projects\n );\n\n return {\n name: camelCase(source.model),\n type: childType,\n module: childTypeModule,\n };\n}\n\n/** One type-only import per module, in declaration order. */\nfunction groupImports(\n resolved: ResolvedModel[]\n): { module: string; types: string[] }[] {\n const byModule = new Map<string, string[]>();\n for (const { type, module } of resolved) {\n if (!module) continue;\n const types = byModule.get(module);\n if (!types) {\n byModule.set(module, [type]);\n } else if (!types.includes(type)) {\n types.push(type);\n }\n }\n return [...byModule].map(([module, types]) => {\n return { module, types };\n });\n}\n","/**\n * The model's own `services/` module — where a model's data-transfer concerns\n * live: the endpoints it calls, the types derived from them, and standalone\n * service functions for callers outside a model context.\n *\n * Created on demand, at the point a capability actually has something to put in\n * it. Scaffolding it up front only produced a placeholder that had to be\n * replaced before the project could compile.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { transformSourceFile, ensureBarrelExport } from \"./ts-toolkit\";\n\n/** `board-model.ts` → `board`; falls back to the requested model name. */\nexport function modelBaseName(\n modelFilePath: string,\n modelName: string\n): string {\n const base = path.basename(modelFilePath);\n const match = base.match(/^(.*)-model\\.ts$/);\n return match ? match[1] : modelName;\n}\n\n/** Where a model's services module lives, whether or not it exists yet. */\nexport function servicesFilePathFor(\n modelFilePath: string,\n modelBase: string\n): string {\n return path.join(\n path.dirname(modelFilePath),\n \"services\",\n `${modelBase}-services.ts`\n );\n}\n\nfunction header(modelBase: string): string {\n return `/**\n * Service layer for the ${modelBase} model: the endpoints it calls and the\n * types derived from them. Standalone service functions for callers outside a\n * model context belong here too.\n */\n`;\n}\n\n/**\n * Ensure the model's services module and its barrel exist, and return the\n * module's path. Existing files are left alone — callers add to them.\n */\nexport function ensureServicesModule(\n codegenFs: CodegenFileSystem,\n modelFilePath: string,\n modelBase: string\n): string {\n const servicesFilePath = servicesFilePathFor(modelFilePath, modelBase);\n if (!codegenFs.exists(servicesFilePath)) {\n codegenFs.write(servicesFilePath, header(modelBase));\n }\n\n const barrelPath = path.join(path.dirname(servicesFilePath), \"index.ts\");\n if (!codegenFs.exists(barrelPath)) {\n codegenFs.write(barrelPath, \"\");\n }\n transformSourceFile(codegenFs, barrelPath, (sf) => {\n ensureBarrelExport(sf, `./${modelBase}-services`);\n });\n\n return servicesFilePath;\n}\n","/**\n * Option normalization for the add-future-to-model generator.\n *\n * Resolves project configuration, computes name case variants,\n * and determines file paths for model, services, and registration files.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\nimport { getKosProjectConfiguration } from \"../../kos-config\";\nimport { normalizeAllValues } from \"../../normalize-values\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { servicesFilePathFor } from \"../augment/model-services\";\nimport type {\n AddFutureToModelOptions,\n NormalizedAddFutureToModelOptions,\n} from \"./types\";\n\nexport function normalizeAddFutureOptions(\n codegenFs: CodegenFileSystem,\n options: AddFutureToModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): NormalizedAddFutureToModelOptions {\n const projectConfiguration = findProjectByName(\n codegenFs.root,\n options.modelProject,\n projects\n );\n\n if (!projectConfiguration) {\n throw new Error(\n `Project not found: ${options.modelProject}. Ensure a project.json exists for this project.`\n );\n }\n\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n options.modelProject,\n projects\n );\n const internal = !!kosConfig?.generator?.internal;\n\n // Normalize name variations\n const normalizedValues = normalizeAllValues({\n modelName: options.modelName,\n });\n\n const nameDashCase = normalizedValues.modelNameDashCase;\n const nameProperCase = normalizedValues.modelNameProperCase;\n const nameCamelCase = normalizedValues.modelNameCamelCase;\n const namePascalCase = normalizedValues.modelNamePascalCase;\n const nameConstantCase = normalizedValues.modelNameConstantCase;\n const nameLowerCase = normalizedValues.modelNameLowerCase;\n\n const projectRoot = projectConfiguration.root;\n const sourceRoot =\n projectConfiguration.sourceRoot || path.join(projectRoot, \"src\");\n\n // Determine model file path — shared resolution covers co-located containers\n // and shared-dir models, not just the conventional `<folder>/<name>/` layout.\n const { modelFilePath } = resolveModelFilePath(\n codegenFs,\n { modelName: options.modelName, modelProject: options.modelProject },\n projects\n );\n const modelDirectory = path.dirname(modelFilePath);\n\n // The services module is created on demand by the capability that needs it,\n // so this path is where it belongs, not proof that it already exists.\n const servicesFilePath = servicesFilePathFor(modelFilePath, nameDashCase);\n\n // Determine registration file path\n const registrationFilePath = path.join(\n modelDirectory,\n `${nameDashCase}-registration.ts`\n );\n\n return {\n ...options,\n nameDashCase,\n nameProperCase,\n nameCamelCase,\n namePascalCase,\n nameConstantCase,\n nameLowerCase,\n projectRoot,\n sourceRoot,\n modelFilePath,\n servicesFilePath,\n registrationFilePath: codegenFs.exists(registrationFilePath)\n ? registrationFilePath\n : undefined,\n internal,\n };\n}\n","/**\n * Transformer that updates existing models to use the @kosFutureAware\n * decorator pattern with TypeScript interface merging for type safety.\n *\n * AST-based (ts-morph via the augment toolkit): every edit anchors on a real\n * node — class, decorator list, import declaration, type alias — so a model\n * with existing decorated methods round-trips intact. The earlier regex\n * string-splice version doubled the class declaration and unbalanced braces\n * on any non-trivial model (G-111).\n */\nimport type { SourceFile, ClassDeclaration } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { NormalizedAddFutureToModelOptions } from \"./types\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addClassDecorator,\n ensureDeclarationMerge,\n ensureFileEslintDisable,\n} from \"../augment/ts-toolkit\";\n\n// Symbols from the legacy (pre-decorator) future pattern, scrubbed on sight.\nconst LEGACY_IMPORTS = new Set([\n \"setupCompleteFutureSupport\",\n \"setupMinimalFutureSupport\",\n \"FutureAwareContainer\",\n \"FutureHandlerContainer\",\n \"FutureStateAccessor\",\n \"FutureUpdateHandler\",\n]);\nconst LEGACY_IMPLEMENTS = new Set([\n \"FutureUpdateHandler\",\n \"FutureHandlerContainer\",\n \"FutureStateAccessor\",\n]);\n\nexport class ModelFileTransformer {\n constructor(\n private codegenFs: CodegenFileSystem,\n private options: NormalizedAddFutureToModelOptions\n ) {}\n\n private get progressType(): string {\n const { nameProperCase, updateServices } = this.options;\n return updateServices\n ? `${nameProperCase}OperationProgress`\n : \"Record<string, unknown>\";\n }\n\n transform(): void {\n const { modelFilePath } = this.options;\n\n if (!this.codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n transformSourceFile(this.codegenFs, modelFilePath, (sf) => {\n this.removeLegacyImports(sf);\n this.addImports(sf);\n\n const cls = getModelClass(sf, `${this.options.nameProperCase}ModelImpl`);\n this.removeLegacyClassMembers(cls);\n this.addDecorator(cls);\n this.addFutureMethod(cls);\n if (this.options.futureType === \"complete\") {\n this.addOnFutureUpdateMethod(cls);\n }\n\n this.updatePublicType(sf);\n\n // Raw-text insertions LAST — they invalidate node references.\n ensureDeclarationMerge(\n sf,\n `${this.options.nameProperCase}ModelImpl`,\n `${\n this.options.futureType === \"complete\"\n ? \"KosFutureAwareFull\"\n : \"KosFutureAwareMinimal\"\n }<${this.progressType}>`\n );\n ensureFileEslintDisable(\n sf,\n \"@typescript-eslint/no-unsafe-declaration-merging\"\n );\n });\n }\n\n private removeLegacyImports(sf: SourceFile): void {\n for (const decl of sf.getImportDeclarations()) {\n for (const named of decl.getNamedImports()) {\n if (LEGACY_IMPORTS.has(named.getName())) named.remove();\n }\n if (\n decl.getNamedImports().length === 0 &&\n !decl.getDefaultImport() &&\n !decl.getNamespaceImport()\n ) {\n decl.remove();\n }\n }\n }\n\n private addImports(sf: SourceFile): void {\n const { internal, futureType, updateServices, nameProperCase } =\n this.options;\n const isComplete = futureType === \"complete\";\n const sdkSpec = resolveSdkModuleSpecifier(sf);\n\n ensureNamedImport(sf, sdkSpec, [\n { name: \"kosFuture\" },\n { name: \"kosFutureAware\" },\n {\n name: isComplete ? \"KosFutureAwareFull\" : \"KosFutureAwareMinimal\",\n isTypeOnly: true,\n },\n ]);\n\n const typeSpec = internal\n ? \"../../../models/types/future-interfaces\"\n : sdkSpec;\n ensureNamedImport(sf, typeSpec, [\n { name: \"ExternalFutureInterface\", isTypeOnly: true },\n ...(isComplete ? [{ name: \"IFutureModel\", isTypeOnly: true }] : []),\n ]);\n\n if (updateServices) {\n ensureNamedImport(sf, \"./services\", [\n { name: `${nameProperCase}OperationProgress`, isTypeOnly: true },\n ]);\n }\n }\n\n private removeLegacyClassMembers(cls: ClassDeclaration): void {\n for (const ctor of cls.getConstructors()) {\n for (const stmt of ctor.getStatements()) {\n if (\n /setup(Complete|Minimal)FutureSupport\\s*\\(\\s*this\\s*\\)/.test(\n stmt.getText()\n )\n ) {\n stmt.remove();\n }\n }\n }\n\n const futureHandler = cls.getProperty(\"futureHandler\");\n if (\n futureHandler?.getTypeNode()?.getText().includes(\"FutureAwareContainer\")\n ) {\n futureHandler.remove();\n }\n const future = cls.getProperty(\"future\");\n if (future?.getTypeNode()?.getText().includes(\"IFutureModel\")) {\n future.remove();\n }\n\n const impls = cls.getImplements();\n for (let i = impls.length - 1; i >= 0; i--) {\n const base = impls[i].getText().split(\"<\")[0].trim();\n if (LEGACY_IMPLEMENTS.has(base)) cls.removeImplements(i);\n }\n }\n\n private addDecorator(cls: ClassDeclaration): void {\n const argsText =\n this.options.futureType === \"complete\" ? \"\" : `{ mode: \"minimal\" }`;\n addClassDecorator(cls, \"kosFutureAware\", { argsText });\n }\n\n private updatePublicType(sf: SourceFile): void {\n const { nameProperCase } = this.options;\n const alias = sf.getTypeAlias(`${nameProperCase}Model`);\n if (!alias) return;\n const text = alias.getTypeNode()?.getText() ?? \"\";\n if (\n !text.includes(`PublicModelInterface<${nameProperCase}ModelImpl>`) ||\n text.includes(\"ExternalFutureInterface\")\n ) {\n return;\n }\n alias.setType(\n `PublicModelInterface<${nameProperCase}ModelImpl> & ExternalFutureInterface<${this.progressType}>`\n );\n }\n\n private addFutureMethod(cls: ClassDeclaration): void {\n const { nameProperCase } = this.options;\n // A model that already has any @kosFuture method needs no placeholder.\n const hasFutureMethod = cls\n .getMethods()\n .some((m) => m.getDecorator(\"kosFuture\"));\n if (hasFutureMethod || cls.getMethod(\"performLongRunningOperation\")) return;\n\n cls.addMethod({\n name: \"performLongRunningOperation\",\n isAsync: true,\n returnType: \"Promise<void>\",\n decorators: [{ name: \"kosFuture\", arguments: [] }],\n docs: [\n {\n description:\n \"Placeholder method for Future operations\\nReplace this with your actual long-running operation\",\n },\n ],\n statements: [\n \"// TODO: Implement your long-running operation here\",\n \"// This method should use a service that returns a Future for progress tracking\",\n \"\",\n \"this.logger.debug(`Starting long-running operation for ${this.id}`);\",\n \"\",\n \"// Example implementation pattern using services:\",\n `// import { perform${nameProperCase}Operation } from './services';`,\n \"//\",\n `// const future = await perform${nameProperCase}Operation();`,\n \"// return this.futureHandler.setFuture(future);\",\n \"\",\n \"// Placeholder that doesn't actually do anything\",\n \"await new Promise((resolve) => setTimeout(resolve, 1000));\",\n \"\",\n \"this.logger.debug(`Completed long-running operation for ${this.id}`);\",\n ],\n });\n }\n\n private addOnFutureUpdateMethod(cls: ClassDeclaration): void {\n if (cls.getMethod(\"onFutureUpdate\")) return;\n\n cls.addMethod({\n name: \"onFutureUpdate\",\n hasQuestionToken: true,\n returnType: \"void\",\n parameters: [\n { name: \"update\", type: `IFutureModel<${this.progressType}>` },\n ],\n docs: [\n {\n description:\n \"Optional: Custom Future update handling\\nCalled whenever the Future state changes (progress, status, completion, etc.)\",\n },\n ],\n statements: [\n \"// Add custom Future update logic here\",\n \"// Examples:\",\n \"// - Log progress milestones\",\n \"// - Update derived state based on progress\",\n \"// - Handle specific error conditions\",\n \"// - Trigger notifications at certain thresholds\",\n \"\",\n \"this.logger.debug(`Future update for ${this.id}:`, {\",\n \" progress: update.progress,\",\n \" status: update.status,\",\n \" endState: update.endState,\",\n \" clientData: update.clientData,\",\n \"});\",\n ],\n });\n }\n}\n","/**\n * Adds Future-operation scaffolding to the model's services module: a\n * placeholder long-running operation and the progress/result types that go with\n * it, created on demand when the model has no services module yet.\n *\n * Every piece it needs — the SDK import, the logger, the function, the types —\n * is ensured independently, because the module it edits may have been created\n * by any capability (or by hand) and carries no guaranteed shape.\n */\nimport { VariableDeclarationKind, type SourceFile } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { NormalizedAddFutureToModelOptions } from \"./types\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n ensureModuleConst,\n ensureExportedTypeAlias,\n} from \"../augment/ts-toolkit\";\nimport { ensureServicesModule } from \"../augment/model-services\";\n\nconst SDK_MODULE = \"@kosdev-code/kos-ui-sdk\";\n\nexport class ServiceFileTransformer {\n constructor(\n private codegenFs: CodegenFileSystem,\n private options: NormalizedAddFutureToModelOptions\n ) {}\n\n transform(): void {\n const { modelFilePath, nameDashCase } = this.options;\n if (!modelFilePath) return;\n\n const servicesFilePath = ensureServicesModule(\n this.codegenFs,\n modelFilePath,\n nameDashCase\n );\n\n transformSourceFile(this.codegenFs, servicesFilePath, (sf) => {\n ensureNamedImport(sf, SDK_MODULE, [\n { name: \"KosLog\" },\n { name: \"FutureResponse\", isTypeOnly: true },\n ]);\n // The emitted operation logs through `log`; a services module written by\n // another capability has no logger of its own.\n ensureModuleConst(sf, {\n name: \"log\",\n initializer: `KosLog.createLogger({ name: \"${nameDashCase}-service\", group: \"Services\" })`,\n });\n this.addFutureOperation(sf);\n this.addProgressTypes(sf);\n });\n }\n\n private addFutureOperation(sf: SourceFile): void {\n const { nameProperCase, nameLowerCase } = this.options;\n const name = `perform${nameProperCase}Operation`;\n if (sf.getVariableDeclaration(name)) return;\n\n sf.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name,\n initializer: `async (): Promise<FutureResponse> => {\n log.debug(\"starting long-running ${nameLowerCase} operation\");\n throw new Error(\"${name} not yet implemented\");\n}`,\n },\n ],\n docs: [\n {\n description: `@category Service - Future Operation\\nA long-running operation returning a Future for progress tracking. Replace the body with the real service call.`,\n },\n ],\n });\n }\n\n private addProgressTypes(sf: SourceFile): void {\n const { nameProperCase } = this.options;\n ensureExportedTypeAlias(sf, {\n name: `${nameProperCase}OperationProgress`,\n type: `{\n stage: string;\n percentComplete: number;\n currentItem?: string;\n totalItems?: number;\n}`,\n });\n ensureExportedTypeAlias(sf, {\n name: `${nameProperCase}OperationResult`,\n type: `{\n success: boolean;\n message?: string;\n data?: unknown;\n}`,\n });\n }\n}\n","/**\n * Transformer that updates registration files to support Future-enabled models.\n *\n * Adds type casts and documentation for Future capabilities.\n *\n * Ported from kos-nx-plugin to use CodegenFileSystem instead of Nx Tree.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { getCodegenLogger } from \"../../logger\";\nimport type { NormalizedAddFutureToModelOptions } from \"./types\";\n\nexport class RegistrationFileTransformer {\n constructor(\n private codegenFs: CodegenFileSystem,\n private options: NormalizedAddFutureToModelOptions\n ) {}\n\n transform(): void {\n const logger = getCodegenLogger();\n const { registrationFilePath } = this.options;\n\n if (!registrationFilePath || !this.codegenFs.exists(registrationFilePath)) {\n logger.warn(\"Registration file not found, skipping registration updates\");\n return;\n }\n\n const original = this.codegenFs.read(registrationFilePath)!;\n\n let content = original;\n content = this.addTypeCast(content);\n content = this.updateDocumentation(content);\n\n // Only legacy registration patterns produce edits — writing unchanged\n // content makes dry-run predict a modification that never happens.\n if (content === original) {\n logger.info(\n \"Registration file has no legacy future patterns — leaving it untouched\"\n );\n return;\n }\n this.codegenFs.write(registrationFilePath, content);\n }\n\n private addTypeCast(content: string): string {\n const { nameProperCase } = this.options;\n\n // Find the registration factory instantiation and add type cast\n const factoryRegex = new RegExp(`class: ${nameProperCase}ModelImpl,`);\n\n const replacement = `class: ${nameProperCase}ModelImpl as any, // Type cast needed for Future intersection`;\n\n return content.replace(factoryRegex, replacement);\n }\n\n private updateDocumentation(content: string): string {\n const { nameProperCase, futureType } = this.options;\n\n // Add Future support documentation after the main description\n const descriptionRegex = new RegExp(\n `(\\\\* The registration bean includes convenience methods for creating and working with ${nameProperCase}Model instances\\\\.)`\n );\n\n const futureDocumentation = `$1\n *\n * ## Future Support\n * This model includes ${futureType} Future support for tracking long-running operations with:\n * - Progress tracking (0-1) with reactive updates\n * - Status messages during operation\n * - Cancellation support with bi-directional AbortController integration\n * - Reactive integration for UI updates${\n futureType === \"complete\"\n ? \"\\n * - Internal access to Future state for custom logic and computed properties\"\n : \"\"\n }`;\n\n if (content.match(descriptionRegex)) {\n content = content.replace(descriptionRegex, futureDocumentation);\n }\n\n // Add Future usage examples to factory documentation\n const factoryExampleRegex = /(\\*\\s+\\}\\);?\\s*\\*\\s+```)/;\n\n const futureExample = `$1\n *\n * // Example: Accessing Future state (when a Future is active)\n * const isRunning = model.futureIsRunning;\n * const progress = model.futureProgress; // 0-1\n * const status = model.futureStatus; // Current status message\n * \\`\\`\\``;\n\n if (content.match(factoryExampleRegex)) {\n content = content.replace(factoryExampleRegex, futureExample);\n }\n\n // Add Future capabilities to predicate examples\n const predicateExampleRegex =\n /(\\*\\s+model\\.updateAvailability\\(false\\);?\\s*\\*\\s+\\})/;\n\n const predicateFutureExample = `$1\n *\n * // Future capabilities are also available\n * const isRunning = model.futureIsRunning;\n * const progress = model.futureProgress;\n * }`;\n\n if (content.match(predicateExampleRegex)) {\n content = content.replace(predicateExampleRegex, predicateFutureExample);\n }\n\n return content;\n }\n}\n","/**\n * Framework-agnostic core logic for the add-future-to-model generator.\n *\n * Adds Future (long-running operation) support to an existing KOS model\n * by transforming model, service, and registration files. Works through\n * the CodegenFileSystem abstraction so it can run in any environment\n * (CLI, VS Code, Nx).\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { normalizeAddFutureOptions } from \"./normalize-options\";\nimport { ModelFileTransformer } from \"./model-transformer\";\nimport { ServiceFileTransformer } from \"./service-transformer\";\nimport { RegistrationFileTransformer } from \"./registration-transformer\";\nimport type { AddFutureToModelOptions } from \"./types\";\n\nexport function addFutureToModel(\n codegenFs: CodegenFileSystem,\n options: AddFutureToModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n const logger = getCodegenLogger();\n const normalized = normalizeAddFutureOptions(codegenFs, options, projects);\n\n logger.info(\n `Adding ${normalized.futureType} Future support to model: ${normalized.modelName}`\n );\n\n // Validate that model file exists\n if (!codegenFs.exists(normalized.modelFilePath)) {\n throw new Error(`Model file not found: ${normalized.modelFilePath}`);\n }\n\n if (options.dryRun) {\n logger.info(\"DRY RUN - No files will be modified\");\n logger.info(`Would modify model file: ${normalized.modelFilePath}`);\n if (normalized.servicesFilePath) {\n logger.info(\n `Would modify/create services file: ${normalized.servicesFilePath}`\n );\n }\n if (normalized.registrationFilePath) {\n logger.info(\n `Would update registration file (only if legacy patterns are present): ${normalized.registrationFilePath}`\n );\n }\n return;\n }\n\n try {\n // Transform model file\n logger.info(`Transforming model file: ${normalized.modelFilePath}`);\n const modelTransformer = new ModelFileTransformer(codegenFs, normalized);\n modelTransformer.transform();\n\n // Transform or create services file\n if (normalized.updateServices) {\n logger.info(\n `Transforming services file: ${\n normalized.servicesFilePath || \"creating new\"\n }`\n );\n const serviceTransformer = new ServiceFileTransformer(\n codegenFs,\n normalized\n );\n serviceTransformer.transform();\n }\n\n // Transform registration file\n if (normalized.registrationFilePath) {\n logger.info(\n `Transforming registration file: ${normalized.registrationFilePath}`\n );\n const registrationTransformer = new RegistrationFileTransformer(\n codegenFs,\n normalized\n );\n registrationTransformer.transform();\n }\n\n logger.info(\n `Successfully added ${normalized.futureType} Future support to ${normalized.modelName}`\n );\n logger.info(\"\");\n logger.info(\"Next steps:\");\n logger.info(\n \"1. Review the generated @kosFuture method and implement your actual operation\"\n );\n logger.info(\n \"2. Update the service method to return a proper FutureResponse\"\n );\n logger.info(\"3. Define your specific progress and result types\");\n if (normalized.futureType === \"complete\") {\n logger.info(\n \"4. Customize the onFutureUpdate method for your specific needs\"\n );\n }\n } catch (error) {\n logger.error(`Failed to add Future support: ${error}`);\n throw error;\n }\n}\n","/**\n * Capability mutator: add container support to an EXISTING model.\n *\n * Applies the `@kosContainerAware` capability (decorator + declaration-merging\n * interface + imports) to a model in place, so a model can manage a collection of\n * children directly — replacing the older pattern that forced a separate container\n * model plus an extra model-manager layer.\n *\n * AST-based via the shared ts-morph toolkit (no regex); routes all I/O through\n * CodegenFileSystem so dry-run + formatFiles apply unchanged.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { recordContainerSupportInKosConfig } from \"../../kos-config\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { type ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { resolveChildModelType } from \"../augment/resolve-child-model\";\nimport {\n addClassDecorator,\n ensureDeclarationMerge,\n ensureFileEslintDisable,\n ensureNamedImport,\n getModelClass,\n resolveSdkModuleSpecifier,\n transformSourceFile,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddContainerSupportOptions {\n modelName: string;\n modelProject: string;\n /** TS type the container holds. Default `IKosDataModel`. */\n childType?: string;\n /** Container property name on the instance. Default `container`. */\n containerProperty?: string;\n /** Optional `containerOptions.sortKey`. */\n sortKey?: string;\n /** Explicit model file path (relative to root), overriding resolution. */\n modelPath?: string;\n /**\n * Module the `childType` is imported from, when it is a model type rather\n * than the SDK default. Without it a caller naming a concrete child type\n * produces a file that references a type it never imports.\n */\n childTypeModule?: string;\n /**\n * Name of the model the container holds. Resolves to `<ProperCase>Model` and\n * to the module that exports it, so the caller does not have to know whether\n * that is a relative path or the child project's package name.\n */\n childModel?: string;\n /** Project owning `childModel`. Defaults to the container model's project. */\n childModelProject?: string;\n}\n\nfunction buildDecoratorArgs(options: AddContainerSupportOptions): string {\n const top: string[] = [];\n if (options.containerProperty) {\n top.push(`containerProperty: ${JSON.stringify(options.containerProperty)}`);\n }\n if (options.sortKey) {\n top.push(\n `containerOptions: { sortKey: ${JSON.stringify(options.sortKey)} }`\n );\n }\n return top.length ? `{ ${top.join(\", \")} }` : \"\";\n}\n\n/**\n * Add `@kosContainerAware` support to an existing model file.\n */\nexport function addContainerSupportToModel(\n codegenFs: CodegenFileSystem,\n options: AddContainerSupportOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const resolvedChild = options.childModel\n ? resolveChildModelType(\n codegenFs,\n {\n modelFilePath,\n modelProject: options.modelProject,\n childModel: options.childModel,\n childModelProject: options.childModelProject,\n },\n projects\n )\n : {\n childType: options.childType,\n childTypeModule: options.childTypeModule,\n };\n const childType = resolvedChild.childType?.trim() || \"IKosDataModel\";\n const childTypeModule = resolvedChild.childTypeModule;\n\n logger.info(\n `Adding container support (<${childType}>) to model: ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [\n { name: \"kosContainerAware\" },\n { name: \"KosContainerAware\", isTypeOnly: true },\n ]);\n // The default child type comes from the SDK; a named one comes from the\n // module the caller resolved it to.\n if (childType === \"IKosDataModel\") {\n ensureNamedImport(sf, sdk, [{ name: \"IKosDataModel\", isTypeOnly: true }]);\n } else if (childTypeModule) {\n ensureNamedImport(sf, childTypeModule, [\n { name: childType, isTypeOnly: true },\n ]);\n }\n\n const cls = getModelClass(sf);\n const className = cls.getName();\n if (!className) throw new Error(\"Model class has no name.\");\n // Capture the class's type parameters so the merged interface matches.\n const typeParams = cls.getTypeParameters().map((tp) => tp.getText());\n\n addClassDecorator(cls, \"kosContainerAware\", {\n typeArgs: [childType],\n argsText: buildDecoratorArgs(options),\n });\n\n ensureDeclarationMerge(\n sf,\n className,\n `KosContainerAware<${childType}>`,\n typeParams\n );\n ensureFileEslintDisable(\n sf,\n \"@typescript-eslint/no-unsafe-declaration-merging\"\n );\n });\n\n // The model now manages children directly — reflect that containment in the\n // catalog (`container: true`, and `managedBy` on a concrete held model).\n recordContainerSupportInKosConfig({\n codegenFs,\n projectName: options.modelProject,\n modelName: options.modelName,\n childType,\n projects,\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: make an EXISTING model aware of its parent.\n *\n * Applies `@kosParentAware()` to the model class and extends the model's options\n * interface with `KosParentAware`, so the parent is available immediately after\n * creation and the parent id is part of the options contract.\n *\n * Both edits belong together: the decorator sets the model's `optionsRequired`\n * flag, so an options type that does not carry the parent id describes a model\n * that cannot be constructed.\n *\n * AST-based via the shared ts-morph toolkit; routes all I/O through\n * CodegenFileSystem so dry-run and formatFiles apply unchanged.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { getCodegenLogger } from \"../../logger\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n addClassDecorator,\n ensureNamedImport,\n getModelClass,\n resolveSdkModuleSpecifier,\n transformSourceFile,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddParentAwareOptions {\n modelName: string;\n modelProject: string;\n /** Options key holding the parent id. Defaults to the SDK's own key. */\n parentId?: string;\n /** Explicit model file path (relative to root), overriding resolution. */\n modelPath?: string;\n}\n\nexport function addParentAwareToModel(\n codegenFs: CodegenFileSystem,\n options: AddParentAwareOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string; optionsFilePath?: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n logger.info(`Adding parent awareness to model: ${options.modelName}`);\n\n let optionsTypeName: string | undefined;\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [{ name: \"kosParentAware\" }]);\n\n const cls = getModelClass(sf);\n addClassDecorator(cls, \"kosParentAware\", {\n argsText: options.parentId\n ? `{ parentId: ${JSON.stringify(options.parentId)} }`\n : \"\",\n });\n\n // The options type is the one the constructor takes; it is what has to\n // carry the parent id.\n const ctor = cls.getConstructors()[0];\n optionsTypeName = ctor\n ?.getParameters()[1]\n ?.getTypeNode()\n ?.getText()\n ?.replace(/<.*$/, \"\");\n });\n\n const optionsFilePath = optionsTypeName\n ? extendOptionsInterface(codegenFs, modelFilePath, optionsTypeName, logger)\n : undefined;\n\n return { modelFilePath, optionsFilePath };\n}\n\n/**\n * Extend the model's options interface with `KosParentAware`, in whichever file\n * declares it — generated models keep it in the folder's `types/index.d.ts`.\n */\nfunction extendOptionsInterface(\n codegenFs: CodegenFileSystem,\n modelFilePath: string,\n optionsTypeName: string,\n logger: ReturnType<typeof getCodegenLogger>\n): string | undefined {\n const typesPath = path.join(\n path.dirname(modelFilePath),\n \"types\",\n \"index.d.ts\"\n );\n const target = codegenFs.exists(typesPath) ? typesPath : modelFilePath;\n\n let extended = false;\n transformSourceFile(codegenFs, target, (sf) => {\n const iface = sf.getInterface(optionsTypeName);\n if (!iface) return;\n\n const already = iface\n .getExtends()\n .some((clause) => clause.getText().includes(\"KosParentAware\"));\n if (already) {\n extended = true;\n return;\n }\n\n ensureNamedImport(sf, \"@kosdev-code/kos-ui-sdk\", [\n { name: \"KosParentAware\", isTypeOnly: true },\n ]);\n iface.addExtends(\"KosParentAware\");\n extended = true;\n });\n\n if (!extended) {\n logger.warn(\n `Could not find interface ${optionsTypeName}; add \"extends KosParentAware\" to it by hand.`\n );\n return undefined;\n }\n return target;\n}\n","/**\n * Read-only structural report of a KOS model. AST-based (ts-morph): surfaces the\n * model's type id, the @kos* decorators it carries, the capabilities already wired\n * (child collections, dependencies, topic handlers, config properties, service\n * requests, effects, futures), and whether it is itself a companion. Lets an agent\n * see what a model already has before deciding which mutator to apply — the\n * discovery counterpart to validate_model.\n */\nimport { Project, type ClassDeclaration } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { decoratorConfigText } from \"../augment/ts-toolkit\";\n\nexport interface DescribeModelOptions {\n modelName: string;\n modelProject: string;\n modelPath?: string;\n}\n\n/** A decorated member (method or property) and the bare argument text of its decorator. */\nexport interface DescribedMember {\n name: string;\n /** First decorator argument as written, trimmed (e.g. the topic or config path). */\n arg?: string;\n /** Property/return type as written, when present. */\n type?: string;\n}\n\nexport interface ModelDescription {\n modelFilePath: string;\n /** Value of the MODEL_TYPE constant, if declared. */\n modelType?: string;\n /** The impl class name (e.g. BoardModelImpl). */\n className?: string;\n /** Class-level @kos* decorators in source order (e.g. kosModel, kosLoggerAware). */\n classDecorators: string[];\n singleton: boolean;\n /** True when the class carries @kosCompanion — it augments a parent model. */\n isCompanion: boolean;\n /** @kosChild collection/child properties. */\n children: DescribedMember[];\n /** @kosDependency cross-model references. */\n dependencies: DescribedMember[];\n /** @kosTopicHandler subscription methods. */\n topicHandlers: DescribedMember[];\n /** @kosConfigProperty reactive config-bound properties. */\n configProperties: DescribedMember[];\n /** @kosServiceRequest backend-call methods. */\n serviceRequests: DescribedMember[];\n /** @kosModelEffect reaction methods. */\n effects: DescribedMember[];\n /** @kosFuture long-running-operation methods. */\n futures: DescribedMember[];\n}\n\n/** First decorator argument as written, whitespace-collapsed to one line, if any. */\nfunction firstDecoratorArg(decoratorText: string): string | undefined {\n const open = decoratorText.indexOf(\"(\");\n if (open === -1) return undefined;\n const inner = decoratorText\n .slice(open + 1, decoratorText.lastIndexOf(\")\"))\n .replace(/\\s+/g, \" \")\n .trim();\n return inner || undefined;\n}\n\nfunction collectDecorated(\n cls: ClassDeclaration,\n decoratorName: string\n): DescribedMember[] {\n const members: DescribedMember[] = [];\n const visit = (\n name: string,\n decoratorTextOf: () => string | undefined,\n typeText?: string\n ) => {\n const text = decoratorTextOf();\n if (text === undefined) return;\n members.push({\n name,\n arg: firstDecoratorArg(text),\n type: typeText || undefined,\n });\n };\n for (const m of cls.getMethods()) {\n const dec = m.getDecorator(decoratorName);\n if (dec) {\n visit(m.getName(), () => dec.getText(), m.getReturnTypeNode()?.getText());\n }\n }\n for (const p of cls.getProperties()) {\n const dec = p.getDecorator(decoratorName);\n if (dec) {\n visit(p.getName(), () => dec.getText(), p.getTypeNode()?.getText());\n }\n }\n return members;\n}\n\nexport function describeModel(\n codegenFs: CodegenFileSystem,\n options: DescribeModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): ModelDescription {\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n const content = codegenFs.read(modelFilePath);\n if (content === null) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const project = new Project({ useInMemoryFileSystem: true });\n const sf = project.createSourceFile(modelFilePath, content, {\n overwrite: true,\n });\n\n // MODEL_TYPE = \"...\" (the runtime model-type id).\n let modelType: string | undefined;\n const modelTypeDecl = sf.getVariableDeclaration(\"MODEL_TYPE\");\n if (modelTypeDecl) {\n const init = modelTypeDecl.getInitializer()?.getText();\n if (init) modelType = init.replace(/^[\"'`]|[\"'`]$/g, \"\");\n }\n\n // The model impl class is the one carrying @kosModel.\n const cls =\n sf.getClasses().find((c) => c.getDecorator(\"kosModel\")) ??\n sf.getClasses().find((c) => c.isExported()) ??\n sf.getClasses()[0];\n\n if (!cls) {\n return {\n modelFilePath,\n modelType,\n classDecorators: [],\n singleton: false,\n isCompanion: false,\n children: [],\n dependencies: [],\n topicHandlers: [],\n configProperties: [],\n serviceRequests: [],\n effects: [],\n futures: [],\n };\n }\n\n const classDecorators = cls.getDecorators().map((d) => d.getName());\n const kosModelArg = decoratorConfigText(sf, cls, \"kosModel\");\n const singleton = /\\bsingleton\\s*:\\s*true\\b/.test(kosModelArg ?? \"\");\n\n return {\n modelFilePath,\n modelType,\n className: cls.getName(),\n classDecorators,\n singleton,\n isCompanion: classDecorators.includes(\"kosCompanion\"),\n children: collectDecorated(cls, \"kosChild\"),\n dependencies: collectDecorated(cls, \"kosDependency\"),\n topicHandlers: collectDecorated(cls, \"kosTopicHandler\"),\n configProperties: collectDecorated(cls, \"kosConfigProperty\"),\n serviceRequests: collectDecorated(cls, \"kosServiceRequest\"),\n effects: collectDecorated(cls, \"kosModelEffect\"),\n futures: collectDecorated(cls, \"kosFuture\"),\n };\n}\n","/**\n * Capability mutator: add a `@kosModelEffect` reaction method to an existing model.\n * Generates an idiomatic skeleton (dependencies arrow + async handler) for the\n * developer/agent to fill in. AST-based via the shared toolkit.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedMethod,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddModelEffectOptions {\n modelName: string;\n modelProject: string;\n /** Effect handler method name, e.g. `handleSelectionChange`. */\n methodName: string;\n modelPath?: string;\n}\n\nexport function addModelEffectToModel(\n codegenFs: CodegenFileSystem,\n options: AddModelEffectOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosModelEffect \"${options.methodName}\" to ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [{ name: \"kosModelEffect\" }]);\n const cls = getModelClass(sf);\n const modelType = (cls.getName() ?? \"\").replace(/Impl$/, \"\");\n addDecoratedMethod(cls, {\n name: options.methodName,\n decoratorName: \"kosModelEffect\",\n decoratorArgsText: `{ dependencies: (model: ${modelType}) => [] }`,\n isAsync: true,\n returnType: \"Promise<void>\",\n statements: \"// TODO: react to the tracked dependencies\",\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosDependency` property (cross-model reference) to an\n * existing model. The dependency's TS type and `modelType` ref are caller-supplied.\n *\n * When `dependencyPackage` is given (the SDK that owns the dependency — exactly what\n * `describe_sdk_model` surfaces from the catalog), this also adds the import for the\n * registration bean (the `X` in `X.type`) and the model interface type from that\n * package, so wiring an SDK model is a single call. Without it, importing those\n * symbols stays the caller's responsibility (the mutator can't guess their origin).\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedProperty,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddDependencyOptions {\n modelName: string;\n modelProject: string;\n /** Property name to hold the dependency, e.g. `application`. */\n propertyName: string;\n /** TS type of the dependency, e.g. `ApplicationModel`. */\n dependencyType: string;\n /** Runtime model-type ref, e.g. `Application.type` or a string literal. */\n modelTypeRef: string;\n /** Optional dependency id. */\n id?: string;\n /**\n * The SDK package that owns the dependency (e.g. `@kosdev-code/kos-ui-sdk`). When\n * set, the registration bean and the model interface type are imported from it.\n */\n dependencyPackage?: string;\n modelPath?: string;\n}\n\n// Framework generics that come from the KOS SDK, not the dependency's own package —\n// never import these from `dependencyPackage`.\nconst FRAMEWORK_TYPES = new Set([\"IKosDataModel\", \"IKosIdentifiable\"]);\n\nexport function addDependencyToModel(\n codegenFs: CodegenFileSystem,\n options: AddDependencyOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosDependency \"${options.propertyName}\" to ${options.modelName}`\n );\n\n const argsParts = [`modelType: ${options.modelTypeRef}`];\n if (options.id) argsParts.push(`id: ${JSON.stringify(options.id)}`);\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [{ name: \"kosDependency\" }]);\n\n // Import the dependency's own symbols from the SDK root barrel (NOT a subpath —\n // every model/bean/type is re-exported from the package root).\n if (options.dependencyPackage) {\n const named: { name: string; isTypeOnly?: boolean }[] = [];\n // Registration bean: the `X` in `X.type` (skip string-literal refs).\n const bean = options.modelTypeRef.match(\n /^([A-Za-z_$][\\w$]*)\\.type$/\n )?.[1];\n if (bean) named.push({ name: bean });\n // Model interface type, unless it's a framework generic from the SDK.\n const depType = options.dependencyType?.trim();\n if (\n depType &&\n /^[A-Za-z_$][\\w$]*$/.test(depType) &&\n !FRAMEWORK_TYPES.has(depType)\n ) {\n named.push({ name: depType, isTypeOnly: true });\n }\n if (named.length) ensureNamedImport(sf, options.dependencyPackage, named);\n }\n\n const cls = getModelClass(sf);\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosDependency\",\n decoratorArgsText: `{ ${argsParts.join(\", \")} }`,\n type: options.dependencyType,\n scope: \"private\",\n hasExclamation: true,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosChild` property (owned sub-model enrollment) to an\n * existing model. Enrolls the child(ren) into the parent's model graph, lifecycle\n * cascade, and context scope-chain (a key the parent sets on its context bean resolves\n * down the whole subtree — see kos://guide/model-context). Three shapes:\n * single → `@kosChild private {prop}!: {Child};`\n * container → `@kosChild private {prop} = new KosModelContainer<{Child}>();`\n * array → `@kosChild private {prop}: {Child}[] = [];`\n *\n * When `childPackage` is given (the SDK/package that owns the child model — exactly\n * what `describe_sdk_model` surfaces), the child type is imported from it; without it,\n * importing the child type stays the caller's responsibility (the mutator can't guess\n * its origin). `KosModelContainer` (container shape) always imports from the SDK.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport { resolveChildModelType } from \"../augment/resolve-child-model\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedProperty,\n} from \"../augment/ts-toolkit\";\n\nexport type ChildShape = \"single\" | \"container\" | \"array\";\n\nexport interface AddChildOptions {\n modelName: string;\n modelProject: string;\n /** Property name that holds the child(ren), e.g. `pages`, `pump`, `sensors`. */\n propertyName: string;\n /** Child model TS type, e.g. `PageModel`. Derived when `childModel` is given. */\n childType?: string;\n /**\n * Name of the child model. Resolves to `<ProperCase>Model` and to the module\n * that exports it, so the caller does not have to know whether that is a\n * relative path or the child project's package name.\n */\n childModel?: string;\n /** Project owning `childModel`. Defaults to the parent model's project. */\n childModelProject?: string;\n /** How the child(ren) are held. Default `single`. */\n shape?: ChildShape;\n /** Package that owns the child model; when set, its type is imported from the root. */\n childPackage?: string;\n modelPath?: string;\n}\n\n// Framework generics that come from the KOS SDK, not the child's own package — never\n// import these from `childPackage`.\nconst FRAMEWORK_TYPES = new Set([\"IKosDataModel\", \"IKosIdentifiable\"]);\n\nexport function addChildToModel(\n codegenFs: CodegenFileSystem,\n options: AddChildOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const shape: ChildShape = options.shape ?? \"single\";\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosChild \"${options.propertyName}\" (${shape}) to ${options.modelName}`\n );\n\n const resolvedChild = options.childModel\n ? resolveChildModelType(\n codegenFs,\n {\n modelFilePath,\n modelProject: options.modelProject,\n childModel: options.childModel,\n childModelProject: options.childModelProject,\n },\n projects\n )\n : { childType: options.childType, childTypeModule: options.childPackage };\n const childType = resolvedChild.childType?.trim();\n const childTypeModule = resolvedChild.childTypeModule;\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n const sdkImports: { name: string; isTypeOnly?: boolean }[] = [\n { name: \"kosChild\" },\n ];\n // The container shape uses KosModelContainer as a VALUE (`new …`) — import it.\n if (shape === \"container\") sdkImports.push({ name: \"KosModelContainer\" });\n ensureNamedImport(sf, sdk, sdkImports);\n\n // Import the child model type from its owning package when known. In every shape\n // the child type appears only in TYPE position (annotation or generic arg), so a\n // type-only import is correct.\n if (\n childTypeModule &&\n childType &&\n /^[A-Za-z_$][\\w$]*$/.test(childType) &&\n !FRAMEWORK_TYPES.has(childType)\n ) {\n ensureNamedImport(sf, childTypeModule, [\n { name: childType, isTypeOnly: true },\n ]);\n }\n\n const cls = getModelClass(sf);\n if (shape === \"container\") {\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosChild\",\n bare: true,\n initializer: `new KosModelContainer<${childType}>()`,\n scope: \"private\",\n });\n } else if (shape === \"array\") {\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosChild\",\n bare: true,\n type: `${childType}[]`,\n initializer: \"[]\",\n scope: \"private\",\n });\n } else {\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosChild\",\n bare: true,\n type: childType,\n scope: \"private\",\n hasExclamation: true,\n });\n }\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosTopicHandler` subscription method to an existing\n * model. Generates an idiomatic INIT/websocket handler skeleton. The `topic` and\n * event type are caller-supplied (the caller ensures the topic constant is defined).\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedMethod,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddTopicHandlerOptions {\n modelName: string;\n modelProject: string;\n /** Handler method name, e.g. `handleBoardLinked`. */\n handlerName: string;\n /** Topic expression — a constant ref (e.g. `TOPIC_BOARD_LINKED`) or string literal. */\n topic: string;\n /** Event payload TS type for the handler parameter. Default `unknown`. */\n eventType?: string;\n /** Subscribe over websocket. Default true. */\n websocket?: boolean;\n modelPath?: string;\n}\n\nexport function addTopicHandlerToModel(\n codegenFs: CodegenFileSystem,\n options: AddTopicHandlerOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosTopicHandler \"${options.handlerName}\" to ${options.modelName}`\n );\n\n const websocket = options.websocket ?? true;\n const eventType = options.eventType || \"unknown\";\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [\n { name: \"kosTopicHandler\" },\n { name: \"DependencyLifecycle\" },\n ]);\n const cls = getModelClass(sf);\n addDecoratedMethod(cls, {\n name: options.handlerName,\n decoratorName: \"kosTopicHandler\",\n decoratorArgsText: `{ lifecycle: DependencyLifecycle.INIT, topic: ${options.topic}, websocket: ${websocket} }`,\n parameters: [{ name: \"event\", type: eventType }],\n statements: \"// TODO: handle the topic event\",\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a `@kosConfigProperty` reactive config-bound property to an\n * existing model. The `path` (config path ref/literal) and `attribute` are caller\n * supplied; the value is exposed as `KosConfigProperty<T>`.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedProperty,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddConfigPropertyOptions {\n modelName: string;\n modelProject: string;\n /** Property name to hold the config value, e.g. `remoteTrayEnabled`. */\n propertyName: string;\n /** Config path expression — a constant ref (e.g. `PROP_CONFIG_PATH`) or string literal. */\n path: string;\n /** Config attribute name, e.g. `enabled` or `settings.volWithoutIceMl`. */\n attribute: string;\n /** Value TS type inside `KosConfigProperty<…>`. Default `unknown`. */\n valueType?: string;\n modelPath?: string;\n}\n\nexport function addConfigPropertyToModel(\n codegenFs: CodegenFileSystem,\n options: AddConfigPropertyOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding @kosConfigProperty \"${options.propertyName}\" to ${options.modelName}`\n );\n\n const valueType = options.valueType || \"unknown\";\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const sdk = resolveSdkModuleSpecifier(sf);\n ensureNamedImport(sf, sdk, [\n { name: \"kosConfigProperty\" },\n { name: \"KosConfigProperty\", isTypeOnly: true },\n ]);\n const cls = getModelClass(sf);\n addDecoratedProperty(cls, {\n name: options.propertyName,\n decoratorName: \"kosConfigProperty\",\n decoratorArgsText: `{ path: ${options.path}, attribute: ${JSON.stringify(\n options.attribute\n )} }`,\n type: `KosConfigProperty<${valueType}>`,\n hasExclamation: true,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a basic (plain) typed property to an existing model —\n * just a TypeScript field like `prop1: string`. This is local model state, NOT a\n * device-config-bound reactive value (that's `addConfigPropertyToModel`) nor a\n * cross-model reference (`addDependencyToModel`). Use for simple state the model\n * holds and sets itself.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n getModelClass,\n addPlainProperty,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddPropertyOptions {\n modelName: string;\n modelProject: string;\n /** Property name, e.g. `prop1`. */\n propertyName: string;\n /** TS type of the field, e.g. `string`, `number`, `boolean`. Default `string`. */\n type?: string;\n /** Optional initializer expression (e.g. `\"\"`, `0`, `false`). */\n initializer?: string;\n /** Mark the field `readonly`. */\n readonly?: boolean;\n modelPath?: string;\n}\n\n/** Sensible default initializer per primitive so the field compiles under strict mode. */\nfunction defaultInitializer(type: string): string | undefined {\n switch (type) {\n case \"string\":\n return '\"\"';\n case \"number\":\n return \"0\";\n case \"boolean\":\n return \"false\";\n default:\n return undefined; // non-primitive → definite-assignment `!`\n }\n}\n\nexport function addPropertyToModel(\n codegenFs: CodegenFileSystem,\n options: AddPropertyOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const type = options.type || \"string\";\n // Caller initializer wins; else a primitive default; else definite-assignment.\n const initializer =\n options.initializer !== undefined\n ? options.initializer\n : defaultInitializer(type);\n\n logger.info(\n `Adding property \"${options.propertyName}: ${type}\" to ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const cls = getModelClass(sf);\n addPlainProperty(cls, {\n name: options.propertyName,\n type,\n initializer,\n readonly: options.readonly,\n hasExclamation: initializer === undefined,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * Capability mutator: add a COMPUTED member to a model — a read-only getter\n * (`get name(): T { ... }`) that derives its value from other model state. Distinct\n * from a stored field (`addPropertyToModel`): a computed member holds no state, it\n * recomputes on access.\n */\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n transformSourceFile,\n getModelClass,\n addGetter,\n} from \"../augment/ts-toolkit\";\n\nexport interface AddComputedOptions {\n modelName: string;\n modelProject: string;\n /** Getter name, e.g. `displayName`. */\n name: string;\n /** Return TS type, e.g. `string`. Default inferred (omitted). */\n returnType?: string;\n /** Body statements; default a TODO stub. */\n body?: string;\n modelPath?: string;\n}\n\nexport function addComputedToModel(\n codegenFs: CodegenFileSystem,\n options: AddComputedOptions,\n projects?: Map<string, ProjectConfiguration>\n): { modelFilePath: string } {\n const logger = getCodegenLogger();\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n logger.info(\n `Adding computed getter \"${options.name}\" to ${options.modelName}`\n );\n\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n const cls = getModelClass(sf);\n addGetter(cls, {\n name: options.name,\n returnType: options.returnType,\n statements: options.body,\n });\n });\n\n return { modelFilePath };\n}\n","/**\n * The model's `mocks/` module — KosMock routes standing in for endpoints the\n * generated OpenAPI types do not declare yet.\n *\n * Deliberately OUTSIDE the model's `services/` barrel and outside the project\n * index: nothing imports it, so it cannot reach a production bundle by accident.\n * Arming it is one explicit call from the app, which is also the only place that\n * decision belongs.\n *\n * Its whole purpose is to be deleted. Everything else the provisional form emits\n * — decorator, lifecycle, error-first handler, transform — is real code that\n * survives the endpoint landing; only the wire response is synthetic, and it\n * lives here.\n */\nimport * as path from \"path\";\nimport { VariableDeclarationKind, type SourceFile } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { constantCase, dashCase, pascalCase } from \"../../name-utils\";\nimport { transformSourceFile, ensureNamedImport } from \"./ts-toolkit\";\n\n/** Where a model's mocks module lives, whether or not it exists yet. */\nexport function mocksFilePathFor(\n modelFilePath: string,\n modelBase: string\n): string {\n return path.join(\n path.dirname(modelFilePath),\n \"mocks\",\n `${modelBase}-mocks.ts`\n );\n}\n\n/** The function an app calls to arm this model's provisional routes. */\nexport function mockRegisterFunctionName(modelBase: string): string {\n return `register${pascalCase(modelBase)}Mocks`;\n}\n\n/**\n * KosMock matches `:name` segments; OpenAPI writes `{name}`. Same meaning, one\n * translation — so the route pattern and the endpoint stay recognizably the\n * same string.\n */\nexport function toMockRoutePattern(servicePath: string): string {\n return servicePath.replace(/\\{([^}]+)\\}/g, \":$1\");\n}\n\n/**\n * The KosMock call for a method. `del` because `delete` is a reserved word, and\n * PATCH has no shorthand at all — both facts belong here rather than in the\n * caller.\n */\nfunction mockRouteCall(method: string, pattern: string, body: string): string {\n const shorthand: Record<string, string> = {\n get: \"get\",\n post: \"post\",\n put: \"put\",\n delete: \"del\",\n };\n const fn = shorthand[method];\n return fn\n ? `KosMock.${fn}(${JSON.stringify(pattern)}, ${body});`\n : `KosMock.route(${JSON.stringify(method.toUpperCase())}, ${JSON.stringify(\n pattern\n )}, ${body});`;\n}\n\nfunction header(modelBase: string, registerFn: string): string {\n return `/**\n * KosMock routes for the ${modelBase} model's PROVISIONAL endpoints — the ones\n * this project's generated OpenAPI types do not declare.\n *\n * NOTHING IMPORTS THIS FILE. Call \\`${registerFn}()\\` from the app's dev entry,\n * gated so it cannot run in a production build (\\`import.meta.env.DEV\\`, a\n * dev-only entry module, or behind your own switch). Registering a route enables\n * KosMock, and a mock that shipped would shadow the real endpoint once it exists.\n *\n * Unmatched requests still pass through to the real device (KosMock's hybrid\n * default), so these routes shadow only the paths named below. Every mocked\n * response carries the \\`kos-mocked: true\\` wire header, so mock-fed data is\n * identifiable in devtools.\n *\n * DELETE THIS FILE once every endpoint below is in the generated types.\n */\n`;\n}\n\nexport interface EnsureMockRouteOptions {\n modelFilePath: string;\n /** `board-model.ts` → `board`. */\n modelBase: string;\n /** Specifier the MODEL imports the SDK from, e.g. `@kosdev-code/kos-ui-sdk`. */\n sdkModuleSpecifier: string;\n /** Raw wire type exported by the model's services module. */\n rawAlias: string;\n /** Endpoint the route stands in for. */\n servicePath: string;\n method: string;\n /** Catalog key, used to name the sample payload. */\n endpointKey: string;\n /**\n * Sample payload as TypeScript expression text. Omitted when the caller\n * supplied none, and a placeholder + TODO is emitted instead.\n */\n sampleText?: string;\n}\n\nexport interface EnsureMockRouteResult {\n mocksFilePath: string;\n registerFunction: string;\n routePattern: string;\n sampleName: string;\n /** False when a route for this (method, pattern) was already registered. */\n routeCreated: boolean;\n /** True when no sample was supplied, so the route serves a placeholder. */\n samplePlaceholder: boolean;\n}\n\n/**\n * Ensure the model's mocks module registers a route for one provisional\n * endpoint. Idempotent on (method, pattern): a second call for the same\n * endpoint adds nothing.\n */\nexport function ensureMockRoute(\n codegenFs: CodegenFileSystem,\n options: EnsureMockRouteOptions\n): EnsureMockRouteResult {\n const mocksFilePath = mocksFilePathFor(\n options.modelFilePath,\n options.modelBase\n );\n const registerFunction = mockRegisterFunctionName(options.modelBase);\n const routePattern = toMockRoutePattern(options.servicePath);\n const sampleName = `SAMPLE_${constantCase(dashCase(options.endpointKey))}`;\n const samplePlaceholder = !options.sampleText;\n\n if (!codegenFs.exists(mocksFilePath)) {\n codegenFs.write(mocksFilePath, header(options.modelBase, registerFunction));\n }\n\n // The mocks module sits one directory deeper than the model, so a relative SDK\n // specifier (the in-SDK case) needs one more hop; a package specifier does not.\n const sdkSpecifier = options.sdkModuleSpecifier.startsWith(\".\")\n ? `../${options.sdkModuleSpecifier}`\n : options.sdkModuleSpecifier;\n\n let routeCreated = false;\n\n transformSourceFile(codegenFs, mocksFilePath, (sf) => {\n ensureNamedImport(sf, sdkSpecifier, [{ name: \"KosMock\" }]);\n ensureNamedImport(sf, \"../services\", [\n { name: options.rawAlias, isTypeOnly: true },\n ]);\n\n ensureSample(sf, {\n name: sampleName,\n type: options.rawAlias,\n servicePath: options.servicePath,\n method: options.method,\n sampleText: options.sampleText,\n });\n\n const statement = mockRouteCall(\n options.method,\n routePattern,\n `{ data: ${sampleName} }`\n );\n routeCreated = ensureRegisteredRoute(sf, {\n registerFunction,\n modelBase: options.modelBase,\n statement,\n // Matching on the pattern literal alone would collide across methods.\n marker: `${options.method.toUpperCase()} ${routePattern}`,\n matches: (existing) =>\n existing.includes(JSON.stringify(routePattern)) &&\n existing.includes(shorthandOrMethod(options.method)),\n });\n });\n\n return {\n mocksFilePath,\n registerFunction,\n routePattern,\n sampleName,\n routeCreated,\n samplePlaceholder,\n };\n}\n\n/** The token a route statement carries for its method, for match-on-reuse. */\nfunction shorthandOrMethod(method: string): string {\n const shorthand: Record<string, string> = {\n get: \"KosMock.get(\",\n post: \"KosMock.post(\",\n put: \"KosMock.put(\",\n delete: \"KosMock.del(\",\n };\n return shorthand[method] ?? `\"${method.toUpperCase()}\"`;\n}\n\nfunction ensureSample(\n sf: SourceFile,\n spec: {\n name: string;\n type: string;\n servicePath: string;\n method: string;\n sampleText?: string;\n }\n): void {\n if (sf.getVariableDeclaration(spec.name)) return;\n\n // What the transform receives, not what the socket carries: the client strips\n // the `{status, data}` envelope before the decorator's transform runs, and\n // KosMock's `{ data: … }` puts the envelope back. Saying so here is the\n // difference between a sample that exercises the mapper and one that doesn't.\n const lines = [\n `Sample payload for \\`${spec.method.toUpperCase()} ${\n spec.servicePath\n }\\` — the`,\n \"UNWRAPPED `data` payload, i.e. exactly what the transform receives.\",\n ];\n if (!spec.sampleText) {\n lines.push(\n \"\",\n \"TODO: replace the placeholder with something the backend would actually\",\n \"serve. Until then the route answers with nothing and the transform is\",\n \"never exercised.\"\n );\n }\n const docs = lines.join(\"\\n\");\n\n sf.addVariableStatement({\n isExported: true,\n declarationKind: VariableDeclarationKind.Const,\n docs: [docs],\n declarations: [\n {\n name: spec.name,\n type: spec.type,\n initializer: spec.sampleText ?? `null as unknown as ${spec.type}`,\n },\n ],\n });\n}\n\n/**\n * Ensure the register function exists and contains this route statement.\n * Returns false when an equivalent route was already registered.\n */\nfunction ensureRegisteredRoute(\n sf: SourceFile,\n spec: {\n registerFunction: string;\n modelBase: string;\n statement: string;\n marker: string;\n matches: (existingStatementText: string) => boolean;\n }\n): boolean {\n let fn = sf.getFunction(spec.registerFunction);\n if (!fn) {\n fn = sf.addFunction({\n name: spec.registerFunction,\n isExported: true,\n returnType: \"void\",\n docs: [\n `Arm the ${spec.modelBase} model's provisional endpoints. Call this from a dev-only entry point — never from code that ships.`,\n ],\n });\n }\n\n const already = fn\n .getStatements()\n .some((statement) => spec.matches(statement.getText()));\n if (already) return false;\n\n fn.addStatements(`// ${spec.marker}\\n${spec.statement}`);\n return true;\n}\n","/**\n * Capability mutator: add a `@kosServiceRequest` method to an existing model.\n *\n * Uses the TYPED decorator generated by `api:generate` (imported from the project's\n * `…/utils/services/<app>/<version>/service.ts`), so `path` is validated against the\n * OpenAPI-derived `openapi.d.ts` at compile time. Purely mechanical: device query,\n * path discovery, and live-spec validation are a separate discovery orchestration.\n *\n * THE PATH IS CHECKED BEFORE ANYTHING IS WRITTEN. Leaving it to the compiler was\n * worse than no check at all: TS2820 answers \"not assignable to keyof paths\" with\n * a nearest-string suggestion, and the nearest string to an endpoint that does not\n * exist is some unrelated feature's endpoint. Following it wires the model to the\n * wrong API and compiles. So a miss fails here, and the alternatives it offers are\n * labelled as other endpoints rather than as corrections.\n *\n * A path the generated types do not declare has exactly two supported answers, and\n * falling back to pre-codegen request patterns is neither of them:\n *\n * generate — the endpoint exists on the device but this project has not pulled\n * types for it. Re-run api:generate; nothing here changes.\n * mock — the endpoint does not exist yet. `mock` emits the PROVISIONAL form:\n * every piece of plumbing real (decorator, lifecycle, error-first handler,\n * transform) and only the wire response synthetic, served by a KosMock route in\n * the model's `mocks/` module. The switch, when the endpoint lands, is deleting\n * the mock and the `as ApiPath` cast.\n *\n * WHERE THE DESCRIPTOR LIVES: the endpoint catalog and the types derived from it\n * belong to the model's own `services/` module, alongside the standalone service\n * functions that serve callers outside a model context. The model file only\n * IMPORTS from there — it declares no paths of its own, so data-transfer concerns\n * stay in one place and one path is described once however many methods use it.\n * The catalog is keyed by handler name but matched by (path, method): a second\n * method on an endpoint already in the catalog reuses that entry.\n *\n * Emits ONE OF TWO SHAPES, because @kosServiceRequest has two, and they are not\n * interchangeable:\n *\n * lifecycle — the framework performs the request during the phase and calls the\n * method back error-first as `(error, data)`. No execution context exists.\n * method — the method performs the request when called, through the `$ctx`\n * the decorator injects as the last parameter.\n *\n * The decorator itself decides by the presence of `lifecycle` (it only wraps the\n * handler to inject `$ctx` when `lifecycle` is absent), so this mutator derives\n * the mode the same way rather than defaulting to one of them.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { getCodegenLogger } from \"../../logger\";\nimport { pascalCase } from \"../../name-utils\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\nimport {\n ensureServicesModule,\n modelBaseName,\n servicesFilePathFor,\n} from \"../augment/model-services\";\nimport { ensureMockRoute } from \"../augment/model-mocks\";\nimport {\n readServiceModuleOperations,\n type ServiceOperation,\n} from \"../service-catalog\";\nimport {\n transformSourceFile,\n readSourceFile,\n ensureNamedImport,\n resolveSdkModuleSpecifier,\n getModelClass,\n addDecoratedMethod,\n addClassDecorator,\n ensureDeclarationMerge,\n ensureFileEslintDisable,\n ensureConstCatalogEntry,\n ensureExportedTypeAlias,\n ensureExportedMapper,\n} from \"../augment/ts-toolkit\";\n\nexport type ServiceRequestMode = \"lifecycle\" | \"method\";\n\n/**\n * What to do when the generated types do not declare the requested endpoint.\n *\n * `auto` never silently substitutes mocking for a real request — the result says\n * plainly that it did, and why, so the caller reports a missing endpoint rather\n * than a finished feature.\n */\nexport type ServiceRequestMockMode = \"auto\" | \"always\" | \"never\";\n\nexport interface AddServiceRequestOptions {\n modelName: string;\n modelProject: string;\n /** Handler method name, e.g. `onDataLoaded`. */\n methodName: string;\n /** OpenAPI path string, validated by the generated types, e.g. `/api/board/{id}`. */\n servicePath: string;\n /** HTTP method. Default `get`. */\n method?: string;\n /**\n * Which form to emit. Defaults to `lifecycle` when `lifecycle` is supplied and\n * `method` otherwise — the same rule @kosServiceRequest applies at runtime.\n */\n mode?: ServiceRequestMode;\n /**\n * DependencyLifecycle member name (LOAD, INIT, …). Only meaningful in\n * `lifecycle` mode; defaults to `LOAD` there.\n */\n lifecycle?: string;\n /**\n * What to do about an endpoint the generated types do not declare.\n *\n * `never` — a hard error; nothing is written.\n * `auto` — (default) emit the provisional, mock-backed form and say so.\n * `always` — emit a KosMock route even for an endpoint that IS typed, for\n * developing against something the spec declares but the device does not\n * serve yet. A typed endpoint keeps its typed request; only the mock is added.\n */\n mock?: ServiceRequestMockMode;\n /**\n * The raw wire shape a PROVISIONAL endpoint is expected to serve, as TypeScript\n * type text (`DeviceGrantSyncBean[]`, `{ id: string; label: string }`). This is\n * the UNWRAPPED `data` payload: the client strips the `{status, data}` envelope\n * before the transform runs. Defaults to `unknown`, which compiles but leaves\n * the response boundary undescribed.\n */\n rawType?: string;\n /**\n * Sample payload for the mock route, as TypeScript expression text. Typed\n * against the raw wire shape, so a sample that does not match it fails the\n * build rather than the demo. Without one the route answers with a placeholder\n * and the transform is never exercised.\n */\n sample?: string;\n /** Import specifier for the generated typed service module (relative to the model\n * file). If omitted, auto-resolved when the project has exactly one. */\n serviceModule?: string;\n /**\n * Root-relative path of the service module, as `listServiceCatalog` reports\n * it. Converted to an import specifier here, so a caller that picked an\n * operation from the catalog does not have to compute one — and does not trip\n * the \"multiple service modules\" error when a project types several versions.\n */\n serviceModulePath?: string;\n modelPath?: string;\n}\n\nexport interface AddServiceRequestResult {\n modelFilePath: string;\n /** The model's services module the descriptor was written to. */\n servicesFilePath: string;\n serviceModule: string;\n mode: ServiceRequestMode;\n /** Catalog entry the method points at — reused when the endpoint was known. */\n endpointKey: string;\n /** False when an existing catalog entry for this (path, method) was reused. */\n endpointCreated: boolean;\n /**\n * Whether the path was actually checked. False when the generated module\n * exposes no `paths` this can read — which is not evidence the endpoint exists.\n */\n pathValidated: boolean;\n /** True when the endpoint is absent from the generated types and was mocked. */\n provisional: boolean;\n /** The mock module, when one was written. */\n mocksFilePath?: string;\n /** Function the app must call to arm the routes, when one was written. */\n mockRegisterFunction?: string;\n /** `GET /api/board/grants`, when a route was registered. */\n mockRoute?: string;\n /** True when no sample was supplied, so the mock serves a placeholder. */\n mockSamplePlaceholder?: boolean;\n /** Exactly what to undo when the endpoint lands, in order. */\n removalSteps?: string[];\n}\n\n/**\n * Everything needed to report a rejected path, carried on the error rather than\n * flattened into its message — so a tool surface can present the alternatives\n * with their warning attached instead of as a list of corrections.\n */\nexport interface UntypedEndpointDetails {\n servicePath: string;\n method: string;\n /** True when the path is typed, but not for this method. */\n pathTypedForOtherMethods: boolean;\n /** Methods this path DOES support, when it is typed at all. */\n methodsForPath: string[];\n /** Nearest paths in the same API — alternatives to rule out, not to adopt. */\n otherEndpointsInThisApi: string[];\n warning: string;\n waysForward: string[];\n}\n\n/** A rejected path, with the alternatives kept apart from the verdict. */\nexport interface UntypedEndpointError extends Error {\n details: UntypedEndpointDetails;\n}\n\nconst SERVICE_MODULE_RE = /\\/utils\\/services\\/.*\\/service\\.ts$/;\n\n/** Find generated service modules under the project source root (root-relative paths). */\nfunction findServiceModules(\n codegenFs: CodegenFileSystem,\n sourceRoot: string\n): string[] {\n return codegenFs\n .listFiles(sourceRoot)\n .filter((f) => SERVICE_MODULE_RE.test(f.split(path.sep).join(\"/\")));\n}\n\n/** Build a relative import specifier (posix, no extension) from one file to another. */\nfunction toImportSpecifier(fromFile: string, toFileNoExt: string): string {\n let rel = path\n .relative(path.dirname(fromFile), toFileNoExt)\n .split(path.sep)\n .join(\"/\");\n if (!rel.startsWith(\".\")) rel = `./${rel}`;\n return rel;\n}\n\n/** Resolve a specifier stated relative to one file into a root-relative path. */\nfunction fromImportSpecifier(fromFile: string, specifier: string): string {\n return path.join(path.dirname(fromFile), specifier);\n}\n\n/**\n * The emitted method passes a transformed type to `EndpointCtx` and to\n * `serviceRequest`, which only the current `api:generate` output declares. A\n * module generated before that would accept the code and then fail to compile,\n * so refuse up front rather than write something that cannot build.\n *\n * A module that does not declare `EndpointCtx` at all is left alone — that is a\n * shape this check does not claim to understand.\n */\nfunction assertServiceModuleAcceptsTransform(\n codegenFs: CodegenFileSystem,\n serviceModuleFile: string,\n modelProject: string\n): void {\n const file = `${serviceModuleFile}.ts`;\n if (!codegenFs.exists(file)) return;\n\n const typeParams = readSourceFile(codegenFs, file, (sf) => {\n const alias = sf.getTypeAlias(\"EndpointCtx\");\n return alias ? alias.getTypeParameters().length : null;\n });\n if (typeParams === null || typeParams >= 2) return;\n\n throw new Error(\n `${file} predates the transform-aware service layer (EndpointCtx takes ${typeParams} type parameter). ` +\n `Run \\`kosui api:generate --project ${modelProject} --helpers-only\\` to refresh the helper layer ` +\n `in place (no spec fetch, openapi.d.ts untouched), then add the service request.`\n );\n}\n\nconst MUTATING_METHODS = new Set([\"post\", \"put\", \"delete\", \"patch\"]);\n\n/** A lifecycle request runs on phase, so a mutating verb must not carry one. */\nfunction assertLifecycleSuitsMethod(\n method: string,\n mode: ServiceRequestMode,\n methodName: string\n): void {\n if (mode !== \"lifecycle\" || !MUTATING_METHODS.has(method)) return;\n\n throw new Error(\n `${methodName} is a ${method.toUpperCase()} with a lifecycle, so it would run every time the model ` +\n `reaches that phase rather than when something calls it — a mutation on every load. ` +\n `Drop \\`lifecycle\\` to get the method-driven form (the default for ${method.toUpperCase()}), ` +\n `or pass \\`mode: \"method\"\\`. If the phase really is the trigger, the model calls the method from ` +\n `its own lifecycle hook, where the call is visible.`\n );\n}\n\n/**\n * The provisional form is emitted against `provisionalServiceRequest`, which\n * only the current helper layer declares. Same refusal, same fix as the\n * transform check above — and for the same reason: writing code the project\n * cannot compile is worse than not writing it.\n */\nfunction assertServiceModuleAcceptsProvisional(\n codegenFs: CodegenFileSystem,\n serviceModuleFile: string,\n modelProject: string\n): void {\n const file = `${serviceModuleFile}.ts`;\n if (!codegenFs.exists(file)) return;\n\n const declared = readSourceFile(codegenFs, file, (sf) =>\n Boolean(sf.getFunction(\"provisionalServiceRequest\"))\n );\n if (declared) return;\n\n throw new Error(\n `${file} has no \\`provisionalServiceRequest\\` — the helper layer predates provisional endpoints. ` +\n `Run \\`kosui api:generate --project ${modelProject} --helpers-only\\` to refresh it in place ` +\n `(no spec fetch, openapi.d.ts untouched), then add the service request.`\n );\n}\n\n/**\n * The two `endpoint(...)` initializers describe the same endpoint when their\n * path and method arguments match. Compared as parsed literals rather than as\n * text so quote style and spacing in a hand-edited catalog do not defeat reuse.\n *\n * The optional `as ApiPath` is the provisional marker, and it is deliberately\n * ignored here: an endpoint that has since been typed is still the same\n * endpoint, so dropping the cast must not orphan the entry that used it.\n */\nfunction sameEndpoint(existing: string, candidate: string): boolean {\n const args = (text: string) => {\n const match = text.match(\n /^endpoint\\s*\\(\\s*(['\"])(.*?)\\1(?:\\s+as\\s+ApiPath)?\\s*,\\s*(['\"])(.*?)\\3\\s*,?\\s*\\)$/\n );\n return match ? [match[2], match[4].toLowerCase()] : null;\n };\n const a = args(existing.trim());\n const b = args(candidate.trim());\n return !!a && !!b && a[0] === b[0] && a[1] === b[1];\n}\n\n/** Levenshtein distance, for ranking what else this API offers. */\nfunction editDistance(a: string, b: string): number {\n let previous = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n previous[j] + 1,\n current[j - 1] + 1,\n previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)\n );\n }\n previous = current;\n }\n return previous[b.length];\n}\n\nconst NEAREST_SHOWN = 5;\n\n/**\n * The comment that sits on the provisional catalog entry — the durable flag,\n * next to the cast, in the file a later reader opens to find out what this model\n * calls. Names the removal steps so nobody has to reconstruct them.\n */\nfunction provisionalEntryComment(\n servicePath: string,\n method: string,\n catalogName: string\n): string {\n return `/**\n * PROVISIONAL — \\`${method.toUpperCase()} ${servicePath}\\` is NOT in this project's\n * generated OpenAPI types. \\`as ApiPath\\` is standing in for a \\`paths\\` entry that\n * does not exist, so nothing about this endpoint is checked against a spec and\n * its response cannot be derived from one. Do not read this as a real endpoint.\n *\n * WHEN THE ENDPOINT LANDS:\n * 1. regenerate this project's API types (\\`kosui api:generate\\`)\n * 2. delete \\` as ApiPath\\` from the entry below\n * 3. point the endpoint's \\`…Raw\\` alias at\n * \\`EndpointResponse<typeof ${catalogName}.…>\\`\n * 4. swap \\`provisionalServiceRequest\\` for \\`serviceRequest\\` in the model\n * 5. delete the model's \\`mocks/\\` module\n * 6. KEEP the transform — it is real code and survives all of the above\n */\n`;\n}\n\n/** The flag on the method itself, where the request is read. */\nfunction provisionalMethodDocs(servicePath: string, method: string): string {\n return [\n `PROVISIONAL — \\`${method.toUpperCase()} ${servicePath}\\` is not in the`,\n \"generated OpenAPI types, so this request is served by a KosMock route, not\",\n \"by the device. The feature it backs is NOT complete: report the missing\",\n \"endpoint rather than treating this as finished.\",\n \"\",\n \"See the endpoint's entry in `./services` for what to undo when it lands.\",\n ].join(\"\\n\");\n}\n\n/** Doc for the hand-written wire type a provisional endpoint has to declare. */\nfunction rawTypeDocs(\n servicePath: string,\n method: string,\n rawType?: string\n): string {\n const shape = rawType\n ? [\n \"Stated by hand and unverified: there is no spec entry to check it\",\n \"against.\",\n ]\n : [\n \"TODO: state the shape the backend is expected to serve. `unknown`\",\n \"compiles, but leaves the response boundary undescribed and the\",\n \"transform with nothing to narrow.\",\n ];\n return [\n `Raw wire shape of \\`${method.toUpperCase()} ${servicePath}\\` — the UNWRAPPED`,\n \"`data` payload, since the client strips the `{status, data}` envelope\",\n \"before the transform runs.\",\n \"\",\n ...shape,\n \"\",\n \"Replace with `EndpointResponse<…>` once the endpoint is in the generated\",\n \"types.\",\n ].join(\"\\n\");\n}\n\n/**\n * What has to be undone, in order, once the endpoint exists. Returned rather\n * than only written into comments so the caller can put it in front of whoever\n * asked, at the moment they still remember why the mock is there.\n */\nfunction removalSteps(spec: {\n modelProject: string;\n servicePath: string;\n method: string;\n catalogName: string;\n endpointKey: string;\n servicesFilePath: string;\n mocksFilePath?: string;\n mapperName: string;\n}): string[] {\n return [\n `Regenerate the API types for ${\n spec.modelProject\n } (generate_api_types), and confirm ${spec.method.toUpperCase()} ${\n spec.servicePath\n } is now in them.`,\n `In ${spec.servicesFilePath}: delete \\` as ApiPath\\` from \\`${spec.catalogName}.${spec.endpointKey}\\`.`,\n `In ${spec.servicesFilePath}: point the endpoint's \\`…Raw\\` alias at \\`EndpointResponse<typeof ${spec.catalogName}.${spec.endpointKey}>\\` and drop the hand-written shape.`,\n `In the model: swap \\`provisionalServiceRequest\\` for \\`serviceRequest\\` and drop its explicit type arguments — the response type comes from the spec again.`,\n spec.mocksFilePath\n ? `Delete ${spec.mocksFilePath} (and the call to its register function in the app) once no provisional endpoint is left in it.`\n : `Delete the model's mocks module once no provisional endpoint is left in it.`,\n `KEEP \\`${spec.mapperName}\\` and the data type it produces. The transform is real code; it is what let the model read the final shape all along.`,\n ];\n}\n\n/**\n * Refuse a path the generated types do not declare.\n *\n * The nearest paths are listed because \"which of these did you mean\" is\n * occasionally the answer — but they are labelled as OTHER endpoints, because\n * usually it is not. TypeScript's own TS2820 makes the opposite bet, offering\n * the nearest string as a correction, and an agent that takes it wires the model\n * to an unrelated feature's API and compiles clean.\n */\nfunction untypedEndpointError(spec: {\n servicePath: string;\n method: string;\n modelProject: string;\n operations: ServiceOperation[];\n}): UntypedEndpointError {\n const methodsForPath = spec.operations\n .filter((op) => op.path === spec.servicePath)\n .map((op) => op.method);\n const pathTypedForOtherMethods = methodsForPath.length > 0;\n\n const nearest = [...new Set(spec.operations.map((op) => op.path))]\n .sort(\n (a, b) =>\n editDistance(a, spec.servicePath) - editDistance(b, spec.servicePath)\n )\n .slice(0, NEAREST_SHOWN);\n\n const waysForward = [\n `The endpoint EXISTS on the device but this project has not pulled types for it: re-run api:generate (generate_api_types) for ${spec.modelProject}, then add the request unchanged. Confirm on the device first — kos-device search_services / describe_endpoint — since the live OpenAPI is what says whether it exists.`,\n `The endpoint DOES NOT EXIST yet: pass mock:\"auto\" (the default) or mock:\"always\" to emit the provisional, mock-backed form — real decorator, lifecycle, error-first handler and transform, with a KosMock route standing in for the wire response.`,\n `What is NOT supported: falling back to resolveServiceUrl / ServiceFactory.build / getAll to make the UI render. That compiles and looks finished, which is worse than the hole. A missing endpoint is a blocker to report, not a licence to route around the generated service layer.`,\n ];\n\n const message = pathTypedForOtherMethods\n ? `${spec.method.toUpperCase()} ${\n spec.servicePath\n } is not in the generated OpenAPI types for ${\n spec.modelProject\n } — the path is typed, but only for: ${methodsForPath\n .map((m) => m.toUpperCase())\n .join(\", \")}.`\n : `${spec.method.toUpperCase()} ${\n spec.servicePath\n } is not in the generated OpenAPI types for ${\n spec.modelProject\n } — the path is absent entirely. Nothing was written.`;\n\n const error = new Error(message) as UntypedEndpointError;\n error.details = {\n servicePath: spec.servicePath,\n method: spec.method,\n pathTypedForOtherMethods,\n methodsForPath,\n otherEndpointsInThisApi: nearest,\n warning:\n \"These are OTHER endpoints in this API, listed only so they can be ruled out — they are almost certainly NOT what you want. Do not substitute one for the requested path because the strings look similar.\",\n waysForward,\n };\n return error;\n}\n\nexport function addServiceRequestToModel(\n codegenFs: CodegenFileSystem,\n options: AddServiceRequestOptions,\n projects?: Map<string, ProjectConfiguration>\n): AddServiceRequestResult {\n const logger = getCodegenLogger();\n const { modelFilePath, sourceRoot } = resolveModelFilePath(\n codegenFs,\n options,\n projects\n );\n if (!codegenFs.exists(modelFilePath)) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n // Resolve the generated service module as a ROOT-RELATIVE path first: the\n // model and the services module sit at different depths, so each needs its own\n // specifier and neither can be derived from the other's.\n let serviceModuleFile: string | undefined;\n if (options.serviceModulePath) {\n serviceModuleFile = options.serviceModulePath.replace(/\\.ts$/, \"\");\n } else if (options.serviceModule) {\n serviceModuleFile = fromImportSpecifier(\n modelFilePath,\n options.serviceModule\n );\n } else {\n if (!sourceRoot) {\n throw new Error(\n \"Cannot auto-resolve the service module without a project source root. Pass serviceModule.\"\n );\n }\n const modules = findServiceModules(codegenFs, sourceRoot);\n if (modules.length === 0) {\n throw new Error(\n \"No generated service module found. Run `kosui api:generate` for this project first.\"\n );\n }\n if (modules.length > 1) {\n const specifiers = modules.map((m) =>\n toImportSpecifier(modelFilePath, m.replace(/\\.ts$/, \"\"))\n );\n throw new Error(\n `Multiple service modules found — pass serviceModule (one of): ${specifiers.join(\n \", \"\n )}`\n );\n }\n serviceModuleFile = modules[0].replace(/\\.ts$/, \"\");\n }\n\n assertServiceModuleAcceptsTransform(\n codegenFs,\n serviceModuleFile,\n options.modelProject\n );\n\n const modelBase = modelBaseName(modelFilePath, options.modelName);\n const servicesFilePath = servicesFilePathFor(modelFilePath, modelBase);\n\n const serviceImportFromModel = toImportSpecifier(\n modelFilePath,\n serviceModuleFile\n );\n const serviceImportFromServices = toImportSpecifier(\n servicesFilePath,\n serviceModuleFile\n );\n\n const method = (options.method || \"get\").toLowerCase();\n const mode: ServiceRequestMode =\n options.mode ?? (options.lifecycle ? \"lifecycle\" : \"method\");\n assertLifecycleSuitsMethod(method, mode, options.methodName);\n const lifecycle = options.lifecycle || \"LOAD\";\n const catalogName = `${pascalCase(modelBase)}Endpoints`;\n\n // ---- does the endpoint exist? --------------------------------------------\n // Two independent questions, deliberately not conflated: whether the endpoint\n // is TYPED decides the shape of the request, and whether to MOCK decides\n // whether a route is written. A typed endpoint asked to mock keeps its typed\n // request and merely gains a stand-in response.\n const mockMode: ServiceRequestMockMode = options.mock ?? \"auto\";\n const operations = readServiceModuleOperations(codegenFs, serviceModuleFile);\n const pathValidated = operations !== null;\n const operationTyped =\n operations === null ||\n operations.some(\n (op) => op.path === options.servicePath && op.method === method\n );\n\n if (!operationTyped && mockMode === \"never\") {\n throw untypedEndpointError({\n servicePath: options.servicePath,\n method,\n modelProject: options.modelProject,\n operations: operations ?? [],\n });\n }\n\n const provisional = !operationTyped;\n const writeMock = provisional || mockMode === \"always\";\n\n if (provisional) {\n assertServiceModuleAcceptsProvisional(\n codegenFs,\n serviceModuleFile,\n options.modelProject\n );\n }\n\n logger.info(\n `Adding ${mode}-driven ${\n provisional ? \"PROVISIONAL \" : \"\"\n }@kosServiceRequest \"${options.methodName}\" (${method} ${\n options.servicePath\n }) to ${options.modelName}`\n );\n if (provisional) {\n logger.warn(\n `${method.toUpperCase()} ${options.servicePath} is not in ${\n options.modelProject\n }'s generated OpenAPI types — emitting the ` +\n `provisional, mock-backed form. The feature is NOT complete until the endpoint lands.`\n );\n }\n\n // ---- the model's services module: the endpoint and the types from it ----\n ensureServicesModule(codegenFs, modelFilePath, modelBase);\n\n let endpointKey = options.methodName;\n let endpointCreated = true;\n // Everything the endpoint implies — its normalized shape, the mapper that\n // normalizes it, and the context type carrying that shape — belongs to the\n // ENDPOINT, not to whichever method happens to call it. Normalization is a\n // property of the service response, so a second method on the same endpoint\n // shares all three rather than declaring a parallel set that could drift.\n // These are keyed off the resolved catalog entry, so they are filled in once\n // it is known.\n let dataAlias = \"\";\n let mapperName = \"\";\n let ctxAlias = \"\";\n let rawAlias = \"\";\n\n transformSourceFile(codegenFs, servicesFilePath, (sf) => {\n ensureNamedImport(sf, serviceImportFromServices, [{ name: \"endpoint\" }]);\n if (provisional) {\n ensureNamedImport(sf, serviceImportFromServices, [\n { name: \"ApiPath\", isTypeOnly: true },\n ]);\n }\n\n // The cast is the whole marker: one token, in the one place the path is\n // written, that says the generated types do not back this. Deleting it is\n // the first step of undoing the provisional form, and it is what fails to\n // compile if the path is still absent when someone tries.\n const pathText = provisional\n ? `${JSON.stringify(options.servicePath)} as ApiPath`\n : JSON.stringify(options.servicePath);\n\n const entry = ensureConstCatalogEntry(sf, {\n catalogName,\n key: options.methodName,\n initializer: `endpoint(${pathText}, ${JSON.stringify(method)})`,\n equals: sameEndpoint,\n leadingTrivia: provisional\n ? provisionalEntryComment(options.servicePath, method, catalogName)\n : undefined,\n });\n endpointKey = entry.key;\n endpointCreated = entry.created;\n dataAlias = `${pascalCase(endpointKey)}Data`;\n mapperName = `to${pascalCase(endpointKey)}Data`;\n ctxAlias = `${pascalCase(endpointKey)}Ctx`;\n rawAlias = `${pascalCase(endpointKey)}Raw`;\n\n // Everything below reads the path back through `typeof`, so no type can\n // drift from the descriptor even though each is declared separately — except\n // for a provisional endpoint, where there is no schema entry to read back\n // and the wire shape is stated by hand instead.\n let rawType: string;\n if (provisional) {\n ensureExportedTypeAlias(sf, {\n name: rawAlias,\n type: options.rawType || \"unknown\",\n docs: rawTypeDocs(options.servicePath, method, options.rawType),\n });\n rawType = rawAlias;\n } else {\n rawType = `EndpointResponse<typeof ${catalogName}.${endpointKey}>`;\n ensureNamedImport(sf, serviceImportFromServices, [\n { name: \"EndpointResponse\", isTypeOnly: true },\n ]);\n // A mock has to be typed by what the WIRE carries, never by the mapper's\n // output — the two are the same only until someone narrows the data type,\n // and a sample typed by the narrowed shape would stop matching the\n // endpoint it stands in for. So a typed endpoint being mocked gets the\n // raw shape named too, and the mock imports that.\n if (writeMock) {\n ensureExportedTypeAlias(sf, {\n name: rawAlias,\n type: rawType,\n docs: `Raw wire shape of \\`${method.toUpperCase()} ${\n options.servicePath\n }\\`, as the spec declares it — what a mock for this endpoint must serve.`,\n });\n }\n }\n\n // The mapper is where the response stops being the wire shape and starts\n // being the model's. It is emitted as an identity so the project compiles\n // untouched; narrowing the data type is what turns it into a real boundary,\n // and the compiler then walks the author through filling it in.\n //\n // It is also the one thing that survives the endpoint landing untouched,\n // which is why the model reads its output and never the raw bean.\n ensureExportedTypeAlias(sf, { name: dataAlias, type: rawType });\n ensureExportedMapper(sf, {\n name: mapperName,\n rawType,\n dataType: dataAlias,\n });\n\n if (mode === \"method\") {\n ensureNamedImport(sf, serviceImportFromServices, [\n { name: \"EndpointCtx\", isTypeOnly: true },\n ]);\n ensureExportedTypeAlias(sf, {\n name: ctxAlias,\n type: `EndpointCtx<typeof ${catalogName}.${endpointKey}, ${dataAlias}>`,\n });\n }\n });\n\n // ---- the model: imports and the decorated method, nothing declared ----\n transformSourceFile(codegenFs, modelFilePath, (sf) => {\n // EVERY file-level write below (eslint pragma, imports, the merged\n // interface) re-writes the file text, which makes ts-morph forget nodes\n // captured before it. So all of them happen first, and the class is looked\n // up only once nothing else will move underneath it.\n const className = getModelClass(sf).getName();\n if (!className) throw new Error(\"Model class has no name.\");\n const typeParams = getModelClass(sf)\n .getTypeParameters()\n .map((tp) => tp.getText());\n\n // A provisional endpoint has no schema to derive a response from, so the\n // request goes through `provisionalServiceRequest` with the wire shape\n // stated explicitly. The decorator's NAME is the flag at the call site: a\n // later reader (or agent) cannot mistake this method for one backed by the\n // spec, and `grep provisionalServiceRequest` finds every such debt.\n const decoratorName = provisional\n ? \"provisionalServiceRequest\"\n : \"serviceRequest\";\n const decoratorTypeArgs = provisional ? [rawAlias, dataAlias] : undefined;\n ensureNamedImport(sf, serviceImportFromModel, [{ name: decoratorName }]);\n\n if (mode === \"lifecycle\") {\n ensureNamedImport(sf, \"./services\", [\n { name: catalogName },\n { name: mapperName },\n { name: dataAlias, isTypeOnly: true },\n ...(provisional ? [{ name: rawAlias, isTypeOnly: true }] : []),\n ]);\n ensureNamedImport(sf, resolveSdkModuleSpecifier(sf), [\n { name: \"DependencyLifecycle\" },\n ]);\n addDecoratedMethod(getModelClass(sf), {\n name: options.methodName,\n decoratorName,\n decoratorTypeArgs,\n decoratorArgsText: `${catalogName}.${endpointKey}, { lifecycle: DependencyLifecycle.${lifecycle}, transform: ${mapperName} }`,\n docs: provisional\n ? provisionalMethodDocs(options.servicePath, method)\n : undefined,\n // The manager invokes phase handlers error-first, passing (null, data)\n // on success. The `error` half is only ever reached because\n // `serviceRequest` supplies an errorHandler — the bare decorator\n // defaults to `throw`, which fails the phase instead of calling back.\n parameters: [\n { name: \"error\", type: \"string | null\" },\n { name: \"data\", type: dataAlias },\n ],\n returnType: \"void\",\n statements: \"// TODO: apply `data` to the model\",\n });\n return;\n }\n\n ensureNamedImport(sf, \"./services\", [\n { name: catalogName },\n { name: mapperName },\n { name: ctxAlias, isTypeOnly: true },\n ...(provisional\n ? [\n { name: rawAlias, isTypeOnly: true },\n { name: dataAlias, isTypeOnly: true },\n ]\n : []),\n ]);\n ensureNamedImport(sf, resolveSdkModuleSpecifier(sf), [\n { name: \"executeServiceRequest\" },\n { name: \"kosLoggerAware\" },\n { name: \"KosLoggerAware\", isTypeOnly: true },\n ]);\n\n // executeServiceRequest reports failures through the model's logger, so the\n // model has to be logger-aware for the emitted call to compile at all.\n ensureFileEslintDisable(\n sf,\n \"@typescript-eslint/no-unsafe-declaration-merging\"\n );\n ensureDeclarationMerge(sf, className, \"KosLoggerAware\", typeParams);\n addClassDecorator(getModelClass(sf), \"kosLoggerAware\", { argsText: \"\" });\n\n addDecoratedMethod(getModelClass(sf), {\n name: options.methodName,\n decoratorName,\n decoratorTypeArgs,\n decoratorArgsText: `${catalogName}.${endpointKey}, { transform: ${mapperName} }`,\n docs: provisional\n ? provisionalMethodDocs(options.servicePath, method)\n : undefined,\n // Optional: the framework appends the context, callers never pass it.\n parameters: [{ name: \"$ctx\", type: ctxAlias, optional: true }],\n isAsync: true,\n returnType: \"Promise<void>\",\n statements: [\n \"const data = await executeServiceRequest(this, $ctx);\",\n \"if (!data) return;\",\n \"// TODO: apply `data` to the model\",\n ].join(\"\\n\"),\n });\n });\n\n // ---- the mock route, when the wire response has to be stood in for --------\n const mock = writeMock\n ? ensureMockRoute(codegenFs, {\n modelFilePath,\n modelBase,\n sdkModuleSpecifier: readSourceFile(\n codegenFs,\n modelFilePath,\n resolveSdkModuleSpecifier\n ),\n rawAlias,\n servicePath: options.servicePath,\n method,\n endpointKey,\n sampleText: options.sample,\n })\n : undefined;\n\n return {\n modelFilePath,\n servicesFilePath,\n serviceModule: serviceImportFromModel,\n mode,\n endpointKey,\n endpointCreated,\n pathValidated,\n provisional,\n mocksFilePath: mock?.mocksFilePath,\n mockRegisterFunction: mock?.registerFunction,\n mockRoute: mock && `${method.toUpperCase()} ${mock.routePattern}`,\n mockSamplePlaceholder: mock?.samplePlaceholder,\n removalSteps: provisional\n ? removalSteps({\n modelProject: options.modelProject,\n servicePath: options.servicePath,\n method,\n catalogName,\n endpointKey,\n servicesFilePath,\n mocksFilePath: mock?.mocksFilePath,\n mapperName,\n })\n : undefined,\n };\n}\n","/**\n * Resolve an exported SDK symbol to its signature, so an agent (especially a\n * consumer building models) never hallucinates a type's shape. AST-based\n * (ts-morph); confined here in codegen-core, never a runtime SDK dep.\n *\n * Graceful resolution, in priority order:\n * 1. Monorepo SOURCE — the SDK project's `src/index.ts` (source of truth).\n * 2. Installed DECLARATIONS — `node_modules/<pkg>` `exports[\".\"].*.types` /\n * `types` entry (a consumer workspace only has this built `.d.ts`).\n * 3. Neither present → a clear \"not resolvable\" result (no throw).\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { Project, Node, type ExportedDeclarations } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../project-discovery\";\n\nconst DEFAULT_SDK_PACKAGE = \"@kosdev-code/kos-ui-sdk\";\nconst MAX_SIGNATURE_CHARS = 2000;\n\nexport interface LookupSdkTypeOptions {\n symbol: string;\n /** SDK package name. Default @kosdev-code/kos-ui-sdk. */\n sdkPackage?: string;\n /** Explicit entry file (absolute or workspace-relative), overriding resolution. */\n entryFile?: string;\n}\n\nexport interface SdkSymbolDeclaration {\n kind: string;\n /** Declaring file, workspace-relative when under root. */\n file: string;\n /** Signature text (bodies stripped, length-capped). */\n signature: string;\n}\n\nexport interface SdkTypeLookupResult {\n symbol: string;\n resolved: boolean;\n /** Which surface answered: the SDK source tree or the installed declarations. */\n mode?: \"source\" | \"declarations\";\n entryFile?: string;\n declarations: SdkSymbolDeclaration[];\n /** Set when not resolved (or partially) — explains what was tried. */\n message?: string;\n triedEntries: string[];\n}\n\n/** Read a package's TS-declaration entry from its package.json exports/types. */\nfunction declarationEntryFromPackageJson(pkgDir: string): string | undefined {\n const pkgJsonPath = path.join(pkgDir, \"package.json\");\n if (!fs.existsSync(pkgJsonPath)) return undefined;\n let pkg: any;\n try {\n pkg = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf-8\"));\n } catch {\n return undefined;\n }\n const candidates: Array<string | undefined> = [\n pkg.exports?.[\".\"]?.import?.types,\n pkg.exports?.[\".\"]?.require?.types,\n pkg.exports?.[\".\"]?.types,\n pkg.types,\n pkg.typings,\n ];\n for (const rel of candidates) {\n if (typeof rel === \"string\") {\n const abs = path.join(pkgDir, rel);\n if (fs.existsSync(abs)) return abs;\n }\n }\n return undefined;\n}\n\n/** Build the ordered list of candidate entry files (absolute paths). */\nfunction resolveCandidateEntries(\n codegenFs: CodegenFileSystem,\n options: LookupSdkTypeOptions,\n projects?: Map<string, ProjectConfiguration>\n): Array<{ file: string; mode: \"source\" | \"declarations\" }> {\n const root = codegenFs.root;\n const sdkPackage = options.sdkPackage || DEFAULT_SDK_PACKAGE;\n const out: Array<{ file: string; mode: \"source\" | \"declarations\" }> = [];\n\n if (options.entryFile) {\n const abs = path.isAbsolute(options.entryFile)\n ? options.entryFile\n : path.join(root, options.entryFile);\n out.push({\n file: abs,\n mode: abs.endsWith(\".d.ts\") ? \"declarations\" : \"source\",\n });\n }\n\n // 1. Monorepo source — the SDK project's src/index.ts.\n const sdkProject = findProjectByName(root, sdkPackage, projects);\n const sourceRoot = sdkProject\n ? sdkProject.sourceRoot || path.join(sdkProject.root, \"src\")\n : undefined;\n for (const srcDir of [\n sourceRoot && path.join(root, sourceRoot),\n path.join(root, \"packages\", \"kos-ui-sdk\", \"src\"),\n ]) {\n if (!srcDir) continue;\n const entry = path.join(srcDir, \"index.ts\");\n if (fs.existsSync(entry) && !out.some((c) => c.file === entry)) {\n out.push({ file: entry, mode: \"source\" });\n }\n }\n\n // 2. Installed declarations — node_modules/<pkg> types entry.\n const dts = declarationEntryFromPackageJson(\n path.join(root, \"node_modules\", ...sdkPackage.split(\"/\"))\n );\n if (dts && !out.some((c) => c.file === dts)) {\n out.push({ file: dts, mode: \"declarations\" });\n }\n\n return out;\n}\n\n/**\n * Render an object-like type as a member list via the type checker. KOS model\n * interfaces are utility-wrapped aliases — e.g. `type KosTimeModel =\n * PublicModelInterface<KosTimeModelImpl>` — so the verbatim declaration text is\n * just the unevaluated alias and carries NO members. Resolving the type expands\n * the projection (public members, private/@internal already stripped by\n * `PublicModelInterface<T>`) into the real surface: `timezone`,\n * `updateSystemTimezone(...)`, etc. Returns undefined for non-object types\n * (unions, primitives, generics with unresolved params) so the caller falls back\n * to the literal text, which is clearer for those.\n */\nfunction renderTypeMembers(\n decl: ExportedDeclarations & { getType: () => import(\"ts-morph\").Type }\n): string | undefined {\n const props = decl.getType().getProperties();\n if (props.length === 0) return undefined;\n const lines: string[] = [];\n for (const p of props) {\n const at = p.getDeclarations()[0] ?? decl;\n let pt: string;\n try {\n pt = p.getTypeAtLocation(at).getText(at);\n } catch {\n pt = \"unknown\";\n }\n lines.push(` ${p.getName()}: ${pt};`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Strip method/function bodies and length-cap a declaration's text. */\nfunction signatureText(decl: ExportedDeclarations): string {\n let text: string;\n if (Node.isTypeAliasDeclaration(decl) || Node.isInterfaceDeclaration(decl)) {\n // Resolve to members so utility-wrapped model interfaces yield their real\n // shape in ONE lookup (no jump from the bean to the model alias to the impl).\n const members = renderTypeMembers(decl);\n if (members) {\n const name = decl.getName();\n const tps = decl.getTypeParameters().map((t) => t.getText());\n const head = tps.length ? `${name}<${tps.join(\", \")}>` : name;\n const kw = Node.isInterfaceDeclaration(decl) ? \"interface\" : \"type\";\n const open = Node.isInterfaceDeclaration(decl) ? \" {\" : \" = {\";\n text = `${kw} ${head}${open}\\n${members}\\n}`;\n } else {\n text = decl.getText();\n }\n } else if (Node.isEnumDeclaration(decl)) {\n text = decl.getText();\n } else if (Node.isVariableDeclaration(decl)) {\n // Avoid dumping a large initializer — show the inferred type instead.\n const name = decl.getName();\n const typeText = decl.getType().getText(decl);\n text = `const ${name}: ${typeText}`;\n } else if (Node.isFunctionDeclaration(decl)) {\n if (decl.getBody()) decl.removeBody();\n text = decl.getText();\n } else if (Node.isClassDeclaration(decl)) {\n // Show the PUBLIC surface — drop private/protected members so the useful\n // public API fits the cap, and strip method/constructor bodies.\n const isHidden = (member: { getScope?: () => string }): boolean =>\n typeof member.getScope === \"function\" && member.getScope() !== \"public\";\n for (const p of decl.getProperties()) if (isHidden(p)) p.remove();\n for (const a of [...decl.getGetAccessors(), ...decl.getSetAccessors()]) {\n if (isHidden(a)) a.remove();\n }\n for (const m of decl.getMethods()) {\n if (isHidden(m)) {\n m.remove();\n continue;\n }\n if (m.getBody()) m.removeBody();\n }\n for (const c of decl.getConstructors()) {\n if (c.getBody()) c.removeBody();\n }\n text = decl.getText();\n } else {\n text = decl.getText();\n }\n text = text.replace(/\\s+$/, \"\");\n if (text.length > MAX_SIGNATURE_CHARS) {\n text = text.slice(0, MAX_SIGNATURE_CHARS) + \"\\n/* … truncated */\";\n }\n return text;\n}\n\nexport function lookupSdkType(\n codegenFs: CodegenFileSystem,\n options: LookupSdkTypeOptions,\n projects?: Map<string, ProjectConfiguration>\n): SdkTypeLookupResult {\n const symbol = options.symbol;\n const candidates = resolveCandidateEntries(codegenFs, options, projects);\n const triedEntries = candidates.map((c) =>\n path.relative(codegenFs.root, c.file)\n );\n\n if (candidates.length === 0) {\n return {\n symbol,\n resolved: false,\n declarations: [],\n triedEntries,\n message:\n \"No SDK entry found — neither the SDK source (packages/kos-ui-sdk/src/index.ts) nor an installed declaration file (node_modules/@kosdev-code/kos-ui-sdk) is present. Build or install the SDK, or pass entryFile.\",\n };\n }\n\n const project = new Project({\n skipAddingFilesFromTsConfig: true,\n compilerOptions: { allowJs: false, skipLibCheck: true },\n });\n\n for (const candidate of candidates) {\n let sf;\n try {\n sf = project.addSourceFileAtPath(candidate.file);\n } catch {\n continue;\n }\n let exported: ReadonlyMap<string, ExportedDeclarations[]>;\n try {\n exported = sf.getExportedDeclarations();\n } catch {\n continue;\n }\n const decls = exported.get(symbol);\n if (!decls || decls.length === 0) continue;\n\n return {\n symbol,\n resolved: true,\n mode: candidate.mode,\n entryFile: path.relative(codegenFs.root, candidate.file),\n triedEntries,\n declarations: decls.map((d) => {\n return {\n kind: d.getKindName(),\n file: path.relative(codegenFs.root, d.getSourceFile().getFilePath()),\n signature: signatureText(d),\n };\n }),\n };\n }\n\n return {\n symbol,\n resolved: false,\n declarations: [],\n triedEntries,\n message: `Symbol '${symbol}' is not an export of the SDK entry (${triedEntries.join(\n \", \"\n )}). Check the name, or it may be internal / not part of the public surface.`,\n };\n}\n","/**\n * Read-only static validation of a KOS model against best-practice guardrails.\n * AST-based (ts-morph), high-signal / low-false-positive — a few reliable checks\n * beat many noisy ones. Mirrors the AGENTS.md guardrails + anti-patterns guide.\n */\nimport { Project } from \"ts-morph\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { resolveModelFilePath } from \"../augment/resolve-model-file\";\n\nexport interface ValidateModelOptions {\n modelName: string;\n modelProject: string;\n modelPath?: string;\n}\n\nexport interface ValidationFinding {\n level: \"error\" | \"warning\";\n rule: string;\n message: string;\n}\n\nexport interface ValidationResult {\n modelFilePath: string;\n ok: boolean; // no errors (warnings allowed)\n findings: ValidationFinding[];\n}\n\n/** Extract a `*Model`-named element type from a raw collection type, else null. */\nfunction modelElementType(typeText: string): string | null {\n let m: RegExpMatchArray | null;\n if ((m = typeText.match(/^([A-Za-z_]\\w*Model)\\s*\\[\\]$/))) return m[1];\n if ((m = typeText.match(/^Array<\\s*([A-Za-z_]\\w*Model)\\s*>$/))) return m[1];\n if ((m = typeText.match(/^(?:Map|Set)<[^>]*?\\b([A-Za-z_]\\w*Model)\\b[^>]*>$/)))\n return m[1];\n return null;\n}\n\nexport function validateModel(\n codegenFs: CodegenFileSystem,\n options: ValidateModelOptions,\n projects?: Map<string, ProjectConfiguration>\n): ValidationResult {\n const { modelFilePath } = resolveModelFilePath(codegenFs, options, projects);\n const content = codegenFs.read(modelFilePath);\n if (content === null) {\n throw new Error(`Model file not found: ${modelFilePath}`);\n }\n\n const project = new Project({ useInMemoryFileSystem: true });\n const sf = project.createSourceFile(modelFilePath, content, {\n overwrite: true,\n });\n const findings: ValidationFinding[] = [];\n\n // 1. Must be a KOS model.\n const hasKosModel = sf.getClasses().some((c) => c.getDecorator(\"kosModel\"));\n if (!hasKosModel) {\n findings.push({\n level: \"error\",\n rule: \"missing-kosModel\",\n message: \"No @kosModel decorator found — this is not a KOS model.\",\n });\n }\n\n const imports = sf.getImportDeclarations();\n\n // 2. No direct MobX — reactivity is internal to KOS.\n const mobxImport = imports.find((d) =>\n /^mobx(-react-lite)?$/.test(d.getModuleSpecifierValue())\n );\n if (mobxImport) {\n findings.push({\n level: \"error\",\n rule: \"mobx-import\",\n message:\n \"Imports mobx directly. Reactivity is internal to KOS — remove the mobx import and use KOS reactivity / container models.\",\n });\n }\n\n // 3. Service requests should use the typed decorator from the api:generate'd\n // service module, not the untyped one from the SDK barrel.\n const barrelServiceRequest = imports.find(\n (d) =>\n d.getModuleSpecifierValue() === \"@kosdev-code/kos-ui-sdk\" &&\n d.getNamedImports().some((n) => n.getName() === \"kosServiceRequest\")\n );\n if (barrelServiceRequest) {\n findings.push({\n level: \"warning\",\n rule: \"untyped-service-request\",\n message:\n \"kosServiceRequest imported from the SDK barrel. Use the typed decorator from the api:generate'd service module so paths are validated against the OpenAPI types.\",\n });\n }\n\n // 4. Model collections should be KOS containers + enrolled as children.\n for (const cls of sf.getClasses()) {\n for (const prop of cls.getProperties()) {\n const name = prop.getName();\n const typeText = (prop.getTypeNode()?.getText() ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n const initText = prop.getInitializer()?.getText() ?? \"\";\n const hasChild = !!prop.getDecorator(\"kosChild\");\n\n const isModelContainer =\n /\\bI?KosModelContainer\\s*</.test(typeText) ||\n /new\\s+KosModelContainer\\b/.test(initText);\n\n if (isModelContainer && !hasChild) {\n findings.push({\n level: \"warning\",\n rule: \"container-missing-kosChild\",\n message: `Property '${name}' is a model container but is not marked @kosChild — add @kosChild so its models join the model graph and lifecycle.`,\n });\n continue;\n }\n\n const elem = modelElementType(typeText);\n if (elem && !isModelContainer) {\n findings.push({\n level: \"warning\",\n rule: \"raw-model-collection\",\n message: `Property '${name}' is a raw ${typeText} of models — prefer a KosModelContainer<${elem}> (indexing, sorting, lifecycle, delta handling) marked @kosChild.`,\n });\n }\n }\n }\n\n const hasError = findings.some((f) => f.level === \"error\");\n return { modelFilePath, ok: !hasError, findings };\n}\n","/**\n * Type definitions for KOS Component Generator\n */\n\n// Plugin type constants\nexport const PLUGIN_TYPES = {\n CUI: \"cui\",\n UTILITY: \"utility\",\n TROUBLE_ACTION: \"troubleAction\",\n SETUP: \"setup\",\n SETTING: \"setting\",\n NAV: \"nav\",\n CONTROL_POUR: \"controlPour\",\n CUSTOM: \"custom\",\n} as const;\n\nexport type PluginType = (typeof PLUGIN_TYPES)[keyof typeof PLUGIN_TYPES];\n\n// Contribution type mapping\nexport const CONTRIBUTION_TYPE_MAP: Record<string, string> = {\n [PLUGIN_TYPES.SETUP]: \"setup\",\n [PLUGIN_TYPES.CUI]: \"cui\",\n [PLUGIN_TYPES.UTILITY]: \"utility\",\n [PLUGIN_TYPES.SETTING]: \"setting\",\n [PLUGIN_TYPES.NAV]: \"nav\",\n [PLUGIN_TYPES.TROUBLE_ACTION]: \"trouble-action\",\n [PLUGIN_TYPES.CONTROL_POUR]: \"control-pour\",\n [PLUGIN_TYPES.CUSTOM]: \"custom\",\n};\n\n// Plugin types that require localization\nexport const LOCALIZED_PLUGIN_TYPES: ReadonlySet<string> = new Set([\n PLUGIN_TYPES.CUI,\n PLUGIN_TYPES.UTILITY,\n PLUGIN_TYPES.SETUP,\n PLUGIN_TYPES.SETTING,\n PLUGIN_TYPES.NAV,\n PLUGIN_TYPES.CONTROL_POUR,\n PLUGIN_TYPES.TROUBLE_ACTION,\n PLUGIN_TYPES.CUSTOM,\n]);\n\n// Configuration interfaces\nexport interface ExperienceConfig {\n id: string;\n component: string;\n location: string;\n}\n\nexport interface PluginContribution {\n id: string;\n title: string;\n namespace: string;\n experienceId?: string;\n [key: string]: any; // Allow plugin-specific properties\n}\n\nexport interface PluginConfiguration {\n contributions: Record<string, PluginContribution[]>;\n experiences: Record<string, ExperienceConfig>;\n views?: Record<string, any[]>;\n}\n\nexport interface NormalizedComponentOptions {\n name: string;\n nameDashCase: string;\n nameCamelCase: string;\n namePascalCase: string;\n nameLowerCase: string;\n appProject: string;\n group?: string;\n pluginType?: string;\n type: string;\n appDirectory: string;\n useEmotionCss?: boolean;\n contributionKey?: string; // User-specified contribution key for custom plugins\n}\n\n// Component generator input options\nexport interface ComponentOptions {\n name: string;\n type: \"components\" | \"features\";\n useEmotionCss: boolean;\n appProject: string;\n appDirectory: string;\n modelDirectory: string;\n group?: string;\n pluginType?: string;\n contributionKey?: string;\n registrationProject?: string;\n skipRegistration?: boolean;\n companion?: boolean;\n companionModel?: string;\n companionModelProject?: string;\n companionPattern?: \"composition\" | \"decorator\";\n}\n\n// JSON path constants for .kos.json structure\nexport const KOS_JSON_PATHS = {\n PLUGIN_ROOT: \"kosdev.ddk.ncui.plugin\",\n CONTRIBUTES: \"kosdev.ddk.ncui.plugin.contributes\",\n EXPERIENCES: \"kosdev.ddk.ncui.plugin.contributes.experiences\",\n VIEWS: \"kosdev.ddk.ncui.plugin.contributes.views\",\n TAB_VIEW: \"ddk.ncui.settings.tabView\",\n} as const;\n","import {\n ExperienceConfig,\n NormalizedComponentOptions,\n PluginConfiguration,\n} from \"../types\";\n\n/**\n * Base interface for plugin-specific handlers\n */\nexport interface PluginHandler {\n /**\n * Creates the plugin-specific configuration\n */\n createConfiguration(options: NormalizedComponentOptions): PluginConfiguration;\n\n /**\n * Returns the contribution key for this plugin type\n */\n getContributionKey(): string;\n\n /**\n * Checks if this plugin type requires localization\n */\n requiresLocalization(): boolean;\n\n /**\n * Gets the template source path for this plugin type\n */\n getTemplatePath(): string;\n}\n\n/**\n * Base implementation with common functionality\n */\nexport abstract class BasePluginHandler implements PluginHandler {\n protected abstract pluginType: string;\n protected abstract contributionKey: string;\n protected abstract requiresI18n: boolean;\n\n abstract createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration;\n\n getContributionKey(): string {\n return this.contributionKey;\n }\n\n requiresLocalization(): boolean {\n return this.requiresI18n;\n }\n\n getTemplatePath(): string {\n return this.contributionKey;\n }\n\n /**\n * Helper to create experience configuration\n */\n protected createExperience(\n options: NormalizedComponentOptions,\n experienceId: string\n ): ExperienceConfig {\n const compPath = this.getComponentPath(options);\n\n return {\n id: experienceId,\n component: options.namePascalCase,\n location: `./src/${compPath}`,\n };\n }\n\n /**\n * Helper to get component path\n */\n protected getComponentPath(options: NormalizedComponentOptions): string {\n return `${options.appDirectory}/${this.contributionKey}/${options.nameDashCase}/${options.nameDashCase}.tsx`;\n }\n\n /**\n * Helper to create config prefix\n */\n protected getConfigPrefix(options: NormalizedComponentOptions): string {\n return `${options.appProject}.${options.nameCamelCase}`;\n }\n}\n","import {\n NormalizedComponentOptions,\n PLUGIN_TYPES,\n PluginConfiguration,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class ControlPourPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.CONTROL_POUR;\n protected contributionKey = \"control-pour\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.controlPour.experience`;\n\n const contribution = {\n id: `${configPrefix}.controlPour`,\n title: `${configPrefix}.controlPour.title`,\n namespace: options.appProject,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n controlPour: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PLUGIN_TYPES,\n PluginConfiguration,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class CuiPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.CUI;\n protected contributionKey = \"cui\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.cui.experience`;\n\n const contribution = {\n id: configPrefix,\n title: `${configPrefix}.cui.title`,\n namespace: options.appProject,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n cui: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PLUGIN_TYPES,\n PluginConfiguration,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class CustomPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.CUSTOM;\n protected contributionKey = \"custom\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.${\n options.contributionKey || \"custom\"\n }.experience`;\n\n // Get the user-specified contribution key or default to 'custom'\n const userContributionKey = options.contributionKey || \"custom\";\n\n const contribution = {\n id: configPrefix,\n title: `${configPrefix}.${userContributionKey}.title`,\n namespace: options.appProject,\n experienceId,\n // TODO: Add additional fields as required by the plugin-explorer specification\n // Refer to the plugin-explorer documentation for your specific contribution type\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n [userContributionKey]: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n\n override getTemplatePath(): string {\n // Use the generic 'custom' template path\n return this.contributionKey || \"custom\";\n }\n\n protected override getComponentPath(\n options: NormalizedComponentOptions\n ): string {\n // Use the user-specified contribution key for the path if available\n const pathKey = options.contributionKey || \"custom\";\n return `${options.appDirectory}/${pathKey}/${options.nameDashCase}/${options.nameDashCase}.tsx`;\n }\n}\n","import { NormalizedComponentOptions, PluginConfiguration } from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\n/**\n * Default handler for non-plugin components\n */\nexport class DefaultComponentHandler extends BasePluginHandler {\n protected pluginType = \"component\";\n protected contributionKey = \"components\";\n protected requiresI18n = false;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const compPath = this.getComponentPath(options);\n\n const viewConfig = {\n id: `${options.appProject}.${options.nameCamelCase}`,\n title: \"ddk.ncui.config.title\",\n namespace: options.appProject,\n component: options.namePascalCase,\n location: `./src/${compPath}`,\n };\n\n return {\n contributions: {},\n experiences: {},\n views: {\n [this.getTabViewKey()]: [viewConfig],\n },\n };\n }\n\n private getTabViewKey(): string {\n return \"ddk.ncui.settings.tabView\";\n }\n\n override getTemplatePath(): string {\n return \"files\"; // Default template path\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class NavPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.NAV;\n protected contributionKey = \"nav\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.nav.experience`;\n\n const contribution = {\n id: `${configPrefix}.nav`,\n title: `${configPrefix}.nav.title`,\n namespace: options.appProject,\n navDescriptor: options.nameLowerCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n navViews: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class SettingPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.SETTING;\n protected contributionKey = \"setting\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.settings.experience`;\n\n const contribution = {\n id: `${configPrefix}.setting`,\n title: `${configPrefix}.setting.title`,\n namespace: options.appProject,\n settingsGroup: options.group || \"general\",\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n settings: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class SetupPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.SETUP;\n protected contributionKey = \"setup\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.setup.experience`;\n\n const contribution = {\n id: `${configPrefix}.setup`,\n title: `${configPrefix}.setup.title`,\n namespace: options.appProject,\n setupDescriptor: options.nameCamelCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n setupStep: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class TroubleActionPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.TROUBLE_ACTION;\n protected contributionKey = \"trouble-action\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.troubleAction.experience`;\n\n const contribution = {\n id: `${configPrefix}.troubleAction`,\n title: `${configPrefix}.troubleAction.title`,\n namespace: options.appProject,\n troubleType: options.nameCamelCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n troubleActions: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import {\n NormalizedComponentOptions,\n PluginConfiguration,\n PLUGIN_TYPES,\n} from \"../types\";\nimport { BasePluginHandler } from \"./base\";\n\nexport class UtilityPluginHandler extends BasePluginHandler {\n protected pluginType = PLUGIN_TYPES.UTILITY;\n protected contributionKey = \"utility\";\n protected requiresI18n = true;\n\n createConfiguration(\n options: NormalizedComponentOptions\n ): PluginConfiguration {\n const configPrefix = this.getConfigPrefix(options);\n const experienceId = `${configPrefix}.util.experience`;\n\n const contribution = {\n id: `${configPrefix}.util`,\n title: `${configPrefix}.utility.title`,\n namespace: options.appProject,\n utilDescriptor: options.nameCamelCase,\n experienceId,\n };\n\n const experience = this.createExperience(options, experienceId);\n\n return {\n contributions: {\n utilities: [contribution],\n },\n experiences: {\n [experienceId]: experience,\n },\n };\n }\n}\n","import { PLUGIN_TYPES } from \"../types\";\nimport { PluginHandler } from \"./base\";\nimport { ControlPourPluginHandler } from \"./control-pour-handler\";\nimport { CuiPluginHandler } from \"./cui-handler\";\nimport { CustomPluginHandler } from \"./custom-handler\";\nimport { DefaultComponentHandler } from \"./default-handler\";\nimport { NavPluginHandler } from \"./nav-handler\";\nimport { SettingPluginHandler } from \"./setting-handler\";\nimport { SetupPluginHandler } from \"./setup-handler\";\nimport { TroubleActionPluginHandler } from \"./trouble-action-handler\";\nimport { UtilityPluginHandler } from \"./utility-handler\";\n\n/**\n * Factory for creating plugin-specific handlers\n */\nexport class PluginHandlerFactory {\n private static handlers: Map<string, new () => PluginHandler> = new Map<\n string,\n new () => PluginHandler\n >([\n [PLUGIN_TYPES.CUI, CuiPluginHandler],\n [PLUGIN_TYPES.UTILITY, UtilityPluginHandler],\n [PLUGIN_TYPES.SETTING, SettingPluginHandler],\n [PLUGIN_TYPES.SETUP, SetupPluginHandler],\n [PLUGIN_TYPES.NAV, NavPluginHandler],\n [PLUGIN_TYPES.CONTROL_POUR, ControlPourPluginHandler],\n [PLUGIN_TYPES.TROUBLE_ACTION, TroubleActionPluginHandler],\n [PLUGIN_TYPES.CUSTOM, CustomPluginHandler],\n ]);\n\n static createHandler(pluginType?: string): PluginHandler {\n if (!pluginType) {\n return new DefaultComponentHandler();\n }\n\n const HandlerClass = this.handlers.get(pluginType);\n\n if (!HandlerClass) {\n console.warn(\n `No handler found for plugin type: ${pluginType}. Using default handler.`\n );\n return new DefaultComponentHandler();\n }\n\n return new HandlerClass();\n }\n\n static isValidPluginType(type: string): boolean {\n return this.handlers.has(type);\n }\n}\n","import * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport { generateFilesFromTemplates } from \"../../../generate-files\";\nimport { NormalizedComponentOptions } from \"../types\";\n\n/**\n * Generates component files from templates.\n *\n * @param codegenFs - Filesystem abstraction\n * @param templateBaseDir - Absolute path to the base template directory\n * @param templateSubPath - Sub-path from handler (e.g., \"cui\", \"files\")\n * @param targetPath - Destination path relative to workspace root\n * @param options - Normalized component options for template substitution\n */\nexport function generateComponentFiles(\n codegenFs: CodegenFileSystem,\n templateBaseDir: string,\n templateSubPath: string,\n targetPath: string,\n options: NormalizedComponentOptions\n): void {\n generateFilesFromTemplates(\n codegenFs,\n path.join(templateBaseDir, templateSubPath),\n targetPath,\n options\n );\n\n // Handle CSS file deletion if needed\n if (options.useEmotionCss) {\n deleteCssFile(codegenFs, targetPath, options);\n }\n}\n\n/**\n * Deletes the CSS file when using Emotion CSS\n */\nfunction deleteCssFile(\n codegenFs: CodegenFileSystem,\n targetPath: string,\n options: NormalizedComponentOptions\n): void {\n const cssPath = path.join(targetPath, `${options.nameDashCase}.css`);\n\n if (codegenFs.exists(cssPath)) {\n codegenFs.delete(cssPath);\n }\n}\n","import type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport { updateJson } from \"../../../json-utils\";\nimport { PluginConfiguration } from \"../types\";\n\n/**\n * Builder for constructing and updating .kos.json configuration\n */\nexport class KosConfigBuilder {\n private contributions: Record<string, any[]> = {};\n private experiences: Record<string, any> = {};\n private views: Record<string, any[]> = {};\n\n /**\n * Adds plugin configuration to the builder\n */\n addPluginConfiguration(config: PluginConfiguration): this {\n // Merge contributions\n Object.entries(config.contributions).forEach(([key, value]) => {\n this.contributions[key] = [...(this.contributions[key] || []), ...value];\n });\n\n // Merge experiences\n Object.assign(this.experiences, config.experiences);\n\n // Merge views\n if (config.views) {\n Object.entries(config.views).forEach(([key, value]) => {\n this.views[key] = [...(this.views[key] || []), ...value];\n });\n }\n\n return this;\n }\n\n /**\n * Applies the built configuration to the .kos.json file\n */\n applyToFile(codegenFs: CodegenFileSystem, kosConfigPath: string): void {\n updateJson(codegenFs, kosConfigPath, (json: any) => {\n // Initialize the deep structure if it doesn't exist\n const structure = this.initializeStructure(json);\n\n // Merge contributions\n Object.entries(this.contributions).forEach(([key, value]) => {\n structure.contributes[key] = [\n ...(structure.contributes[key] || []),\n ...value,\n ];\n });\n\n // Merge experiences\n structure.contributes.experiences = {\n ...structure.contributes.experiences,\n ...this.experiences,\n };\n\n // Merge views\n if (Object.keys(this.views).length > 0) {\n structure.contributes.views = structure.contributes.views || {};\n\n Object.entries(this.views).forEach(([key, value]) => {\n structure.contributes.views[key] = [\n ...(structure.contributes.views[key] || []),\n ...value,\n ];\n });\n }\n\n return json;\n });\n }\n\n /**\n * Initializes the deep JSON structure\n */\n private initializeStructure(json: any): any {\n json.kos ??= {};\n json.kos.ui ??= {};\n json.kos.ui.plugin ??= {};\n json.kos.ui.plugin.contributes ??= {};\n\n return json.kos.ui.plugin;\n }\n\n /**\n * Creates a new builder instance\n */\n static create(): KosConfigBuilder {\n return new KosConfigBuilder();\n }\n}\n","import * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport { updateJson } from \"../../../json-utils\";\nimport { NormalizedComponentOptions } from \"../types\";\n\n/**\n * Updates localization files for plugin components\n */\nexport function updateLocalization(\n codegenFs: CodegenFileSystem,\n projectRoot: string,\n options: NormalizedComponentOptions,\n pluginType: string\n): void {\n const localePath = path.join(\n projectRoot,\n \"assets\",\n \"locales\",\n \"en\",\n `${options.appProject}.json`\n );\n\n if (!codegenFs.exists(localePath)) {\n console.warn(`Locale file not found: ${localePath}`);\n return;\n }\n\n updateJson(codegenFs, localePath, (json: any) => {\n // Ensure nested structure exists\n json[options.appProject] = json[options.appProject] || {};\n json[options.appProject][options.nameCamelCase] =\n json[options.appProject][options.nameCamelCase] || {};\n\n // Add localization entry\n json[options.appProject][options.nameCamelCase][pluginType] = {\n ...json[options.appProject][options.nameCamelCase][pluginType],\n title: options.nameCamelCase,\n };\n\n return json;\n });\n}\n","import type { CodegenFileSystem } from \"../../../codegen-filesystem\";\nimport {\n findProjectByName,\n type ProjectConfiguration,\n} from \"../../../project-discovery\";\nimport { PluginHandlerFactory } from \"../plugin-handlers/factory\";\nimport type { ComponentOptions } from \"../types\";\n\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Validates generator options\n */\nexport function validateOptions(\n codegenFs: CodegenFileSystem,\n options: ComponentOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n // Validate required fields\n if (!options.name) {\n throw new ValidationError(\"Component name is required\");\n }\n\n if (!options.appProject) {\n throw new ValidationError(\"App project is required\");\n }\n\n // Validate project exists\n const project = findProjectByName(\n codegenFs.root,\n options.appProject,\n projects\n );\n if (!project) {\n throw new ValidationError(\n `Project \"${options.appProject}\" not found in workspace`\n );\n }\n\n // Validate plugin type if provided\n if (\n options.pluginType &&\n !PluginHandlerFactory.isValidPluginType(options.pluginType)\n ) {\n console.warn(\n `Unknown plugin type \"${options.pluginType}\". ` +\n `Component will be generated with default configuration.`\n );\n }\n\n // Validate group is provided for setting type\n if (options.pluginType === \"setting\" && !options.group) {\n throw new ValidationError(\n \"Settings group is required for setting plugin type\"\n );\n }\n}\n\n/**\n * Validates file paths\n */\nexport function validateFilePath(\n codegenFs: CodegenFileSystem,\n filePath: string\n): boolean {\n return codegenFs.exists(filePath);\n}\n\n/**\n * Safe JSON update with error handling\n */\nexport function safeJsonUpdate<T = any>(\n operation: () => T,\n fallback: T,\n errorMessage?: string\n): T {\n try {\n return operation();\n } catch (error) {\n if (errorMessage) {\n console.error(errorMessage, error);\n }\n return fallback;\n }\n}\n","/**\n * Core component generator — framework-agnostic.\n *\n * Replaces the Nx-coupled logic from kos-nx-plugin kos-component generator.\n * Uses CodegenFileSystem instead of @nx/devkit Tree.\n */\nimport * as path from \"path\";\nimport type { CodegenFileSystem } from \"../../codegen-filesystem\";\nimport { getKosProjectConfiguration } from \"../../kos-config\";\nimport type { ProjectConfiguration } from \"../../project-discovery\";\nimport { findProjectByName } from \"../../project-discovery\";\nimport { normalizeOptions } from \"../normalize-options\";\nimport { PluginHandlerFactory } from \"./plugin-handlers/factory\";\nimport {\n ComponentOptions,\n CONTRIBUTION_TYPE_MAP,\n NormalizedComponentOptions,\n} from \"./types\";\nimport { generateComponentFiles } from \"./utils/file-generator\";\nimport { KosConfigBuilder } from \"./utils/kos-config-builder\";\nimport { updateLocalization } from \"./utils/localization\";\nimport { validateOptions } from \"./utils/validation\";\n\nexport type { ComponentOptions } from \"./types\";\n\n/**\n * Generate a KOS component using the framework-agnostic CodegenFileSystem.\n *\n * @param codegenFs - Filesystem abstraction (NxTreeAdapter or DirectFileSystem)\n * @param templateDir - Absolute path to the template base directory\n * @param options - Component generator options\n * @param projects - Optional pre-computed project map (avoids rescan)\n */\nexport function generateComponent(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n options: ComponentOptions,\n projects?: Map<string, ProjectConfiguration>\n): void {\n // Step 1: Validate options\n validateOptions(codegenFs, options, projects);\n\n // Step 2: Normalize options\n const normalized = prepareOptions(codegenFs, options, projects);\n\n // Step 3: Get project configuration\n const projectConfig = findProjectByName(\n codegenFs.root,\n normalized.appProject,\n projects\n );\n\n if (!projectConfig) {\n throw new Error(\n `Project \"${normalized.appProject}\" not found in workspace`\n );\n }\n\n const projectRoot = projectConfig.sourceRoot;\n\n if (!projectRoot) {\n throw new Error(\n `No source root found for project ${normalized.appProject}`\n );\n }\n\n // Step 4: Generate component files\n generateFiles(codegenFs, templateDir, projectRoot, normalized);\n\n // Step 5: Update plugin configuration if needed\n if (options.pluginType) {\n updatePluginConfiguration(codegenFs, projectConfig, normalized);\n }\n}\n\n/**\n * Prepares and normalizes options\n */\nfunction prepareOptions(\n codegenFs: CodegenFileSystem,\n options: ComponentOptions,\n projects?: Map<string, ProjectConfiguration>\n): NormalizedComponentOptions {\n const normalized = normalizeOptions(\n codegenFs,\n {\n ...options,\n modelProject: \"__NONE__\",\n },\n projects\n ) as unknown as NormalizedComponentOptions;\n\n // Get KOS configuration for component location\n const kosConfig = getKosProjectConfiguration(\n codegenFs,\n options.appProject,\n projects\n );\n\n const componentLocation =\n (kosConfig?.generator?.defaults as any)?.component?.folder || \"\";\n\n // Set component directory and type\n normalized.appDirectory = options.appDirectory || componentLocation;\n normalized.type =\n CONTRIBUTION_TYPE_MAP[options.pluginType || \"\"] || options.type;\n\n // Pass through contributionKey for custom plugin types\n if (options.contributionKey) {\n normalized.contributionKey = options.contributionKey;\n }\n\n return normalized;\n}\n\n/**\n * Generates component files from templates\n */\nfunction generateFiles(\n codegenFs: CodegenFileSystem,\n templateDir: string,\n projectRoot: string,\n options: NormalizedComponentOptions\n): void {\n // Get appropriate handler\n const handler = PluginHandlerFactory.createHandler(options.pluginType);\n const templatePath = handler.getTemplatePath();\n\n // Determine target path\n const targetPath = path.join(\n projectRoot,\n options.appDirectory,\n options.type,\n options.nameDashCase\n );\n\n // Generate files\n generateComponentFiles(\n codegenFs,\n templateDir,\n templatePath,\n targetPath,\n options\n );\n}\n\n/**\n * Updates plugin configuration in .kos.json\n */\nfunction updatePluginConfiguration(\n codegenFs: CodegenFileSystem,\n projectConfig: ProjectConfiguration,\n options: NormalizedComponentOptions\n): void {\n const kosConfigPath = path.join(projectConfig.root, \".kos.json\");\n\n if (!codegenFs.exists(kosConfigPath)) {\n console.warn(`No .kos.json found at ${kosConfigPath}`);\n return;\n }\n\n // Get handler and create configuration\n const handler = PluginHandlerFactory.createHandler(options.pluginType);\n const pluginConfig = handler.createConfiguration(options);\n\n // Update .kos.json using builder\n const builder = KosConfigBuilder.create();\n builder.addPluginConfiguration(pluginConfig);\n builder.applyToFile(codegenFs, kosConfigPath);\n\n // Update localization if needed\n if (handler.requiresLocalization() && projectConfig.sourceRoot) {\n updateLocalization(\n codegenFs,\n projectConfig.sourceRoot,\n options,\n handler.getContributionKey()\n );\n }\n}\n","/**\n * Upsert a `.model(Bean)` entry and its import into an imperative registration\n * chain (`KosModelRegistry.<ns>.models().model(A)...`), on the AST.\n */\nimport {\n IndentationText,\n Project,\n QuoteKind,\n SyntaxKind,\n type CallExpression,\n type SourceFile,\n} from \"ts-morph\";\nimport { ensureNamedImport } from \"../augment/ts-toolkit\";\n\nexport interface UpsertChainEntryResult {\n changed: boolean;\n /** The full file text after the edit (only when `changed`). */\n content?: string;\n /** Whether an import for the bean had to be added (only when `changed`). */\n importAdded?: boolean;\n note?: string;\n error?: string;\n}\n\nfunction parse(content: string): SourceFile {\n // Match the file's own quote style for any import this adds.\n const singleQuoted = /^\\s*import\\b[^\"']*'/m.test(content);\n const project = new Project({\n useInMemoryFileSystem: true,\n manipulationSettings: {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: singleQuoted ? QuoteKind.Single : QuoteKind.Double,\n },\n });\n return project.createSourceFile(\"registration-chain.ts\", content, {\n overwrite: true,\n });\n}\n\n/** Every `<expr>.<name>(...)` call in the file, in source order. */\nfunction chainCalls(sf: SourceFile, name: string): CallExpression[] {\n return sf.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => {\n const callee = call.getExpression();\n return (\n callee.getKind() === SyntaxKind.PropertyAccessExpression &&\n callee.asKindOrThrow(SyntaxKind.PropertyAccessExpression).getName() ===\n name\n );\n });\n}\n\n/** Leading whitespace of the line the call's `.name` token sits on. */\nfunction indentOfCall(sf: SourceFile, call: CallExpression): string {\n const text = sf.getFullText();\n const nameNode = call\n .getExpression()\n .asKindOrThrow(SyntaxKind.PropertyAccessExpression)\n .getNameNode();\n const lineStart = text.lastIndexOf(\"\\n\", nameNode.getStart()) + 1;\n return text.slice(lineStart).match(/^[ \\t]*/)?.[0] ?? \"\";\n}\n\n/** Number of `.model(...)` entries in a chain file. */\nexport function countChainEntries(content: string): number {\n return chainCalls(parse(content), \"model\").length;\n}\n\nexport function upsertChainEntry(\n content: string,\n bean: string,\n importSpec: string\n): UpsertChainEntryResult {\n const sf = parse(content);\n\n const modelCalls = chainCalls(sf, \"model\");\n const registered = modelCalls.some((call) => {\n const [arg, ...rest] = call.getArguments();\n return rest.length === 0 && arg?.getText() === bean;\n });\n if (registered) return { changed: false, note: \"already registered\" };\n\n // Outermost entry of the last chain in the file; a trailing .companion() wraps it.\n let anchor: CallExpression | undefined;\n let indent: string;\n if (modelCalls.length > 0) {\n anchor = modelCalls.reduce((last, call) =>\n call.getEnd() > last.getEnd() ? call : last\n );\n indent = indentOfCall(sf, anchor);\n } else {\n // Empty chain: the first entry goes right after .models().\n const starts = chainCalls(sf, \"models\").filter(\n (call) => call.getArguments().length === 0\n );\n anchor = starts[starts.length - 1];\n if (!anchor) {\n return {\n changed: false,\n error: \"no .models() chain found in the registration file\",\n };\n }\n const text = sf.getFullText();\n const lineStart = text.lastIndexOf(\"\\n\", anchor.getStart()) + 1;\n indent = (text.slice(lineStart).match(/^[ \\t]*/)?.[0] ?? \"\") + \" \";\n }\n anchor.replaceWithText(`${anchor.getText()}\\n${indent}.model(${bean})`);\n\n const imported = sf\n .getImportDeclarations()\n .some((decl) =>\n decl.getNamedImports().some((named) => named.getName() === bean)\n );\n if (!imported) ensureNamedImport(sf, importSpec, [{ name: bean }]);\n\n return { changed: true, content: sf.getFullText(), importAdded: !imported };\n}\n"],"names":["unquote","SERVICE_MODULE_RE","header","FRAMEWORK_TYPES"],"mappings":"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"}