@kittl/cli 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/run.js +4 -1
- package/dist/chunk-CT7IDOZX.js +71 -0
- package/dist/chunk-CT7IDOZX.js.map +1 -0
- package/dist/chunk-FRAFJMJ5.js +117 -0
- package/dist/chunk-FRAFJMJ5.js.map +1 -0
- package/dist/{chunk-YIAPJLU2.js → chunk-GOOP3XEU.js} +3 -3
- package/dist/{chunk-KYEOPC4O.js → chunk-LEELFFFY.js} +2 -2
- package/dist/{chunk-XEFALKNN.js → chunk-LZM72TST.js} +2 -2
- package/dist/{chunk-SCPSO3P6.js → chunk-X67IL4KU.js} +22 -65
- package/dist/chunk-X67IL4KU.js.map +1 -0
- package/dist/chunk-ZS7NZCD4.js +36 -0
- package/dist/chunk-ZS7NZCD4.js.map +1 -0
- package/dist/commands/app/init.js +7 -4
- package/dist/commands/app/init.js.map +1 -1
- package/dist/commands/app/release.js +5 -3
- package/dist/commands/app/release.js.map +1 -1
- package/dist/commands/app/update.js +7 -4
- package/dist/commands/app/update.js.map +1 -1
- package/dist/commands/app/upload.js +6 -3
- package/dist/commands/app/upload.js.map +1 -1
- package/dist/commands/auth/login.js +5 -2
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.js +5 -2
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/whoami.js +4 -2
- package/dist/commands/whoami.js +4 -2
- package/dist/dist-3OYSVDTD.js +546 -0
- package/dist/dist-3OYSVDTD.js.map +1 -0
- package/dist/hooks/finally/telemetry.js +9 -0
- package/dist/hooks/finally/telemetry.js.map +1 -0
- package/dist/hooks/finally/telemetry.test.js +16242 -0
- package/dist/hooks/finally/telemetry.test.js.map +1 -0
- package/dist/magic-string.es-APUP3ZXW.js +1389 -0
- package/dist/magic-string.es-APUP3ZXW.js.map +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +12 -2
- package/dist/chunk-SCPSO3P6.js.map +0 -1
- /package/dist/{chunk-YIAPJLU2.js.map → chunk-GOOP3XEU.js.map} +0 -0
- /package/dist/{chunk-KYEOPC4O.js.map → chunk-LEELFFFY.js.map} +0 -0
- /package/dist/{chunk-XEFALKNN.js.map → chunk-LZM72TST.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/app/init.ts","../../../src/core/scaffolder.ts","../../../src/core/templates.ts","../../../src/services/developer-organizations.service.ts","../../../src/ui/views/app-init/AppInitWizardView.tsx","../../../src/ui/views/app-init/AppsInitOrgPickerView.tsx","../../../src/ui/views/app-init/TextInputView.tsx"],"sourcesContent":["import { join, relative, resolve } from 'node:path';\nimport { Args } from '@oclif/core';\nimport { CLI_CONFIG } from '../../constants';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatHttpClientError } from '../../core/error';\nimport { getFileNameFromPath } from '../../core/files';\nimport {\n internalConfigExists,\n internalConfigPath,\n writeInternalConfig,\n} from '../../core/internal.config';\nimport { scaffoldExtension } from '../../core/scaffolder';\nimport { ensureDirectory } from '../../core/utils';\nimport {\n type DeveloperOrganization,\n listDeveloperOrganizations,\n} from '../../services/developer-organizations.service';\nimport { createExtensionDraftVersion } from '../../services/extensions.service';\nimport { AppInitWizardView } from '../../ui/views/app-init';\n\nexport default class AppInit extends BaseCommand {\n public static override description =\n 'Initialize a Kittl app in the current directory OR in a custom PATH';\n\n public static override args = {\n path: Args.string({\n description: 'Directory for the app (created if it does not exist)',\n default: '.',\n required: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { args } = await this.parse(AppInit);\n\n await this.ensureAuthenticated();\n\n const targetDir = resolve(process.cwd(), args.path);\n\n try {\n await ensureDirectory(targetDir);\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n if (await internalConfigExists(targetDir)) {\n this.error(\n `Kittl config already exists at ${internalConfigPath(targetDir)}. Remove it or choose a different directory.`,\n { exit: 2 },\n );\n }\n\n const client = this.getKittlApiClient();\n let organizations: DeveloperOrganization[];\n try {\n organizations = await listDeveloperOrganizations(client);\n } catch (e) {\n this.error(formatHttpClientError(e), { exit: 2 });\n }\n\n const extensionNameSuggestion =\n args.path === '.' ? undefined : getFileNameFromPath(targetDir);\n\n const wizardResult = await this.renderView(AppInitWizardView, {\n organizations,\n client,\n extensionNameSuggestion,\n });\n\n if (wizardResult.kind === 'cancelled') {\n this.exit(130);\n }\n\n const { data } = wizardResult;\n\n const configFilePath = await writeInternalConfig(targetDir, {\n developerOrganizationId: data.developerOrganizationId,\n extensionId: data.extensionId,\n });\n // controls init message for getting started with starter scaffold\n let starterScaffoldWritten = false;\n try {\n const { skipped, existingPackageJson, createdManifestOnly } =\n await scaffoldExtension(targetDir, data.extensionName);\n starterScaffoldWritten = !existingPackageJson;\n if (existingPackageJson) {\n if (createdManifestOnly) {\n this.log(\n `package.json found; created ${CLI_CONFIG.manifestFileName} only (starter scaffold skipped).`,\n );\n } else {\n this.log(\n 'package.json found; skipped starter scaffold (manifest already present).',\n );\n }\n } else if (skipped.length > 0) {\n this.log(\n `Skipped starter files (already present): ${skipped.join(', ')}`,\n );\n }\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n try {\n await createExtensionDraftVersion(\n client,\n data.extensionId,\n join(targetDir, CLI_CONFIG.manifestFileName),\n );\n } catch (e) {\n this.error(formatHttpClientError(e), { exit: 2 });\n }\n\n if (data.isNewDeveloperOrganizationCreated) {\n this.log(`Created organization: \"${data.developerOrganizationName}\".`);\n } else {\n this.log(`Developer organization: \"${data.developerOrganizationName}\".`);\n }\n this.log(`Created app: \"${data.extensionName}\".`);\n this.debug(`Generated config file at ${configFilePath}`);\n\n this.log('');\n this.log(`Success! Extension \"${data.extensionName}\" is ready.`);\n this.log('Next steps:');\n let step = 1;\n const isCurrentDir = resolve(process.cwd()) === targetDir;\n const displayPath = relative(process.cwd(), targetDir);\n if (!isCurrentDir) {\n this.log(` ${step++}. cd ${JSON.stringify(displayPath)}`);\n }\n if (starterScaffoldWritten) {\n this.log(` ${step++}. npm install`);\n this.log(` ${step++}. npm run dev`);\n this.log(\n ` → http://localhost:${String(CLI_CONFIG.scaffoldViteDevPort)} (see vite.config.ts)`,\n );\n }\n this.log(\n ` ${step++}. Edit ${CLI_CONFIG.manifestFileName} as needed, then run 'kittl app update'`,\n );\n this.log(` ${step++}. When you have a build, run 'kittl app upload'`);\n }\n}\n","import { access, mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { CLI_CONFIG } from '../constants';\nimport { isSystemError } from './error';\nimport {\n agentsMdTemplate,\n ICON_SVG_TEMPLATE,\n indexHtmlTemplate,\n indexTypescriptTemplate,\n manifestTemplate,\n packageJsonTemplate,\n viteConfigTemplate,\n} from './templates';\n\nexport type ScaffoldExtensionResult = {\n // Paths relative to `cwd` that were created.\n written: string[];\n // Paths relative to `cwd` that already existed and were left unchanged.\n skipped: string[];\n /**\n * `package.json` was already present, Vite/HTML scaffolding was skipped.\n * The extension manifest file is still ensured (see {@link createdManifestOnly}).\n */\n existingPackageJson?: true;\n createdManifestOnly?: true;\n};\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch (e) {\n if (isSystemError(e, 'ENOENT')) {\n return false;\n }\n throw e;\n }\n}\n\n/**\n * Writes a minimal Vite + HTML starter in the extension root after init (internal CLI config lives under `.kittl/`).\n * If `package.json` already exists, skips the starter kit but still creates the extension manifest when missing.\n * Otherwise, existing paths are left unchanged and only missing files are written.\n */\nexport async function scaffoldExtension(\n cwd: string,\n displayName: string,\n): Promise<ScaffoldExtensionResult> {\n const manifestPath = join(cwd, CLI_CONFIG.manifestFileName);\n const packageJsonPath = join(cwd, 'package.json');\n\n if (await fileExists(packageJsonPath)) {\n if (await fileExists(manifestPath)) {\n return {\n written: [],\n skipped: [],\n existingPackageJson: true,\n };\n }\n await writeFile(manifestPath, manifestTemplate(displayName), 'utf8');\n return {\n written: [CLI_CONFIG.manifestFileName],\n skipped: [],\n existingPackageJson: true,\n createdManifestOnly: true,\n };\n }\n\n const files: { rel: string; path: string; content: string }[] = [\n {\n rel: CLI_CONFIG.manifestFileName,\n path: manifestPath,\n content: manifestTemplate(displayName),\n },\n {\n rel: 'package.json',\n path: packageJsonPath,\n content: packageJsonTemplate(displayName),\n },\n {\n rel: 'AGENTS.md',\n path: join(cwd, 'AGENTS.md'),\n content: agentsMdTemplate(displayName),\n },\n {\n rel: 'vite.config.ts',\n path: join(cwd, 'vite.config.ts'),\n content: viteConfigTemplate(),\n },\n {\n rel: 'index.html',\n path: join(cwd, 'index.html'),\n content: indexHtmlTemplate(displayName),\n },\n {\n rel: join('public', 'icon.svg'),\n path: join(cwd, 'public', 'icon.svg'),\n content: ICON_SVG_TEMPLATE,\n },\n {\n rel: join('src', 'index.ts'),\n path: join(cwd, 'src', 'index.ts'),\n content: indexTypescriptTemplate(displayName),\n },\n ];\n\n await mkdir(join(cwd, 'public'), { recursive: true });\n await mkdir(join(cwd, 'src'), { recursive: true });\n\n const written: string[] = [];\n const skipped: string[] = [];\n\n for (const f of files) {\n if (await fileExists(f.path)) {\n skipped.push(f.rel);\n continue;\n }\n await writeFile(f.path, f.content, 'utf8');\n written.push(f.rel);\n }\n\n return { written, skipped };\n}\n","/**\n * Default extension scaffold strings. Adjust here to change the baseline Kittl extension layout.\n */\n\nimport { CLI_CONFIG } from '../constants';\nimport type { ExtensionManifest } from './schemas/extension-manifest';\n\n/**\n * Default legal placeholder links used in the generated manifest.\n * These are intentionally obvious placeholders so they get replaced before release.\n */\nconst DEFAULT_TERMS_URL = 'https://example.com/terms';\nconst DEFAULT_PRIVACY_URL = 'https://example.com/privacy';\n\n/**\n * Default embedded app entrypoint produced by the Vite scaffold build.\n * This path is interpreted relative to the built artifact root (Vite `outDir`).\n */\nconst DEFAULT_MAIN_APP_PANEL_PATH = 'index.html';\n\n// manifest JSON Schema URL for `manifest.json`\nexport const EXTENSION_MANIFEST_JSON_SCHEMA_URL =\n 'https://api.kittl.com/extensions/manifest/schema.json';\n\nfunction packageNameFromExtensionName(name: string): string {\n const slug = name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '');\n return slug.length > 0 ? slug : 'kittl-extension';\n}\n\n/**\n * Default manifest object written to `manifest.json` and pushed as the first draft version.\n * The scaffold includes every required field from the current manifest schema.\n */\nexport function initialExtensionManifest(\n displayName: string,\n): ExtensionManifest {\n const value = displayName.trim() || 'Unnamed extension';\n return {\n $schema: EXTENSION_MANIFEST_JSON_SCHEMA_URL,\n displayName: value,\n icon: 'icon.svg',\n tagline: `${value} for Kittl.`,\n installPage: {\n description: `Install ${value} to use this extension in Kittl.`,\n coverImage: 'icon.svg',\n termsAndConditionsLink: DEFAULT_TERMS_URL,\n privacyPolicyLink: DEFAULT_PRIVACY_URL,\n },\n config: {\n // New projects start without privileged scopes and can opt into them later.\n scopes: ['design:state:read', 'design:state:write'],\n embed: {\n mainAppPanel: {\n path: DEFAULT_MAIN_APP_PANEL_PATH,\n },\n },\n },\n };\n}\n\n/**\n * Serialized manifest file contents written by the CLI scaffold.\n */\nexport function manifestTemplate(displayName: string): string {\n return `${JSON.stringify(\n initialExtensionManifest(displayName),\n null, // replacer: none - default serialization\n 2, // space: 2-space indent + line breaks\n )}\\n`;\n}\n\nexport function packageJsonTemplate(displayName: string): string {\n return `${JSON.stringify(\n {\n name: packageNameFromExtensionName(displayName),\n private: true,\n version: '0.0.0',\n type: 'module',\n scripts: {\n dev: 'vite',\n build: 'vite build',\n preview: 'vite preview',\n },\n dependencies: {\n '@kittl/sdk': '^0.0.1',\n },\n devDependencies: {\n vite: '^8.0.0',\n },\n },\n null, // replacer: none, default serialization\n 2, // space: 2-space indent + line breaks\n )}\\n`;\n}\n\nexport function viteConfigTemplate(): string {\n return `import { readdirSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { defineConfig } from 'vite';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction htmlBuildInputs(): Record<string, string> {\n return Object.fromEntries(\n readdirSync(__dirname)\n .filter((name) => name.endsWith('.html'))\n .map((name) => [basename(name, '.html'), join(__dirname, name)]),\n );\n}\n\nconst contentSecurityPolicy =\n \"default-src 'self'; style-src 'self' 'unsafe-inline'; img-src https: data: blob:; connect-src 'self' https: ws: wss: http://localhost:* http://127.0.0.1:*; frame-ancestors 'self' https://*.kittl.io https://*.kittl.com http://localhost:* http://127.0.0.1:*\";\n\nexport default defineConfig({\n server: {\n port: ${CLI_CONFIG.scaffoldViteDevPort},\n headers: {\n 'Content-Security-Policy': contentSecurityPolicy,\n },\n },\n publicDir: 'public',\n build: {\n outDir: 'dist',\n rolldownOptions: {\n input: htmlBuildInputs(),\n },\n },\n base: './',\n});\n`;\n}\n\nexport function agentsMdTemplate(displayName: string): string {\n const name = displayName.trim() || 'Unnamed extension';\n return `# Kittl app\n\n**${name}** — [Kittl](https://www.kittl.com) starter from \\`kittl app init\\`. Kittl runs this app **inside a sandboxed iframe** in the editor; **@kittl/sdk** talks to the **Kittl canvas and design** (layers, artboards, export, drag-and-drop). **${CLI_CONFIG.manifestFileName}** holds scopes, install page, and embed paths.\n\n## AI instructions\n\n- **SDK (agents / LLMs):** \\`https://sdk-docs.kittl.dev/llms-full.txt\\` is the source of truth for \\`@kittl/sdk\\` APIs.\n- **SDK (humans):** https://sdk-docs.kittl.dev/\n- **Build:** Vite 8; production uses **Rolldown** via \\`build.rolldownOptions\\` (see \\`vite.config.ts\\`).\n- **Entries:** Do not hardcode HTML entry points. \\`htmlBuildInputs()\\` maps every root \\`*.html\\` to \\`build.rolldownOptions.input\\`.\n- **Rule (Security):** Never remove \\`localhost\\`, \\`127.0.0.1\\`, or \\`ws:\\` from the CSP in \\`vite.config.ts\\`.\n- **Reason:** These are required for the Kittl Live Bridge and Vite HMR. Removing them will break the connection between the Kittl Canvas and this local app.\n\n## Project structure\n\n- **${CLI_CONFIG.manifestFileName}**: Extension metadata. [Schema](${EXTENSION_MANIFEST_JSON_SCHEMA_URL})\n- **.kittl/**: Local Kittl CLI state (developer org, extension id); not shipped with the UI bundle.\n- **src/**: TypeScript imported from each root HTML shell.\n- **dist/**: \\`pnpm run build\\` output; manifest \\`embed\\` paths usually target files here after upload.\n- **\\`*.html\\` (next to \\`vite.config.ts\\`): Each file is a Rolldown entry (chunk name = basename without \\`.html\\`).\n\n## Workflow & commands\n\n| Command | Action |\n| :--- | :--- |\n| \\`pnpm install\\` | Install dependencies (once per clone or after lockfile changes). |\n| \\`pnpm run dev\\` | Vite dev server + HMR (port in \\`vite.config.ts\\`). |\n| \\`pnpm run build\\` | Production bundle into \\`dist/\\` (Rolldown). |\n| \\`kittl app update\\` | Push manifest changes to Kittl. |\n| \\`kittl app upload\\` | Upload the current \\`dist/\\` to Kittl. |\n| \\`kittl app --help\\` | Other \\`kittl app\\` subcommands. |\n\n**Note for agents:** A typical deployment sequence is \\`pnpm run build\\` → \\`kittl app update\\` → \\`kittl app upload\\`.\n\n## Terminology\n\n- **Extension:** Technical implementation—manifest, scopes, embeds, platform APIs.\n- **App:** Product name in Kittl and in the CLI (\\`kittl app ...\\`); same codebase as an extension.\n- **Sandboxed iframe:** The UI is embedded in an iframe (sandboxed); use **@kittl/sdk** to reach the host and canvas—do not assume unfettered access to the parent page.\n`;\n}\n\nexport function indexHtmlTemplate(displayName: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${displayName}</title>\n </head>\n <body>\n <div id=\"app\">\n <h1>Hello Kittl!</h1>\n <p>Welcome to your new extension: ${displayName}</p>\n <button id=\"doSomething\" type=\"button\">Do some magic!</button>\n </div>\n <script type=\"module\" src=\"/src/index.ts\"></script>\n </body>\n</html>\n`;\n}\n\nexport function indexTypescriptTemplate(displayName: string): string {\n return `import { kittl } from '@kittl/sdk';\n\ndocument.getElementById('doSomething')?.addEventListener('click', async () => {\n await kittl.design.text.addText({\n text: 'Hello ${displayName} from Kittl SDK!',\n position: {\n relative: {\n to: 'viewport',\n location: 'center',\n },\n },\n size: {\n height: 100,\n width: 400,\n },\n });\n});\n`;\n}\n\n// kittl logo\nexport const ICON_SVG_TEMPLATE =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"128\" height=\"128\" viewBox=\"0 0 1024 1024\"><rect width=\"1024\" height=\"1024\" rx=\"225\" fill=\"#DEFE00\"/><path fill=\"#080B10\" transform=\"translate(581,235)\" d=\"M0 0 C-7.93 26.81 -15.97 53.57 -24.12 80.31 C-24.35 81.04 -24.57 81.76 -24.79 82.5 C-25.92 86.19 -27.04 89.88 -28.17 93.57 C-28.5 94.67 -28.5 94.67 -28.85 95.8 C-29.3 97.29 -29.76 98.78 -30.21 100.27 C-35.39 117.26 -40.54 134.25 -45.69 151.25 C-46.09 152.58 -46.49 153.92 -46.9 155.25 C-47.68 157.83 -48.46 160.4 -49.24 162.98 C-50 165.48 -50.75 167.98 -51.51 170.48 C-53.37 176.6 -55.22 182.72 -57.06 188.84 C-57.99 191.91 -58.92 194.99 -59.84 198.06 C-60.29 199.54 -60.74 201.02 -61.18 202.51 C-61.8 204.56 -62.42 206.61 -63.04 208.67 C-63.4 209.84 -63.75 211.02 -64.12 212.23 C-65 215 -65 215 -66 217 C-31.32 207.79 -0.81 191.01 25.38 166.43 C27.48 164.48 29.6 162.63 31.81 160.81 C34.85 158.23 37.44 155.4 40.01 152.35 C41.45 150.66 42.91 148.99 44.39 147.34 C73.97 114.11 93.03 70.13 98 26 C113.47 23.05 128.96 20.3 144.5 17.74 C155.19 15.98 165.86 14.18 176.54 12.36 C178.95 11.95 181.37 11.54 183.79 11.13 C184.59 10.99 185.4 10.85 186.23 10.71 C187.86 10.44 189.49 10.16 191.13 9.88 C195.22 9.18 199.31 8.49 203.41 7.79 C207.32 7.12 211.22 6.45 215.13 5.79 C216.6 5.54 218.06 5.29 219.52 5.04 C221.55 4.69 223.57 4.35 225.6 4.01 C226.74 3.81 227.89 3.62 229.07 3.42 C232 3 232 3 236 3 C236.16 11.12 235.76 19 234.75 27.06 C234.62 28.15 234.48 29.23 234.34 30.35 C226.13 93.59 192.52 153.61 144 195 C143.05 195.84 142.11 196.67 141.13 197.53 C115.92 219.57 86.53 236.49 56 250 C55.6 259.92 56.83 269.35 58.31 279.13 C58.55 280.7 58.78 282.28 59.01 283.86 C59.57 287.61 60.14 291.36 60.71 295.11 C61.08 297.53 61.43 299.95 61.79 302.37 C64.96 323.35 70.45 343.85 77 364 C77.44 365.35 77.87 366.69 78.31 368.04 C87.9 397.66 98.51 426.64 111.58 454.91 C112.79 457.54 113.99 460.18 115.18 462.82 C120.11 473.66 125.8 484.06 131.59 494.45 C132.83 496.69 134.06 498.93 135.28 501.18 C144 517.14 153.68 532.57 165 546.81 C165.51 547.45 166.02 548.1 166.55 548.76 C167 549.32 167.45 549.87 167.92 550.45 C169 552 169 552 170 555 C169.42 555.28 168.83 555.56 168.23 555.85 C154.35 562.49 140.48 569.18 126.63 575.9 C115.75 581.18 104.87 586.45 93.98 591.7 C86.76 595.18 79.56 598.67 72.36 602.17 C66.13 605.19 59.89 608.21 53.66 611.23 C51.35 612.34 49.05 613.46 46.75 614.58 C44.04 615.89 41.33 617.2 38.63 618.5 C37.87 618.87 37.12 619.24 36.34 619.61 C33.37 621.03 31.33 622 28 622 C7.88 582.22 -1.64 541.14 -9.53 497.6 C-9.84 495.9 -10.14 494.21 -10.45 492.52 C-11.93 484.45 -13.35 476.42 -14.12 468.25 C-14.61 462.97 -14.61 462.97 -15.48 457.76 C-16.15 454.21 -16.43 450.66 -16.72 447.07 C-16.78 446.31 -16.84 445.56 -16.91 444.78 C-17.11 442.37 -17.3 439.97 -17.5 437.56 C-17.7 435.16 -17.89 432.76 -18.09 430.36 C-18.21 428.87 -18.34 427.38 -18.45 425.89 C-18.7 422.94 -18.99 420.04 -19.49 417.13 C-19.98 414.12 -20.26 411.19 -20.46 408.15 C-20.54 407.02 -20.62 405.88 -20.7 404.71 C-20.78 403.49 -20.86 402.26 -20.94 401 C-21.06 399.08 -21.06 399.08 -21.19 397.11 C-21.47 392.93 -21.74 388.75 -22 384.56 C-22.05 383.85 -22.09 383.14 -22.14 382.4 C-24.41 346.58 -25.21 310.89 -25 275 C-26.05 275.24 -27.1 275.48 -28.19 275.73 C-47.22 279.84 -66.64 281.24 -86 283 C-94.42 309.89 -102.59 336.84 -110.71 363.82 C-112.14 368.58 -113.57 373.34 -115 378.09 C-115.36 379.3 -115.36 379.3 -115.73 380.52 C-122.46 402.89 -129.26 425.23 -136.06 447.57 C-137.03 450.75 -137.99 453.93 -138.96 457.11 C-139.6 459.21 -140.24 461.32 -140.88 463.42 C-145.3 477.93 -149.64 492.47 -154 507 C-195.58 507 -237.16 507 -280 507 C-278.24 499.96 -276.51 493.16 -274.25 486.31 C-271.9 479.06 -269.79 471.77 -267.77 464.42 C-264.19 451.54 -260.37 438.73 -256.5 425.94 C-255.24 421.76 -253.98 417.58 -252.72 413.4 C-252.41 412.37 -252.1 411.35 -251.78 410.29 C-249.63 403.13 -247.52 395.96 -245.44 388.79 C-242.47 378.56 -239.41 368.37 -236.32 358.19 C-230.85 340.22 -230.85 340.22 -225.56 322.19 C-222.19 310.48 -218.62 298.84 -215.06 287.19 C-210.72 272.95 -206.4 258.7 -202.19 244.42 C-200.36 238.2 -198.51 231.98 -196.65 225.77 C-196.35 224.76 -196.05 223.75 -195.74 222.71 C-195.12 220.63 -194.5 218.55 -193.88 216.47 C-188.13 197.22 -188.13 197.22 -182.5 177.94 C-178.85 165.29 -174.97 152.72 -171.13 140.13 C-164.93 119.8 -158.75 99.46 -153 79 C-188.09 81.55 -226.46 97.99 -253 121 C-253.83 121.71 -254.66 122.42 -255.51 123.14 C-274.69 139.92 -289.02 161.6 -291.21 187.46 C-293.11 216.05 -280.75 245.26 -264.87 268.69 C-264.26 269.78 -263.64 270.87 -263 272 C-264.07 275.31 -265.83 276.91 -268.61 278.89 C-269.36 279.43 -270.1 279.96 -270.86 280.52 C-271.67 281.09 -272.48 281.66 -273.31 282.25 C-275.05 283.51 -276.79 284.76 -278.53 286.02 C-279.43 286.68 -280.33 287.33 -281.27 288 C-285.68 291.23 -290.03 294.55 -294.37 297.88 C-295.25 298.54 -296.12 299.21 -297.01 299.89 C-299.68 301.93 -302.34 303.96 -305 306 C-316.83 315.06 -328.7 324.04 -340.71 332.85 C-346.17 336.86 -351.59 340.92 -357 345 C-361.44 343.43 -363.83 339.89 -366.62 336.31 C-367.42 335.31 -367.42 335.31 -368.22 334.28 C-401.71 291.18 -419.04 237.97 -413.54 183.33 C-412.98 179.14 -412.11 175.08 -411 171 C-410.81 170.29 -410.62 169.57 -410.43 168.84 C-405.86 152.16 -397.84 136.47 -387 123 C-386.27 122.07 -385.54 121.14 -384.79 120.18 C-377.09 110.54 -368.68 102.62 -359 95 C-358.12 94.29 -357.24 93.58 -356.33 92.85 C-316.02 61.35 -264.24 45.67 -214.89 35.25 C-214.08 35.08 -213.27 34.91 -212.43 34.73 C-192.67 30.58 -172.78 27.22 -152.85 23.93 C-147.76 23.09 -142.68 22.24 -137.59 21.39 C-129.1 19.97 -120.6 18.56 -112.1 17.15 C-102.3 15.53 -92.51 13.9 -82.71 12.26 C-73.2 10.67 -63.69 9.09 -54.19 7.51 C-50.17 6.84 -46.15 6.17 -42.13 5.5 C-37.42 4.71 -32.71 3.93 -28 3.15 C-26.28 2.87 -24.56 2.58 -22.83 2.29 C-20.48 1.9 -18.12 1.51 -15.77 1.12 C-14.76 0.95 -14.76 0.95 -13.72 0.77 C-9.08 0.03 -4.68 -0.09 0 0 Z\"/></svg>';\n","import type { AxiosInstance } from 'axios';\nimport { z } from 'zod';\n\nconst developerOrganizationSchema = z.object({\n id: z.string(),\n name: z.string(),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n});\n\nconst listResponseSchema = z.object({\n success: z.literal(true),\n result: z.object({\n developerOrganizations: z.array(developerOrganizationSchema),\n }),\n});\n\nconst createOrgResponseSchema = z.object({\n success: z.literal(true),\n result: z.object({\n developerOrganizationId: z.string(),\n }),\n});\n\nconst createExtensionResponseSchema = z.object({\n success: z.literal(true),\n result: z.object({\n extensionId: z.string(),\n }),\n});\n\nexport type DeveloperOrganization = z.infer<typeof developerOrganizationSchema>;\n\nexport async function listDeveloperOrganizations(\n client: AxiosInstance,\n): Promise<DeveloperOrganization[]> {\n const { data } = await client.get('/developer-organizations');\n const parsed = listResponseSchema.parse(data);\n return parsed.result.developerOrganizations;\n}\n\nexport async function createDeveloperOrganization(\n client: AxiosInstance,\n name: string,\n): Promise<string> {\n const { data } = await client.post('/developer-organizations', {\n name,\n });\n const parsed = createOrgResponseSchema.parse(data);\n return parsed.result.developerOrganizationId;\n}\n\nexport async function createExtensionInDeveloperOrganization(\n client: AxiosInstance,\n developerOrganizationId: string,\n body: { name: string; id?: string },\n): Promise<string> {\n const path = `/developer-organizations/${developerOrganizationId}/extensions`;\n const { data } = await client.post(path, body);\n const parsed = createExtensionResponseSchema.parse(data);\n return parsed.result.extensionId;\n}\n","import type { AxiosInstance } from 'axios';\nimport { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport { useCallback, useState } from 'react';\nimport { formatHttpClientError } from '../../../core/error';\nimport {\n createDeveloperOrganization,\n createExtensionInDeveloperOrganization,\n type DeveloperOrganization,\n} from '../../../services/developer-organizations.service';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { spacing } from '../../theme/tokens';\nimport type { AppsInitOrgPickerResult } from './AppsInitOrgPickerView';\nimport { AppsInitOrgPickerView } from './AppsInitOrgPickerView';\nimport type { TextInputViewDone } from './TextInputView';\nimport { TextInputView } from './TextInputView';\n\nexport type AppInitWizardSuccess = {\n developerOrganizationId: string;\n developerOrganizationName: string;\n extensionId: string;\n extensionName: string;\n // True when the org was created in this wizard (vs chosen from the list).\n isNewDeveloperOrganizationCreated: boolean;\n};\n\nexport type AppInitWizardResult =\n | { kind: 'cancelled' }\n | { kind: 'success'; data: AppInitWizardSuccess };\n\ntype Step = 'pick' | 'org_name' | 'ext_name';\n\ntype WizardDraft = {\n developerOrganizationId?: string;\n developerOrganizationName?: string;\n isNewDeveloperOrganizationCreated?: boolean;\n};\n\nexport type AppInitWizardViewProps = {\n organizations: DeveloperOrganization[];\n client: AxiosInstance;\n extensionNameSuggestion?: string;\n onDone: (result: AppInitWizardResult) => void;\n};\n\nfunction AppInitStepShell({\n width,\n apiError,\n isLoading,\n loadingText,\n children,\n}: {\n width: number | string;\n apiError: string | null;\n isLoading: boolean;\n loadingText: string;\n children: ReactNode;\n}) {\n return (\n <Box flexDirection=\"column\" width={width} minWidth={0}>\n {apiError ? (\n <Box marginLeft={spacing.sm} marginBottom={spacing.sm}>\n <Text {...textStyles.error}>{apiError}</Text>\n </Box>\n ) : null}\n {isLoading ? (\n <Box {...layoutStyles.viewColumn}>\n <Text {...textStyles.muted}>{loadingText}…</Text>\n </Box>\n ) : (\n children\n )}\n </Box>\n );\n}\n\nexport function AppInitWizardView({\n organizations,\n client,\n extensionNameSuggestion,\n onDone,\n}: AppInitWizardViewProps) {\n const width = useTerminalWidth();\n const w = width > 0 ? width : '100%';\n\n const [step, setStep] = useState<Step>('pick');\n const [draft, setDraft] = useState<WizardDraft>({});\n const [apiError, setApiError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const runTask = useCallback(async (task: () => Promise<void>) => {\n setApiError(null);\n setIsLoading(true);\n try {\n await task();\n } catch (e) {\n setApiError(formatHttpClientError(e));\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const handlePick = useCallback(\n (r: AppsInitOrgPickerResult) => {\n if (r.kind === 'cancelled') {\n onDone({ kind: 'cancelled' });\n return;\n }\n setApiError(null);\n if (r.kind === 'selected') {\n setDraft({\n developerOrganizationId: r.developerOrganizationId,\n developerOrganizationName: r.name,\n isNewDeveloperOrganizationCreated: false,\n });\n setStep('ext_name');\n return;\n }\n setDraft({});\n setStep('org_name');\n },\n [onDone],\n );\n\n const handleOrgName = useCallback(\n (r: TextInputViewDone) => {\n if (r.kind === 'cancelled') {\n onDone({ kind: 'cancelled' });\n return;\n }\n void runTask(async () => {\n const developerOrganizationId = await createDeveloperOrganization(\n client,\n r.value,\n );\n setDraft({\n developerOrganizationId,\n developerOrganizationName: r.value,\n isNewDeveloperOrganizationCreated: true,\n });\n setStep('ext_name');\n });\n },\n [client, onDone, runTask],\n );\n\n const handleExtName = useCallback(\n (r: TextInputViewDone) => {\n if (r.kind === 'cancelled') {\n onDone({ kind: 'cancelled' });\n return;\n }\n const orgId = draft.developerOrganizationId;\n const orgName = draft.developerOrganizationName;\n if (!orgId || !orgName) {\n return;\n }\n const isNewDeveloperOrganizationCreated = Boolean(\n draft.isNewDeveloperOrganizationCreated,\n );\n void runTask(async () => {\n const extensionId = await createExtensionInDeveloperOrganization(\n client,\n orgId,\n { name: r.value },\n );\n onDone({\n kind: 'success',\n data: {\n developerOrganizationId: orgId,\n developerOrganizationName: orgName,\n extensionId,\n extensionName: r.value,\n isNewDeveloperOrganizationCreated,\n },\n });\n });\n },\n [client, draft, onDone, runTask],\n );\n\n switch (step) {\n case 'pick':\n return (\n <AppsInitOrgPickerView\n organizations={organizations}\n onDone={handlePick}\n />\n );\n case 'org_name':\n return (\n <AppInitStepShell\n width={w}\n apiError={apiError}\n isLoading={isLoading}\n loadingText=\"Creating organization\"\n >\n <TextInputView\n key=\"wizard-org-name\"\n label=\"New organization name:\"\n placeholder=\"e.g. Functor Fountain Org\"\n onDone={handleOrgName}\n />\n </AppInitStepShell>\n );\n case 'ext_name':\n return (\n <AppInitStepShell\n width={w}\n apiError={apiError}\n isLoading={isLoading}\n loadingText=\"Creating extension\"\n >\n <TextInputView\n key=\"wizard-ext-name\"\n label=\"Extension name:\"\n placeholder=\"e.g. WASM-powered toaster\"\n initialValue={extensionNameSuggestion}\n onDone={handleExtName}\n />\n </AppInitStepShell>\n );\n }\n}\n","import { Box, type Key, Text, useInput } from 'ink';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { isSubmitKey } from '../../../core/utils';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { colors } from '../../theme/tokens';\n\nexport type DeveloperOrganizationRow = {\n id: string;\n name: string;\n};\n\nexport type AppsInitOrgPickerResult =\n | { kind: 'selected'; developerOrganizationId: string; name: string }\n | { kind: 'create_new' }\n | { kind: 'cancelled' };\n\nexport type AppsInitOrgPickerViewProps = {\n organizations: DeveloperOrganizationRow[];\n onDone: (result: AppsInitOrgPickerResult) => void;\n};\n\nconst CREATE_NEW_LABEL = 'Create new organization';\n\nexport function AppsInitOrgPickerView({\n organizations,\n onDone,\n}: AppsInitOrgPickerViewProps) {\n const width = useTerminalWidth();\n const [index, setIndex] = useState(0);\n\n const indexRef = useRef(index);\n const organizationsRef = useRef(organizations);\n const onDoneRef = useRef(onDone);\n\n indexRef.current = index;\n organizationsRef.current = organizations;\n onDoneRef.current = onDone;\n\n useEffect(() => {\n const maxIndex = organizations.length;\n setIndex((i) => (i > maxIndex ? maxIndex : i));\n }, [organizations]);\n\n const labels = useMemo(\n () => [...organizations.map((o) => o.name), CREATE_NEW_LABEL],\n [organizations],\n );\n\n const handleInput = useCallback((_input: string, key: Key) => {\n if (key.escape) {\n onDoneRef.current({ kind: 'cancelled' });\n return;\n }\n if (isSubmitKey(key)) {\n const idx = indexRef.current;\n const orgs = organizationsRef.current;\n if (idx === orgs.length) {\n onDoneRef.current({ kind: 'create_new' });\n return;\n }\n const org = orgs[idx];\n onDoneRef.current({\n kind: 'selected',\n developerOrganizationId: org.id,\n name: org.name,\n });\n return;\n }\n if (key.upArrow) {\n setIndex((i) => {\n const rc = organizationsRef.current.length + 1;\n const next = i <= 0 ? rc - 1 : i - 1;\n indexRef.current = next;\n return next;\n });\n return;\n }\n if (key.downArrow) {\n setIndex((i) => {\n const rc = organizationsRef.current.length + 1;\n const next = i >= rc - 1 ? 0 : i + 1;\n indexRef.current = next;\n return next;\n });\n }\n }, []);\n\n useInput(handleInput);\n\n const empty = organizations.length === 0;\n\n return (\n <Box\n {...layoutStyles.viewColumn}\n width={width > 0 ? width : '100%'}\n minWidth={0}\n >\n <Text {...textStyles.title}>Select developer organization</Text>\n <Text {...textStyles.muted}>↑↓ move · Enter confirm · Esc cancel</Text>\n <Box {...layoutStyles.section} flexDirection=\"column\">\n {empty ? (\n <Box marginBottom={1}>\n <Text {...textStyles.muted}>\n {\"No organizations found. Let's make one!\"}\n </Text>\n </Box>\n ) : null}\n {labels.map((label, i) => {\n const isSelected = i === index;\n return (\n <Text\n key={`${label}-${i}`}\n bold={isSelected}\n color={isSelected ? colors.accent : undefined}\n >\n {isSelected ? '› ' : ' '}\n {label}\n </Text>\n );\n })}\n </Box>\n </Box>\n );\n}\n","import { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useCallback, useState } from 'react';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\n\nexport type TextInputViewDone =\n | { kind: 'submit'; value: string }\n | { kind: 'cancelled' };\n\nexport type TextInputViewProps = {\n label: string;\n placeholder?: string;\n /** Initial field value (trimmed once on mount). */\n initialValue?: string;\n // When true, Enter on whitespace-only keeps you on the screen with an error.\n requireNonEmpty?: boolean;\n onDone: (result: TextInputViewDone) => void;\n};\n\n/**\n * text input field using Ink + `ink-text-input`.\n */\nexport function TextInputView({\n label,\n placeholder,\n initialValue,\n requireNonEmpty = true,\n onDone,\n}: TextInputViewProps) {\n const width = useTerminalWidth();\n const [value, setValue] = useState(() => initialValue?.trim() ?? '');\n const [error, setError] = useState<string | null>(null);\n\n const finish = useCallback(\n (result: TextInputViewDone) => {\n onDone(result);\n },\n [onDone],\n );\n\n useInput((_input, key) => {\n if (key.escape) {\n finish({ kind: 'cancelled' });\n }\n });\n\n const handleSubmit = useCallback(\n (submitted: string) => {\n const trimmed = submitted.trim();\n if (requireNonEmpty && trimmed.length === 0) {\n setError('Cannot be empty.');\n return;\n }\n setError(null);\n finish({ kind: 'submit', value: trimmed });\n },\n [finish, requireNonEmpty],\n );\n\n return (\n <Box\n {...layoutStyles.viewColumn}\n width={width > 0 ? width : '100%'}\n minWidth={0}\n >\n <Text {...textStyles.title}>{label}</Text>\n <Box {...layoutStyles.section} flexDirection=\"row\" flexWrap=\"wrap\">\n <TextInput\n value={value}\n onChange={(v) => {\n setValue(v);\n if (error) {\n setError(null);\n }\n }}\n onSubmit={handleSubmit}\n placeholder={placeholder ?? ''}\n />\n </Box>\n {error ? (\n <Text {...textStyles.error}>{error}</Text>\n ) : (\n <Text {...textStyles.muted}>Enter confirm · Esc cancel</Text>\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":["join","Box","Text","useCallback","useState","Box","Text","useInput","useCallback","useState","jsx","jsxs","useState","useCallback","useInput","Box","Text","jsx","jsxs","Box","Text","useState","useCallback","join"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/app/init.ts","../../../src/core/scaffolder.ts","../../../src/core/templates.ts","../../../src/services/developer-organizations.service.ts","../../../src/ui/views/app-init/AppInitWizardView.tsx","../../../src/ui/views/app-init/AppsInitOrgPickerView.tsx","../../../src/ui/views/app-init/TextInputView.tsx"],"sourcesContent":["import { join, relative, resolve } from 'node:path';\nimport { Args } from '@oclif/core';\nimport { CLI_CONFIG } from '../../constants';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatHttpClientError } from '../../core/error';\nimport { getFileNameFromPath } from '../../core/files';\nimport {\n internalConfigExists,\n internalConfigPath,\n writeInternalConfig,\n} from '../../core/internal.config';\nimport { scaffoldExtension } from '../../core/scaffolder';\nimport { ensureDirectory } from '../../core/utils';\nimport {\n type DeveloperOrganization,\n listDeveloperOrganizations,\n} from '../../services/developer-organizations.service';\nimport { createExtensionDraftVersion } from '../../services/extensions.service';\nimport { AppInitWizardView } from '../../ui/views/app-init';\n\nexport default class AppInit extends BaseCommand {\n public static override description =\n 'Initialize a Kittl app in the current directory OR in a custom PATH';\n\n public static override args = {\n path: Args.string({\n description: 'Directory for the app (created if it does not exist)',\n default: '.',\n required: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { args } = await this.parse(AppInit);\n\n await this.ensureAuthenticated();\n\n const targetDir = resolve(process.cwd(), args.path);\n\n try {\n await ensureDirectory(targetDir);\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n if (await internalConfigExists(targetDir)) {\n this.error(\n `Kittl config already exists at ${internalConfigPath(targetDir)}. Remove it or choose a different directory.`,\n { exit: 2 },\n );\n }\n\n const client = this.getKittlApiClient();\n let organizations: DeveloperOrganization[];\n try {\n organizations = await listDeveloperOrganizations(client);\n } catch (e) {\n this.error(formatHttpClientError(e), { exit: 2 });\n }\n\n const extensionNameSuggestion =\n args.path === '.' ? undefined : getFileNameFromPath(targetDir);\n\n const wizardResult = await this.renderView(AppInitWizardView, {\n organizations,\n client,\n extensionNameSuggestion,\n });\n\n if (wizardResult.kind === 'cancelled') {\n this.exit(130);\n }\n\n const { data } = wizardResult;\n\n const configFilePath = await writeInternalConfig(targetDir, {\n developerOrganizationId: data.developerOrganizationId,\n extensionId: data.extensionId,\n });\n // controls init message for getting started with starter scaffold\n let starterScaffoldWritten = false;\n try {\n const { skipped, existingPackageJson, createdManifestOnly } =\n await scaffoldExtension(targetDir, data.extensionName);\n starterScaffoldWritten = !existingPackageJson;\n if (existingPackageJson) {\n if (createdManifestOnly) {\n this.log(\n `package.json found; created ${CLI_CONFIG.manifestFileName} only (starter scaffold skipped).`,\n );\n } else {\n this.log(\n 'package.json found; skipped starter scaffold (manifest already present).',\n );\n }\n } else if (skipped.length > 0) {\n this.log(\n `Skipped starter files (already present): ${skipped.join(', ')}`,\n );\n }\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n try {\n await createExtensionDraftVersion(\n client,\n data.extensionId,\n join(targetDir, CLI_CONFIG.manifestFileName),\n );\n } catch (e) {\n this.error(formatHttpClientError(e), { exit: 2 });\n }\n\n if (data.isNewDeveloperOrganizationCreated) {\n this.log(`Created organization: \"${data.developerOrganizationName}\".`);\n } else {\n this.log(`Developer organization: \"${data.developerOrganizationName}\".`);\n }\n this.log(`Created app: \"${data.extensionName}\".`);\n this.debug(`Generated config file at ${configFilePath}`);\n\n this.log('');\n this.log(`Success! Extension \"${data.extensionName}\" is ready.`);\n this.log('Next steps:');\n let step = 1;\n const isCurrentDir = resolve(process.cwd()) === targetDir;\n const displayPath = relative(process.cwd(), targetDir);\n if (!isCurrentDir) {\n this.log(` ${step++}. cd ${JSON.stringify(displayPath)}`);\n }\n if (starterScaffoldWritten) {\n this.log(` ${step++}. npm install`);\n this.log(` ${step++}. npm run dev`);\n this.log(\n ` → http://localhost:${String(CLI_CONFIG.scaffoldViteDevPort)} (see vite.config.ts)`,\n );\n }\n this.log(\n ` ${step++}. Edit ${CLI_CONFIG.manifestFileName} as needed, then run 'kittl app update'`,\n );\n this.log(` ${step++}. When you have a build, run 'kittl app upload'`);\n }\n}\n","import { access, mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { CLI_CONFIG } from '../constants';\nimport { isSystemError } from './error';\nimport {\n agentsMdTemplate,\n ICON_SVG_TEMPLATE,\n indexHtmlTemplate,\n indexTypescriptTemplate,\n manifestTemplate,\n packageJsonTemplate,\n viteConfigTemplate,\n} from './templates';\n\nexport type ScaffoldExtensionResult = {\n // Paths relative to `cwd` that were created.\n written: string[];\n // Paths relative to `cwd` that already existed and were left unchanged.\n skipped: string[];\n /**\n * `package.json` was already present, Vite/HTML scaffolding was skipped.\n * The extension manifest file is still ensured (see {@link createdManifestOnly}).\n */\n existingPackageJson?: true;\n createdManifestOnly?: true;\n};\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch (e) {\n if (isSystemError(e, 'ENOENT')) {\n return false;\n }\n throw e;\n }\n}\n\n/**\n * Writes a minimal Vite + HTML starter in the extension root after init (internal CLI config lives under `.kittl/`).\n * If `package.json` already exists, skips the starter kit but still creates the extension manifest when missing.\n * Otherwise, existing paths are left unchanged and only missing files are written.\n */\nexport async function scaffoldExtension(\n cwd: string,\n displayName: string,\n): Promise<ScaffoldExtensionResult> {\n const manifestPath = join(cwd, CLI_CONFIG.manifestFileName);\n const packageJsonPath = join(cwd, 'package.json');\n\n if (await fileExists(packageJsonPath)) {\n if (await fileExists(manifestPath)) {\n return {\n written: [],\n skipped: [],\n existingPackageJson: true,\n };\n }\n await writeFile(manifestPath, manifestTemplate(displayName), 'utf8');\n return {\n written: [CLI_CONFIG.manifestFileName],\n skipped: [],\n existingPackageJson: true,\n createdManifestOnly: true,\n };\n }\n\n const files: { rel: string; path: string; content: string }[] = [\n {\n rel: CLI_CONFIG.manifestFileName,\n path: manifestPath,\n content: manifestTemplate(displayName),\n },\n {\n rel: 'package.json',\n path: packageJsonPath,\n content: packageJsonTemplate(displayName),\n },\n {\n rel: 'AGENTS.md',\n path: join(cwd, 'AGENTS.md'),\n content: agentsMdTemplate(displayName),\n },\n {\n rel: 'vite.config.ts',\n path: join(cwd, 'vite.config.ts'),\n content: viteConfigTemplate(),\n },\n {\n rel: 'index.html',\n path: join(cwd, 'index.html'),\n content: indexHtmlTemplate(displayName),\n },\n {\n rel: join('public', 'icon.svg'),\n path: join(cwd, 'public', 'icon.svg'),\n content: ICON_SVG_TEMPLATE,\n },\n {\n rel: join('src', 'index.ts'),\n path: join(cwd, 'src', 'index.ts'),\n content: indexTypescriptTemplate(displayName),\n },\n ];\n\n await mkdir(join(cwd, 'public'), { recursive: true });\n await mkdir(join(cwd, 'src'), { recursive: true });\n\n const written: string[] = [];\n const skipped: string[] = [];\n\n for (const f of files) {\n if (await fileExists(f.path)) {\n skipped.push(f.rel);\n continue;\n }\n await writeFile(f.path, f.content, 'utf8');\n written.push(f.rel);\n }\n\n return { written, skipped };\n}\n","/**\n * Default extension scaffold strings. Adjust here to change the baseline Kittl extension layout.\n */\n\nimport { CLI_CONFIG } from '../constants';\nimport type { ExtensionManifest } from './schemas/extension-manifest';\n\n/**\n * Default legal placeholder links used in the generated manifest.\n * These are intentionally obvious placeholders so they get replaced before release.\n */\nconst DEFAULT_TERMS_URL = 'https://example.com/terms';\nconst DEFAULT_PRIVACY_URL = 'https://example.com/privacy';\n\n/**\n * Default embedded app entrypoint produced by the Vite scaffold build.\n * This path is interpreted relative to the built artifact root (Vite `outDir`).\n */\nconst DEFAULT_MAIN_APP_PANEL_PATH = 'index.html';\n\n// manifest JSON Schema URL for `manifest.json`\nexport const EXTENSION_MANIFEST_JSON_SCHEMA_URL =\n 'https://api.kittl.com/extensions/manifest/schema.json';\n\nfunction packageNameFromExtensionName(name: string): string {\n const slug = name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '');\n return slug.length > 0 ? slug : 'kittl-extension';\n}\n\n/**\n * Default manifest object written to `manifest.json` and pushed as the first draft version.\n * The scaffold includes every required field from the current manifest schema.\n */\nexport function initialExtensionManifest(\n displayName: string,\n): ExtensionManifest {\n const value = displayName.trim() || 'Unnamed extension';\n return {\n $schema: EXTENSION_MANIFEST_JSON_SCHEMA_URL,\n displayName: value,\n icon: 'icon.svg',\n tagline: `${value} for Kittl.`,\n installPage: {\n description: `Install ${value} to use this extension in Kittl.`,\n coverImage: 'icon.svg',\n termsAndConditionsLink: DEFAULT_TERMS_URL,\n privacyPolicyLink: DEFAULT_PRIVACY_URL,\n },\n config: {\n // New projects start without privileged scopes and can opt into them later.\n scopes: ['design:state:read', 'design:state:write'],\n embed: {\n mainAppPanel: {\n path: DEFAULT_MAIN_APP_PANEL_PATH,\n },\n },\n },\n };\n}\n\n/**\n * Serialized manifest file contents written by the CLI scaffold.\n */\nexport function manifestTemplate(displayName: string): string {\n return `${JSON.stringify(\n initialExtensionManifest(displayName),\n null, // replacer: none - default serialization\n 2, // space: 2-space indent + line breaks\n )}\\n`;\n}\n\nexport function packageJsonTemplate(displayName: string): string {\n return `${JSON.stringify(\n {\n name: packageNameFromExtensionName(displayName),\n private: true,\n version: '0.0.0',\n type: 'module',\n scripts: {\n dev: 'vite',\n build: 'vite build',\n preview: 'vite preview',\n },\n dependencies: {\n '@kittl/sdk': '^0.0.1',\n },\n devDependencies: {\n vite: '^8.0.0',\n },\n },\n null, // replacer: none, default serialization\n 2, // space: 2-space indent + line breaks\n )}\\n`;\n}\n\nexport function viteConfigTemplate(): string {\n return `import { readdirSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { defineConfig } from 'vite';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction htmlBuildInputs(): Record<string, string> {\n return Object.fromEntries(\n readdirSync(__dirname)\n .filter((name) => name.endsWith('.html'))\n .map((name) => [basename(name, '.html'), join(__dirname, name)]),\n );\n}\n\nconst contentSecurityPolicy =\n \"default-src 'self'; style-src 'self' 'unsafe-inline'; img-src https: data: blob:; connect-src 'self' https: ws: wss: http://localhost:* http://127.0.0.1:*; frame-ancestors 'self' https://*.kittl.io https://*.kittl.com http://localhost:* http://127.0.0.1:*\";\n\nexport default defineConfig({\n server: {\n port: ${CLI_CONFIG.scaffoldViteDevPort},\n headers: {\n 'Content-Security-Policy': contentSecurityPolicy,\n },\n },\n publicDir: 'public',\n build: {\n outDir: 'dist',\n rolldownOptions: {\n input: htmlBuildInputs(),\n },\n },\n base: './',\n});\n`;\n}\n\nexport function agentsMdTemplate(displayName: string): string {\n const name = displayName.trim() || 'Unnamed extension';\n return `# Kittl app\n\n**${name}** — [Kittl](https://www.kittl.com) starter from \\`kittl app init\\`. Kittl runs this app **inside a sandboxed iframe** in the editor; **@kittl/sdk** talks to the **Kittl canvas and design** (layers, artboards, export, drag-and-drop). **${CLI_CONFIG.manifestFileName}** holds scopes, install page, and embed paths.\n\n## AI instructions\n\n- **SDK (agents / LLMs):** \\`https://sdk-docs.kittl.dev/llms-full.txt\\` is the source of truth for \\`@kittl/sdk\\` APIs.\n- **SDK (humans):** https://sdk-docs.kittl.dev/\n- **Build:** Vite 8; production uses **Rolldown** via \\`build.rolldownOptions\\` (see \\`vite.config.ts\\`).\n- **Entries:** Do not hardcode HTML entry points. \\`htmlBuildInputs()\\` maps every root \\`*.html\\` to \\`build.rolldownOptions.input\\`.\n- **Rule (Security):** Never remove \\`localhost\\`, \\`127.0.0.1\\`, or \\`ws:\\` from the CSP in \\`vite.config.ts\\`.\n- **Reason:** These are required for the Kittl Live Bridge and Vite HMR. Removing them will break the connection between the Kittl Canvas and this local app.\n\n## Project structure\n\n- **${CLI_CONFIG.manifestFileName}**: Extension metadata. [Schema](${EXTENSION_MANIFEST_JSON_SCHEMA_URL})\n- **.kittl/**: Local Kittl CLI state (developer org, extension id); not shipped with the UI bundle.\n- **src/**: TypeScript imported from each root HTML shell.\n- **dist/**: \\`pnpm run build\\` output; manifest \\`embed\\` paths usually target files here after upload.\n- **\\`*.html\\` (next to \\`vite.config.ts\\`): Each file is a Rolldown entry (chunk name = basename without \\`.html\\`).\n\n## Workflow & commands\n\n| Command | Action |\n| :--- | :--- |\n| \\`pnpm install\\` | Install dependencies (once per clone or after lockfile changes). |\n| \\`pnpm run dev\\` | Vite dev server + HMR (port in \\`vite.config.ts\\`). |\n| \\`pnpm run build\\` | Production bundle into \\`dist/\\` (Rolldown). |\n| \\`kittl app update\\` | Push manifest changes to Kittl. |\n| \\`kittl app upload\\` | Upload the current \\`dist/\\` to Kittl. |\n| \\`kittl app --help\\` | Other \\`kittl app\\` subcommands. |\n\n**Note for agents:** A typical deployment sequence is \\`pnpm run build\\` → \\`kittl app update\\` → \\`kittl app upload\\`.\n\n## Terminology\n\n- **Extension:** Technical implementation—manifest, scopes, embeds, platform APIs.\n- **App:** Product name in Kittl and in the CLI (\\`kittl app ...\\`); same codebase as an extension.\n- **Sandboxed iframe:** The UI is embedded in an iframe (sandboxed); use **@kittl/sdk** to reach the host and canvas—do not assume unfettered access to the parent page.\n`;\n}\n\nexport function indexHtmlTemplate(displayName: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${displayName}</title>\n </head>\n <body>\n <div id=\"app\">\n <h1>Hello Kittl!</h1>\n <p>Welcome to your new extension: ${displayName}</p>\n <button id=\"doSomething\" type=\"button\">Do some magic!</button>\n </div>\n <script type=\"module\" src=\"/src/index.ts\"></script>\n </body>\n</html>\n`;\n}\n\nexport function indexTypescriptTemplate(displayName: string): string {\n return `import { kittl } from '@kittl/sdk';\n\ndocument.getElementById('doSomething')?.addEventListener('click', async () => {\n await kittl.design.text.addText({\n text: 'Hello ${displayName} from Kittl SDK!',\n position: {\n relative: {\n to: 'viewport',\n location: 'center',\n },\n },\n size: {\n height: 100,\n width: 400,\n },\n });\n});\n`;\n}\n\n// kittl logo\nexport const ICON_SVG_TEMPLATE =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"128\" height=\"128\" viewBox=\"0 0 1024 1024\"><rect width=\"1024\" height=\"1024\" rx=\"225\" fill=\"#DEFE00\"/><path fill=\"#080B10\" transform=\"translate(581,235)\" d=\"M0 0 C-7.93 26.81 -15.97 53.57 -24.12 80.31 C-24.35 81.04 -24.57 81.76 -24.79 82.5 C-25.92 86.19 -27.04 89.88 -28.17 93.57 C-28.5 94.67 -28.5 94.67 -28.85 95.8 C-29.3 97.29 -29.76 98.78 -30.21 100.27 C-35.39 117.26 -40.54 134.25 -45.69 151.25 C-46.09 152.58 -46.49 153.92 -46.9 155.25 C-47.68 157.83 -48.46 160.4 -49.24 162.98 C-50 165.48 -50.75 167.98 -51.51 170.48 C-53.37 176.6 -55.22 182.72 -57.06 188.84 C-57.99 191.91 -58.92 194.99 -59.84 198.06 C-60.29 199.54 -60.74 201.02 -61.18 202.51 C-61.8 204.56 -62.42 206.61 -63.04 208.67 C-63.4 209.84 -63.75 211.02 -64.12 212.23 C-65 215 -65 215 -66 217 C-31.32 207.79 -0.81 191.01 25.38 166.43 C27.48 164.48 29.6 162.63 31.81 160.81 C34.85 158.23 37.44 155.4 40.01 152.35 C41.45 150.66 42.91 148.99 44.39 147.34 C73.97 114.11 93.03 70.13 98 26 C113.47 23.05 128.96 20.3 144.5 17.74 C155.19 15.98 165.86 14.18 176.54 12.36 C178.95 11.95 181.37 11.54 183.79 11.13 C184.59 10.99 185.4 10.85 186.23 10.71 C187.86 10.44 189.49 10.16 191.13 9.88 C195.22 9.18 199.31 8.49 203.41 7.79 C207.32 7.12 211.22 6.45 215.13 5.79 C216.6 5.54 218.06 5.29 219.52 5.04 C221.55 4.69 223.57 4.35 225.6 4.01 C226.74 3.81 227.89 3.62 229.07 3.42 C232 3 232 3 236 3 C236.16 11.12 235.76 19 234.75 27.06 C234.62 28.15 234.48 29.23 234.34 30.35 C226.13 93.59 192.52 153.61 144 195 C143.05 195.84 142.11 196.67 141.13 197.53 C115.92 219.57 86.53 236.49 56 250 C55.6 259.92 56.83 269.35 58.31 279.13 C58.55 280.7 58.78 282.28 59.01 283.86 C59.57 287.61 60.14 291.36 60.71 295.11 C61.08 297.53 61.43 299.95 61.79 302.37 C64.96 323.35 70.45 343.85 77 364 C77.44 365.35 77.87 366.69 78.31 368.04 C87.9 397.66 98.51 426.64 111.58 454.91 C112.79 457.54 113.99 460.18 115.18 462.82 C120.11 473.66 125.8 484.06 131.59 494.45 C132.83 496.69 134.06 498.93 135.28 501.18 C144 517.14 153.68 532.57 165 546.81 C165.51 547.45 166.02 548.1 166.55 548.76 C167 549.32 167.45 549.87 167.92 550.45 C169 552 169 552 170 555 C169.42 555.28 168.83 555.56 168.23 555.85 C154.35 562.49 140.48 569.18 126.63 575.9 C115.75 581.18 104.87 586.45 93.98 591.7 C86.76 595.18 79.56 598.67 72.36 602.17 C66.13 605.19 59.89 608.21 53.66 611.23 C51.35 612.34 49.05 613.46 46.75 614.58 C44.04 615.89 41.33 617.2 38.63 618.5 C37.87 618.87 37.12 619.24 36.34 619.61 C33.37 621.03 31.33 622 28 622 C7.88 582.22 -1.64 541.14 -9.53 497.6 C-9.84 495.9 -10.14 494.21 -10.45 492.52 C-11.93 484.45 -13.35 476.42 -14.12 468.25 C-14.61 462.97 -14.61 462.97 -15.48 457.76 C-16.15 454.21 -16.43 450.66 -16.72 447.07 C-16.78 446.31 -16.84 445.56 -16.91 444.78 C-17.11 442.37 -17.3 439.97 -17.5 437.56 C-17.7 435.16 -17.89 432.76 -18.09 430.36 C-18.21 428.87 -18.34 427.38 -18.45 425.89 C-18.7 422.94 -18.99 420.04 -19.49 417.13 C-19.98 414.12 -20.26 411.19 -20.46 408.15 C-20.54 407.02 -20.62 405.88 -20.7 404.71 C-20.78 403.49 -20.86 402.26 -20.94 401 C-21.06 399.08 -21.06 399.08 -21.19 397.11 C-21.47 392.93 -21.74 388.75 -22 384.56 C-22.05 383.85 -22.09 383.14 -22.14 382.4 C-24.41 346.58 -25.21 310.89 -25 275 C-26.05 275.24 -27.1 275.48 -28.19 275.73 C-47.22 279.84 -66.64 281.24 -86 283 C-94.42 309.89 -102.59 336.84 -110.71 363.82 C-112.14 368.58 -113.57 373.34 -115 378.09 C-115.36 379.3 -115.36 379.3 -115.73 380.52 C-122.46 402.89 -129.26 425.23 -136.06 447.57 C-137.03 450.75 -137.99 453.93 -138.96 457.11 C-139.6 459.21 -140.24 461.32 -140.88 463.42 C-145.3 477.93 -149.64 492.47 -154 507 C-195.58 507 -237.16 507 -280 507 C-278.24 499.96 -276.51 493.16 -274.25 486.31 C-271.9 479.06 -269.79 471.77 -267.77 464.42 C-264.19 451.54 -260.37 438.73 -256.5 425.94 C-255.24 421.76 -253.98 417.58 -252.72 413.4 C-252.41 412.37 -252.1 411.35 -251.78 410.29 C-249.63 403.13 -247.52 395.96 -245.44 388.79 C-242.47 378.56 -239.41 368.37 -236.32 358.19 C-230.85 340.22 -230.85 340.22 -225.56 322.19 C-222.19 310.48 -218.62 298.84 -215.06 287.19 C-210.72 272.95 -206.4 258.7 -202.19 244.42 C-200.36 238.2 -198.51 231.98 -196.65 225.77 C-196.35 224.76 -196.05 223.75 -195.74 222.71 C-195.12 220.63 -194.5 218.55 -193.88 216.47 C-188.13 197.22 -188.13 197.22 -182.5 177.94 C-178.85 165.29 -174.97 152.72 -171.13 140.13 C-164.93 119.8 -158.75 99.46 -153 79 C-188.09 81.55 -226.46 97.99 -253 121 C-253.83 121.71 -254.66 122.42 -255.51 123.14 C-274.69 139.92 -289.02 161.6 -291.21 187.46 C-293.11 216.05 -280.75 245.26 -264.87 268.69 C-264.26 269.78 -263.64 270.87 -263 272 C-264.07 275.31 -265.83 276.91 -268.61 278.89 C-269.36 279.43 -270.1 279.96 -270.86 280.52 C-271.67 281.09 -272.48 281.66 -273.31 282.25 C-275.05 283.51 -276.79 284.76 -278.53 286.02 C-279.43 286.68 -280.33 287.33 -281.27 288 C-285.68 291.23 -290.03 294.55 -294.37 297.88 C-295.25 298.54 -296.12 299.21 -297.01 299.89 C-299.68 301.93 -302.34 303.96 -305 306 C-316.83 315.06 -328.7 324.04 -340.71 332.85 C-346.17 336.86 -351.59 340.92 -357 345 C-361.44 343.43 -363.83 339.89 -366.62 336.31 C-367.42 335.31 -367.42 335.31 -368.22 334.28 C-401.71 291.18 -419.04 237.97 -413.54 183.33 C-412.98 179.14 -412.11 175.08 -411 171 C-410.81 170.29 -410.62 169.57 -410.43 168.84 C-405.86 152.16 -397.84 136.47 -387 123 C-386.27 122.07 -385.54 121.14 -384.79 120.18 C-377.09 110.54 -368.68 102.62 -359 95 C-358.12 94.29 -357.24 93.58 -356.33 92.85 C-316.02 61.35 -264.24 45.67 -214.89 35.25 C-214.08 35.08 -213.27 34.91 -212.43 34.73 C-192.67 30.58 -172.78 27.22 -152.85 23.93 C-147.76 23.09 -142.68 22.24 -137.59 21.39 C-129.1 19.97 -120.6 18.56 -112.1 17.15 C-102.3 15.53 -92.51 13.9 -82.71 12.26 C-73.2 10.67 -63.69 9.09 -54.19 7.51 C-50.17 6.84 -46.15 6.17 -42.13 5.5 C-37.42 4.71 -32.71 3.93 -28 3.15 C-26.28 2.87 -24.56 2.58 -22.83 2.29 C-20.48 1.9 -18.12 1.51 -15.77 1.12 C-14.76 0.95 -14.76 0.95 -13.72 0.77 C-9.08 0.03 -4.68 -0.09 0 0 Z\"/></svg>';\n","import type { AxiosInstance } from 'axios';\nimport { z } from 'zod';\n\nconst developerOrganizationSchema = z.object({\n id: z.string(),\n name: z.string(),\n createdAt: z.string().optional(),\n updatedAt: z.string().optional(),\n});\n\nconst listResponseSchema = z.object({\n success: z.literal(true),\n result: z.object({\n developerOrganizations: z.array(developerOrganizationSchema),\n }),\n});\n\nconst createOrgResponseSchema = z.object({\n success: z.literal(true),\n result: z.object({\n developerOrganizationId: z.string(),\n }),\n});\n\nconst createExtensionResponseSchema = z.object({\n success: z.literal(true),\n result: z.object({\n extensionId: z.string(),\n }),\n});\n\nexport type DeveloperOrganization = z.infer<typeof developerOrganizationSchema>;\n\nexport async function listDeveloperOrganizations(\n client: AxiosInstance,\n): Promise<DeveloperOrganization[]> {\n const { data } = await client.get('/developer-organizations');\n const parsed = listResponseSchema.parse(data);\n return parsed.result.developerOrganizations;\n}\n\nexport async function createDeveloperOrganization(\n client: AxiosInstance,\n name: string,\n): Promise<string> {\n const { data } = await client.post('/developer-organizations', {\n name,\n });\n const parsed = createOrgResponseSchema.parse(data);\n return parsed.result.developerOrganizationId;\n}\n\nexport async function createExtensionInDeveloperOrganization(\n client: AxiosInstance,\n developerOrganizationId: string,\n body: { name: string; id?: string },\n): Promise<string> {\n const path = `/developer-organizations/${developerOrganizationId}/extensions`;\n const { data } = await client.post(path, body);\n const parsed = createExtensionResponseSchema.parse(data);\n return parsed.result.extensionId;\n}\n","import type { AxiosInstance } from 'axios';\nimport { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport { useCallback, useState } from 'react';\nimport { formatHttpClientError } from '../../../core/error';\nimport {\n createDeveloperOrganization,\n createExtensionInDeveloperOrganization,\n type DeveloperOrganization,\n} from '../../../services/developer-organizations.service';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { spacing } from '../../theme/tokens';\nimport type { AppsInitOrgPickerResult } from './AppsInitOrgPickerView';\nimport { AppsInitOrgPickerView } from './AppsInitOrgPickerView';\nimport type { TextInputViewDone } from './TextInputView';\nimport { TextInputView } from './TextInputView';\n\nexport type AppInitWizardSuccess = {\n developerOrganizationId: string;\n developerOrganizationName: string;\n extensionId: string;\n extensionName: string;\n // True when the org was created in this wizard (vs chosen from the list).\n isNewDeveloperOrganizationCreated: boolean;\n};\n\nexport type AppInitWizardResult =\n | { kind: 'cancelled' }\n | { kind: 'success'; data: AppInitWizardSuccess };\n\ntype Step = 'pick' | 'org_name' | 'ext_name';\n\ntype WizardDraft = {\n developerOrganizationId?: string;\n developerOrganizationName?: string;\n isNewDeveloperOrganizationCreated?: boolean;\n};\n\nexport type AppInitWizardViewProps = {\n organizations: DeveloperOrganization[];\n client: AxiosInstance;\n extensionNameSuggestion?: string;\n onDone: (result: AppInitWizardResult) => void;\n};\n\nfunction AppInitStepShell({\n width,\n apiError,\n isLoading,\n loadingText,\n children,\n}: {\n width: number | string;\n apiError: string | null;\n isLoading: boolean;\n loadingText: string;\n children: ReactNode;\n}) {\n return (\n <Box flexDirection=\"column\" width={width} minWidth={0}>\n {apiError ? (\n <Box marginLeft={spacing.sm} marginBottom={spacing.sm}>\n <Text {...textStyles.error}>{apiError}</Text>\n </Box>\n ) : null}\n {isLoading ? (\n <Box {...layoutStyles.viewColumn}>\n <Text {...textStyles.muted}>{loadingText}…</Text>\n </Box>\n ) : (\n children\n )}\n </Box>\n );\n}\n\nexport function AppInitWizardView({\n organizations,\n client,\n extensionNameSuggestion,\n onDone,\n}: AppInitWizardViewProps) {\n const width = useTerminalWidth();\n const w = width > 0 ? width : '100%';\n\n const [step, setStep] = useState<Step>('pick');\n const [draft, setDraft] = useState<WizardDraft>({});\n const [apiError, setApiError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const runTask = useCallback(async (task: () => Promise<void>) => {\n setApiError(null);\n setIsLoading(true);\n try {\n await task();\n } catch (e) {\n setApiError(formatHttpClientError(e));\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const handlePick = useCallback(\n (r: AppsInitOrgPickerResult) => {\n if (r.kind === 'cancelled') {\n onDone({ kind: 'cancelled' });\n return;\n }\n setApiError(null);\n if (r.kind === 'selected') {\n setDraft({\n developerOrganizationId: r.developerOrganizationId,\n developerOrganizationName: r.name,\n isNewDeveloperOrganizationCreated: false,\n });\n setStep('ext_name');\n return;\n }\n setDraft({});\n setStep('org_name');\n },\n [onDone],\n );\n\n const handleOrgName = useCallback(\n (r: TextInputViewDone) => {\n if (r.kind === 'cancelled') {\n onDone({ kind: 'cancelled' });\n return;\n }\n void runTask(async () => {\n const developerOrganizationId = await createDeveloperOrganization(\n client,\n r.value,\n );\n setDraft({\n developerOrganizationId,\n developerOrganizationName: r.value,\n isNewDeveloperOrganizationCreated: true,\n });\n setStep('ext_name');\n });\n },\n [client, onDone, runTask],\n );\n\n const handleExtName = useCallback(\n (r: TextInputViewDone) => {\n if (r.kind === 'cancelled') {\n onDone({ kind: 'cancelled' });\n return;\n }\n const orgId = draft.developerOrganizationId;\n const orgName = draft.developerOrganizationName;\n if (!orgId || !orgName) {\n return;\n }\n const isNewDeveloperOrganizationCreated = Boolean(\n draft.isNewDeveloperOrganizationCreated,\n );\n void runTask(async () => {\n const extensionId = await createExtensionInDeveloperOrganization(\n client,\n orgId,\n { name: r.value },\n );\n onDone({\n kind: 'success',\n data: {\n developerOrganizationId: orgId,\n developerOrganizationName: orgName,\n extensionId,\n extensionName: r.value,\n isNewDeveloperOrganizationCreated,\n },\n });\n });\n },\n [client, draft, onDone, runTask],\n );\n\n switch (step) {\n case 'pick':\n return (\n <AppsInitOrgPickerView\n organizations={organizations}\n onDone={handlePick}\n />\n );\n case 'org_name':\n return (\n <AppInitStepShell\n width={w}\n apiError={apiError}\n isLoading={isLoading}\n loadingText=\"Creating organization\"\n >\n <TextInputView\n key=\"wizard-org-name\"\n label=\"New organization name:\"\n placeholder=\"e.g. Functor Fountain Org\"\n onDone={handleOrgName}\n />\n </AppInitStepShell>\n );\n case 'ext_name':\n return (\n <AppInitStepShell\n width={w}\n apiError={apiError}\n isLoading={isLoading}\n loadingText=\"Creating extension\"\n >\n <TextInputView\n key=\"wizard-ext-name\"\n label=\"Extension name:\"\n placeholder=\"e.g. WASM-powered toaster\"\n initialValue={extensionNameSuggestion}\n onDone={handleExtName}\n />\n </AppInitStepShell>\n );\n }\n}\n","import { Box, type Key, Text, useInput } from 'ink';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { isSubmitKey } from '../../../core/utils';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { colors } from '../../theme/tokens';\n\nexport type DeveloperOrganizationRow = {\n id: string;\n name: string;\n};\n\nexport type AppsInitOrgPickerResult =\n | { kind: 'selected'; developerOrganizationId: string; name: string }\n | { kind: 'create_new' }\n | { kind: 'cancelled' };\n\nexport type AppsInitOrgPickerViewProps = {\n organizations: DeveloperOrganizationRow[];\n onDone: (result: AppsInitOrgPickerResult) => void;\n};\n\nconst CREATE_NEW_LABEL = 'Create new organization';\n\nexport function AppsInitOrgPickerView({\n organizations,\n onDone,\n}: AppsInitOrgPickerViewProps) {\n const width = useTerminalWidth();\n const [index, setIndex] = useState(0);\n\n const indexRef = useRef(index);\n const organizationsRef = useRef(organizations);\n const onDoneRef = useRef(onDone);\n\n indexRef.current = index;\n organizationsRef.current = organizations;\n onDoneRef.current = onDone;\n\n useEffect(() => {\n const maxIndex = organizations.length;\n setIndex((i) => (i > maxIndex ? maxIndex : i));\n }, [organizations]);\n\n const labels = useMemo(\n () => [...organizations.map((o) => o.name), CREATE_NEW_LABEL],\n [organizations],\n );\n\n const handleInput = useCallback((_input: string, key: Key) => {\n if (key.escape) {\n onDoneRef.current({ kind: 'cancelled' });\n return;\n }\n if (isSubmitKey(key)) {\n const idx = indexRef.current;\n const orgs = organizationsRef.current;\n if (idx === orgs.length) {\n onDoneRef.current({ kind: 'create_new' });\n return;\n }\n const org = orgs[idx];\n onDoneRef.current({\n kind: 'selected',\n developerOrganizationId: org.id,\n name: org.name,\n });\n return;\n }\n if (key.upArrow) {\n setIndex((i) => {\n const rc = organizationsRef.current.length + 1;\n const next = i <= 0 ? rc - 1 : i - 1;\n indexRef.current = next;\n return next;\n });\n return;\n }\n if (key.downArrow) {\n setIndex((i) => {\n const rc = organizationsRef.current.length + 1;\n const next = i >= rc - 1 ? 0 : i + 1;\n indexRef.current = next;\n return next;\n });\n }\n }, []);\n\n useInput(handleInput);\n\n const empty = organizations.length === 0;\n\n return (\n <Box\n {...layoutStyles.viewColumn}\n width={width > 0 ? width : '100%'}\n minWidth={0}\n >\n <Text {...textStyles.title}>Select developer organization</Text>\n <Text {...textStyles.muted}>↑↓ move · Enter confirm · Esc cancel</Text>\n <Box {...layoutStyles.section} flexDirection=\"column\">\n {empty ? (\n <Box marginBottom={1}>\n <Text {...textStyles.muted}>\n {\"No organizations found. Let's make one!\"}\n </Text>\n </Box>\n ) : null}\n {labels.map((label, i) => {\n const isSelected = i === index;\n return (\n <Text\n key={`${label}-${i}`}\n bold={isSelected}\n color={isSelected ? colors.accent : undefined}\n >\n {isSelected ? '› ' : ' '}\n {label}\n </Text>\n );\n })}\n </Box>\n </Box>\n );\n}\n","import { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useCallback, useState } from 'react';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\n\nexport type TextInputViewDone =\n | { kind: 'submit'; value: string }\n | { kind: 'cancelled' };\n\nexport type TextInputViewProps = {\n label: string;\n placeholder?: string;\n /** Initial field value (trimmed once on mount). */\n initialValue?: string;\n // When true, Enter on whitespace-only keeps you on the screen with an error.\n requireNonEmpty?: boolean;\n onDone: (result: TextInputViewDone) => void;\n};\n\n/**\n * text input field using Ink + `ink-text-input`.\n */\nexport function TextInputView({\n label,\n placeholder,\n initialValue,\n requireNonEmpty = true,\n onDone,\n}: TextInputViewProps) {\n const width = useTerminalWidth();\n const [value, setValue] = useState(() => initialValue?.trim() ?? '');\n const [error, setError] = useState<string | null>(null);\n\n const finish = useCallback(\n (result: TextInputViewDone) => {\n onDone(result);\n },\n [onDone],\n );\n\n useInput((_input, key) => {\n if (key.escape) {\n finish({ kind: 'cancelled' });\n }\n });\n\n const handleSubmit = useCallback(\n (submitted: string) => {\n const trimmed = submitted.trim();\n if (requireNonEmpty && trimmed.length === 0) {\n setError('Cannot be empty.');\n return;\n }\n setError(null);\n finish({ kind: 'submit', value: trimmed });\n },\n [finish, requireNonEmpty],\n );\n\n return (\n <Box\n {...layoutStyles.viewColumn}\n width={width > 0 ? width : '100%'}\n minWidth={0}\n >\n <Text {...textStyles.title}>{label}</Text>\n <Box {...layoutStyles.section} flexDirection=\"row\" flexWrap=\"wrap\">\n <TextInput\n value={value}\n onChange={(v) => {\n setValue(v);\n if (error) {\n setError(null);\n }\n }}\n onSubmit={handleSubmit}\n placeholder={placeholder ?? ''}\n />\n </Box>\n {error ? (\n <Text {...textStyles.error}>{error}</Text>\n ) : (\n <Text {...textStyles.muted}>Enter confirm · Esc cancel</Text>\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":["join","Box","Text","useCallback","useState","Box","Text","useInput","useCallback","useState","jsx","jsxs","useState","useCallback","useInput","Box","Text","jsx","jsxs","Box","Text","useState","useCallback","join"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
markExtensionDraftReadyForReview
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-GOOP3XEU.js";
|
|
4
4
|
import {
|
|
5
5
|
formatExtensionReadyForReviewHttpError,
|
|
6
6
|
readInternalConfig
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-LEELFFFY.js";
|
|
8
8
|
import {
|
|
9
9
|
layoutStyles,
|
|
10
10
|
spacing,
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
} from "../../chunk-3BPIJLS7.js";
|
|
13
13
|
import {
|
|
14
14
|
BaseCommand
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-CT7IDOZX.js";
|
|
16
|
+
import "../../chunk-X67IL4KU.js";
|
|
17
|
+
import "../../chunk-ZS7NZCD4.js";
|
|
16
18
|
|
|
17
19
|
// src/commands/app/release.ts
|
|
18
20
|
import { Flags } from "@oclif/core";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/app/release.ts","../../../src/ui/views/app-release/AppReleaseConfirmView.tsx"],"sourcesContent":["import { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatExtensionReadyForReviewHttpError } from '../../core/error';\nimport { readInternalConfig } from '../../core/internal.config';\nimport { markExtensionDraftReadyForReview } from '../../services/extensions.service';\nimport { AppReleaseConfirmView } from '../../ui/views/app-release';\n\nexport default class AppRelease extends BaseCommand {\n public static override description =\n 'Mark the extension draft as ready for review. Kittl admin handles review from here.';\n\n public static override flags = {\n yes: Flags.boolean({\n char: 'y',\n description: 'Skip the confirmation screen',\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(AppRelease);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n let extensionId: string;\n try {\n ({ extensionId } = await readInternalConfig(cwd));\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n if (!flags.yes) {\n const choice = await this.renderView(AppReleaseConfirmView, {\n extensionId,\n });\n if (choice.kind === 'cancel') {\n this.log('Release cancelled. Your draft was not submitted.');\n return;\n }\n }\n\n const client = this.getKittlApiClient();\n try {\n const { extensionVersionId, status } =\n await markExtensionDraftReadyForReview(client, extensionId);\n this.log(\n `Your app is set to ready for review (version ${extensionVersionId}, ${status}). Kittl admin will take it from there.`,\n );\n } catch (e) {\n this.error(formatExtensionReadyForReviewHttpError(e), { exit: 2 });\n }\n }\n}\n","import { Box, Text, useInput } from 'ink';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { spacing } from '../../theme/tokens';\n\nexport type AppReleaseConfirmResult = { kind: 'confirm' } | { kind: 'cancel' };\n\nexport type AppReleaseConfirmViewProps = {\n extensionId: string;\n onDone: (result: AppReleaseConfirmResult) => void;\n};\n\nexport function AppReleaseConfirmView({\n extensionId,\n onDone,\n}: AppReleaseConfirmViewProps) {\n useInput((input, key) => {\n if (key.escape) {\n onDone({ kind: 'cancel' });\n return;\n }\n switch (input) {\n case 'y':\n case 'Y':\n onDone({ kind: 'confirm' });\n return;\n case 'n':\n case 'N':\n onDone({ kind: 'cancel' });\n return;\n default:\n break;\n }\n });\n\n return (\n <Box minWidth={0} {...layoutStyles.viewColumn}>\n <Text {...textStyles.title}>Submit extension for review?</Text>\n\n <Box marginTop={spacing.md} flexDirection=\"column\">\n <Text {...textStyles.warning} bold>\n This is final. After release, this version is immutable.\n </Text>\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>\n Make sure this draft already has the manifest and build files you\n want:{' '}\n <Text bold color=\"white\">\n kittl app update\n </Text>{' '}\n pushes your manifest;{' '}\n <Text bold color=\"white\">\n kittl app upload\n </Text>{' '}\n pushes dist output. Run them first if anything is still only on\n disk.\n </Text>\n </Box>\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>\n Future pushes go to a{' '}\n <Text bold color=\"white\">\n new draft\n </Text>{' '}\n and count as the{' '}\n <Text bold color=\"white\">\n next version\n </Text>{' '}\n (auto-incremented). This submission stays immutable.\n </Text>\n </Box>\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>\n Extension ID: <Text color=\"white\">{extensionId}</Text>\n </Text>\n </Box>\n </Box>\n\n <Box marginTop={spacing.md}>\n <Text bold color=\"white\">\n Type y to submit for review\n </Text>\n <Text {...textStyles.muted}> · n or Esc to cancel</Text>\n </Box>\n </Box>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/app/release.ts","../../../src/ui/views/app-release/AppReleaseConfirmView.tsx"],"sourcesContent":["import { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatExtensionReadyForReviewHttpError } from '../../core/error';\nimport { readInternalConfig } from '../../core/internal.config';\nimport { markExtensionDraftReadyForReview } from '../../services/extensions.service';\nimport { AppReleaseConfirmView } from '../../ui/views/app-release';\n\nexport default class AppRelease extends BaseCommand {\n public static override description =\n 'Mark the extension draft as ready for review. Kittl admin handles review from here.';\n\n public static override flags = {\n yes: Flags.boolean({\n char: 'y',\n description: 'Skip the confirmation screen',\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(AppRelease);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n let extensionId: string;\n try {\n ({ extensionId } = await readInternalConfig(cwd));\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n if (!flags.yes) {\n const choice = await this.renderView(AppReleaseConfirmView, {\n extensionId,\n });\n if (choice.kind === 'cancel') {\n this.log('Release cancelled. Your draft was not submitted.');\n return;\n }\n }\n\n const client = this.getKittlApiClient();\n try {\n const { extensionVersionId, status } =\n await markExtensionDraftReadyForReview(client, extensionId);\n this.log(\n `Your app is set to ready for review (version ${extensionVersionId}, ${status}). Kittl admin will take it from there.`,\n );\n } catch (e) {\n this.error(formatExtensionReadyForReviewHttpError(e), { exit: 2 });\n }\n }\n}\n","import { Box, Text, useInput } from 'ink';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { spacing } from '../../theme/tokens';\n\nexport type AppReleaseConfirmResult = { kind: 'confirm' } | { kind: 'cancel' };\n\nexport type AppReleaseConfirmViewProps = {\n extensionId: string;\n onDone: (result: AppReleaseConfirmResult) => void;\n};\n\nexport function AppReleaseConfirmView({\n extensionId,\n onDone,\n}: AppReleaseConfirmViewProps) {\n useInput((input, key) => {\n if (key.escape) {\n onDone({ kind: 'cancel' });\n return;\n }\n switch (input) {\n case 'y':\n case 'Y':\n onDone({ kind: 'confirm' });\n return;\n case 'n':\n case 'N':\n onDone({ kind: 'cancel' });\n return;\n default:\n break;\n }\n });\n\n return (\n <Box minWidth={0} {...layoutStyles.viewColumn}>\n <Text {...textStyles.title}>Submit extension for review?</Text>\n\n <Box marginTop={spacing.md} flexDirection=\"column\">\n <Text {...textStyles.warning} bold>\n This is final. After release, this version is immutable.\n </Text>\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>\n Make sure this draft already has the manifest and build files you\n want:{' '}\n <Text bold color=\"white\">\n kittl app update\n </Text>{' '}\n pushes your manifest;{' '}\n <Text bold color=\"white\">\n kittl app upload\n </Text>{' '}\n pushes dist output. Run them first if anything is still only on\n disk.\n </Text>\n </Box>\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>\n Future pushes go to a{' '}\n <Text bold color=\"white\">\n new draft\n </Text>{' '}\n and count as the{' '}\n <Text bold color=\"white\">\n next version\n </Text>{' '}\n (auto-incremented). This submission stays immutable.\n </Text>\n </Box>\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>\n Extension ID: <Text color=\"white\">{extensionId}</Text>\n </Text>\n </Box>\n </Box>\n\n <Box marginTop={spacing.md}>\n <Text bold color=\"white\">\n Type y to submit for review\n </Text>\n <Text {...textStyles.muted}> · n or Esc to cancel</Text>\n </Box>\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;;;ACAtB,SAAS,KAAK,MAAM,gBAAgB;AAoC9B,cAOI,YAPJ;AAzBC,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAA+B;AAC7B,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,aAAO,EAAE,MAAM,SAAS,CAAC;AACzB;AAAA,IACF;AACA,YAAQ,OAAO;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AACH,eAAO,EAAE,MAAM,UAAU,CAAC;AAC1B;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AACH,eAAO,EAAE,MAAM,SAAS,CAAC;AACzB;AAAA,MACF;AACE;AAAA,IACJ;AAAA,EACF,CAAC;AAED,SACE,qBAAC,OAAI,UAAU,GAAI,GAAG,aAAa,YACjC;AAAA,wBAAC,QAAM,GAAG,WAAW,OAAO,0CAA4B;AAAA,IAExD,qBAAC,OAAI,WAAW,QAAQ,IAAI,eAAc,UACxC;AAAA,0BAAC,QAAM,GAAG,WAAW,SAAS,MAAI,MAAC,sEAEnC;AAAA,MACA,oBAAC,OAAI,WAAW,QAAQ,IACtB,+BAAC,QAAM,GAAG,WAAW,OAAO;AAAA;AAAA,QAEpB;AAAA,QACN,oBAAC,QAAK,MAAI,MAAC,OAAM,SAAQ,8BAEzB;AAAA,QAAQ;AAAA,QAAI;AAAA,QACU;AAAA,QACtB,oBAAC,QAAK,MAAI,MAAC,OAAM,SAAQ,8BAEzB;AAAA,QAAQ;AAAA,QAAI;AAAA,SAGd,GACF;AAAA,MACA,oBAAC,OAAI,WAAW,QAAQ,IACtB,+BAAC,QAAM,GAAG,WAAW,OAAO;AAAA;AAAA,QACJ;AAAA,QACtB,oBAAC,QAAK,MAAI,MAAC,OAAM,SAAQ,uBAEzB;AAAA,QAAQ;AAAA,QAAI;AAAA,QACK;AAAA,QACjB,oBAAC,QAAK,MAAI,MAAC,OAAM,SAAQ,0BAEzB;AAAA,QAAQ;AAAA,QAAI;AAAA,SAEd,GACF;AAAA,MACA,oBAAC,OAAI,WAAW,QAAQ,IACtB,+BAAC,QAAM,GAAG,WAAW,OAAO;AAAA;AAAA,QACZ,oBAAC,QAAK,OAAM,SAAS,uBAAY;AAAA,SACjD,GACF;AAAA,OACF;AAAA,IAEA,qBAAC,OAAI,WAAW,QAAQ,IACtB;AAAA,0BAAC,QAAK,MAAI,MAAC,OAAM,SAAQ,yCAEzB;AAAA,MACA,oBAAC,QAAM,GAAG,WAAW,OAAO,sCAAqB;AAAA,OACnD;AAAA,KACF;AAEJ;;;AD9EA,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAuB,cACrB;AAAA,EAEF,OAAuB,QAAQ;AAAA,IAC7B,KAAK,MAAM,QAAQ;AAAA,MACjB,MAAM;AAAA,MACN,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,MAAa,MAAqB;AAChC,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,WAAU;AAE7C,UAAM,KAAK,oBAAoB;AAE/B,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI;AACJ,QAAI;AACF,OAAC,EAAE,YAAY,IAAI,MAAM,mBAAmB,GAAG;AAAA,IACjD,SAAS,GAAG;AACV,WAAK,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IACpE;AAEA,QAAI,CAAC,MAAM,KAAK;AACd,YAAM,SAAS,MAAM,KAAK,WAAW,uBAAuB;AAAA,QAC1D;AAAA,MACF,CAAC;AACD,UAAI,OAAO,SAAS,UAAU;AAC5B,aAAK,IAAI,kDAAkD;AAC3D;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,kBAAkB;AACtC,QAAI;AACF,YAAM,EAAE,oBAAoB,OAAO,IACjC,MAAM,iCAAiC,QAAQ,WAAW;AAC5D,WAAK;AAAA,QACH,gDAAgD,kBAAkB,KAAK,MAAM;AAAA,MAC/E;AAAA,IACF,SAAS,GAAG;AACV,WAAK,MAAM,uCAAuC,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IACnE;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createExtensionDraftVersion
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-GOOP3XEU.js";
|
|
4
4
|
import {
|
|
5
5
|
formatHttpClientError,
|
|
6
6
|
readInternalConfig
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-LEELFFFY.js";
|
|
8
|
+
import {
|
|
9
|
+
BaseCommand
|
|
10
|
+
} from "../../chunk-CT7IDOZX.js";
|
|
8
11
|
import {
|
|
9
|
-
BaseCommand,
|
|
10
12
|
CLI_CONFIG
|
|
11
|
-
} from "../../chunk-
|
|
13
|
+
} from "../../chunk-X67IL4KU.js";
|
|
14
|
+
import "../../chunk-ZS7NZCD4.js";
|
|
12
15
|
|
|
13
16
|
// src/commands/app/update.ts
|
|
14
17
|
import { join } from "node:path";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/app/update.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { CLI_CONFIG } from '../../constants';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatHttpClientError } from '../../core/error';\nimport {\n type InternalConfig,\n readInternalConfig,\n} from '../../core/internal.config';\nimport { createExtensionDraftVersion } from '../../services/extensions.service';\n\nexport default class AppUpdate extends BaseCommand {\n public static override description =\n 'Update the draft extension version with the current extension manifest file';\n\n public async run(): Promise<void> {\n await this.parse(AppUpdate);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n let config: InternalConfig;\n try {\n config = await readInternalConfig(cwd);\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n const client = this.getKittlApiClient();\n const manifestPath = join(cwd, CLI_CONFIG.manifestFileName);\n\n let extensionVersionId: string;\n try {\n extensionVersionId = await createExtensionDraftVersion(\n client,\n config.extensionId,\n manifestPath,\n );\n } catch (e) {\n this.error(formatHttpClientError(e), { exit: 2 });\n }\n\n this.log(`Updated draft extension version ${extensionVersionId}.`);\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/app/update.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { CLI_CONFIG } from '../../constants';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatHttpClientError } from '../../core/error';\nimport {\n type InternalConfig,\n readInternalConfig,\n} from '../../core/internal.config';\nimport { createExtensionDraftVersion } from '../../services/extensions.service';\n\nexport default class AppUpdate extends BaseCommand {\n public static override description =\n 'Update the draft extension version with the current extension manifest file';\n\n public async run(): Promise<void> {\n await this.parse(AppUpdate);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n let config: InternalConfig;\n try {\n config = await readInternalConfig(cwd);\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n const client = this.getKittlApiClient();\n const manifestPath = join(cwd, CLI_CONFIG.manifestFileName);\n\n let extensionVersionId: string;\n try {\n extensionVersionId = await createExtensionDraftVersion(\n client,\n config.extensionId,\n manifestPath,\n );\n } catch (e) {\n this.error(formatHttpClientError(e), { exit: 2 });\n }\n\n this.log(`Updated draft extension version ${extensionVersionId}.`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS,YAAY;AAUrB,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EACjD,OAAuB,cACrB;AAAA,EAEF,MAAa,MAAqB;AAChC,UAAM,KAAK,MAAM,UAAS;AAE1B,UAAM,KAAK,oBAAoB;AAE/B,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,mBAAmB,GAAG;AAAA,IACvC,SAAS,GAAG;AACV,WAAK,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IACpE;AAEA,UAAM,SAAS,KAAK,kBAAkB;AACtC,UAAM,eAAe,KAAK,KAAK,WAAW,gBAAgB;AAE1D,QAAI;AACJ,QAAI;AACF,2BAAqB,MAAM;AAAA,QACzB;AAAA,QACA,OAAO;AAAA,QACP;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,WAAK,MAAM,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IAClD;AAEA,SAAK,IAAI,mCAAmC,kBAAkB,GAAG;AAAA,EACnE;AACF;","names":[]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
formatExtensionArtifactUploadError,
|
|
3
3
|
isSystemError,
|
|
4
4
|
readInternalConfig
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-LEELFFFY.js";
|
|
6
6
|
import {
|
|
7
7
|
useTerminalWidth
|
|
8
8
|
} from "../../chunk-EKU4DKQK.js";
|
|
@@ -12,11 +12,14 @@ import {
|
|
|
12
12
|
textStyles
|
|
13
13
|
} from "../../chunk-3BPIJLS7.js";
|
|
14
14
|
import {
|
|
15
|
-
BaseCommand
|
|
15
|
+
BaseCommand
|
|
16
|
+
} from "../../chunk-CT7IDOZX.js";
|
|
17
|
+
import {
|
|
16
18
|
chunkArray,
|
|
17
19
|
contentTypeForPath,
|
|
18
20
|
listAllFilesUnderDir
|
|
19
|
-
} from "../../chunk-
|
|
21
|
+
} from "../../chunk-X67IL4KU.js";
|
|
22
|
+
import "../../chunk-ZS7NZCD4.js";
|
|
20
23
|
|
|
21
24
|
// src/commands/app/upload.ts
|
|
22
25
|
import { stat } from "node:fs/promises";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/app/upload.ts","../../../src/core/extension-upload.core.ts","../../../src/services/extension-artifacts.service.ts","../../../src/ui/views/app-upload/AppUploadProgressView.tsx","../../../src/ui/views/app-upload/verbose-upload-paths.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../core/core.command';\nimport { isSystemError } from '../../core/error';\nimport {\n collectDistUploadDescriptors,\n type DistUploadFileDescriptor,\n} from '../../core/extension-upload.core';\nimport { readInternalConfig } from '../../core/internal.config';\nimport { chunkArray } from '../../core/utils';\nimport { AppUploadProgressView } from '../../ui/views/app-upload';\n\nexport default class AppUpload extends BaseCommand {\n public static override description =\n 'Upload build output to the extension draft.';\n\n public static override flags = {\n dist: Flags.string({\n description: 'Path to the build output directory (relative to cwd)',\n default: 'dist',\n }),\n verbose: Flags.boolean({\n char: 'v',\n default: false,\n description:\n 'List each dist file path on its own line as uploads complete (no S3 keys)',\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(AppUpload);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n\n let extensionId: string;\n try {\n ({ extensionId } = await readInternalConfig(cwd));\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n const distAbs = resolve(cwd, flags.dist);\n try {\n const st = await stat(distAbs);\n if (!st.isDirectory()) {\n this.error(`Not a directory: ${distAbs}`, { exit: 2 });\n }\n } catch (e) {\n if (isSystemError(e, 'ENOENT')) {\n this.error(\n `Dist directory not found: ${distAbs}. Build your app first, or pass --dist.`,\n { exit: 2 },\n );\n }\n if (isSystemError(e, 'EACCES') || isSystemError(e, 'EPERM')) {\n this.error(`Cannot access dist directory: ${distAbs}`, { exit: 2 });\n }\n if (isSystemError(e, 'ENOTDIR')) {\n this.error(`Invalid dist path (not a directory): ${distAbs}`, {\n exit: 2,\n });\n }\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n let descriptors: DistUploadFileDescriptor[];\n try {\n descriptors = await collectDistUploadDescriptors(distAbs);\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n const result = await this.renderView(AppUploadProgressView, {\n client: this.getKittlApiClient(),\n extensionId,\n batches: chunkArray(descriptors, 50),\n total: descriptors.length,\n verbose: flags.verbose,\n });\n\n if (result.kind === 'error') {\n const msg = result.failedPath\n ? `${result.failedPath}\\n${result.message}`\n : result.message;\n this.error(msg, { exit: 2 });\n }\n\n this.log(`Uploaded ${result.uploaded} file(s) to your extension draft.`);\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { basename, relative } from 'node:path';\nimport type { AxiosInstance } from 'axios';\nimport {\n type ExtensionUploadSignedUrlRow,\n putPresignedUpload,\n requestExtensionUploadSignedUrls,\n} from '../services/extension-artifacts.service';\nimport { formatExtensionArtifactUploadError } from './error';\nimport { contentTypeForPath, listAllFilesUnderDir } from './files';\n\nconst MAX_RELATIVE_PATH_LEN = 512;\nconst RELATIVE_PATH_SEGMENT = /^[a-zA-Z0-9._-]+$/;\nconst S3_PUT_MAX_ATTEMPTS = 3;\nconst S3_PUT_RETRY_BASE_MS = 500;\n\nexport type DistUploadFileDescriptor = {\n absolutePath: string;\n relativePath: string;\n contentType: string;\n};\n\nexport type ArtifactUploadProgress = {\n completedSoFar: number;\n total: number;\n // path currently being read or uploaded.\n activeRelativePath: string;\n // paths uploaded so far (same order as uploads).\n uploadedRelativePaths: string[];\n};\n\nexport type ArtifactUploadResult =\n | { ok: true; uploaded: number }\n | { ok: false; message: string; failedPath?: string };\n\n// --- Path + MIME (upload-signed-urls contract) ---------------------------------------------------\n\n/** POSIX slashes, trim, strip leading `./` and `/` (single pass after `path.relative`). */\nexport function normalizeDistPath(rawPath: string): string {\n return rawPath\n .replace(/\\\\/g, '/')\n .trim()\n .replace(/^(\\.\\/|\\/)+/, '');\n}\n\n/** API path validation (segments, length, traversal). */\nexport function validateUploadPath(relativePath: string): string | null {\n if (!relativePath) {\n return 'Path is empty.';\n }\n if (relativePath.includes('\\\\')) {\n return 'Path must use forward slashes only, not backslashes.';\n }\n if (relativePath.length > MAX_RELATIVE_PATH_LEN) {\n return `Path exceeds max length (${MAX_RELATIVE_PATH_LEN}).`;\n }\n for (const segment of relativePath.split('/')) {\n if (!segment || segment === '.' || segment === '..') {\n return `Invalid path segment \"${segment}\" (no empty, \".\", or \"..\" segments).`;\n }\n if (!RELATIVE_PATH_SEGMENT.test(segment)) {\n return `Invalid path segment \"${segment}\" (allowed: letters, digits, \".\", \"_\", \"-\").`;\n }\n }\n return null;\n}\n\n/**\n * Lists `distRoot` recursively, validates paths, dedupes, sorts for stable progress / API order.\n */\nexport async function collectDistUploadDescriptors(\n distRoot: string,\n): Promise<DistUploadFileDescriptor[]> {\n const files = await listAllFilesUnderDir(distRoot);\n\n if (files.length === 0) {\n throw new Error(\n `No files found under ${distRoot}. Build your app before uploading.`,\n );\n }\n\n const descriptorByRelativePath = new Map<string, DistUploadFileDescriptor>();\n\n for (const absolutePath of files) {\n const relativePath = normalizeDistPath(relative(distRoot, absolutePath));\n const validationError = validateUploadPath(relativePath);\n if (validationError) {\n throw new Error(`${basename(absolutePath)}: ${validationError}`);\n }\n if (descriptorByRelativePath.has(relativePath)) {\n throw new Error(\n `Duplicate upload path after normalization: ${relativePath}`,\n );\n }\n descriptorByRelativePath.set(relativePath, {\n absolutePath,\n relativePath,\n contentType: contentTypeForPath(absolutePath),\n });\n }\n\n return [...descriptorByRelativePath.values()].sort((a, b) =>\n a.relativePath.localeCompare(b.relativePath),\n );\n}\n\nasync function putPresignedUploadWithRetry(\n url: string,\n body: Buffer,\n contentType: string,\n): Promise<void> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= S3_PUT_MAX_ATTEMPTS; attempt++) {\n try {\n await putPresignedUpload(url, body, contentType);\n return;\n } catch (err) {\n lastError = err;\n if (attempt >= S3_PUT_MAX_ATTEMPTS) {\n break;\n }\n await new Promise((r) => setTimeout(r, S3_PUT_RETRY_BASE_MS * attempt));\n }\n }\n throw lastError;\n}\n\n// --- Presigned batch upload ----------------------------------------------------------------------\n\n/**\n * Presigned URL batching + S3 PUTs with progress callbacks for Ink UI.\n * S3 PUTs retry with linear backoff.\n */\nexport async function runArtifactUpload(\n client: AxiosInstance,\n extensionId: string,\n batches: DistUploadFileDescriptor[][],\n opts: {\n total: number;\n onProgress: (p: ArtifactUploadProgress) => void;\n },\n): Promise<ArtifactUploadResult> {\n const { total, onProgress } = opts;\n let uploaded = 0;\n let lastRelativePath = '';\n const uploadedRelativePaths: string[] = [];\n\n for (let b = 0; b < batches.length; b++) {\n const batch = batches[b];\n if (!batch?.length) {\n continue;\n }\n const specs = batch.map((d) => ({\n relativePath: d.relativePath,\n contentType: d.contentType,\n }));\n let signed: ExtensionUploadSignedUrlRow[];\n try {\n signed = await requestExtensionUploadSignedUrls(\n client,\n extensionId,\n specs,\n );\n } catch (e) {\n return { ok: false, message: formatExtensionArtifactUploadError(e) };\n }\n\n for (let i = 0; i < batch.length; i++) {\n const d = batch[i];\n const row = signed[i];\n if (!d || !row) {\n return {\n ok: false,\n message: `Internal error: missing batch entry at index ${i} (batch ${b + 1}).`,\n };\n }\n if (row.relativePath !== d.relativePath) {\n return {\n ok: false,\n failedPath: d.relativePath,\n message: `Presigned URL order mismatch for ${d.relativePath} (batch ${b + 1}).`,\n };\n }\n\n lastRelativePath = d.relativePath;\n\n onProgress({\n completedSoFar: uploaded,\n total,\n activeRelativePath: d.relativePath,\n uploadedRelativePaths: [...uploadedRelativePaths],\n });\n\n let body: Buffer;\n try {\n body = await readFile(d.absolutePath);\n } catch (e) {\n return {\n ok: false,\n failedPath: d.relativePath,\n message:\n e instanceof Error\n ? `Failed to read ${d.relativePath}: ${e.message}`\n : String(e),\n };\n }\n\n try {\n await putPresignedUploadWithRetry(row.url, body, row.contentType);\n } catch (e) {\n return {\n ok: false,\n failedPath: d.relativePath,\n message:\n e instanceof Error\n ? `S3 upload failed for ${d.relativePath}: ${e.message}`\n : `S3 upload failed for ${d.relativePath}: ${String(e)}`,\n };\n }\n\n uploaded++;\n uploadedRelativePaths.push(d.relativePath);\n onProgress({\n completedSoFar: uploaded,\n total,\n activeRelativePath: d.relativePath,\n uploadedRelativePaths: [...uploadedRelativePaths],\n });\n }\n }\n\n onProgress({\n completedSoFar: uploaded,\n total,\n activeRelativePath:\n total <= 1 ? lastRelativePath : `${uploaded} files uploaded`,\n uploadedRelativePaths: [...uploadedRelativePaths],\n });\n return { ok: true, uploaded };\n}\n","import type { AxiosInstance } from 'axios';\nimport axios from 'axios';\nimport { z } from 'zod';\n\nconst uploadSignedUrlsResponseSchema = z.object({\n success: z.literal(true),\n results: z.array(\n z.object({\n url: z.string().min(1),\n key: z.string(),\n relativePath: z.string(),\n contentType: z.string().min(1),\n }),\n ),\n});\n\nexport type UploadSignedUrlFileSpec = {\n relativePath: string;\n contentType: string;\n};\n\nexport type ExtensionUploadSignedUrlRow = {\n url: string;\n key: string;\n relativePath: string;\n contentType: string;\n};\n\nexport async function requestExtensionUploadSignedUrls(\n client: AxiosInstance,\n extensionId: string,\n files: UploadSignedUrlFileSpec[],\n): Promise<ExtensionUploadSignedUrlRow[]> {\n const path = `/extensions/${extensionId}/versions/upload-signed-urls`;\n const { data } = await client.post(path, { files });\n const parsed = uploadSignedUrlsResponseSchema.safeParse(data);\n if (!parsed.success) {\n throw parsed.error;\n }\n const map = new Map(\n parsed.data.results.map((r) => [r.relativePath, r] as const),\n );\n const ordered: ExtensionUploadSignedUrlRow[] = [];\n for (const f of files) {\n const row = map.get(f.relativePath);\n if (row === undefined) {\n throw new Error(`Missing presigned URL for path: ${f.relativePath}`);\n }\n ordered.push(row);\n }\n return ordered;\n}\n\n/**\n * Dedicated Axios instance for presigned S3 PUT requests only.\n * `maxBodyLength` / `maxContentLength`: avoid Axios body-size caps on large assets.\n * `timeout: 0`: no Axios deadline on slow uploads (TCP / network still apply).\n */\nconst s3Client = axios.create({\n maxBodyLength: Infinity,\n maxContentLength: Infinity,\n timeout: 0,\n});\n\n/**\n * PUT raw bytes to a presigned URL using {@link s3Client} only.\n * `contentType` must match the value the API used when signing, byte-for-byte, or S3 returns 403.\n */\nexport async function putPresignedUpload(\n url: string,\n body: Buffer,\n contentType: string,\n): Promise<void> {\n await s3Client.put(url, body, {\n headers: { 'Content-Type': contentType },\n });\n}\n","import type { AxiosInstance } from 'axios';\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n type ArtifactUploadProgress,\n type DistUploadFileDescriptor,\n runArtifactUpload,\n} from '../../../core/extension-upload.core';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { spacing } from '../../theme/tokens';\nimport { formatVerboseUploadPaths } from './verbose-upload-paths';\n\nexport type AppUploadProgressResult =\n | { kind: 'success'; uploaded: number }\n | { kind: 'error'; message: string; failedPath?: string };\n\nexport type AppUploadProgressViewProps = {\n client: AxiosInstance;\n extensionId: string;\n batches: DistUploadFileDescriptor[][];\n total: number;\n // When true, completed dist paths are listed one per line\n verbose?: boolean;\n onDone: (result: AppUploadProgressResult) => void;\n};\n\nfunction ProgressBar({\n done,\n total,\n width,\n}: {\n done: number;\n total: number;\n width: number;\n}) {\n const label = `${done}/${total}`;\n const reserved = label.length + 2;\n const barWidth = Math.max(2, width - reserved);\n const inner = Math.min(barWidth, 40);\n const filled =\n total === 0 ? 0 : Math.min(inner, Math.round((done / total) * inner));\n const bar = `${'█'.repeat(filled)}${'░'.repeat(inner - filled)}`;\n return (\n <Text>\n <Text {...textStyles.muted}>{bar}</Text> <Text bold>{label}</Text>\n </Text>\n );\n}\n\nexport function AppUploadProgressView({\n client,\n extensionId,\n batches,\n total,\n verbose = false,\n onDone,\n}: AppUploadProgressViewProps) {\n const termWidth = useTerminalWidth();\n const layoutWidth = termWidth > 0 ? termWidth : '100%';\n const progressBarWidth = termWidth > 0 ? termWidth : 80;\n const [progress, setProgress] = useState<ArtifactUploadProgress | null>(null);\n const settledRef = useRef(false);\n\n useEffect(() => {\n settledRef.current = false;\n let cancelled = false;\n let finishTimer: ReturnType<typeof setTimeout> | undefined;\n\n void runArtifactUpload(client, extensionId, batches, {\n total,\n onProgress: (p) => {\n if (!cancelled) {\n setProgress(p);\n }\n },\n }).then((result) => {\n if (cancelled) {\n return;\n }\n if (!result.ok) {\n if (cancelled || settledRef.current) {\n return;\n }\n settledRef.current = true;\n onDone({\n kind: 'error',\n message: result.message,\n failedPath: result.failedPath,\n });\n return;\n }\n setProgress((prev) =>\n prev ? { ...prev, completedSoFar: result.uploaded, total } : prev,\n );\n finishTimer = setTimeout(() => {\n if (cancelled || settledRef.current) {\n return;\n }\n settledRef.current = true;\n onDone({ kind: 'success', uploaded: result.uploaded });\n }, 0);\n });\n\n return () => {\n cancelled = true;\n if (finishTimer !== undefined) {\n clearTimeout(finishTimer);\n }\n };\n }, [batches, client, extensionId, onDone, total]);\n\n const done = progress?.completedSoFar ?? 0;\n const active = progress?.activeRelativePath ?? '…';\n const uploadedPaths = progress?.uploadedRelativePaths ?? [];\n const showVerboseFileList = verbose && uploadedPaths.length > 0;\n const verboseText = formatVerboseUploadPaths(uploadedPaths);\n\n return (\n <Box width={layoutWidth} minWidth={0} {...layoutStyles.viewColumn}>\n <Box marginBottom={spacing.sm}>\n <Text {...textStyles.title}>Upload extension artifacts</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n <ProgressBar done={done} total={total} width={progressBarWidth} />\n <Box marginTop={spacing.sm}>\n <Text bold color=\"white\">\n {active}\n </Text>\n </Box>\n {showVerboseFileList ? (\n <Box marginTop={spacing.xs}>\n <Text {...textStyles.muted} wrap=\"wrap\">\n {verboseText}\n </Text>\n </Box>\n ) : null}\n {!progress ? (\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>Preparing…</Text>\n </Box>\n ) : null}\n </Box>\n </Box>\n );\n}\n","/** Tail cap for verbose CLI output (one multiline Text, not N Ink nodes). */\nexport const VERBOSE_UPLOAD_PATH_TAIL_MAX = 300;\n\n/**\n * Renders completed dist paths as newline-separated text; when there are more\n * than `maxTailLines`, keeps only the last `maxTailLines` and prefixes a\n * one-line omission summary.\n */\nexport function formatVerboseUploadPaths(\n paths: string[],\n maxTailLines = VERBOSE_UPLOAD_PATH_TAIL_MAX,\n): string {\n if (paths.length === 0) {\n return '';\n }\n if (paths.length <= maxTailLines) {\n return paths.join('\\n');\n }\n const omitted = paths.length - maxTailLines;\n return `… ${omitted} earlier path(s) omitted\\n${paths.slice(-maxTailLines).join('\\n')}`;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/app/upload.ts","../../../src/core/extension-upload.core.ts","../../../src/services/extension-artifacts.service.ts","../../../src/ui/views/app-upload/AppUploadProgressView.tsx","../../../src/ui/views/app-upload/verbose-upload-paths.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../core/core.command';\nimport { isSystemError } from '../../core/error';\nimport {\n collectDistUploadDescriptors,\n type DistUploadFileDescriptor,\n} from '../../core/extension-upload.core';\nimport { readInternalConfig } from '../../core/internal.config';\nimport { chunkArray } from '../../core/utils';\nimport { AppUploadProgressView } from '../../ui/views/app-upload';\n\nexport default class AppUpload extends BaseCommand {\n public static override description =\n 'Upload build output to the extension draft.';\n\n public static override flags = {\n dist: Flags.string({\n description: 'Path to the build output directory (relative to cwd)',\n default: 'dist',\n }),\n verbose: Flags.boolean({\n char: 'v',\n default: false,\n description:\n 'List each dist file path on its own line as uploads complete (no S3 keys)',\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(AppUpload);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n\n let extensionId: string;\n try {\n ({ extensionId } = await readInternalConfig(cwd));\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n const distAbs = resolve(cwd, flags.dist);\n try {\n const st = await stat(distAbs);\n if (!st.isDirectory()) {\n this.error(`Not a directory: ${distAbs}`, { exit: 2 });\n }\n } catch (e) {\n if (isSystemError(e, 'ENOENT')) {\n this.error(\n `Dist directory not found: ${distAbs}. Build your app first, or pass --dist.`,\n { exit: 2 },\n );\n }\n if (isSystemError(e, 'EACCES') || isSystemError(e, 'EPERM')) {\n this.error(`Cannot access dist directory: ${distAbs}`, { exit: 2 });\n }\n if (isSystemError(e, 'ENOTDIR')) {\n this.error(`Invalid dist path (not a directory): ${distAbs}`, {\n exit: 2,\n });\n }\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n let descriptors: DistUploadFileDescriptor[];\n try {\n descriptors = await collectDistUploadDescriptors(distAbs);\n } catch (e) {\n this.error(e instanceof Error ? e.message : String(e), { exit: 2 });\n }\n\n const result = await this.renderView(AppUploadProgressView, {\n client: this.getKittlApiClient(),\n extensionId,\n batches: chunkArray(descriptors, 50),\n total: descriptors.length,\n verbose: flags.verbose,\n });\n\n if (result.kind === 'error') {\n const msg = result.failedPath\n ? `${result.failedPath}\\n${result.message}`\n : result.message;\n this.error(msg, { exit: 2 });\n }\n\n this.log(`Uploaded ${result.uploaded} file(s) to your extension draft.`);\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { basename, relative } from 'node:path';\nimport type { AxiosInstance } from 'axios';\nimport {\n type ExtensionUploadSignedUrlRow,\n putPresignedUpload,\n requestExtensionUploadSignedUrls,\n} from '../services/extension-artifacts.service';\nimport { formatExtensionArtifactUploadError } from './error';\nimport { contentTypeForPath, listAllFilesUnderDir } from './files';\n\nconst MAX_RELATIVE_PATH_LEN = 512;\nconst RELATIVE_PATH_SEGMENT = /^[a-zA-Z0-9._-]+$/;\nconst S3_PUT_MAX_ATTEMPTS = 3;\nconst S3_PUT_RETRY_BASE_MS = 500;\n\nexport type DistUploadFileDescriptor = {\n absolutePath: string;\n relativePath: string;\n contentType: string;\n};\n\nexport type ArtifactUploadProgress = {\n completedSoFar: number;\n total: number;\n // path currently being read or uploaded.\n activeRelativePath: string;\n // paths uploaded so far (same order as uploads).\n uploadedRelativePaths: string[];\n};\n\nexport type ArtifactUploadResult =\n | { ok: true; uploaded: number }\n | { ok: false; message: string; failedPath?: string };\n\n// --- Path + MIME (upload-signed-urls contract) ---------------------------------------------------\n\n/** POSIX slashes, trim, strip leading `./` and `/` (single pass after `path.relative`). */\nexport function normalizeDistPath(rawPath: string): string {\n return rawPath\n .replace(/\\\\/g, '/')\n .trim()\n .replace(/^(\\.\\/|\\/)+/, '');\n}\n\n/** API path validation (segments, length, traversal). */\nexport function validateUploadPath(relativePath: string): string | null {\n if (!relativePath) {\n return 'Path is empty.';\n }\n if (relativePath.includes('\\\\')) {\n return 'Path must use forward slashes only, not backslashes.';\n }\n if (relativePath.length > MAX_RELATIVE_PATH_LEN) {\n return `Path exceeds max length (${MAX_RELATIVE_PATH_LEN}).`;\n }\n for (const segment of relativePath.split('/')) {\n if (!segment || segment === '.' || segment === '..') {\n return `Invalid path segment \"${segment}\" (no empty, \".\", or \"..\" segments).`;\n }\n if (!RELATIVE_PATH_SEGMENT.test(segment)) {\n return `Invalid path segment \"${segment}\" (allowed: letters, digits, \".\", \"_\", \"-\").`;\n }\n }\n return null;\n}\n\n/**\n * Lists `distRoot` recursively, validates paths, dedupes, sorts for stable progress / API order.\n */\nexport async function collectDistUploadDescriptors(\n distRoot: string,\n): Promise<DistUploadFileDescriptor[]> {\n const files = await listAllFilesUnderDir(distRoot);\n\n if (files.length === 0) {\n throw new Error(\n `No files found under ${distRoot}. Build your app before uploading.`,\n );\n }\n\n const descriptorByRelativePath = new Map<string, DistUploadFileDescriptor>();\n\n for (const absolutePath of files) {\n const relativePath = normalizeDistPath(relative(distRoot, absolutePath));\n const validationError = validateUploadPath(relativePath);\n if (validationError) {\n throw new Error(`${basename(absolutePath)}: ${validationError}`);\n }\n if (descriptorByRelativePath.has(relativePath)) {\n throw new Error(\n `Duplicate upload path after normalization: ${relativePath}`,\n );\n }\n descriptorByRelativePath.set(relativePath, {\n absolutePath,\n relativePath,\n contentType: contentTypeForPath(absolutePath),\n });\n }\n\n return [...descriptorByRelativePath.values()].sort((a, b) =>\n a.relativePath.localeCompare(b.relativePath),\n );\n}\n\nasync function putPresignedUploadWithRetry(\n url: string,\n body: Buffer,\n contentType: string,\n): Promise<void> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= S3_PUT_MAX_ATTEMPTS; attempt++) {\n try {\n await putPresignedUpload(url, body, contentType);\n return;\n } catch (err) {\n lastError = err;\n if (attempt >= S3_PUT_MAX_ATTEMPTS) {\n break;\n }\n await new Promise((r) => setTimeout(r, S3_PUT_RETRY_BASE_MS * attempt));\n }\n }\n throw lastError;\n}\n\n// --- Presigned batch upload ----------------------------------------------------------------------\n\n/**\n * Presigned URL batching + S3 PUTs with progress callbacks for Ink UI.\n * S3 PUTs retry with linear backoff.\n */\nexport async function runArtifactUpload(\n client: AxiosInstance,\n extensionId: string,\n batches: DistUploadFileDescriptor[][],\n opts: {\n total: number;\n onProgress: (p: ArtifactUploadProgress) => void;\n },\n): Promise<ArtifactUploadResult> {\n const { total, onProgress } = opts;\n let uploaded = 0;\n let lastRelativePath = '';\n const uploadedRelativePaths: string[] = [];\n\n for (let b = 0; b < batches.length; b++) {\n const batch = batches[b];\n if (!batch?.length) {\n continue;\n }\n const specs = batch.map((d) => ({\n relativePath: d.relativePath,\n contentType: d.contentType,\n }));\n let signed: ExtensionUploadSignedUrlRow[];\n try {\n signed = await requestExtensionUploadSignedUrls(\n client,\n extensionId,\n specs,\n );\n } catch (e) {\n return { ok: false, message: formatExtensionArtifactUploadError(e) };\n }\n\n for (let i = 0; i < batch.length; i++) {\n const d = batch[i];\n const row = signed[i];\n if (!d || !row) {\n return {\n ok: false,\n message: `Internal error: missing batch entry at index ${i} (batch ${b + 1}).`,\n };\n }\n if (row.relativePath !== d.relativePath) {\n return {\n ok: false,\n failedPath: d.relativePath,\n message: `Presigned URL order mismatch for ${d.relativePath} (batch ${b + 1}).`,\n };\n }\n\n lastRelativePath = d.relativePath;\n\n onProgress({\n completedSoFar: uploaded,\n total,\n activeRelativePath: d.relativePath,\n uploadedRelativePaths: [...uploadedRelativePaths],\n });\n\n let body: Buffer;\n try {\n body = await readFile(d.absolutePath);\n } catch (e) {\n return {\n ok: false,\n failedPath: d.relativePath,\n message:\n e instanceof Error\n ? `Failed to read ${d.relativePath}: ${e.message}`\n : String(e),\n };\n }\n\n try {\n await putPresignedUploadWithRetry(row.url, body, row.contentType);\n } catch (e) {\n return {\n ok: false,\n failedPath: d.relativePath,\n message:\n e instanceof Error\n ? `S3 upload failed for ${d.relativePath}: ${e.message}`\n : `S3 upload failed for ${d.relativePath}: ${String(e)}`,\n };\n }\n\n uploaded++;\n uploadedRelativePaths.push(d.relativePath);\n onProgress({\n completedSoFar: uploaded,\n total,\n activeRelativePath: d.relativePath,\n uploadedRelativePaths: [...uploadedRelativePaths],\n });\n }\n }\n\n onProgress({\n completedSoFar: uploaded,\n total,\n activeRelativePath:\n total <= 1 ? lastRelativePath : `${uploaded} files uploaded`,\n uploadedRelativePaths: [...uploadedRelativePaths],\n });\n return { ok: true, uploaded };\n}\n","import type { AxiosInstance } from 'axios';\nimport axios from 'axios';\nimport { z } from 'zod';\n\nconst uploadSignedUrlsResponseSchema = z.object({\n success: z.literal(true),\n results: z.array(\n z.object({\n url: z.string().min(1),\n key: z.string(),\n relativePath: z.string(),\n contentType: z.string().min(1),\n }),\n ),\n});\n\nexport type UploadSignedUrlFileSpec = {\n relativePath: string;\n contentType: string;\n};\n\nexport type ExtensionUploadSignedUrlRow = {\n url: string;\n key: string;\n relativePath: string;\n contentType: string;\n};\n\nexport async function requestExtensionUploadSignedUrls(\n client: AxiosInstance,\n extensionId: string,\n files: UploadSignedUrlFileSpec[],\n): Promise<ExtensionUploadSignedUrlRow[]> {\n const path = `/extensions/${extensionId}/versions/upload-signed-urls`;\n const { data } = await client.post(path, { files });\n const parsed = uploadSignedUrlsResponseSchema.safeParse(data);\n if (!parsed.success) {\n throw parsed.error;\n }\n const map = new Map(\n parsed.data.results.map((r) => [r.relativePath, r] as const),\n );\n const ordered: ExtensionUploadSignedUrlRow[] = [];\n for (const f of files) {\n const row = map.get(f.relativePath);\n if (row === undefined) {\n throw new Error(`Missing presigned URL for path: ${f.relativePath}`);\n }\n ordered.push(row);\n }\n return ordered;\n}\n\n/**\n * Dedicated Axios instance for presigned S3 PUT requests only.\n * `maxBodyLength` / `maxContentLength`: avoid Axios body-size caps on large assets.\n * `timeout: 0`: no Axios deadline on slow uploads (TCP / network still apply).\n */\nconst s3Client = axios.create({\n maxBodyLength: Infinity,\n maxContentLength: Infinity,\n timeout: 0,\n});\n\n/**\n * PUT raw bytes to a presigned URL using {@link s3Client} only.\n * `contentType` must match the value the API used when signing, byte-for-byte, or S3 returns 403.\n */\nexport async function putPresignedUpload(\n url: string,\n body: Buffer,\n contentType: string,\n): Promise<void> {\n await s3Client.put(url, body, {\n headers: { 'Content-Type': contentType },\n });\n}\n","import type { AxiosInstance } from 'axios';\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n type ArtifactUploadProgress,\n type DistUploadFileDescriptor,\n runArtifactUpload,\n} from '../../../core/extension-upload.core';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\nimport { spacing } from '../../theme/tokens';\nimport { formatVerboseUploadPaths } from './verbose-upload-paths';\n\nexport type AppUploadProgressResult =\n | { kind: 'success'; uploaded: number }\n | { kind: 'error'; message: string; failedPath?: string };\n\nexport type AppUploadProgressViewProps = {\n client: AxiosInstance;\n extensionId: string;\n batches: DistUploadFileDescriptor[][];\n total: number;\n // When true, completed dist paths are listed one per line\n verbose?: boolean;\n onDone: (result: AppUploadProgressResult) => void;\n};\n\nfunction ProgressBar({\n done,\n total,\n width,\n}: {\n done: number;\n total: number;\n width: number;\n}) {\n const label = `${done}/${total}`;\n const reserved = label.length + 2;\n const barWidth = Math.max(2, width - reserved);\n const inner = Math.min(barWidth, 40);\n const filled =\n total === 0 ? 0 : Math.min(inner, Math.round((done / total) * inner));\n const bar = `${'█'.repeat(filled)}${'░'.repeat(inner - filled)}`;\n return (\n <Text>\n <Text {...textStyles.muted}>{bar}</Text> <Text bold>{label}</Text>\n </Text>\n );\n}\n\nexport function AppUploadProgressView({\n client,\n extensionId,\n batches,\n total,\n verbose = false,\n onDone,\n}: AppUploadProgressViewProps) {\n const termWidth = useTerminalWidth();\n const layoutWidth = termWidth > 0 ? termWidth : '100%';\n const progressBarWidth = termWidth > 0 ? termWidth : 80;\n const [progress, setProgress] = useState<ArtifactUploadProgress | null>(null);\n const settledRef = useRef(false);\n\n useEffect(() => {\n settledRef.current = false;\n let cancelled = false;\n let finishTimer: ReturnType<typeof setTimeout> | undefined;\n\n void runArtifactUpload(client, extensionId, batches, {\n total,\n onProgress: (p) => {\n if (!cancelled) {\n setProgress(p);\n }\n },\n }).then((result) => {\n if (cancelled) {\n return;\n }\n if (!result.ok) {\n if (cancelled || settledRef.current) {\n return;\n }\n settledRef.current = true;\n onDone({\n kind: 'error',\n message: result.message,\n failedPath: result.failedPath,\n });\n return;\n }\n setProgress((prev) =>\n prev ? { ...prev, completedSoFar: result.uploaded, total } : prev,\n );\n finishTimer = setTimeout(() => {\n if (cancelled || settledRef.current) {\n return;\n }\n settledRef.current = true;\n onDone({ kind: 'success', uploaded: result.uploaded });\n }, 0);\n });\n\n return () => {\n cancelled = true;\n if (finishTimer !== undefined) {\n clearTimeout(finishTimer);\n }\n };\n }, [batches, client, extensionId, onDone, total]);\n\n const done = progress?.completedSoFar ?? 0;\n const active = progress?.activeRelativePath ?? '…';\n const uploadedPaths = progress?.uploadedRelativePaths ?? [];\n const showVerboseFileList = verbose && uploadedPaths.length > 0;\n const verboseText = formatVerboseUploadPaths(uploadedPaths);\n\n return (\n <Box width={layoutWidth} minWidth={0} {...layoutStyles.viewColumn}>\n <Box marginBottom={spacing.sm}>\n <Text {...textStyles.title}>Upload extension artifacts</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n <ProgressBar done={done} total={total} width={progressBarWidth} />\n <Box marginTop={spacing.sm}>\n <Text bold color=\"white\">\n {active}\n </Text>\n </Box>\n {showVerboseFileList ? (\n <Box marginTop={spacing.xs}>\n <Text {...textStyles.muted} wrap=\"wrap\">\n {verboseText}\n </Text>\n </Box>\n ) : null}\n {!progress ? (\n <Box marginTop={spacing.sm}>\n <Text {...textStyles.muted}>Preparing…</Text>\n </Box>\n ) : null}\n </Box>\n </Box>\n );\n}\n","/** Tail cap for verbose CLI output (one multiline Text, not N Ink nodes). */\nexport const VERBOSE_UPLOAD_PATH_TAIL_MAX = 300;\n\n/**\n * Renders completed dist paths as newline-separated text; when there are more\n * than `maxTailLines`, keeps only the last `maxTailLines` and prefixes a\n * one-line omission summary.\n */\nexport function formatVerboseUploadPaths(\n paths: string[],\n maxTailLines = VERBOSE_UPLOAD_PATH_TAIL_MAX,\n): string {\n if (paths.length === 0) {\n return '';\n }\n if (paths.length <= maxTailLines) {\n return paths.join('\\n');\n }\n const omitted = paths.length - maxTailLines;\n return `… ${omitted} earlier path(s) omitted\\n${paths.slice(-maxTailLines).join('\\n')}`;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,10 +6,13 @@ import {
|
|
|
6
6
|
textStyles
|
|
7
7
|
} from "../../chunk-3BPIJLS7.js";
|
|
8
8
|
import {
|
|
9
|
-
BaseCommand
|
|
9
|
+
BaseCommand
|
|
10
|
+
} from "../../chunk-CT7IDOZX.js";
|
|
11
|
+
import {
|
|
10
12
|
INK_VIEW_UNMOUNT_REASON,
|
|
11
13
|
authService
|
|
12
|
-
} from "../../chunk-
|
|
14
|
+
} from "../../chunk-X67IL4KU.js";
|
|
15
|
+
import "../../chunk-ZS7NZCD4.js";
|
|
13
16
|
|
|
14
17
|
// src/ui/views/login/LoginView.tsx
|
|
15
18
|
import { Box, Text as Text2 } from "ink";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/views/login/LoginView.tsx","../../../src/ui/components/InlineSpinner.tsx","../../../src/commands/auth/login.ts"],"sourcesContent":["import { Box, Text } from 'ink';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { INK_VIEW_UNMOUNT_REASON } from '../../../core/utils';\nimport { authService } from '../../../services/auth.service';\nimport { InlineSpinner } from '../../components/InlineSpinner';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\n\nconst CHECKING_SESSION = 'Checking session…';\nconst SIGNING_IN = 'Signing in…';\n\nexport type LoginResult =\n | { kind: 'success'; reusedSession?: boolean }\n | { kind: 'cancelled' }\n | { kind: 'error'; error: Error };\n\nexport type LoginViewProps = {\n onDone: (result: LoginResult) => void;\n};\n\n/**\n * OAuth login TUI.\n * **Unmount:** aborts the local `AbortController` so discovery + the callback server stop cleanly.\n */\nexport function LoginView({ onDone }: LoginViewProps) {\n const width = useTerminalWidth();\n const doneRef = useRef(false);\n const [phase, setPhase] = useState<'checking' | 'signing-in'>('checking');\n\n const finish = useCallback(\n (result: LoginResult, force = false) => {\n if (doneRef.current && !force) return;\n doneRef.current = true;\n onDone(result);\n },\n [onDone],\n );\n\n useEffect(() => {\n doneRef.current = false;\n const ac = new AbortController();\n\n void (async () => {\n try {\n const existing = await authService.getSession();\n if (ac.signal.aborted) {\n finish({ kind: 'cancelled' }, true);\n return;\n }\n if (existing?.accessToken) {\n finish({ kind: 'success', reusedSession: true });\n return;\n }\n\n setPhase('signing-in');\n await authService.login({ signal: ac.signal });\n finish({ kind: 'success' });\n } catch (error) {\n if (error === INK_VIEW_UNMOUNT_REASON) {\n finish({ kind: 'cancelled' }, true);\n return;\n }\n if (doneRef.current) return;\n finish({\n kind: 'error',\n error: error instanceof Error ? error : new Error('Auth failed'),\n });\n }\n })();\n\n return () => {\n doneRef.current = true;\n ac.abort(INK_VIEW_UNMOUNT_REASON);\n };\n }, [finish]);\n\n return (\n <Box\n {...layoutStyles.viewColumn}\n width={width > 0 ? width : '100%'}\n minWidth={0}\n >\n <Text {...textStyles.title}>Kittl CLI Authentication</Text>\n <Box {...layoutStyles.section}>\n <InlineSpinner\n label={phase === 'checking' ? CHECKING_SESSION : SIGNING_IN}\n />\n </Box>\n </Box>\n );\n}\n","import { Text } from 'ink';\nimport { useEffect, useState } from 'react';\nimport { textStyles } from '../theme/styles';\n\nexport type InlineSpinnerProps = {\n label: string;\n};\nconst frames = ['-', '\\\\', '|', '/'];\nexport function InlineSpinner({ label }: InlineSpinnerProps) {\n const [frameIndex, setFrameIndex] = useState(0);\n\n useEffect(() => {\n const timer = setInterval(() => {\n setFrameIndex((current) => (current + 1) % frames.length);\n }, 80);\n return () => clearInterval(timer);\n }, []);\n\n return (\n <Text {...textStyles.muted}>\n {frames[frameIndex]} {label}\n </Text>\n );\n}\n","import { BaseCommand } from '../../core/core.command';\nimport { LoginView } from '../../ui/views/login';\n\nexport default class AuthLogin extends BaseCommand {\n public static description = 'Authenticate with your Kittl account';\n\n public async run(): Promise<void> {\n await this.parse(AuthLogin);\n\n const result = await this.renderView(LoginView);\n\n if (result.kind === 'cancelled') {\n this.exit(130);\n }\n if (result.kind === 'error') {\n throw result.error;\n }\n\n if (result.reusedSession) {\n this.log('Already signed in.');\n } else {\n this.log('Signed in successfully.');\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/views/login/LoginView.tsx","../../../src/ui/components/InlineSpinner.tsx","../../../src/commands/auth/login.ts"],"sourcesContent":["import { Box, Text } from 'ink';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { INK_VIEW_UNMOUNT_REASON } from '../../../core/utils';\nimport { authService } from '../../../services/auth.service';\nimport { InlineSpinner } from '../../components/InlineSpinner';\nimport { useTerminalWidth } from '../../hooks';\nimport { layoutStyles, textStyles } from '../../theme/styles';\n\nconst CHECKING_SESSION = 'Checking session…';\nconst SIGNING_IN = 'Signing in…';\n\nexport type LoginResult =\n | { kind: 'success'; reusedSession?: boolean }\n | { kind: 'cancelled' }\n | { kind: 'error'; error: Error };\n\nexport type LoginViewProps = {\n onDone: (result: LoginResult) => void;\n};\n\n/**\n * OAuth login TUI.\n * **Unmount:** aborts the local `AbortController` so discovery + the callback server stop cleanly.\n */\nexport function LoginView({ onDone }: LoginViewProps) {\n const width = useTerminalWidth();\n const doneRef = useRef(false);\n const [phase, setPhase] = useState<'checking' | 'signing-in'>('checking');\n\n const finish = useCallback(\n (result: LoginResult, force = false) => {\n if (doneRef.current && !force) return;\n doneRef.current = true;\n onDone(result);\n },\n [onDone],\n );\n\n useEffect(() => {\n doneRef.current = false;\n const ac = new AbortController();\n\n void (async () => {\n try {\n const existing = await authService.getSession();\n if (ac.signal.aborted) {\n finish({ kind: 'cancelled' }, true);\n return;\n }\n if (existing?.accessToken) {\n finish({ kind: 'success', reusedSession: true });\n return;\n }\n\n setPhase('signing-in');\n await authService.login({ signal: ac.signal });\n finish({ kind: 'success' });\n } catch (error) {\n if (error === INK_VIEW_UNMOUNT_REASON) {\n finish({ kind: 'cancelled' }, true);\n return;\n }\n if (doneRef.current) return;\n finish({\n kind: 'error',\n error: error instanceof Error ? error : new Error('Auth failed'),\n });\n }\n })();\n\n return () => {\n doneRef.current = true;\n ac.abort(INK_VIEW_UNMOUNT_REASON);\n };\n }, [finish]);\n\n return (\n <Box\n {...layoutStyles.viewColumn}\n width={width > 0 ? width : '100%'}\n minWidth={0}\n >\n <Text {...textStyles.title}>Kittl CLI Authentication</Text>\n <Box {...layoutStyles.section}>\n <InlineSpinner\n label={phase === 'checking' ? CHECKING_SESSION : SIGNING_IN}\n />\n </Box>\n </Box>\n );\n}\n","import { Text } from 'ink';\nimport { useEffect, useState } from 'react';\nimport { textStyles } from '../theme/styles';\n\nexport type InlineSpinnerProps = {\n label: string;\n};\nconst frames = ['-', '\\\\', '|', '/'];\nexport function InlineSpinner({ label }: InlineSpinnerProps) {\n const [frameIndex, setFrameIndex] = useState(0);\n\n useEffect(() => {\n const timer = setInterval(() => {\n setFrameIndex((current) => (current + 1) % frames.length);\n }, 80);\n return () => clearInterval(timer);\n }, []);\n\n return (\n <Text {...textStyles.muted}>\n {frames[frameIndex]} {label}\n </Text>\n );\n}\n","import { BaseCommand } from '../../core/core.command';\nimport { LoginView } from '../../ui/views/login';\n\nexport default class AuthLogin extends BaseCommand {\n public static description = 'Authenticate with your Kittl account';\n\n public async run(): Promise<void> {\n await this.parse(AuthLogin);\n\n const result = await this.renderView(LoginView);\n\n if (result.kind === 'cancelled') {\n this.exit(130);\n }\n if (result.kind === 'error') {\n throw result.error;\n }\n\n if (result.reusedSession) {\n this.log('Already signed in.');\n } else {\n this.log('Signed in successfully.');\n }\n }\n}\n"],"mappings":"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","names":["Text","useEffect","useState","jsxs","useState","useEffect","Text"]}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BaseCommand
|
|
2
|
+
BaseCommand
|
|
3
|
+
} from "../../chunk-CT7IDOZX.js";
|
|
4
|
+
import {
|
|
3
5
|
authService
|
|
4
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-X67IL4KU.js";
|
|
7
|
+
import "../../chunk-ZS7NZCD4.js";
|
|
5
8
|
|
|
6
9
|
// src/commands/auth/logout.ts
|
|
7
10
|
var AuthLogout = class _AuthLogout extends BaseCommand {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/auth/logout.ts"],"sourcesContent":["import { BaseCommand } from '../../core/core.command';\nimport { authService } from '../../services/auth.service';\n\nexport default class AuthLogout extends BaseCommand {\n public static override description = 'Clear local Kittl CLI session';\n\n public async run(): Promise<void> {\n await this.parse(AuthLogout);\n\n await authService.logout();\n this.log('Logged out.');\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/auth/logout.ts"],"sourcesContent":["import { BaseCommand } from '../../core/core.command';\nimport { authService } from '../../services/auth.service';\n\nexport default class AuthLogout extends BaseCommand {\n public static override description = 'Clear local Kittl CLI session';\n\n public async run(): Promise<void> {\n await this.parse(AuthLogout);\n\n await authService.logout();\n this.log('Logged out.');\n }\n}\n"],"mappings":";;;;;;;;;AAGA,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAuB,cAAc;AAAA,EAErC,MAAa,MAAqB;AAChC,UAAM,KAAK,MAAM,WAAU;AAE3B,UAAM,YAAY,OAAO;AACzB,SAAK,IAAI,aAAa;AAAA,EACxB;AACF;","names":[]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthWhoAmI
|
|
3
|
-
} from "../../chunk-
|
|
4
|
-
import "../../chunk-
|
|
3
|
+
} from "../../chunk-LZM72TST.js";
|
|
4
|
+
import "../../chunk-CT7IDOZX.js";
|
|
5
|
+
import "../../chunk-X67IL4KU.js";
|
|
6
|
+
import "../../chunk-ZS7NZCD4.js";
|
|
5
7
|
export {
|
|
6
8
|
AuthWhoAmI as default
|
|
7
9
|
};
|