@fluid-app/fluid-cli-widget 0.1.61 → 0.1.63

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["isNodeError","isRecord","readPackageJson","isRecord","buildWidgetPackageArtifacts","isRecord","isRecord","resolveDroplet","publishWidgetPackageArtifacts"],"sources":["../src/utils/config.ts","../src/utils/validation.ts","../src/utils/source-package.ts","../src/utils/command.ts","../src/utils/package-manager.ts","../src/utils/package-scripts.ts","../src/utils/template.ts","../src/commands/build.ts","../../../platform/api-client-core/src/api-error-shape.ts","../../../platform/api-client-core/src/fetch-client.ts","../../../platform/api-client-core/src/hey-api-error-policy.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/bodySerializer.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/params.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/serverSentEvents.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/pathSerializer.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/utils.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/auth.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/client/utils.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/client/client.gen.ts","../../../api-clients/fluidos/src/hey-api-client.ts","../src/utils/auth-client.ts","../src/lib/git.ts","../src/utils/git-credential.ts","../src/utils/widget-marker.ts","../src/commands/clone.ts","../src/utils/github-template.ts","../src/commands/create.ts","../src/commands/dev.ts","../src/utils/droplets.ts","../src/commands/link.ts","../src/utils/droplet-api.ts","../src/commands/logs.ts","../src/commands/publish.ts","../src/utils/me.ts","../src/lib/git-sync.ts","../src/commands/push.ts","../src/commands/status.ts","../src/commands/validate.ts","../src/index.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport const WIDGET_CONFIG_FILE = \"fluid.widget.config.ts\";\n\n/** Author-owned settings in `fluid.widget.config.ts`. */\nexport interface FluidWidgetConfig {\n /** Stable Fluid droplet identifier that owns published package versions. */\n readonly droplet?: string;\n}\n\nexport interface LoadedWidgetConfig {\n readonly path: string;\n readonly config: Partial<FluidWidgetConfig>;\n}\n\nexport class WidgetConfigParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WidgetConfigParseError\";\n }\n}\n\nexport function resolveWidgetConfigPath(projectDir: string): string {\n return path.join(projectDir, WIDGET_CONFIG_FILE);\n}\n\nexport async function loadWidgetConfig(\n projectDir: string,\n): Promise<LoadedWidgetConfig> {\n const configPath = resolveWidgetConfigPath(projectDir);\n\n let source: string;\n try {\n source = await readFile(configPath, \"utf-8\");\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") {\n return { path: configPath, config: {} };\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Unable to read ${WIDGET_CONFIG_FILE}: ${message}`);\n }\n\n return { path: configPath, config: parseWidgetConfigSource(source) };\n}\n\nexport async function writeWidgetConfig(\n projectDir: string,\n config: FluidWidgetConfig,\n): Promise<void> {\n await writeFile(\n resolveWidgetConfigPath(projectDir),\n formatWidgetConfig(config),\n \"utf-8\",\n );\n}\n\nexport function formatWidgetConfig(config: FluidWidgetConfig): string {\n const lines = [\n 'import type { FluidWidgetConfig } from \"@fluid-app/fluid-cli-widget\";',\n 'import { widgetPackage as sourceWidgetPackage } from \"./manifest\";',\n \"\",\n \"const config = {\",\n ];\n\n if (config.droplet) {\n lines.push(` droplet: ${JSON.stringify(config.droplet)},`);\n }\n\n lines.push(\n \"} satisfies FluidWidgetConfig;\",\n \"\",\n \"const widgetConfig: FluidWidgetConfig = config;\",\n \"const packageStableId = widgetConfig.droplet;\",\n \"\",\n \"export const widgetPackage = packageStableId\",\n \" ? {\",\n \" ...sourceWidgetPackage,\",\n \" packageStableId,\",\n \" packageId: `${sourceWidgetPackage.scope}.${packageStableId}` as const,\",\n \" }\",\n \" : sourceWidgetPackage;\",\n \"export const widgetPackages = [widgetPackage] as const;\",\n \"\",\n \"export default config;\",\n \"export const droplet = widgetConfig.droplet;\",\n \"\",\n );\n return lines.join(\"\\n\");\n}\n\nexport function parseWidgetConfigSource(\n source: string,\n): Partial<FluidWidgetConfig> {\n const objectSource = extractConfigObjectLiteral(source);\n const config = parseConfigObjectProperties(objectSource);\n\n return config;\n}\n\nexport function mergeWidgetConfig(\n current: Partial<FluidWidgetConfig>,\n updates: Partial<FluidWidgetConfig>,\n): FluidWidgetConfig {\n const droplet =\n normalizeOptionalString(updates.droplet) ??\n normalizeOptionalString(current.droplet);\n\n return droplet ? { droplet } : {};\n}\n\nexport function validateDropletUuid(dropletUuid: string): string | undefined {\n if (!dropletUuid) return \"Droplet UUID is required.\";\n if (dropletUuid.length > MAX_DROPLET_UUID_LENGTH) {\n return `Droplet UUID must be ${MAX_DROPLET_UUID_LENGTH} characters or fewer.`;\n }\n if (!URL_SAFE_IDENTIFIER_PATTERN.test(dropletUuid)) {\n return (\n \"Droplet UUID must be URL-safe text: letters, numbers, \" +\n \"'_', '~', and '-' only.\"\n );\n }\n return undefined;\n}\n\nfunction extractConfigObjectLiteral(source: string): string {\n const configStart = /\\bconst\\s+config\\s*=\\s*\\{/.exec(source);\n if (!configStart) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} must declare \\`const config = { ... } satisfies FluidWidgetConfig\\`.`,\n );\n }\n\n const openBraceIndex = source.indexOf(\"{\", configStart.index);\n const closeBraceIndex = findMatchingBrace(source, openBraceIndex);\n const suffix = stripComments(source.slice(closeBraceIndex + 1));\n if (!/^\\s*(?:as\\s+const\\s+)?satisfies\\s+FluidWidgetConfig\\s*;/.test(suffix)) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} config object must use \\`satisfies FluidWidgetConfig\\` or \\`as const satisfies FluidWidgetConfig\\`.`,\n );\n }\n\n return stripComments(source.slice(openBraceIndex + 1, closeBraceIndex));\n}\n\nfunction parseConfigObjectProperties(\n objectSource: string,\n): Partial<FluidWidgetConfig> {\n const config: { droplet?: string } = {};\n\n for (const member of splitTopLevelMembers(objectSource)) {\n const trimmedMember = member.trim();\n if (!trimmedMember) continue;\n\n const propertyMatch = /^(droplet)\\s*:\\s*([\\s\\S]+)$/.exec(trimmedMember);\n if (!propertyMatch) {\n const propertyName = /^([A-Za-z_$][\\w$]*)\\s*:/.exec(trimmedMember)?.[1];\n throw new WidgetConfigParseError(\n propertyName\n ? `${WIDGET_CONFIG_FILE} does not support config field ${propertyName}. Supported field is droplet.`\n : `${WIDGET_CONFIG_FILE} config fields must use optional droplet: \"...\" string literal.`,\n );\n }\n\n const propertyName = propertyMatch[1];\n if (propertyName !== \"droplet\") {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} config field could not be parsed.`,\n );\n }\n const valueSource = propertyMatch[2]?.trim() ?? \"\";\n const value = parseStringLiteralValue(valueSource, propertyName);\n if (!value.trim()) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} field ${propertyName} must be a non-empty string literal.`,\n );\n }\n\n if (config.droplet !== undefined) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} field droplet must only be declared once.`,\n );\n }\n config.droplet = value;\n }\n\n return config;\n}\n\nfunction parseStringLiteralValue(\n valueSource: string,\n propertyName: string,\n): string {\n if (valueSource.startsWith('\"') && valueSource.endsWith('\"')) {\n try {\n const parsed = JSON.parse(valueSource) as unknown;\n if (typeof parsed === \"string\") return parsed;\n } catch {\n // Fall through to the actionable error below.\n }\n }\n\n if (valueSource.startsWith(\"'\") && valueSource.endsWith(\"'\")) {\n return parseSingleQuotedStringLiteral(valueSource);\n }\n\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} field ${propertyName} must be a string literal (for example ${propertyName}: \"value\").`,\n );\n}\n\nfunction parseSingleQuotedStringLiteral(valueSource: string): string {\n let value = \"\";\n\n for (let index = 1; index < valueSource.length - 1; index += 1) {\n const char = valueSource[index];\n if (char !== \"\\\\\") {\n value += char;\n continue;\n }\n\n index += 1;\n const escaped = valueSource[index];\n switch (escaped) {\n case \"\\\\\":\n case \"'\":\n case '\"':\n value += escaped;\n break;\n case \"n\":\n value += \"\\n\";\n break;\n case \"r\":\n value += \"\\r\";\n break;\n case \"t\":\n value += \"\\t\";\n break;\n case \"b\":\n value += \"\\b\";\n break;\n case \"f\":\n value += \"\\f\";\n break;\n case \"v\":\n value += \"\\v\";\n break;\n default:\n value += escaped ?? \"\";\n break;\n }\n }\n\n return value;\n}\n\nfunction stripComments(source: string): string {\n let result = \"\";\n let stringQuote: '\"' | \"'\" | \"`\" | undefined;\n let escaped = false;\n let lineComment = false;\n let blockComment = false;\n\n for (let index = 0; index < source.length; index += 1) {\n const char = source[index];\n const nextChar = source[index + 1];\n\n if (lineComment) {\n if (char === \"\\n\" || char === \"\\r\") {\n lineComment = false;\n result += char;\n } else {\n result += \" \";\n }\n continue;\n }\n\n if (blockComment) {\n if (char === \"*\" && nextChar === \"/\") {\n blockComment = false;\n result += \" \";\n index += 1;\n } else if (char === \"\\n\" || char === \"\\r\") {\n result += char;\n } else {\n result += \" \";\n }\n continue;\n }\n\n if (stringQuote) {\n result += char;\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === stringQuote) {\n stringQuote = undefined;\n }\n continue;\n }\n\n if (char === \"/\" && nextChar === \"/\") {\n lineComment = true;\n result += \" \";\n index += 1;\n continue;\n }\n\n if (char === \"/\" && nextChar === \"*\") {\n blockComment = true;\n result += \" \";\n index += 1;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n stringQuote = char;\n }\n result += char;\n }\n\n return result;\n}\n\nfunction splitTopLevelMembers(objectSource: string): string[] {\n const members: string[] = [];\n let memberStart = 0;\n let stringQuote: '\"' | \"'\" | \"`\" | undefined;\n let escaped = false;\n let nestedDepth = 0;\n\n for (let index = 0; index < objectSource.length; index += 1) {\n const char = objectSource[index];\n\n if (stringQuote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === stringQuote) {\n stringQuote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n stringQuote = char;\n continue;\n }\n\n if (char === \"{\" || char === \"[\" || char === \"(\") {\n nestedDepth += 1;\n continue;\n }\n if (char === \"}\" || char === \"]\" || char === \")\") {\n nestedDepth -= 1;\n continue;\n }\n\n if (char === \",\" && nestedDepth === 0) {\n members.push(objectSource.slice(memberStart, index));\n memberStart = index + 1;\n }\n }\n\n members.push(objectSource.slice(memberStart));\n return members;\n}\n\nfunction findMatchingBrace(source: string, openBraceIndex: number): number {\n let depth = 0;\n let stringQuote: '\"' | \"'\" | \"`\" | undefined;\n let escaped = false;\n let lineComment = false;\n let blockComment = false;\n\n for (let index = openBraceIndex; index < source.length; index += 1) {\n const char = source[index];\n const nextChar = source[index + 1];\n\n if (lineComment) {\n if (char === \"\\n\" || char === \"\\r\") lineComment = false;\n continue;\n }\n\n if (blockComment) {\n if (char === \"*\" && nextChar === \"/\") {\n blockComment = false;\n index += 1;\n }\n continue;\n }\n\n if (stringQuote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === stringQuote) {\n stringQuote = undefined;\n }\n continue;\n }\n\n if (char === \"/\" && nextChar === \"/\") {\n lineComment = true;\n index += 1;\n continue;\n }\n\n if (char === \"/\" && nextChar === \"*\") {\n blockComment = true;\n index += 1;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n stringQuote = char;\n continue;\n }\n\n if (char === \"{\") depth += 1;\n if (char === \"}\") {\n depth -= 1;\n if (depth === 0) return index;\n }\n }\n\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} config object is missing a closing brace.`,\n );\n}\n\nfunction normalizeOptionalString(\n value: string | undefined,\n): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\ninterface NodeError extends Error {\n readonly code?: string;\n}\n\nfunction isNodeError(error: unknown): error is NodeError {\n return error instanceof Error && \"code\" in error;\n}\n\nconst MAX_DROPLET_UUID_LENGTH = 256;\nconst URL_SAFE_SEGMENT_SOURCE = \"[A-Za-z0-9][A-Za-z0-9_~-]*\";\nconst URL_SAFE_IDENTIFIER_PATTERN = new RegExp(`^${URL_SAFE_SEGMENT_SOURCE}$`);\n","export interface WidgetCliValidationError {\n readonly path?: string;\n readonly message: string;\n}\n\nexport function formatValidationErrors(\n errors: readonly WidgetCliValidationError[],\n): string {\n if (errors.length === 0) return \"Validation failed.\";\n\n return [\n \"Validation failed:\",\n ...errors.map((error) => {\n const location = error.path ? `${error.path}: ` : \"\";\n return ` - ${location}${error.message}`;\n }),\n ].join(\"\\n\");\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, rm, rmdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n loadAndValidateWidgetPackage,\n WidgetToolingError,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageValidationError,\n} from \"@fluid-app/fluid-cli-widget-tooling\";\nimport {\n WIDGET_CONFIG_FILE,\n loadWidgetConfig,\n validateDropletUuid,\n} from \"./config.js\";\nimport { formatValidationErrors } from \"./validation.js\";\n\nexport const DEFAULT_WIDGET_OUT_DIR = \".fluid/widget-dist\";\nexport const ROOT_WIDGET_CONFIG_FILE: string = WIDGET_CONFIG_FILE;\n\nconst SOURCE_CONFIG_CANDIDATES = [\n \"src/widgets.config.ts\",\n \"src/portal.config.ts\",\n \"portal.config.ts\",\n] as const;\n\nexport interface WidgetValidationResult {\n readonly projectDir: string;\n readonly sourceConfigPath?: string;\n readonly validated: ValidatedWidgetPackageBuild;\n}\n\nexport class WidgetValidationError extends Error {\n public readonly errors: readonly WidgetPackageValidationError[];\n\n constructor(errors: readonly WidgetPackageValidationError[]) {\n super(formatValidationErrors(errors));\n this.name = \"WidgetValidationError\";\n this.errors = errors;\n }\n}\n\nexport async function validateDropletWidgetProject(\n projectDir: string,\n packageKeyOverride?: string,\n): Promise<WidgetValidationResult> {\n const resolvedProjectDir = path.resolve(projectDir);\n const sourceConfig = resolveWidgetSourceConfig(resolvedProjectDir);\n if (!sourceConfig) {\n throw new WidgetValidationError([\n {\n code: \"NO_SOURCE_PACKAGE\",\n path: ROOT_WIDGET_CONFIG_FILE,\n message:\n `No widget package config found. Create ${ROOT_WIDGET_CONFIG_FILE} ` +\n \"or src/widgets.config.ts that exports defineWidgetPackage(...).\",\n },\n ]);\n }\n\n const configErrors = await validateRootWidgetConfig(\n resolvedProjectDir,\n packageKeyOverride,\n );\n if (configErrors.length > 0) {\n throw new WidgetValidationError(configErrors);\n }\n\n let validated: ValidatedWidgetPackageBuild;\n try {\n const loaded = await withRootWidgetConfigBridge(\n resolvedProjectDir,\n () =>\n loadAndValidateWidgetPackage({\n projectDir: resolvedProjectDir,\n owner: \"droplet\",\n }),\n packageKeyOverride,\n );\n validated = loaded.validated;\n } catch (error) {\n if (error instanceof WidgetToolingError) {\n if (error.diagnostics) {\n throw new WidgetValidationError(error.diagnostics);\n }\n throw new WidgetValidationError([\n {\n code: \"INVALID_SOURCE_PACKAGE\",\n path: sourceConfig.relativePath,\n message: error.details\n ? `${error.message}\\n${error.details}`\n : error.message,\n },\n ]);\n }\n throw error;\n }\n\n return {\n projectDir: resolvedProjectDir,\n sourceConfigPath: sourceConfig.relativePath,\n validated,\n };\n}\n\nexport async function withRootWidgetConfigBridge<T>(\n projectDir: string,\n callback: () => Promise<T>,\n packageKeyOverride?: string,\n): Promise<T> {\n const rootConfigPath = path.join(projectDir, ROOT_WIDGET_CONFIG_FILE);\n if (!existsSync(rootConfigPath) || resolvePortalSourceConfig(projectDir)) {\n return callback();\n }\n\n const packageKey =\n packageKeyOverride?.trim() ||\n (await loadWidgetConfig(projectDir)).config.droplet;\n if (!packageKey) {\n throw new Error(\n \"fluid.widget.config.ts must set droplet before validating, building, or publishing.\",\n );\n }\n\n const srcDir = path.join(projectDir, \"src\");\n const bridgePath = path.join(srcDir, \"widgets.config.ts\");\n const srcDirExisted = existsSync(srcDir);\n await mkdir(srcDir, { recursive: true });\n try {\n await writeFile(\n bridgePath,\n createRootWidgetConfigBridgeSource(packageKey),\n {\n encoding: \"utf-8\",\n flag: \"wx\",\n },\n );\n } catch (err) {\n if (isNodeError(err) && err.code === \"EEXIST\") {\n throw new Error(\n `${path.relative(projectDir, bridgePath)} already exists. ` +\n \"Remove this stale Fluid widget CLI bridge file and try again.\",\n );\n }\n throw err;\n }\n\n try {\n return await callback();\n } finally {\n await rm(bridgePath, { force: true }).catch(() => {});\n if (!srcDirExisted) await rmdir(srcDir).catch(() => {});\n }\n}\n\nfunction createRootWidgetConfigBridgeSource(packageKey: string): string {\n return `import { widgetPackage as sourceWidgetPackage } from \"../manifest\";\n\nconst packageKey = ${JSON.stringify(packageKey)};\nconst packageId = sourceWidgetPackage.scope + \".\" + packageKey;\n\nexport const widgetPackage = {\n ...sourceWidgetPackage,\n packageStableId: packageKey,\n packageId,\n};\n\nexport const widgetPackages = [widgetPackage] as const;\nexport default widgetPackage;\n`;\n}\n\nexport function resolveWidgetSourceConfig(\n projectDir: string,\n): { readonly path: string; readonly relativePath: string } | undefined {\n const rootConfig = path.join(projectDir, ROOT_WIDGET_CONFIG_FILE);\n if (existsSync(rootConfig)) {\n return { path: rootConfig, relativePath: ROOT_WIDGET_CONFIG_FILE };\n }\n\n return resolvePortalSourceConfig(projectDir);\n}\n\nexport function formatValidationSuccess(\n result: WidgetValidationResult,\n): string {\n return [\n \"Widget package is valid.\",\n `Config: ${result.sourceConfigPath ?? \"unknown\"}`,\n `Package: ${result.validated.packageId}`,\n `Version: ${result.validated.version}`,\n `Widgets: ${result.validated.widgets.length}`,\n ].join(\"\\n\");\n}\n\nasync function validateRootWidgetConfig(\n projectDir: string,\n packageKeyOverride?: string,\n): Promise<WidgetPackageValidationError[]> {\n const configPath = path.join(projectDir, ROOT_WIDGET_CONFIG_FILE);\n if (!existsSync(configPath)) return [];\n\n try {\n const loaded = await loadWidgetConfig(projectDir);\n const droplet = packageKeyOverride ?? loaded.config.droplet ?? \"\";\n const packageKeyError = validateDropletUuid(droplet);\n if (!packageKeyError) return [];\n\n return [\n {\n code: \"INVALID_PACKAGE_KEY\",\n path: ROOT_WIDGET_CONFIG_FILE,\n message: packageKeyError,\n },\n ];\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return [\n {\n code: \"INVALID_SOURCE_PACKAGE\",\n path: ROOT_WIDGET_CONFIG_FILE,\n message,\n },\n ];\n }\n}\n\nfunction resolvePortalSourceConfig(\n projectDir: string,\n): { readonly path: string; readonly relativePath: string } | undefined {\n for (const relativePath of SOURCE_CONFIG_CANDIDATES) {\n const candidate = path.join(projectDir, relativePath);\n if (existsSync(candidate)) return { path: candidate, relativePath };\n }\n\n return undefined;\n}\n\ninterface NodeError extends Error {\n readonly code?: string;\n}\n\nfunction isNodeError(error: unknown): error is NodeError {\n return error instanceof Error && \"code\" in error;\n}\n","import chalk from \"chalk\";\n\nexport async function runCliAction(action: () => Promise<void>): Promise<void> {\n try {\n await action();\n } catch (err) {\n console.error(chalk.red(\"Error:\") + \" \" + formatUnknownError(err));\n process.exit(1);\n }\n}\n\nexport function formatUnknownError(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport function getRunCommand(\n script: string,\n cwd: string = process.cwd(),\n): string {\n return `${detectPackageManager(cwd)} run ${script}`;\n}\n\nexport function getInstallCommand(cwd: string = process.cwd()): string {\n return `${detectPackageManager(cwd)} install`;\n}\n\nexport async function installDependencies(cwd: string): Promise<void> {\n const packageManager = detectPackageManager(cwd);\n await runPackageManager(packageManager, [\"install\"], cwd);\n}\n\nexport function detectPackageManager(cwd: string): PackageManager {\n if (existsSync(path.join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(path.join(cwd, \"yarn.lock\"))) return \"yarn\";\n if (existsSync(path.join(cwd, \"bun.lockb\"))) return \"bun\";\n if (existsSync(path.join(cwd, \"package-lock.json\"))) return \"npm\";\n\n const invokingPackageManager = readInvokingPackageManager();\n if (invokingPackageManager) return invokingPackageManager;\n\n const declaredPackageManager = readDeclaredPackageManager(cwd);\n if (declaredPackageManager && isCommandAvailable(declaredPackageManager)) {\n return declaredPackageManager;\n }\n\n return findAvailablePackageManager() ?? \"pnpm\";\n}\n\nfunction runPackageManager(\n command: PackageManager,\n args: readonly string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, [...args], {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n\n child.once(\"error\", (error: Error) => {\n reject(error);\n });\n\n child.once(\"exit\", (code: number | null) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(\n new Error(\n `${command} ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n });\n}\n\nfunction readInvokingPackageManager(): PackageManager | undefined {\n const userAgent = process.env[\"npm_config_user_agent\"];\n if (!userAgent) return undefined;\n\n const name = userAgent.split(\"/\")[0];\n if (isPackageManager(name)) return name;\n return undefined;\n}\n\nfunction readDeclaredPackageManager(cwd: string): PackageManager | undefined {\n const packageJsonPath = path.join(cwd, \"package.json\");\n if (!existsSync(packageJsonPath)) return undefined;\n\n try {\n const packageJson = JSON.parse(\n readFileSync(packageJsonPath, \"utf-8\"),\n ) as unknown;\n if (!isRecord(packageJson)) return undefined;\n\n const packageManager = packageJson[\"packageManager\"];\n if (typeof packageManager !== \"string\") return undefined;\n\n const name = packageManager.split(\"@\")[0];\n if (isPackageManager(name)) return name;\n } catch {\n // Malformed package.json is reported by command paths that need to parse it.\n }\n\n return undefined;\n}\n\nfunction findAvailablePackageManager(): PackageManager | undefined {\n for (const packageManager of [\"pnpm\", \"yarn\", \"bun\", \"npm\"] as const) {\n if (isCommandAvailable(packageManager)) return packageManager;\n }\n return undefined;\n}\n\nfunction isCommandAvailable(command: PackageManager): boolean {\n const result = spawnSync(command, [\"--version\"], {\n shell: process.platform === \"win32\",\n stdio: \"ignore\",\n });\n return result.status === 0;\n}\n\nfunction isPackageManager(value: string | undefined): value is PackageManager {\n return (\n value === \"pnpm\" || value === \"yarn\" || value === \"bun\" || value === \"npm\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { detectPackageManager } from \"./package-manager.js\";\n\nexport interface PackageScriptRunResult {\n readonly ran: boolean;\n readonly command?: string;\n}\n\nexport async function runPackageScriptIfAvailable(options: {\n readonly projectDir: string;\n readonly scriptName: string;\n}): Promise<PackageScriptRunResult> {\n const packageJsonPath = path.join(options.projectDir, \"package.json\");\n if (!existsSync(packageJsonPath)) return { ran: false };\n\n const packageJson = await readPackageJson(packageJsonPath);\n if (!hasPackageScript(packageJson, options.scriptName)) return { ran: false };\n\n const packageManager = detectPackageManager(options.projectDir);\n const args = [\"run\", options.scriptName];\n await runCommand(packageManager, args, options.projectDir);\n\n return {\n ran: true,\n command: `${packageManager} ${args.join(\" \")}`,\n };\n}\n\nfunction runCommand(\n command: string,\n args: readonly string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n stdio: \"inherit\",\n env: process.env,\n shell: process.platform === \"win32\",\n });\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(\n new Error(\n signal\n ? `${command} ${args.join(\" \")} exited with signal ${signal}.`\n : `${command} ${args.join(\" \")} exited with code ${code ?? \"unknown\"}.`,\n ),\n );\n });\n });\n}\n\nasync function readPackageJson(packageJsonPath: string): Promise<unknown> {\n const source = await readFile(packageJsonPath, \"utf-8\");\n try {\n return JSON.parse(source) as unknown;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Unable to parse package.json: ${message}`);\n }\n}\n\nfunction hasPackageScript(value: unknown, scriptName: string): boolean {\n if (!isRecord(value)) return false;\n const scripts = value[\"scripts\"];\n if (!isRecord(scripts)) return false;\n return typeof scripts[scriptName] === \"string\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { WidgetTemplateVariables } from \"../types.js\";\n\ndeclare const __FLUID_PORTAL_SDK_VERSION__: string | undefined;\ndeclare const __FLUID_CLI_CORE_VERSION__: string | undefined;\ndeclare const __FLUID_CLI_WIDGET_VERSION__: string | undefined;\n\nconst EMBEDDED_PORTAL_SDK_VERSION =\n typeof __FLUID_PORTAL_SDK_VERSION__ === \"string\"\n ? __FLUID_PORTAL_SDK_VERSION__\n : undefined;\nconst EMBEDDED_CLI_CORE_VERSION =\n typeof __FLUID_CLI_CORE_VERSION__ === \"string\"\n ? __FLUID_CLI_CORE_VERSION__\n : undefined;\nconst EMBEDDED_CLI_WIDGET_VERSION =\n typeof __FLUID_CLI_WIDGET_VERSION__ === \"string\"\n ? __FLUID_CLI_WIDGET_VERSION__\n : undefined;\n\nexport function getDefaultTemplatePath(): string {\n return path.join(findPackageRoot(), \"templates\", \"default\");\n}\n\nexport async function directoryExists(filePath: string): Promise<boolean> {\n try {\n const stats = await stat(filePath);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function copyWidgetTemplate(\n templatePath: string,\n targetPath: string,\n variables: WidgetTemplateVariables,\n): Promise<void> {\n const files = await getFiles(templatePath);\n\n for (const file of files) {\n const sourcePath = path.join(templatePath, file);\n const isTemplate = file.endsWith(\".template\");\n const outputFiles = getOutputFilenames(file);\n\n const content = await readFile(sourcePath, \"utf-8\");\n const processed = isTemplate ? renderTemplate(content, variables) : content;\n\n await writeOutputFiles(targetPath, outputFiles, processed);\n }\n\n for (const skillFile of await getSharedTemplateSkillFiles()) {\n await writeOutputFiles(\n targetPath,\n getOutputFilenames(skillFile.relativePath),\n skillFile.content,\n );\n }\n}\n\nexport async function getPortalSdkVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion(\n [\"portal\", \"sdk\"],\n EMBEDDED_PORTAL_SDK_VERSION,\n options,\n );\n}\n\nexport async function getPortalCoreVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion([\"portal\", \"core\"], undefined, options);\n}\n\nexport async function getCliVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion(\n [\"cli\", \"core\"],\n EMBEDDED_CLI_CORE_VERSION,\n options,\n );\n}\n\nexport async function getWidgetCliVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion(\n [\"cli\", \"widget\"],\n EMBEDDED_CLI_WIDGET_VERSION,\n options,\n );\n}\n\nasync function getWorkspacePackageVersion(\n packagePathSegments: readonly string[],\n embeddedVersion: string | undefined,\n options: { readonly local?: boolean },\n): Promise<string> {\n try {\n const packageRoot = findPackageRoot();\n const packagesRoot = path.join(packageRoot, \"..\", \"..\");\n const targetPackageRoot = path.join(packagesRoot, ...packagePathSegments);\n\n if (options.local) {\n return getLocalPackageLinkVersion(targetPackageRoot);\n }\n\n if (embeddedVersion) return embeddedVersion;\n\n const packageJsonPath = path.join(targetPackageRoot, \"package.json\");\n const content = await readFile(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content) as { version?: string };\n if (typeof pkg.version !== \"string\") {\n throw new Error(`Missing version in ${packageJsonPath}`);\n }\n return pkg.version;\n } catch (error) {\n if (embeddedVersion) return embeddedVersion;\n throw new Error(\n `Could not resolve the exact template package version for ${packagePathSegments.join(\"/\")}`,\n { cause: error },\n );\n }\n}\n\n/**\n * Builds an absolute pnpm link: specifier for local scaffolds.\n *\n * link: keeps the dependency pointed at the workspace package source instead of\n * packing only package.json \"files\" entries like file: does. That lets Vite's\n * development export resolve the SDK source and its workspace dependencies. An\n * absolute path also remains valid when the operating system canonicalizes the\n * generated project path, such as macOS resolving /tmp to /private/tmp.\n */\nfunction getLocalPackageLinkVersion(packagePath: string): string {\n const linkPath = path.resolve(packagePath).replace(/\\\\/g, \"/\");\n return `link:${linkPath}`;\n}\n\nasync function getFiles(dir: string, baseDir = dir): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await getFiles(fullPath, baseDir)));\n } else {\n files.push(path.relative(baseDir, fullPath));\n }\n }\n\n return files;\n}\n\ninterface TemplateSkillFile {\n readonly relativePath: string;\n readonly content: string;\n}\n\nasync function getSharedTemplateSkillFiles(): Promise<TemplateSkillFile[]> {\n const packageRoot = findFluidCliPackageRoot();\n const skillsRoot = path.join(packageRoot, \"template-skills\");\n const files = await getFiles(skillsRoot);\n\n return Promise.all(\n files.map(async (file) => ({\n relativePath: path.join(\"skills\", file),\n content: await readFile(path.join(skillsRoot, file), \"utf-8\"),\n })),\n );\n}\n\nfunction findFluidCliPackageRoot(): string {\n const workspacePackageRoot = path.join(findPackageRoot(), \"..\", \"core\");\n if (existsSync(path.join(workspacePackageRoot, \"template-skills\"))) {\n return workspacePackageRoot;\n }\n\n let dir = path.dirname(\n fileURLToPath(import.meta.resolve(\"@fluid-app/fluid-cli\")),\n );\n while (!existsSync(path.join(dir, \"package.json\"))) {\n const parent = path.dirname(dir);\n if (parent === dir)\n throw new Error(\"Could not find Fluid CLI package root\");\n dir = parent;\n }\n return dir;\n}\n\nfunction renderTemplate(\n content: string,\n variables: WidgetTemplateVariables,\n): string {\n const withConditionals = content.replace(\n /{{\\s*#if\\s+([a-zA-Z0-9_]+)\\s*}}([\\s\\S]*?){{\\s*\\/if\\s*}}/g,\n (match, key, block) => {\n if (!isTemplateVariableKey(key)) return match;\n return variables[key] ? String(block) : \"\";\n },\n );\n\n return withConditionals.replace(\n /{{\\s*([a-zA-Z0-9_]+)\\s*}}/g,\n (match, key) => {\n if (isTemplateVariableKey(key)) return variables[key] ?? \"\";\n return match;\n },\n );\n}\n\nfunction isTemplateVariableKey(\n key: string,\n): key is keyof WidgetTemplateVariables {\n return [\n \"projectName\",\n \"widgetScope\",\n \"widgetPackageVersion\",\n \"sdkVersion\",\n \"localCoreVersion\",\n \"fluidCliVersion\",\n \"widgetCliVersion\",\n \"droplet\",\n ].includes(key);\n}\n\nasync function writeOutputFiles(\n targetPath: string,\n outputFiles: readonly string[],\n content: string,\n): Promise<void> {\n for (const outputFile of outputFiles) {\n const destinationPath = path.join(targetPath, outputFile);\n await mkdir(path.dirname(destinationPath), { recursive: true });\n await writeFile(destinationPath, content, \"utf-8\");\n }\n}\n\nfunction getOutputFilenames(filename: string): string[] {\n const outputFilename = getOutputFilename(filename);\n const normalized = outputFilename.replace(/\\\\/g, \"/\");\n\n if (normalized === \"AGENTS.md\") return [\"AGENTS.md\", \"CLAUDE.md\"];\n\n if (normalized.startsWith(\"skills/\")) {\n return [\n path.join(\".agents\", outputFilename),\n path.join(\".claude\", outputFilename),\n ];\n }\n\n return [outputFilename];\n}\n\nfunction getOutputFilename(filename: string): string {\n return filename.endsWith(\".template\")\n ? filename.slice(0, -\".template\".length)\n : filename;\n}\n\nfunction findPackageRoot(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n while (!existsSync(path.join(dir, \"package.json\"))) {\n const parent = path.dirname(dir);\n if (parent === dir)\n throw new Error(\"Could not find widget CLI package root\");\n dir = parent;\n }\n return dir;\n}\n","import { Command } from \"commander\";\nimport {\n buildWidgetPackage as buildWidgetPackageArtifacts,\n WidgetToolingError,\n type WidgetPackageBuildResult,\n} from \"@fluid-app/fluid-cli-widget-tooling\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n DEFAULT_WIDGET_OUT_DIR,\n validateDropletWidgetProject,\n withRootWidgetConfigBridge,\n} from \"../utils/source-package.js\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { runPackageScriptIfAvailable } from \"../utils/package-scripts.js\";\nimport { getWidgetCliVersion } from \"../utils/template.js\";\n\nexport interface BuildWidgetOptions {\n readonly outDir?: string;\n readonly skipTypecheck?: boolean;\n}\n\nexport interface BuildWidgetPackageOptions {\n readonly projectDir: string;\n readonly outDir: string;\n readonly skipTypecheck?: boolean;\n}\n\nexport interface BuildWidgetPackageResult {\n readonly outDir: string;\n readonly packageId: string;\n readonly version: string;\n}\n\nexport async function buildWidgetPackage(\n options: BuildWidgetPackageOptions,\n): Promise<BuildWidgetPackageResult> {\n await validateDropletWidgetProject(options.projectDir);\n\n if (options.skipTypecheck !== true) {\n await runPackageScriptIfAvailable({\n projectDir: options.projectDir,\n scriptName: \"typecheck\",\n });\n }\n\n let buildResult: WidgetPackageBuildResult;\n try {\n const cliVersion = await getWidgetCliVersion();\n buildResult = await withRootWidgetConfigBridge(options.projectDir, () =>\n buildWidgetPackageArtifacts({\n projectDir: options.projectDir,\n outDir: options.outDir,\n owner: \"droplet\",\n cliVersion,\n }),\n );\n } catch (error) {\n if (error instanceof WidgetToolingError && error.details) {\n throw new Error(`${error.message}\\n${error.details}`, { cause: error });\n }\n throw error;\n }\n\n return {\n outDir: buildResult.publishDir,\n packageId: buildResult.packageId,\n version: buildResult.version,\n };\n}\n\nexport const buildCommand: Command = new Command(\"build\")\n .description(\"Validate and build the current droplet widget package\")\n .option(\n \"-o, --out-dir <dir>\",\n \"Widget artifact output directory\",\n DEFAULT_WIDGET_OUT_DIR,\n )\n .option(\"--skip-typecheck\", \"Skip package typecheck script when present\")\n .action((options: BuildWidgetOptions) => {\n return runCliAction(async () => {\n const outDir = options.outDir ?? DEFAULT_WIDGET_OUT_DIR;\n console.log(chalk.blue.bold(\"Building Fluid widget package\"));\n console.log();\n\n const spinner = ora(\n \"Validating and building widget artifacts...\",\n ).start();\n const result = await buildWidgetPackage({\n projectDir: process.cwd(),\n outDir,\n skipTypecheck: options.skipTypecheck,\n });\n spinner.succeed(\"Built widget runtime artifacts\");\n\n console.log();\n console.log(chalk.gray(\"Package: \") + chalk.white(result.packageId));\n console.log(chalk.gray(\"Version: \") + chalk.white(result.version));\n console.log(chalk.gray(\"Output: \") + chalk.cyan(outDir));\n });\n });\n","/**\n * The shape contract for `ApiError.body` and `ApiError.data`.\n *\n * One decision, in one place: `body` is the response envelope exactly as the\n * server sent it, `data` is the unwrapped field-error bag. Rationale and the\n * alternatives considered live in `docs/api-error-data-contract.md`.\n */\n\n/**\n * The parsed JSON error response body, exactly as the server sent it.\n *\n * This is the envelope: `errors`, `error_message`, `error`, `status`, `meta`\n * and `request_id` all live here. `null` when the response carried no JSON\n * object — HTML, an empty body, a JSON primitive, or unparseable text.\n */\nexport type ApiErrorBody = Record<string, unknown> | null;\n\n/**\n * The field-level error bag: the envelope's `errors` value when the body has\n * one, otherwise the body itself.\n *\n * `errors` is declared `never` because unwrapping already consumed it — read\n * the envelope from `ApiError.body`, not from here. That makes the historical\n * mistake (`error.data.errors.some_field`, which silently resolved to\n * `undefined`) a typecheck failure instead of a degraded error message.\n */\nexport type ApiErrorFieldErrors = Record<string, unknown> & {\n errors?: never;\n};\n\n/**\n * Every value `ApiError.data` can hold. Fluid endpoints return an object bag,\n * but `errors` is occasionally an array or a string, and non-JSON responses\n * carry no data at all.\n */\nexport type ApiErrorData =\n | ApiErrorFieldErrors\n | readonly unknown[]\n | string\n | number\n | boolean\n | null;\n\n/**\n * Narrows a parsed JSON error payload to the envelope contract. Arrays and\n * primitives are not envelopes, so they resolve to `null` — their content is\n * still reachable through `ApiError.data`.\n */\nexport function toApiErrorBody(value: unknown): ApiErrorBody {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n\n/**\n * The single unwrap rule, shared by every producer of `ApiError`.\n *\n * `??` rather than `||` so an explicitly empty `errors` (`\"\"`, `0`, `false`)\n * is preserved instead of silently falling back to the whole envelope.\n */\nexport function toApiErrorData(body: ApiErrorBody): ApiErrorData {\n if (!body) {\n return null;\n }\n\n return (body.errors ?? body) as ApiErrorData;\n}\n","/**\n * Minimal, framework-agnostic fetch client for Fluid APIs\n * Compatible with fluid-admin patterns but usable standalone\n */\n\nimport type { ApiErrorBody, ApiErrorData } from \"./api-error-shape\";\nimport { toApiErrorBody, toApiErrorData } from \"./api-error-shape\";\n\nexport interface FetchClientConfig {\n /**\n * Base URL for all requests (e.g., \"https://api.fluid.app/api\")\n */\n baseUrl: string;\n\n /**\n * Optional function to get auth token\n * Return null/undefined if no token available\n */\n getAuthToken?: () => string | null | Promise<string | null>;\n\n /**\n * Optional callback when 401 auth error occurs\n */\n onAuthError?: () => void;\n\n /**\n * Default headers to include in all requests\n * Example: { \"x-fluid-client\": \"admin\" }\n */\n defaultHeaders?: Record<string, string>;\n\n /**\n * Credentials mode for fetch requests.\n * Set to `\"include\"` for cookie-based (same-origin BFF) authentication.\n * @default undefined (browser default: \"same-origin\")\n */\n credentials?: RequestCredentials;\n\n /**\n * Request cache mode for fetch requests.\n * @default undefined (browser default)\n */\n cache?: RequestCache;\n\n /**\n * Retry configuration for thrown network errors from fetch.\n * Does not retry HTTP error responses or aborted requests.\n * @default undefined (no retries)\n */\n networkRetry?: {\n maxRetries?: number;\n baseDelayMs?: number;\n };\n\n /**\n * Throw ApiError when a successful response declares JSON but cannot be parsed.\n * Defaults to false to preserve the legacy generated-client behavior.\n * @default false\n */\n throwOnInvalidJson?: boolean;\n}\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n headers?: Record<string, string>;\n params?: Record<string, unknown>;\n body?: unknown;\n signal?: AbortSignal;\n priority?: RequestInit[\"priority\"];\n}\n\n/**\n * API Error class compatible with fluid-admin's ApiError\n */\nexport class ApiError extends Error {\n public readonly status: number;\n\n /**\n * The unwrapped field-error bag. See `ApiErrorData`; the contract is\n * documented in `docs/api-error-data-contract.md`.\n */\n public readonly data: ApiErrorData;\n\n /**\n * The full error response envelope. Read `error_message`, `error`, `status`\n * and nested `errors` from here — `data` has already unwrapped one level.\n */\n public readonly body: ApiErrorBody;\n\n public readonly requestId?: string;\n\n constructor(\n message: string,\n status: number,\n data?: ApiErrorData,\n requestId?: string,\n body?: ApiErrorBody,\n ) {\n super(message);\n this.name = \"ApiError\";\n this.status = status;\n this.data = data ?? null;\n this.body = body ?? null;\n this.requestId = requestId;\n\n if (\"captureStackTrace\" in Error) {\n (\n Error as {\n captureStackTrace: (\n target: Error,\n constructor: NewableFunction,\n ) => void;\n }\n ).captureStackTrace(this, ApiError);\n }\n }\n\n toJSON(): {\n name: string;\n message: string;\n status: number;\n data: ApiErrorData;\n body: ApiErrorBody;\n requestId?: string;\n } {\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n data: this.data,\n body: this.body,\n requestId: this.requestId,\n };\n }\n}\n\nfunction getStringRequestId(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction getRequestIdFromHeaders(headers: Headers): string | undefined {\n return (\n getStringRequestId(headers.get(\"x-request-id\")) ??\n getStringRequestId(headers.get(\"request-id\")) ??\n getStringRequestId(headers.get(\"X-Request-ID\"))\n );\n}\n\nfunction getRequestIdFromJsonBody(body: unknown): string | undefined {\n if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n return undefined;\n }\n\n const record = body as Record<string, unknown>;\n const meta = record.meta;\n\n return (\n getStringRequestId(record.request_id) ??\n getStringRequestId(record.requestId) ??\n (meta && typeof meta === \"object\" && !Array.isArray(meta)\n ? (getStringRequestId((meta as Record<string, unknown>).request_id) ??\n getStringRequestId((meta as Record<string, unknown>).requestId))\n : undefined)\n );\n}\n\n/**\n * Type guard for ApiError\n */\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError;\n}\n\nexport interface FetchClientInstance {\n request: <TResponse = unknown>(\n endpoint: string,\n options?: RequestOptions,\n ) => Promise<TResponse>;\n requestWithFormData: <TResponse = unknown>(\n endpoint: string,\n formData: FormData,\n options?: Omit<RequestOptions, \"body\" | \"params\"> & {\n method?: \"POST\" | \"PUT\" | \"PATCH\";\n },\n ) => Promise<TResponse>;\n get: <TResponse = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: Omit<RequestOptions, \"method\" | \"params\">,\n ) => Promise<TResponse>;\n post: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ) => Promise<TResponse>;\n put: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ) => Promise<TResponse>;\n patch: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ) => Promise<TResponse>;\n delete: <TResponse = unknown>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\">,\n ) => Promise<TResponse>;\n}\n\n/**\n * Creates a configured fetch client instance\n */\nexport function createFetchClient(\n config: FetchClientConfig,\n): FetchClientInstance {\n const {\n baseUrl,\n getAuthToken,\n onAuthError,\n defaultHeaders = {},\n credentials,\n cache,\n networkRetry,\n throwOnInvalidJson = false,\n } = config;\n const maxNetworkRetries = Math.max(0, networkRetry?.maxRetries ?? 0);\n const baseNetworkRetryDelayMs = Math.max(0, networkRetry?.baseDelayMs ?? 0);\n\n /**\n * Build headers for a request\n */\n async function buildHeaders(\n customHeaders?: Record<string, string>,\n ): Promise<Record<string, string>> {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n ...defaultHeaders,\n ...customHeaders,\n };\n\n // Add auth token if available\n if (getAuthToken) {\n const token = await getAuthToken();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n return headers;\n }\n\n /**\n * Join baseUrl + endpoint via string concatenation (matches fetchApi).\n * Using `new URL(endpoint, baseUrl)` would strip any path prefix from\n * baseUrl (e.g. \"/api\") when the endpoint starts with \"/\".\n */\n function joinUrl(endpoint: string): string {\n return `${baseUrl}${endpoint}`;\n }\n\n /**\n * Build URL with query parameters for GET requests\n * Compatible with fluid-admin's query param handling\n */\n function buildUrl(\n endpoint: string,\n params?: Record<string, unknown>,\n ): string {\n const fullUrl = joinUrl(endpoint);\n\n if (!params || Object.keys(params).length === 0) {\n return fullUrl;\n }\n\n const queryString = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return; // Skip undefined/null values\n }\n\n if (Array.isArray(value)) {\n // Handle arrays like Rails expects: key[]\n value.forEach((item) => queryString.append(`${key}[]`, String(item)));\n } else if (typeof value === \"object\") {\n // Handle nested objects: key[subkey]\n Object.entries(value).forEach(([subKey, subValue]) => {\n if (subValue === undefined || subValue === null) {\n return;\n }\n\n if (Array.isArray(subValue)) {\n subValue.forEach((item) =>\n queryString.append(`${key}[${subKey}][]`, String(item)),\n );\n } else {\n queryString.append(`${key}[${subKey}]`, String(subValue));\n }\n });\n } else {\n queryString.append(key, String(value));\n }\n });\n\n const qs = queryString.toString();\n return qs ? `${fullUrl}?${qs}` : fullUrl;\n }\n\n /**\n * Shared response handler for both JSON and FormData requests.\n * Handles auth errors, non-OK responses, 204 No Content, and JSON parsing.\n */\n async function handleResponse<TResponse>(\n response: Response,\n method: string,\n _url: string,\n ): Promise<TResponse> {\n const headerRequestId = getRequestIdFromHeaders(response.headers);\n\n if (response.status === 401 && onAuthError) {\n onAuthError();\n }\n\n if (!response.ok) {\n // Read body as text first to avoid SyntaxError from response.json()\n // when server returns non-JSON bodies with application/json content-type.\n const errorText = await response.text().catch(() => \"\");\n const contentType = response.headers.get(\"content-type\");\n\n if (contentType?.includes(\"application/json\")) {\n // Parsed as `unknown` and narrowed before any property read: a body of\n // `null` (or a bare string/number/array) is valid JSON, and reading\n // `.error` off it directly threw a TypeError instead of an ApiError.\n let parsed: unknown;\n try {\n parsed = JSON.parse(errorText);\n } catch {\n throw new ApiError(\n errorText.slice(0, 200) ||\n `${method} request failed with status ${response.status}`,\n response.status,\n null,\n headerRequestId,\n );\n }\n\n const body = toApiErrorBody(parsed);\n // Only an object envelope can carry a message. Some Rails BFF endpoints\n // return `{ error: { message, details } }` instead of `{ message }` or\n // `{ error_message }`, so that shape is tried last.\n const msg = body\n ? (() => {\n const nestedError =\n typeof body.error === \"object\" && body.error !== null\n ? (body.error as { message?: unknown }).message\n : undefined;\n const directError =\n typeof body.error === \"string\" ? body.error : undefined;\n const message =\n typeof body.message === \"string\" ? body.message : undefined;\n const errorMessage =\n typeof body.error_message === \"string\"\n ? body.error_message\n : undefined;\n return (\n message ||\n errorMessage ||\n directError ||\n (typeof nestedError === \"string\" ? nestedError : undefined)\n );\n })()\n : undefined;\n\n throw new ApiError(\n msg || `${method} request failed with status ${response.status}`,\n response.status,\n body ? toApiErrorData(body) : (parsed as ApiErrorData),\n headerRequestId ?? getRequestIdFromJsonBody(parsed),\n body,\n );\n } else {\n throw new ApiError(\n `${method} request failed with status ${response.status}`,\n response.status,\n null,\n headerRequestId,\n );\n }\n }\n\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return null as TResponse;\n }\n\n const contentType = response.headers.get(\"content-type\");\n\n if (contentType?.includes(\"application/json\")) {\n const responseText = await response.text();\n\n try {\n const data = JSON.parse(responseText);\n return data as TResponse;\n } catch {\n if (throwOnInvalidJson) {\n throw new ApiError(\n \"Failed to parse response as JSON\",\n response.status,\n null,\n headerRequestId,\n );\n }\n\n // API declared JSON content-type but body isn't valid JSON.\n // Return the raw payload to preserve the legacy non-strict path.\n return responseText ? (responseText as TResponse) : (null as TResponse);\n }\n }\n\n // Non-JSON response (text/plain, text/html, etc.)\n return null as TResponse;\n }\n\n function getNetworkRetryDelayMs(retryAttempt: number): number {\n return baseNetworkRetryDelayMs * 2 ** (retryAttempt - 1);\n }\n\n async function waitForNetworkRetry(retryAttempt: number): Promise<void> {\n const delayMs = getNetworkRetryDelayMs(retryAttempt);\n if (delayMs <= 0) {\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n async function fetchWithNetworkRetry(\n url: string,\n fetchOptions: RequestInit,\n signal?: AbortSignal,\n ): Promise<Response> {\n let retryCount = 0;\n\n while (true) {\n try {\n return await fetch(url, fetchOptions);\n } catch (networkError) {\n if (signal?.aborted || retryCount >= maxNetworkRetries) {\n throw networkError;\n }\n\n retryCount += 1;\n await waitForNetworkRetry(retryCount);\n\n if (signal?.aborted) {\n throw networkError;\n }\n }\n }\n }\n\n /**\n * Main request function\n */\n async function request<TResponse = unknown>(\n endpoint: string,\n options: RequestOptions = {},\n ): Promise<TResponse> {\n const {\n method = \"GET\",\n headers: customHeaders,\n params,\n body,\n signal,\n priority,\n } = options;\n\n const url = params ? buildUrl(endpoint, params) : joinUrl(endpoint);\n\n const headers = await buildHeaders(customHeaders);\n\n let response: Response;\n\n try {\n const fetchOptions: RequestInit = { method, headers };\n if (credentials) fetchOptions.credentials = credentials;\n if (cache) fetchOptions.cache = cache;\n if (priority) fetchOptions.priority = priority;\n const serializedBody =\n body && method !== \"GET\" ? JSON.stringify(body) : null;\n if (serializedBody) fetchOptions.body = serializedBody;\n if (signal) fetchOptions.signal = signal;\n response = await fetchWithNetworkRetry(url, fetchOptions, signal);\n } catch (networkError) {\n throw new ApiError(\n `Network error: ${networkError instanceof Error ? networkError.message : \"Unknown network error\"}`,\n 0,\n null,\n );\n }\n\n return handleResponse<TResponse>(response, method, url);\n }\n\n /**\n * Request with FormData (for file uploads)\n */\n async function requestWithFormData<TResponse = unknown>(\n endpoint: string,\n formData: FormData,\n options: Omit<RequestOptions, \"body\" | \"params\"> & {\n method?: \"POST\" | \"PUT\" | \"PATCH\";\n } = {},\n ): Promise<TResponse> {\n const {\n method = \"POST\",\n headers: customHeaders,\n signal,\n priority,\n } = options;\n\n const url = joinUrl(endpoint);\n const headers = await buildHeaders(customHeaders);\n\n // Remove Content-Type to let browser set it with boundary\n delete headers[\"Content-Type\"];\n\n let response: Response;\n\n try {\n const fetchOptions: RequestInit = { method, headers, body: formData };\n if (credentials) fetchOptions.credentials = credentials;\n if (cache) fetchOptions.cache = cache;\n if (priority) fetchOptions.priority = priority;\n if (signal) fetchOptions.signal = signal;\n response = await fetchWithNetworkRetry(url, fetchOptions, signal);\n } catch (networkError) {\n throw new ApiError(\n `Network error: ${networkError instanceof Error ? networkError.message : \"Unknown network error\"}`,\n 0,\n null,\n );\n }\n\n return handleResponse<TResponse>(response, method, url);\n }\n\n // Return client with convenience methods\n return {\n request: request,\n requestWithFormData: requestWithFormData,\n\n // Convenience methods for common HTTP verbs\n get: <TResponse = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: Omit<RequestOptions, \"method\" | \"params\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"GET\" as const,\n ...(params && { params }),\n }),\n\n post: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"POST\",\n body,\n }),\n\n put: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"PUT\",\n body,\n }),\n\n patch: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"PATCH\",\n body,\n }),\n\n delete: <TResponse = unknown>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"DELETE\",\n }),\n };\n}\n\nexport type FetchClient = FetchClientInstance;\n","import type { ApiErrorBody, ApiErrorData } from \"./api-error-shape\";\nimport { toApiErrorBody, toApiErrorData } from \"./api-error-shape\";\nimport { ApiError } from \"./fetch-client\";\n\nexport interface HeyApiErrorRequestOptions {\n method?: string;\n}\n\nexport interface HeyApiErrorInterceptorOptions {\n onResponseError?: (response: Response) => void;\n shouldPassThroughTransportError?: (error: unknown) => boolean;\n}\n\nexport type HeyApiErrorInterceptor = (\n error: unknown,\n response: Response | undefined,\n request: Request | undefined,\n options: HeyApiErrorRequestOptions,\n) => unknown;\n\nfunction getNonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction getRequestId(\n response: Response,\n error: ApiErrorBody,\n): string | undefined {\n const meta = toApiErrorBody(error?.meta);\n\n return (\n getNonEmptyString(response.headers.get(\"x-request-id\")) ??\n getNonEmptyString(response.headers.get(\"request-id\")) ??\n getNonEmptyString(error?.request_id) ??\n getNonEmptyString(error?.requestId) ??\n getNonEmptyString(meta?.request_id) ??\n getNonEmptyString(meta?.requestId)\n );\n}\n\nfunction getErrorMessage(\n error: Record<string, unknown>,\n fallback: string,\n): string {\n const nestedError = toApiErrorBody(error.error);\n\n return (\n getNonEmptyString(error.message) ??\n getNonEmptyString(error.error_message) ??\n getNonEmptyString(nestedError?.message) ??\n fallback\n );\n}\n\n/**\n * Creates an error interceptor compatible with generated Hey API fetch clients.\n * Consumer-specific auth and cancellation policy is supplied through callbacks,\n * keeping this package independent from generated client types.\n */\nexport function createHeyApiErrorInterceptor(\n options: HeyApiErrorInterceptorOptions = {},\n): HeyApiErrorInterceptor {\n return (error, response, request, requestOptions) => {\n if (!response) {\n if (error instanceof ApiError) {\n return error;\n }\n\n if (options.shouldPassThroughTransportError?.(error)) {\n return error;\n }\n\n // Request construction and auth callbacks run before dispatch. Preserve\n // those errors instead of reporting them as network failures.\n if (!request) {\n return error;\n }\n\n return new ApiError(\n `Network error: ${error instanceof Error ? error.message : \"Unknown network error\"}`,\n 0,\n null,\n );\n }\n\n // Generated clients surface malformed JSON bodies as SyntaxError. Map an\n // otherwise successful response to the shared strict parse contract.\n if (response.ok && error instanceof SyntaxError) {\n return new ApiError(\n \"Failed to parse response as JSON\",\n response.status,\n null,\n getRequestId(response, null),\n );\n }\n\n options.onResponseError?.(response);\n\n const method = request?.method ?? requestOptions.method ?? \"GET\";\n const errorRecord = toApiErrorBody(error);\n const requestId = getRequestId(response, errorRecord);\n\n if (errorRecord) {\n // `data` is the unwrapped field-error bag, `body` the whole envelope.\n // Both derive from one shared rule — see docs/api-error-data-contract.md.\n return new ApiError(\n getErrorMessage(errorRecord, `${method} request failed`),\n response.status,\n toApiErrorData(errorRecord),\n requestId,\n errorRecord,\n );\n }\n\n const isJson = response.headers\n .get(\"content-type\")\n ?.includes(\"application/json\");\n const text = getNonEmptyString(error);\n\n return new ApiError(\n isJson && text\n ? text.slice(0, 200)\n : `${method} request failed with status ${response.status}`,\n response.status,\n // A parsed JSON string is a legal `ApiErrorData` member, so it is kept\n // rather than dropped — the shared fetch client already preserves it, and\n // discarding it here made the two producers disagree.\n isJson ? (error as ApiErrorData) : null,\n requestId,\n // Unreachable as an envelope: this branch runs only when the payload is\n // not a plain object, which is exactly what `toApiErrorBody` rejects.\n null,\n );\n };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n ArrayStyle,\n ObjectStyle,\n SerializerOptions,\n} from \"./pathSerializer.gen\";\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: unknown) => unknown;\n\ntype QuerySerializerOptionsObject = {\n allowReserved?: boolean;\n array?: Partial<SerializerOptions<ArrayStyle>>;\n object?: Partial<SerializerOptions<ObjectStyle>>;\n};\n\nexport type QuerySerializerOptions = QuerySerializerOptionsObject & {\n /**\n * Per-parameter serialization overrides. When provided, these settings\n * override the global array/object settings for specific parameter names.\n */\n parameters?: Record<string, QuerySerializerOptionsObject>;\n};\n\nconst serializeFormDataPair = (\n data: FormData,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\" || value instanceof Blob) {\n data.append(key, value);\n } else if (value instanceof Date) {\n data.append(key, value.toISOString());\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (\n data: URLSearchParams,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\") {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: (body: unknown): FormData => {\n const data = new FormData();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: (body: unknown): string =>\n JSON.stringify(body, (_key, value) =>\n typeof value === \"bigint\" ? value.toString() : value,\n ),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: (body: unknown): string => {\n const data = new URLSearchParams();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\ntype Slot = \"body\" | \"headers\" | \"path\" | \"query\";\n\nexport type Field =\n | {\n in: Exclude<Slot, \"body\">;\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If omitted, we use the same value as `key`.\n */\n map?: string;\n }\n | {\n in: Extract<Slot, \"body\">;\n /**\n * Key isn't required for bodies.\n */\n key?: string;\n map?: string;\n }\n | {\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If `in` is omitted, `map` aliases `key` to the transport layer.\n */\n map: Slot;\n };\n\nexport interface Fields {\n allowExtra?: Partial<Record<Slot, boolean>>;\n args?: ReadonlyArray<Field>;\n}\n\nexport type FieldsConfig = ReadonlyArray<Field | Fields>;\n\nconst extraPrefixesMap: Record<string, Slot> = {\n $body_: \"body\",\n $headers_: \"headers\",\n $path_: \"path\",\n $query_: \"query\",\n};\nconst extraPrefixes = Object.entries(extraPrefixesMap);\n\ntype KeyMap = Map<\n string,\n | {\n in: Slot;\n map?: string;\n }\n | {\n in?: never;\n map: Slot;\n }\n>;\n\nfunction buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {\n if (!map) {\n map = new Map();\n }\n\n for (const config of fields) {\n if (\"in\" in config) {\n if (config.key) {\n map.set(config.key, {\n in: config.in,\n map: config.map,\n });\n }\n } else if (\"key\" in config) {\n map.set(config.key, {\n map: config.map,\n });\n } else if (config.args) {\n buildKeyMap(config.args, map);\n }\n }\n\n return map;\n}\n\ninterface Params {\n body?: unknown;\n headers: Record<string, unknown>;\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n}\n\nfunction stripEmptySlots(params: Params): void {\n for (const [slot, value] of Object.entries(params)) {\n if (slot === \"body\") continue;\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !Object.keys(value).length\n ) {\n delete params[slot as Slot];\n }\n }\n}\n\nexport function buildClientParams(\n args: ReadonlyArray<unknown>,\n fields: FieldsConfig,\n): Params {\n const params: Params = {\n headers: Object.create(null),\n path: Object.create(null),\n query: Object.create(null),\n };\n\n const map = buildKeyMap(fields);\n\n function writeSlot(slot: Slot, key: string, value: unknown): void {\n let record = params[slot] as Record<string, unknown> | undefined;\n if (record === undefined) {\n record = Object.create(null) as Record<string, unknown>;\n params[slot] = record;\n }\n record[key] = value;\n }\n\n let config: FieldsConfig[number] | undefined;\n\n for (const [index, arg] of args.entries()) {\n if (fields[index]) {\n config = fields[index];\n }\n\n if (!config) {\n continue;\n }\n\n if (\"in\" in config) {\n if (config.key) {\n const field = map.get(config.key)!;\n const name = field.map || config.key;\n if (field.in) {\n writeSlot(field.in, name, arg);\n }\n } else {\n params.body = arg;\n }\n } else {\n for (const [key, value] of Object.entries(arg ?? {})) {\n const field = map.get(key);\n\n if (field) {\n if (field.in) {\n const name = field.map || key;\n writeSlot(field.in, name, value);\n } else {\n params[field.map] = value;\n }\n } else {\n const extra = extraPrefixes.find(([prefix]) =>\n key.startsWith(prefix),\n );\n\n if (extra) {\n const [prefix, slot] = extra;\n writeSlot(slot, key.slice(prefix.length), value);\n } else if (\"allowExtra\" in config && config.allowExtra) {\n for (const [slot, allowed] of Object.entries(config.allowExtra)) {\n if (allowed) {\n writeSlot(slot as Slot, key, value);\n break;\n }\n }\n }\n }\n }\n }\n }\n\n stripEmptySlots(params);\n\n return params;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from \"./types.gen\";\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<\n RequestInit,\n \"method\"\n> &\n Pick<Config, \"method\" | \"responseTransformer\" | \"responseValidator\"> & {\n /**\n * Fetch API implementation. You can use this option to provide a custom\n * fetch instance.\n *\n * @default globalThis.fetch\n */\n fetch?: typeof fetch;\n /**\n * Implementing clients can call request interceptors inside this hook.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n /**\n * Callback invoked when a network or parsing error occurs during streaming.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param error The error that occurred.\n */\n onSseError?: (error: unknown) => void;\n /**\n * Callback invoked when an event is streamed from the server.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param event Event streamed from the server.\n * @returns Nothing (void).\n */\n onSseEvent?: (event: StreamEvent<TData>) => void;\n serializedBody?: RequestInit[\"body\"];\n /**\n * Default retry delay in milliseconds.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 3000\n */\n sseDefaultRetryDelay?: number;\n /**\n * Maximum number of retry attempts before giving up.\n */\n sseMaxRetryAttempts?: number;\n /**\n * Maximum retry delay in milliseconds.\n *\n * Applies only when exponential backoff is used.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 30000\n */\n sseMaxRetryDelay?: number;\n /**\n * Optional sleep function for retry backoff.\n *\n * Defaults to using `setTimeout`.\n */\n sseSleepFn?: (ms: number) => Promise<void>;\n url: string;\n };\n\nexport interface StreamEvent<TData = unknown> {\n data: TData;\n event?: string;\n id?: string;\n retry?: number;\n}\n\nexport type ServerSentEventsResult<\n TData = unknown,\n TReturn = void,\n TNext = unknown,\n> = {\n stream: AsyncGenerator<\n TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n TReturn,\n TNext\n >;\n};\n\nexport function createSseClient<TData = unknown>({\n onRequest,\n onSseError,\n onSseEvent,\n responseTransformer,\n responseValidator,\n sseDefaultRetryDelay,\n sseMaxRetryAttempts,\n sseMaxRetryDelay,\n sseSleepFn,\n url,\n ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> {\n let lastEventId: string | undefined;\n\n const sleep =\n sseSleepFn ??\n ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const createStream = async function* () {\n let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n let attempt = 0;\n const signal = options.signal ?? new AbortController().signal;\n\n while (true) {\n if (signal.aborted) break;\n\n attempt++;\n\n const headers =\n options.headers instanceof Headers\n ? options.headers\n : new Headers(options.headers as Record<string, string> | undefined);\n\n if (lastEventId !== undefined) {\n headers.set(\"Last-Event-ID\", lastEventId);\n }\n\n try {\n const requestInit: RequestInit = {\n redirect: \"follow\",\n ...options,\n body: options.serializedBody,\n headers,\n signal,\n };\n let request = new Request(url, requestInit);\n if (onRequest) {\n request = await onRequest(url, requestInit);\n }\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = options.fetch ?? globalThis.fetch;\n const response = await _fetch(request);\n\n if (!response.ok)\n throw new Error(\n `SSE failed: ${response.status} ${response.statusText}`,\n );\n\n if (!response.body) throw new Error(\"No body in SSE response\");\n\n const reader = response.body\n .pipeThrough(new TextDecoderStream())\n .getReader();\n\n let buffer = \"\";\n\n const abortHandler = () => {\n try {\n reader.cancel();\n } catch {\n // noop\n }\n };\n\n signal.addEventListener(\"abort\", abortHandler);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += value;\n buffer = buffer.replace(/\\r\\n?/g, \"\\n\"); // normalize line endings\n\n const chunks = buffer.split(\"\\n\\n\");\n buffer = chunks.pop() ?? \"\";\n\n for (const chunk of chunks) {\n const lines = chunk.split(\"\\n\");\n const dataLines: Array<string> = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith(\"data:\")) {\n dataLines.push(line.replace(/^data:\\s*/, \"\"));\n } else if (line.startsWith(\"event:\")) {\n eventName = line.replace(/^event:\\s*/, \"\");\n } else if (line.startsWith(\"id:\")) {\n lastEventId = line.replace(/^id:\\s*/, \"\");\n } else if (line.startsWith(\"retry:\")) {\n const parsed = Number.parseInt(\n line.replace(/^retry:\\s*/, \"\"),\n 10,\n );\n if (!Number.isNaN(parsed)) {\n retryDelay = parsed;\n }\n }\n }\n\n let data: unknown;\n let parsedJson = false;\n\n if (dataLines.length) {\n const rawData = dataLines.join(\"\\n\");\n try {\n data = JSON.parse(rawData);\n parsedJson = true;\n } catch {\n data = rawData;\n }\n }\n\n if (parsedJson) {\n if (responseValidator) {\n await responseValidator(data);\n }\n\n if (responseTransformer) {\n data = await responseTransformer(data);\n }\n }\n\n onSseEvent?.({\n data,\n event: eventName,\n id: lastEventId,\n retry: retryDelay,\n });\n\n if (dataLines.length) {\n yield data as any;\n }\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abortHandler);\n reader.releaseLock();\n }\n\n break; // exit loop on normal completion\n } catch (error) {\n // connection failed or aborted; retry after delay\n onSseError?.(error);\n\n if (\n sseMaxRetryAttempts !== undefined &&\n attempt >= sseMaxRetryAttempts\n ) {\n break; // stop after firing error\n }\n\n // exponential backoff: double retry each attempt, cap at 30s\n const backoff = Math.min(\n retryDelay * 2 ** (attempt - 1),\n sseMaxRetryDelay ?? 30000,\n );\n await sleep(backoff);\n }\n }\n };\n\n const stream = createStream();\n\n return { stream };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\ninterface SerializeOptions<T>\n extends SerializePrimitiveOptions, SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = \"label\" | \"matrix\" | \"simple\";\nexport type ObjectStyle = \"form\" | \"deepObject\";\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (\n style: ArraySeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const separatorArrayNoExplode = (\n style: ArraySeparatorStyle,\n): \",\" | \"|\" | \"%20\" => {\n switch (style) {\n case \"form\":\n return \",\";\n case \"pipeDelimited\":\n return \"|\";\n case \"spaceDelimited\":\n return \"%20\";\n default:\n return \",\";\n }\n};\n\nexport const separatorObjectExplode = (\n style: ObjectSeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}): string => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n case \"simple\":\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === \"label\" || style === \"simple\") {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam): string => {\n if (value === undefined || value === null) {\n return \"\";\n }\n\n if (typeof value === \"object\") {\n throw new Error(\n \"Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.\",\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n valueOnly,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n valueOnly?: boolean;\n}): string => {\n if (value instanceof Date) {\n return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;\n }\n\n if (style !== \"deepObject\" && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [\n ...values,\n key,\n allowReserved ? (v as string) : encodeURIComponent(v as string),\n ];\n });\n const joinedValues = values.join(\",\");\n switch (style) {\n case \"form\":\n return `${name}=${joinedValues}`;\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === \"deepObject\" ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { BodySerializer, QuerySerializer } from \"./bodySerializer.gen\";\nimport {\n type ArraySeparatorStyle,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"./pathSerializer.gen\";\n\nexport interface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nexport const PATH_PARAM_RE: RegExp = /\\{[^{}]+\\}/g;\n\nexport const defaultPathSerializer = ({\n path,\n url: _url,\n}: PathSerializer): string => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = \"simple\";\n\n if (name.endsWith(\"*\")) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith(\".\")) {\n name = name.substring(1);\n style = \"label\";\n } else if (name.startsWith(\";\")) {\n name = name.substring(1);\n style = \"matrix\";\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(\n match,\n serializeArrayParam({ explode, name, style, value }),\n );\n continue;\n }\n\n if (typeof value === \"object\") {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n valueOnly: true,\n }),\n );\n continue;\n }\n\n if (style === \"matrix\") {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === \"label\" ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}): string => {\n const pathUrl = _url.startsWith(\"/\") ? _url : `/${_url}`;\n let url = (baseUrl ?? \"\") + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : \"\";\n if (search.startsWith(\"?\")) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport function getValidRequestBody(options: {\n body?: unknown;\n bodySerializer?: BodySerializer | null;\n serializedBody?: unknown;\n}): unknown {\n const hasBody = options.body !== undefined;\n const isSerializedBody = hasBody && options.bodySerializer;\n\n if (isSerializedBody) {\n if (\"serializedBody\" in options) {\n const hasSerializedBody =\n options.serializedBody !== undefined && options.serializedBody !== \"\";\n\n return hasSerializedBody ? options.serializedBody : null;\n }\n\n // not all clients implement a serializedBody property (i.e., client-axios)\n return options.body !== \"\" ? options.body : null;\n }\n\n // plain/text body\n if (hasBody) {\n return options.body;\n }\n\n // no body was provided\n return undefined;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nexport type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: \"header\" | \"query\" | \"cookie\";\n /**\n * A unique identifier for the security scheme.\n *\n * Defined only when there are multiple security schemes whose `Auth`\n * shape would otherwise be identical.\n */\n key?: string;\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: \"basic\" | \"bearer\";\n type: \"apiKey\" | \"http\";\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token =\n typeof callback === \"function\" ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === \"bearer\") {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === \"basic\") {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { getAuthToken } from \"../core/auth.gen\";\nimport type { QuerySerializerOptions } from \"../core/bodySerializer.gen\";\nimport { jsonBodySerializer } from \"../core/bodySerializer.gen\";\nimport {\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"../core/pathSerializer.gen\";\nimport { getUrl } from \"../core/utils.gen\";\nimport type {\n Client,\n ClientOptions,\n Config,\n RequestOptions,\n} from \"./types.gen\";\n\nexport const createQuerySerializer = <T = unknown>({\n parameters = {},\n ...args\n}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {\n const querySerializer = (queryParams: T): string => {\n const search: string[] = [];\n if (queryParams && typeof queryParams === \"object\") {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const options = parameters[name] || args;\n\n if (Array.isArray(value)) {\n const serializedArray = serializeArrayParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"form\",\n value,\n ...options.array,\n });\n if (serializedArray) search.push(serializedArray);\n } else if (typeof value === \"object\") {\n const serializedObject = serializeObjectParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"deepObject\",\n value: value as Record<string, unknown>,\n ...options.object,\n });\n if (serializedObject) search.push(serializedObject);\n } else {\n const serializedPrimitive = serializePrimitiveParam({\n allowReserved: options.allowReserved,\n name,\n value: value as string,\n });\n if (serializedPrimitive) search.push(serializedPrimitive);\n }\n }\n }\n return search.join(\"&\");\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (\n contentType: string | null,\n): Exclude<Config[\"parseAs\"], \"auto\"> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return \"stream\";\n }\n\n const cleanContent = contentType.split(\";\")[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (\n cleanContent.startsWith(\"application/json\") ||\n cleanContent.endsWith(\"+json\")\n ) {\n return \"json\";\n }\n\n if (cleanContent === \"multipart/form-data\") {\n return \"formData\";\n }\n\n if (\n [\"application/\", \"audio/\", \"image/\", \"video/\"].some((type) =>\n cleanContent.startsWith(type),\n )\n ) {\n return \"blob\";\n }\n\n if (cleanContent.startsWith(\"text/\")) {\n return \"text\";\n }\n\n return;\n};\n\nconst checkForExistence = (\n options: Pick<RequestOptions, \"auth\" | \"query\"> & {\n headers: Headers;\n },\n name?: string,\n): boolean => {\n if (!name) {\n return false;\n }\n if (\n options.headers.has(name) ||\n options.query?.[name] ||\n options.headers.get(\"Cookie\")?.includes(`${name}=`)\n ) {\n return true;\n }\n return false;\n};\n\nexport async function setAuthParams(\n options: Pick<RequestOptions, \"auth\" | \"query\" | \"security\"> & {\n headers: Headers;\n },\n): Promise<void> {\n for (const auth of options.security ?? []) {\n if (checkForExistence(options, auth.name)) {\n continue;\n }\n\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? \"Authorization\";\n\n switch (auth.in) {\n case \"query\":\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case \"cookie\":\n options.headers.append(\"Cookie\", `${name}=${token}`);\n break;\n case \"header\":\n default:\n options.headers.set(name, token);\n break;\n }\n }\n}\n\nexport const buildUrl: Client[\"buildUrl\"] = (options) =>\n getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === \"function\"\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith(\"/\")) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nconst headersEntries = (headers: Headers): Array<[string, string]> => {\n const entries: Array<[string, string]> = [];\n headers.forEach((value, key) => {\n entries.push([key, value]);\n });\n return entries;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>[\"headers\"] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header) {\n continue;\n }\n\n const iterator =\n header instanceof Headers\n ? headersEntries(header)\n : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e., their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === \"object\" ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n /** response may be undefined due to a network error where no response object is produced */\n response: Res | undefined,\n /** request may be undefined, because error may be from building the request object itself */\n request: Req | undefined,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (\n request: Req,\n options: Options,\n) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n fns: Array<Interceptor | null> = [];\n\n clear(): void {\n this.fns = [];\n }\n\n eject(id: number | Interceptor): void {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = null;\n }\n }\n\n exists(id: number | Interceptor): boolean {\n const index = this.getInterceptorIndex(id);\n return Boolean(this.fns[index]);\n }\n\n getInterceptorIndex(id: number | Interceptor): number {\n if (typeof id === \"number\") {\n return this.fns[id] ? id : -1;\n }\n return this.fns.indexOf(id);\n }\n\n update(\n id: number | Interceptor,\n fn: Interceptor,\n ): number | Interceptor | false {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = fn;\n return id;\n }\n return false;\n }\n\n use(fn: Interceptor): number {\n this.fns.push(fn);\n return this.fns.length - 1;\n }\n}\n\nexport interface Middleware<Req, Res, Err, Options> {\n error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;\n request: Interceptors<ReqInterceptor<Req, Options>>;\n response: Interceptors<ResInterceptor<Res, Req, Options>>;\n}\n\nexport const createInterceptors = <Req, Res, Err, Options>(): Middleware<\n Req,\n Res,\n Err,\n Options\n> => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: \"form\",\n },\n object: {\n explode: true,\n style: \"deepObject\",\n },\n});\n\nconst defaultHeaders = {\n \"Content-Type\": \"application/json\",\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: \"auto\",\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { createSseClient } from \"../core/serverSentEvents.gen\";\nimport type { HttpMethod } from \"../core/types.gen\";\nimport { getValidRequestBody } from \"../core/utils.gen\";\nimport type {\n Client,\n Config,\n RequestOptions,\n ResolvedRequestOptions,\n} from \"./types.gen\";\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from \"./utils.gen\";\n\ntype ReqInit = Omit<RequestInit, \"body\" | \"headers\"> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<\n Request,\n Response,\n unknown,\n ResolvedRequestOptions\n >();\n\n const beforeRequest = async <\n TData = unknown,\n TResponseStyle extends \"data\" | \"fields\" = \"fields\",\n ThrowOnError extends boolean = boolean,\n Url extends string = string,\n >(\n options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,\n ) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n serializedBody: undefined as string | undefined,\n };\n\n if (opts.security) {\n await setAuthParams(opts);\n }\n\n if (opts.requestValidator) {\n await opts.requestValidator(opts);\n }\n\n if (opts.body !== undefined && opts.bodySerializer) {\n opts.serializedBody = opts.bodySerializer(opts.body) as\n | string\n | undefined;\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.serializedBody === \"\") {\n opts.headers.delete(\"Content-Type\");\n }\n\n const resolvedOpts = opts as typeof opts &\n ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;\n const url = buildUrl(resolvedOpts);\n\n return { opts: resolvedOpts, url };\n };\n\n const request: Client[\"request\"] = async (options) => {\n const throwOnError = options.throwOnError ?? _config.throwOnError;\n const responseStyle = options.responseStyle ?? _config.responseStyle;\n\n let request: Request | undefined;\n let response: Response | undefined;\n\n try {\n const { opts, url } = await beforeRequest(options);\n const requestInit: ReqInit = {\n redirect: \"follow\",\n ...opts,\n body: getValidRequestBody(opts),\n };\n\n request = new Request(url, requestInit);\n\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n\n response = await _fetch(request);\n\n for (const fn of interceptors.response.fns) {\n if (fn) {\n response = await fn(response, request, opts);\n }\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n const parseAs =\n (opts.parseAs === \"auto\"\n ? getParseAs(response.headers.get(\"Content-Type\"))\n : opts.parseAs) ?? \"json\";\n\n if (\n response.status === 204 ||\n response.headers.get(\"Content-Length\") === \"0\"\n ) {\n let emptyData: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"text\":\n emptyData = await response[parseAs]();\n break;\n case \"formData\":\n emptyData = new FormData();\n break;\n case \"stream\":\n emptyData = response.body;\n break;\n case \"json\":\n default:\n emptyData = {};\n break;\n }\n return opts.responseStyle === \"data\"\n ? emptyData\n : {\n data: emptyData,\n ...result,\n };\n }\n\n let data: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"formData\":\n case \"text\":\n data = await response[parseAs]();\n break;\n case \"json\": {\n // Some servers return 200 with no Content-Length and empty body.\n // response.json() would throw; read as text and parse if non-empty.\n const text = await response.text();\n data = text ? JSON.parse(text) : {};\n break;\n }\n case \"stream\":\n return opts.responseStyle === \"data\"\n ? response.body\n : {\n data: response.body,\n ...result,\n };\n }\n\n if (parseAs === \"json\") {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return opts.responseStyle === \"data\"\n ? data\n : {\n data,\n ...result,\n };\n }\n\n const textError = await response.text();\n let jsonError: unknown;\n\n try {\n jsonError = JSON.parse(textError);\n } catch {\n // noop\n }\n\n throw jsonError ?? textError;\n } catch (error) {\n let finalError = error;\n\n for (const fn of interceptors.error.fns) {\n if (fn) {\n finalError = await fn(\n finalError,\n response,\n request,\n options as ResolvedRequestOptions,\n );\n }\n }\n\n finalError = finalError || {};\n\n if (throwOnError) {\n throw finalError;\n }\n\n // TODO: we probably want to return error and improve types\n return responseStyle === \"data\"\n ? undefined\n : {\n error: finalError,\n request,\n response,\n };\n }\n };\n\n const makeMethodFn =\n (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>\n request({ ...options, method });\n\n const makeSseFn =\n (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {\n const { opts, url } = await beforeRequest(options);\n return createSseClient({\n ...opts,\n body: opts.body as BodyInit | null | undefined,\n method,\n onRequest: async (url, init) => {\n let request = new Request(url, init);\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n return request;\n },\n serializedBody: getValidRequestBody(opts) as\n | BodyInit\n | null\n | undefined,\n url,\n });\n };\n\n const _buildUrl: Client[\"buildUrl\"] = (options) =>\n buildUrl({ ..._config, ...options });\n\n return {\n buildUrl: _buildUrl,\n connect: makeMethodFn(\"CONNECT\"),\n delete: makeMethodFn(\"DELETE\"),\n get: makeMethodFn(\"GET\"),\n getConfig,\n head: makeMethodFn(\"HEAD\"),\n interceptors,\n options: makeMethodFn(\"OPTIONS\"),\n patch: makeMethodFn(\"PATCH\"),\n post: makeMethodFn(\"POST\"),\n put: makeMethodFn(\"PUT\"),\n request,\n setConfig,\n sse: {\n connect: makeSseFn(\"CONNECT\"),\n delete: makeSseFn(\"DELETE\"),\n get: makeSseFn(\"GET\"),\n head: makeSseFn(\"HEAD\"),\n options: makeSseFn(\"OPTIONS\"),\n patch: makeSseFn(\"PATCH\"),\n post: makeSseFn(\"POST\"),\n put: makeSseFn(\"PUT\"),\n trace: makeSseFn(\"TRACE\"),\n },\n trace: makeMethodFn(\"TRACE\"),\n } as Client;\n};\n","import { createHeyApiErrorInterceptor } from \"@fluid-app/api-client-core\";\nimport { type Client, createClient } from \"@fluid-app/hey-api-fetch-runtime\";\n\nexport type FluidOsHeyApiClient = Client;\n\nexport interface FluidOsHeyApiClientConfig {\n baseUrl: string;\n fetch?: typeof fetch;\n getAuthToken?: () =>\n | string\n | null\n | undefined\n | Promise<string | null | undefined>;\n defaultHeaders?: Record<string, string>;\n onAuthError?: () => void;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n (error instanceof DOMException && error.name === \"AbortError\") ||\n (error instanceof Error && error.name === \"AbortError\")\n );\n}\n\nexport function createFluidOsHeyApiClient(\n config: FluidOsHeyApiClientConfig,\n): Client {\n const client = createClient({\n auth: async () => (await config.getAuthToken?.()) ?? undefined,\n baseUrl: config.baseUrl,\n fetch: config.fetch,\n headers: {\n Accept: \"application/json\",\n ...config.defaultHeaders,\n },\n throwOnError: true,\n });\n\n client.interceptors.error.use(\n createHeyApiErrorInterceptor({\n onResponseError: (response) => {\n if (response.status === 401) {\n config.onAuthError?.();\n }\n },\n shouldPassThroughTransportError: isAbortError,\n }),\n );\n\n return client;\n}\n","import { findProjectConfig, readConfig } from \"@fluid-app/fluid-cli\";\nimport {\n createFluidOsHeyApiClient,\n type FluidOsHeyApiClient,\n} from \"@fluid-app/fluidos-api-client\";\nimport chalk from \"chalk\";\n\nexport interface AuthenticatedClientResult {\n readonly client: FluidOsHeyApiClient;\n}\n\nexport function createAuthenticatedClient(): AuthenticatedClientResult {\n return { client: createAuthenticatedWidgetPackageClient() };\n}\n\nexport function createAuthenticatedWidgetPackageClient(): FluidOsHeyApiClient {\n const { profile, profileName, token } = resolveAuthenticatedProfile();\n if (!token) {\n if (!profileName) {\n throw new Error(\n \"Not logged in. Run \" + chalk.cyan(\"fluid login\") + \" first.\",\n );\n }\n throw new Error(\n \"No auth token found for profile \" +\n chalk.cyan(profileName) +\n \". Run \" +\n chalk.cyan(\"fluid login\") +\n \" to re-authenticate.\",\n );\n }\n\n return createFluidOsHeyApiClient({\n baseUrl:\n profile?.baseUrl ??\n process.env[\"FLUID_API_BASE\"] ??\n \"https://api.fluid.app\",\n getAuthToken: () => token,\n });\n}\n\ntype ProfileWithBaseUrl = ReturnType<typeof readConfig>[\"profiles\"][string] & {\n readonly baseUrl?: string;\n};\n\nfunction resolveAuthenticatedProfile(): {\n readonly profile?: ProfileWithBaseUrl;\n readonly profileName?: string;\n readonly token?: string;\n} {\n const config = readConfig();\n const projectConfig = findProjectConfig(process.cwd());\n\n if (projectConfig?.profile) {\n const profile = config.profiles[projectConfig.profile] as\n | ProfileWithBaseUrl\n | undefined;\n if (profile) {\n return {\n profile,\n profileName: projectConfig.profile,\n token: profile.token,\n };\n }\n }\n\n if (!config.activeProfile) return {};\n const profile = config.profiles[config.activeProfile] as\n | ProfileWithBaseUrl\n | undefined;\n if (!profile) return {};\n\n return {\n profile,\n profileName: config.activeProfile,\n token: profile.token,\n };\n}\n","/**\n * Git wrapper for the Fluid widget CLI — shells out to the system `git`\n * binary via execa. Mirrors the Mist CLI write path\n * (`packages/cli/mist/src/lib/git.ts`): we deliberately do NOT bundle git or\n * use a pure-JS implementation; users are expected to have git installed and\n * we surface a friendly, actionable error when they don't.\n *\n * Security: a token-bearing `remote_url` from POST .../git_credential must\n * never be logged, persisted, or exposed in the process table. The token is\n * stripped from the URL and handed to git through a GIT_ASKPASS script via env\n * vars (FLUID_GIT_USER / FLUID_GIT_PASS) — so it never appears in argv\n * (visible to `ps aux` / `/proc/<pid>/cmdline`) and is never written to\n * `.git/config`. `-c credential.helper=` stops git from caching it, and\n * `GIT_TERMINAL_PROMPT=0` makes auth fail fast instead of hanging on a prompt.\n */\n\nimport {\n parseNameStatusZ,\n type ChangeEntry,\n type CommitMessage,\n} from \"@fluid-app/fluid-cli\";\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { execa, type ExecaError } from \"execa\";\n\nexport class GitError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode = 1) {\n super(message);\n this.name = \"GitError\";\n this.exitCode = exitCode;\n }\n}\n\n/**\n * execa throws ENOENT when the git binary itself is missing — the single most\n * common failure on non-developer machines. Translate it into an actionable\n * message (mirrors Mist Desktop's git-availability guidance) instead of a\n * bare \"git <verb> failed (exit 1)\". Returns null for every other failure so\n * call sites keep their specific messages.\n */\nexport function gitMissingError(err: unknown): GitError | null {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code !== \"ENOENT\") return null;\n return new GitError(\n \"Git isn't installed or isn't on your PATH. Install it and try again:\\n\" +\n \" macOS: xcode-select --install (or `brew install git`)\\n\" +\n \" Windows: https://git-scm.com/download/win\\n\" +\n \" Linux: use your package manager, e.g. `sudo apt-get install git`\\n\" +\n \"Downloads for all platforms: https://git-scm.com/downloads\",\n 127,\n );\n}\n\n/**\n * Split a token-bearing remote URL into the userless URL + creds. Keeps the\n * token off git's argv: we pass `cleanUrl` to git and feed `username` /\n * `password` back through GIT_ASKPASS env vars. If the URL has no embedded\n * credentials, returns empty strings — fine for public repos where git won't\n * invoke askpass.\n */\nfunction splitRemoteCredentials(remoteUrl: string): {\n cleanUrl: string;\n username: string;\n password: string;\n} {\n let u: URL;\n try {\n u = new URL(remoteUrl);\n } catch {\n // Not a URL (e.g. a local filesystem path used for dev/testing). Pass it\n // through untouched — there are no embedded credentials to strip.\n return { cleanUrl: remoteUrl, username: \"\", password: \"\" };\n }\n const username = decodeURIComponent(u.username);\n const password = decodeURIComponent(u.password);\n u.username = \"\";\n u.password = \"\";\n return { cleanUrl: u.toString(), username, password };\n}\n\n/**\n * Write a stub GIT_ASKPASS shell script to a per-process tmpdir and return its\n * path. The script contains no secret — it just echoes back whichever env var\n * (FLUID_GIT_USER / FLUID_GIT_PASS) matches git's prompt. Credentials only\n * live in the spawned git process's env for the duration of the call.\n *\n * One POSIX script for all platforms: Git for Windows runs GIT_ASKPASS through\n * its bundled sh, so a plain sh script works everywhere. Idempotent.\n */\nlet askpassPath: string | null = null;\nfunction ensureAskpassScript(): string {\n if (askpassPath && existsSync(askpassPath)) return askpassPath;\n const dir = path.join(os.tmpdir(), `fluid-widget-askpass-${process.pid}`);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 });\n const p = path.join(dir, \"askpass.sh\");\n writeFileSync(\n p,\n `#!/bin/sh\\ncase \"$1\" in\\n Username*) printf '%s' \"$FLUID_GIT_USER\" ;;\\n *) printf '%s' \"$FLUID_GIT_PASS\" ;;\\nesac\\n`,\n { mode: 0o700 },\n );\n chmodSync(p, 0o700);\n askpassPath = p;\n return askpassPath;\n}\n\n/**\n * Build the spawn env + cleaned URL for a credentialed git invocation. The\n * returned `cleanUrl` has userinfo stripped (safe to pass as argv); the `env`\n * carries GIT_ASKPASS + FLUID_GIT_USER / FLUID_GIT_PASS and\n * GIT_TERMINAL_PROMPT=0.\n */\nfunction gitAuthSpawn(remoteUrl: string): {\n cleanUrl: string;\n env: NodeJS.ProcessEnv;\n} {\n const { cleanUrl, username, password } = splitRemoteCredentials(remoteUrl);\n return {\n cleanUrl,\n env: {\n ...process.env,\n GIT_ASKPASS: ensureAskpassScript(),\n GIT_TERMINAL_PROMPT: \"0\",\n FLUID_GIT_USER: username,\n FLUID_GIT_PASS: password,\n },\n };\n}\n\nfunction wrapGitError(err: unknown, verb: string): GitError {\n const missing = gitMissingError(err);\n if (missing) return missing;\n const e = err as ExecaError;\n return new GitError(\n `git ${verb} failed${e.exitCode != null ? ` (exit ${e.exitCode})` : \"\"}`,\n e.exitCode ?? 1,\n );\n}\n\n/** Confirm git is installed. Cheap call once at the start of a git command. */\nexport async function ensureGitAvailable(): Promise<void> {\n try {\n await execa(\"git\", [\"--version\"]);\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n throw new GitError(\n \"`git` is required but couldn't be run. Install it from https://git-scm.com/downloads.\",\n );\n }\n}\n\n/** Is `cwd` inside a git working tree? */\nexport async function isGitRepository(cwd: string): Promise<boolean> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"rev-parse\", \"--is-inside-work-tree\"],\n { cwd },\n );\n return stdout.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/** `git init` (+ set the initial branch to `branch`). No-op if already a repo. */\nexport async function gitInit(cwd: string, branch = \"main\"): Promise<void> {\n try {\n await execa(\"git\", [\"init\", \"--initial-branch\", branch], { cwd });\n } catch (err) {\n // Older gits lack --initial-branch; fall back to a plain init.\n const missing = gitMissingError(err);\n if (missing) throw missing;\n try {\n await execa(\"git\", [\"init\"], { cwd });\n } catch (fallbackErr) {\n throw wrapGitError(fallbackErr, \"init\");\n }\n }\n}\n\n/**\n * `git clone <cleanUrl> <targetDir>`. The original remoteUrl carries a token;\n * gitAuthSpawn strips it from the URL and re-injects it via GIT_ASKPASS.\n */\nexport async function gitClone(\n remoteUrl: string,\n targetDir: string,\n options: {\n readonly depth?: number;\n readonly branch?: string;\n /**\n * Capture git's stderr instead of inheriting it. Used for best-effort\n * clones (e.g. the create template fetch) where the caller handles\n * failure and doesn't want git's raw error text on the console.\n */\n readonly silent?: boolean;\n } = {},\n): Promise<void> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n const args = [\"-c\", \"credential.helper=\", \"clone\", \"--quiet\"];\n if (options.depth != null) args.push(\"--depth\", String(options.depth));\n if (options.branch) args.push(\"--branch\", options.branch);\n args.push(cleanUrl, targetDir);\n try {\n await execa(\"git\", args, {\n env,\n stdio: options.silent ? \"pipe\" : [\"ignore\", \"inherit\", \"inherit\"],\n });\n } catch (err) {\n throw wrapGitError(err, \"clone\");\n }\n}\n\n/** `git push <remote> HEAD:<branch>` — credentials via GIT_ASKPASS, never argv. */\nexport async function gitPush(\n cwd: string,\n remoteUrl: string,\n branch = \"main\",\n): Promise<void> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n try {\n await execa(\n \"git\",\n [\n \"-c\",\n \"credential.helper=\",\n \"-c\",\n \"http.https://github.com/.extraheader=\",\n \"push\",\n cleanUrl,\n `HEAD:${branch}`,\n ],\n { cwd, env, stdio: [\"ignore\", \"inherit\", \"inherit\"] },\n );\n } catch (err) {\n throw wrapGitError(err, \"push\");\n }\n}\n\n/**\n * Does `branch` exist on the remote? Uses `git ls-remote --heads`, which is\n * the reliable way to tell a genuinely-empty remote (freshly provisioned repo,\n * first push) apart from a connection/auth failure. Returns false only when the\n * remote answered but has no such branch; **throws** on any transport/auth\n * error so callers don't mistake a network blip for \"empty remote\" and skip\n * reconciliation.\n */\nexport async function gitRemoteBranchExists(\n cwd: string,\n remoteUrl: string,\n branch = \"main\",\n): Promise<boolean> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n try {\n const { stdout } = await execa(\n \"git\",\n [\"-c\", \"credential.helper=\", \"ls-remote\", \"--heads\", cleanUrl, branch],\n { cwd, env },\n );\n return stdout.trim().length > 0;\n } catch (err) {\n throw wrapGitError(err, \"ls-remote\");\n }\n}\n\n/**\n * Fetch the given branch from the token-bearing remote, writing `FETCH_HEAD`.\n * Throws on failure — callers should first confirm the branch exists with\n * `gitRemoteBranchExists` so a genuinely-empty remote isn't treated as an error.\n */\nexport async function gitFetch(\n cwd: string,\n remoteUrl: string,\n branch = \"main\",\n): Promise<void> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n try {\n await execa(\n \"git\",\n [\"-c\", \"credential.helper=\", \"fetch\", \"--quiet\", cleanUrl, branch],\n { cwd, env },\n );\n } catch (err) {\n throw wrapGitError(err, \"fetch\");\n }\n}\n\n/**\n * Count commits in local HEAD vs `FETCH_HEAD` (after `gitFetch`). Returns\n * `{ahead, behind}`. `0/0` means \"in sync\" (or no FETCH_HEAD / no HEAD yet).\n */\nexport async function gitAheadBehindVsFetchHead(\n cwd: string,\n): Promise<{ ahead: number; behind: number }> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"rev-list\", \"--left-right\", \"--count\", \"HEAD...FETCH_HEAD\"],\n { cwd },\n );\n const [a, b] = stdout.trim().split(/\\s+/);\n const ahead = Number.parseInt(a ?? \"0\", 10);\n const behind = Number.parseInt(b ?? \"0\", 10);\n return {\n ahead: Number.isFinite(ahead) ? ahead : 0,\n behind: Number.isFinite(behind) ? behind : 0,\n };\n } catch {\n return { ahead: 0, behind: 0 };\n }\n}\n\n/** Does `cwd` have any commits yet? (false right after `git init`.) */\nexport async function hasCommits(cwd: string): Promise<boolean> {\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", \"HEAD\"], { cwd });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Adopt `FETCH_HEAD` as the current (unborn) branch's base: point the branch\n * ref at it and load its tree into the index, leaving the working tree\n * untouched. The next auto-commit then records the local project tree as a\n * child of the remote history — local files win, remote-only files are\n * recorded as deletions — so the push fast-forwards instead of being\n * rejected for unrelated history. Only call this when `hasCommits` is false;\n * on a repo with local commits it would silently rewrite the branch ref.\n *\n * Returns the number of remote commits adopted.\n */\nexport async function gitAdoptFetchHead(cwd: string): Promise<number> {\n try {\n await execa(\"git\", [\"reset\", \"--mixed\", \"FETCH_HEAD\"], { cwd });\n const { stdout } = await execa(\n \"git\",\n [\"rev-list\", \"--count\", \"FETCH_HEAD\"],\n { cwd },\n );\n const count = Number.parseInt(stdout.trim(), 10);\n return Number.isFinite(count) ? count : 0;\n } catch (err) {\n throw wrapGitError(err, \"adopt remote history\");\n }\n}\n\n/** Fast-forward `HEAD` to `FETCH_HEAD`. Fails if not fast-forwardable. */\nexport async function gitMergeFastForward(cwd: string): Promise<void> {\n try {\n await execa(\"git\", [\"merge\", \"--ff-only\", \"FETCH_HEAD\"], { cwd });\n } catch (err) {\n throw wrapGitError(err, \"fast-forward merge\");\n }\n}\n\n/** Are there uncommitted changes (working tree or index) in this repo? */\nexport async function hasUncommittedChanges(cwd: string): Promise<boolean> {\n try {\n const { stdout } = await execa(\"git\", [\"status\", \"--porcelain\"], { cwd });\n return stdout.trim().length > 0;\n } catch {\n return false;\n }\n}\n\n/** Stash working-tree + untracked changes with a tagged message. */\nexport async function gitStash(cwd: string, message: string): Promise<void> {\n try {\n await execa(\n \"git\",\n [\"stash\", \"push\", \"--include-untracked\", \"--message\", message],\n { cwd },\n );\n } catch (err) {\n throw wrapGitError(err, \"stash push\");\n }\n}\n\n/** Pop the most recent stash. Throws on conflict so callers can surface it. */\nexport async function gitStashPop(cwd: string): Promise<void> {\n try {\n await execa(\"git\", [\"stash\", \"pop\"], { cwd });\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n const e = err as ExecaError;\n throw new GitError(\n \"Couldn't restore your local changes after pulling — the edits collided \" +\n \"with a teammate's. Run `git stash list` and resolve manually.\",\n e.exitCode ?? 1,\n );\n }\n}\n\n/** Read the current HEAD sha, or null if there is no commit yet. */\nexport async function getHeadSha(cwd: string): Promise<string | null> {\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"], { cwd });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Local-only state that must never reach a widget's provisioned repo.\n *\n * `.mist-desktop/` is Mist Desktop's per-machine working state for the\n * project directory it opened — chat transcripts, user attachments,\n * screenshots, source baselines, media cache. When Desktop drives\n * `fluid widget push`, that directory sits in the project root, so a\n * whole-tree `git add -A` publishes every private conversation.\n * `.mist` is the sibling clone/slug marker.\n *\n * Mirrors the portal CLI (`packages/cli/portal/src/lib/git.ts`) and the\n * Mist CLI (`packages/cli/mist/src/lib/git.ts`).\n */\nconst LOCAL_ONLY_GIT_PATHS = [\".mist\", \".mist-desktop/\"] as const;\n\n/**\n * Append {@link LOCAL_ONLY_GIT_PATHS} to `.git/info/exclude` when absent.\n *\n * Why the local exclude and not `.gitignore`: `.gitignore` ships from the\n * widget starter template, so editing it would never reach the clones\n * already on people's machines. `.git/info/exclude` is per-checkout, so\n * writing it on every sync heals a pre-existing clone on its next push.\n *\n * Idempotent and best-effort: never throws. {@link gitAutoCommit} also\n * cleans these paths out of the index after staging.\n */\nexport function excludeLocalStateFromGit(cwd: string): void {\n try {\n const gitDir = path.join(cwd, \".git\");\n if (!existsSync(gitDir)) return;\n const infoDir = path.join(gitDir, \"info\");\n if (!existsSync(infoDir)) mkdirSync(infoDir, { recursive: true });\n const excludePath = path.join(infoDir, \"exclude\");\n const existing = existsSync(excludePath)\n ? readFileSync(excludePath, \"utf8\")\n : \"\";\n const existingLines = new Set(\n existing\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean),\n );\n const missing = LOCAL_ONLY_GIT_PATHS.filter(\n (entry) => !existingLines.has(entry),\n );\n if (missing.length === 0) return;\n const needsLeadingNewline = existing.length > 0 && !existing.endsWith(\"\\n\");\n writeFileSync(\n excludePath,\n `${existing}${needsLeadingNewline ? \"\\n\" : \"\"}${missing.join(\"\\n\")}\\n`,\n \"utf8\",\n );\n } catch {\n // Best-effort — see doc comment.\n }\n}\n\n/**\n * Absolute path of the repository containing `cwd`, or `cwd` when\n * resolution fails. Every local-state defense anchors here: `git add -A`\n * stages the WHOLE repository, so a push run from a subdirectory would\n * otherwise look for `<subdir>/.git`, skip the exclude, and sweep the\n * root `.mist-desktop/` in anyway.\n */\nasync function resolveRepoRoot(cwd: string): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n });\n const root = stdout.trim();\n if (root.length > 0) return root;\n } catch {\n // Fall through to cwd.\n }\n return cwd;\n}\n\n/**\n * Repository-root-anchored {@link excludeLocalStateFromGit}. Run before\n * any working-tree cleanliness check: while `.mist-desktop/` is neither\n * tracked nor excluded it shows as untracked in `git status --porcelain`,\n * so a Desktop-driven push needlessly stashes/pops around a pull.\n */\nexport async function ensureLocalStateExcluded(cwd: string): Promise<void> {\n excludeLocalStateFromGit(await resolveRepoRoot(cwd));\n}\n\nexport interface GitCommitIdentity {\n readonly name: string;\n readonly email: string;\n}\n\n/** Paths currently tracked under `.mist-desktop/`, or [] when none. */\nasync function trackedLocalStatePaths(repoRoot: string): Promise<string[]> {\n try {\n const { stdout } = await execa(\"git\", [\"ls-files\", \"--\", \".mist-desktop\"], {\n cwd: repoRoot,\n });\n return stdout.split(\"\\n\").filter((l) => l.trim().length > 0);\n } catch {\n return [];\n }\n}\n\n/**\n * Untrack private Mist Desktop state and, if anything was tracked,\n * commit ONLY that removal so the next push deletes it from the remote.\n * Returns true when a purge commit was made.\n *\n * Must run regardless of working-tree cleanliness AND of `--no-commit`:\n * an older CLI could have committed chats to a checkout that is now\n * clean, and gating on either would skip the cleanup forever, leaving\n * the chats published.\n *\n * The commit is built through a THROWAWAY index (`GIT_INDEX_FILE`), not\n * the user's: `read-tree HEAD` → `rm --cached` → `write-tree` →\n * `commit-tree` → `update-ref`. A plain `git commit` would capture the\n * user's entire index, so anything they had pre-staged would be swept\n * into the purge commit and pushed — the exact thing `--no-commit`\n * exists to prevent. A pathspec commit (`git commit -- .mist-desktop`)\n * is also wrong: with `--only` git takes the *working tree* content of\n * those paths, and the chats are still on disk, so it would re-add\n * exactly what we are removing.\n *\n * The user's real index then gets the same scoped `rm --cached`, so any\n * other staged work stays staged and the working tree is never touched.\n */\nexport async function purgeLocalStateFromIndex(\n cwd: string,\n message: string,\n identity: GitCommitIdentity = DEFAULT_COMMIT_IDENTITY,\n): Promise<boolean> {\n const repoRoot = await resolveRepoRoot(cwd);\n if ((await trackedLocalStatePaths(repoRoot)).length === 0) return false;\n\n let head: string;\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: repoRoot,\n });\n head = stdout.trim();\n if (!head) return false;\n } catch {\n return false;\n }\n\n const tmpIndex = path.join(\n os.tmpdir(),\n `fluid-widget-purge-${process.pid}-${randomUUID()}.index`,\n );\n const indexEnv = { ...process.env, GIT_INDEX_FILE: tmpIndex };\n let commitSha: string;\n try {\n await execa(\"git\", [\"read-tree\", head], { cwd: repoRoot, env: indexEnv });\n await execa(\n \"git\",\n [\"rm\", \"-q\", \"-r\", \"--cached\", \"--ignore-unmatch\", \"--\", \".mist-desktop\"],\n { cwd: repoRoot, env: indexEnv },\n );\n const { stdout: tree } = await execa(\"git\", [\"write-tree\"], {\n cwd: repoRoot,\n env: indexEnv,\n });\n const { stdout: sha } = await execa(\n \"git\",\n [\"commit-tree\", tree.trim(), \"-p\", head, \"-m\", message],\n {\n cwd: repoRoot,\n env: { ...indexEnv, ...(await identityEnv(repoRoot, identity)) },\n },\n );\n commitSha = sha.trim();\n if (!commitSha) return false;\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n throw wrapGitError(err, \"purge local state\");\n } finally {\n rmSync(tmpIndex, { force: true });\n }\n\n try {\n await execa(\"git\", [\"update-ref\", \"HEAD\", commitSha, head], {\n cwd: repoRoot,\n });\n } catch (err) {\n throw wrapGitError(err, \"purge local state\");\n }\n try {\n await execa(\n \"git\",\n [\"rm\", \"-q\", \"-r\", \"--cached\", \"--ignore-unmatch\", \"--\", \".mist-desktop\"],\n { cwd: repoRoot },\n );\n } catch {\n // Non-fatal: HEAD is already correct, so the push ships the removal.\n }\n return true;\n}\n\n/** `GIT_{AUTHOR,COMMITTER}_*` overrides for `commit-tree`, which (unlike\n * `git commit`) fails outright rather than prompting when the repo has\n * no identity. Only set what the repo itself doesn't define. */\nasync function identityEnv(\n cwd: string,\n identity: GitCommitIdentity,\n): Promise<NodeJS.ProcessEnv> {\n const env: NodeJS.ProcessEnv = {};\n const has = async (key: string): Promise<boolean> => {\n try {\n const r = await execa(\"git\", [\"config\", key], { cwd });\n return r.stdout.trim().length > 0;\n } catch {\n return false;\n }\n };\n if (!(await has(\"user.name\"))) {\n env[\"GIT_AUTHOR_NAME\"] = identity.name;\n env[\"GIT_COMMITTER_NAME\"] = identity.name;\n }\n if (!(await has(\"user.email\"))) {\n env[\"GIT_AUTHOR_EMAIL\"] = identity.email;\n env[\"GIT_COMMITTER_EMAIL\"] = identity.email;\n }\n return env;\n}\n\n/** Shared `-c user.*` args: prefer the repo's configured identity, else\n * the supplied synthetic one so the commit isn't rejected. */\nasync function resolveIdentityArgs(\n cwd: string,\n identity: GitCommitIdentity,\n): Promise<string[]> {\n let hasName = false;\n let hasEmail = false;\n try {\n const r = await execa(\"git\", [\"config\", \"user.name\"], { cwd });\n hasName = r.stdout.trim().length > 0;\n } catch {\n // exit 1 from `git config <key>` just means the key is unset.\n }\n try {\n const r = await execa(\"git\", [\"config\", \"user.email\"], { cwd });\n hasEmail = r.stdout.trim().length > 0;\n } catch {\n // ditto.\n }\n return [\n ...(hasName ? [] : [\"-c\", `user.name=${identity.name}`]),\n ...(hasEmail ? [] : [\"-c\", `user.email=${identity.email}`]),\n ];\n}\n\nconst DEFAULT_COMMIT_IDENTITY: GitCommitIdentity = {\n name: \"Fluid CLI\",\n email: \"cli@fluid.app\",\n};\n\n/**\n * `git add -A && git commit -m <message>` in `cwd`.\n *\n * The widget \"push\" UX is \"ship my changes\" — the user shouldn't need to know\n * about staging or commit messages. This bundles working-tree edits into one\n * commit per push. If the repo has no configured user.name / user.email we\n * pass a synthetic identity so the commit isn't rejected. \"nothing to commit\"\n * is treated as a no-op rather than an error.\n *\n * Scope: `add -A` stages the whole work tree, bounded by the project\n * `.gitignore` — which can't cover tool-local state written INTO the\n * project by whatever opened it (Mist Desktop's `.mist-desktop/` chats and\n * the `.mist` marker). Belt and suspenders, all repo-root-anchored:\n *\n * 1. {@link excludeLocalStateFromGit} — idempotent `.git/info/exclude`\n * write so `git add` never sees the paths. Heals old clones.\n * 2. `git reset -- ':(top).mist' .mist` — unstages the marker if step 1\n * silently failed. We deliberately do NOT pass `:(exclude)` to\n * `git add`: when the path is also in `.git/info/exclude`, git exits\n * 1 with \"paths are ignored by one of your .gitignore files\", which\n * would turn the already-healed case into a hard failure.\n * 3. `git rm --cached -r --ignore-unmatch .mist-desktop` — untracks\n * chats an older push already committed (ignore rules can't untrack).\n * `--cached` keeps every file on disk.\n *\n * Steps 2 and 3 are best-effort and never fail the push.\n */\n/**\n * The staged file set, as {@link ChangeEntry}s — the input a\n * {@link CommitMessage} resolver summarizes.\n *\n * `-z` (NUL-delimited) rather than the default: paths with spaces or\n * quotes are legal in git and common in themes and asset folders, and\n * the newline form quotes and escapes them, which would corrupt both the\n * path and the count.\n *\n * Best-effort — a summary is a nicety, never a reason to fail a publish.\n * An empty result makes the resolver fall back to its own constant.\n */\nasync function stagedChanges(cwd: string): Promise<ChangeEntry[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"diff\", \"--cached\", \"--name-status\", \"-z\"],\n { cwd },\n );\n return parseNameStatusZ(stdout);\n } catch {\n return [];\n }\n}\n\nexport async function gitAutoCommit(\n cwd: string,\n message: CommitMessage,\n identity: GitCommitIdentity = DEFAULT_COMMIT_IDENTITY,\n): Promise<void> {\n const repoRoot = await resolveRepoRoot(cwd);\n excludeLocalStateFromGit(repoRoot);\n\n try {\n await execa(\"git\", [\"add\", \"-A\"], { cwd });\n } catch (err) {\n throw wrapGitError(err, \"add\");\n }\n\n try {\n await execa(\"git\", [\"reset\", \"-q\", \"--\", \":(top).mist\", \".mist\"], { cwd });\n } catch {\n // Non-fatal — see doc comment.\n }\n try {\n await execa(\n \"git\",\n [\"rm\", \"-q\", \"-r\", \"--cached\", \"--ignore-unmatch\", \"--\", \".mist-desktop\"],\n { cwd: repoRoot },\n );\n } catch {\n // Non-fatal — the exclude file remains the primary defense.\n }\n\n // Resolve the subject only now: everything above decides what is\n // actually staged, so a summary built any earlier would describe a\n // file set the commit doesn't carry.\n const subject =\n typeof message === \"string\"\n ? message\n : await message(await stagedChanges(cwd));\n const identityArgs = await resolveIdentityArgs(cwd, identity);\n\n try {\n await execa(\"git\", [...identityArgs, \"commit\", \"-m\", subject], {\n cwd,\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n const e = err as ExecaError;\n if (typeof e.stderr === \"string\" && /nothing to commit/i.test(e.stderr)) {\n return;\n }\n throw wrapGitError(err, \"commit\");\n }\n}\n","import type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport { fluidOsV0WidgetPackageGitCredentialCreate } from \"@fluid-app/fluidos-api-client/sdk\";\n\n/**\n * A short-lived (~1h) credentialed git remote URL minted by the backend. The\n * `remoteUrl` embeds an installation token and must never be logged,\n * persisted, or written to `.git/config` — hand it straight to the git helpers\n * in `../lib/git.js`, which strip the token off argv via GIT_ASKPASS.\n */\nexport interface WidgetGitCredential {\n readonly remoteUrl: string;\n readonly expiresAt: string | null;\n}\n\ninterface GitCredentialResponse {\n readonly git_credential?: {\n readonly remote_url?: unknown;\n readonly expires_at?: unknown;\n };\n}\n\nexport interface MintWidgetGitCredentialOptions {\n readonly client: FluidOsHeyApiClient;\n /**\n * Droplet UUID that owns the widget package. When provided we mint against\n * the droplet-scoped endpoint; otherwise we mint against the company-owned\n * widget package endpoint.\n */\n readonly droplet?: string;\n}\n\nfunction unwrapResponseData(response: unknown): unknown {\n if (\n response !== null &&\n typeof response === \"object\" &&\n \"data\" in response &&\n !(\"git_credential\" in response)\n ) {\n return response.data;\n }\n return response;\n}\n\n/**\n * Mint a git credential for a widget package.\n *\n * Backend endpoints:\n * - droplet-owned: POST /api/droplets/:uuid/widget_package/git_credential\n * - company-owned: POST /api/company/fluid_os/widget_package/git_credential\n * Both respond `{ git_credential: { remote_url, expires_at } }`.\n *\n * The raw droplet-scoped call must pass `security` — the hey-api runtime only\n * attaches the bearer token when a request declares it (generated SDK\n * functions do; a bare `client.post` does not, and the request goes out\n * unauthenticated → 401 \"Invalid credentials\").\n *\n * Throws the underlying `ApiError` (with `.status`) on failure so callers can\n * decide whether to degrade gracefully (see `isGitSyncUnavailable`).\n */\nexport async function mintWidgetGitCredential(\n options: MintWidgetGitCredentialOptions,\n): Promise<WidgetGitCredential> {\n const rawResponse = options.droplet\n ? await options.client.post({\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: `/api/droplets/${encodeURIComponent(options.droplet)}/widget_package/git_credential`,\n })\n : await fluidOsV0WidgetPackageGitCredentialCreate({\n client: options.client,\n responseStyle: \"data\",\n });\n const response = unwrapResponseData(rawResponse) as GitCredentialResponse;\n const remoteUrl = response?.git_credential?.remote_url;\n if (typeof remoteUrl !== \"string\" || remoteUrl.length === 0) {\n throw new Error(\n \"The git credential response did not include a remote URL. \" +\n \"Update the Fluid CLI, or contact support if this persists.\",\n );\n }\n const expiresAtRaw = response.git_credential?.expires_at;\n return {\n remoteUrl,\n expiresAt: typeof expiresAtRaw === \"string\" ? expiresAtRaw : null,\n };\n}\n\n/**\n * Sanitize a package key the same way the backend does when naming the repo\n * (`GitSync::Provisioner`): GitHub's repo-name alphabet is `[A-Za-z0-9._-]`,\n * so every other character (including the `~` allowed in package keys) becomes\n * a hyphen. Lets us compare a requested key against the minted repo name.\n */\nexport function sanitizeWidgetPackageKey(key: string): string {\n return key.replace(/[^A-Za-z0-9._-]/g, \"-\");\n}\n\n/**\n * Extract the sanitized package key from a minted widget remote URL. The\n * backend names repos `widget-<sanitized package_key>-<widget_package id>`, so\n * `https://x-access-token:tok@github.com/org/widget-reviews-42.git` → `reviews`.\n * Returns null when the URL doesn't match that shape (never throws; the token\n * in the URL is never logged — only the pathname is read).\n */\nexport function widgetRepoKeyFromRemoteUrl(remoteUrl: string): string | null {\n try {\n const name = new URL(remoteUrl).pathname\n .split(\"/\")\n .pop()\n ?.replace(/\\.git$/, \"\");\n const match = name?.match(/^widget-(.+)-\\d+$/);\n return match?.[1] ?? null;\n } catch {\n return null;\n }\n}\n\n/** Best-effort read of an HTTP status off an unknown thrown error. */\nexport function getErrorStatus(err: unknown): number | undefined {\n if (err && typeof err === \"object\" && \"status\" in err) {\n const status = (err as { status?: unknown }).status;\n if (typeof status === \"number\") return status;\n }\n return undefined;\n}\n\n/**\n * Should a git-credential failure degrade to \"publish artifacts only\" rather\n * than abort? True when there is no repository to sync with yet: the widget\n * package record does not exist (404), or it exists but its `GitSync` repo has\n * not been created and connected (409). Other statuses (auth, 5xx) are genuine\n * errors the caller may still choose to treat as best-effort.\n */\nexport function isGitSyncUnavailable(err: unknown): boolean {\n const status = getErrorStatus(err);\n return status === 404 || status === 409;\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * `.fluid-widget` marker file — written by `fluid widget clone` so future\n * commands (and Mist Desktop) can identify a checked-out widget package repo\n * and know which owner to mint git credentials against. Mirrors Mist's `.mist`\n * marker (which records slug / vendor_name).\n */\nexport const WIDGET_MARKER_FILE = \".fluid-widget\";\n\nexport interface WidgetMarker {\n readonly package_key: string;\n /** Droplet UUID when the package is droplet-owned; omitted for company-owned. */\n readonly droplet?: string;\n}\n\nexport function resolveWidgetMarkerPath(dir: string): string {\n return path.join(dir, WIDGET_MARKER_FILE);\n}\n\nexport function writeWidgetMarker(dir: string, marker: WidgetMarker): void {\n const payload: WidgetMarker = marker.droplet\n ? { package_key: marker.package_key, droplet: marker.droplet }\n : { package_key: marker.package_key };\n writeFileSync(\n resolveWidgetMarkerPath(dir),\n JSON.stringify(payload, null, 2) + \"\\n\",\n \"utf8\",\n );\n}\n\nexport function readWidgetMarker(dir: string): WidgetMarker | null {\n const filePath = resolveWidgetMarkerPath(dir);\n if (!existsSync(filePath)) return null;\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf8\")) as unknown;\n if (!parsed || typeof parsed !== \"object\") return null;\n const obj = parsed as Record<string, unknown>;\n const packageKey = obj[\"package_key\"];\n if (typeof packageKey !== \"string\" || packageKey.length === 0) return null;\n const droplet = obj[\"droplet\"];\n return {\n package_key: packageKey,\n ...(typeof droplet === \"string\" && droplet.length > 0 ? { droplet } : {}),\n };\n } catch {\n return null;\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { ensureGitAvailable, gitClone } from \"../lib/git.js\";\nimport {\n isGitSyncUnavailable,\n mintWidgetGitCredential,\n sanitizeWidgetPackageKey,\n widgetRepoKeyFromRemoteUrl,\n} from \"../utils/git-credential.js\";\nimport { validateDropletUuid } from \"../utils/config.js\";\nimport { writeWidgetMarker } from \"../utils/widget-marker.js\";\nimport {\n getInstallCommand,\n installDependencies,\n} from \"../utils/package-manager.js\";\n\nexport interface CloneCommandOptions {\n readonly droplet?: string;\n readonly dir?: string;\n readonly skipInstall?: boolean;\n}\n\nexport const cloneCommand: Command = new Command(\"clone\")\n .description(\n \"Clone a widget package's git repository (mints a fresh token per call)\",\n )\n .argument(\"<package>\", \"Widget package key to clone\")\n .option(\n \"--droplet <uuid>\",\n \"Droplet UUID that owns the package (defaults to the company-owned package)\",\n )\n .option(\"--dir <dir>\", \"Target directory (defaults to ./<package>/)\")\n .option(\"--skip-install\", \"Skip dependency installation\")\n .action((packageKey: string, options: CloneCommandOptions) =>\n runCliAction(async () => {\n const trimmedPackage = packageKey.trim();\n if (!trimmedPackage) throw new Error(\"A widget package key is required.\");\n\n const droplet = options.droplet?.trim();\n if (droplet) {\n const dropletError = validateDropletUuid(droplet);\n if (dropletError) throw new Error(dropletError);\n }\n\n // Clone is a pure git operation — fail fast with an actionable message\n // when git isn't installed rather than partway through.\n await ensureGitAvailable();\n\n const targetDir = path.resolve(options.dir ?? trimmedPackage);\n if (existsSync(targetDir)) {\n throw new Error(\n `Directory ${targetDir} already exists. Pass --dir or remove it first.`,\n );\n }\n\n // The credential endpoints are scoped to an *owner*, not a package key:\n // a company (or droplet) has exactly one widget package, so the backend\n // resolves the repo from the authenticated company / the droplet uuid —\n // there is no package-key selector to send. `<package>` is therefore a\n // local label used for the target directory name and the `.fluid-widget`\n // marker, mirroring how `fluid mist clone` names by vendor_name.\n const client = createAuthenticatedWidgetPackageClient();\n const spinner = ora(\"Minting git credential…\").start();\n let remoteUrl: string;\n try {\n const cred = await mintWidgetGitCredential({\n client,\n ...(droplet ? { droplet } : {}),\n });\n remoteUrl = cred.remoteUrl;\n } catch (err) {\n spinner.fail(\"Couldn't mint a git credential\");\n if (isGitSyncUnavailable(err)) {\n throw new Error(\n \"Widget git sync isn't available for this package yet. \" +\n \"Publish the package first, or try again once git sync is enabled.\",\n );\n }\n throw err;\n }\n\n // The owner determines the repo, so guard against a requested key that\n // disagrees with what was actually minted — otherwise we'd clone one\n // repo but stamp the marker with a different package name, leaving future\n // push/publish acting on a checkout whose marker and source disagree.\n const mintedKey = widgetRepoKeyFromRemoteUrl(remoteUrl);\n if (!mintedKey) {\n // Fail closed: an unparseable repo name means we can't prove the\n // checkout matches the requested key, and a wrong marker would leave\n // future push/publish acting on the wrong package.\n spinner.fail(\"Couldn't verify the owner's widget repository\");\n throw new Error(\n \"The minted git repository URL did not match the expected widget \" +\n \"repository format, so the CLI cannot safely write a package \" +\n \"marker. Update the Fluid CLI, or contact support if this persists.\",\n );\n }\n if (mintedKey !== sanitizeWidgetPackageKey(trimmedPackage)) {\n spinner.fail(\"Requested package does not match the owner's repository\");\n throw new Error(\n `The ${droplet ? \"droplet\" : \"company\"}'s widget package is ` +\n `\"${mintedKey}\", not \"${trimmedPackage}\". Re-run with the correct ` +\n `package key (or --droplet), so the checkout and its marker agree.`,\n );\n }\n\n spinner.text = `Cloning into ${path.basename(targetDir)}/…`;\n try {\n // Token-bearing URL is passed inline only — never written to .git/config.\n await gitClone(remoteUrl, targetDir);\n } catch (err) {\n spinner.fail(\"git clone failed\");\n throw err;\n }\n\n // Drop a `.fluid-widget` marker so future commands (and Mist Desktop)\n // know the owner without re-parsing config.\n writeWidgetMarker(targetDir, {\n package_key: trimmedPackage,\n ...(droplet ? { droplet } : {}),\n });\n\n spinner.succeed(`Cloned into ${chalk.cyan(targetDir)}`);\n\n // A cloned checkout is unrunnable until dependencies land (`widget dev`\n // needs the project's own Vite) — install here like `create` does so\n // clone-then-run works without a manual step in between.\n const installCommand = getInstallCommand(targetDir);\n if (options.skipInstall !== true) {\n spinner.start(`Installing dependencies with ${installCommand}...`);\n try {\n await installDependencies(targetDir);\n spinner.succeed(\"Installed dependencies\");\n } catch {\n spinner.fail(\"Failed to install dependencies\");\n console.log();\n console.log(chalk.yellow(\"You can install dependencies manually:\"));\n console.log(chalk.cyan(` ${installCommand}`));\n }\n }\n\n console.log(\n chalk.dim(` cd ${path.relative(process.cwd(), targetDir) || \".\"}`),\n );\n if (options.skipInstall === true) {\n console.log(chalk.dim(` ${installCommand}`));\n }\n }),\n );\n","import { cp, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { ensureGitAvailable, gitClone } from \"../lib/git.js\";\n\n/**\n * The canonical widget starter lives on GitHub so widget projects share the\n * same \"invisible git\" collaboration model Mist apps have. It is an explicit\n * opt-in for `fluid widget create`; the bundled template is the default.\n */\nexport const DEFAULT_WIDGET_TEMPLATE_REPO_URL =\n \"https://github.com/Fluid-WeCommerce/widget-template.git\";\n\n/**\n * The template repo to clone. Overridable via `FLUID_WIDGET_TEMPLATE_REPO`\n * (read at call time so tests can point at a local repo). Falls back to the\n * canonical GitHub template.\n */\nexport function widgetTemplateRepoUrl(): string {\n return (\n process.env[\"FLUID_WIDGET_TEMPLATE_REPO\"] ??\n DEFAULT_WIDGET_TEMPLATE_REPO_URL\n );\n}\n\n/**\n * The defaults baked into the GitHub template's rendered files. `create`\n * rewrites these to the user's chosen values after cloning. Keep in sync with\n * `scripts/render-template-repo.mts`.\n */\nexport const TEMPLATE_DEFAULTS = {\n projectName: \"my-widget\",\n widgetScope: \"droplet\",\n widgetPackageVersion: \"0.1.0\",\n} as const;\n\nexport interface GithubTemplateVariables {\n readonly projectName: string;\n readonly widgetScope: string;\n readonly widgetPackageVersion: string;\n}\n\n/**\n * Clone the GitHub widget template into `targetPath`, strip its git history,\n * and rewrite the baked defaults to the user's values. The repo holds a fully\n * rendered project (no `{{placeholders}}`), so we do targeted, deterministic\n * replacements of the known defaults rather than template interpolation.\n *\n * Returns true on success. Returns false (never throws) when the template\n * couldn't be fetched — git missing, offline, repo unavailable. The caller\n * reports that requested-template failure. The partially-cloned target is\n * cleaned up before returning false.\n */\nexport async function tryFetchGithubTemplate(\n targetPath: string,\n variables: GithubTemplateVariables,\n): Promise<boolean> {\n let tempDir: string | undefined;\n try {\n await ensureGitAvailable();\n tempDir = await mkdtemp(path.join(os.tmpdir(), \"fluid-widget-template-\"));\n const clonePath = path.join(tempDir, \"template\");\n await gitClone(widgetTemplateRepoUrl(), clonePath, {\n depth: 1,\n branch: \"main\",\n silent: true,\n });\n\n // Strip git history: generate-from-template semantics — the new project\n // gets its own (invisible) repo later via `fluid widget push`.\n await rm(path.join(clonePath, \".git\"), { recursive: true, force: true });\n\n await cp(clonePath, targetPath, { recursive: true });\n await applyTemplateRenames(targetPath, variables);\n return true;\n } catch {\n // Any failure → clean up and let the caller report the opt-in failure.\n await rm(targetPath, { recursive: true, force: true }).catch(() => {});\n return false;\n } finally {\n if (tempDir)\n await rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Rewrite the template's baked defaults (project name, scope, version) to the\n * user's chosen values across the small set of files that reference them.\n * Missing files are skipped — the template can evolve without breaking this.\n */\nasync function applyTemplateRenames(\n targetPath: string,\n variables: GithubTemplateVariables,\n): Promise<void> {\n const { projectName, widgetScope, widgetPackageVersion } = variables;\n\n await replaceInFile(path.join(targetPath, \"package.json\"), [\n [\n `\"name\": ${JSON.stringify(TEMPLATE_DEFAULTS.projectName)}`,\n `\"name\": ${JSON.stringify(projectName)}`,\n ],\n ]);\n\n await replaceInFile(path.join(targetPath, \"index.html\"), [\n [\n `<title>${TEMPLATE_DEFAULTS.projectName}</title>`,\n `<title>${projectName}</title>`,\n ],\n ]);\n\n await replaceInFile(path.join(targetPath, \"README.md\"), [\n [`# ${TEMPLATE_DEFAULTS.projectName}\\n`, `# ${projectName}\\n`],\n ]);\n\n await replaceInFile(path.join(targetPath, \"manifest.ts\"), [\n [\n `scope: ${JSON.stringify(TEMPLATE_DEFAULTS.widgetScope)},`,\n `scope: ${JSON.stringify(widgetScope)},`,\n ],\n [\n `version: ${JSON.stringify(TEMPLATE_DEFAULTS.widgetPackageVersion)},`,\n `version: ${JSON.stringify(widgetPackageVersion)},`,\n ],\n ]);\n}\n\n/**\n * Replace the first occurrence of each `[from, to]` pair in a file. No-op when\n * `from` isn't present (or `from === to`), so re-running is harmless and an\n * unchanged default (e.g. scope already \"droplet\") isn't a failure.\n */\nasync function replaceInFile(\n filePath: string,\n replacements: ReadonlyArray<readonly [string, string]>,\n): Promise<void> {\n if (!existsSync(filePath)) return;\n let content = await readFile(filePath, \"utf8\");\n let changed = false;\n for (const [from, to] of replacements) {\n if (from === to) continue;\n const index = content.indexOf(from);\n if (index === -1) continue;\n content = content.slice(0, index) + to + content.slice(index + from.length);\n changed = true;\n }\n if (changed) await writeFile(filePath, content, \"utf8\");\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport path from \"node:path\";\nimport type { WidgetCreateOptions } from \"../types.js\";\nimport {\n copyWidgetTemplate,\n directoryExists,\n getCliVersion,\n getDefaultTemplatePath,\n getPortalCoreVersion,\n getPortalSdkVersion,\n getWidgetCliVersion,\n} from \"../utils/template.js\";\nimport {\n getInstallCommand,\n getRunCommand,\n installDependencies,\n} from \"../utils/package-manager.js\";\nimport {\n mergeWidgetConfig,\n validateDropletUuid,\n writeWidgetConfig,\n} from \"../utils/config.js\";\nimport { tryFetchGithubTemplate } from \"../utils/github-template.js\";\n\nconst DEFAULT_WIDGET_PACKAGE_VERSION = \"0.1.0\";\nconst DEFAULT_WIDGET_SCOPE = \"droplet\";\n\nexport interface CreateWidgetProjectDependencies {\n readonly installDependencies: typeof installDependencies;\n readonly tryFetchGithubTemplate: typeof tryFetchGithubTemplate;\n}\n\nconst defaultCreateWidgetProjectDependencies = {\n installDependencies,\n tryFetchGithubTemplate,\n} satisfies CreateWidgetProjectDependencies;\n\nexport const createCommand: Command = new Command(\"create\")\n .description(\"Create a standalone Fluid widget project\")\n .argument(\"<project-name>\", \"Name of the widget project to create\")\n .option(\n \"--skip-install\",\n \"Create the scaffold only; skip dependency installation\",\n )\n .option(\n \"-o, --output-dir <dir>\",\n \"Directory to create the project in (defaults to cwd)\",\n )\n .option(\n \"--scope <scope>\",\n \"Widget package scope/namespace\",\n DEFAULT_WIDGET_SCOPE,\n )\n .option(\n \"--package-version <version>\",\n \"Initial widget package version\",\n DEFAULT_WIDGET_PACKAGE_VERSION,\n )\n .option(\n \"--local\",\n \"Use local monorepo packages via link: paths (for development testing)\",\n )\n .option(\n \"--remote-template\",\n \"Use the GitHub starter template instead of the bundled template\",\n )\n .option(\"--droplet <uuid>\", \"Existing droplet UUID that owns the package\")\n .action(async (projectName: string, options: WidgetCreateOptions) => {\n try {\n await createWidgetProject(projectName, options);\n } catch (err) {\n console.log();\n console.error(\n chalk.red(\"Error:\") +\n \" \" +\n (err instanceof Error ? err.message : String(err)),\n );\n console.log();\n process.exit(1);\n }\n });\n\nexport async function createWidgetProject(\n projectName: string,\n options: WidgetCreateOptions,\n dependencies: CreateWidgetProjectDependencies = defaultCreateWidgetProjectDependencies,\n): Promise<void> {\n console.log();\n console.log(chalk.bold(\"Creating a new Fluid widget project\"));\n console.log();\n\n const projectNameError = validateProjectName(projectName);\n if (projectNameError) throw new Error(projectNameError);\n\n const droplet = options.droplet?.trim();\n if (droplet) {\n const dropletError = validateDropletUuid(droplet);\n if (dropletError) throw new Error(dropletError);\n }\n\n const outputDir = path.resolve(options.outputDir ?? process.cwd());\n const targetPath = path.join(outputDir, projectName);\n if (await directoryExists(targetPath)) {\n throw new Error(`Directory already exists: ${targetPath}`);\n }\n\n const templatePath = getDefaultTemplatePath();\n if (\n options.remoteTemplate !== true &&\n !(await directoryExists(templatePath))\n ) {\n throw new Error(\"Default widget template not found.\");\n }\n\n const config = mergeWidgetConfig({}, { droplet });\n const widgetScope = options.scope ?? DEFAULT_WIDGET_SCOPE;\n const localOptions = { local: options.local === true };\n const variables = {\n projectName,\n droplet: config.droplet,\n widgetScope,\n widgetPackageVersion:\n options.packageVersion ?? DEFAULT_WIDGET_PACKAGE_VERSION,\n sdkVersion: await getPortalSdkVersion(localOptions),\n localCoreVersion: options.local\n ? await getPortalCoreVersion(localOptions)\n : undefined,\n fluidCliVersion: await getCliVersion(localOptions),\n widgetCliVersion: await getWidgetCliVersion(localOptions),\n };\n\n if (options.local === true && options.remoteTemplate === true) {\n throw new Error(\"--remote-template cannot be combined with --local\");\n }\n\n // The bundled template is the deterministic default. The mutable GitHub\n // mirror is available only through an explicit opt-in and never silently\n // replaces or falls back to a different schema.\n const useRemoteTemplate = options.remoteTemplate === true;\n\n let scaffolded = false;\n if (useRemoteTemplate) {\n const remoteSpinner = ora(\n \"Fetching widget template from GitHub...\",\n ).start();\n scaffolded = await dependencies.tryFetchGithubTemplate(targetPath, {\n projectName,\n widgetScope,\n widgetPackageVersion:\n options.packageVersion ?? DEFAULT_WIDGET_PACKAGE_VERSION,\n });\n if (scaffolded) {\n remoteSpinner.succeed(\"Fetched widget template from GitHub\");\n } else {\n remoteSpinner.fail(\"Failed to fetch the GitHub widget template\");\n throw new Error(\n \"Couldn't fetch the requested GitHub template. Remove --remote-template to use the bundled template.\",\n );\n }\n }\n\n const spinner = ora(\n scaffolded ? \"Finalizing widget project...\" : \"Copying widget template...\",\n ).start();\n try {\n if (!scaffolded) {\n await copyWidgetTemplate(templatePath, targetPath, variables);\n }\n await writeWidgetConfig(targetPath, config);\n spinner.succeed(\n scaffolded ? \"Prepared widget project\" : \"Copied widget template\",\n );\n } catch (err) {\n spinner.fail(\"Failed to create widget project\");\n throw err;\n }\n\n const installCommand = getInstallCommand(targetPath);\n if (options.skipInstall !== true) {\n spinner.start(`Installing dependencies with ${installCommand}...`);\n try {\n await dependencies.installDependencies(targetPath);\n spinner.succeed(\"Installed dependencies\");\n } catch (error) {\n spinner.fail(\"Failed to install dependencies\");\n console.log();\n console.log(chalk.yellow(`The scaffold was retained at ${targetPath}.`));\n console.log(chalk.yellow(\"Install dependencies manually to continue:\"));\n console.log(chalk.cyan(` cd ${formatCdPath(targetPath)}`));\n console.log(chalk.cyan(` ${installCommand}`));\n throw error;\n }\n }\n\n console.log();\n if (options.skipInstall === true) {\n console.log(\n chalk.yellow(\n \"Scaffold only: dependencies were not installed and must be installed before development.\",\n ),\n );\n console.log();\n }\n console.log(\n chalk.green.bold(\"Success!\") + ` Created ${chalk.cyan(projectName)}`,\n );\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.cyan(` cd ${formatCdPath(targetPath)}`));\n if (options.skipInstall === true) {\n console.log(chalk.cyan(` ${installCommand}`));\n }\n if (!config.droplet) {\n console.log(chalk.cyan(\" fluid widget link\"));\n }\n console.log(chalk.cyan(` ${getRunCommand(\"dev\", targetPath)}`));\n console.log();\n console.log(\n \"Edit \" + chalk.cyan(\"manifest.ts\") + \" to customize your widget package.\",\n );\n console.log(\n chalk.dim(\n \"This command only creates local project files; it does not create a droplet.\",\n ),\n );\n console.log();\n}\n\nfunction validateProjectName(projectName: string): string | undefined {\n if (!projectName) return \"Project name is required.\";\n if (!/^[a-z0-9][a-z0-9-]*$/.test(projectName)) {\n return \"Project name must contain only lowercase letters, numbers, and hyphens.\";\n }\n return undefined;\n}\n\nfunction formatCdPath(targetPath: string): string {\n return path.relative(process.cwd(), targetPath) || \".\";\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { runCliAction } from \"../utils/command.js\";\nimport {\n getInstallCommand,\n installDependencies,\n} from \"../utils/package-manager.js\";\n\nexport const DEFAULT_WIDGET_DEV_PORT = 5174;\n\nexport const WIDGET_DEV_ROUTES = [\n \"/__widget-packages__\",\n \"/__runtime-entry__\",\n] as const;\n\nexport interface WidgetDevOptions {\n readonly port?: string;\n readonly host?: boolean | string;\n readonly mode?: string;\n}\n\nexport interface WidgetDevProjectSummary {\n readonly projectDir: string;\n readonly packageName: string;\n readonly viteConfigPath: string;\n readonly localUrl: string;\n readonly target: string;\n readonly mode: string;\n readonly routes: readonly string[];\n}\n\nexport const devCommand: Command = new Command(\"dev\")\n .description(\"Start the local Fluid widget development endpoints\")\n .option(\n \"-p, --port <port>\",\n \"Port to run the widget dev server on\",\n String(DEFAULT_WIDGET_DEV_PORT),\n )\n .option(\"--host [host]\", \"Expose the dev server to the network\")\n .option(\"--mode <mode>\", \"Vite mode to run\", \"development\")\n .action((options: WidgetDevOptions) => {\n return runCliAction(async () => {\n const projectDir = process.cwd();\n const summary = await resolveWidgetDevProject(projectDir, options);\n\n printWidgetDevSummary(summary);\n await runViteDevServer(projectDir, options);\n });\n });\n\nexport async function resolveWidgetDevProject(\n projectDir: string,\n options: WidgetDevOptions = {},\n): Promise<WidgetDevProjectSummary> {\n const resolvedProjectDir = path.resolve(projectDir);\n const packageJsonPath = path.join(resolvedProjectDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n throw new Error(\n \"No package.json found. Run this command from a Fluid widget project directory.\",\n );\n }\n\n const packageJson = await readPackageJson(packageJsonPath);\n const packageName = readPackageName(packageJson) ?? path.basename(projectDir);\n\n const viteConfigPath = path.join(resolvedProjectDir, \"vite.config.ts\");\n if (!existsSync(viteConfigPath)) {\n throw new Error(\n \"No vite.config.ts found. Run this command from a Fluid widget project directory.\",\n );\n }\n\n const port = parsePort(options.port ?? String(DEFAULT_WIDGET_DEV_PORT));\n const host = normalizeHostOption(options.host);\n const mode = normalizeMode(options.mode);\n\n return {\n projectDir: resolvedProjectDir,\n packageName,\n viteConfigPath,\n localUrl: formatLocalUrl(port, host),\n target: packageName,\n mode,\n routes: WIDGET_DEV_ROUTES,\n };\n}\n\nexport function buildViteDevArgs(options: WidgetDevOptions = {}): string[] {\n const port = parsePort(options.port ?? String(DEFAULT_WIDGET_DEV_PORT));\n const host = normalizeHostOption(options.host);\n const mode = normalizeMode(options.mode);\n const args = [\"--port\", String(port), \"--mode\", mode];\n\n if (host) {\n args.push(\"--host\", host);\n }\n\n return args;\n}\n\nexport function printWidgetDevSummary(summary: WidgetDevProjectSummary): void {\n console.log();\n console.log(chalk.blue.bold(\"Fluid Widget Dev\"));\n console.log(chalk.gray(\"Local: \") + chalk.cyan(summary.localUrl));\n console.log(chalk.gray(\"Target: \") + chalk.white(summary.target));\n console.log(chalk.gray(\"Mode: \") + chalk.white(summary.mode));\n console.log(chalk.gray(\"Routes:\"));\n for (const route of summary.routes) {\n console.log(chalk.gray(\" - \") + chalk.cyan(route));\n }\n console.log();\n}\n\nexport async function runViteDevServer(\n projectDir: string,\n options: WidgetDevOptions = {},\n): Promise<void> {\n let viteCliPath = resolveViteCliPath(projectDir);\n if (!viteCliPath) {\n // Cloned checkouts arrive without node_modules (`fluid widget clone` is a\n // pure git operation) and agent-scaffolded projects may skip the install\n // too. Install once here instead of bouncing the user to a manual step.\n const installCommand = getInstallCommand(projectDir);\n console.log(\n chalk.yellow(\n `Vite is not installed yet — running ${installCommand} first...`,\n ),\n );\n try {\n await installDependencies(projectDir);\n } catch {\n // Fall through to the resolution check below for the actionable error.\n }\n viteCliPath = resolveViteCliPath(projectDir);\n }\n if (!viteCliPath) {\n throw new Error(\n `Unable to find Vite in node_modules. Run \\`${getInstallCommand(projectDir)}\\` in ${projectDir}, then retry.`,\n );\n }\n\n await runNodeScript(viteCliPath, buildViteDevArgs(options), projectDir);\n}\n\nfunction resolveViteCliPath(projectDir: string): string | undefined {\n const viteCliPath = path.join(\n projectDir,\n \"node_modules\",\n \"vite\",\n \"bin\",\n \"vite.js\",\n );\n return existsSync(viteCliPath) ? viteCliPath : undefined;\n}\n\nasync function readPackageJson(packageJsonPath: string): Promise<unknown> {\n try {\n return JSON.parse(await readFile(packageJsonPath, \"utf-8\")) as unknown;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Unable to read package.json: ${message}`);\n }\n}\n\nfunction readPackageName(packageJson: unknown): string | undefined {\n if (!isRecord(packageJson)) return undefined;\n const name = packageJson[\"name\"];\n if (typeof name !== \"string\") return undefined;\n const trimmed = name.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction parsePort(value: string): number {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"Port must be an integer between 1 and 65535.\");\n }\n return port;\n}\n\nfunction normalizeHostOption(\n host: WidgetDevOptions[\"host\"],\n): string | undefined {\n if (host === undefined || host === false) return undefined;\n if (host === true) return \"0.0.0.0\";\n\n const trimmed = host.trim();\n return trimmed.length > 0 ? trimmed : \"0.0.0.0\";\n}\n\nfunction normalizeMode(mode: string | undefined): string {\n const trimmed = mode?.trim();\n return trimmed && trimmed.length > 0 ? trimmed : \"development\";\n}\n\nfunction formatLocalUrl(port: number, host: string | undefined): string {\n const displayHost = host && host !== \"0.0.0.0\" ? host : \"localhost\";\n return `http://${displayHost}:${port}`;\n}\n\nfunction runNodeScript(\n scriptPath: string,\n args: readonly string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, [scriptPath, ...args], {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n if (code === 0 || signal === \"SIGINT\" || signal === \"SIGTERM\") {\n resolve();\n return;\n }\n\n reject(\n new Error(\n signal\n ? `Vite dev server exited with signal ${signal}.`\n : `Vite dev server exited with code ${code ?? \"unknown\"}.`,\n ),\n );\n });\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import prompts from \"prompts\";\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport type { Choice } from \"prompts\";\n\nexport interface DropletChoice {\n readonly uuid: string;\n readonly name: string;\n}\n\nconst MAX_DROPLET_PAGES = 100;\n\nexport async function promptForDroplet(\n client: FluidOsHeyApiClient,\n): Promise<string | undefined> {\n const droplets = await listDroplets(client);\n\n if (droplets.length === 0) {\n throw new Error(\n \"No droplets were found for this account. Create a droplet in Fluid first, then run this command again.\",\n );\n }\n\n const response = await prompts({\n type: \"autocomplete\",\n name: \"droplet\",\n message: \"Select the droplet that owns this widget package\",\n choices: droplets.map((droplet) => ({\n title: `${droplet.name} (${droplet.uuid})`,\n value: droplet.uuid,\n })),\n suggest: (input: string, choices: Choice[]) =>\n Promise.resolve(\n input\n ? choices.filter((choice) =>\n choice.title.toLowerCase().includes(input.toLowerCase()),\n )\n : choices,\n ),\n });\n\n return response[\"droplet\"] as string | undefined;\n}\n\nexport async function listDroplets(\n client: FluidOsHeyApiClient,\n): Promise<readonly DropletChoice[]> {\n try {\n const firstResponse = await client.get({\n query: { page: 1 },\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/api/droplets\",\n });\n const totalPages = Math.min(\n readTotalPages(firstResponse) ?? 1,\n MAX_DROPLET_PAGES,\n );\n const responses = [firstResponse];\n\n for (let page = 2; page <= totalPages; page += 1) {\n responses.push(\n await client.get({\n query: { page },\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/api/droplets\",\n }),\n );\n }\n\n return responses.flatMap(normalizeDropletsResponse);\n } catch (err) {\n if (isApiLikeError(err)) {\n if (err.status === 401 || err.status === 403) {\n throw new Error(\n \"Your Fluid session has expired. Run `fluid login` and try again.\",\n );\n }\n throw new Error(\n `Could not fetch droplets from Fluid (HTTP ${err.status}). ${err.message}`,\n );\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Could not fetch droplets from Fluid. ${message}`);\n }\n}\n\nfunction readTotalPages(response: unknown): number | undefined {\n if (!isRecord(response)) return undefined;\n const meta = response[\"meta\"];\n if (!isRecord(meta)) return undefined;\n const pagination = meta[\"pagination\"];\n if (!isRecord(pagination)) return undefined;\n const totalPages = pagination[\"total_pages\"] ?? pagination[\"totalPages\"];\n if (\n typeof totalPages !== \"number\" ||\n !Number.isInteger(totalPages) ||\n totalPages < 1\n ) {\n return undefined;\n }\n return totalPages;\n}\n\nfunction normalizeDropletsResponse(response: unknown): DropletChoice[] {\n const candidates = extractDropletArray(response);\n return candidates\n .map(normalizeDroplet)\n .filter((droplet): droplet is DropletChoice => droplet !== undefined);\n}\n\nfunction extractDropletArray(response: unknown): readonly unknown[] {\n if (Array.isArray(response)) return response;\n if (!isRecord(response)) return [];\n\n const directDroplets = response[\"droplets\"];\n if (Array.isArray(directDroplets)) return directDroplets;\n\n const data = response[\"data\"];\n if (Array.isArray(data)) return data;\n if (isRecord(data) && Array.isArray(data[\"droplets\"])) {\n return data[\"droplets\"];\n }\n\n return [];\n}\n\nfunction normalizeDroplet(value: unknown): DropletChoice | undefined {\n if (!isRecord(value)) return undefined;\n\n const uuid = readString(value, \"uuid\") ?? readString(value, \"id\");\n if (!uuid) return undefined;\n\n const name =\n readString(value, \"name\") ??\n readString(value, \"title\") ??\n readString(value, \"slug\") ??\n uuid;\n\n return { uuid, name };\n}\n\nfunction readString(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): string | undefined {\n const value = record[key];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction isApiLikeError(\n error: unknown,\n): error is { readonly status: number; readonly message: string } {\n return (\n error instanceof Error &&\n \"status\" in error &&\n typeof (error as { readonly status?: unknown }).status === \"number\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import path from \"node:path\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport type { WidgetLinkOptions } from \"../types.js\";\nimport { createAuthenticatedClient } from \"../utils/auth-client.js\";\nimport { promptForDroplet } from \"../utils/droplets.js\";\nimport {\n WIDGET_CONFIG_FILE,\n loadWidgetConfig,\n mergeWidgetConfig,\n validateDropletUuid,\n writeWidgetConfig,\n} from \"../utils/config.js\";\n\nexport const linkCommand: Command = new Command(\"link\")\n .description(\"Link this widget project to an existing Fluid droplet\")\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .action(async (options: WidgetLinkOptions) => {\n try {\n const projectDir = process.cwd();\n const loaded = await loadWidgetConfig(projectDir);\n\n let droplet = options.droplet?.trim() || undefined;\n if (!droplet) {\n const spinner = ora(\"Fetching droplets...\").start();\n try {\n const { client } = createAuthenticatedClient();\n spinner.stop();\n droplet = await promptForDroplet(client);\n } catch (err) {\n spinner.fail(\"Unable to load droplets\");\n throw err;\n }\n\n if (!droplet) {\n console.log(chalk.dim(\"Cancelled.\"));\n return;\n }\n }\n\n const nextConfig = mergeWidgetConfig(loaded.config, { droplet });\n const nextDropletError = validateDropletUuid(nextConfig.droplet ?? \"\");\n if (nextDropletError) throw new Error(nextDropletError);\n\n await writeWidgetConfig(projectDir, nextConfig);\n\n console.log();\n console.log(chalk.green(\"Linked widget project.\"));\n console.log(\n chalk.gray(\"Config: \") +\n chalk.cyan(\n path.relative(projectDir, loaded.path) || WIDGET_CONFIG_FILE,\n ),\n );\n console.log(\n chalk.gray(\"Droplet: \") + chalk.white(nextConfig.droplet),\n );\n console.log(\n chalk.gray(\"Package key: \") +\n chalk.white(`${nextConfig.droplet} (derived from droplet)`),\n );\n console.log();\n } catch (err) {\n console.log();\n console.error(\n chalk.red(\"Error:\") +\n \" \" +\n (err instanceof Error ? err.message : String(err)),\n );\n console.log();\n process.exit(1);\n }\n });\n","import type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\n\nexport interface DropletWidgetVersionSummary {\n readonly packageKey?: string;\n readonly packageId?: string;\n readonly version?: string;\n readonly status?: string;\n readonly createdAt?: string;\n readonly updatedAt?: string;\n readonly artifactCount?: number;\n readonly raw: unknown;\n}\n\nexport interface DropletWidgetLogEntry {\n readonly timestamp?: string;\n readonly level?: string;\n readonly message: string;\n readonly raw: unknown;\n}\n\nexport async function fetchDropletWidgetStatus(options: {\n readonly client: FluidOsHeyApiClient;\n readonly droplet: string;\n}): Promise<DropletWidgetVersionSummary[]> {\n const response = await options.client.get({\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: `/api/droplets/${encodeURIComponent(options.droplet)}/widget_package_versions`,\n });\n return extractArray(response).map(normalizeVersionSummary);\n}\n\nexport async function fetchDropletWidgetLogs(options: {\n readonly client: FluidOsHeyApiClient;\n readonly droplet: string;\n readonly limit?: number;\n}): Promise<DropletWidgetLogEntry[]> {\n const response = await options.client.get({\n query: options.limit ? { limit: options.limit } : undefined,\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: `/api/droplets/${encodeURIComponent(options.droplet)}/widget_package_versions/logs`,\n });\n return extractArray(response).map(normalizeLogEntry);\n}\n\nexport function formatStatusRows(\n versions: readonly DropletWidgetVersionSummary[],\n): string {\n if (versions.length === 0) return \"No widget package versions found.\";\n\n return versions\n .map((version) => {\n const identity =\n version.packageId ?? version.packageKey ?? \"unknown-package\";\n const release = version.version ?? \"unknown-version\";\n const status = version.status ?? \"unknown\";\n const updated = version.updatedAt ?? version.createdAt ?? \"unknown time\";\n const artifacts =\n version.artifactCount === undefined\n ? \"unknown artifacts\"\n : `${version.artifactCount} artifact${version.artifactCount === 1 ? \"\" : \"s\"}`;\n return `${identity}@${release} — ${status} — ${artifacts} — ${updated}`;\n })\n .join(\"\\n\");\n}\n\nexport function formatLogRows(logs: readonly DropletWidgetLogEntry[]): string {\n if (logs.length === 0) return \"No widget package logs found.\";\n\n return logs\n .map((entry) => {\n const timestamp = entry.timestamp ?? \"unknown time\";\n const level = entry.level ? entry.level.toUpperCase() : \"INFO\";\n return `[${timestamp}] ${level} ${entry.message}`;\n })\n .join(\"\\n\");\n}\n\nfunction normalizeVersionSummary(value: unknown): DropletWidgetVersionSummary {\n const record = unwrapKnownNestedRecord(value);\n const artifacts = readArray(record, \"artifacts\");\n return {\n packageKey: readFirstString(record, [\"package_key\", \"packageKey\"]),\n packageId: readFirstString(record, [\"package_id\", \"packageId\"]),\n version: readFirstString(record, [\"version\", \"name\"]),\n status: readFirstString(record, [\"status\", \"state\"]),\n createdAt: readFirstString(record, [\"created_at\", \"createdAt\"]),\n updatedAt: readFirstString(record, [\"updated_at\", \"updatedAt\"]),\n ...(artifacts ? { artifactCount: artifacts.length } : {}),\n raw: value,\n };\n}\n\nfunction normalizeLogEntry(value: unknown): DropletWidgetLogEntry {\n const record = unwrapKnownNestedRecord(value);\n return {\n timestamp: readFirstString(record, [\n \"timestamp\",\n \"created_at\",\n \"createdAt\",\n ]),\n level: readFirstString(record, [\"level\", \"severity\"]),\n message:\n readFirstString(record, [\"message\", \"event\", \"status\", \"state\"]) ??\n JSON.stringify(value),\n raw: value,\n };\n}\n\nfunction extractArray(value: unknown): unknown[] {\n if (Array.isArray(value)) return value;\n if (!isRecord(value)) return [];\n\n for (const key of [\n \"widget_package_versions\",\n \"widgetPackageVersions\",\n \"versions\",\n \"logs\",\n \"events\",\n \"data\",\n ] as const) {\n const nested = value[key];\n if (Array.isArray(nested)) return nested;\n }\n\n return [value];\n}\n\nfunction unwrapKnownNestedRecord(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) return {};\n for (const key of [\n \"widget_package_version\",\n \"widgetPackageVersion\",\n \"version\",\n \"log\",\n \"event\",\n ] as const) {\n const nested = value[key];\n if (isRecord(nested)) return nested;\n }\n return value;\n}\n\nfunction readArray(\n record: Record<string, unknown>,\n key: string,\n): readonly unknown[] | undefined {\n const value = record[key];\n return Array.isArray(value) ? value : undefined;\n}\n\nfunction readFirstString(\n record: Record<string, unknown>,\n keys: readonly string[],\n): string | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) return value;\n if (typeof value === \"number\" && Number.isFinite(value))\n return String(value);\n }\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { loadWidgetConfig, validateDropletUuid } from \"../utils/config.js\";\nimport { fetchDropletWidgetLogs, formatLogRows } from \"../utils/droplet-api.js\";\nimport { runCliAction } from \"../utils/command.js\";\n\nexport interface LogsCommandOptions {\n readonly droplet?: string;\n readonly limit?: string;\n readonly json?: boolean;\n}\n\nexport const logsCommand: Command = new Command(\"logs\")\n .description(\"Show recent widget package publish logs for a Droplet\")\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--limit <number>\", \"Maximum number of log entries to request\", \"50\")\n .option(\"--json\", \"Print raw log response as JSON\")\n .action((options: LogsCommandOptions) => {\n return runCliAction(async () => {\n const droplet = await resolveDroplet(process.cwd(), options.droplet);\n const limit = parseLimit(options.limit);\n const logs = await fetchDropletWidgetLogs({\n client: createAuthenticatedWidgetPackageClient(),\n droplet,\n limit,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n logs.map((entry) => entry.raw),\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(chalk.blue.bold(`Widget logs for droplet ${droplet}`));\n console.log();\n console.log(formatLogRows(logs));\n });\n });\n\nasync function resolveDroplet(\n projectDir: string,\n override: string | undefined,\n): Promise<string> {\n const droplet =\n override?.trim() || (await loadWidgetConfig(projectDir)).config.droplet;\n if (droplet?.trim()) {\n const trimmedDroplet = droplet.trim();\n const dropletError = validateDropletUuid(trimmedDroplet);\n if (dropletError) throw new Error(dropletError);\n return trimmedDroplet;\n }\n\n throw new Error(\n \"Missing droplet UUID. Pass --droplet <uuid> or set droplet in fluid.widget.config.ts.\",\n );\n}\n\nfunction parseLimit(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n if (Number.isInteger(parsed) && parsed > 0 && parsed <= 500) return parsed;\n throw new Error(\"--limit must be an integer between 1 and 500.\");\n}\n","import { Command } from \"commander\";\nimport {\n publishWidgetPackage as publishWidgetPackageArtifacts,\n type PublishedWidgetPackage,\n} from \"@fluid-app/fluid-cli-widget-tooling\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n DEFAULT_WIDGET_OUT_DIR,\n validateDropletWidgetProject,\n withRootWidgetConfigBridge,\n} from \"../utils/source-package.js\";\nimport { loadWidgetConfig, validateDropletUuid } from \"../utils/config.js\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { runPackageScriptIfAvailable } from \"../utils/package-scripts.js\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { getWidgetCliVersion } from \"../utils/template.js\";\n\nexport interface PublishWidgetPackageOptions {\n readonly projectDir: string;\n readonly outDir: string;\n readonly droplet?: string;\n readonly dryRun?: boolean;\n readonly skipTypecheck?: boolean;\n}\n\nexport interface PublishWidgetPackageResult {\n readonly dryRun: boolean;\n readonly uploaded: boolean;\n readonly outDir: string;\n readonly droplet?: string;\n}\n\nexport async function publishWidgetPackage(\n options: PublishWidgetPackageOptions,\n): Promise<PublishWidgetPackageResult> {\n const droplet = await resolvePublishDroplet(\n options.projectDir,\n options.droplet,\n );\n\n await validateDropletWidgetProject(options.projectDir, droplet);\n if (options.skipTypecheck !== true) {\n await runPackageScriptIfAvailable({\n projectDir: options.projectDir,\n scriptName: \"typecheck\",\n });\n }\n\n const dryRun = options.dryRun === true;\n await withRootWidgetConfigBridge(\n options.projectDir,\n () =>\n publishDropletWidgetPackageArtifacts({\n projectDir: options.projectDir,\n outDir: options.outDir,\n droplet,\n dryRun,\n }),\n droplet,\n );\n\n return {\n dryRun,\n uploaded: !dryRun,\n outDir: options.outDir,\n droplet,\n };\n}\n\nexport interface PublishCommandOptions {\n readonly outDir?: string;\n readonly droplet?: string;\n readonly dryRun?: boolean;\n readonly skipTypecheck?: boolean;\n}\n\nexport const publishCommand: Command = new Command(\"publish\")\n .description(\"Publish a Fluid widget package\")\n .option(\n \"-o, --out-dir <dir>\",\n \"Widget artifact output directory\",\n DEFAULT_WIDGET_OUT_DIR,\n )\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--dry-run\", \"Build and validate without uploading\")\n .option(\"--skip-typecheck\", \"Skip package typecheck script when present\")\n .action((options: PublishCommandOptions) => {\n return runCliAction(async () => {\n const projectDir = process.cwd();\n const outDir = options.outDir ?? DEFAULT_WIDGET_OUT_DIR;\n const droplet = await resolvePublishDroplet(projectDir, options.droplet);\n const dryRun = options.dryRun === true;\n\n console.log();\n console.log(chalk.blue.bold(\"Fluid Widget Publish\"));\n console.log();\n printRuntimeOnlyNotice();\n console.log(chalk.gray(\"Droplet: \") + chalk.white(droplet));\n console.log(chalk.gray(\"Output: \") + chalk.cyan(outDir));\n if (dryRun) {\n console.log(chalk.yellow(\"Dry run: no upload will be created.\"));\n }\n console.log();\n\n const validateSpinner = ora(\"Validating widget package...\").start();\n await validateDropletWidgetProject(projectDir, droplet);\n validateSpinner.succeed(\"Validated widget package\");\n\n if (options.skipTypecheck !== true) {\n const typecheckSpinner = ora(\"Running package typecheck...\").start();\n const typecheck = await runPackageScriptIfAvailable({\n projectDir,\n scriptName: \"typecheck\",\n });\n if (typecheck.ran) {\n typecheckSpinner.succeed(\"Package typecheck passed\");\n } else {\n typecheckSpinner.info(\"No typecheck script found; skipping\");\n }\n }\n\n const publishSpinner = ora(\n dryRun\n ? \"Building and preparing dry-run upload payload...\"\n : \"Building and publishing widget artifacts...\",\n ).start();\n\n const result = await withRootWidgetConfigBridge(\n projectDir,\n () =>\n publishDropletWidgetPackageArtifacts({\n projectDir,\n outDir,\n droplet,\n dryRun,\n }),\n droplet,\n );\n\n publishSpinner.succeed(\n dryRun ? \"Prepared dry-run upload payload\" : \"Published widget package\",\n );\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"Dry run complete — upload session was not requested.\"),\n );\n console.log();\n printDryRunSessionPayload(result);\n }\n\n printWidgetPublishSummary({\n title: dryRun ? \"Widget publish dry run\" : \"Widget publish\",\n ownerLabel: `droplet ${droplet}`,\n outDir,\n result,\n });\n });\n });\n\nexport async function resolvePublishDroplet(\n projectDir: string,\n override: string | undefined,\n): Promise<string> {\n const droplet =\n override?.trim() || (await loadWidgetConfig(projectDir)).config.droplet;\n if (droplet?.trim()) {\n const trimmedDroplet = droplet.trim();\n const dropletError = validateDropletUuid(trimmedDroplet);\n if (dropletError) throw new Error(dropletError);\n return trimmedDroplet;\n }\n\n throw new Error(\n \"Missing droplet UUID. Pass --droplet <uuid> or set droplet in fluid.widget.config.ts.\",\n );\n}\n\nasync function publishDropletWidgetPackageArtifacts(options: {\n readonly projectDir: string;\n readonly outDir: string;\n readonly droplet: string;\n readonly dryRun: boolean;\n}): Promise<PublishedWidgetPackage> {\n const common = {\n projectDir: options.projectDir,\n outDir: options.outDir,\n owner: \"droplet\",\n uploadOwner: { kind: \"droplet\", uuid: options.droplet },\n cliVersion: await getWidgetCliVersion(),\n } as const;\n\n if (options.dryRun) {\n return publishWidgetPackageArtifacts({\n ...common,\n dryRun: true,\n });\n }\n\n return publishWidgetPackageArtifacts({\n ...common,\n dryRun: false,\n client: createAuthenticatedWidgetPackageClient(),\n });\n}\n\nfunction printRuntimeOnlyNotice(): void {\n console.log(\n chalk.yellow(\n \"This publishes widget runtime artifacts only; it does not deploy the hosted portal shell.\",\n ),\n );\n console.log();\n}\n\nfunction printDryRunSessionPayload(result: PublishedWidgetPackage): void {\n console.log(chalk.bold(\"Dry-run upload session payload:\"));\n console.log(JSON.stringify(result.publish.sessionPayload, null, 2));\n console.log();\n}\n\nfunction printWidgetPublishSummary(options: {\n readonly title: string;\n readonly ownerLabel: string;\n readonly outDir: string;\n readonly result: PublishedWidgetPackage;\n}): void {\n console.log();\n console.log(chalk.green.bold(`${options.title} complete`));\n console.log();\n console.log(chalk.gray(\"Owner: \") + chalk.white(options.ownerLabel));\n console.log(\n chalk.gray(\"Package: \") + chalk.white(options.result.build.packageId),\n );\n console.log(\n chalk.gray(\"Version: \") + chalk.white(options.result.build.version),\n );\n console.log(chalk.gray(\"Output: \") + chalk.cyan(options.outDir));\n console.log(\n chalk.gray(\"Artifacts: \") +\n chalk.white(String(options.result.request.artifacts.length)),\n );\n console.log();\n}\n","import type { GitSyncActor } from \"@fluid-app/fluid-cli\";\nimport { gitSyncActorFromMe } from \"@fluid-app/fluid-cli\";\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\n\n/**\n * `GET /api/me` — the authenticated user's identity, used to stamp\n * auto-commit messages in the canonical GitSync format. The name fallback\n * chain and the shape it feeds both live in `@fluid-app/fluid-cli`'s\n * git-sync/commit-subject.ts, shared with the mist / portal / theme CLIs.\n *\n * Best-effort by contract: callers treat a rejection (or a null actor) as\n * a system-attributed commit rather than failing the push.\n */\nexport async function fetchCurrentUser(\n client: FluidOsHeyApiClient,\n): Promise<GitSyncActor | null> {\n const raw = (await client.get({\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/api/me\",\n })) as Record<string, unknown>;\n return gitSyncActorFromMe(raw);\n}\n","import type { ChangeEntry, GitSyncActor } from \"@fluid-app/fluid-cli\";\nimport {\n gitSyncCommitSubject,\n resolveGitSyncActor,\n subjectFragment,\n summarizeChanges,\n} from \"@fluid-app/fluid-cli\";\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport {\n ensureLocalStateExcluded,\n gitAdoptFetchHead,\n gitAheadBehindVsFetchHead,\n gitAutoCommit,\n gitFetch,\n gitInit,\n gitMergeFastForward,\n gitPush,\n gitRemoteBranchExists,\n gitStash,\n gitStashPop,\n hasCommits,\n hasUncommittedChanges,\n isGitRepository,\n purgeLocalStateFromIndex,\n type GitCommitIdentity,\n} from \"./git.js\";\nimport { mintWidgetGitCredential } from \"../utils/git-credential.js\";\nimport { fetchCurrentUser } from \"../utils/me.js\";\nimport { readWidgetMarker } from \"../utils/widget-marker.js\";\n\nexport interface SyncWidgetGitRepoOptions {\n readonly cwd: string;\n readonly client: FluidOsHeyApiClient;\n /** Droplet UUID that owns the package; omitted for company-owned packages. */\n readonly droplet?: string;\n readonly branch?: string;\n /** Base auto-commit message (before the author/public-id stamp). */\n readonly message?: string;\n /** Skip the auto-commit step and push existing commits only. */\n readonly commit?: boolean;\n}\n\nexport type SyncWidgetGitRepoResult =\n | {\n readonly kind: \"synced\";\n readonly pulled: number;\n readonly committed: boolean;\n }\n | {\n readonly kind: \"diverged\";\n readonly ahead: number;\n readonly behind: number;\n };\n\n/**\n * Sync a widget project's invisible git repo: mint a credential, reconcile\n * with origin (fast-forward pull when safe), auto-commit working-tree changes\n * with an author-stamped message, and push HEAD to the branch.\n *\n * Mirrors the Mist CLI write path (`packages/cli/mist/src/commands/push.ts`).\n * Throws on hard failures (mint error, diverged history is returned rather\n * than thrown so the caller can message it); the token-bearing remote URL is\n * only ever handed to the git helpers, never logged or persisted.\n */\nexport async function syncWidgetGitRepo(\n options: SyncWidgetGitRepoOptions,\n): Promise<SyncWidgetGitRepoResult> {\n const { cwd, client } = options;\n const branch = options.branch ?? \"main\";\n // One `/api/me` for the whole sync, shared by the message stamp and the\n // git author. Previously each of the three consumers below fetched it\n // independently, so a slow /api/me cost up to 15s of a push.\n const actor = memoizeActor(client);\n\n // Ensure a local repo exists — projects created via `fluid widget create`\n // have their git history stripped, so first push initializes one.\n if (!(await isGitRepository(cwd))) {\n await gitInit(cwd, branch);\n }\n\n // Scope the sync to the widget project before ANY tree inspection. Mist\n // Desktop writes its private per-machine state (`.mist-desktop/`: chat\n // transcripts, attachments, screenshots) into the project root it\n // opened; left unexcluded it makes every Desktop-opened project read as\n // dirty (forcing a needless stash/pop around the pull below) and gets\n // published wholesale by the auto-commit.\n await ensureLocalStateExcluded(cwd);\n\n // Mint one credential for the whole sync — tokens live ~1h, far beyond a\n // push. Minting again mid-flow would reintroduce a degrade window AFTER\n // the auto-commit: a 404/409 there reads as \"sync unavailable\" to the\n // caller, which would publish artifacts while the fresh commit stays\n // local. With a single mint, unavailability can only surface before any\n // local or remote mutation.\n const cred = await mintWidgetGitCredential({\n client,\n droplet: options.droplet,\n });\n\n // Reconcile against the remote before committing. `gitRemoteBranchExists`\n // and `gitFetch` both throw on transport/auth failure (propagated to the\n // caller as a hard error) so a network blip is never mistaken for an empty\n // remote — that would skip drift detection and let us push over a\n // collaborator's work. We only skip reconciliation when the branch\n // genuinely doesn't exist yet (freshly provisioned repo, first push).\n let pulled = 0;\n const branchExists = await gitRemoteBranchExists(cwd, cred.remoteUrl, branch);\n if (branchExists) {\n await gitFetch(cwd, cred.remoteUrl, branch);\n if (await hasCommits(cwd)) {\n const { ahead, behind } = await gitAheadBehindVsFetchHead(cwd);\n if (behind > 0 && ahead > 0) {\n return { kind: \"diverged\", ahead, behind };\n }\n if (behind > 0) {\n const wasDirty = await hasUncommittedChanges(cwd);\n if (wasDirty) await gitStash(cwd, \"fluid-widget-push: pre-pull stash\");\n try {\n await gitMergeFastForward(cwd);\n } finally {\n if (wasDirty) await gitStashPop(cwd); // throws on conflict\n }\n pulled = behind;\n }\n } else {\n // Brand-new local repo (`create` strips git history) but the remote\n // branch already has commits — the backend provisions repos with an\n // auto-init README (or starter-template) commit. Adopt that history\n // as the local base so the auto-commit below lands on top of it and\n // the push fast-forwards; a fresh root commit here would be rejected\n // as unrelated history.\n pulled = await gitAdoptFetchHead(cwd);\n }\n }\n\n // Untrack chats leaked by an older CLI, UNCONDITIONALLY. A checkout\n // whose only problem is a tracked `.mist-desktop/` has a clean working\n // tree, and `--no-commit` suppresses the commit below entirely — so\n // gating this on either would skip the cleanup forever and leave the\n // chats published. Runs after reconciliation, immediately before the\n // push. No-op when nothing was tracked (the common case).\n await purgeLocalStateFromIndex(\n cwd,\n // Housekeeping the CLI does on its own initiative, so it's attributed\n // to `Fluid` rather than to whoever happened to trigger this push.\n gitSyncCommitSubject(\n \"Remove private Mist Desktop state from the widget repository\",\n null,\n ),\n commitIdentity(await actor()),\n );\n\n // Auto-commit working-tree changes (unless --no-commit).\n let committed = false;\n if (options.commit !== false && (await hasUncommittedChanges(cwd))) {\n const resolved = await actor();\n await gitAutoCommit(\n cwd,\n (changes) => buildCommitMessage(cwd, resolved, changes, options.message),\n commitIdentity(resolved),\n );\n committed = true;\n }\n\n await gitPush(cwd, cred.remoteUrl, branch);\n\n return { kind: \"synced\", pulled, committed };\n}\n\n/**\n * Build the auto-commit message in the canonical GitSync shape —\n * `<name>: <action> · <timestamp> (<public_id>)` — so widget history reads\n * the same as mist / theme / portal history and always says who published.\n * A `-m` message replaces the action but keeps the stamp. An unknown actor\n * yields a `Fluid:` system commit rather than an unattributed one.\n */\nfunction buildCommitMessage(\n cwd: string,\n actor: GitSyncActor | null,\n changes: readonly ChangeEntry[],\n base?: string,\n): string {\n // Precedence: an explicit `-m` states the INTENT, which no diff can\n // recover. Otherwise describe what actually changed. The package-key\n // constant is the last resort, for a diff we couldn't read.\n const packageKey = readWidgetMarker(cwd)?.package_key;\n const fallback = packageKey\n ? `Publish widget ${subjectFragment(packageKey)}`\n : \"Publish widget\";\n const action = base?.trim() || summarizeChanges(changes) || fallback;\n return gitSyncCommitSubject(action, actor);\n}\n\n/** Prefer the Fluid user for the git author when the repo has no identity. */\nfunction commitIdentity(\n actor: GitSyncActor | null,\n): GitCommitIdentity | undefined {\n // undefined → git.ts's default identity.\n return actor ? { name: actor.name, email: \"cli@fluid.app\" } : undefined;\n}\n\n/**\n * Resolve the signed-in user once per sync, cached across callers.\n * Best-effort by contract: a failed or slow `/api/me` resolves to null (a\n * system-attributed commit) instead of failing the push.\n */\nfunction memoizeActor(\n client: FluidOsHeyApiClient,\n): () => Promise<GitSyncActor | null> {\n let pending: Promise<GitSyncActor | null> | null = null;\n return () =>\n (pending ??= resolveGitSyncActor(() =>\n withTimeout(fetchCurrentUser(client), 5_000),\n ));\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms),\n ),\n ]);\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { DEFAULT_WIDGET_OUT_DIR } from \"../utils/source-package.js\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { syncWidgetGitRepo } from \"../lib/git-sync.js\";\nimport { GitError } from \"../lib/git.js\";\nimport { isGitSyncUnavailable } from \"../utils/git-credential.js\";\nimport { publishWidgetPackage, resolvePublishDroplet } from \"./publish.js\";\n\nexport interface PushCommandOptions {\n readonly outDir?: string;\n readonly droplet?: string;\n readonly dryRun?: boolean;\n readonly skipTypecheck?: boolean;\n readonly branch?: string;\n readonly message?: string;\n /** Set false by `--no-commit`: push existing commits without auto-committing. */\n readonly commit?: boolean;\n /** Sync the git repo but skip the build + publish pipeline. */\n readonly skipPublish?: boolean;\n}\n\nexport const pushCommand: Command = new Command(\"push\")\n .description(\n \"Sync the widget's git repository (commit + push), then build and publish\",\n )\n .option(\n \"-o, --out-dir <dir>\",\n \"Widget artifact output directory\",\n DEFAULT_WIDGET_OUT_DIR,\n )\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--branch <name>\", \"Branch to push (default: main)\")\n .option(\n \"-m, --message <message>\",\n \"Commit message for the auto-commit (default: timestamped Publish)\",\n )\n .option(\n \"--no-commit\",\n \"Skip the auto-commit step (push existing commits only)\",\n )\n .option(\n \"--skip-publish\",\n \"Sync the git repository only; skip build + publish\",\n )\n .option(\"--dry-run\", \"Build and validate without uploading (publish step)\")\n .option(\"--skip-typecheck\", \"Skip package typecheck script when present\")\n .action((options: PushCommandOptions) =>\n runCliAction(async () => {\n const projectDir = process.cwd();\n const outDir = options.outDir ?? DEFAULT_WIDGET_OUT_DIR;\n const droplet = await resolvePublishDroplet(projectDir, options.droplet);\n const branch = options.branch ?? \"main\";\n\n console.log();\n console.log(chalk.blue.bold(\"Fluid Widget Push\"));\n console.log(chalk.gray(\"Droplet: \") + chalk.white(droplet));\n console.log();\n\n // --- Git sync phase -------------------------------------------------\n // Degrade to publish-only ONLY when git sync isn't in play: there is no\n // repository to sync with yet (404/409, see `isGitSyncUnavailable`) or\n // git isn't installed. Every other failure — diverged history, stash-pop\n // conflict, auth failure after a local commit, rejected push — aborts\n // BEFORE publish, so we never leave artifacts published while the source\n // repo is unsynced or the local checkout is in a broken git state.\n const client = createAuthenticatedWidgetPackageClient();\n const syncSpinner = ora(\"Syncing widget repository…\").start();\n try {\n const result = await syncWidgetGitRepo({\n cwd: projectDir,\n client,\n droplet,\n branch,\n ...(options.message ? { message: options.message } : {}),\n ...(options.commit === false ? { commit: false } : {}),\n });\n if (result.kind === \"diverged\") {\n syncSpinner.fail(\n `Your local history and origin/${branch} have diverged ` +\n `(${result.ahead} ahead, ${result.behind} behind).`,\n );\n throw new Error(\n \"Resolve in a terminal with `git pull --rebase`, fix any conflicts, \" +\n \"then re-run `fluid widget push`. Nothing was published.\",\n );\n }\n const parts: string[] = [];\n if (result.pulled > 0) {\n parts.push(\n `pulled ${result.pulled} commit${result.pulled === 1 ? \"\" : \"s\"}`,\n );\n }\n parts.push(result.committed ? \"committed + pushed\" : \"pushed\");\n syncSpinner.succeed(`Synced widget repository (${parts.join(\", \")})`);\n } catch (err) {\n if (isGitSyncUnavailable(err)) {\n syncSpinner.info(\n \"Widget git sync isn't available yet — publishing artifacts only.\",\n );\n } else if (err instanceof GitError && err.exitCode === 127) {\n syncSpinner.warn(err.message);\n console.log(\n chalk.yellow(\n \"Skipping git sync (git unavailable); publishing artifacts only.\",\n ),\n );\n } else {\n // Hard failure — stop before publishing so source and artifacts\n // don't drift out of sync.\n if (syncSpinner.isSpinning) syncSpinner.fail(\"Git sync failed\");\n throw err;\n }\n }\n\n if (options.skipPublish === true) {\n console.log();\n console.log(chalk.dim(\"Skipped build + publish (--skip-publish).\"));\n return;\n }\n\n // --- Publish phase ---------------------------------------------------\n const dryRun = options.dryRun === true;\n const publishSpinner = ora(\n dryRun\n ? \"Building and preparing dry-run upload payload…\"\n : \"Building and publishing widget artifacts…\",\n ).start();\n try {\n await publishWidgetPackage({\n projectDir,\n outDir,\n droplet,\n dryRun,\n skipTypecheck: options.skipTypecheck === true,\n });\n publishSpinner.succeed(\n dryRun\n ? \"Prepared dry-run upload payload\"\n : \"Published widget package\",\n );\n } catch (err) {\n publishSpinner.fail(\"Publish failed\");\n throw err;\n }\n\n console.log();\n console.log(chalk.green.bold(\"Done.\"));\n }),\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { loadWidgetConfig, validateDropletUuid } from \"../utils/config.js\";\nimport {\n fetchDropletWidgetStatus,\n formatStatusRows,\n} from \"../utils/droplet-api.js\";\nimport { runCliAction } from \"../utils/command.js\";\n\nexport interface StatusCommandOptions {\n readonly droplet?: string;\n readonly json?: boolean;\n}\n\nexport const statusCommand: Command = new Command(\"status\")\n .description(\"Show published widget package status for a Droplet\")\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--json\", \"Print raw status response as JSON\")\n .action((options: StatusCommandOptions) => {\n return runCliAction(async () => {\n const droplet = await resolveDroplet(process.cwd(), options.droplet);\n const versions = await fetchDropletWidgetStatus({\n client: createAuthenticatedWidgetPackageClient(),\n droplet,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n versions.map((version) => version.raw),\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(chalk.blue.bold(`Widget status for droplet ${droplet}`));\n console.log();\n console.log(formatStatusRows(versions));\n });\n });\n\nasync function resolveDroplet(\n projectDir: string,\n override: string | undefined,\n): Promise<string> {\n const droplet =\n override?.trim() || (await loadWidgetConfig(projectDir)).config.droplet;\n if (droplet?.trim()) {\n const trimmedDroplet = droplet.trim();\n const dropletError = validateDropletUuid(trimmedDroplet);\n if (dropletError) throw new Error(dropletError);\n return trimmedDroplet;\n }\n\n throw new Error(\n \"Missing droplet UUID. Pass --droplet <uuid> or set droplet in fluid.widget.config.ts.\",\n );\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport {\n formatValidationSuccess,\n validateDropletWidgetProject,\n} from \"../utils/source-package.js\";\nimport { runCliAction } from \"../utils/command.js\";\n\nexport interface ValidateWidgetOptions {\n readonly json?: boolean;\n}\n\nexport const validateCommand: Command = new Command(\"validate\")\n .description(\"Validate the current droplet widget package\")\n .option(\"--json\", \"Print machine-readable validation output\")\n .action((options: ValidateWidgetOptions) => {\n return runCliAction(async () => {\n const result = await validateDropletWidgetProject(process.cwd());\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n valid: true,\n config: result.sourceConfigPath,\n packageId: result.validated.packageId,\n version: result.validated.version,\n widgets: result.validated.widgets.map((widget) => ({\n name: widget.name,\n type: widget.type,\n })),\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(chalk.green(formatValidationSuccess(result)));\n });\n });\n","import { Command } from \"commander\";\nimport type { FluidPlugin, PluginContext } from \"@fluid-app/fluid-cli\";\nimport { buildCommand } from \"./commands/build.js\";\nimport { cloneCommand } from \"./commands/clone.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { devCommand } from \"./commands/dev.js\";\nimport { linkCommand } from \"./commands/link.js\";\nimport { logsCommand } from \"./commands/logs.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { pushCommand } from \"./commands/push.js\";\nimport { statusCommand } from \"./commands/status.js\";\nimport { validateCommand } from \"./commands/validate.js\";\n\nexport const widgetCommand: Command = new Command(\"widget\")\n .description(\n \"Create, preview, link, validate, build, publish, push, and clone standalone Fluid widgets\",\n )\n .addCommand(createCommand)\n .addCommand(cloneCommand)\n .addCommand(devCommand)\n .addCommand(linkCommand)\n .addCommand(validateCommand)\n .addCommand(buildCommand)\n .addCommand(publishCommand)\n .addCommand(pushCommand)\n .addCommand(statusCommand)\n .addCommand(logsCommand);\n\nconst plugin: FluidPlugin = {\n name: \"@fluid-app/fluid-cli-widget\",\n version: \"0.1.0\",\n register(ctx: PluginContext) {\n const existingWidgetCommand = findCommand(ctx.program, \"widget\");\n if (existingWidgetCommand) {\n addCommandIfMissing(existingWidgetCommand, createCommand);\n addCommandIfMissing(existingWidgetCommand, cloneCommand);\n addCommandIfMissing(existingWidgetCommand, devCommand);\n addCommandIfMissing(existingWidgetCommand, linkCommand);\n addCommandIfMissing(existingWidgetCommand, validateCommand);\n addCommandIfMissing(existingWidgetCommand, buildCommand);\n addCommandIfMissing(existingWidgetCommand, publishCommand);\n addCommandIfMissing(existingWidgetCommand, pushCommand);\n addCommandIfMissing(existingWidgetCommand, statusCommand);\n addCommandIfMissing(existingWidgetCommand, logsCommand);\n return;\n }\n\n ctx.program.addCommand(widgetCommand);\n },\n};\n\nexport default plugin;\n\nexport type {\n WidgetCommandOptions,\n WidgetCreateOptions,\n WidgetLinkOptions,\n WidgetTemplateVariables,\n} from \"./types.js\";\nexport { buildCommand, buildWidgetPackage } from \"./commands/build.js\";\nexport type {\n BuildWidgetOptions,\n BuildWidgetPackageOptions,\n BuildWidgetPackageResult,\n} from \"./commands/build.js\";\nexport { cloneCommand } from \"./commands/clone.js\";\nexport type { CloneCommandOptions } from \"./commands/clone.js\";\nexport {\n createCommand,\n createWidgetProject,\n type CreateWidgetProjectDependencies,\n} from \"./commands/create.js\";\nexport { pushCommand } from \"./commands/push.js\";\nexport type { PushCommandOptions } from \"./commands/push.js\";\nexport {\n DEFAULT_WIDGET_DEV_PORT,\n WIDGET_DEV_ROUTES,\n buildViteDevArgs,\n devCommand,\n printWidgetDevSummary,\n resolveWidgetDevProject,\n runViteDevServer,\n} from \"./commands/dev.js\";\nexport type {\n WidgetDevOptions,\n WidgetDevProjectSummary,\n} from \"./commands/dev.js\";\nexport { linkCommand } from \"./commands/link.js\";\nexport { logsCommand } from \"./commands/logs.js\";\nexport type { LogsCommandOptions } from \"./commands/logs.js\";\nexport { publishCommand, publishWidgetPackage } from \"./commands/publish.js\";\nexport type {\n PublishCommandOptions,\n PublishWidgetPackageOptions,\n PublishWidgetPackageResult,\n} from \"./commands/publish.js\";\nexport { statusCommand } from \"./commands/status.js\";\nexport type { StatusCommandOptions } from \"./commands/status.js\";\nexport { validateCommand } from \"./commands/validate.js\";\nexport type { ValidateWidgetOptions } from \"./commands/validate.js\";\nexport {\n WIDGET_CONFIG_FILE,\n formatWidgetConfig,\n loadWidgetConfig,\n mergeWidgetConfig,\n parseWidgetConfigSource,\n resolveWidgetConfigPath,\n validateDropletUuid,\n writeWidgetConfig,\n type FluidWidgetConfig,\n type LoadedWidgetConfig,\n} from \"./utils/config.js\";\nexport {\n DEFAULT_WIDGET_OUT_DIR,\n ROOT_WIDGET_CONFIG_FILE,\n WidgetValidationError,\n formatValidationSuccess,\n resolveWidgetSourceConfig,\n validateDropletWidgetProject,\n withRootWidgetConfigBridge,\n type WidgetValidationResult,\n} from \"./utils/source-package.js\";\nexport { formatValidationErrors } from \"./utils/validation.js\";\nexport type { WidgetCliValidationError } from \"./utils/validation.js\";\n\nfunction addCommandIfMissing(parent: Command, child: Command): void {\n if (findCommand(parent, child.name())) return;\n parent.addCommand(child);\n}\n\nfunction findCommand(parent: Command, name: string): Command | undefined {\n return parent.commands?.find((command) => command.name() === name);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["isNodeError","isRecord","readPackageJson","isRecord","buildWidgetPackageArtifacts","isRecord","isRecord","resolveDroplet","publishWidgetPackageArtifacts"],"sources":["../src/utils/config.ts","../src/utils/validation.ts","../src/utils/source-package.ts","../src/utils/command.ts","../src/utils/package-manager.ts","../src/utils/package-scripts.ts","../src/utils/template.ts","../src/commands/build.ts","../../../platform/api-client-core/src/api-error-shape.ts","../../../platform/api-client-core/src/fetch-client.ts","../../../platform/api-client-core/src/hey-api-error-policy.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/bodySerializer.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/params.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/serverSentEvents.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/pathSerializer.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/utils.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/core/auth.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/client/utils.gen.ts","../../../api-clients/hey-api-fetch-runtime/src/generated/client/client.gen.ts","../../../api-clients/fluidos/src/hey-api-client.ts","../src/utils/auth-client.ts","../src/lib/git.ts","../src/utils/git-credential.ts","../src/utils/widget-marker.ts","../src/commands/clone.ts","../src/utils/github-template.ts","../src/commands/create.ts","../src/commands/dev.ts","../src/utils/droplets.ts","../src/commands/link.ts","../src/utils/droplet-api.ts","../src/commands/logs.ts","../src/commands/publish.ts","../src/utils/me.ts","../src/lib/git-sync.ts","../src/commands/push.ts","../src/commands/status.ts","../src/commands/validate.ts","../src/index.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport const WIDGET_CONFIG_FILE = \"fluid.widget.config.ts\";\n\n/** Author-owned settings in `fluid.widget.config.ts`. */\nexport interface FluidWidgetConfig {\n /** Stable Fluid droplet identifier that owns published package versions. */\n readonly droplet?: string;\n}\n\nexport interface LoadedWidgetConfig {\n readonly path: string;\n readonly config: Partial<FluidWidgetConfig>;\n}\n\nexport class WidgetConfigParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WidgetConfigParseError\";\n }\n}\n\nexport function resolveWidgetConfigPath(projectDir: string): string {\n return path.join(projectDir, WIDGET_CONFIG_FILE);\n}\n\nexport async function loadWidgetConfig(\n projectDir: string,\n): Promise<LoadedWidgetConfig> {\n const configPath = resolveWidgetConfigPath(projectDir);\n\n let source: string;\n try {\n source = await readFile(configPath, \"utf-8\");\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") {\n return { path: configPath, config: {} };\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Unable to read ${WIDGET_CONFIG_FILE}: ${message}`);\n }\n\n return { path: configPath, config: parseWidgetConfigSource(source) };\n}\n\nexport async function writeWidgetConfig(\n projectDir: string,\n config: FluidWidgetConfig,\n): Promise<void> {\n await writeFile(\n resolveWidgetConfigPath(projectDir),\n formatWidgetConfig(config),\n \"utf-8\",\n );\n}\n\nexport function formatWidgetConfig(config: FluidWidgetConfig): string {\n const lines = [\n 'import type { FluidWidgetConfig } from \"@fluid-app/fluid-cli-widget\";',\n 'import { widgetPackage as sourceWidgetPackage } from \"./manifest\";',\n \"\",\n \"const config = {\",\n ];\n\n if (config.droplet) {\n lines.push(` droplet: ${JSON.stringify(config.droplet)},`);\n }\n\n lines.push(\n \"} satisfies FluidWidgetConfig;\",\n \"\",\n \"const widgetConfig: FluidWidgetConfig = config;\",\n \"const packageStableId = widgetConfig.droplet;\",\n \"\",\n \"export const widgetPackage = packageStableId\",\n \" ? {\",\n \" ...sourceWidgetPackage,\",\n \" packageStableId,\",\n \" packageId: `${sourceWidgetPackage.scope}.${packageStableId}` as const,\",\n \" }\",\n \" : sourceWidgetPackage;\",\n \"export const widgetPackages = [widgetPackage] as const;\",\n \"\",\n \"export default config;\",\n \"export const droplet = widgetConfig.droplet;\",\n \"\",\n );\n return lines.join(\"\\n\");\n}\n\nexport function parseWidgetConfigSource(\n source: string,\n): Partial<FluidWidgetConfig> {\n const objectSource = extractConfigObjectLiteral(source);\n const config = parseConfigObjectProperties(objectSource);\n\n return config;\n}\n\nexport function mergeWidgetConfig(\n current: Partial<FluidWidgetConfig>,\n updates: Partial<FluidWidgetConfig>,\n): FluidWidgetConfig {\n const droplet =\n normalizeOptionalString(updates.droplet) ??\n normalizeOptionalString(current.droplet);\n\n return droplet ? { droplet } : {};\n}\n\nexport function validateDropletUuid(dropletUuid: string): string | undefined {\n if (!dropletUuid) return \"Droplet UUID is required.\";\n if (dropletUuid.length > MAX_DROPLET_UUID_LENGTH) {\n return `Droplet UUID must be ${MAX_DROPLET_UUID_LENGTH} characters or fewer.`;\n }\n if (!URL_SAFE_IDENTIFIER_PATTERN.test(dropletUuid)) {\n return (\n \"Droplet UUID must be URL-safe text: letters, numbers, \" +\n \"'_', '~', and '-' only.\"\n );\n }\n return undefined;\n}\n\nfunction extractConfigObjectLiteral(source: string): string {\n const configStart = /\\bconst\\s+config\\s*=\\s*\\{/.exec(source);\n if (!configStart) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} must declare \\`const config = { ... } satisfies FluidWidgetConfig\\`.`,\n );\n }\n\n const openBraceIndex = source.indexOf(\"{\", configStart.index);\n const closeBraceIndex = findMatchingBrace(source, openBraceIndex);\n const suffix = stripComments(source.slice(closeBraceIndex + 1));\n if (!/^\\s*(?:as\\s+const\\s+)?satisfies\\s+FluidWidgetConfig\\s*;/.test(suffix)) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} config object must use \\`satisfies FluidWidgetConfig\\` or \\`as const satisfies FluidWidgetConfig\\`.`,\n );\n }\n\n return stripComments(source.slice(openBraceIndex + 1, closeBraceIndex));\n}\n\nfunction parseConfigObjectProperties(\n objectSource: string,\n): Partial<FluidWidgetConfig> {\n const config: { droplet?: string } = {};\n\n for (const member of splitTopLevelMembers(objectSource)) {\n const trimmedMember = member.trim();\n if (!trimmedMember) continue;\n\n const propertyMatch = /^(droplet)\\s*:\\s*([\\s\\S]+)$/.exec(trimmedMember);\n if (!propertyMatch) {\n const propertyName = /^([A-Za-z_$][\\w$]*)\\s*:/.exec(trimmedMember)?.[1];\n throw new WidgetConfigParseError(\n propertyName\n ? `${WIDGET_CONFIG_FILE} does not support config field ${propertyName}. Supported field is droplet.`\n : `${WIDGET_CONFIG_FILE} config fields must use optional droplet: \"...\" string literal.`,\n );\n }\n\n const propertyName = propertyMatch[1];\n if (propertyName !== \"droplet\") {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} config field could not be parsed.`,\n );\n }\n const valueSource = propertyMatch[2]?.trim() ?? \"\";\n const value = parseStringLiteralValue(valueSource, propertyName);\n if (!value.trim()) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} field ${propertyName} must be a non-empty string literal.`,\n );\n }\n\n if (config.droplet !== undefined) {\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} field droplet must only be declared once.`,\n );\n }\n config.droplet = value;\n }\n\n return config;\n}\n\nfunction parseStringLiteralValue(\n valueSource: string,\n propertyName: string,\n): string {\n if (valueSource.startsWith('\"') && valueSource.endsWith('\"')) {\n try {\n const parsed = JSON.parse(valueSource) as unknown;\n if (typeof parsed === \"string\") return parsed;\n } catch {\n // Fall through to the actionable error below.\n }\n }\n\n if (valueSource.startsWith(\"'\") && valueSource.endsWith(\"'\")) {\n return parseSingleQuotedStringLiteral(valueSource);\n }\n\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} field ${propertyName} must be a string literal (for example ${propertyName}: \"value\").`,\n );\n}\n\nfunction parseSingleQuotedStringLiteral(valueSource: string): string {\n let value = \"\";\n\n for (let index = 1; index < valueSource.length - 1; index += 1) {\n const char = valueSource[index];\n if (char !== \"\\\\\") {\n value += char;\n continue;\n }\n\n index += 1;\n const escaped = valueSource[index];\n switch (escaped) {\n case \"\\\\\":\n case \"'\":\n case '\"':\n value += escaped;\n break;\n case \"n\":\n value += \"\\n\";\n break;\n case \"r\":\n value += \"\\r\";\n break;\n case \"t\":\n value += \"\\t\";\n break;\n case \"b\":\n value += \"\\b\";\n break;\n case \"f\":\n value += \"\\f\";\n break;\n case \"v\":\n value += \"\\v\";\n break;\n default:\n value += escaped ?? \"\";\n break;\n }\n }\n\n return value;\n}\n\nfunction stripComments(source: string): string {\n let result = \"\";\n let stringQuote: '\"' | \"'\" | \"`\" | undefined;\n let escaped = false;\n let lineComment = false;\n let blockComment = false;\n\n for (let index = 0; index < source.length; index += 1) {\n const char = source[index];\n const nextChar = source[index + 1];\n\n if (lineComment) {\n if (char === \"\\n\" || char === \"\\r\") {\n lineComment = false;\n result += char;\n } else {\n result += \" \";\n }\n continue;\n }\n\n if (blockComment) {\n if (char === \"*\" && nextChar === \"/\") {\n blockComment = false;\n result += \" \";\n index += 1;\n } else if (char === \"\\n\" || char === \"\\r\") {\n result += char;\n } else {\n result += \" \";\n }\n continue;\n }\n\n if (stringQuote) {\n result += char;\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === stringQuote) {\n stringQuote = undefined;\n }\n continue;\n }\n\n if (char === \"/\" && nextChar === \"/\") {\n lineComment = true;\n result += \" \";\n index += 1;\n continue;\n }\n\n if (char === \"/\" && nextChar === \"*\") {\n blockComment = true;\n result += \" \";\n index += 1;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n stringQuote = char;\n }\n result += char;\n }\n\n return result;\n}\n\nfunction splitTopLevelMembers(objectSource: string): string[] {\n const members: string[] = [];\n let memberStart = 0;\n let stringQuote: '\"' | \"'\" | \"`\" | undefined;\n let escaped = false;\n let nestedDepth = 0;\n\n for (let index = 0; index < objectSource.length; index += 1) {\n const char = objectSource[index];\n\n if (stringQuote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === stringQuote) {\n stringQuote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n stringQuote = char;\n continue;\n }\n\n if (char === \"{\" || char === \"[\" || char === \"(\") {\n nestedDepth += 1;\n continue;\n }\n if (char === \"}\" || char === \"]\" || char === \")\") {\n nestedDepth -= 1;\n continue;\n }\n\n if (char === \",\" && nestedDepth === 0) {\n members.push(objectSource.slice(memberStart, index));\n memberStart = index + 1;\n }\n }\n\n members.push(objectSource.slice(memberStart));\n return members;\n}\n\nfunction findMatchingBrace(source: string, openBraceIndex: number): number {\n let depth = 0;\n let stringQuote: '\"' | \"'\" | \"`\" | undefined;\n let escaped = false;\n let lineComment = false;\n let blockComment = false;\n\n for (let index = openBraceIndex; index < source.length; index += 1) {\n const char = source[index];\n const nextChar = source[index + 1];\n\n if (lineComment) {\n if (char === \"\\n\" || char === \"\\r\") lineComment = false;\n continue;\n }\n\n if (blockComment) {\n if (char === \"*\" && nextChar === \"/\") {\n blockComment = false;\n index += 1;\n }\n continue;\n }\n\n if (stringQuote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === stringQuote) {\n stringQuote = undefined;\n }\n continue;\n }\n\n if (char === \"/\" && nextChar === \"/\") {\n lineComment = true;\n index += 1;\n continue;\n }\n\n if (char === \"/\" && nextChar === \"*\") {\n blockComment = true;\n index += 1;\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n stringQuote = char;\n continue;\n }\n\n if (char === \"{\") depth += 1;\n if (char === \"}\") {\n depth -= 1;\n if (depth === 0) return index;\n }\n }\n\n throw new WidgetConfigParseError(\n `${WIDGET_CONFIG_FILE} config object is missing a closing brace.`,\n );\n}\n\nfunction normalizeOptionalString(\n value: string | undefined,\n): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\ninterface NodeError extends Error {\n readonly code?: string;\n}\n\nfunction isNodeError(error: unknown): error is NodeError {\n return error instanceof Error && \"code\" in error;\n}\n\nconst MAX_DROPLET_UUID_LENGTH = 256;\nconst URL_SAFE_SEGMENT_SOURCE = \"[A-Za-z0-9][A-Za-z0-9_~-]*\";\nconst URL_SAFE_IDENTIFIER_PATTERN = new RegExp(`^${URL_SAFE_SEGMENT_SOURCE}$`);\n","export interface WidgetCliValidationError {\n readonly path?: string;\n readonly message: string;\n}\n\nexport function formatValidationErrors(\n errors: readonly WidgetCliValidationError[],\n): string {\n if (errors.length === 0) return \"Validation failed.\";\n\n return [\n \"Validation failed:\",\n ...errors.map((error) => {\n const location = error.path ? `${error.path}: ` : \"\";\n return ` - ${location}${error.message}`;\n }),\n ].join(\"\\n\");\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, rm, rmdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n loadAndValidateWidgetPackage,\n WidgetToolingError,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageValidationError,\n} from \"@fluid-app/fluid-cli-widget-tooling\";\nimport {\n WIDGET_CONFIG_FILE,\n loadWidgetConfig,\n validateDropletUuid,\n} from \"./config.js\";\nimport { formatValidationErrors } from \"./validation.js\";\n\nexport const DEFAULT_WIDGET_OUT_DIR = \".fluid/widget-dist\";\nexport const ROOT_WIDGET_CONFIG_FILE: string = WIDGET_CONFIG_FILE;\n\nconst SOURCE_CONFIG_CANDIDATES = [\n \"src/widgets.config.ts\",\n \"src/portal.config.ts\",\n \"portal.config.ts\",\n] as const;\n\nexport interface WidgetValidationResult {\n readonly projectDir: string;\n readonly sourceConfigPath?: string;\n readonly validated: ValidatedWidgetPackageBuild;\n}\n\nexport class WidgetValidationError extends Error {\n public readonly errors: readonly WidgetPackageValidationError[];\n\n constructor(errors: readonly WidgetPackageValidationError[]) {\n super(formatValidationErrors(errors));\n this.name = \"WidgetValidationError\";\n this.errors = errors;\n }\n}\n\nexport async function validateDropletWidgetProject(\n projectDir: string,\n packageKeyOverride?: string,\n): Promise<WidgetValidationResult> {\n const resolvedProjectDir = path.resolve(projectDir);\n const sourceConfig = resolveWidgetSourceConfig(resolvedProjectDir);\n if (!sourceConfig) {\n throw new WidgetValidationError([\n {\n code: \"NO_SOURCE_PACKAGE\",\n path: ROOT_WIDGET_CONFIG_FILE,\n message:\n `No widget package config found. Create ${ROOT_WIDGET_CONFIG_FILE} ` +\n \"or src/widgets.config.ts that exports defineWidgetPackage(...).\",\n },\n ]);\n }\n\n const configErrors = await validateRootWidgetConfig(\n resolvedProjectDir,\n packageKeyOverride,\n );\n if (configErrors.length > 0) {\n throw new WidgetValidationError(configErrors);\n }\n\n let validated: ValidatedWidgetPackageBuild;\n try {\n const loaded = await withRootWidgetConfigBridge(\n resolvedProjectDir,\n () =>\n loadAndValidateWidgetPackage({\n projectDir: resolvedProjectDir,\n owner: \"droplet\",\n }),\n packageKeyOverride,\n );\n validated = loaded.validated;\n } catch (error) {\n if (error instanceof WidgetToolingError) {\n if (error.diagnostics) {\n throw new WidgetValidationError(error.diagnostics);\n }\n throw new WidgetValidationError([\n {\n code: \"INVALID_SOURCE_PACKAGE\",\n path: sourceConfig.relativePath,\n message: error.details\n ? `${error.message}\\n${error.details}`\n : error.message,\n },\n ]);\n }\n throw error;\n }\n\n return {\n projectDir: resolvedProjectDir,\n sourceConfigPath: sourceConfig.relativePath,\n validated,\n };\n}\n\nexport async function withRootWidgetConfigBridge<T>(\n projectDir: string,\n callback: () => Promise<T>,\n packageKeyOverride?: string,\n): Promise<T> {\n const rootConfigPath = path.join(projectDir, ROOT_WIDGET_CONFIG_FILE);\n if (!existsSync(rootConfigPath) || resolvePortalSourceConfig(projectDir)) {\n return callback();\n }\n\n const packageKey =\n packageKeyOverride?.trim() ||\n (await loadWidgetConfig(projectDir)).config.droplet;\n if (!packageKey) {\n throw new Error(\n \"fluid.widget.config.ts must set droplet before validating, building, or publishing.\",\n );\n }\n\n const srcDir = path.join(projectDir, \"src\");\n const bridgePath = path.join(srcDir, \"widgets.config.ts\");\n const srcDirExisted = existsSync(srcDir);\n await mkdir(srcDir, { recursive: true });\n try {\n await writeFile(\n bridgePath,\n createRootWidgetConfigBridgeSource(packageKey),\n {\n encoding: \"utf-8\",\n flag: \"wx\",\n },\n );\n } catch (err) {\n if (isNodeError(err) && err.code === \"EEXIST\") {\n throw new Error(\n `${path.relative(projectDir, bridgePath)} already exists. ` +\n \"Remove this stale Fluid widget CLI bridge file and try again.\",\n );\n }\n throw err;\n }\n\n try {\n return await callback();\n } finally {\n await rm(bridgePath, { force: true }).catch(() => {});\n if (!srcDirExisted) await rmdir(srcDir).catch(() => {});\n }\n}\n\nfunction createRootWidgetConfigBridgeSource(packageKey: string): string {\n return `import { widgetPackage as sourceWidgetPackage } from \"../manifest\";\n\nconst packageKey = ${JSON.stringify(packageKey)};\nconst packageId = sourceWidgetPackage.scope + \".\" + packageKey;\n\nexport const widgetPackage = {\n ...sourceWidgetPackage,\n packageStableId: packageKey,\n packageId,\n};\n\nexport const widgetPackages = [widgetPackage] as const;\nexport default widgetPackage;\n`;\n}\n\nexport function resolveWidgetSourceConfig(\n projectDir: string,\n): { readonly path: string; readonly relativePath: string } | undefined {\n const rootConfig = path.join(projectDir, ROOT_WIDGET_CONFIG_FILE);\n if (existsSync(rootConfig)) {\n return { path: rootConfig, relativePath: ROOT_WIDGET_CONFIG_FILE };\n }\n\n return resolvePortalSourceConfig(projectDir);\n}\n\nexport function formatValidationSuccess(\n result: WidgetValidationResult,\n): string {\n return [\n \"Widget package is valid.\",\n `Config: ${result.sourceConfigPath ?? \"unknown\"}`,\n `Package: ${result.validated.packageId}`,\n `Version: ${result.validated.version}`,\n `Widgets: ${result.validated.widgets.length}`,\n ].join(\"\\n\");\n}\n\nasync function validateRootWidgetConfig(\n projectDir: string,\n packageKeyOverride?: string,\n): Promise<WidgetPackageValidationError[]> {\n const configPath = path.join(projectDir, ROOT_WIDGET_CONFIG_FILE);\n if (!existsSync(configPath)) return [];\n\n try {\n const loaded = await loadWidgetConfig(projectDir);\n const droplet = packageKeyOverride ?? loaded.config.droplet ?? \"\";\n const packageKeyError = validateDropletUuid(droplet);\n if (!packageKeyError) return [];\n\n return [\n {\n code: \"INVALID_PACKAGE_KEY\",\n path: ROOT_WIDGET_CONFIG_FILE,\n message: packageKeyError,\n },\n ];\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return [\n {\n code: \"INVALID_SOURCE_PACKAGE\",\n path: ROOT_WIDGET_CONFIG_FILE,\n message,\n },\n ];\n }\n}\n\nfunction resolvePortalSourceConfig(\n projectDir: string,\n): { readonly path: string; readonly relativePath: string } | undefined {\n for (const relativePath of SOURCE_CONFIG_CANDIDATES) {\n const candidate = path.join(projectDir, relativePath);\n if (existsSync(candidate)) return { path: candidate, relativePath };\n }\n\n return undefined;\n}\n\ninterface NodeError extends Error {\n readonly code?: string;\n}\n\nfunction isNodeError(error: unknown): error is NodeError {\n return error instanceof Error && \"code\" in error;\n}\n","import chalk from \"chalk\";\n\nexport async function runCliAction(action: () => Promise<void>): Promise<void> {\n try {\n await action();\n } catch (err) {\n console.error(chalk.red(\"Error:\") + \" \" + formatUnknownError(err));\n process.exit(1);\n }\n}\n\nexport function formatUnknownError(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport function getRunCommand(\n script: string,\n cwd: string = process.cwd(),\n): string {\n return `${detectPackageManager(cwd)} run ${script}`;\n}\n\nexport function getInstallCommand(cwd: string = process.cwd()): string {\n return `${detectPackageManager(cwd)} install`;\n}\n\nexport async function installDependencies(cwd: string): Promise<void> {\n const packageManager = detectPackageManager(cwd);\n await runPackageManager(packageManager, [\"install\"], cwd);\n}\n\nexport function detectPackageManager(cwd: string): PackageManager {\n if (existsSync(path.join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(path.join(cwd, \"yarn.lock\"))) return \"yarn\";\n if (existsSync(path.join(cwd, \"bun.lockb\"))) return \"bun\";\n if (existsSync(path.join(cwd, \"package-lock.json\"))) return \"npm\";\n\n const invokingPackageManager = readInvokingPackageManager();\n if (invokingPackageManager) return invokingPackageManager;\n\n const declaredPackageManager = readDeclaredPackageManager(cwd);\n if (declaredPackageManager && isCommandAvailable(declaredPackageManager)) {\n return declaredPackageManager;\n }\n\n return findAvailablePackageManager() ?? \"pnpm\";\n}\n\nfunction runPackageManager(\n command: PackageManager,\n args: readonly string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, [...args], {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n\n child.once(\"error\", (error: Error) => {\n reject(error);\n });\n\n child.once(\"exit\", (code: number | null) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(\n new Error(\n `${command} ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n });\n}\n\nfunction readInvokingPackageManager(): PackageManager | undefined {\n const userAgent = process.env[\"npm_config_user_agent\"];\n if (!userAgent) return undefined;\n\n const name = userAgent.split(\"/\")[0];\n if (isPackageManager(name)) return name;\n return undefined;\n}\n\nfunction readDeclaredPackageManager(cwd: string): PackageManager | undefined {\n const packageJsonPath = path.join(cwd, \"package.json\");\n if (!existsSync(packageJsonPath)) return undefined;\n\n try {\n const packageJson = JSON.parse(\n readFileSync(packageJsonPath, \"utf-8\"),\n ) as unknown;\n if (!isRecord(packageJson)) return undefined;\n\n const packageManager = packageJson[\"packageManager\"];\n if (typeof packageManager !== \"string\") return undefined;\n\n const name = packageManager.split(\"@\")[0];\n if (isPackageManager(name)) return name;\n } catch {\n // Malformed package.json is reported by command paths that need to parse it.\n }\n\n return undefined;\n}\n\nfunction findAvailablePackageManager(): PackageManager | undefined {\n for (const packageManager of [\"pnpm\", \"yarn\", \"bun\", \"npm\"] as const) {\n if (isCommandAvailable(packageManager)) return packageManager;\n }\n return undefined;\n}\n\nfunction isCommandAvailable(command: PackageManager): boolean {\n const result = spawnSync(command, [\"--version\"], {\n shell: process.platform === \"win32\",\n stdio: \"ignore\",\n });\n return result.status === 0;\n}\n\nfunction isPackageManager(value: string | undefined): value is PackageManager {\n return (\n value === \"pnpm\" || value === \"yarn\" || value === \"bun\" || value === \"npm\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { detectPackageManager } from \"./package-manager.js\";\n\nexport interface PackageScriptRunResult {\n readonly ran: boolean;\n readonly command?: string;\n}\n\nexport async function runPackageScriptIfAvailable(options: {\n readonly projectDir: string;\n readonly scriptName: string;\n}): Promise<PackageScriptRunResult> {\n const packageJsonPath = path.join(options.projectDir, \"package.json\");\n if (!existsSync(packageJsonPath)) return { ran: false };\n\n const packageJson = await readPackageJson(packageJsonPath);\n if (!hasPackageScript(packageJson, options.scriptName)) return { ran: false };\n\n const packageManager = detectPackageManager(options.projectDir);\n const args = [\"run\", options.scriptName];\n await runCommand(packageManager, args, options.projectDir);\n\n return {\n ran: true,\n command: `${packageManager} ${args.join(\" \")}`,\n };\n}\n\nfunction runCommand(\n command: string,\n args: readonly string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n stdio: \"inherit\",\n env: process.env,\n shell: process.platform === \"win32\",\n });\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(\n new Error(\n signal\n ? `${command} ${args.join(\" \")} exited with signal ${signal}.`\n : `${command} ${args.join(\" \")} exited with code ${code ?? \"unknown\"}.`,\n ),\n );\n });\n });\n}\n\nasync function readPackageJson(packageJsonPath: string): Promise<unknown> {\n const source = await readFile(packageJsonPath, \"utf-8\");\n try {\n return JSON.parse(source) as unknown;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Unable to parse package.json: ${message}`);\n }\n}\n\nfunction hasPackageScript(value: unknown, scriptName: string): boolean {\n if (!isRecord(value)) return false;\n const scripts = value[\"scripts\"];\n if (!isRecord(scripts)) return false;\n return typeof scripts[scriptName] === \"string\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { WidgetTemplateVariables } from \"../types.js\";\n\ndeclare const __FLUID_PORTAL_SDK_VERSION__: string | undefined;\ndeclare const __FLUID_CLI_CORE_VERSION__: string | undefined;\ndeclare const __FLUID_CLI_WIDGET_VERSION__: string | undefined;\n\nconst EMBEDDED_PORTAL_SDK_VERSION =\n typeof __FLUID_PORTAL_SDK_VERSION__ === \"string\"\n ? __FLUID_PORTAL_SDK_VERSION__\n : undefined;\nconst EMBEDDED_CLI_CORE_VERSION =\n typeof __FLUID_CLI_CORE_VERSION__ === \"string\"\n ? __FLUID_CLI_CORE_VERSION__\n : undefined;\nconst EMBEDDED_CLI_WIDGET_VERSION =\n typeof __FLUID_CLI_WIDGET_VERSION__ === \"string\"\n ? __FLUID_CLI_WIDGET_VERSION__\n : undefined;\n\nexport function getDefaultTemplatePath(): string {\n return path.join(findPackageRoot(), \"templates\", \"default\");\n}\n\nexport async function directoryExists(filePath: string): Promise<boolean> {\n try {\n const stats = await stat(filePath);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function copyWidgetTemplate(\n templatePath: string,\n targetPath: string,\n variables: WidgetTemplateVariables,\n): Promise<void> {\n const files = await getFiles(templatePath);\n\n for (const file of files) {\n const sourcePath = path.join(templatePath, file);\n const isTemplate = file.endsWith(\".template\");\n const outputFiles = getOutputFilenames(file);\n\n const content = await readFile(sourcePath, \"utf-8\");\n const processed = isTemplate ? renderTemplate(content, variables) : content;\n\n await writeOutputFiles(targetPath, outputFiles, processed);\n }\n\n for (const skillFile of await getSharedTemplateSkillFiles()) {\n await writeOutputFiles(\n targetPath,\n getOutputFilenames(skillFile.relativePath),\n skillFile.content,\n );\n }\n}\n\nexport async function getPortalSdkVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion(\n [\"portal\", \"sdk\"],\n EMBEDDED_PORTAL_SDK_VERSION,\n options,\n );\n}\n\nexport async function getPortalCoreVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion([\"portal\", \"core\"], undefined, options);\n}\n\nexport async function getCliVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion(\n [\"cli\", \"core\"],\n EMBEDDED_CLI_CORE_VERSION,\n options,\n );\n}\n\nexport async function getWidgetCliVersion(\n options: { readonly local?: boolean } = {},\n): Promise<string> {\n return getWorkspacePackageVersion(\n [\"cli\", \"widget\"],\n EMBEDDED_CLI_WIDGET_VERSION,\n options,\n );\n}\n\nasync function getWorkspacePackageVersion(\n packagePathSegments: readonly string[],\n embeddedVersion: string | undefined,\n options: { readonly local?: boolean },\n): Promise<string> {\n try {\n const packageRoot = findPackageRoot();\n const packagesRoot = path.join(packageRoot, \"..\", \"..\");\n const targetPackageRoot = path.join(packagesRoot, ...packagePathSegments);\n\n if (options.local) {\n return getLocalPackageLinkVersion(targetPackageRoot);\n }\n\n if (embeddedVersion) return embeddedVersion;\n\n const packageJsonPath = path.join(targetPackageRoot, \"package.json\");\n const content = await readFile(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content) as { version?: string };\n if (typeof pkg.version !== \"string\") {\n throw new Error(`Missing version in ${packageJsonPath}`);\n }\n return pkg.version;\n } catch (error) {\n if (embeddedVersion) return embeddedVersion;\n throw new Error(\n `Could not resolve the exact template package version for ${packagePathSegments.join(\"/\")}`,\n { cause: error },\n );\n }\n}\n\n/**\n * Builds an absolute pnpm link: specifier for local scaffolds.\n *\n * link: keeps the dependency pointed at the workspace package source instead of\n * packing only package.json \"files\" entries like file: does. That lets Vite's\n * development export resolve the SDK source and its workspace dependencies. An\n * absolute path also remains valid when the operating system canonicalizes the\n * generated project path, such as macOS resolving /tmp to /private/tmp.\n */\nfunction getLocalPackageLinkVersion(packagePath: string): string {\n const linkPath = path.resolve(packagePath).replace(/\\\\/g, \"/\");\n return `link:${linkPath}`;\n}\n\nasync function getFiles(dir: string, baseDir = dir): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await getFiles(fullPath, baseDir)));\n } else {\n files.push(path.relative(baseDir, fullPath));\n }\n }\n\n return files;\n}\n\ninterface TemplateSkillFile {\n readonly relativePath: string;\n readonly content: string;\n}\n\nasync function getSharedTemplateSkillFiles(): Promise<TemplateSkillFile[]> {\n const packageRoot = findFluidCliPackageRoot();\n const skillsRoot = path.join(packageRoot, \"template-skills\");\n const files = await getFiles(skillsRoot);\n\n return Promise.all(\n files.map(async (file) => ({\n relativePath: path.join(\"skills\", file),\n content: await readFile(path.join(skillsRoot, file), \"utf-8\"),\n })),\n );\n}\n\nfunction findFluidCliPackageRoot(): string {\n const workspacePackageRoot = path.join(findPackageRoot(), \"..\", \"core\");\n if (existsSync(path.join(workspacePackageRoot, \"template-skills\"))) {\n return workspacePackageRoot;\n }\n\n let dir = path.dirname(\n fileURLToPath(import.meta.resolve(\"@fluid-app/fluid-cli\")),\n );\n while (!existsSync(path.join(dir, \"package.json\"))) {\n const parent = path.dirname(dir);\n if (parent === dir)\n throw new Error(\"Could not find Fluid CLI package root\");\n dir = parent;\n }\n return dir;\n}\n\nfunction renderTemplate(\n content: string,\n variables: WidgetTemplateVariables,\n): string {\n const withConditionals = content.replace(\n /{{\\s*#if\\s+([a-zA-Z0-9_]+)\\s*}}([\\s\\S]*?){{\\s*\\/if\\s*}}/g,\n (match, key, block) => {\n if (!isTemplateVariableKey(key)) return match;\n return variables[key] ? String(block) : \"\";\n },\n );\n\n return withConditionals.replace(\n /{{\\s*([a-zA-Z0-9_]+)\\s*}}/g,\n (match, key) => {\n if (isTemplateVariableKey(key)) return variables[key] ?? \"\";\n return match;\n },\n );\n}\n\nfunction isTemplateVariableKey(\n key: string,\n): key is keyof WidgetTemplateVariables {\n return [\n \"projectName\",\n \"widgetScope\",\n \"widgetPackageVersion\",\n \"sdkVersion\",\n \"localCoreVersion\",\n \"fluidCliVersion\",\n \"widgetCliVersion\",\n \"droplet\",\n ].includes(key);\n}\n\nasync function writeOutputFiles(\n targetPath: string,\n outputFiles: readonly string[],\n content: string,\n): Promise<void> {\n for (const outputFile of outputFiles) {\n const destinationPath = path.join(targetPath, outputFile);\n await mkdir(path.dirname(destinationPath), { recursive: true });\n await writeFile(destinationPath, content, \"utf-8\");\n }\n}\n\nfunction getOutputFilenames(filename: string): string[] {\n const outputFilename = getOutputFilename(filename);\n const normalized = outputFilename.replace(/\\\\/g, \"/\");\n\n if (normalized === \"AGENTS.md\") return [\"AGENTS.md\", \"CLAUDE.md\"];\n\n if (normalized.startsWith(\"skills/\")) {\n return [\n path.join(\".agents\", outputFilename),\n path.join(\".claude\", outputFilename),\n ];\n }\n\n return [outputFilename];\n}\n\nfunction getOutputFilename(filename: string): string {\n return filename.endsWith(\".template\")\n ? filename.slice(0, -\".template\".length)\n : filename;\n}\n\nfunction findPackageRoot(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n while (!existsSync(path.join(dir, \"package.json\"))) {\n const parent = path.dirname(dir);\n if (parent === dir)\n throw new Error(\"Could not find widget CLI package root\");\n dir = parent;\n }\n return dir;\n}\n","import { Command } from \"commander\";\nimport {\n buildWidgetPackage as buildWidgetPackageArtifacts,\n WidgetToolingError,\n type WidgetPackageBuildResult,\n} from \"@fluid-app/fluid-cli-widget-tooling\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n DEFAULT_WIDGET_OUT_DIR,\n validateDropletWidgetProject,\n withRootWidgetConfigBridge,\n} from \"../utils/source-package.js\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { runPackageScriptIfAvailable } from \"../utils/package-scripts.js\";\nimport { getWidgetCliVersion } from \"../utils/template.js\";\n\nexport interface BuildWidgetOptions {\n readonly outDir?: string;\n readonly skipTypecheck?: boolean;\n}\n\nexport interface BuildWidgetPackageOptions {\n readonly projectDir: string;\n readonly outDir: string;\n readonly skipTypecheck?: boolean;\n}\n\nexport interface BuildWidgetPackageResult {\n readonly outDir: string;\n readonly packageId: string;\n readonly version: string;\n}\n\nexport async function buildWidgetPackage(\n options: BuildWidgetPackageOptions,\n): Promise<BuildWidgetPackageResult> {\n await validateDropletWidgetProject(options.projectDir);\n\n if (options.skipTypecheck !== true) {\n await runPackageScriptIfAvailable({\n projectDir: options.projectDir,\n scriptName: \"typecheck\",\n });\n }\n\n let buildResult: WidgetPackageBuildResult;\n try {\n const cliVersion = await getWidgetCliVersion();\n buildResult = await withRootWidgetConfigBridge(options.projectDir, () =>\n buildWidgetPackageArtifacts({\n projectDir: options.projectDir,\n outDir: options.outDir,\n owner: \"droplet\",\n cliVersion,\n }),\n );\n } catch (error) {\n if (error instanceof WidgetToolingError && error.details) {\n throw new Error(`${error.message}\\n${error.details}`, { cause: error });\n }\n throw error;\n }\n\n return {\n outDir: buildResult.publishDir,\n packageId: buildResult.packageId,\n version: buildResult.version,\n };\n}\n\nexport const buildCommand: Command = new Command(\"build\")\n .description(\"Validate and build the current droplet widget package\")\n .option(\n \"-o, --out-dir <dir>\",\n \"Widget artifact output directory\",\n DEFAULT_WIDGET_OUT_DIR,\n )\n .option(\"--skip-typecheck\", \"Skip package typecheck script when present\")\n .action((options: BuildWidgetOptions) => {\n return runCliAction(async () => {\n const outDir = options.outDir ?? DEFAULT_WIDGET_OUT_DIR;\n console.log(chalk.blue.bold(\"Building Fluid widget package\"));\n console.log();\n\n const spinner = ora(\n \"Validating and building widget artifacts...\",\n ).start();\n const result = await buildWidgetPackage({\n projectDir: process.cwd(),\n outDir,\n skipTypecheck: options.skipTypecheck,\n });\n spinner.succeed(\"Built widget runtime artifacts\");\n\n console.log();\n console.log(chalk.gray(\"Package: \") + chalk.white(result.packageId));\n console.log(chalk.gray(\"Version: \") + chalk.white(result.version));\n console.log(chalk.gray(\"Output: \") + chalk.cyan(outDir));\n });\n });\n","/**\n * The shape contract for `ApiError.body` and `ApiError.data`.\n *\n * One decision, in one place: `body` is the response envelope exactly as the\n * server sent it, `data` is the unwrapped field-error bag. Rationale and the\n * alternatives considered live in `docs/api-error-data-contract.md`.\n */\n\n/**\n * The parsed JSON error response body, exactly as the server sent it.\n *\n * This is the envelope: `errors`, `error_message`, `error`, `status`, `meta`\n * and `request_id` all live here. `null` when the response carried no JSON\n * object — HTML, an empty body, a JSON primitive, or unparseable text.\n */\nexport type ApiErrorBody = Record<string, unknown> | null;\n\n/**\n * The field-level error bag: the envelope's `errors` value when the body has\n * one, otherwise the body itself.\n *\n * `errors` is declared `never` because unwrapping already consumed it — read\n * the envelope from `ApiError.body`, not from here. That makes the historical\n * mistake (`error.data.errors.some_field`, which silently resolved to\n * `undefined`) a typecheck failure instead of a degraded error message.\n */\nexport type ApiErrorFieldErrors = Record<string, unknown> & {\n errors?: never;\n};\n\n/**\n * Every value `ApiError.data` can hold. Fluid endpoints return an object bag,\n * but `errors` is occasionally an array or a string, and non-JSON responses\n * carry no data at all.\n */\nexport type ApiErrorData =\n | ApiErrorFieldErrors\n | readonly unknown[]\n | string\n | number\n | boolean\n | null;\n\n/**\n * Narrows a parsed JSON error payload to the envelope contract. Arrays and\n * primitives are not envelopes, so they resolve to `null` — their content is\n * still reachable through `ApiError.data`.\n */\nexport function toApiErrorBody(value: unknown): ApiErrorBody {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n\n/**\n * The single unwrap rule, shared by every producer of `ApiError`.\n *\n * `??` rather than `||` so an explicitly empty `errors` (`\"\"`, `0`, `false`)\n * is preserved instead of silently falling back to the whole envelope.\n */\nexport function toApiErrorData(body: ApiErrorBody): ApiErrorData {\n if (!body) {\n return null;\n }\n\n return (body.errors ?? body) as ApiErrorData;\n}\n","/**\n * Minimal, framework-agnostic fetch client for Fluid APIs\n * Compatible with fluid-admin patterns but usable standalone\n */\n\nimport type { ApiErrorBody, ApiErrorData } from \"./api-error-shape\";\nimport { toApiErrorBody, toApiErrorData } from \"./api-error-shape\";\n\nexport interface FetchClientConfig {\n /**\n * Base URL for all requests (e.g., \"https://api.fluid.app/api\")\n */\n baseUrl: string;\n\n /**\n * Optional function to get auth token\n * Return null/undefined if no token available\n */\n getAuthToken?: () => string | null | Promise<string | null>;\n\n /**\n * Optional callback when 401 auth error occurs\n */\n onAuthError?: () => void;\n\n /**\n * Default headers to include in all requests\n * Example: { \"x-fluid-client\": \"admin\" }\n */\n defaultHeaders?: Record<string, string>;\n\n /**\n * Credentials mode for fetch requests.\n * Set to `\"include\"` for cookie-based (same-origin BFF) authentication.\n * @default undefined (browser default: \"same-origin\")\n */\n credentials?: RequestCredentials;\n\n /**\n * Request cache mode for fetch requests.\n * @default undefined (browser default)\n */\n cache?: RequestCache;\n\n /**\n * Retry configuration for thrown network errors from fetch.\n * Does not retry HTTP error responses or aborted requests.\n * @default undefined (no retries)\n */\n networkRetry?: {\n maxRetries?: number;\n baseDelayMs?: number;\n };\n\n /**\n * Throw ApiError when a successful response declares JSON but cannot be parsed.\n * Defaults to false to preserve the legacy generated-client behavior.\n * @default false\n */\n throwOnInvalidJson?: boolean;\n}\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n headers?: Record<string, string>;\n params?: Record<string, unknown>;\n body?: unknown;\n signal?: AbortSignal;\n priority?: RequestInit[\"priority\"];\n}\n\n/**\n * API Error class compatible with fluid-admin's ApiError\n */\nexport class ApiError extends Error {\n public readonly status: number;\n\n /**\n * The unwrapped field-error bag. See `ApiErrorData`; the contract is\n * documented in `docs/api-error-data-contract.md`.\n */\n public readonly data: ApiErrorData;\n\n /**\n * The full error response envelope. Read `error_message`, `error`, `status`\n * and nested `errors` from here — `data` has already unwrapped one level.\n */\n public readonly body: ApiErrorBody;\n\n public readonly requestId?: string;\n\n constructor(\n message: string,\n status: number,\n data?: ApiErrorData,\n requestId?: string,\n body?: ApiErrorBody,\n ) {\n super(message);\n this.name = \"ApiError\";\n this.status = status;\n this.data = data ?? null;\n this.body = body ?? null;\n this.requestId = requestId;\n\n if (\"captureStackTrace\" in Error) {\n (\n Error as {\n captureStackTrace: (\n target: Error,\n constructor: NewableFunction,\n ) => void;\n }\n ).captureStackTrace(this, ApiError);\n }\n }\n\n toJSON(): {\n name: string;\n message: string;\n status: number;\n data: ApiErrorData;\n body: ApiErrorBody;\n requestId?: string;\n } {\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n data: this.data,\n body: this.body,\n requestId: this.requestId,\n };\n }\n}\n\nfunction getStringRequestId(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction getRequestIdFromHeaders(headers: Headers): string | undefined {\n return (\n getStringRequestId(headers.get(\"x-request-id\")) ??\n getStringRequestId(headers.get(\"request-id\")) ??\n getStringRequestId(headers.get(\"X-Request-ID\"))\n );\n}\n\nfunction getRequestIdFromJsonBody(body: unknown): string | undefined {\n if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n return undefined;\n }\n\n const record = body as Record<string, unknown>;\n const meta = record.meta;\n\n return (\n getStringRequestId(record.request_id) ??\n getStringRequestId(record.requestId) ??\n (meta && typeof meta === \"object\" && !Array.isArray(meta)\n ? (getStringRequestId((meta as Record<string, unknown>).request_id) ??\n getStringRequestId((meta as Record<string, unknown>).requestId))\n : undefined)\n );\n}\n\n/**\n * Type guard for ApiError\n */\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError;\n}\n\nexport interface FetchClientInstance {\n request: <TResponse = unknown>(\n endpoint: string,\n options?: RequestOptions,\n ) => Promise<TResponse>;\n requestWithFormData: <TResponse = unknown>(\n endpoint: string,\n formData: FormData,\n options?: Omit<RequestOptions, \"body\" | \"params\"> & {\n method?: \"POST\" | \"PUT\" | \"PATCH\";\n },\n ) => Promise<TResponse>;\n get: <TResponse = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: Omit<RequestOptions, \"method\" | \"params\">,\n ) => Promise<TResponse>;\n post: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ) => Promise<TResponse>;\n put: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ) => Promise<TResponse>;\n patch: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ) => Promise<TResponse>;\n delete: <TResponse = unknown>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\">,\n ) => Promise<TResponse>;\n}\n\n/**\n * Creates a configured fetch client instance\n */\nexport function createFetchClient(\n config: FetchClientConfig,\n): FetchClientInstance {\n const {\n baseUrl,\n getAuthToken,\n onAuthError,\n defaultHeaders = {},\n credentials,\n cache,\n networkRetry,\n throwOnInvalidJson = false,\n } = config;\n const maxNetworkRetries = Math.max(0, networkRetry?.maxRetries ?? 0);\n const baseNetworkRetryDelayMs = Math.max(0, networkRetry?.baseDelayMs ?? 0);\n\n /**\n * Build headers for a request\n */\n async function buildHeaders(\n customHeaders?: Record<string, string>,\n ): Promise<Record<string, string>> {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n ...defaultHeaders,\n ...customHeaders,\n };\n\n // Add auth token if available\n if (getAuthToken) {\n const token = await getAuthToken();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n\n return headers;\n }\n\n /**\n * Join baseUrl + endpoint via string concatenation (matches fetchApi).\n * Using `new URL(endpoint, baseUrl)` would strip any path prefix from\n * baseUrl (e.g. \"/api\") when the endpoint starts with \"/\".\n */\n function joinUrl(endpoint: string): string {\n return `${baseUrl}${endpoint}`;\n }\n\n /**\n * Build URL with query parameters for GET requests\n * Compatible with fluid-admin's query param handling\n */\n function buildUrl(\n endpoint: string,\n params?: Record<string, unknown>,\n ): string {\n const fullUrl = joinUrl(endpoint);\n\n if (!params || Object.keys(params).length === 0) {\n return fullUrl;\n }\n\n const queryString = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return; // Skip undefined/null values\n }\n\n if (Array.isArray(value)) {\n // Handle arrays like Rails expects: key[]. The OpenAPI-declared\n // param name is sometimes already bracketed (e.g. \"product_ids[]\",\n // \"filters[integration_class][]\") to match Rails' own convention;\n // appending another \"[]\" in that case would double-bracket the wire\n // format (key[][]=1), which Rails does not parse as the array.\n const arrayKey = key.endsWith(\"[]\") ? key : `${key}[]`;\n value.forEach((item) => queryString.append(arrayKey, String(item)));\n } else if (typeof value === \"object\") {\n // Handle nested objects: key[subkey]\n Object.entries(value).forEach(([subKey, subValue]) => {\n if (subValue === undefined || subValue === null) {\n return;\n }\n\n if (Array.isArray(subValue)) {\n subValue.forEach((item) =>\n queryString.append(`${key}[${subKey}][]`, String(item)),\n );\n } else {\n queryString.append(`${key}[${subKey}]`, String(subValue));\n }\n });\n } else {\n queryString.append(key, String(value));\n }\n });\n\n const qs = queryString.toString();\n return qs ? `${fullUrl}?${qs}` : fullUrl;\n }\n\n /**\n * Shared response handler for both JSON and FormData requests.\n * Handles auth errors, non-OK responses, 204 No Content, and JSON parsing.\n */\n async function handleResponse<TResponse>(\n response: Response,\n method: string,\n _url: string,\n ): Promise<TResponse> {\n const headerRequestId = getRequestIdFromHeaders(response.headers);\n\n if (response.status === 401 && onAuthError) {\n onAuthError();\n }\n\n if (!response.ok) {\n // Read body as text first to avoid SyntaxError from response.json()\n // when server returns non-JSON bodies with application/json content-type.\n const errorText = await response.text().catch(() => \"\");\n const contentType = response.headers.get(\"content-type\");\n\n if (contentType?.includes(\"application/json\")) {\n // Parsed as `unknown` and narrowed before any property read: a body of\n // `null` (or a bare string/number/array) is valid JSON, and reading\n // `.error` off it directly threw a TypeError instead of an ApiError.\n let parsed: unknown;\n try {\n parsed = JSON.parse(errorText);\n } catch {\n throw new ApiError(\n errorText.slice(0, 200) ||\n `${method} request failed with status ${response.status}`,\n response.status,\n null,\n headerRequestId,\n );\n }\n\n const body = toApiErrorBody(parsed);\n // Only an object envelope can carry a message. Some Rails BFF endpoints\n // return `{ error: { message, details } }` instead of `{ message }` or\n // `{ error_message }`, so that shape is tried last.\n const msg = body\n ? (() => {\n const nestedError =\n typeof body.error === \"object\" && body.error !== null\n ? (body.error as { message?: unknown }).message\n : undefined;\n const directError =\n typeof body.error === \"string\" ? body.error : undefined;\n const message =\n typeof body.message === \"string\" ? body.message : undefined;\n const errorMessage =\n typeof body.error_message === \"string\"\n ? body.error_message\n : undefined;\n return (\n message ||\n errorMessage ||\n directError ||\n (typeof nestedError === \"string\" ? nestedError : undefined)\n );\n })()\n : undefined;\n\n throw new ApiError(\n msg || `${method} request failed with status ${response.status}`,\n response.status,\n body ? toApiErrorData(body) : (parsed as ApiErrorData),\n headerRequestId ?? getRequestIdFromJsonBody(parsed),\n body,\n );\n } else {\n throw new ApiError(\n `${method} request failed with status ${response.status}`,\n response.status,\n null,\n headerRequestId,\n );\n }\n }\n\n if (\n response.status === 204 ||\n response.headers.get(\"content-length\") === \"0\"\n ) {\n return null as TResponse;\n }\n\n const contentType = response.headers.get(\"content-type\");\n\n if (contentType?.includes(\"application/json\")) {\n const responseText = await response.text();\n\n try {\n const data = JSON.parse(responseText);\n return data as TResponse;\n } catch {\n if (throwOnInvalidJson) {\n throw new ApiError(\n \"Failed to parse response as JSON\",\n response.status,\n null,\n headerRequestId,\n );\n }\n\n // API declared JSON content-type but body isn't valid JSON.\n // Return the raw payload to preserve the legacy non-strict path.\n return responseText ? (responseText as TResponse) : (null as TResponse);\n }\n }\n\n // Non-JSON response (text/plain, text/html, etc.)\n return null as TResponse;\n }\n\n function getNetworkRetryDelayMs(retryAttempt: number): number {\n return baseNetworkRetryDelayMs * 2 ** (retryAttempt - 1);\n }\n\n async function waitForNetworkRetry(retryAttempt: number): Promise<void> {\n const delayMs = getNetworkRetryDelayMs(retryAttempt);\n if (delayMs <= 0) {\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n async function fetchWithNetworkRetry(\n url: string,\n fetchOptions: RequestInit,\n signal?: AbortSignal,\n ): Promise<Response> {\n let retryCount = 0;\n\n while (true) {\n try {\n return await fetch(url, fetchOptions);\n } catch (networkError) {\n if (signal?.aborted || retryCount >= maxNetworkRetries) {\n throw networkError;\n }\n\n retryCount += 1;\n await waitForNetworkRetry(retryCount);\n\n if (signal?.aborted) {\n throw networkError;\n }\n }\n }\n }\n\n /**\n * Main request function\n */\n async function request<TResponse = unknown>(\n endpoint: string,\n options: RequestOptions = {},\n ): Promise<TResponse> {\n const {\n method = \"GET\",\n headers: customHeaders,\n params,\n body,\n signal,\n priority,\n } = options;\n\n const url = params ? buildUrl(endpoint, params) : joinUrl(endpoint);\n\n const headers = await buildHeaders(customHeaders);\n\n let response: Response;\n\n try {\n const fetchOptions: RequestInit = { method, headers };\n if (credentials) fetchOptions.credentials = credentials;\n if (cache) fetchOptions.cache = cache;\n if (priority) fetchOptions.priority = priority;\n const serializedBody =\n body && method !== \"GET\" ? JSON.stringify(body) : null;\n if (serializedBody) fetchOptions.body = serializedBody;\n if (signal) fetchOptions.signal = signal;\n response = await fetchWithNetworkRetry(url, fetchOptions, signal);\n } catch (networkError) {\n throw new ApiError(\n `Network error: ${networkError instanceof Error ? networkError.message : \"Unknown network error\"}`,\n 0,\n null,\n );\n }\n\n return handleResponse<TResponse>(response, method, url);\n }\n\n /**\n * Request with FormData (for file uploads)\n */\n async function requestWithFormData<TResponse = unknown>(\n endpoint: string,\n formData: FormData,\n options: Omit<RequestOptions, \"body\" | \"params\"> & {\n method?: \"POST\" | \"PUT\" | \"PATCH\";\n } = {},\n ): Promise<TResponse> {\n const {\n method = \"POST\",\n headers: customHeaders,\n signal,\n priority,\n } = options;\n\n const url = joinUrl(endpoint);\n const headers = await buildHeaders(customHeaders);\n\n // Remove Content-Type to let browser set it with boundary\n delete headers[\"Content-Type\"];\n\n let response: Response;\n\n try {\n const fetchOptions: RequestInit = { method, headers, body: formData };\n if (credentials) fetchOptions.credentials = credentials;\n if (cache) fetchOptions.cache = cache;\n if (priority) fetchOptions.priority = priority;\n if (signal) fetchOptions.signal = signal;\n response = await fetchWithNetworkRetry(url, fetchOptions, signal);\n } catch (networkError) {\n throw new ApiError(\n `Network error: ${networkError instanceof Error ? networkError.message : \"Unknown network error\"}`,\n 0,\n null,\n );\n }\n\n return handleResponse<TResponse>(response, method, url);\n }\n\n // Return client with convenience methods\n return {\n request: request,\n requestWithFormData: requestWithFormData,\n\n // Convenience methods for common HTTP verbs\n get: <TResponse = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: Omit<RequestOptions, \"method\" | \"params\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"GET\" as const,\n ...(params && { params }),\n }),\n\n post: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"POST\",\n body,\n }),\n\n put: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"PUT\",\n body,\n }),\n\n patch: <TResponse = unknown>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"PATCH\",\n body,\n }),\n\n delete: <TResponse = unknown>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\">,\n ): Promise<TResponse> =>\n request<TResponse>(endpoint, {\n ...options,\n method: \"DELETE\",\n }),\n };\n}\n\nexport type FetchClient = FetchClientInstance;\n","import type { ApiErrorBody, ApiErrorData } from \"./api-error-shape\";\nimport { toApiErrorBody, toApiErrorData } from \"./api-error-shape\";\nimport { ApiError } from \"./fetch-client\";\n\nexport interface HeyApiErrorRequestOptions {\n method?: string;\n}\n\nexport interface HeyApiErrorInterceptorOptions {\n onResponseError?: (response: Response) => void;\n shouldPassThroughTransportError?: (error: unknown) => boolean;\n}\n\nexport type HeyApiErrorInterceptor = (\n error: unknown,\n response: Response | undefined,\n request: Request | undefined,\n options: HeyApiErrorRequestOptions,\n) => unknown;\n\nfunction getNonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction getRequestId(\n response: Response,\n error: ApiErrorBody,\n): string | undefined {\n const meta = toApiErrorBody(error?.meta);\n\n return (\n getNonEmptyString(response.headers.get(\"x-request-id\")) ??\n getNonEmptyString(response.headers.get(\"request-id\")) ??\n getNonEmptyString(error?.request_id) ??\n getNonEmptyString(error?.requestId) ??\n getNonEmptyString(meta?.request_id) ??\n getNonEmptyString(meta?.requestId)\n );\n}\n\nfunction getErrorMessage(\n error: Record<string, unknown>,\n fallback: string,\n): string {\n const nestedError = toApiErrorBody(error.error);\n\n return (\n getNonEmptyString(error.message) ??\n getNonEmptyString(error.error_message) ??\n getNonEmptyString(nestedError?.message) ??\n fallback\n );\n}\n\n/**\n * Creates an error interceptor compatible with generated Hey API fetch clients.\n * Consumer-specific auth and cancellation policy is supplied through callbacks,\n * keeping this package independent from generated client types.\n */\nexport function createHeyApiErrorInterceptor(\n options: HeyApiErrorInterceptorOptions = {},\n): HeyApiErrorInterceptor {\n return (error, response, request, requestOptions) => {\n if (!response) {\n if (error instanceof ApiError) {\n return error;\n }\n\n if (options.shouldPassThroughTransportError?.(error)) {\n return error;\n }\n\n // Request construction and auth callbacks run before dispatch. Preserve\n // those errors instead of reporting them as network failures.\n if (!request) {\n return error;\n }\n\n return new ApiError(\n `Network error: ${error instanceof Error ? error.message : \"Unknown network error\"}`,\n 0,\n null,\n );\n }\n\n // Generated clients surface malformed JSON bodies as SyntaxError. Map an\n // otherwise successful response to the shared strict parse contract.\n if (response.ok && error instanceof SyntaxError) {\n return new ApiError(\n \"Failed to parse response as JSON\",\n response.status,\n null,\n getRequestId(response, null),\n );\n }\n\n options.onResponseError?.(response);\n\n const method = request?.method ?? requestOptions.method ?? \"GET\";\n const errorRecord = toApiErrorBody(error);\n const requestId = getRequestId(response, errorRecord);\n\n if (errorRecord) {\n // `data` is the unwrapped field-error bag, `body` the whole envelope.\n // Both derive from one shared rule — see docs/api-error-data-contract.md.\n return new ApiError(\n getErrorMessage(errorRecord, `${method} request failed`),\n response.status,\n toApiErrorData(errorRecord),\n requestId,\n errorRecord,\n );\n }\n\n const isJson = response.headers\n .get(\"content-type\")\n ?.includes(\"application/json\");\n const text = getNonEmptyString(error);\n\n return new ApiError(\n isJson && text\n ? text.slice(0, 200)\n : `${method} request failed with status ${response.status}`,\n response.status,\n // A parsed JSON string is a legal `ApiErrorData` member, so it is kept\n // rather than dropped — the shared fetch client already preserves it, and\n // discarding it here made the two producers disagree.\n isJson ? (error as ApiErrorData) : null,\n requestId,\n // Unreachable as an envelope: this branch runs only when the payload is\n // not a plain object, which is exactly what `toApiErrorBody` rejects.\n null,\n );\n };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n ArrayStyle,\n ObjectStyle,\n SerializerOptions,\n} from \"./pathSerializer.gen\";\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: unknown) => unknown;\n\ntype QuerySerializerOptionsObject = {\n allowReserved?: boolean;\n array?: Partial<SerializerOptions<ArrayStyle>>;\n object?: Partial<SerializerOptions<ObjectStyle>>;\n};\n\nexport type QuerySerializerOptions = QuerySerializerOptionsObject & {\n /**\n * Per-parameter serialization overrides. When provided, these settings\n * override the global array/object settings for specific parameter names.\n */\n parameters?: Record<string, QuerySerializerOptionsObject>;\n};\n\nconst serializeFormDataPair = (\n data: FormData,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\" || value instanceof Blob) {\n data.append(key, value);\n } else if (value instanceof Date) {\n data.append(key, value.toISOString());\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (\n data: URLSearchParams,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\") {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: (body: unknown): FormData => {\n const data = new FormData();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: (body: unknown): string =>\n JSON.stringify(body, (_key, value) =>\n typeof value === \"bigint\" ? value.toString() : value,\n ),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: (body: unknown): string => {\n const data = new URLSearchParams();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\ntype Slot = \"body\" | \"headers\" | \"path\" | \"query\";\n\nexport type Field =\n | {\n in: Exclude<Slot, \"body\">;\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If omitted, we use the same value as `key`.\n */\n map?: string;\n }\n | {\n in: Extract<Slot, \"body\">;\n /**\n * Key isn't required for bodies.\n */\n key?: string;\n map?: string;\n }\n | {\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If `in` is omitted, `map` aliases `key` to the transport layer.\n */\n map: Slot;\n };\n\nexport interface Fields {\n allowExtra?: Partial<Record<Slot, boolean>>;\n args?: ReadonlyArray<Field>;\n}\n\nexport type FieldsConfig = ReadonlyArray<Field | Fields>;\n\nconst extraPrefixesMap: Record<string, Slot> = {\n $body_: \"body\",\n $headers_: \"headers\",\n $path_: \"path\",\n $query_: \"query\",\n};\nconst extraPrefixes = Object.entries(extraPrefixesMap);\n\ntype KeyMap = Map<\n string,\n | {\n in: Slot;\n map?: string;\n }\n | {\n in?: never;\n map: Slot;\n }\n>;\n\nfunction buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {\n if (!map) {\n map = new Map();\n }\n\n for (const config of fields) {\n if (\"in\" in config) {\n if (config.key) {\n map.set(config.key, {\n in: config.in,\n map: config.map,\n });\n }\n } else if (\"key\" in config) {\n map.set(config.key, {\n map: config.map,\n });\n } else if (config.args) {\n buildKeyMap(config.args, map);\n }\n }\n\n return map;\n}\n\ninterface Params {\n body?: unknown;\n headers: Record<string, unknown>;\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n}\n\nfunction stripEmptySlots(params: Params): void {\n for (const [slot, value] of Object.entries(params)) {\n if (slot === \"body\") continue;\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !Object.keys(value).length\n ) {\n delete params[slot as Slot];\n }\n }\n}\n\nexport function buildClientParams(\n args: ReadonlyArray<unknown>,\n fields: FieldsConfig,\n): Params {\n const params: Params = {\n headers: Object.create(null),\n path: Object.create(null),\n query: Object.create(null),\n };\n\n const map = buildKeyMap(fields);\n\n function writeSlot(slot: Slot, key: string, value: unknown): void {\n let record = params[slot] as Record<string, unknown> | undefined;\n if (record === undefined) {\n record = Object.create(null) as Record<string, unknown>;\n params[slot] = record;\n }\n record[key] = value;\n }\n\n let config: FieldsConfig[number] | undefined;\n\n for (const [index, arg] of args.entries()) {\n if (fields[index]) {\n config = fields[index];\n }\n\n if (!config) {\n continue;\n }\n\n if (\"in\" in config) {\n if (config.key) {\n const field = map.get(config.key)!;\n const name = field.map || config.key;\n if (field.in) {\n writeSlot(field.in, name, arg);\n }\n } else {\n params.body = arg;\n }\n } else {\n for (const [key, value] of Object.entries(arg ?? {})) {\n const field = map.get(key);\n\n if (field) {\n if (field.in) {\n const name = field.map || key;\n writeSlot(field.in, name, value);\n } else {\n params[field.map] = value;\n }\n } else {\n const extra = extraPrefixes.find(([prefix]) =>\n key.startsWith(prefix),\n );\n\n if (extra) {\n const [prefix, slot] = extra;\n writeSlot(slot, key.slice(prefix.length), value);\n } else if (\"allowExtra\" in config && config.allowExtra) {\n for (const [slot, allowed] of Object.entries(config.allowExtra)) {\n if (allowed) {\n writeSlot(slot as Slot, key, value);\n break;\n }\n }\n }\n }\n }\n }\n }\n\n stripEmptySlots(params);\n\n return params;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from \"./types.gen\";\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<\n RequestInit,\n \"method\"\n> &\n Pick<Config, \"method\" | \"responseTransformer\" | \"responseValidator\"> & {\n /**\n * Fetch API implementation. You can use this option to provide a custom\n * fetch instance.\n *\n * @default globalThis.fetch\n */\n fetch?: typeof fetch;\n /**\n * Implementing clients can call request interceptors inside this hook.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n /**\n * Callback invoked when a network or parsing error occurs during streaming.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param error The error that occurred.\n */\n onSseError?: (error: unknown) => void;\n /**\n * Callback invoked when an event is streamed from the server.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param event Event streamed from the server.\n * @returns Nothing (void).\n */\n onSseEvent?: (event: StreamEvent<TData>) => void;\n serializedBody?: RequestInit[\"body\"];\n /**\n * Default retry delay in milliseconds.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 3000\n */\n sseDefaultRetryDelay?: number;\n /**\n * Maximum number of retry attempts before giving up.\n */\n sseMaxRetryAttempts?: number;\n /**\n * Maximum retry delay in milliseconds.\n *\n * Applies only when exponential backoff is used.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 30000\n */\n sseMaxRetryDelay?: number;\n /**\n * Optional sleep function for retry backoff.\n *\n * Defaults to using `setTimeout`.\n */\n sseSleepFn?: (ms: number) => Promise<void>;\n url: string;\n };\n\nexport interface StreamEvent<TData = unknown> {\n data: TData;\n event?: string;\n id?: string;\n retry?: number;\n}\n\nexport type ServerSentEventsResult<\n TData = unknown,\n TReturn = void,\n TNext = unknown,\n> = {\n stream: AsyncGenerator<\n TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n TReturn,\n TNext\n >;\n};\n\nexport function createSseClient<TData = unknown>({\n onRequest,\n onSseError,\n onSseEvent,\n responseTransformer,\n responseValidator,\n sseDefaultRetryDelay,\n sseMaxRetryAttempts,\n sseMaxRetryDelay,\n sseSleepFn,\n url,\n ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> {\n let lastEventId: string | undefined;\n\n const sleep =\n sseSleepFn ??\n ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const createStream = async function* () {\n let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n let attempt = 0;\n const signal = options.signal ?? new AbortController().signal;\n\n while (true) {\n if (signal.aborted) break;\n\n attempt++;\n\n const headers =\n options.headers instanceof Headers\n ? options.headers\n : new Headers(options.headers as Record<string, string> | undefined);\n\n if (lastEventId !== undefined) {\n headers.set(\"Last-Event-ID\", lastEventId);\n }\n\n try {\n const requestInit: RequestInit = {\n redirect: \"follow\",\n ...options,\n body: options.serializedBody,\n headers,\n signal,\n };\n let request = new Request(url, requestInit);\n if (onRequest) {\n request = await onRequest(url, requestInit);\n }\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = options.fetch ?? globalThis.fetch;\n const response = await _fetch(request);\n\n if (!response.ok)\n throw new Error(\n `SSE failed: ${response.status} ${response.statusText}`,\n );\n\n if (!response.body) throw new Error(\"No body in SSE response\");\n\n const reader = response.body\n .pipeThrough(new TextDecoderStream())\n .getReader();\n\n let buffer = \"\";\n\n const abortHandler = () => {\n try {\n reader.cancel();\n } catch {\n // noop\n }\n };\n\n signal.addEventListener(\"abort\", abortHandler);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += value;\n buffer = buffer.replace(/\\r\\n?/g, \"\\n\"); // normalize line endings\n\n const chunks = buffer.split(\"\\n\\n\");\n buffer = chunks.pop() ?? \"\";\n\n for (const chunk of chunks) {\n const lines = chunk.split(\"\\n\");\n const dataLines: Array<string> = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith(\"data:\")) {\n dataLines.push(line.replace(/^data:\\s*/, \"\"));\n } else if (line.startsWith(\"event:\")) {\n eventName = line.replace(/^event:\\s*/, \"\");\n } else if (line.startsWith(\"id:\")) {\n lastEventId = line.replace(/^id:\\s*/, \"\");\n } else if (line.startsWith(\"retry:\")) {\n const parsed = Number.parseInt(\n line.replace(/^retry:\\s*/, \"\"),\n 10,\n );\n if (!Number.isNaN(parsed)) {\n retryDelay = parsed;\n }\n }\n }\n\n let data: unknown;\n let parsedJson = false;\n\n if (dataLines.length) {\n const rawData = dataLines.join(\"\\n\");\n try {\n data = JSON.parse(rawData);\n parsedJson = true;\n } catch {\n data = rawData;\n }\n }\n\n if (parsedJson) {\n if (responseValidator) {\n await responseValidator(data);\n }\n\n if (responseTransformer) {\n data = await responseTransformer(data);\n }\n }\n\n onSseEvent?.({\n data,\n event: eventName,\n id: lastEventId,\n retry: retryDelay,\n });\n\n if (dataLines.length) {\n yield data as any;\n }\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abortHandler);\n reader.releaseLock();\n }\n\n break; // exit loop on normal completion\n } catch (error) {\n // connection failed or aborted; retry after delay\n onSseError?.(error);\n\n if (\n sseMaxRetryAttempts !== undefined &&\n attempt >= sseMaxRetryAttempts\n ) {\n break; // stop after firing error\n }\n\n // exponential backoff: double retry each attempt, cap at 30s\n const backoff = Math.min(\n retryDelay * 2 ** (attempt - 1),\n sseMaxRetryDelay ?? 30000,\n );\n await sleep(backoff);\n }\n }\n };\n\n const stream = createStream();\n\n return { stream };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\ninterface SerializeOptions<T>\n extends SerializePrimitiveOptions, SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = \"label\" | \"matrix\" | \"simple\";\nexport type ObjectStyle = \"form\" | \"deepObject\";\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (\n style: ArraySeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const separatorArrayNoExplode = (\n style: ArraySeparatorStyle,\n): \",\" | \"|\" | \"%20\" => {\n switch (style) {\n case \"form\":\n return \",\";\n case \"pipeDelimited\":\n return \"|\";\n case \"spaceDelimited\":\n return \"%20\";\n default:\n return \",\";\n }\n};\n\nexport const separatorObjectExplode = (\n style: ObjectSeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}): string => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n case \"simple\":\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === \"label\" || style === \"simple\") {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam): string => {\n if (value === undefined || value === null) {\n return \"\";\n }\n\n if (typeof value === \"object\") {\n throw new Error(\n \"Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.\",\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n valueOnly,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n valueOnly?: boolean;\n}): string => {\n if (value instanceof Date) {\n return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;\n }\n\n if (style !== \"deepObject\" && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [\n ...values,\n key,\n allowReserved ? (v as string) : encodeURIComponent(v as string),\n ];\n });\n const joinedValues = values.join(\",\");\n switch (style) {\n case \"form\":\n return `${name}=${joinedValues}`;\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === \"deepObject\" ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { BodySerializer, QuerySerializer } from \"./bodySerializer.gen\";\nimport {\n type ArraySeparatorStyle,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"./pathSerializer.gen\";\n\nexport interface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nexport const PATH_PARAM_RE: RegExp = /\\{[^{}]+\\}/g;\n\nexport const defaultPathSerializer = ({\n path,\n url: _url,\n}: PathSerializer): string => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = \"simple\";\n\n if (name.endsWith(\"*\")) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith(\".\")) {\n name = name.substring(1);\n style = \"label\";\n } else if (name.startsWith(\";\")) {\n name = name.substring(1);\n style = \"matrix\";\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(\n match,\n serializeArrayParam({ explode, name, style, value }),\n );\n continue;\n }\n\n if (typeof value === \"object\") {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n valueOnly: true,\n }),\n );\n continue;\n }\n\n if (style === \"matrix\") {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === \"label\" ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}): string => {\n const pathUrl = _url.startsWith(\"/\") ? _url : `/${_url}`;\n let url = (baseUrl ?? \"\") + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : \"\";\n if (search.startsWith(\"?\")) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport function getValidRequestBody(options: {\n body?: unknown;\n bodySerializer?: BodySerializer | null;\n serializedBody?: unknown;\n}): unknown {\n const hasBody = options.body !== undefined;\n const isSerializedBody = hasBody && options.bodySerializer;\n\n if (isSerializedBody) {\n if (\"serializedBody\" in options) {\n const hasSerializedBody =\n options.serializedBody !== undefined && options.serializedBody !== \"\";\n\n return hasSerializedBody ? options.serializedBody : null;\n }\n\n // not all clients implement a serializedBody property (i.e., client-axios)\n return options.body !== \"\" ? options.body : null;\n }\n\n // plain/text body\n if (hasBody) {\n return options.body;\n }\n\n // no body was provided\n return undefined;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nexport type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: \"header\" | \"query\" | \"cookie\";\n /**\n * A unique identifier for the security scheme.\n *\n * Defined only when there are multiple security schemes whose `Auth`\n * shape would otherwise be identical.\n */\n key?: string;\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: \"basic\" | \"bearer\";\n type: \"apiKey\" | \"http\";\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token =\n typeof callback === \"function\" ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === \"bearer\") {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === \"basic\") {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { getAuthToken } from \"../core/auth.gen\";\nimport type { QuerySerializerOptions } from \"../core/bodySerializer.gen\";\nimport { jsonBodySerializer } from \"../core/bodySerializer.gen\";\nimport {\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"../core/pathSerializer.gen\";\nimport { getUrl } from \"../core/utils.gen\";\nimport type {\n Client,\n ClientOptions,\n Config,\n RequestOptions,\n} from \"./types.gen\";\n\nexport const createQuerySerializer = <T = unknown>({\n parameters = {},\n ...args\n}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {\n const querySerializer = (queryParams: T): string => {\n const search: string[] = [];\n if (queryParams && typeof queryParams === \"object\") {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const options = parameters[name] || args;\n\n if (Array.isArray(value)) {\n const serializedArray = serializeArrayParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"form\",\n value,\n ...options.array,\n });\n if (serializedArray) search.push(serializedArray);\n } else if (typeof value === \"object\") {\n const serializedObject = serializeObjectParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"deepObject\",\n value: value as Record<string, unknown>,\n ...options.object,\n });\n if (serializedObject) search.push(serializedObject);\n } else {\n const serializedPrimitive = serializePrimitiveParam({\n allowReserved: options.allowReserved,\n name,\n value: value as string,\n });\n if (serializedPrimitive) search.push(serializedPrimitive);\n }\n }\n }\n return search.join(\"&\");\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (\n contentType: string | null,\n): Exclude<Config[\"parseAs\"], \"auto\"> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return \"stream\";\n }\n\n const cleanContent = contentType.split(\";\")[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (\n cleanContent.startsWith(\"application/json\") ||\n cleanContent.endsWith(\"+json\")\n ) {\n return \"json\";\n }\n\n if (cleanContent === \"multipart/form-data\") {\n return \"formData\";\n }\n\n if (\n [\"application/\", \"audio/\", \"image/\", \"video/\"].some((type) =>\n cleanContent.startsWith(type),\n )\n ) {\n return \"blob\";\n }\n\n if (cleanContent.startsWith(\"text/\")) {\n return \"text\";\n }\n\n return;\n};\n\nconst checkForExistence = (\n options: Pick<RequestOptions, \"auth\" | \"query\"> & {\n headers: Headers;\n },\n name?: string,\n): boolean => {\n if (!name) {\n return false;\n }\n if (\n options.headers.has(name) ||\n options.query?.[name] ||\n options.headers.get(\"Cookie\")?.includes(`${name}=`)\n ) {\n return true;\n }\n return false;\n};\n\nexport async function setAuthParams(\n options: Pick<RequestOptions, \"auth\" | \"query\" | \"security\"> & {\n headers: Headers;\n },\n): Promise<void> {\n for (const auth of options.security ?? []) {\n if (checkForExistence(options, auth.name)) {\n continue;\n }\n\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? \"Authorization\";\n\n switch (auth.in) {\n case \"query\":\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case \"cookie\":\n options.headers.append(\"Cookie\", `${name}=${token}`);\n break;\n case \"header\":\n default:\n options.headers.set(name, token);\n break;\n }\n }\n}\n\nexport const buildUrl: Client[\"buildUrl\"] = (options) =>\n getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === \"function\"\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith(\"/\")) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nconst headersEntries = (headers: Headers): Array<[string, string]> => {\n const entries: Array<[string, string]> = [];\n headers.forEach((value, key) => {\n entries.push([key, value]);\n });\n return entries;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>[\"headers\"] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header) {\n continue;\n }\n\n const iterator =\n header instanceof Headers\n ? headersEntries(header)\n : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e., their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === \"object\" ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n /** response may be undefined due to a network error where no response object is produced */\n response: Res | undefined,\n /** request may be undefined, because error may be from building the request object itself */\n request: Req | undefined,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (\n request: Req,\n options: Options,\n) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n fns: Array<Interceptor | null> = [];\n\n clear(): void {\n this.fns = [];\n }\n\n eject(id: number | Interceptor): void {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = null;\n }\n }\n\n exists(id: number | Interceptor): boolean {\n const index = this.getInterceptorIndex(id);\n return Boolean(this.fns[index]);\n }\n\n getInterceptorIndex(id: number | Interceptor): number {\n if (typeof id === \"number\") {\n return this.fns[id] ? id : -1;\n }\n return this.fns.indexOf(id);\n }\n\n update(\n id: number | Interceptor,\n fn: Interceptor,\n ): number | Interceptor | false {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = fn;\n return id;\n }\n return false;\n }\n\n use(fn: Interceptor): number {\n this.fns.push(fn);\n return this.fns.length - 1;\n }\n}\n\nexport interface Middleware<Req, Res, Err, Options> {\n error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;\n request: Interceptors<ReqInterceptor<Req, Options>>;\n response: Interceptors<ResInterceptor<Res, Req, Options>>;\n}\n\nexport const createInterceptors = <Req, Res, Err, Options>(): Middleware<\n Req,\n Res,\n Err,\n Options\n> => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: \"form\",\n },\n object: {\n explode: true,\n style: \"deepObject\",\n },\n});\n\nconst defaultHeaders = {\n \"Content-Type\": \"application/json\",\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: \"auto\",\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { createSseClient } from \"../core/serverSentEvents.gen\";\nimport type { HttpMethod } from \"../core/types.gen\";\nimport { getValidRequestBody } from \"../core/utils.gen\";\nimport type {\n Client,\n Config,\n RequestOptions,\n ResolvedRequestOptions,\n} from \"./types.gen\";\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from \"./utils.gen\";\n\ntype ReqInit = Omit<RequestInit, \"body\" | \"headers\"> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<\n Request,\n Response,\n unknown,\n ResolvedRequestOptions\n >();\n\n const beforeRequest = async <\n TData = unknown,\n TResponseStyle extends \"data\" | \"fields\" = \"fields\",\n ThrowOnError extends boolean = boolean,\n Url extends string = string,\n >(\n options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,\n ) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n serializedBody: undefined as string | undefined,\n };\n\n if (opts.security) {\n await setAuthParams(opts);\n }\n\n if (opts.requestValidator) {\n await opts.requestValidator(opts);\n }\n\n if (opts.body !== undefined && opts.bodySerializer) {\n opts.serializedBody = opts.bodySerializer(opts.body) as\n | string\n | undefined;\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.serializedBody === \"\") {\n opts.headers.delete(\"Content-Type\");\n }\n\n const resolvedOpts = opts as typeof opts &\n ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;\n const url = buildUrl(resolvedOpts);\n\n return { opts: resolvedOpts, url };\n };\n\n const request: Client[\"request\"] = async (options) => {\n const throwOnError = options.throwOnError ?? _config.throwOnError;\n const responseStyle = options.responseStyle ?? _config.responseStyle;\n\n let request: Request | undefined;\n let response: Response | undefined;\n\n try {\n const { opts, url } = await beforeRequest(options);\n const requestInit: ReqInit = {\n redirect: \"follow\",\n ...opts,\n body: getValidRequestBody(opts),\n };\n\n request = new Request(url, requestInit);\n\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n\n response = await _fetch(request);\n\n for (const fn of interceptors.response.fns) {\n if (fn) {\n response = await fn(response, request, opts);\n }\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n const parseAs =\n (opts.parseAs === \"auto\"\n ? getParseAs(response.headers.get(\"Content-Type\"))\n : opts.parseAs) ?? \"json\";\n\n if (\n response.status === 204 ||\n response.headers.get(\"Content-Length\") === \"0\"\n ) {\n let emptyData: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"text\":\n emptyData = await response[parseAs]();\n break;\n case \"formData\":\n emptyData = new FormData();\n break;\n case \"stream\":\n emptyData = response.body;\n break;\n case \"json\":\n default:\n emptyData = {};\n break;\n }\n return opts.responseStyle === \"data\"\n ? emptyData\n : {\n data: emptyData,\n ...result,\n };\n }\n\n let data: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"formData\":\n case \"text\":\n data = await response[parseAs]();\n break;\n case \"json\": {\n // Some servers return 200 with no Content-Length and empty body.\n // response.json() would throw; read as text and parse if non-empty.\n const text = await response.text();\n data = text ? JSON.parse(text) : {};\n break;\n }\n case \"stream\":\n return opts.responseStyle === \"data\"\n ? response.body\n : {\n data: response.body,\n ...result,\n };\n }\n\n if (parseAs === \"json\") {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return opts.responseStyle === \"data\"\n ? data\n : {\n data,\n ...result,\n };\n }\n\n const textError = await response.text();\n let jsonError: unknown;\n\n try {\n jsonError = JSON.parse(textError);\n } catch {\n // noop\n }\n\n throw jsonError ?? textError;\n } catch (error) {\n let finalError = error;\n\n for (const fn of interceptors.error.fns) {\n if (fn) {\n finalError = await fn(\n finalError,\n response,\n request,\n options as ResolvedRequestOptions,\n );\n }\n }\n\n finalError = finalError || {};\n\n if (throwOnError) {\n throw finalError;\n }\n\n // TODO: we probably want to return error and improve types\n return responseStyle === \"data\"\n ? undefined\n : {\n error: finalError,\n request,\n response,\n };\n }\n };\n\n const makeMethodFn =\n (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>\n request({ ...options, method });\n\n const makeSseFn =\n (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {\n const { opts, url } = await beforeRequest(options);\n return createSseClient({\n ...opts,\n body: opts.body as BodyInit | null | undefined,\n method,\n onRequest: async (url, init) => {\n let request = new Request(url, init);\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n return request;\n },\n serializedBody: getValidRequestBody(opts) as\n | BodyInit\n | null\n | undefined,\n url,\n });\n };\n\n const _buildUrl: Client[\"buildUrl\"] = (options) =>\n buildUrl({ ..._config, ...options });\n\n return {\n buildUrl: _buildUrl,\n connect: makeMethodFn(\"CONNECT\"),\n delete: makeMethodFn(\"DELETE\"),\n get: makeMethodFn(\"GET\"),\n getConfig,\n head: makeMethodFn(\"HEAD\"),\n interceptors,\n options: makeMethodFn(\"OPTIONS\"),\n patch: makeMethodFn(\"PATCH\"),\n post: makeMethodFn(\"POST\"),\n put: makeMethodFn(\"PUT\"),\n request,\n setConfig,\n sse: {\n connect: makeSseFn(\"CONNECT\"),\n delete: makeSseFn(\"DELETE\"),\n get: makeSseFn(\"GET\"),\n head: makeSseFn(\"HEAD\"),\n options: makeSseFn(\"OPTIONS\"),\n patch: makeSseFn(\"PATCH\"),\n post: makeSseFn(\"POST\"),\n put: makeSseFn(\"PUT\"),\n trace: makeSseFn(\"TRACE\"),\n },\n trace: makeMethodFn(\"TRACE\"),\n } as Client;\n};\n","import { createHeyApiErrorInterceptor } from \"@fluid-app/api-client-core\";\nimport { type Client, createClient } from \"@fluid-app/hey-api-fetch-runtime\";\n\nexport type FluidOsHeyApiClient = Client;\n\nexport interface FluidOsHeyApiClientConfig {\n baseUrl: string;\n fetch?: typeof fetch;\n getAuthToken?: () =>\n | string\n | null\n | undefined\n | Promise<string | null | undefined>;\n defaultHeaders?: Record<string, string>;\n onAuthError?: () => void;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n (error instanceof DOMException && error.name === \"AbortError\") ||\n (error instanceof Error && error.name === \"AbortError\")\n );\n}\n\nexport function createFluidOsHeyApiClient(\n config: FluidOsHeyApiClientConfig,\n): Client {\n const client = createClient({\n auth: async () => (await config.getAuthToken?.()) ?? undefined,\n baseUrl: config.baseUrl,\n fetch: config.fetch,\n headers: {\n Accept: \"application/json\",\n ...config.defaultHeaders,\n },\n throwOnError: true,\n });\n\n client.interceptors.error.use(\n createHeyApiErrorInterceptor({\n onResponseError: (response) => {\n if (response.status === 401) {\n config.onAuthError?.();\n }\n },\n shouldPassThroughTransportError: isAbortError,\n }),\n );\n\n return client;\n}\n","import { findProjectConfig, readConfig } from \"@fluid-app/fluid-cli\";\nimport {\n createFluidOsHeyApiClient,\n type FluidOsHeyApiClient,\n} from \"@fluid-app/fluidos-api-client\";\nimport chalk from \"chalk\";\n\nexport interface AuthenticatedClientResult {\n readonly client: FluidOsHeyApiClient;\n}\n\nexport function createAuthenticatedClient(): AuthenticatedClientResult {\n return { client: createAuthenticatedWidgetPackageClient() };\n}\n\nexport function createAuthenticatedWidgetPackageClient(): FluidOsHeyApiClient {\n const { profile, profileName, token } = resolveAuthenticatedProfile();\n if (!token) {\n if (!profileName) {\n throw new Error(\n \"Not logged in. Run \" + chalk.cyan(\"fluid login\") + \" first.\",\n );\n }\n throw new Error(\n \"No auth token found for profile \" +\n chalk.cyan(profileName) +\n \". Run \" +\n chalk.cyan(\"fluid login\") +\n \" to re-authenticate.\",\n );\n }\n\n return createFluidOsHeyApiClient({\n baseUrl:\n profile?.baseUrl ??\n process.env[\"FLUID_API_BASE\"] ??\n \"https://api.fluid.app\",\n getAuthToken: () => token,\n });\n}\n\ntype ProfileWithBaseUrl = ReturnType<typeof readConfig>[\"profiles\"][string] & {\n readonly baseUrl?: string;\n};\n\nfunction resolveAuthenticatedProfile(): {\n readonly profile?: ProfileWithBaseUrl;\n readonly profileName?: string;\n readonly token?: string;\n} {\n const config = readConfig();\n const projectConfig = findProjectConfig(process.cwd());\n\n if (projectConfig?.profile) {\n const profile = config.profiles[projectConfig.profile] as\n | ProfileWithBaseUrl\n | undefined;\n if (profile) {\n return {\n profile,\n profileName: projectConfig.profile,\n token: profile.token,\n };\n }\n }\n\n if (!config.activeProfile) return {};\n const profile = config.profiles[config.activeProfile] as\n | ProfileWithBaseUrl\n | undefined;\n if (!profile) return {};\n\n return {\n profile,\n profileName: config.activeProfile,\n token: profile.token,\n };\n}\n","/**\n * Git wrapper for the Fluid widget CLI — shells out to the system `git`\n * binary via execa. Mirrors the Mist CLI write path\n * (`packages/cli/mist/src/lib/git.ts`): we deliberately do NOT bundle git or\n * use a pure-JS implementation; users are expected to have git installed and\n * we surface a friendly, actionable error when they don't.\n *\n * Security: a token-bearing `remote_url` from POST .../git_credential must\n * never be logged, persisted, or exposed in the process table. The token is\n * stripped from the URL and handed to git through a GIT_ASKPASS script via env\n * vars (FLUID_GIT_USER / FLUID_GIT_PASS) — so it never appears in argv\n * (visible to `ps aux` / `/proc/<pid>/cmdline`) and is never written to\n * `.git/config`. `-c credential.helper=` stops git from caching it, and\n * `GIT_TERMINAL_PROMPT=0` makes auth fail fast instead of hanging on a prompt.\n */\n\nimport {\n parseNameStatusZ,\n type ChangeEntry,\n type CommitMessage,\n} from \"@fluid-app/fluid-cli\";\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { execa, type ExecaError } from \"execa\";\n\nexport class GitError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode = 1) {\n super(message);\n this.name = \"GitError\";\n this.exitCode = exitCode;\n }\n}\n\n/**\n * execa throws ENOENT when the git binary itself is missing — the single most\n * common failure on non-developer machines. Translate it into an actionable\n * message (mirrors Mist Desktop's git-availability guidance) instead of a\n * bare \"git <verb> failed (exit 1)\". Returns null for every other failure so\n * call sites keep their specific messages.\n */\nexport function gitMissingError(err: unknown): GitError | null {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code !== \"ENOENT\") return null;\n return new GitError(\n \"Git isn't installed or isn't on your PATH. Install it and try again:\\n\" +\n \" macOS: xcode-select --install (or `brew install git`)\\n\" +\n \" Windows: https://git-scm.com/download/win\\n\" +\n \" Linux: use your package manager, e.g. `sudo apt-get install git`\\n\" +\n \"Downloads for all platforms: https://git-scm.com/downloads\",\n 127,\n );\n}\n\n/**\n * Split a token-bearing remote URL into the userless URL + creds. Keeps the\n * token off git's argv: we pass `cleanUrl` to git and feed `username` /\n * `password` back through GIT_ASKPASS env vars. If the URL has no embedded\n * credentials, returns empty strings — fine for public repos where git won't\n * invoke askpass.\n */\nfunction splitRemoteCredentials(remoteUrl: string): {\n cleanUrl: string;\n username: string;\n password: string;\n} {\n let u: URL;\n try {\n u = new URL(remoteUrl);\n } catch {\n // Not a URL (e.g. a local filesystem path used for dev/testing). Pass it\n // through untouched — there are no embedded credentials to strip.\n return { cleanUrl: remoteUrl, username: \"\", password: \"\" };\n }\n const username = decodeURIComponent(u.username);\n const password = decodeURIComponent(u.password);\n u.username = \"\";\n u.password = \"\";\n return { cleanUrl: u.toString(), username, password };\n}\n\n/**\n * Write a stub GIT_ASKPASS shell script to a per-process tmpdir and return its\n * path. The script contains no secret — it just echoes back whichever env var\n * (FLUID_GIT_USER / FLUID_GIT_PASS) matches git's prompt. Credentials only\n * live in the spawned git process's env for the duration of the call.\n *\n * One POSIX script for all platforms: Git for Windows runs GIT_ASKPASS through\n * its bundled sh, so a plain sh script works everywhere. Idempotent.\n */\nlet askpassPath: string | null = null;\nfunction ensureAskpassScript(): string {\n if (askpassPath && existsSync(askpassPath)) return askpassPath;\n const dir = path.join(os.tmpdir(), `fluid-widget-askpass-${process.pid}`);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 });\n const p = path.join(dir, \"askpass.sh\");\n writeFileSync(\n p,\n `#!/bin/sh\\ncase \"$1\" in\\n Username*) printf '%s' \"$FLUID_GIT_USER\" ;;\\n *) printf '%s' \"$FLUID_GIT_PASS\" ;;\\nesac\\n`,\n { mode: 0o700 },\n );\n chmodSync(p, 0o700);\n askpassPath = p;\n return askpassPath;\n}\n\n/**\n * Build the spawn env + cleaned URL for a credentialed git invocation. The\n * returned `cleanUrl` has userinfo stripped (safe to pass as argv); the `env`\n * carries GIT_ASKPASS + FLUID_GIT_USER / FLUID_GIT_PASS and\n * GIT_TERMINAL_PROMPT=0.\n */\nfunction gitAuthSpawn(remoteUrl: string): {\n cleanUrl: string;\n env: NodeJS.ProcessEnv;\n} {\n const { cleanUrl, username, password } = splitRemoteCredentials(remoteUrl);\n return {\n cleanUrl,\n env: {\n ...process.env,\n GIT_ASKPASS: ensureAskpassScript(),\n GIT_TERMINAL_PROMPT: \"0\",\n FLUID_GIT_USER: username,\n FLUID_GIT_PASS: password,\n },\n };\n}\n\nfunction wrapGitError(err: unknown, verb: string): GitError {\n const missing = gitMissingError(err);\n if (missing) return missing;\n const e = err as ExecaError;\n return new GitError(\n `git ${verb} failed${e.exitCode != null ? ` (exit ${e.exitCode})` : \"\"}`,\n e.exitCode ?? 1,\n );\n}\n\n/** Confirm git is installed. Cheap call once at the start of a git command. */\nexport async function ensureGitAvailable(): Promise<void> {\n try {\n await execa(\"git\", [\"--version\"]);\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n throw new GitError(\n \"`git` is required but couldn't be run. Install it from https://git-scm.com/downloads.\",\n );\n }\n}\n\n/** Is `cwd` inside a git working tree? */\nexport async function isGitRepository(cwd: string): Promise<boolean> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"rev-parse\", \"--is-inside-work-tree\"],\n { cwd },\n );\n return stdout.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/** `git init` (+ set the initial branch to `branch`). No-op if already a repo. */\nexport async function gitInit(cwd: string, branch = \"main\"): Promise<void> {\n try {\n await execa(\"git\", [\"init\", \"--initial-branch\", branch], { cwd });\n } catch (err) {\n // Older gits lack --initial-branch; fall back to a plain init.\n const missing = gitMissingError(err);\n if (missing) throw missing;\n try {\n await execa(\"git\", [\"init\"], { cwd });\n } catch (fallbackErr) {\n throw wrapGitError(fallbackErr, \"init\");\n }\n }\n}\n\n/**\n * `git clone <cleanUrl> <targetDir>`. The original remoteUrl carries a token;\n * gitAuthSpawn strips it from the URL and re-injects it via GIT_ASKPASS.\n */\nexport async function gitClone(\n remoteUrl: string,\n targetDir: string,\n options: {\n readonly depth?: number;\n readonly branch?: string;\n /**\n * Capture git's stderr instead of inheriting it. Used for best-effort\n * clones (e.g. the create template fetch) where the caller handles\n * failure and doesn't want git's raw error text on the console.\n */\n readonly silent?: boolean;\n } = {},\n): Promise<void> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n const args = [\"-c\", \"credential.helper=\", \"clone\", \"--quiet\"];\n if (options.depth != null) args.push(\"--depth\", String(options.depth));\n if (options.branch) args.push(\"--branch\", options.branch);\n args.push(cleanUrl, targetDir);\n try {\n await execa(\"git\", args, {\n env,\n stdio: options.silent ? \"pipe\" : [\"ignore\", \"inherit\", \"inherit\"],\n });\n } catch (err) {\n throw wrapGitError(err, \"clone\");\n }\n}\n\n/** `git push <remote> HEAD:<branch>` — credentials via GIT_ASKPASS, never argv. */\nexport async function gitPush(\n cwd: string,\n remoteUrl: string,\n branch = \"main\",\n): Promise<void> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n try {\n await execa(\n \"git\",\n [\n \"-c\",\n \"credential.helper=\",\n \"-c\",\n \"http.https://github.com/.extraheader=\",\n \"push\",\n cleanUrl,\n `HEAD:${branch}`,\n ],\n { cwd, env, stdio: [\"ignore\", \"inherit\", \"inherit\"] },\n );\n } catch (err) {\n throw wrapGitError(err, \"push\");\n }\n}\n\n/**\n * Does `branch` exist on the remote? Uses `git ls-remote --heads`, which is\n * the reliable way to tell a genuinely-empty remote (freshly provisioned repo,\n * first push) apart from a connection/auth failure. Returns false only when the\n * remote answered but has no such branch; **throws** on any transport/auth\n * error so callers don't mistake a network blip for \"empty remote\" and skip\n * reconciliation.\n */\nexport async function gitRemoteBranchExists(\n cwd: string,\n remoteUrl: string,\n branch = \"main\",\n): Promise<boolean> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n try {\n const { stdout } = await execa(\n \"git\",\n [\"-c\", \"credential.helper=\", \"ls-remote\", \"--heads\", cleanUrl, branch],\n { cwd, env },\n );\n return stdout.trim().length > 0;\n } catch (err) {\n throw wrapGitError(err, \"ls-remote\");\n }\n}\n\n/**\n * Fetch the given branch from the token-bearing remote, writing `FETCH_HEAD`.\n * Throws on failure — callers should first confirm the branch exists with\n * `gitRemoteBranchExists` so a genuinely-empty remote isn't treated as an error.\n */\nexport async function gitFetch(\n cwd: string,\n remoteUrl: string,\n branch = \"main\",\n): Promise<void> {\n const { cleanUrl, env } = gitAuthSpawn(remoteUrl);\n try {\n await execa(\n \"git\",\n [\"-c\", \"credential.helper=\", \"fetch\", \"--quiet\", cleanUrl, branch],\n { cwd, env },\n );\n } catch (err) {\n throw wrapGitError(err, \"fetch\");\n }\n}\n\n/**\n * Count commits in local HEAD vs `FETCH_HEAD` (after `gitFetch`). Returns\n * `{ahead, behind}`. `0/0` means \"in sync\" (or no FETCH_HEAD / no HEAD yet).\n */\nexport async function gitAheadBehindVsFetchHead(\n cwd: string,\n): Promise<{ ahead: number; behind: number }> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"rev-list\", \"--left-right\", \"--count\", \"HEAD...FETCH_HEAD\"],\n { cwd },\n );\n const [a, b] = stdout.trim().split(/\\s+/);\n const ahead = Number.parseInt(a ?? \"0\", 10);\n const behind = Number.parseInt(b ?? \"0\", 10);\n return {\n ahead: Number.isFinite(ahead) ? ahead : 0,\n behind: Number.isFinite(behind) ? behind : 0,\n };\n } catch {\n return { ahead: 0, behind: 0 };\n }\n}\n\n/** Does `cwd` have any commits yet? (false right after `git init`.) */\nexport async function hasCommits(cwd: string): Promise<boolean> {\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", \"HEAD\"], { cwd });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Adopt `FETCH_HEAD` as the current (unborn) branch's base: point the branch\n * ref at it and load its tree into the index, leaving the working tree\n * untouched. The next auto-commit then records the local project tree as a\n * child of the remote history — local files win, remote-only files are\n * recorded as deletions — so the push fast-forwards instead of being\n * rejected for unrelated history. Only call this when `hasCommits` is false;\n * on a repo with local commits it would silently rewrite the branch ref.\n *\n * Returns the number of remote commits adopted.\n */\nexport async function gitAdoptFetchHead(cwd: string): Promise<number> {\n try {\n await execa(\"git\", [\"reset\", \"--mixed\", \"FETCH_HEAD\"], { cwd });\n const { stdout } = await execa(\n \"git\",\n [\"rev-list\", \"--count\", \"FETCH_HEAD\"],\n { cwd },\n );\n const count = Number.parseInt(stdout.trim(), 10);\n return Number.isFinite(count) ? count : 0;\n } catch (err) {\n throw wrapGitError(err, \"adopt remote history\");\n }\n}\n\n/** Fast-forward `HEAD` to `FETCH_HEAD`. Fails if not fast-forwardable. */\nexport async function gitMergeFastForward(cwd: string): Promise<void> {\n try {\n await execa(\"git\", [\"merge\", \"--ff-only\", \"FETCH_HEAD\"], { cwd });\n } catch (err) {\n throw wrapGitError(err, \"fast-forward merge\");\n }\n}\n\n/** Are there uncommitted changes (working tree or index) in this repo? */\nexport async function hasUncommittedChanges(cwd: string): Promise<boolean> {\n try {\n const { stdout } = await execa(\"git\", [\"status\", \"--porcelain\"], { cwd });\n return stdout.trim().length > 0;\n } catch {\n return false;\n }\n}\n\n/** Stash working-tree + untracked changes with a tagged message. */\nexport async function gitStash(cwd: string, message: string): Promise<void> {\n try {\n await execa(\n \"git\",\n [\"stash\", \"push\", \"--include-untracked\", \"--message\", message],\n { cwd },\n );\n } catch (err) {\n throw wrapGitError(err, \"stash push\");\n }\n}\n\n/** Pop the most recent stash. Throws on conflict so callers can surface it. */\nexport async function gitStashPop(cwd: string): Promise<void> {\n try {\n await execa(\"git\", [\"stash\", \"pop\"], { cwd });\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n const e = err as ExecaError;\n throw new GitError(\n \"Couldn't restore your local changes after pulling — the edits collided \" +\n \"with a teammate's. Run `git stash list` and resolve manually.\",\n e.exitCode ?? 1,\n );\n }\n}\n\n/** Read the current HEAD sha, or null if there is no commit yet. */\nexport async function getHeadSha(cwd: string): Promise<string | null> {\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"], { cwd });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Local-only state that must never reach a widget's provisioned repo.\n *\n * `.mist-desktop/` is Mist Desktop's per-machine working state for the\n * project directory it opened — chat transcripts, user attachments,\n * screenshots, source baselines, media cache. When Desktop drives\n * `fluid widget push`, that directory sits in the project root, so a\n * whole-tree `git add -A` publishes every private conversation.\n * `.mist` is the sibling clone/slug marker.\n *\n * Mirrors the portal CLI (`packages/cli/portal/src/lib/git.ts`) and the\n * Mist CLI (`packages/cli/mist/src/lib/git.ts`).\n */\nconst LOCAL_ONLY_GIT_PATHS = [\".mist\", \".mist-desktop/\"] as const;\n\n/**\n * Append {@link LOCAL_ONLY_GIT_PATHS} to `.git/info/exclude` when absent.\n *\n * Why the local exclude and not `.gitignore`: `.gitignore` ships from the\n * widget starter template, so editing it would never reach the clones\n * already on people's machines. `.git/info/exclude` is per-checkout, so\n * writing it on every sync heals a pre-existing clone on its next push.\n *\n * Idempotent and best-effort: never throws. {@link gitAutoCommit} also\n * cleans these paths out of the index after staging.\n */\nexport function excludeLocalStateFromGit(cwd: string): void {\n try {\n const gitDir = path.join(cwd, \".git\");\n if (!existsSync(gitDir)) return;\n const infoDir = path.join(gitDir, \"info\");\n if (!existsSync(infoDir)) mkdirSync(infoDir, { recursive: true });\n const excludePath = path.join(infoDir, \"exclude\");\n const existing = existsSync(excludePath)\n ? readFileSync(excludePath, \"utf8\")\n : \"\";\n const existingLines = new Set(\n existing\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean),\n );\n const missing = LOCAL_ONLY_GIT_PATHS.filter(\n (entry) => !existingLines.has(entry),\n );\n if (missing.length === 0) return;\n const needsLeadingNewline = existing.length > 0 && !existing.endsWith(\"\\n\");\n writeFileSync(\n excludePath,\n `${existing}${needsLeadingNewline ? \"\\n\" : \"\"}${missing.join(\"\\n\")}\\n`,\n \"utf8\",\n );\n } catch {\n // Best-effort — see doc comment.\n }\n}\n\n/**\n * Absolute path of the repository containing `cwd`, or `cwd` when\n * resolution fails. Every local-state defense anchors here: `git add -A`\n * stages the WHOLE repository, so a push run from a subdirectory would\n * otherwise look for `<subdir>/.git`, skip the exclude, and sweep the\n * root `.mist-desktop/` in anyway.\n */\nasync function resolveRepoRoot(cwd: string): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n });\n const root = stdout.trim();\n if (root.length > 0) return root;\n } catch {\n // Fall through to cwd.\n }\n return cwd;\n}\n\n/**\n * Repository-root-anchored {@link excludeLocalStateFromGit}. Run before\n * any working-tree cleanliness check: while `.mist-desktop/` is neither\n * tracked nor excluded it shows as untracked in `git status --porcelain`,\n * so a Desktop-driven push needlessly stashes/pops around a pull.\n */\nexport async function ensureLocalStateExcluded(cwd: string): Promise<void> {\n excludeLocalStateFromGit(await resolveRepoRoot(cwd));\n}\n\nexport interface GitCommitIdentity {\n readonly name: string;\n readonly email: string;\n}\n\n/** Paths currently tracked under `.mist-desktop/`, or [] when none. */\nasync function trackedLocalStatePaths(repoRoot: string): Promise<string[]> {\n try {\n const { stdout } = await execa(\"git\", [\"ls-files\", \"--\", \".mist-desktop\"], {\n cwd: repoRoot,\n });\n return stdout.split(\"\\n\").filter((l) => l.trim().length > 0);\n } catch {\n return [];\n }\n}\n\n/**\n * Untrack private Mist Desktop state and, if anything was tracked,\n * commit ONLY that removal so the next push deletes it from the remote.\n * Returns true when a purge commit was made.\n *\n * Must run regardless of working-tree cleanliness AND of `--no-commit`:\n * an older CLI could have committed chats to a checkout that is now\n * clean, and gating on either would skip the cleanup forever, leaving\n * the chats published.\n *\n * The commit is built through a THROWAWAY index (`GIT_INDEX_FILE`), not\n * the user's: `read-tree HEAD` → `rm --cached` → `write-tree` →\n * `commit-tree` → `update-ref`. A plain `git commit` would capture the\n * user's entire index, so anything they had pre-staged would be swept\n * into the purge commit and pushed — the exact thing `--no-commit`\n * exists to prevent. A pathspec commit (`git commit -- .mist-desktop`)\n * is also wrong: with `--only` git takes the *working tree* content of\n * those paths, and the chats are still on disk, so it would re-add\n * exactly what we are removing.\n *\n * The user's real index then gets the same scoped `rm --cached`, so any\n * other staged work stays staged and the working tree is never touched.\n */\nexport async function purgeLocalStateFromIndex(\n cwd: string,\n message: string,\n identity: GitCommitIdentity = DEFAULT_COMMIT_IDENTITY,\n): Promise<boolean> {\n const repoRoot = await resolveRepoRoot(cwd);\n if ((await trackedLocalStatePaths(repoRoot)).length === 0) return false;\n\n let head: string;\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: repoRoot,\n });\n head = stdout.trim();\n if (!head) return false;\n } catch {\n return false;\n }\n\n const tmpIndex = path.join(\n os.tmpdir(),\n `fluid-widget-purge-${process.pid}-${randomUUID()}.index`,\n );\n const indexEnv = { ...process.env, GIT_INDEX_FILE: tmpIndex };\n let commitSha: string;\n try {\n await execa(\"git\", [\"read-tree\", head], { cwd: repoRoot, env: indexEnv });\n await execa(\n \"git\",\n [\"rm\", \"-q\", \"-r\", \"--cached\", \"--ignore-unmatch\", \"--\", \".mist-desktop\"],\n { cwd: repoRoot, env: indexEnv },\n );\n const { stdout: tree } = await execa(\"git\", [\"write-tree\"], {\n cwd: repoRoot,\n env: indexEnv,\n });\n const { stdout: sha } = await execa(\n \"git\",\n [\"commit-tree\", tree.trim(), \"-p\", head, \"-m\", message],\n {\n cwd: repoRoot,\n env: { ...indexEnv, ...(await identityEnv(repoRoot, identity)) },\n },\n );\n commitSha = sha.trim();\n if (!commitSha) return false;\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n throw wrapGitError(err, \"purge local state\");\n } finally {\n rmSync(tmpIndex, { force: true });\n }\n\n try {\n await execa(\"git\", [\"update-ref\", \"HEAD\", commitSha, head], {\n cwd: repoRoot,\n });\n } catch (err) {\n throw wrapGitError(err, \"purge local state\");\n }\n try {\n await execa(\n \"git\",\n [\"rm\", \"-q\", \"-r\", \"--cached\", \"--ignore-unmatch\", \"--\", \".mist-desktop\"],\n { cwd: repoRoot },\n );\n } catch {\n // Non-fatal: HEAD is already correct, so the push ships the removal.\n }\n return true;\n}\n\n/** `GIT_{AUTHOR,COMMITTER}_*` overrides for `commit-tree`, which (unlike\n * `git commit`) fails outright rather than prompting when the repo has\n * no identity. Only set what the repo itself doesn't define. */\nasync function identityEnv(\n cwd: string,\n identity: GitCommitIdentity,\n): Promise<NodeJS.ProcessEnv> {\n const env: NodeJS.ProcessEnv = {};\n const has = async (key: string): Promise<boolean> => {\n try {\n const r = await execa(\"git\", [\"config\", key], { cwd });\n return r.stdout.trim().length > 0;\n } catch {\n return false;\n }\n };\n if (!(await has(\"user.name\"))) {\n env[\"GIT_AUTHOR_NAME\"] = identity.name;\n env[\"GIT_COMMITTER_NAME\"] = identity.name;\n }\n if (!(await has(\"user.email\"))) {\n env[\"GIT_AUTHOR_EMAIL\"] = identity.email;\n env[\"GIT_COMMITTER_EMAIL\"] = identity.email;\n }\n return env;\n}\n\n/** Shared `-c user.*` args: prefer the repo's configured identity, else\n * the supplied synthetic one so the commit isn't rejected. */\nasync function resolveIdentityArgs(\n cwd: string,\n identity: GitCommitIdentity,\n): Promise<string[]> {\n let hasName = false;\n let hasEmail = false;\n try {\n const r = await execa(\"git\", [\"config\", \"user.name\"], { cwd });\n hasName = r.stdout.trim().length > 0;\n } catch {\n // exit 1 from `git config <key>` just means the key is unset.\n }\n try {\n const r = await execa(\"git\", [\"config\", \"user.email\"], { cwd });\n hasEmail = r.stdout.trim().length > 0;\n } catch {\n // ditto.\n }\n return [\n ...(hasName ? [] : [\"-c\", `user.name=${identity.name}`]),\n ...(hasEmail ? [] : [\"-c\", `user.email=${identity.email}`]),\n ];\n}\n\nconst DEFAULT_COMMIT_IDENTITY: GitCommitIdentity = {\n name: \"Fluid CLI\",\n email: \"cli@fluid.app\",\n};\n\n/**\n * `git add -A && git commit -m <message>` in `cwd`.\n *\n * The widget \"push\" UX is \"ship my changes\" — the user shouldn't need to know\n * about staging or commit messages. This bundles working-tree edits into one\n * commit per push. If the repo has no configured user.name / user.email we\n * pass a synthetic identity so the commit isn't rejected. \"nothing to commit\"\n * is treated as a no-op rather than an error.\n *\n * Scope: `add -A` stages the whole work tree, bounded by the project\n * `.gitignore` — which can't cover tool-local state written INTO the\n * project by whatever opened it (Mist Desktop's `.mist-desktop/` chats and\n * the `.mist` marker). Belt and suspenders, all repo-root-anchored:\n *\n * 1. {@link excludeLocalStateFromGit} — idempotent `.git/info/exclude`\n * write so `git add` never sees the paths. Heals old clones.\n * 2. `git reset -- ':(top).mist' .mist` — unstages the marker if step 1\n * silently failed. We deliberately do NOT pass `:(exclude)` to\n * `git add`: when the path is also in `.git/info/exclude`, git exits\n * 1 with \"paths are ignored by one of your .gitignore files\", which\n * would turn the already-healed case into a hard failure.\n * 3. `git rm --cached -r --ignore-unmatch .mist-desktop` — untracks\n * chats an older push already committed (ignore rules can't untrack).\n * `--cached` keeps every file on disk.\n *\n * Steps 2 and 3 are best-effort and never fail the push.\n */\n/**\n * The staged file set, as {@link ChangeEntry}s — the input a\n * {@link CommitMessage} resolver summarizes.\n *\n * `-z` (NUL-delimited) rather than the default: paths with spaces or\n * quotes are legal in git and common in themes and asset folders, and\n * the newline form quotes and escapes them, which would corrupt both the\n * path and the count.\n *\n * Best-effort — a summary is a nicety, never a reason to fail a publish.\n * An empty result makes the resolver fall back to its own constant.\n */\nasync function stagedChanges(cwd: string): Promise<ChangeEntry[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"diff\", \"--cached\", \"--name-status\", \"-z\"],\n { cwd },\n );\n return parseNameStatusZ(stdout);\n } catch {\n return [];\n }\n}\n\nexport async function gitAutoCommit(\n cwd: string,\n message: CommitMessage,\n identity: GitCommitIdentity = DEFAULT_COMMIT_IDENTITY,\n): Promise<void> {\n const repoRoot = await resolveRepoRoot(cwd);\n excludeLocalStateFromGit(repoRoot);\n\n try {\n await execa(\"git\", [\"add\", \"-A\"], { cwd });\n } catch (err) {\n throw wrapGitError(err, \"add\");\n }\n\n try {\n await execa(\"git\", [\"reset\", \"-q\", \"--\", \":(top).mist\", \".mist\"], { cwd });\n } catch {\n // Non-fatal — see doc comment.\n }\n try {\n await execa(\n \"git\",\n [\"rm\", \"-q\", \"-r\", \"--cached\", \"--ignore-unmatch\", \"--\", \".mist-desktop\"],\n { cwd: repoRoot },\n );\n } catch {\n // Non-fatal — the exclude file remains the primary defense.\n }\n\n // Resolve the subject only now: everything above decides what is\n // actually staged, so a summary built any earlier would describe a\n // file set the commit doesn't carry.\n const subject =\n typeof message === \"string\"\n ? message\n : await message(await stagedChanges(cwd));\n const identityArgs = await resolveIdentityArgs(cwd, identity);\n\n try {\n await execa(\"git\", [...identityArgs, \"commit\", \"-m\", subject], {\n cwd,\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n } catch (err) {\n const missing = gitMissingError(err);\n if (missing) throw missing;\n const e = err as ExecaError;\n if (typeof e.stderr === \"string\" && /nothing to commit/i.test(e.stderr)) {\n return;\n }\n throw wrapGitError(err, \"commit\");\n }\n}\n","import type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport { fluidOsV0WidgetPackageGitCredentialCreate } from \"@fluid-app/fluidos-api-client/sdk\";\n\n/**\n * A short-lived (~1h) credentialed git remote URL minted by the backend. The\n * `remoteUrl` embeds an installation token and must never be logged,\n * persisted, or written to `.git/config` — hand it straight to the git helpers\n * in `../lib/git.js`, which strip the token off argv via GIT_ASKPASS.\n */\nexport interface WidgetGitCredential {\n readonly remoteUrl: string;\n readonly expiresAt: string | null;\n}\n\ninterface GitCredentialResponse {\n readonly git_credential?: {\n readonly remote_url?: unknown;\n readonly expires_at?: unknown;\n };\n}\n\nexport interface MintWidgetGitCredentialOptions {\n readonly client: FluidOsHeyApiClient;\n /**\n * Droplet UUID that owns the widget package. When provided we mint against\n * the droplet-scoped endpoint; otherwise we mint against the company-owned\n * widget package endpoint.\n */\n readonly droplet?: string;\n}\n\nfunction unwrapResponseData(response: unknown): unknown {\n if (\n response !== null &&\n typeof response === \"object\" &&\n \"data\" in response &&\n !(\"git_credential\" in response)\n ) {\n return response.data;\n }\n return response;\n}\n\n/**\n * Mint a git credential for a widget package.\n *\n * Backend endpoints:\n * - droplet-owned: POST /api/droplets/:uuid/widget_package/git_credential\n * - company-owned: POST /api/company/fluid_os/widget_package/git_credential\n * Both respond `{ git_credential: { remote_url, expires_at } }`.\n *\n * The raw droplet-scoped call must pass `security` — the hey-api runtime only\n * attaches the bearer token when a request declares it (generated SDK\n * functions do; a bare `client.post` does not, and the request goes out\n * unauthenticated → 401 \"Invalid credentials\").\n *\n * Throws the underlying `ApiError` (with `.status`) on failure so callers can\n * decide whether to degrade gracefully (see `isGitSyncUnavailable`).\n */\nexport async function mintWidgetGitCredential(\n options: MintWidgetGitCredentialOptions,\n): Promise<WidgetGitCredential> {\n const rawResponse = options.droplet\n ? await options.client.post({\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: `/api/droplets/${encodeURIComponent(options.droplet)}/widget_package/git_credential`,\n })\n : await fluidOsV0WidgetPackageGitCredentialCreate({\n client: options.client,\n responseStyle: \"data\",\n });\n const response = unwrapResponseData(rawResponse) as GitCredentialResponse;\n const remoteUrl = response?.git_credential?.remote_url;\n if (typeof remoteUrl !== \"string\" || remoteUrl.length === 0) {\n throw new Error(\n \"The git credential response did not include a remote URL. \" +\n \"Update the Fluid CLI, or contact support if this persists.\",\n );\n }\n const expiresAtRaw = response.git_credential?.expires_at;\n return {\n remoteUrl,\n expiresAt: typeof expiresAtRaw === \"string\" ? expiresAtRaw : null,\n };\n}\n\n/**\n * Sanitize a package key the same way the backend does when naming the repo\n * (`GitSync::Provisioner`): GitHub's repo-name alphabet is `[A-Za-z0-9._-]`,\n * so every other character (including the `~` allowed in package keys) becomes\n * a hyphen. Lets us compare a requested key against the minted repo name.\n */\nexport function sanitizeWidgetPackageKey(key: string): string {\n return key.replace(/[^A-Za-z0-9._-]/g, \"-\");\n}\n\n/**\n * Extract the sanitized package key from a minted widget remote URL. The\n * backend names repos `widget-<sanitized package_key>-<widget_package id>`, so\n * `https://x-access-token:tok@github.com/org/widget-reviews-42.git` → `reviews`.\n * Returns null when the URL doesn't match that shape (never throws; the token\n * in the URL is never logged — only the pathname is read).\n */\nexport function widgetRepoKeyFromRemoteUrl(remoteUrl: string): string | null {\n try {\n const name = new URL(remoteUrl).pathname\n .split(\"/\")\n .pop()\n ?.replace(/\\.git$/, \"\");\n const match = name?.match(/^widget-(.+)-\\d+$/);\n return match?.[1] ?? null;\n } catch {\n return null;\n }\n}\n\n/** Best-effort read of an HTTP status off an unknown thrown error. */\nexport function getErrorStatus(err: unknown): number | undefined {\n if (err && typeof err === \"object\" && \"status\" in err) {\n const status = (err as { status?: unknown }).status;\n if (typeof status === \"number\") return status;\n }\n return undefined;\n}\n\n/**\n * Should a git-credential failure degrade to \"publish artifacts only\" rather\n * than abort? True when there is no repository to sync with yet: the widget\n * package record does not exist (404), or it exists but its `GitSync` repo has\n * not been created and connected (409). Other statuses (auth, 5xx) are genuine\n * errors the caller may still choose to treat as best-effort.\n */\nexport function isGitSyncUnavailable(err: unknown): boolean {\n const status = getErrorStatus(err);\n return status === 404 || status === 409;\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * `.fluid-widget` marker file — written by `fluid widget clone` so future\n * commands (and Mist Desktop) can identify a checked-out widget package repo\n * and know which owner to mint git credentials against. Mirrors Mist's `.mist`\n * marker (which records slug / vendor_name).\n */\nexport const WIDGET_MARKER_FILE = \".fluid-widget\";\n\nexport interface WidgetMarker {\n readonly package_key: string;\n /** Droplet UUID when the package is droplet-owned; omitted for company-owned. */\n readonly droplet?: string;\n}\n\nexport function resolveWidgetMarkerPath(dir: string): string {\n return path.join(dir, WIDGET_MARKER_FILE);\n}\n\nexport function writeWidgetMarker(dir: string, marker: WidgetMarker): void {\n const payload: WidgetMarker = marker.droplet\n ? { package_key: marker.package_key, droplet: marker.droplet }\n : { package_key: marker.package_key };\n writeFileSync(\n resolveWidgetMarkerPath(dir),\n JSON.stringify(payload, null, 2) + \"\\n\",\n \"utf8\",\n );\n}\n\nexport function readWidgetMarker(dir: string): WidgetMarker | null {\n const filePath = resolveWidgetMarkerPath(dir);\n if (!existsSync(filePath)) return null;\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf8\")) as unknown;\n if (!parsed || typeof parsed !== \"object\") return null;\n const obj = parsed as Record<string, unknown>;\n const packageKey = obj[\"package_key\"];\n if (typeof packageKey !== \"string\" || packageKey.length === 0) return null;\n const droplet = obj[\"droplet\"];\n return {\n package_key: packageKey,\n ...(typeof droplet === \"string\" && droplet.length > 0 ? { droplet } : {}),\n };\n } catch {\n return null;\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { ensureGitAvailable, gitClone } from \"../lib/git.js\";\nimport {\n isGitSyncUnavailable,\n mintWidgetGitCredential,\n sanitizeWidgetPackageKey,\n widgetRepoKeyFromRemoteUrl,\n} from \"../utils/git-credential.js\";\nimport { validateDropletUuid } from \"../utils/config.js\";\nimport { writeWidgetMarker } from \"../utils/widget-marker.js\";\nimport {\n getInstallCommand,\n installDependencies,\n} from \"../utils/package-manager.js\";\n\nexport interface CloneCommandOptions {\n readonly droplet?: string;\n readonly dir?: string;\n readonly skipInstall?: boolean;\n}\n\nexport const cloneCommand: Command = new Command(\"clone\")\n .description(\n \"Clone a widget package's git repository (mints a fresh token per call)\",\n )\n .argument(\"<package>\", \"Widget package key to clone\")\n .option(\n \"--droplet <uuid>\",\n \"Droplet UUID that owns the package (defaults to the company-owned package)\",\n )\n .option(\"--dir <dir>\", \"Target directory (defaults to ./<package>/)\")\n .option(\"--skip-install\", \"Skip dependency installation\")\n .action((packageKey: string, options: CloneCommandOptions) =>\n runCliAction(async () => {\n const trimmedPackage = packageKey.trim();\n if (!trimmedPackage) throw new Error(\"A widget package key is required.\");\n\n const droplet = options.droplet?.trim();\n if (droplet) {\n const dropletError = validateDropletUuid(droplet);\n if (dropletError) throw new Error(dropletError);\n }\n\n // Clone is a pure git operation — fail fast with an actionable message\n // when git isn't installed rather than partway through.\n await ensureGitAvailable();\n\n const targetDir = path.resolve(options.dir ?? trimmedPackage);\n if (existsSync(targetDir)) {\n throw new Error(\n `Directory ${targetDir} already exists. Pass --dir or remove it first.`,\n );\n }\n\n // The credential endpoints are scoped to an *owner*, not a package key:\n // a company (or droplet) has exactly one widget package, so the backend\n // resolves the repo from the authenticated company / the droplet uuid —\n // there is no package-key selector to send. `<package>` is therefore a\n // local label used for the target directory name and the `.fluid-widget`\n // marker, mirroring how `fluid mist clone` names by vendor_name.\n const client = createAuthenticatedWidgetPackageClient();\n const spinner = ora(\"Minting git credential…\").start();\n let remoteUrl: string;\n try {\n const cred = await mintWidgetGitCredential({\n client,\n ...(droplet ? { droplet } : {}),\n });\n remoteUrl = cred.remoteUrl;\n } catch (err) {\n spinner.fail(\"Couldn't mint a git credential\");\n if (isGitSyncUnavailable(err)) {\n throw new Error(\n \"Widget git sync isn't available for this package yet. \" +\n \"Publish the package first, or try again once git sync is enabled.\",\n );\n }\n throw err;\n }\n\n // The owner determines the repo, so guard against a requested key that\n // disagrees with what was actually minted — otherwise we'd clone one\n // repo but stamp the marker with a different package name, leaving future\n // push/publish acting on a checkout whose marker and source disagree.\n const mintedKey = widgetRepoKeyFromRemoteUrl(remoteUrl);\n if (!mintedKey) {\n // Fail closed: an unparseable repo name means we can't prove the\n // checkout matches the requested key, and a wrong marker would leave\n // future push/publish acting on the wrong package.\n spinner.fail(\"Couldn't verify the owner's widget repository\");\n throw new Error(\n \"The minted git repository URL did not match the expected widget \" +\n \"repository format, so the CLI cannot safely write a package \" +\n \"marker. Update the Fluid CLI, or contact support if this persists.\",\n );\n }\n if (mintedKey !== sanitizeWidgetPackageKey(trimmedPackage)) {\n spinner.fail(\"Requested package does not match the owner's repository\");\n throw new Error(\n `The ${droplet ? \"droplet\" : \"company\"}'s widget package is ` +\n `\"${mintedKey}\", not \"${trimmedPackage}\". Re-run with the correct ` +\n `package key (or --droplet), so the checkout and its marker agree.`,\n );\n }\n\n spinner.text = `Cloning into ${path.basename(targetDir)}/…`;\n try {\n // Token-bearing URL is passed inline only — never written to .git/config.\n await gitClone(remoteUrl, targetDir);\n } catch (err) {\n spinner.fail(\"git clone failed\");\n throw err;\n }\n\n // Drop a `.fluid-widget` marker so future commands (and Mist Desktop)\n // know the owner without re-parsing config.\n writeWidgetMarker(targetDir, {\n package_key: trimmedPackage,\n ...(droplet ? { droplet } : {}),\n });\n\n spinner.succeed(`Cloned into ${chalk.cyan(targetDir)}`);\n\n // A cloned checkout is unrunnable until dependencies land (`widget dev`\n // needs the project's own Vite) — install here like `create` does so\n // clone-then-run works without a manual step in between.\n const installCommand = getInstallCommand(targetDir);\n if (options.skipInstall !== true) {\n spinner.start(`Installing dependencies with ${installCommand}...`);\n try {\n await installDependencies(targetDir);\n spinner.succeed(\"Installed dependencies\");\n } catch {\n spinner.fail(\"Failed to install dependencies\");\n console.log();\n console.log(chalk.yellow(\"You can install dependencies manually:\"));\n console.log(chalk.cyan(` ${installCommand}`));\n }\n }\n\n console.log(\n chalk.dim(` cd ${path.relative(process.cwd(), targetDir) || \".\"}`),\n );\n if (options.skipInstall === true) {\n console.log(chalk.dim(` ${installCommand}`));\n }\n }),\n );\n","import { cp, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { ensureGitAvailable, gitClone } from \"../lib/git.js\";\n\n/**\n * The canonical widget starter lives on GitHub so widget projects share the\n * same \"invisible git\" collaboration model Mist apps have. It is an explicit\n * opt-in for `fluid widget create`; the bundled template is the default.\n */\nexport const DEFAULT_WIDGET_TEMPLATE_REPO_URL =\n \"https://github.com/Fluid-WeCommerce/widget-template.git\";\n\n/**\n * The template repo to clone. Overridable via `FLUID_WIDGET_TEMPLATE_REPO`\n * (read at call time so tests can point at a local repo). Falls back to the\n * canonical GitHub template.\n */\nexport function widgetTemplateRepoUrl(): string {\n return (\n process.env[\"FLUID_WIDGET_TEMPLATE_REPO\"] ??\n DEFAULT_WIDGET_TEMPLATE_REPO_URL\n );\n}\n\n/**\n * The defaults baked into the GitHub template's rendered files. `create`\n * rewrites these to the user's chosen values after cloning. Keep in sync with\n * `scripts/render-template-repo.mts`.\n */\nexport const TEMPLATE_DEFAULTS = {\n projectName: \"my-widget\",\n widgetScope: \"droplet\",\n widgetPackageVersion: \"0.1.0\",\n} as const;\n\nexport interface GithubTemplateVariables {\n readonly projectName: string;\n readonly widgetScope: string;\n readonly widgetPackageVersion: string;\n}\n\n/**\n * Clone the GitHub widget template into `targetPath`, strip its git history,\n * and rewrite the baked defaults to the user's values. The repo holds a fully\n * rendered project (no `{{placeholders}}`), so we do targeted, deterministic\n * replacements of the known defaults rather than template interpolation.\n *\n * Returns true on success. Returns false (never throws) when the template\n * couldn't be fetched — git missing, offline, repo unavailable. The caller\n * reports that requested-template failure. The partially-cloned target is\n * cleaned up before returning false.\n */\nexport async function tryFetchGithubTemplate(\n targetPath: string,\n variables: GithubTemplateVariables,\n): Promise<boolean> {\n let tempDir: string | undefined;\n try {\n await ensureGitAvailable();\n tempDir = await mkdtemp(path.join(os.tmpdir(), \"fluid-widget-template-\"));\n const clonePath = path.join(tempDir, \"template\");\n await gitClone(widgetTemplateRepoUrl(), clonePath, {\n depth: 1,\n branch: \"main\",\n silent: true,\n });\n\n // Strip git history: generate-from-template semantics — the new project\n // gets its own (invisible) repo later via `fluid widget push`.\n await rm(path.join(clonePath, \".git\"), { recursive: true, force: true });\n\n await cp(clonePath, targetPath, { recursive: true });\n await applyTemplateRenames(targetPath, variables);\n return true;\n } catch {\n // Any failure → clean up and let the caller report the opt-in failure.\n await rm(targetPath, { recursive: true, force: true }).catch(() => {});\n return false;\n } finally {\n if (tempDir)\n await rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Rewrite the template's baked defaults (project name, scope, version) to the\n * user's chosen values across the small set of files that reference them.\n * Missing files are skipped — the template can evolve without breaking this.\n */\nasync function applyTemplateRenames(\n targetPath: string,\n variables: GithubTemplateVariables,\n): Promise<void> {\n const { projectName, widgetScope, widgetPackageVersion } = variables;\n\n await replaceInFile(path.join(targetPath, \"package.json\"), [\n [\n `\"name\": ${JSON.stringify(TEMPLATE_DEFAULTS.projectName)}`,\n `\"name\": ${JSON.stringify(projectName)}`,\n ],\n ]);\n\n await replaceInFile(path.join(targetPath, \"index.html\"), [\n [\n `<title>${TEMPLATE_DEFAULTS.projectName}</title>`,\n `<title>${projectName}</title>`,\n ],\n ]);\n\n await replaceInFile(path.join(targetPath, \"README.md\"), [\n [`# ${TEMPLATE_DEFAULTS.projectName}\\n`, `# ${projectName}\\n`],\n ]);\n\n await replaceInFile(path.join(targetPath, \"manifest.ts\"), [\n [\n `scope: ${JSON.stringify(TEMPLATE_DEFAULTS.widgetScope)},`,\n `scope: ${JSON.stringify(widgetScope)},`,\n ],\n [\n `version: ${JSON.stringify(TEMPLATE_DEFAULTS.widgetPackageVersion)},`,\n `version: ${JSON.stringify(widgetPackageVersion)},`,\n ],\n ]);\n}\n\n/**\n * Replace the first occurrence of each `[from, to]` pair in a file. No-op when\n * `from` isn't present (or `from === to`), so re-running is harmless and an\n * unchanged default (e.g. scope already \"droplet\") isn't a failure.\n */\nasync function replaceInFile(\n filePath: string,\n replacements: ReadonlyArray<readonly [string, string]>,\n): Promise<void> {\n if (!existsSync(filePath)) return;\n let content = await readFile(filePath, \"utf8\");\n let changed = false;\n for (const [from, to] of replacements) {\n if (from === to) continue;\n const index = content.indexOf(from);\n if (index === -1) continue;\n content = content.slice(0, index) + to + content.slice(index + from.length);\n changed = true;\n }\n if (changed) await writeFile(filePath, content, \"utf8\");\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport path from \"node:path\";\nimport type { WidgetCreateOptions } from \"../types.js\";\nimport {\n copyWidgetTemplate,\n directoryExists,\n getCliVersion,\n getDefaultTemplatePath,\n getPortalCoreVersion,\n getPortalSdkVersion,\n getWidgetCliVersion,\n} from \"../utils/template.js\";\nimport {\n getInstallCommand,\n getRunCommand,\n installDependencies,\n} from \"../utils/package-manager.js\";\nimport {\n mergeWidgetConfig,\n validateDropletUuid,\n writeWidgetConfig,\n} from \"../utils/config.js\";\nimport { tryFetchGithubTemplate } from \"../utils/github-template.js\";\n\nconst DEFAULT_WIDGET_PACKAGE_VERSION = \"0.1.0\";\nconst DEFAULT_WIDGET_SCOPE = \"droplet\";\n\nexport interface CreateWidgetProjectDependencies {\n readonly installDependencies: typeof installDependencies;\n readonly tryFetchGithubTemplate: typeof tryFetchGithubTemplate;\n}\n\nconst defaultCreateWidgetProjectDependencies = {\n installDependencies,\n tryFetchGithubTemplate,\n} satisfies CreateWidgetProjectDependencies;\n\nexport const createCommand: Command = new Command(\"create\")\n .description(\"Create a standalone Fluid widget project\")\n .argument(\"<project-name>\", \"Name of the widget project to create\")\n .option(\n \"--skip-install\",\n \"Create the scaffold only; skip dependency installation\",\n )\n .option(\n \"-o, --output-dir <dir>\",\n \"Directory to create the project in (defaults to cwd)\",\n )\n .option(\n \"--scope <scope>\",\n \"Widget package scope/namespace\",\n DEFAULT_WIDGET_SCOPE,\n )\n .option(\n \"--package-version <version>\",\n \"Initial widget package version\",\n DEFAULT_WIDGET_PACKAGE_VERSION,\n )\n .option(\n \"--local\",\n \"Use local monorepo packages via link: paths (for development testing)\",\n )\n .option(\n \"--remote-template\",\n \"Use the GitHub starter template instead of the bundled template\",\n )\n .option(\"--droplet <uuid>\", \"Existing droplet UUID that owns the package\")\n .action(async (projectName: string, options: WidgetCreateOptions) => {\n try {\n await createWidgetProject(projectName, options);\n } catch (err) {\n console.log();\n console.error(\n chalk.red(\"Error:\") +\n \" \" +\n (err instanceof Error ? err.message : String(err)),\n );\n console.log();\n process.exit(1);\n }\n });\n\nexport async function createWidgetProject(\n projectName: string,\n options: WidgetCreateOptions,\n dependencies: CreateWidgetProjectDependencies = defaultCreateWidgetProjectDependencies,\n): Promise<void> {\n console.log();\n console.log(chalk.bold(\"Creating a new Fluid widget project\"));\n console.log();\n\n const projectNameError = validateProjectName(projectName);\n if (projectNameError) throw new Error(projectNameError);\n\n const droplet = options.droplet?.trim();\n if (droplet) {\n const dropletError = validateDropletUuid(droplet);\n if (dropletError) throw new Error(dropletError);\n }\n\n const outputDir = path.resolve(options.outputDir ?? process.cwd());\n const targetPath = path.join(outputDir, projectName);\n if (await directoryExists(targetPath)) {\n throw new Error(`Directory already exists: ${targetPath}`);\n }\n\n const templatePath = getDefaultTemplatePath();\n if (\n options.remoteTemplate !== true &&\n !(await directoryExists(templatePath))\n ) {\n throw new Error(\"Default widget template not found.\");\n }\n\n const config = mergeWidgetConfig({}, { droplet });\n const widgetScope = options.scope ?? DEFAULT_WIDGET_SCOPE;\n const localOptions = { local: options.local === true };\n const variables = {\n projectName,\n droplet: config.droplet,\n widgetScope,\n widgetPackageVersion:\n options.packageVersion ?? DEFAULT_WIDGET_PACKAGE_VERSION,\n sdkVersion: await getPortalSdkVersion(localOptions),\n localCoreVersion: options.local\n ? await getPortalCoreVersion(localOptions)\n : undefined,\n fluidCliVersion: await getCliVersion(localOptions),\n widgetCliVersion: await getWidgetCliVersion(localOptions),\n };\n\n if (options.local === true && options.remoteTemplate === true) {\n throw new Error(\"--remote-template cannot be combined with --local\");\n }\n\n // The bundled template is the deterministic default. The mutable GitHub\n // mirror is available only through an explicit opt-in and never silently\n // replaces or falls back to a different schema.\n const useRemoteTemplate = options.remoteTemplate === true;\n\n let scaffolded = false;\n if (useRemoteTemplate) {\n const remoteSpinner = ora(\n \"Fetching widget template from GitHub...\",\n ).start();\n scaffolded = await dependencies.tryFetchGithubTemplate(targetPath, {\n projectName,\n widgetScope,\n widgetPackageVersion:\n options.packageVersion ?? DEFAULT_WIDGET_PACKAGE_VERSION,\n });\n if (scaffolded) {\n remoteSpinner.succeed(\"Fetched widget template from GitHub\");\n } else {\n remoteSpinner.fail(\"Failed to fetch the GitHub widget template\");\n throw new Error(\n \"Couldn't fetch the requested GitHub template. Remove --remote-template to use the bundled template.\",\n );\n }\n }\n\n const spinner = ora(\n scaffolded ? \"Finalizing widget project...\" : \"Copying widget template...\",\n ).start();\n try {\n if (!scaffolded) {\n await copyWidgetTemplate(templatePath, targetPath, variables);\n }\n await writeWidgetConfig(targetPath, config);\n spinner.succeed(\n scaffolded ? \"Prepared widget project\" : \"Copied widget template\",\n );\n } catch (err) {\n spinner.fail(\"Failed to create widget project\");\n throw err;\n }\n\n const installCommand = getInstallCommand(targetPath);\n if (options.skipInstall !== true) {\n spinner.start(`Installing dependencies with ${installCommand}...`);\n try {\n await dependencies.installDependencies(targetPath);\n spinner.succeed(\"Installed dependencies\");\n } catch (error) {\n spinner.fail(\"Failed to install dependencies\");\n console.log();\n console.log(chalk.yellow(`The scaffold was retained at ${targetPath}.`));\n console.log(chalk.yellow(\"Install dependencies manually to continue:\"));\n console.log(chalk.cyan(` cd ${formatCdPath(targetPath)}`));\n console.log(chalk.cyan(` ${installCommand}`));\n throw error;\n }\n }\n\n console.log();\n if (options.skipInstall === true) {\n console.log(\n chalk.yellow(\n \"Scaffold only: dependencies were not installed and must be installed before development.\",\n ),\n );\n console.log();\n }\n console.log(\n chalk.green.bold(\"Success!\") + ` Created ${chalk.cyan(projectName)}`,\n );\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.cyan(` cd ${formatCdPath(targetPath)}`));\n if (options.skipInstall === true) {\n console.log(chalk.cyan(` ${installCommand}`));\n }\n if (!config.droplet) {\n console.log(chalk.cyan(\" fluid widget link\"));\n }\n console.log(chalk.cyan(` ${getRunCommand(\"dev\", targetPath)}`));\n console.log();\n console.log(\n \"Edit \" + chalk.cyan(\"manifest.ts\") + \" to customize your widget package.\",\n );\n console.log(\n chalk.dim(\n \"This command only creates local project files; it does not create a droplet.\",\n ),\n );\n console.log();\n}\n\nfunction validateProjectName(projectName: string): string | undefined {\n if (!projectName) return \"Project name is required.\";\n if (!/^[a-z0-9][a-z0-9-]*$/.test(projectName)) {\n return \"Project name must contain only lowercase letters, numbers, and hyphens.\";\n }\n return undefined;\n}\n\nfunction formatCdPath(targetPath: string): string {\n return path.relative(process.cwd(), targetPath) || \".\";\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { runCliAction } from \"../utils/command.js\";\nimport {\n getInstallCommand,\n installDependencies,\n} from \"../utils/package-manager.js\";\n\nexport const DEFAULT_WIDGET_DEV_PORT = 5174;\n\nexport const WIDGET_DEV_ROUTES = [\n \"/__widget-packages__\",\n \"/__runtime-entry__\",\n] as const;\n\nexport interface WidgetDevOptions {\n readonly port?: string;\n readonly host?: boolean | string;\n readonly mode?: string;\n}\n\nexport interface WidgetDevProjectSummary {\n readonly projectDir: string;\n readonly packageName: string;\n readonly viteConfigPath: string;\n readonly localUrl: string;\n readonly target: string;\n readonly mode: string;\n readonly routes: readonly string[];\n}\n\nexport const devCommand: Command = new Command(\"dev\")\n .description(\"Start the local Fluid widget development endpoints\")\n .option(\n \"-p, --port <port>\",\n \"Port to run the widget dev server on\",\n String(DEFAULT_WIDGET_DEV_PORT),\n )\n .option(\"--host [host]\", \"Expose the dev server to the network\")\n .option(\"--mode <mode>\", \"Vite mode to run\", \"development\")\n .action((options: WidgetDevOptions) => {\n return runCliAction(async () => {\n const projectDir = process.cwd();\n const summary = await resolveWidgetDevProject(projectDir, options);\n\n printWidgetDevSummary(summary);\n await runViteDevServer(projectDir, options);\n });\n });\n\nexport async function resolveWidgetDevProject(\n projectDir: string,\n options: WidgetDevOptions = {},\n): Promise<WidgetDevProjectSummary> {\n const resolvedProjectDir = path.resolve(projectDir);\n const packageJsonPath = path.join(resolvedProjectDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n throw new Error(\n \"No package.json found. Run this command from a Fluid widget project directory.\",\n );\n }\n\n const packageJson = await readPackageJson(packageJsonPath);\n const packageName = readPackageName(packageJson) ?? path.basename(projectDir);\n\n const viteConfigPath = path.join(resolvedProjectDir, \"vite.config.ts\");\n if (!existsSync(viteConfigPath)) {\n throw new Error(\n \"No vite.config.ts found. Run this command from a Fluid widget project directory.\",\n );\n }\n\n const port = parsePort(options.port ?? String(DEFAULT_WIDGET_DEV_PORT));\n const host = normalizeHostOption(options.host);\n const mode = normalizeMode(options.mode);\n\n return {\n projectDir: resolvedProjectDir,\n packageName,\n viteConfigPath,\n localUrl: formatLocalUrl(port, host),\n target: packageName,\n mode,\n routes: WIDGET_DEV_ROUTES,\n };\n}\n\nexport function buildViteDevArgs(options: WidgetDevOptions = {}): string[] {\n const port = parsePort(options.port ?? String(DEFAULT_WIDGET_DEV_PORT));\n const host = normalizeHostOption(options.host);\n const mode = normalizeMode(options.mode);\n const args = [\"--port\", String(port), \"--mode\", mode];\n\n if (host) {\n args.push(\"--host\", host);\n }\n\n return args;\n}\n\nexport function printWidgetDevSummary(summary: WidgetDevProjectSummary): void {\n console.log();\n console.log(chalk.blue.bold(\"Fluid Widget Dev\"));\n console.log(chalk.gray(\"Local: \") + chalk.cyan(summary.localUrl));\n console.log(chalk.gray(\"Target: \") + chalk.white(summary.target));\n console.log(chalk.gray(\"Mode: \") + chalk.white(summary.mode));\n console.log(chalk.gray(\"Routes:\"));\n for (const route of summary.routes) {\n console.log(chalk.gray(\" - \") + chalk.cyan(route));\n }\n console.log();\n}\n\nexport async function runViteDevServer(\n projectDir: string,\n options: WidgetDevOptions = {},\n): Promise<void> {\n let viteCliPath = resolveViteCliPath(projectDir);\n if (!viteCliPath) {\n // Cloned checkouts arrive without node_modules (`fluid widget clone` is a\n // pure git operation) and agent-scaffolded projects may skip the install\n // too. Install once here instead of bouncing the user to a manual step.\n const installCommand = getInstallCommand(projectDir);\n console.log(\n chalk.yellow(\n `Vite is not installed yet — running ${installCommand} first...`,\n ),\n );\n try {\n await installDependencies(projectDir);\n } catch {\n // Fall through to the resolution check below for the actionable error.\n }\n viteCliPath = resolveViteCliPath(projectDir);\n }\n if (!viteCliPath) {\n throw new Error(\n `Unable to find Vite in node_modules. Run \\`${getInstallCommand(projectDir)}\\` in ${projectDir}, then retry.`,\n );\n }\n\n await runNodeScript(viteCliPath, buildViteDevArgs(options), projectDir);\n}\n\nfunction resolveViteCliPath(projectDir: string): string | undefined {\n const viteCliPath = path.join(\n projectDir,\n \"node_modules\",\n \"vite\",\n \"bin\",\n \"vite.js\",\n );\n return existsSync(viteCliPath) ? viteCliPath : undefined;\n}\n\nasync function readPackageJson(packageJsonPath: string): Promise<unknown> {\n try {\n return JSON.parse(await readFile(packageJsonPath, \"utf-8\")) as unknown;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Unable to read package.json: ${message}`);\n }\n}\n\nfunction readPackageName(packageJson: unknown): string | undefined {\n if (!isRecord(packageJson)) return undefined;\n const name = packageJson[\"name\"];\n if (typeof name !== \"string\") return undefined;\n const trimmed = name.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction parsePort(value: string): number {\n const port = Number(value);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"Port must be an integer between 1 and 65535.\");\n }\n return port;\n}\n\nfunction normalizeHostOption(\n host: WidgetDevOptions[\"host\"],\n): string | undefined {\n if (host === undefined || host === false) return undefined;\n if (host === true) return \"0.0.0.0\";\n\n const trimmed = host.trim();\n return trimmed.length > 0 ? trimmed : \"0.0.0.0\";\n}\n\nfunction normalizeMode(mode: string | undefined): string {\n const trimmed = mode?.trim();\n return trimmed && trimmed.length > 0 ? trimmed : \"development\";\n}\n\nfunction formatLocalUrl(port: number, host: string | undefined): string {\n const displayHost = host && host !== \"0.0.0.0\" ? host : \"localhost\";\n return `http://${displayHost}:${port}`;\n}\n\nfunction runNodeScript(\n scriptPath: string,\n args: readonly string[],\n cwd: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, [scriptPath, ...args], {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n if (code === 0 || signal === \"SIGINT\" || signal === \"SIGTERM\") {\n resolve();\n return;\n }\n\n reject(\n new Error(\n signal\n ? `Vite dev server exited with signal ${signal}.`\n : `Vite dev server exited with code ${code ?? \"unknown\"}.`,\n ),\n );\n });\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import prompts from \"prompts\";\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport type { Choice } from \"prompts\";\n\nexport interface DropletChoice {\n readonly uuid: string;\n readonly name: string;\n}\n\nconst MAX_DROPLET_PAGES = 100;\n\nexport async function promptForDroplet(\n client: FluidOsHeyApiClient,\n): Promise<string | undefined> {\n const droplets = await listDroplets(client);\n\n if (droplets.length === 0) {\n throw new Error(\n \"No droplets were found for this account. Create a droplet in Fluid first, then run this command again.\",\n );\n }\n\n const response = await prompts({\n type: \"autocomplete\",\n name: \"droplet\",\n message: \"Select the droplet that owns this widget package\",\n choices: droplets.map((droplet) => ({\n title: `${droplet.name} (${droplet.uuid})`,\n value: droplet.uuid,\n })),\n suggest: (input: string, choices: Choice[]) =>\n Promise.resolve(\n input\n ? choices.filter((choice) =>\n choice.title.toLowerCase().includes(input.toLowerCase()),\n )\n : choices,\n ),\n });\n\n return response[\"droplet\"] as string | undefined;\n}\n\nexport async function listDroplets(\n client: FluidOsHeyApiClient,\n): Promise<readonly DropletChoice[]> {\n try {\n const firstResponse = await client.get({\n query: { page: 1 },\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/api/droplets\",\n });\n const totalPages = Math.min(\n readTotalPages(firstResponse) ?? 1,\n MAX_DROPLET_PAGES,\n );\n const responses = [firstResponse];\n\n for (let page = 2; page <= totalPages; page += 1) {\n responses.push(\n await client.get({\n query: { page },\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/api/droplets\",\n }),\n );\n }\n\n return responses.flatMap(normalizeDropletsResponse);\n } catch (err) {\n if (isApiLikeError(err)) {\n if (err.status === 401 || err.status === 403) {\n throw new Error(\n \"Your Fluid session has expired. Run `fluid login` and try again.\",\n );\n }\n throw new Error(\n `Could not fetch droplets from Fluid (HTTP ${err.status}). ${err.message}`,\n );\n }\n\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Could not fetch droplets from Fluid. ${message}`);\n }\n}\n\nfunction readTotalPages(response: unknown): number | undefined {\n if (!isRecord(response)) return undefined;\n const meta = response[\"meta\"];\n if (!isRecord(meta)) return undefined;\n const pagination = meta[\"pagination\"];\n if (!isRecord(pagination)) return undefined;\n const totalPages = pagination[\"total_pages\"] ?? pagination[\"totalPages\"];\n if (\n typeof totalPages !== \"number\" ||\n !Number.isInteger(totalPages) ||\n totalPages < 1\n ) {\n return undefined;\n }\n return totalPages;\n}\n\nfunction normalizeDropletsResponse(response: unknown): DropletChoice[] {\n const candidates = extractDropletArray(response);\n return candidates\n .map(normalizeDroplet)\n .filter((droplet): droplet is DropletChoice => droplet !== undefined);\n}\n\nfunction extractDropletArray(response: unknown): readonly unknown[] {\n if (Array.isArray(response)) return response;\n if (!isRecord(response)) return [];\n\n const directDroplets = response[\"droplets\"];\n if (Array.isArray(directDroplets)) return directDroplets;\n\n const data = response[\"data\"];\n if (Array.isArray(data)) return data;\n if (isRecord(data) && Array.isArray(data[\"droplets\"])) {\n return data[\"droplets\"];\n }\n\n return [];\n}\n\nfunction normalizeDroplet(value: unknown): DropletChoice | undefined {\n if (!isRecord(value)) return undefined;\n\n const uuid = readString(value, \"uuid\") ?? readString(value, \"id\");\n if (!uuid) return undefined;\n\n const name =\n readString(value, \"name\") ??\n readString(value, \"title\") ??\n readString(value, \"slug\") ??\n uuid;\n\n return { uuid, name };\n}\n\nfunction readString(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): string | undefined {\n const value = record[key];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction isApiLikeError(\n error: unknown,\n): error is { readonly status: number; readonly message: string } {\n return (\n error instanceof Error &&\n \"status\" in error &&\n typeof (error as { readonly status?: unknown }).status === \"number\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import path from \"node:path\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport type { WidgetLinkOptions } from \"../types.js\";\nimport { createAuthenticatedClient } from \"../utils/auth-client.js\";\nimport { promptForDroplet } from \"../utils/droplets.js\";\nimport {\n WIDGET_CONFIG_FILE,\n loadWidgetConfig,\n mergeWidgetConfig,\n validateDropletUuid,\n writeWidgetConfig,\n} from \"../utils/config.js\";\n\nexport const linkCommand: Command = new Command(\"link\")\n .description(\"Link this widget project to an existing Fluid droplet\")\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .action(async (options: WidgetLinkOptions) => {\n try {\n const projectDir = process.cwd();\n const loaded = await loadWidgetConfig(projectDir);\n\n let droplet = options.droplet?.trim() || undefined;\n if (!droplet) {\n const spinner = ora(\"Fetching droplets...\").start();\n try {\n const { client } = createAuthenticatedClient();\n spinner.stop();\n droplet = await promptForDroplet(client);\n } catch (err) {\n spinner.fail(\"Unable to load droplets\");\n throw err;\n }\n\n if (!droplet) {\n console.log(chalk.dim(\"Cancelled.\"));\n return;\n }\n }\n\n const nextConfig = mergeWidgetConfig(loaded.config, { droplet });\n const nextDropletError = validateDropletUuid(nextConfig.droplet ?? \"\");\n if (nextDropletError) throw new Error(nextDropletError);\n\n await writeWidgetConfig(projectDir, nextConfig);\n\n console.log();\n console.log(chalk.green(\"Linked widget project.\"));\n console.log(\n chalk.gray(\"Config: \") +\n chalk.cyan(\n path.relative(projectDir, loaded.path) || WIDGET_CONFIG_FILE,\n ),\n );\n console.log(\n chalk.gray(\"Droplet: \") + chalk.white(nextConfig.droplet),\n );\n console.log(\n chalk.gray(\"Package key: \") +\n chalk.white(`${nextConfig.droplet} (derived from droplet)`),\n );\n console.log();\n } catch (err) {\n console.log();\n console.error(\n chalk.red(\"Error:\") +\n \" \" +\n (err instanceof Error ? err.message : String(err)),\n );\n console.log();\n process.exit(1);\n }\n });\n","import type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\n\nexport interface DropletWidgetVersionSummary {\n readonly packageKey?: string;\n readonly packageId?: string;\n readonly version?: string;\n readonly status?: string;\n readonly createdAt?: string;\n readonly updatedAt?: string;\n readonly artifactCount?: number;\n readonly raw: unknown;\n}\n\nexport interface DropletWidgetLogEntry {\n readonly timestamp?: string;\n readonly level?: string;\n readonly message: string;\n readonly raw: unknown;\n}\n\nexport async function fetchDropletWidgetStatus(options: {\n readonly client: FluidOsHeyApiClient;\n readonly droplet: string;\n}): Promise<DropletWidgetVersionSummary[]> {\n const response = await options.client.get({\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: `/api/droplets/${encodeURIComponent(options.droplet)}/widget_package_versions`,\n });\n return extractArray(response).map(normalizeVersionSummary);\n}\n\nexport async function fetchDropletWidgetLogs(options: {\n readonly client: FluidOsHeyApiClient;\n readonly droplet: string;\n readonly limit?: number;\n}): Promise<DropletWidgetLogEntry[]> {\n const response = await options.client.get({\n query: options.limit ? { limit: options.limit } : undefined,\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: `/api/droplets/${encodeURIComponent(options.droplet)}/widget_package_versions/logs`,\n });\n return extractArray(response).map(normalizeLogEntry);\n}\n\nexport function formatStatusRows(\n versions: readonly DropletWidgetVersionSummary[],\n): string {\n if (versions.length === 0) return \"No widget package versions found.\";\n\n return versions\n .map((version) => {\n const identity =\n version.packageId ?? version.packageKey ?? \"unknown-package\";\n const release = version.version ?? \"unknown-version\";\n const status = version.status ?? \"unknown\";\n const updated = version.updatedAt ?? version.createdAt ?? \"unknown time\";\n const artifacts =\n version.artifactCount === undefined\n ? \"unknown artifacts\"\n : `${version.artifactCount} artifact${version.artifactCount === 1 ? \"\" : \"s\"}`;\n return `${identity}@${release} — ${status} — ${artifacts} — ${updated}`;\n })\n .join(\"\\n\");\n}\n\nexport function formatLogRows(logs: readonly DropletWidgetLogEntry[]): string {\n if (logs.length === 0) return \"No widget package logs found.\";\n\n return logs\n .map((entry) => {\n const timestamp = entry.timestamp ?? \"unknown time\";\n const level = entry.level ? entry.level.toUpperCase() : \"INFO\";\n return `[${timestamp}] ${level} ${entry.message}`;\n })\n .join(\"\\n\");\n}\n\nfunction normalizeVersionSummary(value: unknown): DropletWidgetVersionSummary {\n const record = unwrapKnownNestedRecord(value);\n const artifacts = readArray(record, \"artifacts\");\n return {\n packageKey: readFirstString(record, [\"package_key\", \"packageKey\"]),\n packageId: readFirstString(record, [\"package_id\", \"packageId\"]),\n version: readFirstString(record, [\"version\", \"name\"]),\n status: readFirstString(record, [\"status\", \"state\"]),\n createdAt: readFirstString(record, [\"created_at\", \"createdAt\"]),\n updatedAt: readFirstString(record, [\"updated_at\", \"updatedAt\"]),\n ...(artifacts ? { artifactCount: artifacts.length } : {}),\n raw: value,\n };\n}\n\nfunction normalizeLogEntry(value: unknown): DropletWidgetLogEntry {\n const record = unwrapKnownNestedRecord(value);\n return {\n timestamp: readFirstString(record, [\n \"timestamp\",\n \"created_at\",\n \"createdAt\",\n ]),\n level: readFirstString(record, [\"level\", \"severity\"]),\n message:\n readFirstString(record, [\"message\", \"event\", \"status\", \"state\"]) ??\n JSON.stringify(value),\n raw: value,\n };\n}\n\nfunction extractArray(value: unknown): unknown[] {\n if (Array.isArray(value)) return value;\n if (!isRecord(value)) return [];\n\n for (const key of [\n \"widget_package_versions\",\n \"widgetPackageVersions\",\n \"versions\",\n \"logs\",\n \"events\",\n \"data\",\n ] as const) {\n const nested = value[key];\n if (Array.isArray(nested)) return nested;\n }\n\n return [value];\n}\n\nfunction unwrapKnownNestedRecord(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) return {};\n for (const key of [\n \"widget_package_version\",\n \"widgetPackageVersion\",\n \"version\",\n \"log\",\n \"event\",\n ] as const) {\n const nested = value[key];\n if (isRecord(nested)) return nested;\n }\n return value;\n}\n\nfunction readArray(\n record: Record<string, unknown>,\n key: string,\n): readonly unknown[] | undefined {\n const value = record[key];\n return Array.isArray(value) ? value : undefined;\n}\n\nfunction readFirstString(\n record: Record<string, unknown>,\n keys: readonly string[],\n): string | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) return value;\n if (typeof value === \"number\" && Number.isFinite(value))\n return String(value);\n }\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { loadWidgetConfig, validateDropletUuid } from \"../utils/config.js\";\nimport { fetchDropletWidgetLogs, formatLogRows } from \"../utils/droplet-api.js\";\nimport { runCliAction } from \"../utils/command.js\";\n\nexport interface LogsCommandOptions {\n readonly droplet?: string;\n readonly limit?: string;\n readonly json?: boolean;\n}\n\nexport const logsCommand: Command = new Command(\"logs\")\n .description(\"Show recent widget package publish logs for a Droplet\")\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--limit <number>\", \"Maximum number of log entries to request\", \"50\")\n .option(\"--json\", \"Print raw log response as JSON\")\n .action((options: LogsCommandOptions) => {\n return runCliAction(async () => {\n const droplet = await resolveDroplet(process.cwd(), options.droplet);\n const limit = parseLimit(options.limit);\n const logs = await fetchDropletWidgetLogs({\n client: createAuthenticatedWidgetPackageClient(),\n droplet,\n limit,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n logs.map((entry) => entry.raw),\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(chalk.blue.bold(`Widget logs for droplet ${droplet}`));\n console.log();\n console.log(formatLogRows(logs));\n });\n });\n\nasync function resolveDroplet(\n projectDir: string,\n override: string | undefined,\n): Promise<string> {\n const droplet =\n override?.trim() || (await loadWidgetConfig(projectDir)).config.droplet;\n if (droplet?.trim()) {\n const trimmedDroplet = droplet.trim();\n const dropletError = validateDropletUuid(trimmedDroplet);\n if (dropletError) throw new Error(dropletError);\n return trimmedDroplet;\n }\n\n throw new Error(\n \"Missing droplet UUID. Pass --droplet <uuid> or set droplet in fluid.widget.config.ts.\",\n );\n}\n\nfunction parseLimit(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n if (Number.isInteger(parsed) && parsed > 0 && parsed <= 500) return parsed;\n throw new Error(\"--limit must be an integer between 1 and 500.\");\n}\n","import { Command } from \"commander\";\nimport {\n publishWidgetPackage as publishWidgetPackageArtifacts,\n type PublishedWidgetPackage,\n} from \"@fluid-app/fluid-cli-widget-tooling\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n DEFAULT_WIDGET_OUT_DIR,\n validateDropletWidgetProject,\n withRootWidgetConfigBridge,\n} from \"../utils/source-package.js\";\nimport { loadWidgetConfig, validateDropletUuid } from \"../utils/config.js\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { runPackageScriptIfAvailable } from \"../utils/package-scripts.js\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { getWidgetCliVersion } from \"../utils/template.js\";\n\nexport interface PublishWidgetPackageOptions {\n readonly projectDir: string;\n readonly outDir: string;\n readonly droplet?: string;\n readonly dryRun?: boolean;\n readonly skipTypecheck?: boolean;\n}\n\nexport interface PublishWidgetPackageResult {\n readonly dryRun: boolean;\n readonly uploaded: boolean;\n readonly outDir: string;\n readonly droplet?: string;\n}\n\nexport async function publishWidgetPackage(\n options: PublishWidgetPackageOptions,\n): Promise<PublishWidgetPackageResult> {\n const droplet = await resolvePublishDroplet(\n options.projectDir,\n options.droplet,\n );\n\n await validateDropletWidgetProject(options.projectDir, droplet);\n if (options.skipTypecheck !== true) {\n await runPackageScriptIfAvailable({\n projectDir: options.projectDir,\n scriptName: \"typecheck\",\n });\n }\n\n const dryRun = options.dryRun === true;\n await withRootWidgetConfigBridge(\n options.projectDir,\n () =>\n publishDropletWidgetPackageArtifacts({\n projectDir: options.projectDir,\n outDir: options.outDir,\n droplet,\n dryRun,\n }),\n droplet,\n );\n\n return {\n dryRun,\n uploaded: !dryRun,\n outDir: options.outDir,\n droplet,\n };\n}\n\nexport interface PublishCommandOptions {\n readonly outDir?: string;\n readonly droplet?: string;\n readonly dryRun?: boolean;\n readonly skipTypecheck?: boolean;\n}\n\nexport const publishCommand: Command = new Command(\"publish\")\n .description(\"Publish a Fluid widget package\")\n .option(\n \"-o, --out-dir <dir>\",\n \"Widget artifact output directory\",\n DEFAULT_WIDGET_OUT_DIR,\n )\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--dry-run\", \"Build and validate without uploading\")\n .option(\"--skip-typecheck\", \"Skip package typecheck script when present\")\n .action((options: PublishCommandOptions) => {\n return runCliAction(async () => {\n const projectDir = process.cwd();\n const outDir = options.outDir ?? DEFAULT_WIDGET_OUT_DIR;\n const droplet = await resolvePublishDroplet(projectDir, options.droplet);\n const dryRun = options.dryRun === true;\n\n console.log();\n console.log(chalk.blue.bold(\"Fluid Widget Publish\"));\n console.log();\n printRuntimeOnlyNotice();\n console.log(chalk.gray(\"Droplet: \") + chalk.white(droplet));\n console.log(chalk.gray(\"Output: \") + chalk.cyan(outDir));\n if (dryRun) {\n console.log(chalk.yellow(\"Dry run: no upload will be created.\"));\n }\n console.log();\n\n const validateSpinner = ora(\"Validating widget package...\").start();\n await validateDropletWidgetProject(projectDir, droplet);\n validateSpinner.succeed(\"Validated widget package\");\n\n if (options.skipTypecheck !== true) {\n const typecheckSpinner = ora(\"Running package typecheck...\").start();\n const typecheck = await runPackageScriptIfAvailable({\n projectDir,\n scriptName: \"typecheck\",\n });\n if (typecheck.ran) {\n typecheckSpinner.succeed(\"Package typecheck passed\");\n } else {\n typecheckSpinner.info(\"No typecheck script found; skipping\");\n }\n }\n\n const publishSpinner = ora(\n dryRun\n ? \"Building and preparing dry-run upload payload...\"\n : \"Building and publishing widget artifacts...\",\n ).start();\n\n const result = await withRootWidgetConfigBridge(\n projectDir,\n () =>\n publishDropletWidgetPackageArtifacts({\n projectDir,\n outDir,\n droplet,\n dryRun,\n }),\n droplet,\n );\n\n publishSpinner.succeed(\n dryRun ? \"Prepared dry-run upload payload\" : \"Published widget package\",\n );\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"Dry run complete — upload session was not requested.\"),\n );\n console.log();\n printDryRunSessionPayload(result);\n }\n\n printWidgetPublishSummary({\n title: dryRun ? \"Widget publish dry run\" : \"Widget publish\",\n ownerLabel: `droplet ${droplet}`,\n outDir,\n result,\n });\n });\n });\n\nexport async function resolvePublishDroplet(\n projectDir: string,\n override: string | undefined,\n): Promise<string> {\n const droplet =\n override?.trim() || (await loadWidgetConfig(projectDir)).config.droplet;\n if (droplet?.trim()) {\n const trimmedDroplet = droplet.trim();\n const dropletError = validateDropletUuid(trimmedDroplet);\n if (dropletError) throw new Error(dropletError);\n return trimmedDroplet;\n }\n\n throw new Error(\n \"Missing droplet UUID. Pass --droplet <uuid> or set droplet in fluid.widget.config.ts.\",\n );\n}\n\nasync function publishDropletWidgetPackageArtifacts(options: {\n readonly projectDir: string;\n readonly outDir: string;\n readonly droplet: string;\n readonly dryRun: boolean;\n}): Promise<PublishedWidgetPackage> {\n const common = {\n projectDir: options.projectDir,\n outDir: options.outDir,\n owner: \"droplet\",\n uploadOwner: { kind: \"droplet\", uuid: options.droplet },\n cliVersion: await getWidgetCliVersion(),\n } as const;\n\n if (options.dryRun) {\n return publishWidgetPackageArtifacts({\n ...common,\n dryRun: true,\n });\n }\n\n return publishWidgetPackageArtifacts({\n ...common,\n dryRun: false,\n client: createAuthenticatedWidgetPackageClient(),\n });\n}\n\nfunction printRuntimeOnlyNotice(): void {\n console.log(\n chalk.yellow(\n \"This publishes widget runtime artifacts only; it does not deploy the hosted portal shell.\",\n ),\n );\n console.log();\n}\n\nfunction printDryRunSessionPayload(result: PublishedWidgetPackage): void {\n console.log(chalk.bold(\"Dry-run upload session payload:\"));\n console.log(JSON.stringify(result.publish.sessionPayload, null, 2));\n console.log();\n}\n\nfunction printWidgetPublishSummary(options: {\n readonly title: string;\n readonly ownerLabel: string;\n readonly outDir: string;\n readonly result: PublishedWidgetPackage;\n}): void {\n console.log();\n console.log(chalk.green.bold(`${options.title} complete`));\n console.log();\n console.log(chalk.gray(\"Owner: \") + chalk.white(options.ownerLabel));\n console.log(\n chalk.gray(\"Package: \") + chalk.white(options.result.build.packageId),\n );\n console.log(\n chalk.gray(\"Version: \") + chalk.white(options.result.build.version),\n );\n console.log(chalk.gray(\"Output: \") + chalk.cyan(options.outDir));\n console.log(\n chalk.gray(\"Artifacts: \") +\n chalk.white(String(options.result.request.artifacts.length)),\n );\n console.log();\n}\n","import type { GitSyncActor } from \"@fluid-app/fluid-cli\";\nimport { gitSyncActorFromMe } from \"@fluid-app/fluid-cli\";\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\n\n/**\n * `GET /api/me` — the authenticated user's identity, used to stamp\n * auto-commit messages in the canonical GitSync format. The name fallback\n * chain and the shape it feeds both live in `@fluid-app/fluid-cli`'s\n * git-sync/commit-subject.ts, shared with the mist / portal / theme CLIs.\n *\n * Best-effort by contract: callers treat a rejection (or a null actor) as\n * a system-attributed commit rather than failing the push.\n */\nexport async function fetchCurrentUser(\n client: FluidOsHeyApiClient,\n): Promise<GitSyncActor | null> {\n const raw = (await client.get({\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/api/me\",\n })) as Record<string, unknown>;\n return gitSyncActorFromMe(raw);\n}\n","import type { ChangeEntry, GitSyncActor } from \"@fluid-app/fluid-cli\";\nimport {\n gitSyncCommitSubject,\n resolveGitSyncActor,\n subjectFragment,\n summarizeChanges,\n} from \"@fluid-app/fluid-cli\";\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport {\n ensureLocalStateExcluded,\n gitAdoptFetchHead,\n gitAheadBehindVsFetchHead,\n gitAutoCommit,\n gitFetch,\n gitInit,\n gitMergeFastForward,\n gitPush,\n gitRemoteBranchExists,\n gitStash,\n gitStashPop,\n hasCommits,\n hasUncommittedChanges,\n isGitRepository,\n purgeLocalStateFromIndex,\n type GitCommitIdentity,\n} from \"./git.js\";\nimport { mintWidgetGitCredential } from \"../utils/git-credential.js\";\nimport { fetchCurrentUser } from \"../utils/me.js\";\nimport { readWidgetMarker } from \"../utils/widget-marker.js\";\n\nexport interface SyncWidgetGitRepoOptions {\n readonly cwd: string;\n readonly client: FluidOsHeyApiClient;\n /** Droplet UUID that owns the package; omitted for company-owned packages. */\n readonly droplet?: string;\n readonly branch?: string;\n /** Base auto-commit message (before the author/public-id stamp). */\n readonly message?: string;\n /** Skip the auto-commit step and push existing commits only. */\n readonly commit?: boolean;\n}\n\nexport type SyncWidgetGitRepoResult =\n | {\n readonly kind: \"synced\";\n readonly pulled: number;\n readonly committed: boolean;\n }\n | {\n readonly kind: \"diverged\";\n readonly ahead: number;\n readonly behind: number;\n };\n\n/**\n * Sync a widget project's invisible git repo: mint a credential, reconcile\n * with origin (fast-forward pull when safe), auto-commit working-tree changes\n * with an author-stamped message, and push HEAD to the branch.\n *\n * Mirrors the Mist CLI write path (`packages/cli/mist/src/commands/push.ts`).\n * Throws on hard failures (mint error, diverged history is returned rather\n * than thrown so the caller can message it); the token-bearing remote URL is\n * only ever handed to the git helpers, never logged or persisted.\n */\nexport async function syncWidgetGitRepo(\n options: SyncWidgetGitRepoOptions,\n): Promise<SyncWidgetGitRepoResult> {\n const { cwd, client } = options;\n const branch = options.branch ?? \"main\";\n // One `/api/me` for the whole sync, shared by the message stamp and the\n // git author. Previously each of the three consumers below fetched it\n // independently, so a slow /api/me cost up to 15s of a push.\n const actor = memoizeActor(client);\n\n // Ensure a local repo exists — projects created via `fluid widget create`\n // have their git history stripped, so first push initializes one.\n if (!(await isGitRepository(cwd))) {\n await gitInit(cwd, branch);\n }\n\n // Scope the sync to the widget project before ANY tree inspection. Mist\n // Desktop writes its private per-machine state (`.mist-desktop/`: chat\n // transcripts, attachments, screenshots) into the project root it\n // opened; left unexcluded it makes every Desktop-opened project read as\n // dirty (forcing a needless stash/pop around the pull below) and gets\n // published wholesale by the auto-commit.\n await ensureLocalStateExcluded(cwd);\n\n // Mint one credential for the whole sync — tokens live ~1h, far beyond a\n // push. Minting again mid-flow would reintroduce a degrade window AFTER\n // the auto-commit: a 404/409 there reads as \"sync unavailable\" to the\n // caller, which would publish artifacts while the fresh commit stays\n // local. With a single mint, unavailability can only surface before any\n // local or remote mutation.\n const cred = await mintWidgetGitCredential({\n client,\n droplet: options.droplet,\n });\n\n // Reconcile against the remote before committing. `gitRemoteBranchExists`\n // and `gitFetch` both throw on transport/auth failure (propagated to the\n // caller as a hard error) so a network blip is never mistaken for an empty\n // remote — that would skip drift detection and let us push over a\n // collaborator's work. We only skip reconciliation when the branch\n // genuinely doesn't exist yet (freshly provisioned repo, first push).\n let pulled = 0;\n const branchExists = await gitRemoteBranchExists(cwd, cred.remoteUrl, branch);\n if (branchExists) {\n await gitFetch(cwd, cred.remoteUrl, branch);\n if (await hasCommits(cwd)) {\n const { ahead, behind } = await gitAheadBehindVsFetchHead(cwd);\n if (behind > 0 && ahead > 0) {\n return { kind: \"diverged\", ahead, behind };\n }\n if (behind > 0) {\n const wasDirty = await hasUncommittedChanges(cwd);\n if (wasDirty) await gitStash(cwd, \"fluid-widget-push: pre-pull stash\");\n try {\n await gitMergeFastForward(cwd);\n } finally {\n if (wasDirty) await gitStashPop(cwd); // throws on conflict\n }\n pulled = behind;\n }\n } else {\n // Brand-new local repo (`create` strips git history) but the remote\n // branch already has commits — the backend provisions repos with an\n // auto-init README (or starter-template) commit. Adopt that history\n // as the local base so the auto-commit below lands on top of it and\n // the push fast-forwards; a fresh root commit here would be rejected\n // as unrelated history.\n pulled = await gitAdoptFetchHead(cwd);\n }\n }\n\n // Untrack chats leaked by an older CLI, UNCONDITIONALLY. A checkout\n // whose only problem is a tracked `.mist-desktop/` has a clean working\n // tree, and `--no-commit` suppresses the commit below entirely — so\n // gating this on either would skip the cleanup forever and leave the\n // chats published. Runs after reconciliation, immediately before the\n // push. No-op when nothing was tracked (the common case).\n await purgeLocalStateFromIndex(\n cwd,\n // Housekeeping the CLI does on its own initiative, so it's attributed\n // to `Fluid` rather than to whoever happened to trigger this push.\n gitSyncCommitSubject(\n \"Remove private Mist Desktop state from the widget repository\",\n null,\n ),\n commitIdentity(await actor()),\n );\n\n // Auto-commit working-tree changes (unless --no-commit).\n let committed = false;\n if (options.commit !== false && (await hasUncommittedChanges(cwd))) {\n const resolved = await actor();\n await gitAutoCommit(\n cwd,\n (changes) => buildCommitMessage(cwd, resolved, changes, options.message),\n commitIdentity(resolved),\n );\n committed = true;\n }\n\n await gitPush(cwd, cred.remoteUrl, branch);\n\n return { kind: \"synced\", pulled, committed };\n}\n\n/**\n * Build the auto-commit message in the canonical GitSync shape —\n * `<name>: <action> · <timestamp> (<public_id>)` — so widget history reads\n * the same as mist / theme / portal history and always says who published.\n * A `-m` message replaces the action but keeps the stamp. An unknown actor\n * yields a `Fluid:` system commit rather than an unattributed one.\n */\nfunction buildCommitMessage(\n cwd: string,\n actor: GitSyncActor | null,\n changes: readonly ChangeEntry[],\n base?: string,\n): string {\n // Precedence: an explicit `-m` states the INTENT, which no diff can\n // recover. Otherwise describe what actually changed. The package-key\n // constant is the last resort, for a diff we couldn't read.\n const packageKey = readWidgetMarker(cwd)?.package_key;\n const fallback = packageKey\n ? `Publish widget ${subjectFragment(packageKey)}`\n : \"Publish widget\";\n const action = base?.trim() || summarizeChanges(changes) || fallback;\n return gitSyncCommitSubject(action, actor);\n}\n\n/** Prefer the Fluid user for the git author when the repo has no identity. */\nfunction commitIdentity(\n actor: GitSyncActor | null,\n): GitCommitIdentity | undefined {\n // undefined → git.ts's default identity.\n return actor ? { name: actor.name, email: \"cli@fluid.app\" } : undefined;\n}\n\n/**\n * Resolve the signed-in user once per sync, cached across callers.\n * Best-effort by contract: a failed or slow `/api/me` resolves to null (a\n * system-attributed commit) instead of failing the push.\n */\nfunction memoizeActor(\n client: FluidOsHeyApiClient,\n): () => Promise<GitSyncActor | null> {\n let pending: Promise<GitSyncActor | null> | null = null;\n return () =>\n (pending ??= resolveGitSyncActor(() =>\n withTimeout(fetchCurrentUser(client), 5_000),\n ));\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms),\n ),\n ]);\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { DEFAULT_WIDGET_OUT_DIR } from \"../utils/source-package.js\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { runCliAction } from \"../utils/command.js\";\nimport { syncWidgetGitRepo } from \"../lib/git-sync.js\";\nimport { GitError } from \"../lib/git.js\";\nimport { isGitSyncUnavailable } from \"../utils/git-credential.js\";\nimport { publishWidgetPackage, resolvePublishDroplet } from \"./publish.js\";\n\nexport interface PushCommandOptions {\n readonly outDir?: string;\n readonly droplet?: string;\n readonly dryRun?: boolean;\n readonly skipTypecheck?: boolean;\n readonly branch?: string;\n readonly message?: string;\n /** Set false by `--no-commit`: push existing commits without auto-committing. */\n readonly commit?: boolean;\n /** Sync the git repo but skip the build + publish pipeline. */\n readonly skipPublish?: boolean;\n}\n\nexport const pushCommand: Command = new Command(\"push\")\n .description(\n \"Sync the widget's git repository (commit + push), then build and publish\",\n )\n .option(\n \"-o, --out-dir <dir>\",\n \"Widget artifact output directory\",\n DEFAULT_WIDGET_OUT_DIR,\n )\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--branch <name>\", \"Branch to push (default: main)\")\n .option(\n \"-m, --message <message>\",\n \"Commit message for the auto-commit (default: timestamped Publish)\",\n )\n .option(\n \"--no-commit\",\n \"Skip the auto-commit step (push existing commits only)\",\n )\n .option(\n \"--skip-publish\",\n \"Sync the git repository only; skip build + publish\",\n )\n .option(\"--dry-run\", \"Build and validate without uploading (publish step)\")\n .option(\"--skip-typecheck\", \"Skip package typecheck script when present\")\n .action((options: PushCommandOptions) =>\n runCliAction(async () => {\n const projectDir = process.cwd();\n const outDir = options.outDir ?? DEFAULT_WIDGET_OUT_DIR;\n const droplet = await resolvePublishDroplet(projectDir, options.droplet);\n const branch = options.branch ?? \"main\";\n\n console.log();\n console.log(chalk.blue.bold(\"Fluid Widget Push\"));\n console.log(chalk.gray(\"Droplet: \") + chalk.white(droplet));\n console.log();\n\n // --- Git sync phase -------------------------------------------------\n // Degrade to publish-only ONLY when git sync isn't in play: there is no\n // repository to sync with yet (404/409, see `isGitSyncUnavailable`) or\n // git isn't installed. Every other failure — diverged history, stash-pop\n // conflict, auth failure after a local commit, rejected push — aborts\n // BEFORE publish, so we never leave artifacts published while the source\n // repo is unsynced or the local checkout is in a broken git state.\n const client = createAuthenticatedWidgetPackageClient();\n const syncSpinner = ora(\"Syncing widget repository…\").start();\n try {\n const result = await syncWidgetGitRepo({\n cwd: projectDir,\n client,\n droplet,\n branch,\n ...(options.message ? { message: options.message } : {}),\n ...(options.commit === false ? { commit: false } : {}),\n });\n if (result.kind === \"diverged\") {\n syncSpinner.fail(\n `Your local history and origin/${branch} have diverged ` +\n `(${result.ahead} ahead, ${result.behind} behind).`,\n );\n throw new Error(\n \"Resolve in a terminal with `git pull --rebase`, fix any conflicts, \" +\n \"then re-run `fluid widget push`. Nothing was published.\",\n );\n }\n const parts: string[] = [];\n if (result.pulled > 0) {\n parts.push(\n `pulled ${result.pulled} commit${result.pulled === 1 ? \"\" : \"s\"}`,\n );\n }\n parts.push(result.committed ? \"committed + pushed\" : \"pushed\");\n syncSpinner.succeed(`Synced widget repository (${parts.join(\", \")})`);\n } catch (err) {\n if (isGitSyncUnavailable(err)) {\n syncSpinner.info(\n \"Widget git sync isn't available yet — publishing artifacts only.\",\n );\n } else if (err instanceof GitError && err.exitCode === 127) {\n syncSpinner.warn(err.message);\n console.log(\n chalk.yellow(\n \"Skipping git sync (git unavailable); publishing artifacts only.\",\n ),\n );\n } else {\n // Hard failure — stop before publishing so source and artifacts\n // don't drift out of sync.\n if (syncSpinner.isSpinning) syncSpinner.fail(\"Git sync failed\");\n throw err;\n }\n }\n\n if (options.skipPublish === true) {\n console.log();\n console.log(chalk.dim(\"Skipped build + publish (--skip-publish).\"));\n return;\n }\n\n // --- Publish phase ---------------------------------------------------\n const dryRun = options.dryRun === true;\n const publishSpinner = ora(\n dryRun\n ? \"Building and preparing dry-run upload payload…\"\n : \"Building and publishing widget artifacts…\",\n ).start();\n try {\n await publishWidgetPackage({\n projectDir,\n outDir,\n droplet,\n dryRun,\n skipTypecheck: options.skipTypecheck === true,\n });\n publishSpinner.succeed(\n dryRun\n ? \"Prepared dry-run upload payload\"\n : \"Published widget package\",\n );\n } catch (err) {\n publishSpinner.fail(\"Publish failed\");\n throw err;\n }\n\n console.log();\n console.log(chalk.green.bold(\"Done.\"));\n }),\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { createAuthenticatedWidgetPackageClient } from \"../utils/auth-client.js\";\nimport { loadWidgetConfig, validateDropletUuid } from \"../utils/config.js\";\nimport {\n fetchDropletWidgetStatus,\n formatStatusRows,\n} from \"../utils/droplet-api.js\";\nimport { runCliAction } from \"../utils/command.js\";\n\nexport interface StatusCommandOptions {\n readonly droplet?: string;\n readonly json?: boolean;\n}\n\nexport const statusCommand: Command = new Command(\"status\")\n .description(\"Show published widget package status for a Droplet\")\n .option(\"--droplet <uuid>\", \"Droplet UUID that owns the widget package\")\n .option(\"--json\", \"Print raw status response as JSON\")\n .action((options: StatusCommandOptions) => {\n return runCliAction(async () => {\n const droplet = await resolveDroplet(process.cwd(), options.droplet);\n const versions = await fetchDropletWidgetStatus({\n client: createAuthenticatedWidgetPackageClient(),\n droplet,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n versions.map((version) => version.raw),\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(chalk.blue.bold(`Widget status for droplet ${droplet}`));\n console.log();\n console.log(formatStatusRows(versions));\n });\n });\n\nasync function resolveDroplet(\n projectDir: string,\n override: string | undefined,\n): Promise<string> {\n const droplet =\n override?.trim() || (await loadWidgetConfig(projectDir)).config.droplet;\n if (droplet?.trim()) {\n const trimmedDroplet = droplet.trim();\n const dropletError = validateDropletUuid(trimmedDroplet);\n if (dropletError) throw new Error(dropletError);\n return trimmedDroplet;\n }\n\n throw new Error(\n \"Missing droplet UUID. Pass --droplet <uuid> or set droplet in fluid.widget.config.ts.\",\n );\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport {\n formatValidationSuccess,\n validateDropletWidgetProject,\n} from \"../utils/source-package.js\";\nimport { runCliAction } from \"../utils/command.js\";\n\nexport interface ValidateWidgetOptions {\n readonly json?: boolean;\n}\n\nexport const validateCommand: Command = new Command(\"validate\")\n .description(\"Validate the current droplet widget package\")\n .option(\"--json\", \"Print machine-readable validation output\")\n .action((options: ValidateWidgetOptions) => {\n return runCliAction(async () => {\n const result = await validateDropletWidgetProject(process.cwd());\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n valid: true,\n config: result.sourceConfigPath,\n packageId: result.validated.packageId,\n version: result.validated.version,\n widgets: result.validated.widgets.map((widget) => ({\n name: widget.name,\n type: widget.type,\n })),\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(chalk.green(formatValidationSuccess(result)));\n });\n });\n","import { Command } from \"commander\";\nimport type { FluidPlugin, PluginContext } from \"@fluid-app/fluid-cli\";\nimport { buildCommand } from \"./commands/build.js\";\nimport { cloneCommand } from \"./commands/clone.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { devCommand } from \"./commands/dev.js\";\nimport { linkCommand } from \"./commands/link.js\";\nimport { logsCommand } from \"./commands/logs.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { pushCommand } from \"./commands/push.js\";\nimport { statusCommand } from \"./commands/status.js\";\nimport { validateCommand } from \"./commands/validate.js\";\n\nexport const widgetCommand: Command = new Command(\"widget\")\n .description(\n \"Create, preview, link, validate, build, publish, push, and clone standalone Fluid widgets\",\n )\n .addCommand(createCommand)\n .addCommand(cloneCommand)\n .addCommand(devCommand)\n .addCommand(linkCommand)\n .addCommand(validateCommand)\n .addCommand(buildCommand)\n .addCommand(publishCommand)\n .addCommand(pushCommand)\n .addCommand(statusCommand)\n .addCommand(logsCommand);\n\nconst plugin: FluidPlugin = {\n name: \"@fluid-app/fluid-cli-widget\",\n version: \"0.1.0\",\n register(ctx: PluginContext) {\n const existingWidgetCommand = findCommand(ctx.program, \"widget\");\n if (existingWidgetCommand) {\n addCommandIfMissing(existingWidgetCommand, createCommand);\n addCommandIfMissing(existingWidgetCommand, cloneCommand);\n addCommandIfMissing(existingWidgetCommand, devCommand);\n addCommandIfMissing(existingWidgetCommand, linkCommand);\n addCommandIfMissing(existingWidgetCommand, validateCommand);\n addCommandIfMissing(existingWidgetCommand, buildCommand);\n addCommandIfMissing(existingWidgetCommand, publishCommand);\n addCommandIfMissing(existingWidgetCommand, pushCommand);\n addCommandIfMissing(existingWidgetCommand, statusCommand);\n addCommandIfMissing(existingWidgetCommand, logsCommand);\n return;\n }\n\n ctx.program.addCommand(widgetCommand);\n },\n};\n\nexport default plugin;\n\nexport type {\n WidgetCommandOptions,\n WidgetCreateOptions,\n WidgetLinkOptions,\n WidgetTemplateVariables,\n} from \"./types.js\";\nexport { buildCommand, buildWidgetPackage } from \"./commands/build.js\";\nexport type {\n BuildWidgetOptions,\n BuildWidgetPackageOptions,\n BuildWidgetPackageResult,\n} from \"./commands/build.js\";\nexport { cloneCommand } from \"./commands/clone.js\";\nexport type { CloneCommandOptions } from \"./commands/clone.js\";\nexport {\n createCommand,\n createWidgetProject,\n type CreateWidgetProjectDependencies,\n} from \"./commands/create.js\";\nexport { pushCommand } from \"./commands/push.js\";\nexport type { PushCommandOptions } from \"./commands/push.js\";\nexport {\n DEFAULT_WIDGET_DEV_PORT,\n WIDGET_DEV_ROUTES,\n buildViteDevArgs,\n devCommand,\n printWidgetDevSummary,\n resolveWidgetDevProject,\n runViteDevServer,\n} from \"./commands/dev.js\";\nexport type {\n WidgetDevOptions,\n WidgetDevProjectSummary,\n} from \"./commands/dev.js\";\nexport { linkCommand } from \"./commands/link.js\";\nexport { logsCommand } from \"./commands/logs.js\";\nexport type { LogsCommandOptions } from \"./commands/logs.js\";\nexport { publishCommand, publishWidgetPackage } from \"./commands/publish.js\";\nexport type {\n PublishCommandOptions,\n PublishWidgetPackageOptions,\n PublishWidgetPackageResult,\n} from \"./commands/publish.js\";\nexport { statusCommand } from \"./commands/status.js\";\nexport type { StatusCommandOptions } from \"./commands/status.js\";\nexport { validateCommand } from \"./commands/validate.js\";\nexport type { ValidateWidgetOptions } from \"./commands/validate.js\";\nexport {\n WIDGET_CONFIG_FILE,\n formatWidgetConfig,\n loadWidgetConfig,\n mergeWidgetConfig,\n parseWidgetConfigSource,\n resolveWidgetConfigPath,\n validateDropletUuid,\n writeWidgetConfig,\n type FluidWidgetConfig,\n type LoadedWidgetConfig,\n} from \"./utils/config.js\";\nexport {\n DEFAULT_WIDGET_OUT_DIR,\n ROOT_WIDGET_CONFIG_FILE,\n WidgetValidationError,\n formatValidationSuccess,\n resolveWidgetSourceConfig,\n validateDropletWidgetProject,\n withRootWidgetConfigBridge,\n type WidgetValidationResult,\n} from \"./utils/source-package.js\";\nexport { formatValidationErrors } from \"./utils/validation.js\";\nexport type { WidgetCliValidationError } from \"./utils/validation.js\";\n\nfunction addCommandIfMissing(parent: Command, child: Command): void {\n if (findCommand(parent, child.name())) return;\n parent.addCommand(child);\n}\n\nfunction findCommand(parent: Command, name: string): Command | undefined {\n return parent.commands?.find((command) => command.name() === name);\n}\n"],"mappings":"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"}