@kittl/cli 0.0.2 → 0.0.4-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-XU2ZHSRY.js → chunk-7LTVG6SC.js} +2 -2
- package/dist/{chunk-637YZAKM.js → chunk-FJAYC3KU.js} +2 -2
- package/dist/{chunk-TK44DTSK.js → chunk-OY6OB5HM.js} +52 -8
- package/dist/chunk-OY6OB5HM.js.map +1 -0
- package/dist/{chunk-GJPVFQRF.js → chunk-S4KAOR7F.js} +9 -5
- package/dist/chunk-S4KAOR7F.js.map +1 -0
- package/dist/commands/app/init.js +43 -16
- package/dist/commands/app/init.js.map +1 -1
- package/dist/commands/app/release.js +3 -3
- package/dist/commands/app/update.js +3 -3
- package/dist/commands/app/upload.js +5 -20
- package/dist/commands/app/upload.js.map +1 -1
- package/dist/commands/auth/login.js +1 -1
- package/dist/commands/auth/logout.js +1 -1
- package/dist/commands/auth/whoami.js +2 -2
- package/dist/commands/whoami.js +2 -2
- package/oclif.manifest.json +196 -0
- package/package.json +4 -2
- package/dist/chunk-GJPVFQRF.js.map +0 -1
- package/dist/chunk-TK44DTSK.js.map +0 -1
- /package/dist/{chunk-XU2ZHSRY.js.map → chunk-7LTVG6SC.js.map} +0 -0
- /package/dist/{chunk-637YZAKM.js.map → chunk-FJAYC3KU.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 } from 'node:path';\nimport { CLI_CONFIG } from '../../constants';\nimport { BaseCommand } from '../../core/core.command';\nimport { formatHttpClientError } from '../../core/error';\nimport {\n internalConfigExists,\n internalConfigPath,\n writeInternalConfig,\n} from '../../core/internal.config';\nimport { scaffoldExtension } from '../../core/scaffolder';\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 this directory';\n\n public async run(): Promise<void> {\n await this.parse(AppInit);\n\n await this.ensureAuthenticated();\n\n const cwd = process.cwd();\n if (await internalConfigExists(cwd)) {\n this.error(\n `Kittl config already exists at ${internalConfigPath(cwd)}. Remove it or run from another 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 wizardResult = await this.renderView(AppInitWizardView, {\n organizations,\n client,\n });\n\n if (wizardResult.kind === 'cancelled') {\n this.exit(130);\n }\n\n const { data } = wizardResult;\n\n const path = await writeInternalConfig(cwd, {\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(cwd, 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(cwd, 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 ${path}`);\n\n this.log('');\n this.log(`Success! Extension \"${data.extensionName}\" is ready.`);\n this.log('Next steps:');\n let step = 1;\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 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: '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\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 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: '^5.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 { defineConfig } from 'vite';\n\nexport default defineConfig({\n server: {\n port: ${CLI_CONFIG.scaffoldViteDevPort},\n },\n publicDir: 'public',\n build: {\n outDir: 'dist',\n },\n});\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\">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 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 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 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 // 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 requireNonEmpty = true,\n onDone,\n}: TextInputViewProps) {\n const width = useTerminalWidth();\n const [value, setValue] = useState('');\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":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,QAAAA,aAAY;;;ACArB,SAAS,QAAQ,OAAO,iBAAiB;AACzC,SAAS,YAAY;;;ACUrB,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AAM5B,IAAM,8BAA8B;AAEpC,SAAS,6BAA6B,MAAsB;AAC1D,QAAM,OAAO,KACV,KAAK,EACL,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,eAAe,EAAE;AAC5B,SAAO,KAAK,SAAS,IAAI,OAAO;AAClC;AAMO,SAAS,yBACd,aACmB;AACnB,QAAM,QAAQ,YAAY,KAAK,KAAK;AACpC,SAAO;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS,GAAG,KAAK;AAAA,IACjB,aAAa;AAAA,MACX,aAAa,WAAW,KAAK;AAAA,MAC7B,YAAY;AAAA,MACZ,wBAAwB;AAAA,MACxB,mBAAmB;AAAA,IACrB;AAAA,IACA,QAAQ;AAAA;AAAA,MAEN,QAAQ,CAAC,qBAAqB,oBAAoB;AAAA,MAClD,OAAO;AAAA,QACL,cAAc;AAAA,UACZ,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,iBAAiB,aAA6B;AAC5D,SAAO,GAAG,KAAK;AAAA,IACb,yBAAyB,WAAW;AAAA,IACpC;AAAA;AAAA,IACA;AAAA;AAAA,EACF,CAAC;AAAA;AACH;AAEO,SAAS,oBAAoB,aAA6B;AAC/D,SAAO,GAAG,KAAK;AAAA,IACb;AAAA,MACE,MAAM,6BAA6B,WAAW;AAAA,MAC9C,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,QACP,KAAK;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,MACX;AAAA,MACA,cAAc;AAAA,QACZ,cAAc;AAAA,MAChB;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACF,CAAC;AAAA;AACH;AAEO,SAAS,qBAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA;AAAA,YAIG,WAAW,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ1C;AAEO,SAAS,kBAAkB,aAA6B;AAC7D,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,aAKI,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,0CAKkB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOrD;AAEO,SAAS,wBAAwB,aAA6B;AACnE,SAAO;AAAA;AAAA;AAAA;AAAA,mBAIU,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAc9B;AAGO,IAAM,oBACX;;;AD9HF,eAAe,WAAW,UAAoC;AAC5D,MAAI;AACF,UAAM,OAAO,QAAQ;AACrB,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,cAAc,GAAG,QAAQ,GAAG;AAC9B,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAOA,eAAsB,kBACpB,KACA,aACkC;AAClC,QAAM,eAAe,KAAK,KAAK,WAAW,gBAAgB;AAC1D,QAAM,kBAAkB,KAAK,KAAK,cAAc;AAEhD,MAAI,MAAM,WAAW,eAAe,GAAG;AACrC,QAAI,MAAM,WAAW,YAAY,GAAG;AAClC,aAAO;AAAA,QACL,SAAS,CAAC;AAAA,QACV,SAAS,CAAC;AAAA,QACV,qBAAqB;AAAA,MACvB;AAAA,IACF;AACA,UAAM,UAAU,cAAc,iBAAiB,WAAW,GAAG,MAAM;AACnE,WAAO;AAAA,MACL,SAAS,CAAC,WAAW,gBAAgB;AAAA,MACrC,SAAS,CAAC;AAAA,MACV,qBAAqB;AAAA,MACrB,qBAAqB;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,QAA0D;AAAA,IAC9D;AAAA,MACE,KAAK,WAAW;AAAA,MAChB,MAAM;AAAA,MACN,SAAS,iBAAiB,WAAW;AAAA,IACvC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,MAAM;AAAA,MACN,SAAS,oBAAoB,WAAW;AAAA,IAC1C;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,MAAM,KAAK,KAAK,gBAAgB;AAAA,MAChC,SAAS,mBAAmB;AAAA,IAC9B;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,MAAM,KAAK,KAAK,YAAY;AAAA,MAC5B,SAAS,kBAAkB,WAAW;AAAA,IACxC;AAAA,IACA;AAAA,MACE,KAAK,KAAK,UAAU,UAAU;AAAA,MAC9B,MAAM,KAAK,KAAK,UAAU,UAAU;AAAA,MACpC,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,KAAK,KAAK,OAAO,UAAU;AAAA,MAC3B,MAAM,KAAK,KAAK,OAAO,UAAU;AAAA,MACjC,SAAS,wBAAwB,WAAW;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM,MAAM,KAAK,KAAK,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,QAAM,MAAM,KAAK,KAAK,KAAK,GAAG,EAAE,WAAW,KAAK,CAAC;AAEjD,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAE3B,aAAW,KAAK,OAAO;AACrB,QAAI,MAAM,WAAW,EAAE,IAAI,GAAG;AAC5B,cAAQ,KAAK,EAAE,GAAG;AAClB;AAAA,IACF;AACA,UAAM,UAAU,EAAE,MAAM,EAAE,SAAS,MAAM;AACzC,YAAQ,KAAK,EAAE,GAAG;AAAA,EACpB;AAEA,SAAO,EAAE,SAAS,QAAQ;AAC5B;;;AEnHA,SAAS,SAAS;AAElB,IAAM,8BAA8B,EAAE,OAAO;AAAA,EAC3C,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AAAA,EACf,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,WAAW,EAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AAED,IAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,SAAS,EAAE,QAAQ,IAAI;AAAA,EACvB,QAAQ,EAAE,OAAO;AAAA,IACf,wBAAwB,EAAE,MAAM,2BAA2B;AAAA,EAC7D,CAAC;AACH,CAAC;AAED,IAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,SAAS,EAAE,QAAQ,IAAI;AAAA,EACvB,QAAQ,EAAE,OAAO;AAAA,IACf,yBAAyB,EAAE,OAAO;AAAA,EACpC,CAAC;AACH,CAAC;AAED,IAAM,gCAAgC,EAAE,OAAO;AAAA,EAC7C,SAAS,EAAE,QAAQ,IAAI;AAAA,EACvB,QAAQ,EAAE,OAAO;AAAA,IACf,aAAa,EAAE,OAAO;AAAA,EACxB,CAAC;AACH,CAAC;AAID,eAAsB,2BACpB,QACkC;AAClC,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,IAAI,0BAA0B;AAC5D,QAAM,SAAS,mBAAmB,MAAM,IAAI;AAC5C,SAAO,OAAO,OAAO;AACvB;AAEA,eAAsB,4BACpB,QACA,MACiB;AACjB,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,4BAA4B;AAAA,IAC7D;AAAA,EACF,CAAC;AACD,QAAM,SAAS,wBAAwB,MAAM,IAAI;AACjD,SAAO,OAAO,OAAO;AACvB;AAEA,eAAsB,uCACpB,QACA,yBACA,MACiB;AACjB,QAAM,OAAO,4BAA4B,uBAAuB;AAChE,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM,IAAI;AAC7C,QAAM,SAAS,8BAA8B,MAAM,IAAI;AACvD,SAAO,OAAO,OAAO;AACvB;;;AC5DA,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAE1B,SAAS,eAAAC,cAAa,YAAAC,iBAAgB;;;ACHtC,SAAS,KAAe,MAAM,gBAAgB;AAC9C,SAAS,aAAa,WAAW,SAAS,QAAQ,gBAAgB;AAiG5D,cAaM,YAbN;AA5EN,IAAM,mBAAmB;AAElB,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAA+B;AAC7B,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AAEpC,QAAM,WAAW,OAAO,KAAK;AAC7B,QAAM,mBAAmB,OAAO,aAAa;AAC7C,QAAM,YAAY,OAAO,MAAM;AAE/B,WAAS,UAAU;AACnB,mBAAiB,UAAU;AAC3B,YAAU,UAAU;AAEpB,YAAU,MAAM;AACd,UAAM,WAAW,cAAc;AAC/B,aAAS,CAAC,MAAO,IAAI,WAAW,WAAW,CAAE;AAAA,EAC/C,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,SAAS;AAAA,IACb,MAAM,CAAC,GAAG,cAAc,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,gBAAgB;AAAA,IAC5D,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,cAAc,YAAY,CAAC,QAAgB,QAAa;AAC5D,QAAI,IAAI,QAAQ;AACd,gBAAU,QAAQ,EAAE,MAAM,YAAY,CAAC;AACvC;AAAA,IACF;AACA,QAAI,YAAY,GAAG,GAAG;AACpB,YAAM,MAAM,SAAS;AACrB,YAAM,OAAO,iBAAiB;AAC9B,UAAI,QAAQ,KAAK,QAAQ;AACvB,kBAAU,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxC;AAAA,MACF;AACA,YAAM,MAAM,KAAK,GAAG;AACpB,gBAAU,QAAQ;AAAA,QAChB,MAAM;AAAA,QACN,yBAAyB,IAAI;AAAA,QAC7B,MAAM,IAAI;AAAA,MACZ,CAAC;AACD;AAAA,IACF;AACA,QAAI,IAAI,SAAS;AACf,eAAS,CAAC,MAAM;AACd,cAAM,KAAK,iBAAiB,QAAQ,SAAS;AAC7C,cAAM,OAAO,KAAK,IAAI,KAAK,IAAI,IAAI;AACnC,iBAAS,UAAU;AACnB,eAAO;AAAA,MACT,CAAC;AACD;AAAA,IACF;AACA,QAAI,IAAI,WAAW;AACjB,eAAS,CAAC,MAAM;AACd,cAAM,KAAK,iBAAiB,QAAQ,SAAS;AAC7C,cAAM,OAAO,KAAK,KAAK,IAAI,IAAI,IAAI;AACnC,iBAAS,UAAU;AACnB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,WAAS,WAAW;AAEpB,QAAM,QAAQ,cAAc,WAAW;AAEvC,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,aAAa;AAAA,MACjB,OAAO,QAAQ,IAAI,QAAQ;AAAA,MAC3B,UAAU;AAAA,MAEV;AAAA,4BAAC,QAAM,GAAG,WAAW,OAAO,2CAA6B;AAAA,QACzD,oBAAC,QAAM,GAAG,WAAW,OAAO,kEAAoC;AAAA,QAChE,qBAAC,OAAK,GAAG,aAAa,SAAS,eAAc,UAC1C;AAAA,kBACC,oBAAC,OAAI,cAAc,GACjB,8BAAC,QAAM,GAAG,WAAW,OAClB,qDACH,GACF,IACE;AAAA,UACH,OAAO,IAAI,CAAC,OAAO,MAAM;AACxB,kBAAM,aAAa,MAAM;AACzB,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAM;AAAA,gBACN,OAAO,aAAa,OAAO,SAAS;AAAA,gBAEnC;AAAA,+BAAa,YAAO;AAAA,kBACpB;AAAA;AAAA;AAAA,cALI,GAAG,KAAK,IAAI,CAAC;AAAA,YAMpB;AAAA,UAEJ,CAAC;AAAA,WACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC5HA,SAAS,OAAAC,MAAK,QAAAC,OAAM,YAAAC,iBAAgB;AACpC,OAAO,eAAe;AACtB,SAAS,eAAAC,cAAa,YAAAC,iBAAgB;AAwDlC,SAKE,OAAAC,MALF,QAAAC,aAAA;AArCG,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AACF,GAAuB;AACrB,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,EAAE;AACrC,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AAEtD,QAAM,SAASC;AAAA,IACb,CAAC,WAA8B;AAC7B,aAAO,MAAM;AAAA,IACf;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,EAAAC,UAAS,CAAC,QAAQ,QAAQ;AACxB,QAAI,IAAI,QAAQ;AACd,aAAO,EAAE,MAAM,YAAY,CAAC;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,QAAM,eAAeD;AAAA,IACnB,CAAC,cAAsB;AACrB,YAAM,UAAU,UAAU,KAAK;AAC/B,UAAI,mBAAmB,QAAQ,WAAW,GAAG;AAC3C,iBAAS,kBAAkB;AAC3B;AAAA,MACF;AACA,eAAS,IAAI;AACb,aAAO,EAAE,MAAM,UAAU,OAAO,QAAQ,CAAC;AAAA,IAC3C;AAAA,IACA,CAAC,QAAQ,eAAe;AAAA,EAC1B;AAEA,SACE,gBAAAF;AAAA,IAACI;AAAA,IAAA;AAAA,MACE,GAAG,aAAa;AAAA,MACjB,OAAO,QAAQ,IAAI,QAAQ;AAAA,MAC3B,UAAU;AAAA,MAEV;AAAA,wBAAAL,KAACM,OAAA,EAAM,GAAG,WAAW,OAAQ,iBAAM;AAAA,QACnC,gBAAAN,KAACK,MAAA,EAAK,GAAG,aAAa,SAAS,eAAc,OAAM,UAAS,QAC1D,0BAAAL;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,UAAU,CAAC,MAAM;AACf,uBAAS,CAAC;AACV,kBAAI,OAAO;AACT,yBAAS,IAAI;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU;AAAA,YACV,aAAa,eAAe;AAAA;AAAA,QAC9B,GACF;AAAA,QACC,QACC,gBAAAA,KAACM,OAAA,EAAM,GAAG,WAAW,OAAQ,iBAAM,IAEnC,gBAAAN,KAACM,OAAA,EAAM,GAAG,WAAW,OAAO,2CAA0B;AAAA;AAAA;AAAA,EAE1D;AAEJ;;;AFtBU,gBAAAC,MAKA,QAAAC,aALA;AAjBV,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE,gBAAAA,MAACC,MAAA,EAAI,eAAc,UAAS,OAAc,UAAU,GACjD;AAAA,eACC,gBAAAF,KAACE,MAAA,EAAI,YAAY,QAAQ,IAAI,cAAc,QAAQ,IACjD,0BAAAF,KAACG,OAAA,EAAM,GAAG,WAAW,OAAQ,oBAAS,GACxC,IACE;AAAA,IACH,YACC,gBAAAH,KAACE,MAAA,EAAK,GAAG,aAAa,YACpB,0BAAAD,MAACE,OAAA,EAAM,GAAG,WAAW,OAAQ;AAAA;AAAA,MAAY;AAAA,OAAC,GAC5C,IAEA;AAAA,KAEJ;AAEJ;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,IAAI,QAAQ,IAAI,QAAQ;AAE9B,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAe,MAAM;AAC7C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAsB,CAAC,CAAC;AAClD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAwB,IAAI;AAC5D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAEhD,QAAM,UAAUC,aAAY,OAAO,SAA8B;AAC/D,gBAAY,IAAI;AAChB,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,KAAK;AAAA,IACb,SAAS,GAAG;AACV,kBAAY,sBAAsB,CAAC,CAAC;AAAA,IACtC,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,aAAaA;AAAA,IACjB,CAAC,MAA+B;AAC9B,UAAI,EAAE,SAAS,aAAa;AAC1B,eAAO,EAAE,MAAM,YAAY,CAAC;AAC5B;AAAA,MACF;AACA,kBAAY,IAAI;AAChB,UAAI,EAAE,SAAS,YAAY;AACzB,iBAAS;AAAA,UACP,yBAAyB,EAAE;AAAA,UAC3B,2BAA2B,EAAE;AAAA,UAC7B,mCAAmC;AAAA,QACrC,CAAC;AACD,gBAAQ,UAAU;AAClB;AAAA,MACF;AACA,eAAS,CAAC,CAAC;AACX,cAAQ,UAAU;AAAA,IACpB;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,gBAAgBA;AAAA,IACpB,CAAC,MAAyB;AACxB,UAAI,EAAE,SAAS,aAAa;AAC1B,eAAO,EAAE,MAAM,YAAY,CAAC;AAC5B;AAAA,MACF;AACA,WAAK,QAAQ,YAAY;AACvB,cAAM,0BAA0B,MAAM;AAAA,UACpC;AAAA,UACA,EAAE;AAAA,QACJ;AACA,iBAAS;AAAA,UACP;AAAA,UACA,2BAA2B,EAAE;AAAA,UAC7B,mCAAmC;AAAA,QACrC,CAAC;AACD,gBAAQ,UAAU;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,CAAC,QAAQ,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,gBAAgBA;AAAA,IACpB,CAAC,MAAyB;AACxB,UAAI,EAAE,SAAS,aAAa;AAC1B,eAAO,EAAE,MAAM,YAAY,CAAC;AAC5B;AAAA,MACF;AACA,YAAM,QAAQ,MAAM;AACpB,YAAM,UAAU,MAAM;AACtB,UAAI,CAAC,SAAS,CAAC,SAAS;AACtB;AAAA,MACF;AACA,YAAM,oCAAoC;AAAA,QACxC,MAAM;AAAA,MACR;AACA,WAAK,QAAQ,YAAY;AACvB,cAAM,cAAc,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,UACA,EAAE,MAAM,EAAE,MAAM;AAAA,QAClB;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,yBAAyB;AAAA,YACzB,2BAA2B;AAAA,YAC3B;AAAA,YACA,eAAe,EAAE;AAAA,YACjB;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,IACA,CAAC,QAAQ,OAAO,QAAQ,OAAO;AAAA,EACjC;AAEA,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aACE,gBAAAL;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,QAAQ;AAAA;AAAA,MACV;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,aAAY;AAAA,UAEZ,0BAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,OAAM;AAAA,cACN,aAAY;AAAA,cACZ,QAAQ;AAAA;AAAA,YAHJ;AAAA,UAIN;AAAA;AAAA,MACF;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,aAAY;AAAA,UAEZ,0BAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,OAAM;AAAA,cACN,aAAY;AAAA,cACZ,QAAQ;AAAA;AAAA,YAHJ;AAAA,UAIN;AAAA;AAAA,MACF;AAAA,EAEN;AACF;;;AJ5MA,IAAqB,UAArB,MAAqB,iBAAgB,YAAY;AAAA,EAC/C,OAAuB,cACrB;AAAA,EAEF,MAAa,MAAqB;AAChC,UAAM,KAAK,MAAM,QAAO;AAExB,UAAM,KAAK,oBAAoB;AAE/B,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI,MAAM,qBAAqB,GAAG,GAAG;AACnC,WAAK;AAAA,QACH,kCAAkC,mBAAmB,GAAG,CAAC;AAAA,QACzD,EAAE,MAAM,EAAE;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,kBAAkB;AACtC,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM,2BAA2B,MAAM;AAAA,IACzD,SAAS,GAAG;AACV,WAAK,MAAM,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IAClD;AAEA,UAAM,eAAe,MAAM,KAAK,WAAW,mBAAmB;AAAA,MAC5D;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,aAAa,SAAS,aAAa;AACrC,WAAK,KAAK,GAAG;AAAA,IACf;AAEA,UAAM,EAAE,KAAK,IAAI;AAEjB,UAAM,OAAO,MAAM,oBAAoB,KAAK;AAAA,MAC1C,yBAAyB,KAAK;AAAA,MAC9B,aAAa,KAAK;AAAA,IACpB,CAAC;AAED,QAAI,yBAAyB;AAC7B,QAAI;AACF,YAAM,EAAE,SAAS,qBAAqB,oBAAoB,IACxD,MAAM,kBAAkB,KAAK,KAAK,aAAa;AACjD,+BAAyB,CAAC;AAC1B,UAAI,qBAAqB;AACvB,YAAI,qBAAqB;AACvB,eAAK;AAAA,YACH,+BAA+B,WAAW,gBAAgB;AAAA,UAC5D;AAAA,QACF,OAAO;AACL,eAAK;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,QAAQ,SAAS,GAAG;AAC7B,aAAK;AAAA,UACH,4CAA4C,QAAQ,KAAK,IAAI,CAAC;AAAA,QAChE;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,WAAK,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IACpE;AAEA,QAAI;AACF,YAAM;AAAA,QACJ;AAAA,QACA,KAAK;AAAA,QACLM,MAAK,KAAK,WAAW,gBAAgB;AAAA,MACvC;AAAA,IACF,SAAS,GAAG;AACV,WAAK,MAAM,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IAClD;AAEA,QAAI,KAAK,mCAAmC;AAC1C,WAAK,IAAI,0BAA0B,KAAK,yBAAyB,IAAI;AAAA,IACvE,OAAO;AACL,WAAK,IAAI,4BAA4B,KAAK,yBAAyB,IAAI;AAAA,IACzE;AACA,SAAK,IAAI,iBAAiB,KAAK,aAAa,IAAI;AAChD,SAAK,MAAM,4BAA4B,IAAI,EAAE;AAE7C,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,uBAAuB,KAAK,aAAa,aAAa;AAC/D,SAAK,IAAI,aAAa;AACtB,QAAI,OAAO;AACX,QAAI,wBAAwB;AAC1B,WAAK,IAAI,KAAK,MAAM,eAAe;AACnC,WAAK,IAAI,KAAK,MAAM,eAAe;AACnC,WAAK;AAAA,QACH,gCAA2B,OAAO,WAAW,mBAAmB,CAAC;AAAA,MACnE;AAAA,IACF;AACA,SAAK;AAAA,MACH,KAAK,MAAM,UAAU,WAAW,gBAAgB;AAAA,IAClD;AACA,SAAK,IAAI,KAAK,MAAM,iDAAiD;AAAA,EACvE;AACF;","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 a new folder';\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 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: '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: '^5.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 { defineConfig } from 'vite';\n\nexport default defineConfig({\n server: {\n port: ${CLI_CONFIG.scaffoldViteDevPort},\n },\n publicDir: 'public',\n build: {\n outDir: 'dist',\n },\n});\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-S4KAOR7F.js";
|
|
4
4
|
import {
|
|
5
5
|
formatExtensionReadyForReviewHttpError,
|
|
6
6
|
readInternalConfig
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-7LTVG6SC.js";
|
|
8
8
|
import {
|
|
9
9
|
layoutStyles,
|
|
10
10
|
spacing,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "../../chunk-3BPIJLS7.js";
|
|
13
13
|
import {
|
|
14
14
|
BaseCommand
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-OY6OB5HM.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/app/release.ts
|
|
18
18
|
import { Flags } from "@oclif/core";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createExtensionDraftVersion
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-S4KAOR7F.js";
|
|
4
4
|
import {
|
|
5
5
|
formatHttpClientError,
|
|
6
6
|
readInternalConfig
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-7LTVG6SC.js";
|
|
8
8
|
import {
|
|
9
9
|
BaseCommand,
|
|
10
10
|
CLI_CONFIG
|
|
11
|
-
} from "../../chunk-
|
|
11
|
+
} from "../../chunk-OY6OB5HM.js";
|
|
12
12
|
|
|
13
13
|
// src/commands/app/update.ts
|
|
14
14
|
import { join } from "node:path";
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
formatExtensionArtifactUploadError,
|
|
3
3
|
isSystemError,
|
|
4
4
|
readInternalConfig
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-7LTVG6SC.js";
|
|
6
6
|
import {
|
|
7
7
|
useTerminalWidth
|
|
8
8
|
} from "../../chunk-EKU4DKQK.js";
|
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
} from "../../chunk-3BPIJLS7.js";
|
|
14
14
|
import {
|
|
15
15
|
BaseCommand,
|
|
16
|
-
chunkArray
|
|
17
|
-
|
|
16
|
+
chunkArray,
|
|
17
|
+
contentTypeForPath,
|
|
18
|
+
listAllFilesUnderDir
|
|
19
|
+
} from "../../chunk-OY6OB5HM.js";
|
|
18
20
|
|
|
19
21
|
// src/commands/app/upload.ts
|
|
20
22
|
import { stat } from "node:fs/promises";
|
|
@@ -70,23 +72,6 @@ async function putPresignedUpload(url, body, contentType) {
|
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
// src/core/files.ts
|
|
74
|
-
import { lookup } from "mime-types";
|
|
75
|
-
import { glob } from "tinyglobby";
|
|
76
|
-
async function listAllFilesUnderDir(rootAbs) {
|
|
77
|
-
return glob("**/*", {
|
|
78
|
-
cwd: rootAbs,
|
|
79
|
-
absolute: true,
|
|
80
|
-
onlyFiles: true,
|
|
81
|
-
dot: true,
|
|
82
|
-
followSymbolicLinks: false
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
function contentTypeForPath(filePath) {
|
|
86
|
-
const mime = lookup(filePath);
|
|
87
|
-
return mime === false ? "application/octet-stream" : mime;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
75
|
// src/core/extension-upload.core.ts
|
|
91
76
|
var MAX_RELATIVE_PATH_LEN = 512;
|
|
92
77
|
var RELATIVE_PATH_SEGMENT = /^[a-zA-Z0-9._-]+$/;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/app/upload.ts","../../../src/core/extension-upload.core.ts","../../../src/services/extension-artifacts.service.ts","../../../src/core/files.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 { lookup } from 'mime-types';\nimport { glob } from 'tinyglobby';\n\n/**\n * All files under `rootAbs` (recursive), absolute paths.\n * Does not traverse symlinked directories.\n */\nexport async function listAllFilesUnderDir(rootAbs: string): Promise<string[]> {\n return glob('**/*', {\n cwd: rootAbs,\n absolute: true,\n onlyFiles: true,\n dot: true,\n followSymbolicLinks: false,\n });\n}\n\n/**\n * Extension-based MIME for a path or basename. Unknown fallback to `application/octet-stream` (S3-safe).\n */\nexport function contentTypeForPath(filePath: string): string {\n const mime = lookup(filePath);\n return mime === false ? 'application/octet-stream' : mime;\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":";;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,aAAa;;;ACFtB,SAAS,gBAAgB;AACzB,SAAS,UAAU,gBAAgB;;;ACAnC,OAAO,WAAW;AAClB,SAAS,SAAS;AAElB,IAAM,iCAAiC,EAAE,OAAO;AAAA,EAC9C,SAAS,EAAE,QAAQ,IAAI;AAAA,EACvB,SAAS,EAAE;AAAA,IACT,EAAE,OAAO;AAAA,MACP,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACrB,KAAK,EAAE,OAAO;AAAA,MACd,cAAc,EAAE,OAAO;AAAA,MACvB,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC/B,CAAC;AAAA,EACH;AACF,CAAC;AAcD,eAAsB,iCACpB,QACA,aACA,OACwC;AACxC,QAAM,OAAO,eAAe,WAAW;AACvC,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM,EAAE,MAAM,CAAC;AAClD,QAAM,SAAS,+BAA+B,UAAU,IAAI;AAC5D,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,OAAO;AAAA,EACf;AACA,QAAM,MAAM,IAAI;AAAA,IACd,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,CAAU;AAAA,EAC7D;AACA,QAAM,UAAyC,CAAC;AAChD,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,IAAI,IAAI,EAAE,YAAY;AAClC,QAAI,QAAQ,QAAW;AACrB,YAAM,IAAI,MAAM,mCAAmC,EAAE,YAAY,EAAE;AAAA,IACrE;AACA,YAAQ,KAAK,GAAG;AAAA,EAClB;AACA,SAAO;AACT;AAOA,IAAM,WAAW,MAAM,OAAO;AAAA,EAC5B,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,SAAS;AACX,CAAC;AAMD,eAAsB,mBACpB,KACA,MACA,aACe;AACf,QAAM,SAAS,IAAI,KAAK,MAAM;AAAA,IAC5B,SAAS,EAAE,gBAAgB,YAAY;AAAA,EACzC,CAAC;AACH;;;AC5EA,SAAS,cAAc;AACvB,SAAS,YAAY;AAMrB,eAAsB,qBAAqB,SAAoC;AAC7E,SAAO,KAAK,QAAQ;AAAA,IAClB,KAAK;AAAA,IACL,UAAU;AAAA,IACV,WAAW;AAAA,IACX,KAAK;AAAA,IACL,qBAAqB;AAAA,EACvB,CAAC;AACH;AAKO,SAAS,mBAAmB,UAA0B;AAC3D,QAAM,OAAO,OAAO,QAAQ;AAC5B,SAAO,SAAS,QAAQ,6BAA6B;AACvD;;;AFZA,IAAM,wBAAwB;AAC9B,IAAM,wBAAwB;AAC9B,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAwBtB,SAAS,kBAAkB,SAAyB;AACzD,SAAO,QACJ,QAAQ,OAAO,GAAG,EAClB,KAAK,EACL,QAAQ,eAAe,EAAE;AAC9B;AAGO,SAAS,mBAAmB,cAAqC;AACtE,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AACA,MAAI,aAAa,SAAS,IAAI,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,aAAa,SAAS,uBAAuB;AAC/C,WAAO,4BAA4B,qBAAqB;AAAA,EAC1D;AACA,aAAW,WAAW,aAAa,MAAM,GAAG,GAAG;AAC7C,QAAI,CAAC,WAAW,YAAY,OAAO,YAAY,MAAM;AACnD,aAAO,yBAAyB,OAAO;AAAA,IACzC;AACA,QAAI,CAAC,sBAAsB,KAAK,OAAO,GAAG;AACxC,aAAO,yBAAyB,OAAO;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAKA,eAAsB,6BACpB,UACqC;AACrC,QAAM,QAAQ,MAAM,qBAAqB,QAAQ;AAEjD,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,wBAAwB,QAAQ;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,2BAA2B,oBAAI,IAAsC;AAE3E,aAAW,gBAAgB,OAAO;AAChC,UAAM,eAAe,kBAAkB,SAAS,UAAU,YAAY,CAAC;AACvE,UAAM,kBAAkB,mBAAmB,YAAY;AACvD,QAAI,iBAAiB;AACnB,YAAM,IAAI,MAAM,GAAG,SAAS,YAAY,CAAC,KAAK,eAAe,EAAE;AAAA,IACjE;AACA,QAAI,yBAAyB,IAAI,YAAY,GAAG;AAC9C,YAAM,IAAI;AAAA,QACR,8CAA8C,YAAY;AAAA,MAC5D;AAAA,IACF;AACA,6BAAyB,IAAI,cAAc;AAAA,MACzC;AAAA,MACA;AAAA,MACA,aAAa,mBAAmB,YAAY;AAAA,IAC9C,CAAC;AAAA,EACH;AAEA,SAAO,CAAC,GAAG,yBAAyB,OAAO,CAAC,EAAE;AAAA,IAAK,CAAC,GAAG,MACrD,EAAE,aAAa,cAAc,EAAE,YAAY;AAAA,EAC7C;AACF;AAEA,eAAe,4BACb,KACA,MACA,aACe;AACf,MAAI;AACJ,WAAS,UAAU,GAAG,WAAW,qBAAqB,WAAW;AAC/D,QAAI;AACF,YAAM,mBAAmB,KAAK,MAAM,WAAW;AAC/C;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY;AACZ,UAAI,WAAW,qBAAqB;AAClC;AAAA,MACF;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,uBAAuB,OAAO,CAAC;AAAA,IACxE;AAAA,EACF;AACA,QAAM;AACR;AAQA,eAAsB,kBACpB,QACA,aACA,SACA,MAI+B;AAC/B,QAAM,EAAE,OAAO,WAAW,IAAI;AAC9B,MAAI,WAAW;AACf,MAAI,mBAAmB;AACvB,QAAM,wBAAkC,CAAC;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,QAAQ,QAAQ,CAAC;AACvB,QAAI,CAAC,OAAO,QAAQ;AAClB;AAAA,IACF;AACA,UAAM,QAAQ,MAAM,IAAI,CAAC,OAAO;AAAA,MAC9B,cAAc,EAAE;AAAA,MAChB,aAAa,EAAE;AAAA,IACjB,EAAE;AACF,QAAI;AACJ,QAAI;AACF,eAAS,MAAM;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,aAAO,EAAE,IAAI,OAAO,SAAS,mCAAmC,CAAC,EAAE;AAAA,IACrE;AAEA,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,IAAI,MAAM,CAAC;AACjB,YAAM,MAAM,OAAO,CAAC;AACpB,UAAI,CAAC,KAAK,CAAC,KAAK;AACd,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,SAAS,gDAAgD,CAAC,WAAW,IAAI,CAAC;AAAA,QAC5E;AAAA,MACF;AACA,UAAI,IAAI,iBAAiB,EAAE,cAAc;AACvC,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,YAAY,EAAE;AAAA,UACd,SAAS,oCAAoC,EAAE,YAAY,WAAW,IAAI,CAAC;AAAA,QAC7E;AAAA,MACF;AAEA,yBAAmB,EAAE;AAErB,iBAAW;AAAA,QACT,gBAAgB;AAAA,QAChB;AAAA,QACA,oBAAoB,EAAE;AAAA,QACtB,uBAAuB,CAAC,GAAG,qBAAqB;AAAA,MAClD,CAAC;AAED,UAAI;AACJ,UAAI;AACF,eAAO,MAAM,SAAS,EAAE,YAAY;AAAA,MACtC,SAAS,GAAG;AACV,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,YAAY,EAAE;AAAA,UACd,SACE,aAAa,QACT,kBAAkB,EAAE,YAAY,KAAK,EAAE,OAAO,KAC9C,OAAO,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,UAAI;AACF,cAAM,4BAA4B,IAAI,KAAK,MAAM,IAAI,WAAW;AAAA,MAClE,SAAS,GAAG;AACV,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,YAAY,EAAE;AAAA,UACd,SACE,aAAa,QACT,wBAAwB,EAAE,YAAY,KAAK,EAAE,OAAO,KACpD,wBAAwB,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC;AAAA,QAC5D;AAAA,MACF;AAEA;AACA,4BAAsB,KAAK,EAAE,YAAY;AACzC,iBAAW;AAAA,QACT,gBAAgB;AAAA,QAChB;AAAA,QACA,oBAAoB,EAAE;AAAA,QACtB,uBAAuB,CAAC,GAAG,qBAAqB;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,aAAW;AAAA,IACT,gBAAgB;AAAA,IAChB;AAAA,IACA,oBACE,SAAS,IAAI,mBAAmB,GAAG,QAAQ;AAAA,IAC7C,uBAAuB,CAAC,GAAG,qBAAqB;AAAA,EAClD,CAAC;AACD,SAAO,EAAE,IAAI,MAAM,SAAS;AAC9B;;;AG9OA,SAAS,KAAK,YAAY;AAC1B,SAAS,WAAW,QAAQ,gBAAgB;;;ACDrC,IAAM,+BAA+B;AAOrC,SAAS,yBACd,OACA,eAAe,8BACP;AACR,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,UAAU,cAAc;AAChC,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACA,QAAM,UAAU,MAAM,SAAS;AAC/B,SAAO,UAAK,OAAO;AAAA,EAA6B,MAAM,MAAM,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC;AACvF;;;ADwBI,SACE,KADF;AAjBJ,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,QAAQ,GAAG,IAAI,IAAI,KAAK;AAC9B,QAAM,WAAW,MAAM,SAAS;AAChC,QAAM,WAAW,KAAK,IAAI,GAAG,QAAQ,QAAQ;AAC7C,QAAM,QAAQ,KAAK,IAAI,UAAU,EAAE;AACnC,QAAM,SACJ,UAAU,IAAI,IAAI,KAAK,IAAI,OAAO,KAAK,MAAO,OAAO,QAAS,KAAK,CAAC;AACtE,QAAM,MAAM,GAAG,SAAI,OAAO,MAAM,CAAC,GAAG,SAAI,OAAO,QAAQ,MAAM,CAAC;AAC9D,SACE,qBAAC,QACC;AAAA,wBAAC,QAAM,GAAG,WAAW,OAAQ,eAAI;AAAA,IAAO;AAAA,IAAC,oBAAC,QAAK,MAAI,MAAE,iBAAM;AAAA,KAC7D;AAEJ;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAA+B;AAC7B,QAAM,YAAY,iBAAiB;AACnC,QAAM,cAAc,YAAY,IAAI,YAAY;AAChD,QAAM,mBAAmB,YAAY,IAAI,YAAY;AACrD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwC,IAAI;AAC5E,QAAM,aAAa,OAAO,KAAK;AAE/B,YAAU,MAAM;AACd,eAAW,UAAU;AACrB,QAAI,YAAY;AAChB,QAAI;AAEJ,SAAK,kBAAkB,QAAQ,aAAa,SAAS;AAAA,MACnD;AAAA,MACA,YAAY,CAAC,MAAM;AACjB,YAAI,CAAC,WAAW;AACd,sBAAY,CAAC;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAC,EAAE,KAAK,CAAC,WAAW;AAClB,UAAI,WAAW;AACb;AAAA,MACF;AACA,UAAI,CAAC,OAAO,IAAI;AACd,YAAI,aAAa,WAAW,SAAS;AACnC;AAAA,QACF;AACA,mBAAW,UAAU;AACrB,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,OAAO;AAAA,UAChB,YAAY,OAAO;AAAA,QACrB,CAAC;AACD;AAAA,MACF;AACA;AAAA,QAAY,CAAC,SACX,OAAO,EAAE,GAAG,MAAM,gBAAgB,OAAO,UAAU,MAAM,IAAI;AAAA,MAC/D;AACA,oBAAc,WAAW,MAAM;AAC7B,YAAI,aAAa,WAAW,SAAS;AACnC;AAAA,QACF;AACA,mBAAW,UAAU;AACrB,eAAO,EAAE,MAAM,WAAW,UAAU,OAAO,SAAS,CAAC;AAAA,MACvD,GAAG,CAAC;AAAA,IACN,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,gBAAgB,QAAW;AAC7B,qBAAa,WAAW;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,aAAa,QAAQ,KAAK,CAAC;AAEhD,QAAM,OAAO,UAAU,kBAAkB;AACzC,QAAM,SAAS,UAAU,sBAAsB;AAC/C,QAAM,gBAAgB,UAAU,yBAAyB,CAAC;AAC1D,QAAM,sBAAsB,WAAW,cAAc,SAAS;AAC9D,QAAM,cAAc,yBAAyB,aAAa;AAE1D,SACE,qBAAC,OAAI,OAAO,aAAa,UAAU,GAAI,GAAG,aAAa,YACrD;AAAA,wBAAC,OAAI,cAAc,QAAQ,IACzB,8BAAC,QAAM,GAAG,WAAW,OAAO,wCAA0B,GACxD;AAAA,IAEA,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,eAAY,MAAY,OAAc,OAAO,kBAAkB;AAAA,MAChE,oBAAC,OAAI,WAAW,QAAQ,IACtB,8BAAC,QAAK,MAAI,MAAC,OAAM,SACd,kBACH,GACF;AAAA,MACC,sBACC,oBAAC,OAAI,WAAW,QAAQ,IACtB,8BAAC,QAAM,GAAG,WAAW,OAAO,MAAK,QAC9B,uBACH,GACF,IACE;AAAA,MACH,CAAC,WACA,oBAAC,OAAI,WAAW,QAAQ,IACtB,8BAAC,QAAM,GAAG,WAAW,OAAO,6BAAU,GACxC,IACE;AAAA,OACN;AAAA,KACF;AAEJ;;;AJrIA,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EACjD,OAAuB,cACrB;AAAA,EAEF,OAAuB,QAAQ;AAAA,IAC7B,MAAM,MAAM,OAAO;AAAA,MACjB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,SAAS,MAAM,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aACE;AAAA,IACJ,CAAC;AAAA,EACH;AAAA,EAEA,MAAa,MAAqB;AAChC,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,UAAS;AAE5C,UAAM,KAAK,oBAAoB;AAE/B,UAAM,MAAM,QAAQ,IAAI;AAExB,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,UAAM,UAAU,QAAQ,KAAK,MAAM,IAAI;AACvC,QAAI;AACF,YAAM,KAAK,MAAM,KAAK,OAAO;AAC7B,UAAI,CAAC,GAAG,YAAY,GAAG;AACrB,aAAK,MAAM,oBAAoB,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAAA,MACvD;AAAA,IACF,SAAS,GAAG;AACV,UAAI,cAAc,GAAG,QAAQ,GAAG;AAC9B,aAAK;AAAA,UACH,6BAA6B,OAAO;AAAA,UACpC,EAAE,MAAM,EAAE;AAAA,QACZ;AAAA,MACF;AACA,UAAI,cAAc,GAAG,QAAQ,KAAK,cAAc,GAAG,OAAO,GAAG;AAC3D,aAAK,MAAM,iCAAiC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAAA,MACpE;AACA,UAAI,cAAc,GAAG,SAAS,GAAG;AAC/B,aAAK,MAAM,wCAAwC,OAAO,IAAI;AAAA,UAC5D,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AACA,WAAK,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IACpE;AAEA,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,6BAA6B,OAAO;AAAA,IAC1D,SAAS,GAAG;AACV,WAAK,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;AAAA,IACpE;AAEA,UAAM,SAAS,MAAM,KAAK,WAAW,uBAAuB;AAAA,MAC1D,QAAQ,KAAK,kBAAkB;AAAA,MAC/B;AAAA,MACA,SAAS,WAAW,aAAa,EAAE;AAAA,MACnC,OAAO,YAAY;AAAA,MACnB,SAAS,MAAM;AAAA,IACjB,CAAC;AAED,QAAI,OAAO,SAAS,SAAS;AAC3B,YAAM,MAAM,OAAO,aACf,GAAG,OAAO,UAAU;AAAA,EAAK,OAAO,OAAO,KACvC,OAAO;AACX,WAAK,MAAM,KAAK,EAAE,MAAM,EAAE,CAAC;AAAA,IAC7B;AAEA,SAAK,IAAI,YAAY,OAAO,QAAQ,mCAAmC;AAAA,EACzE;AACF;","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":[]}
|