create-tauri-ui 1.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +38 -4
  2. package/dist/index.mjs +89 -78
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -33,9 +33,12 @@ bunx tauri icon app-icon.png
33
33
  ## CLI reference
34
34
 
35
35
  ```
36
- Usage: create-tauri-ui [target-dir] [options]
36
+ Usage:
37
+ create-tauri-ui [target-dir] [options] scaffold a new project
38
+ create-tauri-ui <add|update|remove> <battery> manage batteries in an existing project
39
+ create-tauri-ui list list batteries + install status
37
40
 
38
- Options:
41
+ Scaffold options:
39
42
  -t, --template <name> vite | next | start | react-router | astro
40
43
  --identifier <value> Tauri app identifier (e.g. com.example.myapp)
41
44
  --preset <value> shadcn preset (default: b0)
@@ -47,12 +50,43 @@ Options:
47
50
  --no-invoke-example skip the Rust invoke example
48
51
  --workflow include the GitHub release workflow
49
52
  --no-workflow skip the GitHub release workflow
50
- -f, --force overwrite an existing target directory
51
- -y, --yes accept all defaults
53
+
54
+ Manage options:
55
+ --dir <path> project directory (default: current working dir)
56
+ --target-os <list> comma-separated platforms for workflow
57
+ (windows-latest,macos-latest,ubuntu-latest)
58
+ -f, --force overwrite an existing target directory / battery
59
+ -y, --yes accept defaults / skip confirmations
52
60
  -v, --version display version
53
61
  -h, --help display help
62
+
63
+ Batteries: debug-panel, workflow
54
64
  ```
55
65
 
66
+ ## Managing batteries in an existing project
67
+
68
+ Run inside a scaffolded project to install, update, or remove a battery after the fact.
69
+
70
+ ```bash
71
+ # see which batteries are installed
72
+ bunx create-tauri-ui@latest list
73
+
74
+ # upgrade the debug panel to the latest template
75
+ bunx create-tauri-ui@latest update debug-panel
76
+
77
+ # add the release workflow later
78
+ bunx create-tauri-ui@latest add workflow --target-os macos-latest,ubuntu-latest
79
+
80
+ # remove it
81
+ bunx create-tauri-ui@latest remove workflow
82
+ ```
83
+
84
+ `update` re-applies the battery using the latest CLI templates. Patches are idempotent — existing mounts, imports, and plugin registrations are preserved. Commit first, then run `update` and inspect the diff.
85
+
86
+ `remove` deletes the battery's owned files and best-effort reverts any wiring. For batteries with external dependencies (like the debug panel's `tauri-plugin-log` + `@tauri-apps/plugin-log`), the CLI prints a manual cleanup checklist.
87
+
88
+ The template is auto-detected from `package.json` and project structure — no manifest file is written to your repo.
89
+
56
90
  ## Examples
57
91
 
58
92
  **Vite app with all defaults:**
package/dist/index.mjs CHANGED
@@ -1,33 +1,33 @@
1
- import s from"node:fs";import a from"node:path";import P from"node:process";import{text as D,confirm as w,select as be,multiselect as ye,isCancel as ke,cancel as W,log as v,intro as $e,spinner as Ee,outro as je,note as K}from"@clack/prompts";import A from"picocolors";import Y from"node:os";import{execFile as Se}from"node:child_process";import{fileURLToPath as R}from"node:url";const L=new Set;let J=!1,X=!1;class C extends Error{constructor(t,r,n,i){super(t),this.stdout=r,this.stderr=n,this.code=i}}class x extends Error{constructor(t,r,n){super(r),this.tool=t,this.stderr=n}}class u extends Error{constructor(t,r){super(r),this.file=t}}function _e(e){return e?.trim().replace(/\/+$/g,"")}function q(e,t){s.statSync(e).isDirectory()?Q(e,t):(s.mkdirSync(a.dirname(t),{recursive:!0}),s.copyFileSync(e,t))}function O(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function Z(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}function Q(e,t){s.mkdirSync(t,{recursive:!0});for(const r of s.readdirSync(e)){const n=a.resolve(e,r),i=a.resolve(t,r);q(n,i)}}function Pe(e){const t=s.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"}function c(e,t){const r=s.readFileSync(e,"utf-8").replace(/\r\n/g,`
2
- `);s.writeFileSync(e,t(r),"utf-8")}function f(e,t){const r=JSON.parse(s.readFileSync(e,"utf-8")),n=t(r);s.writeFileSync(e,JSON.stringify(n,null,2)+`
3
- `)}async function T(e,t,r){return await new Promise((n,i)=>{Se(e,t,{cwd:r?.cwd,env:{...process.env,...r?.env},maxBuffer:1024*1024*10},(o,l,I)=>{if(o){i(new C(`Command failed: ${e} ${t.join(" ")}`,l,I,typeof o.code=="number"?o.code:null));return}n(l.trim())})})}function ee(e){return s.mkdtempSync(a.join(Y.tmpdir(),e))}function z(e){L.add(e)}function g(e){L.delete(e)}function h(e){s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0})}function De(){const e=[...L].sort((t,r)=>r.length-t.length);for(const t of e)try{h(t)}catch{}finally{L.delete(t)}}function Le(){if(J)return;J=!0;const e=(t,r)=>{X&&process.exit(r),X=!0,De(),process.exit(r)};process.once("SIGINT",()=>e("SIGINT",130)),process.once("SIGTERM",()=>e("SIGTERM",143))}function Ce(e){return e.replace(/^@[^/]+\//,"").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}const Te={name:"astro",async apply(e,t){c(a.join(e,"astro.config.mjs"),r=>{if(r.includes("server: {"))return r;const n=r.lastIndexOf(`
1
+ import s from"node:fs";import i from"node:path";import h from"node:process";import{intro as ae,outro as H,cancel as W,note as I,log as m,confirm as y,isCancel as ie,multiselect as oe,text as O,select as Ie,spinner as Oe}from"@clack/prompts";import f from"picocolors";import se from"node:os";import{execFile as Re}from"node:child_process";import{fileURLToPath as K}from"node:url";const R=new Set;let le=!1,ce=!1;class z extends Error{constructor(t,r,n,a){super(t),this.stdout=r,this.stderr=n,this.code=a}}class D extends Error{constructor(t,r,n){super(r),this.tool=t,this.stderr=n}}class u extends Error{constructor(t,r){super(r),this.file=t}}function ze(e){return e?.trim().replace(/\/+$/g,"")}function ue(e,t){s.statSync(e).isDirectory()?de(e,t):(s.mkdirSync(i.dirname(t),{recursive:!0}),s.copyFileSync(e,t))}function Y(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function pe(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}function de(e,t){s.mkdirSync(t,{recursive:!0});for(const r of s.readdirSync(e)){const n=i.resolve(e,r),a=i.resolve(t,r);ue(n,a)}}function Fe(e){const t=s.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"}function c(e,t){const r=s.readFileSync(e,"utf-8").replace(/\r\n/g,`
2
+ `);s.writeFileSync(e,t(r),"utf-8")}function v(e,t){const r=JSON.parse(s.readFileSync(e,"utf-8")),n=t(r);s.writeFileSync(e,JSON.stringify(n,null,2)+`
3
+ `)}async function F(e,t,r){return await new Promise((n,a)=>{Re(e,t,{cwd:r?.cwd,env:{...process.env,...r?.env},maxBuffer:1024*1024*10},(o,l,p)=>{if(o){a(new z(`Command failed: ${e} ${t.join(" ")}`,l,p,typeof o.code=="number"?o.code:null));return}n(l.trim())})})}function me(e){return s.mkdtempSync(i.join(se.tmpdir(),e))}function J(e){R.add(e)}function k(e){R.delete(e)}function $(e){s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0})}function Ue(){const e=[...R].sort((t,r)=>r.length-t.length);for(const t of e)try{$(t)}catch{}finally{R.delete(t)}}function Me(){if(le)return;le=!0;const e=(t,r)=>{ce&&process.exit(r),ce=!0,Ue(),process.exit(r)};process.once("SIGINT",()=>e("SIGINT",130)),process.once("SIGTERM",()=>e("SIGTERM",143))}function Ve(e){return e.replace(/^@[^/]+\//,"").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}const Be={name:"astro",async apply(e,t){c(i.join(e,"astro.config.mjs"),r=>{if(r.includes("server: {"))return r;const n=r.lastIndexOf(`
4
4
  })`);if(n===-1)throw new u("astro.config.mjs","Could not find the Astro config closing brace.");return`${r.slice(0,n)}
5
5
  server: {
6
6
  port: 1420,
7
- },${r.slice(n)}`})},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Ge={name:"next",async apply(e,t){c(a.join(e,"next.config.mjs"),r=>{if(r.includes('output: "export"'))return r;if(!r.includes("const nextConfig = {}"))throw new u("next.config.mjs","Could not find the default Next.js config shape.");return r.replace("const nextConfig = {}",`const nextConfig = {
7
+ },${r.slice(n)}`})},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},He={name:"next",async apply(e,t){c(i.join(e,"next.config.mjs"),r=>{if(r.includes('output: "export"'))return r;if(!r.includes("const nextConfig = {}"))throw new u("next.config.mjs","Could not find the default Next.js config shape.");return r.replace("const nextConfig = {}",`const nextConfig = {
8
8
  output: "export",
9
9
  images: {
10
10
  unoptimized: true,
11
11
  },
12
- }`)}),f(a.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("next dev --turbopack","next dev --turbopack -p 1420")),r))},tauriConfig(){return{frontendDist:"../out",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ne(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
12
+ }`)}),v(i.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("next dev --turbopack","next dev --turbopack -p 1420")),r))},tauriConfig(){return{frontendDist:"../out",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function We(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
13
13
  })`);if(t===-1)throw new u("vite.config.ts","Could not find the React Router Vite config closing brace.");return`${e.slice(0,t)}
14
14
  server: {
15
15
  port: 1420,
16
16
  strictPort: true,
17
- },${e.slice(t)}`}const Ie={name:"react-router",async apply(e,t){c(a.join(e,"react-router.config.ts"),r=>{if(r.includes("ssr: false"))return r;if(!r.includes("ssr: true"))throw new u("react-router.config.ts","Could not find the SSR flag in the generated React Router config.");return r.replace("ssr: true","ssr: false")}),c(a.join(e,"vite.config.ts"),Ne)},tauriConfig(){return{frontendDist:"../build/client",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ae(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
17
+ },${e.slice(t)}`}const Ke={name:"react-router",async apply(e,t){c(i.join(e,"react-router.config.ts"),r=>{if(r.includes("ssr: false"))return r;if(!r.includes("ssr: true"))throw new u("react-router.config.ts","Could not find the SSR flag in the generated React Router config.");return r.replace("ssr: true","ssr: false")}),c(i.join(e,"vite.config.ts"),We)},tauriConfig(){return{frontendDist:"../build/client",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ye(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
18
18
  })`);if(t===-1)throw new u("vite.config.ts","Could not find the TanStack Start config closing brace.");return`${e.slice(0,t)}
19
19
  server: {
20
20
  port: 1420,
21
21
  strictPort: true,
22
- },${e.slice(t)}`}const Re={name:"start",async apply(e,t){c(a.join(e,"vite.config.ts"),r=>{let n=Ae(r);if(!n.includes("tanstackStart({ spa: { enabled: true } })")){if(!n.includes("tanstackStart(),"))throw new u("vite.config.ts","Could not find tanstackStart() in the generated Vite config.");n=n.replace("tanstackStart(),","tanstackStart({ spa: { enabled: true } }),")}return n}),f(a.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("--port 3000","--port 1420")),r))},tauriConfig(){return{frontendDist:"../.output/public",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Oe(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
22
+ },${e.slice(t)}`}const Je={name:"start",async apply(e,t){c(i.join(e,"vite.config.ts"),r=>{let n=Ye(r);if(!n.includes("tanstackStart({ spa: { enabled: true } })")){if(!n.includes("tanstackStart(),"))throw new u("vite.config.ts","Could not find tanstackStart() in the generated Vite config.");n=n.replace("tanstackStart(),","tanstackStart({ spa: { enabled: true } }),")}return n}),v(i.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("--port 3000","--port 1420")),r))},tauriConfig(){return{frontendDist:"../.output/public",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Xe(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
23
23
  })`);if(t===-1)throw new u("vite.config.ts","Could not find the Vite config closing brace.");return`${e.slice(0,t)}
24
24
  server: {
25
25
  port: 1420,
26
26
  strictPort: true,
27
- },${e.slice(t)}`}const ze={name:"vite",async apply(e,t){c(a.join(e,"vite.config.ts"),Oe)},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Fe={vite:ze,next:Ge,start:Re,"react-router":Ie,astro:Te};function Ue(e){return Fe[e]}async function te(e,t){try{await T("bunx",["--bun","shadcn@latest",...t],{cwd:e})}catch(r){throw r instanceof C?new x("shadcn","shadcn CLI failed while updating the frontend scaffold.",r.stderr||r.stdout):r}}const Ve="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'%3E%3Crect width='96' height='96' rx='24' fill='%23181f2a'/%3E%3Ccircle cx='48' cy='34' r='18' fill='%23f8fafc'/%3E%3Cpath d='M18 82c6-14 18-22 30-22s24 8 30 22' fill='%23f8fafc'/%3E%3C/svg%3E";function Be(e){const t=a.join(e,"app/layout.tsx");s.existsSync(t)&&c(t,r=>{let n=r;if(n.includes('import { TooltipProvider } from "@/components/ui/tooltip"')||(n=n.replace(`import { ThemeProvider } from "@/components/theme-provider"
27
+ },${e.slice(t)}`}const qe={name:"vite",async apply(e,t){c(i.join(e,"vite.config.ts"),Xe)},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Ze={vite:qe,next:He,start:Je,"react-router":Ke,astro:Be};function Qe(e){return Ze[e]}async function fe(e,t){try{await F("bunx",["--bun","shadcn@latest",...t],{cwd:e})}catch(r){throw r instanceof z?new D("shadcn","shadcn CLI failed while updating the frontend scaffold.",r.stderr||r.stdout):r}}const et="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'%3E%3Crect width='96' height='96' rx='24' fill='%23181f2a'/%3E%3Ccircle cx='48' cy='34' r='18' fill='%23f8fafc'/%3E%3Cpath d='M18 82c6-14 18-22 30-22s24 8 30 22' fill='%23f8fafc'/%3E%3C/svg%3E";function tt(e){const t=i.join(e,"app/layout.tsx");s.existsSync(t)&&c(t,r=>{let n=r;if(n.includes('import { TooltipProvider } from "@/components/ui/tooltip"')||(n=n.replace(`import { ThemeProvider } from "@/components/theme-provider"
28
28
  `,`import { ThemeProvider } from "@/components/theme-provider"
29
29
  import { TooltipProvider } from "@/components/ui/tooltip"
30
- `)),n.includes("<TooltipProvider>"))return n;const i=n.replace(/<ThemeProvider>([\s\S]*?)<\/ThemeProvider>/,"<ThemeProvider><TooltipProvider>$1</TooltipProvider></ThemeProvider>");if(i===n)throw new u(t,"Could not wrap the Next.js layout with TooltipProvider.");return i})}function Me(e,t){const r=t.template==="next"?a.join(e,"components/app-sidebar.tsx"):t.template==="react-router"?a.join(e,"app/components/app-sidebar.tsx"):a.join(e,"src/components/app-sidebar.tsx");s.existsSync(r)&&c(r,n=>n.replace('avatar: "/avatars/shadcn.jpg"',`avatar: "${Ve}"`))}function b(e,t,r,n){return`import type { CSSProperties } from "react"
30
+ `)),n.includes("<TooltipProvider>"))return n;const a=n.replace(/<ThemeProvider>([\s\S]*?)<\/ThemeProvider>/,"<ThemeProvider><TooltipProvider>$1</TooltipProvider></ThemeProvider>");if(a===n)throw new u(t,"Could not wrap the Next.js layout with TooltipProvider.");return a})}function rt(e,t){const r=t.template==="next"?i.join(e,"components/app-sidebar.tsx"):t.template==="react-router"?i.join(e,"app/components/app-sidebar.tsx"):i.join(e,"src/components/app-sidebar.tsx");s.existsSync(r)&&c(r,n=>n.replace('avatar: "/avatars/shadcn.jpg"',`avatar: "${et}"`))}function P(e,t,r,n){return`import type { CSSProperties } from "react"
31
31
  import { AppSidebar } from "${t}components/app-sidebar"
32
32
  import { ChartAreaInteractive } from "${t}components/chart-area-interactive"
33
33
  import { DataTable } from "${t}components/data-table"
@@ -74,11 +74,11 @@ ${n?` <div className="px-4 lg:px-6">
74
74
  </TooltipProvider>
75
75
  )
76
76
  }
77
- `}function He(e){return`import { createFileRoute } from "@tanstack/react-router"
78
- ${b("DashboardPage","@/","@/app/dashboard/data.json",e)}export const Route = createFileRoute("/")({
77
+ `}function nt(e){return`import { createFileRoute } from "@tanstack/react-router"
78
+ ${P("DashboardPage","@/","@/app/dashboard/data.json",e)}export const Route = createFileRoute("/")({
79
79
  component: DashboardPage,
80
80
  })
81
- `}function We(e){return b("DashboardShell","@/","@/app/dashboard/data.json",e).replace("export default function DashboardShell()","export function DashboardShell()")}function Ke(e,t){try{s.renameSync(e,t);return}catch(r){if(!(r instanceof Error)||!("code"in r)||r.code!=="EXDEV")throw r}s.cpSync(e,t,{recursive:!0,force:!0}),s.rmSync(e,{recursive:!0,force:!0})}async function Ye(e){s.mkdirSync(a.dirname(e.targetDir),{recursive:!0});const t=ee("create-tauri-ui-frontend-"),r=a.join(t,e.projectName);z(t);try{if(await T("bunx",["--bun","shadcn@latest","init","--name",e.projectName,"--template",e.template,"--preset",e.preset,"--yes"],{cwd:t}),!s.existsSync(r))throw new Error("shadcn CLI did not produce the expected project directory.");s.rmSync(a.join(r,"node_modules"),{recursive:!0,force:!0}),Ke(r,e.targetDir)}catch(n){if(n instanceof C){g(t);try{h(t)}catch{}throw new x("shadcn","shadcn CLI failed while creating the frontend scaffold.",n.stderr||n.stdout)}g(t);try{h(t)}catch{}throw n}finally{g(t);try{h(t)}catch{}}return e.targetDir}async function Je(e){const t=ee("create-tauri-ui-"),r="tauri-native";z(t);try{await T("bunx",["create-tauri-app",r,"--template","vanilla-ts","--manager","bun","--identifier",e.identifier,"--yes"],{cwd:t})}catch(n){if(n instanceof C){g(t);try{h(t)}catch{}throw new x("cta","create-tauri-app failed while creating the native scaffold.",n.stderr||n.stdout)}g(t);try{h(t)}catch{}throw n}return{tempDir:t,projectDir:a.join(t,r)}}async function Xe(e,t){await te(e,["add","dashboard-01","--yes"]),Me(e,t);const r=t.template==="next"?a.join(e,"components/site-header.tsx"):t.template==="react-router"?a.join(e,"app/components/site-header.tsx"):a.join(e,"src/components/site-header.tsx");switch(s.existsSync(r)&&c(r,n=>n.includes("<Button")?n:n.replace(/import \{ Button \} from ["'][@~]\/components\/ui\/button["']\n/,"")),t.template){case"next":Be(e),s.writeFileSync(a.join(e,"app/page.tsx"),b("Page","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"vite":s.writeFileSync(a.join(e,"src/App.tsx"),b("App","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"start":s.writeFileSync(a.join(e,"src/routes/index.tsx"),He(t.includeInvokeExample));return;case"react-router":s.writeFileSync(a.join(e,"app/routes/home.tsx"),b("Home","~/","~/dashboard/data.json",t.includeInvokeExample));return;case"astro":s.writeFileSync(a.join(e,"src/components/dashboard-shell.tsx"),We(t.includeInvokeExample)),s.writeFileSync(a.join(e,"src/pages/index.astro"),`---
81
+ `}function at(e){return P("DashboardShell","@/","@/app/dashboard/data.json",e).replace("export default function DashboardShell()","export function DashboardShell()")}function it(e,t){try{s.renameSync(e,t);return}catch(r){if(!(r instanceof Error)||!("code"in r)||r.code!=="EXDEV")throw r}s.cpSync(e,t,{recursive:!0,force:!0}),s.rmSync(e,{recursive:!0,force:!0})}async function ot(e){s.mkdirSync(i.dirname(e.targetDir),{recursive:!0});const t=me("create-tauri-ui-frontend-"),r=i.join(t,e.projectName);J(t);try{if(await F("bunx",["--bun","shadcn@latest","init","--name",e.projectName,"--template",e.template,"--preset",e.preset,"--yes"],{cwd:t}),!s.existsSync(r))throw new Error("shadcn CLI did not produce the expected project directory.");s.rmSync(i.join(r,"node_modules"),{recursive:!0,force:!0}),it(r,e.targetDir)}catch(n){if(n instanceof z){k(t);try{$(t)}catch{}throw new D("shadcn","shadcn CLI failed while creating the frontend scaffold.",n.stderr||n.stdout)}k(t);try{$(t)}catch{}throw n}finally{k(t);try{$(t)}catch{}}return e.targetDir}async function st(e){const t=me("create-tauri-ui-"),r="tauri-native";J(t);try{await F("bunx",["create-tauri-app",r,"--template","vanilla-ts","--manager","bun","--identifier",e.identifier,"--yes"],{cwd:t})}catch(n){if(n instanceof z){k(t);try{$(t)}catch{}throw new D("cta","create-tauri-app failed while creating the native scaffold.",n.stderr||n.stdout)}k(t);try{$(t)}catch{}throw n}return{tempDir:t,projectDir:i.join(t,r)}}async function lt(e,t){await fe(e,["add","dashboard-01","--yes"]),rt(e,t);const r=t.template==="next"?i.join(e,"components/site-header.tsx"):t.template==="react-router"?i.join(e,"app/components/site-header.tsx"):i.join(e,"src/components/site-header.tsx");switch(s.existsSync(r)&&c(r,n=>n.includes("<Button")?n:n.replace(/import \{ Button \} from ["'][@~]\/components\/ui\/button["']\n/,"")),t.template){case"next":tt(e),s.writeFileSync(i.join(e,"app/page.tsx"),P("Page","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"vite":s.writeFileSync(i.join(e,"src/App.tsx"),P("App","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"start":s.writeFileSync(i.join(e,"src/routes/index.tsx"),nt(t.includeInvokeExample));return;case"react-router":s.writeFileSync(i.join(e,"app/routes/home.tsx"),P("Home","~/","~/dashboard/data.json",t.includeInvokeExample));return;case"astro":s.writeFileSync(i.join(e,"src/components/dashboard-shell.tsx"),at(t.includeInvokeExample)),s.writeFileSync(i.join(e,"src/pages/index.astro"),`---
82
82
  import Layout from "@/layouts/main.astro"
83
83
  import { DashboardShell } from "@/components/dashboard-shell"
84
84
  ---
@@ -86,10 +86,10 @@ import { DashboardShell } from "@/components/dashboard-shell"
86
86
  <Layout>
87
87
  <DashboardShell client:load />
88
88
  </Layout>
89
- `);return;default:throw new u(e,`No starter UI implementation exists for template "${t.template}".`)}}async function re(e,t){await te(e,["add",t,"--yes"])}const G="use tauri_plugin_log::{Target, TargetKind};",ne=` log::info!("greet command executed for {}", name);
90
- `,ie=` log::info!("opening external link in system browser: {}", url);
91
- `,ae=` log::info!("main webview finished loading");
92
- `,qe=` .plugin(
89
+ `);return;default:throw new u(e,`No starter UI implementation exists for template "${t.template}".`)}}async function ge(e,t){await fe(e,["add",t,"--yes"])}const U="use tauri_plugin_log::{Target, TargetKind};",he=` log::info!("greet command executed for {}", name);
90
+ `,we=` log::info!("opening external link in system browser: {}", url);
91
+ `,ve=` log::info!("main webview finished loading");
92
+ `,ct=` .plugin(
93
93
  tauri_plugin_log::Builder::new()
94
94
  .targets([
95
95
  Target::new(TargetKind::Stdout),
@@ -98,33 +98,33 @@ import { DashboardShell } from "@/components/dashboard-shell"
98
98
  ])
99
99
  .build(),
100
100
  )
101
- `;function Ze(){const e=a.dirname(R(import.meta.url)),t=[a.resolve(e,"../assets/debug-panel"),a.resolve(e,"../../assets/debug-panel")];return t.find(r=>s.existsSync(r))??t[0]}const Qe=Ze();function et(e){return e==="react-router"?"~/":"@/"}function oe(e,t){switch(t.template){case"next":return a.join(e,"components");case"vite":case"start":case"astro":return a.join(e,"src/components");case"react-router":return a.join(e,"app/components")}}function tt(e,t){switch(t.template){case"next":return a.join(e,"lib");case"vite":case"start":case"astro":return a.join(e,"src/lib");case"react-router":return a.join(e,"app/lib")}}function rt(e,t){return a.join(oe(e,t),"ui")}function y(e){switch(e.template){case"next":return"@/components/debug-panel";case"vite":return"./components/debug-panel.tsx";case"start":return"../components/debug-panel";case"react-router":return"./components/debug-panel";case"astro":return"@/components/debug-panel"}}async function nt(e,t){for(const r of["button","badge","dropdown-menu","tabs","tooltip"]){const n=a.join(rt(e,t),`${r}.tsx`);s.existsSync(n)||await re(e,r)}}function F(e){return s.readFileSync(a.join(Qe,e),"utf-8")}function it(e,t){const r=a.join(oe(e,t),"debug-panel.tsx"),n=tt(e,t);s.mkdirSync(a.dirname(r),{recursive:!0}),s.mkdirSync(n,{recursive:!0}),s.writeFileSync(r,F("debug-panel.tsx.tmpl").split("__ALIAS_PREFIX__").join(et(t.template)),"utf-8"),s.writeFileSync(a.join(n,"debug-events.ts"),F("debug-events.ts.tmpl"),"utf-8"),s.writeFileSync(a.join(n,"tauri.ts"),F("tauri.ts.tmpl"),"utf-8")}function at(e){f(a.join(e,"package.json"),t=>(t.dependencies=t.dependencies||{},t.dependencies["@tauri-apps/plugin-log"]||(t.dependencies["@tauri-apps/plugin-log"]="^2"),t))}function se(e,t){if(e.includes(t))return e;const r=/\[dependencies\]\r?\n/;if(!r.test(e))throw new Error(`Could not find [dependencies] while inserting ${t}.`);return e.replace(r,`[dependencies]
101
+ `;function ut(){const e=i.dirname(K(import.meta.url)),t=[i.resolve(e,"../assets/debug-panel"),i.resolve(e,"../../assets/debug-panel")];return t.find(r=>s.existsSync(r))??t[0]}const pt=ut();function dt(e){return e==="react-router"?"~/":"@/"}function xe(e,t){switch(t.template){case"next":return i.join(e,"components");case"vite":case"start":case"astro":return i.join(e,"src/components");case"react-router":return i.join(e,"app/components")}}function mt(e,t){switch(t.template){case"next":return i.join(e,"lib");case"vite":case"start":case"astro":return i.join(e,"src/lib");case"react-router":return i.join(e,"app/lib")}}function ft(e,t){return i.join(xe(e,t),"ui")}function _(e){switch(e.template){case"next":return"@/components/debug-panel";case"vite":return"./components/debug-panel.tsx";case"start":return"../components/debug-panel";case"react-router":return"./components/debug-panel";case"astro":return"@/components/debug-panel"}}async function gt(e,t){for(const r of["button","badge","dropdown-menu","tabs","tooltip"]){const n=i.join(ft(e,t),`${r}.tsx`);s.existsSync(n)||await ge(e,r)}}function X(e){return s.readFileSync(i.join(pt,e),"utf-8")}function ht(e,t){const r=i.join(xe(e,t),"debug-panel.tsx"),n=mt(e,t);s.mkdirSync(i.dirname(r),{recursive:!0}),s.mkdirSync(n,{recursive:!0}),s.writeFileSync(r,X("debug-panel.tsx.tmpl").split("__ALIAS_PREFIX__").join(dt(t.template)),"utf-8"),s.writeFileSync(i.join(n,"debug-events.ts"),X("debug-events.ts.tmpl"),"utf-8"),s.writeFileSync(i.join(n,"tauri.ts"),X("tauri.ts.tmpl"),"utf-8")}function wt(e){v(i.join(e,"package.json"),t=>(t.dependencies=t.dependencies||{},t.dependencies["@tauri-apps/plugin-log"]||(t.dependencies["@tauri-apps/plugin-log"]="^2"),t))}function be(e,t){if(e.includes(t))return e;const r=/\[dependencies\]\r?\n/;if(!r.test(e))throw new Error(`Could not find [dependencies] while inserting ${t}.`);return e.replace(r,`[dependencies]
102
102
  ${t}
103
- `)}function ot(e){const t=a.join(e,"src-tauri/Cargo.toml"),r=a.join(e,"src-tauri/src/lib.rs");c(t,n=>{let i=n;return i=se(i,'tauri-plugin-log = "2"'),i=se(i,'log = "0.4"'),i}),f(a.join(e,"src-tauri/capabilities/default.json"),n=>(n.permissions=Array.isArray(n.permissions)?n.permissions:[],n.permissions.includes("log:default")||n.permissions.push("log:default"),n)),c(r,n=>{let i=n;if(i.includes(G)||(i.includes(`use tauri_plugin_opener::OpenerExt;
104
- `)?i=i.replace(`use tauri_plugin_opener::OpenerExt;
103
+ `)}function vt(e){const t=i.join(e,"src-tauri/Cargo.toml"),r=i.join(e,"src-tauri/src/lib.rs");c(t,n=>{let a=n;return a=be(a,'tauri-plugin-log = "2"'),a=be(a,'log = "0.4"'),a}),v(i.join(e,"src-tauri/capabilities/default.json"),n=>(n.permissions=Array.isArray(n.permissions)?n.permissions:[],n.permissions.includes("log:default")||n.permissions.push("log:default"),n)),c(r,n=>{let a=n;if(a.includes(U)||(a.includes(`use tauri_plugin_opener::OpenerExt;
104
+ `)?a=a.replace(`use tauri_plugin_opener::OpenerExt;
105
105
  `,`use tauri_plugin_opener::OpenerExt;
106
- ${G}
107
- `):i.includes(`use tauri::webview::PageLoadEvent;
108
- `)?i=i.replace(`use tauri::webview::PageLoadEvent;
106
+ ${U}
107
+ `):a.includes(`use tauri::webview::PageLoadEvent;
108
+ `)?a=a.replace(`use tauri::webview::PageLoadEvent;
109
109
  `,`use tauri::webview::PageLoadEvent;
110
- ${G}
111
- `):i=`${G}
112
- ${i}`),i.includes("tauri_plugin_log::Builder::new()"))return i;const o=i.replace(` tauri::Builder::default()
110
+ ${U}
111
+ `):a=`${U}
112
+ ${a}`),a.includes("tauri_plugin_log::Builder::new()"))return a;const o=a.replace(` tauri::Builder::default()
113
113
  `,` tauri::Builder::default()
114
- ${qe}`);if(o===i)throw new u(r,"Could not register the Tauri log plugin.");return i=o,!i.includes(ne.trim())&&i.includes(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
115
- `)&&(i=i.replace(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
114
+ ${ct}`);if(o===a)throw new u(r,"Could not register the Tauri log plugin.");return a=o,!a.includes(he.trim())&&a.includes(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
115
+ `)&&(a=a.replace(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
116
116
  `,` let message = format!("Hello, {}! You've been greeted from Rust!", name);
117
- ${ne}`)),!i.includes(ie.trim())&&i.includes(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
118
- `)&&(i=i.replace(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
119
- `,`${ie} let _ = webview.opener().open_url(url.as_str(), None::<&str>);
120
- `)),!i.includes(ae.trim())&&i.includes(` let _ = webview.window().show();
121
- `)&&(i=i.replace(` let _ = webview.window().show();
122
- `,`${ae} let _ = webview.window().show();
123
- `)),i})}function st(e,t){const r=a.join(e,"src/main.tsx"),n=y(t);c(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(/import { ExternalLinkGuard } from "\.\/components\/external-link-guard\.tsx"\r?\n/,`import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
117
+ ${he}`)),!a.includes(we.trim())&&a.includes(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
118
+ `)&&(a=a.replace(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
119
+ `,`${we} let _ = webview.opener().open_url(url.as_str(), None::<&str>);
120
+ `)),!a.includes(ve.trim())&&a.includes(` let _ = webview.window().show();
121
+ `)&&(a=a.replace(` let _ = webview.window().show();
122
+ `,`${ve} let _ = webview.window().show();
123
+ `)),a})}function xt(e,t){const r=i.join(e,"src/main.tsx"),n=_(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(/import { ExternalLinkGuard } from "\.\/components\/external-link-guard\.tsx"\r?\n/,`import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
124
124
  import { DebugPanel } from "${n}"
125
125
  `)),o.includes("<DebugPanel />"))return o;const l=o.replace(/<ExternalLinkGuard \/>\r?\n(\s*)<main(?:\s+data-ui-scroll-container)?><App \/><\/main>/,`<ExternalLinkGuard />
126
126
  $1{import.meta.env.DEV ? <DebugPanel /> : null}
127
- $1<main data-ui-scroll-container><App /></main>`);if(l===o)throw new u(r,"Could not mount DebugPanel in the Vite entrypoint.");return l})}function lt(e,t){const r=a.join(e,"app/layout.tsx"),n=y(t);c(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o.includes(`import { ExternalLinkGuard } from "@/components/external-link-guard"
127
+ $1<main data-ui-scroll-container><App /></main>`);if(l===o)throw new u(r,"Could not mount DebugPanel in the Vite entrypoint.");return l})}function bt(e,t){const r=i.join(e,"app/layout.tsx"),n=_(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o.includes(`import { ExternalLinkGuard } from "@/components/external-link-guard"
128
128
  `)?o=o.replace(`import { ExternalLinkGuard } from "@/components/external-link-guard"
129
129
  `,`import { ExternalLinkGuard } from "@/components/external-link-guard"
130
130
  import { DebugPanel } from "${n}"
@@ -132,19 +132,19 @@ import { DebugPanel } from "${n}"
132
132
  `)&&(o=o.replace(`import { ThemeProvider } from "@/components/theme-provider"
133
133
  `,`import { ThemeProvider } from "@/components/theme-provider"
134
134
  import { DebugPanel } from "${n}"
135
- `))),o.includes("<DebugPanel />"))return o;const l=o.replace(/<ExternalLinkGuard \/>\{children\}/,'<ExternalLinkGuard />{process.env.NODE_ENV === "development" ? <DebugPanel /> : null}{children}');if(l===o)throw new u(r,"Could not mount DebugPanel in the Next.js layout.");return l})}function ct(e,t){const r=a.join(e,"src/routes/__root.tsx"),n=y(t);c(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "../components/external-link-guard"
135
+ `))),o.includes("<DebugPanel />"))return o;const l=o.replace(/<ExternalLinkGuard \/>\{children\}/,'<ExternalLinkGuard />{process.env.NODE_ENV === "development" ? <DebugPanel /> : null}{children}');if(l===o)throw new u(r,"Could not mount DebugPanel in the Next.js layout.");return l})}function yt(e,t){const r=i.join(e,"src/routes/__root.tsx"),n=_(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "../components/external-link-guard"
136
136
  `,`import { ExternalLinkGuard } from "../components/external-link-guard"
137
137
  import { DebugPanel } from "${n}"
138
- `)),o.includes("<DebugPanel />"))return o;const l=o.replace(/<main(?:\s+data-ui-scroll-container)?><ExternalLinkGuard \/>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{import.meta.env.DEV ? <DebugPanel /> : null}{children}</main>");if(l===o)throw new u(r,"Could not mount DebugPanel in the TanStack Start root route.");return l})}function ut(e,t){const r=a.join(e,"app/root.tsx"),n=y(t);c(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "./components/external-link-guard"
138
+ `)),o.includes("<DebugPanel />"))return o;const l=o.replace(/<main(?:\s+data-ui-scroll-container)?><ExternalLinkGuard \/>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{import.meta.env.DEV ? <DebugPanel /> : null}{children}</main>");if(l===o)throw new u(r,"Could not mount DebugPanel in the TanStack Start root route.");return l})}function kt(e,t){const r=i.join(e,"app/root.tsx"),n=_(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "./components/external-link-guard"
139
139
  `,`import { ExternalLinkGuard } from "./components/external-link-guard"
140
140
  import { DebugPanel } from "${n}"
141
141
  `)),o.includes("<DebugPanel />"))return o;const l=o.replace(`<ExternalLinkGuard />
142
142
  {children}`,`<ExternalLinkGuard />
143
143
  {import.meta.env.DEV ? <DebugPanel /> : null}
144
- {children}`);if(l===o)throw new u(r,"Could not mount DebugPanel in the React Router root layout.");return l})}function pt(e,t){const r=a.join(e,"src/layouts/main.astro"),n=y(t);c(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "@/components/external-link-guard"
144
+ {children}`);if(l===o)throw new u(r,"Could not mount DebugPanel in the React Router root layout.");return l})}function $t(e,t){const r=i.join(e,"src/layouts/main.astro"),n=_(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "@/components/external-link-guard"
145
145
  `,`import { ExternalLinkGuard } from "@/components/external-link-guard"
146
146
  import { DebugPanel } from "${n}"
147
- `)),o.includes("<DebugPanel client:load />"))return o;const l=o.replace(/<main(?:\s+data-ui-scroll-container)?><ExternalLinkGuard client:load \/><slot \/><\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard client:load />{import.meta.env.DEV ? <DebugPanel client:load /> : null}<slot /></main>");if(l===o)throw new u(r,"Could not mount DebugPanel in the Astro layout.");return l})}async function dt(e,t){switch(await nt(e,t),it(e,t),at(e),ot(e),t.template){case"vite":st(e,t);return;case"next":lt(e,t);return;case"start":ct(e,t);return;case"react-router":ut(e,t);return;case"astro":pt(e,t);return}}const U="use tauri_plugin_opener::OpenerExt;",mt=`fn external_navigation_plugin<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
147
+ `)),o.includes("<DebugPanel client:load />"))return o;const l=o.replace(/<main(?:\s+data-ui-scroll-container)?><ExternalLinkGuard client:load \/><slot \/><\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard client:load />{import.meta.env.DEV ? <DebugPanel client:load /> : null}<slot /></main>");if(l===o)throw new u(r,"Could not mount DebugPanel in the Astro layout.");return l})}async function ye(e,t){switch(await gt(e,t),ht(e,t),wt(e),vt(e),t.template){case"vite":xt(e,t);return;case"next":bt(e,t);return;case"start":yt(e,t);return;case"react-router":kt(e,t);return;case"astro":$t(e,t);return}}const q="use tauri_plugin_opener::OpenerExt;",jt=`fn external_navigation_plugin<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
148
148
  tauri::plugin::Builder::<R>::new("external-navigation")
149
149
  .on_navigation(|webview, url| {
150
150
  let is_internal_host = matches!(
@@ -170,7 +170,7 @@ import { DebugPanel } from "${n}"
170
170
  .build()
171
171
  }
172
172
 
173
- `,ft=`"use client"
173
+ `,Et=`"use client"
174
174
 
175
175
  import { useEffect } from "react"
176
176
 
@@ -271,49 +271,49 @@ export function ExternalLinkGuard() {
271
271
 
272
272
  return null
273
273
  }
274
- `;function k(e){s.mkdirSync(a.dirname(e),{recursive:!0}),s.writeFileSync(e,ft,"utf-8")}function gt(e){const t=a.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(U)||(n.includes(`use tauri::webview::PageLoadEvent;
274
+ `;function C(e){s.mkdirSync(i.dirname(e),{recursive:!0}),s.writeFileSync(e,Et,"utf-8")}function St(e){const t=i.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(q)||(n.includes(`use tauri::webview::PageLoadEvent;
275
275
  `)?n=n.replace(`use tauri::webview::PageLoadEvent;
276
276
  `,`use tauri::webview::PageLoadEvent;
277
- ${U}
278
- `):n=`${U}
279
- ${n}`),!n.includes("fn external_navigation_plugin<R: tauri::Runtime>()")){if(!n.includes("#[cfg_attr(mobile, tauri::mobile_entry_point)]"))throw new u(t,"Could not find the Tauri entry point while inserting the external navigation plugin.");n=n.replace("#[cfg_attr(mobile, tauri::mobile_entry_point)]",`${mt}#[cfg_attr(mobile, tauri::mobile_entry_point)]`)}if(!n.includes(".plugin(external_navigation_plugin())")){if(!n.includes(".plugin(tauri_plugin_opener::init())"))throw new u(t,"Could not find the opener plugin while inserting the external navigation guard.");n=n.replace(` .plugin(tauri_plugin_opener::init())
277
+ ${q}
278
+ `):n=`${q}
279
+ ${n}`),!n.includes("fn external_navigation_plugin<R: tauri::Runtime>()")){if(!n.includes("#[cfg_attr(mobile, tauri::mobile_entry_point)]"))throw new u(t,"Could not find the Tauri entry point while inserting the external navigation plugin.");n=n.replace("#[cfg_attr(mobile, tauri::mobile_entry_point)]",`${jt}#[cfg_attr(mobile, tauri::mobile_entry_point)]`)}if(!n.includes(".plugin(external_navigation_plugin())")){if(!n.includes(".plugin(tauri_plugin_opener::init())"))throw new u(t,"Could not find the opener plugin while inserting the external navigation guard.");n=n.replace(` .plugin(tauri_plugin_opener::init())
280
280
  `,` .plugin(tauri_plugin_opener::init())
281
281
  .plugin(external_navigation_plugin())
282
- `)}return n})}function ht(e){const t=a.join(e,"src/components/external-link-guard.tsx"),r=a.join(e,"src/main.tsx");k(t),c(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "./components/external-link-guard.tsx"')||(i=i.replace(/import { ThemeProvider } from "@\/components\/theme-provider\.tsx"\r?\n/,`import { ThemeProvider } from "@/components/theme-provider.tsx"
282
+ `)}return n})}function Dt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/main.tsx");C(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "./components/external-link-guard.tsx"')||(a=a.replace(/import { ThemeProvider } from "@\/components\/theme-provider\.tsx"\r?\n/,`import { ThemeProvider } from "@/components/theme-provider.tsx"
283
283
  import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
284
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(/<ThemeProvider>\r?\n(\s*)<main(?:\s+data-ui-scroll-container)?><App \/><\/main>/,`<ThemeProvider>
284
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(/<ThemeProvider>\r?\n(\s*)<main(?:\s+data-ui-scroll-container)?><App \/><\/main>/,`<ThemeProvider>
285
285
  $1<ExternalLinkGuard />
286
- $1<main data-ui-scroll-container><App /></main>`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Vite entrypoint.");return o})}function wt(e){const t=a.join(e,"components/external-link-guard.tsx"),r=a.join(e,"app/layout.tsx");k(t),c(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(i.includes(`import { TooltipProvider } from "@/components/ui/tooltip"
287
- `)?i=i.replace(`import { TooltipProvider } from "@/components/ui/tooltip"
286
+ $1<main data-ui-scroll-container><App /></main>`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Vite entrypoint.");return o})}function Pt(e){const t=i.join(e,"components/external-link-guard.tsx"),r=i.join(e,"app/layout.tsx");C(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(a.includes(`import { TooltipProvider } from "@/components/ui/tooltip"
287
+ `)?a=a.replace(`import { TooltipProvider } from "@/components/ui/tooltip"
288
288
  `,`import { TooltipProvider } from "@/components/ui/tooltip"
289
289
  import { ExternalLinkGuard } from "@/components/external-link-guard"
290
- `):i=i.replace(`import { ThemeProvider } from "@/components/theme-provider"
290
+ `):a=a.replace(`import { ThemeProvider } from "@/components/theme-provider"
291
291
  `,`import { ThemeProvider } from "@/components/theme-provider"
292
292
  import { ExternalLinkGuard } from "@/components/external-link-guard"
293
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(/<main(?:\s+data-ui-scroll-container)?>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{children}</main>");if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Next.js layout.");return o})}function vt(e){const t=a.join(e,"src/components/external-link-guard.tsx"),r=a.join(e,"src/routes/__root.tsx");k(t),c(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "../components/external-link-guard"')||(i=i.replace(`import appCss from "../styles.css?url"
293
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(/<main(?:\s+data-ui-scroll-container)?>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{children}</main>");if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Next.js layout.");return o})}function _t(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/routes/__root.tsx");C(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "../components/external-link-guard"')||(a=a.replace(`import appCss from "../styles.css?url"
294
294
  `,`import appCss from "../styles.css?url"
295
295
  import { ExternalLinkGuard } from "../components/external-link-guard"
296
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(/<main(?:\s+data-ui-scroll-container)?>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{children}</main>");if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the TanStack Start root route.");return o})}function xt(e){const t=a.join(e,"app/components/external-link-guard.tsx"),r=a.join(e,"app/root.tsx");k(t),c(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "./components/external-link-guard"')||(i=i.replace(`import "./app.css"
296
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(/<main(?:\s+data-ui-scroll-container)?>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{children}</main>");if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the TanStack Start root route.");return o})}function Ct(e){const t=i.join(e,"app/components/external-link-guard.tsx"),r=i.join(e,"app/root.tsx");C(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "./components/external-link-guard"')||(a=a.replace(`import "./app.css"
297
297
  `,`import "./app.css"
298
298
  import { ExternalLinkGuard } from "./components/external-link-guard"
299
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(`<body>
299
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(`<body>
300
300
  {children}`,`<body>
301
301
  <ExternalLinkGuard />
302
- {children}`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the React Router root layout.");return o})}function bt(e){const t=a.join(e,"src/components/external-link-guard.tsx"),r=a.join(e,"src/layouts/main.astro");k(t),c(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(i=i.replace(`import "@/styles/global.css"
302
+ {children}`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the React Router root layout.");return o})}function Lt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/layouts/main.astro");C(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(a=a.replace(`import "@/styles/global.css"
303
303
  `,`import "@/styles/global.css"
304
304
  import { ExternalLinkGuard } from "@/components/external-link-guard"
305
- `)),i.includes("<ExternalLinkGuard client:load />"))return i;const o=i.replace(/ <body>\n <main(?:\s+data-ui-scroll-container)?><slot \/><\/main>\n <\/body>/,` <body>
305
+ `)),a.includes("<ExternalLinkGuard client:load />"))return a;const o=a.replace(/ <body>\n <main(?:\s+data-ui-scroll-container)?><slot \/><\/main>\n <\/body>/,` <body>
306
306
  <main data-ui-scroll-container><ExternalLinkGuard client:load /><slot /></main>
307
- </body>`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Astro layout.");return o})}async function yt(e,t){switch(gt(e),t.template){case"vite":ht(e);return;case"next":wt(e);return;case"start":vt(e);return;case"react-router":xt(e);return;case"astro":bt(e);return}}const V="use tauri::webview::PageLoadEvent;",kt=` .on_page_load(|webview, payload| {
307
+ </body>`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Astro layout.");return o})}async function Tt(e,t){switch(St(e),t.template){case"vite":Dt(e);return;case"next":Pt(e);return;case"start":_t(e);return;case"react-router":Ct(e);return;case"astro":Lt(e);return}}const Z="use tauri::webview::PageLoadEvent;",Gt=` .on_page_load(|webview, payload| {
308
308
  if webview.label() == "main" && matches!(payload.event(), PageLoadEvent::Finished) {
309
309
  let _ = webview.window().show();
310
310
  }
311
311
  })
312
- `;async function $t(e){f(a.join(e,"src-tauri/tauri.conf.json"),r=>{r.app=r.app||{},r.app.windows=Array.isArray(r.app.windows)?r.app.windows:[{}];const n=r.app.windows[0]||{};return r.app.windows[0]={...n,visible:!1},r});const t=a.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(V)||(n.includes(`use tauri::Manager;
312
+ `;async function Nt(e){v(i.join(e,"src-tauri/tauri.conf.json"),r=>{r.app=r.app||{},r.app.windows=Array.isArray(r.app.windows)?r.app.windows:[{}];const n=r.app.windows[0]||{};return r.app.windows[0]={...n,visible:!1},r});const t=i.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(Z)||(n.includes(`use tauri::Manager;
313
313
  `)?n=n.replace(`use tauri::Manager;
314
- `,`${V}
315
- `):n=`${V}
316
- ${n}`),n.includes(".on_page_load("))return n;const i=n.replace(" .run(tauri::generate_context!())",`${kt} .run(tauri::generate_context!())`);if(i===n)throw new u(t,"Could not insert the startup flash-prevention page-load hook.");return i})}function Et(){const e=a.dirname(R(import.meta.url)),t=[a.resolve(e,"../assets"),a.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const jt=Et();async function St(e){q(a.join(jt,"app-icon.png"),a.join(e,"app-icon.png"))}function _t(e){return`"use client"
314
+ `,`${Z}
315
+ `):n=`${Z}
316
+ ${n}`),n.includes(".on_page_load("))return n;const a=n.replace(" .run(tauri::generate_context!())",`${Gt} .run(tauri::generate_context!())`);if(a===n)throw new u(t,"Could not insert the startup flash-prevention page-load hook.");return a})}function At(){const e=i.dirname(K(import.meta.url)),t=[i.resolve(e,"../assets"),i.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const It=At();async function Ot(e){ue(i.join(It,"app-icon.png"),i.join(e,"app-icon.png"))}function Rt(e){return`"use client"
317
317
 
318
318
  import { useState } from "react"
319
319
  import { Button } from "${e}components/ui/button"
@@ -356,7 +356,7 @@ export function Greet() {
356
356
  </div>
357
357
  )
358
358
  }
359
- `}function Pt(e,t){return`import { Greet } from "${t}components/greet"
359
+ `}function zt(e,t){return`import { Greet } from "${t}components/greet"
360
360
 
361
361
  export default function ${e}() {
362
362
  return (
@@ -373,7 +373,7 @@ export default function ${e}() {
373
373
  </div>
374
374
  )
375
375
  }
376
- `}function Dt(){return`import { createFileRoute } from "@tanstack/react-router"
376
+ `}function Ft(){return`import { createFileRoute } from "@tanstack/react-router"
377
377
  import { Greet } from "@/components/greet"
378
378
 
379
379
  export const Route = createFileRoute("/")({
@@ -395,7 +395,7 @@ function Home() {
395
395
  </div>
396
396
  )
397
397
  }
398
- `}function le(e,t){switch(e){case"next":return a.join(t,"app/page.tsx");case"vite":return a.join(t,"src/App.tsx");case"start":return a.join(t,"src/routes/index.tsx");case"react-router":return a.join(t,"app/routes/home.tsx");case"astro":return a.join(t,"src/pages/index.astro")}}function Lt(e,t){switch(e){case"next":return a.join(t,"components/greet.tsx");case"vite":case"start":case"astro":return a.join(t,"src/components/greet.tsx");case"react-router":return a.join(t,"app/components/greet.tsx")}}async function Ct(e,t){t.includeStarterUI||await re(e,"input");const r=t.template==="react-router"?"~/":"@/";if(s.writeFileSync(Lt(t.template,e),_t(r)),t.includeStarterUI)return;if(t.template==="astro"){s.writeFileSync(le(t.template,e),`---
398
+ `}function ke(e,t){switch(e){case"next":return i.join(t,"app/page.tsx");case"vite":return i.join(t,"src/App.tsx");case"start":return i.join(t,"src/routes/index.tsx");case"react-router":return i.join(t,"app/routes/home.tsx");case"astro":return i.join(t,"src/pages/index.astro")}}function Ut(e,t){switch(e){case"next":return i.join(t,"components/greet.tsx");case"vite":case"start":case"astro":return i.join(t,"src/components/greet.tsx");case"react-router":return i.join(t,"app/components/greet.tsx")}}async function Mt(e,t){t.includeStarterUI||await ge(e,"input");const r=t.template==="react-router"?"~/":"@/";if(s.writeFileSync(Ut(t.template,e),Rt(r)),t.includeStarterUI)return;if(t.template==="astro"){s.writeFileSync(ke(t.template,e),`---
399
399
  import Layout from "@/layouts/main.astro"
400
400
  import { Greet } from "@/components/greet"
401
401
  ---
@@ -413,7 +413,7 @@ import { Greet } from "@/components/greet"
413
413
  </div>
414
414
  </div>
415
415
  </Layout>
416
- `);return}const n=t.template==="start"?Dt():Pt(t.template==="vite"?"App":t.template==="react-router"?"Home":"Page",r);s.writeFileSync(le(t.template,e),n)}const m="data-ui-scroll-container",$=`
416
+ `);return}const n=t.template==="start"?Ft():zt(t.template==="vite"?"App":t.template==="react-router"?"Home":"Page",r);s.writeFileSync(ke(t.template,e),n)}const x="data-ui-scroll-container",L=`
417
417
  /* Disable page-level overscroll and rubber-band scrolling so the UI feels more desktop-native. */
418
418
  html,
419
419
  body {
@@ -425,20 +425,20 @@ body {
425
425
  }
426
426
 
427
427
  /* Scope the desktop scroll shell to the generated root container only. */
428
- [${m}] {
428
+ [${x}] {
429
429
  height: 100vh;
430
430
  height: 100dvh;
431
431
  overflow-x: hidden;
432
432
  overflow-y: auto;
433
433
  overscroll-behavior-y: none;
434
434
  }
435
- `,Tt=`
435
+ `,Vt=`
436
436
  /* Vite mounts into #root, so it needs to inherit the full-height desktop shell. */
437
437
  #root {
438
438
  height: 100%;
439
439
  }
440
- `;function E(e,t){c(e,r=>r.includes("Disable page-level overscroll and rubber-band scrolling")?r:`${r.trimEnd()}
441
- ${t}`)}function j(e,t,r){c(e,n=>{if(n.includes(`<main ${m}>`))return n;const i=n.replace(new RegExp(`<main(?![^>]*${m})([^>]*)>`),`<main ${m}$1>`);if(i!==n)return i;const o=n.replace(t,r);if(o===n)throw new u(e,"Could not insert the scroll container <main> wrapper.");return o})}async function Gt(e,t){switch(t.template){case"next":E(a.join(e,"app/globals.css"),$),j(a.join(e,"app/layout.tsx"),/\{children\}/,`<main ${m}>{children}</main>`);return;case"vite":E(a.join(e,"src/index.css"),`${$}${Tt}`),j(a.join(e,"src/main.tsx"),/<App \/>/,`<main ${m}><App /></main>`);return;case"start":E(a.join(e,"src/styles.css"),$),j(a.join(e,"src/routes/__root.tsx"),/\{children\}/,`<main ${m}>{children}</main>`);return;case"react-router":E(a.join(e,"app/app.css"),$),j(a.join(e,"app/root.tsx"),/return <Outlet \/>/,`return <main ${m}><Outlet /></main>`);return;case"astro":E(a.join(e,"src/styles/global.css"),$),j(a.join(e,"src/layouts/main.astro"),/<slot \/>/,`<main ${m}><slot /></main>`);return;default:throw new u(e,`No scroll container battery implementation exists for template "${t.template}".`)}}const S=`
440
+ `;function T(e,t){c(e,r=>r.includes("Disable page-level overscroll and rubber-band scrolling")?r:`${r.trimEnd()}
441
+ ${t}`)}function G(e,t,r){c(e,n=>{if(n.includes(`<main ${x}>`))return n;const a=n.replace(new RegExp(`<main(?![^>]*${x})([^>]*)>`),`<main ${x}$1>`);if(a!==n)return a;const o=n.replace(t,r);if(o===n)throw new u(e,"Could not insert the scroll container <main> wrapper.");return o})}async function Bt(e,t){switch(t.template){case"next":T(i.join(e,"app/globals.css"),L),G(i.join(e,"app/layout.tsx"),/\{children\}/,`<main ${x}>{children}</main>`);return;case"vite":T(i.join(e,"src/index.css"),`${L}${Vt}`),G(i.join(e,"src/main.tsx"),/<App \/>/,`<main ${x}><App /></main>`);return;case"start":T(i.join(e,"src/styles.css"),L),G(i.join(e,"src/routes/__root.tsx"),/\{children\}/,`<main ${x}>{children}</main>`);return;case"react-router":T(i.join(e,"app/app.css"),L),G(i.join(e,"app/root.tsx"),/return <Outlet \/>/,`return <main ${x}><Outlet /></main>`);return;case"astro":T(i.join(e,"src/styles/global.css"),L),G(i.join(e,"src/layouts/main.astro"),/<slot \/>/,`<main ${x}><slot /></main>`);return;default:throw new u(e,`No scroll container battery implementation exists for template "${t.template}".`)}}const N=`
442
442
  @layer base {
443
443
  /* Desktop UIs often feel cleaner with accidental text selection disabled by default. */
444
444
  body {
@@ -461,8 +461,8 @@ ${t}`)}function j(e,t,r){c(e,n=>{if(n.includes(`<main ${m}>`))return n;const i=n
461
461
  @apply select-text;
462
462
  }
463
463
  }
464
- `;function _(e,t){c(e,r=>r.includes(".ui-selectable")?r:`${r.trimEnd()}
465
- ${t}`)}async function Nt(e,t){switch(t.template){case"next":_(a.join(e,"app/globals.css"),S);return;case"vite":_(a.join(e,"src/index.css"),S);return;case"start":_(a.join(e,"src/styles.css"),S);return;case"react-router":_(a.join(e,"app/app.css"),S);return;case"astro":_(a.join(e,"src/styles/global.css"),S);return;default:throw new u(e,`No selection behavior battery implementation exists for template "${t.template}".`)}}const It=`
464
+ `;function A(e,t){c(e,r=>r.includes(".ui-selectable")?r:`${r.trimEnd()}
465
+ ${t}`)}async function Ht(e,t){switch(t.template){case"next":A(i.join(e,"app/globals.css"),N);return;case"vite":A(i.join(e,"src/index.css"),N);return;case"start":A(i.join(e,"src/styles.css"),N);return;case"react-router":A(i.join(e,"app/app.css"),N);return;case"astro":A(i.join(e,"src/styles/global.css"),N);return;default:throw new u(e,`No selection behavior battery implementation exists for template "${t.template}".`)}}const Wt=`
466
466
  [profile.dev]
467
467
  incremental = true # Compile your binary in smaller steps.
468
468
 
@@ -472,14 +472,19 @@ lto = true # Enables link-time-optimizations.
472
472
  opt-level = "s" # Prioritizes small binary size. Use \`3\` if you prefer speed.
473
473
  panic = "abort" # Higher performance by disabling panic handlers.
474
474
  strip = true # Ensures debug symbols are removed.
475
- `;function At(e){const t=a.join(e,"src-tauri/Cargo.toml");c(t,r=>r.includes("[profile.release]")?r:`${r.trimEnd()}
475
+ `;function Kt(e){const t=i.join(e,"src-tauri/Cargo.toml");c(t,r=>r.includes("[profile.release]")?r:`${r.trimEnd()}
476
476
 
477
- ${It}`)}function Rt(e){f(a.join(e,"src-tauri/tauri.conf.json"),t=>(t.build=t.build||{},t.build.removeUnusedCommands=!0,t))}async function Ot(e,t){At(e),Rt(e)}function zt(){const e=a.dirname(R(import.meta.url)),t=[a.resolve(e,"../assets"),a.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const Ft=zt();function Ut(e){const t=[];for(const r of e){if(r==="macos-latest"){t.push({name:"macOS Apple Silicon",platform:"macos-latest",args:"--target aarch64-apple-darwin"},{name:"macOS Intel",platform:"macos-latest",args:"--target x86_64-apple-darwin"});continue}if(r==="ubuntu-latest"){t.push({name:"Linux",platform:"ubuntu-22.04",args:""});continue}t.push({name:"Windows",platform:r,args:""})}return t.map(r=>` - name: "${r.name}"
477
+ ${Wt}`)}function Yt(e){v(i.join(e,"src-tauri/tauri.conf.json"),t=>(t.build=t.build||{},t.build.removeUnusedCommands=!0,t))}async function Jt(e,t){Kt(e),Yt(e)}function Xt(){const e=i.dirname(K(import.meta.url)),t=[i.resolve(e,"../assets"),i.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const qt=Xt();function Zt(e){const t=[];for(const r of e){if(r==="macos-latest"){t.push({name:"macOS Apple Silicon",platform:"macos-latest",args:"--target aarch64-apple-darwin"},{name:"macOS Intel",platform:"macos-latest",args:"--target x86_64-apple-darwin"});continue}if(r==="ubuntu-latest"){t.push({name:"Linux",platform:"ubuntu-22.04",args:""});continue}t.push({name:"Windows",platform:r,args:""})}return t.map(r=>` - name: "${r.name}"
478
478
  platform: "${r.platform}"
479
479
  args: "${r.args}"`).join(`
480
- `)}async function Vt(e,t){const r=s.readFileSync(a.join(Ft,"release.yml.tmpl"),"utf-8").replace("{{PLATFORMS}}",Ut(t.targetOS)),n=a.join(e,".github/workflows");s.mkdirSync(n,{recursive:!0}),s.writeFileSync(a.join(n,"release.yml"),r)}const Bt=1400,Mt=918;async function Ht(e,t,r){Q(a.join(t,"src-tauri"),a.join(e,"src-tauri")),f(a.join(e,"package.json"),o=>(o.name=r.packageName,o.dependencies=o.dependencies||{},o.dependencies["@tauri-apps/api"]="^2",o.dependencies["@tauri-apps/plugin-opener"]="^2",o.devDependencies=o.devDependencies||{},o.devDependencies["@tauri-apps/cli"]="^2",o.scripts=o.scripts||{},o.scripts.tauri="tauri",o));const n=Ce(r.packageName),i=`${n}_lib`;c(a.join(e,"src-tauri/Cargo.toml"),o=>o.replace(/^name = "tauri-app"$/m,`name = "${n}"`).replace(/^name = "tauri_app_lib"$/m,`name = "${i}"`)),c(a.join(e,"src-tauri/src/main.rs"),o=>o.replace("tauri_app_lib::run()",`${i}::run()`))}async function Wt(e,t,r){f(a.join(e,"src-tauri/tauri.conf.json"),n=>{n.productName=t.projectName,n.identifier=t.identifier,n.build={...n.build,...r},n.app=n.app||{},n.app.windows=Array.isArray(n.app.windows)?n.app.windows:[{}];const i=n.app.windows[0]||{};return n.app.windows[0]={...i,title:t.projectName,center:!0,width:Bt,height:Mt},n})}const B=["vite","next","start","react-router","astro"],M=["windows-latest","macos-latest","ubuntu-latest"],ce="tauri-ui",ue="b0",Kt={vite:"Vite",next:"Next.js",start:"TanStack Start","react-router":"React Router",astro:"Astro"},Yt={"windows-latest":"Windows","macos-latest":"macOS (Apple Silicon, Intel)","ubuntu-22.04":"Linux","ubuntu-latest":"Linux"};function p(e,t="Operation cancelled"){if(ke(e))throw new Error(t);return e}function Jt(e){if(B.includes(e))return e;throw new Error(`Unsupported template "${e}". Expected one of: ${B.join(", ")}`)}function pe(e){try{return`com.${Z(Y.userInfo().username)||"example"}.${e}`}catch{return`com.example.${e}`}}function N(e){return{placeholder:e,defaultValue:e}}function de(e){const t=e.trim().replace(/^['"]|['"]$/g,"");return(t.match(/^(?:--preset(?:=|\s+))?(.+)$/)?.[1]??t).trim()}async function Xt(e,t=process.cwd()){let r=_e(e.targetDir);if(r||(r=p(await D({message:"Project name",...N(ce)}))),r||(r=ce),r===".")throw new Error("Scaffolding into the current directory is not supported yet.");const n=a.resolve(t,r),i=a.basename(n),o=O(i)?i:Z(i);if(s.existsSync(n)&&!Pe(n))if(e.force)s.rmSync(n,{recursive:!0,force:!0});else{if(e.yes)throw new Error(`Target directory "${r}" is not empty. Re-run with --force to overwrite it.`);if(!p(await w({message:`Target directory "${r}" is not empty. Remove it and continue?`,initialValue:!1})))throw new Error("Operation cancelled");s.rmSync(n,{recursive:!0,force:!0})}let l=o;O(i)||(e.yes?l=o:l=p(await D({message:"Package name",...N(o),validate(d){if(!d||!O(d))return"Enter a valid package.json name"}})));const I=e.template?Jt(e.template):e.yes?"vite":p(await be({message:"Frontend template",initialValue:"vite",options:B.map(d=>({value:d,label:Kt[d]}))})),fe=e.identifier?e.identifier:e.yes?pe(l):p(await D({message:"App identifier",...N(pe(l))})),ge=e.preset?de(e.preset):e.yes?ue:de(p(await D({message:"shadcn preset",...N(ue)}))),he=e.includeStarterUI??(e.yes?!0:p(await w({message:"Include starter UI?",initialValue:!0}))),we=e.includeSizeOptimization??(e.yes?!1:p(await w({message:"Optimize app size?",initialValue:!0}))),ve=e.includeInvokeExample??(e.yes?!0:p(await w({message:"Include Rust invoke example?",initialValue:!0}))),H=e.includeWorkflow??(e.yes?!0:p(await w({message:"Include GitHub release workflow?",initialValue:!0}))),xe=H?e.yes?[...M]:p(await ye({message:"GitHub workflow target operating systems",initialValues:[...M],required:!0,options:M.map(d=>({value:d,label:Yt[d]??d}))})):[];return{projectName:i,packageName:l,template:I,identifier:fe,preset:ge,includeSizeOptimization:we,includeStarterUI:he,includeInvokeExample:ve,includeWorkflow:H,targetOS:xe,targetDir:n}}function qt(){const e=new URL("../package.json",import.meta.url);return JSON.parse(s.readFileSync(e,"utf-8")).version??"0.0.0"}function Zt(){console.log(`Usage: create-tauri-ui [target-dir] [options]
481
-
482
- Options:
480
+ `)}async function $e(e,t){const r=s.readFileSync(i.join(qt,"release.yml.tmpl"),"utf-8").replace("{{PLATFORMS}}",Zt(t.targetOS)),n=i.join(e,".github/workflows");s.mkdirSync(n,{recursive:!0}),s.writeFileSync(i.join(n,"release.yml"),r)}const Q=["vite","next","start","react-router","astro"],S=["windows-latest","macos-latest","ubuntu-latest"];function Qt(e){const t=i.join(e,"package.json");if(!s.existsSync(t))return null;try{return JSON.parse(s.readFileSync(t,"utf-8"))}catch{return null}}function j(e,t){return!!(e.dependencies?.[t]||e.devDependencies?.[t])}function er(e){const t=[{path:"app/layout.tsx",template:"next"},{path:"app/root.tsx",template:"react-router"},{path:"src/routes/__root.tsx",template:"start"},{path:"src/layouts/main.astro",template:"astro"},{path:"src/main.tsx",template:"vite"}];for(const r of t)if(s.existsSync(i.join(e,r.path)))return r.template;return null}function tr(e){return j(e,"next")?"next":j(e,"@tanstack/react-start")||j(e,"@tanstack/start")?"start":j(e,"react-router")||j(e,"@react-router/dev")?"react-router":j(e,"astro")?"astro":j(e,"vite")?"vite":null}function M(e){const t=i.resolve(e);if(!s.existsSync(t))throw new Error(`Directory not found: ${t}`);if(!s.existsSync(i.join(t,"src-tauri")))throw new Error(`No src-tauri/ directory found in ${t}. Run this command inside a Tauri project.`);const r=Qt(t);if(!r)throw new Error(`No readable package.json found in ${t}.`);const n=er(t)??tr(r);if(!n)throw new Error("Could not detect the frontend template (vite, next, start, react-router, astro).");return{template:n,projectDir:t}}function rr(e){switch(e){case"next":return"components";case"react-router":return"app/components";case"vite":case"start":case"astro":return"src/components"}}function je(e,t){const r=rr(t);return[i.join(e,r,"debug-panel.tsx")]}function nr(e,t){const r={vite:{file:"src/main.tsx",importMatch:/import \{ DebugPanel \} from "\.\/components\/debug-panel\.tsx"\r?\n/,jsxMatch:/ *\{import\.meta\.env\.DEV \? <DebugPanel \/> : null\}\r?\n/},next:{file:"app/layout.tsx",importMatch:/import \{ DebugPanel \} from "@\/components\/debug-panel"\r?\n/,jsxMatch:/\{process\.env\.NODE_ENV === "development" \? <DebugPanel \/> : null\}/},start:{file:"src/routes/__root.tsx",importMatch:/import \{ DebugPanel \} from "\.\.\/components\/debug-panel"\r?\n/,jsxMatch:/\{import\.meta\.env\.DEV \? <DebugPanel \/> : null\}/},"react-router":{file:"app/root.tsx",importMatch:/import \{ DebugPanel \} from "\.\/components\/debug-panel"\r?\n/,jsxMatch:/ *\{import\.meta\.env\.DEV \? <DebugPanel \/> : null\}\r?\n/},astro:{file:"src/layouts/main.astro",importMatch:/import \{ DebugPanel \} from "@\/components\/debug-panel"\r?\n/,jsxMatch:/\{import\.meta\.env\.DEV \? <DebugPanel client:load \/> : null\}/}}[t],n=i.join(e,r.file);s.existsSync(n)&&c(n,a=>a.replace(r.importMatch,"").replace(r.jsxMatch,""))}function ar(e){const t=i.join(e,"src-tauri/capabilities/default.json");s.existsSync(t)&&v(t,r=>(Array.isArray(r.permissions)&&(r.permissions=r.permissions.filter(n=>n!=="log:default")),r))}const ee={"debug-panel":{id:"debug-panel",name:"Development debug panel",description:"Dev-only inspector for state, window, host diagnostics, invokes, events, logs.",detectFiles(e,t){return je(e,t).filter(r=>s.existsSync(r))},async apply(e,t){await ye(e,t)},remove(e,t){const r=[],n=je(e,t.template);for(const a of n)s.existsSync(a)&&(s.rmSync(a),r.push(i.relative(e,a)));return nr(e,t.template),ar(e),{removed:r,manual:["src/lib/debug-events.ts and src/lib/tauri.ts are shared with the invoke-example battery \u2014 leave them in place unless you also remove invoke-example","src-tauri/Cargo.toml \u2014 remove `tauri-plugin-log` and `log` dependencies if unused","src-tauri/src/lib.rs \u2014 remove the `tauri_plugin_log` import and `.plugin(...)` registration if unused","package.json \u2014 remove `@tauri-apps/plugin-log` if unused","run `bun install` and `cargo check` in src-tauri/ to confirm"]}}},workflow:{id:"workflow",name:"GitHub release workflow",description:"GitHub Actions workflow that builds and publishes a release per platform.",detectFiles(e){const t=i.join(e,".github/workflows/release.yml");return s.existsSync(t)?[t]:[]},async apply(e,t){await $e(e,t)},remove(e){const t=[],r=i.join(e,".github/workflows/release.yml");return s.existsSync(r)&&(s.rmSync(r),t.push(i.relative(e,r))),{removed:t,manual:[]}}}};function ir(e){const t=ee[e];if(!t)throw new Error(`Unknown battery "${e}". Available: ${Object.keys(ee).join(", ")}`);return t}function Ee(){return Object.values(ee)}function V(e,t,r){const n=e.detectFiles(t,r);return{installed:n.length>0,detectedFiles:n}}const or={"windows-latest":"Windows","macos-latest":"macOS (Apple Silicon + Intel)","ubuntu-latest":"Linux"};function te(e){if(ie(e))throw new Error("Operation cancelled");return e}async function Se(e){const t=["macos-latest","ubuntu-latest","windows-latest"];return e?t:te(await oe({message:"Target platforms for the release workflow",options:S.map(r=>({value:r,label:or[r]??r})),initialValues:t,required:!0}))}function re(e,t,r=[]){const n=i.basename(e);return{projectName:n,packageName:n,template:t,identifier:`com.example.${n}`,preset:"b0",includeSizeOptimization:!1,includeStarterUI:!1,includeInvokeExample:!1,includeWorkflow:!1,targetOS:r,targetDir:e}}async function sr(e,t){const{template:r,projectDir:n}=M(t.targetDir??h.cwd()),a=V(e,n,r);if(a.installed&&!t.force){m.warn(`${e.name} is already installed. Use \`update\` to overwrite, or pass --force.`);for(const p of a.detectedFiles)m.message(` \xB7 ${i.relative(n,p)}`);return}let o=[];e.id==="workflow"&&(o=t.targetOS?.length?t.targetOS:await Se(t.yes));const l=re(n,r,o);m.info(`Installing ${e.name} in ${f.dim(n)}`),await e.apply(n,l),m.success(`${e.name} installed.`)}async function lr(e,t){const{template:r,projectDir:n}=M(t.targetDir??h.cwd());if(!V(e,n,r).installed&&!t.force){m.warn(`${e.name} is not installed yet. Use \`add\` to install, or pass --force to write anyway.`);return}if(!t.yes&&!te(await y({message:`Overwrite ${e.name} files with the latest template?`,initialValue:!0}))){m.info("Update cancelled.");return}let a=[];e.id==="workflow"&&(a=t.targetOS?.length?t.targetOS:await Se(t.yes));const o=re(n,r,a);await e.apply(n,o),m.success(`${e.name} updated.`)}async function cr(e,t){const{template:r,projectDir:n}=M(t.targetDir??h.cwd());if(!V(e,n,r).installed){m.warn(`${e.name} is not installed.`);return}if(!t.yes&&!te(await y({message:`Remove ${e.name} files from this project?`,initialValue:!1}))){m.info("Remove cancelled.");return}const a=re(n,r),o=e.remove(n,a);if(o.removed.length===0)m.warn("No files removed.");else{m.success(`Removed ${o.removed.length} file(s):`);for(const l of o.removed)m.message(` \xB7 ${l}`)}o.manual.length>0&&I(o.manual.map(l=>`- ${l}`).join(`
481
+ `),"Manual cleanup")}function ur(e){const{template:t,projectDir:r}=M(e.targetDir??h.cwd()),n=[];for(const a of Ee()){const o=V(a,r,t),l=o.installed?f.green("\u25CF"):f.dim("\u25CB"),p=o.installed?f.green("installed"):f.dim("not installed");n.push(`${l} ${f.bold(a.id.padEnd(14))} ${p}`),n.push(f.dim(` ${a.description}`))}I(n.join(`
482
+ `),`Batteries (${t})`)}async function pr(e){ae(f.bold(`create-tauri-ui \xB7 ${e.action}`));try{if(e.action==="list"){ur(e),H("Done");return}if(!e.batteryId)throw new Error(`Missing battery name. Available: ${Ee().map(r=>r.id).join(", ")}`);const t=ir(e.batteryId);switch(e.action){case"add":await sr(t,e);break;case"update":await lr(t,e);break;case"remove":await cr(t,e);break}H("Done")}catch(t){const r=t instanceof Error?t.message:String(t);W(r),h.exitCode=1}}const dr=1400,mr=918;async function fr(e,t,r){de(i.join(t,"src-tauri"),i.join(e,"src-tauri")),v(i.join(e,"package.json"),o=>(o.name=r.packageName,o.dependencies=o.dependencies||{},o.dependencies["@tauri-apps/api"]="^2",o.dependencies["@tauri-apps/plugin-opener"]="^2",o.devDependencies=o.devDependencies||{},o.devDependencies["@tauri-apps/cli"]="^2",o.scripts=o.scripts||{},o.scripts.tauri="tauri",o));const n=Ve(r.packageName),a=`${n}_lib`;c(i.join(e,"src-tauri/Cargo.toml"),o=>o.replace(/^name = "tauri-app"$/m,`name = "${n}"`).replace(/^name = "tauri_app_lib"$/m,`name = "${a}"`)),c(i.join(e,"src-tauri/src/main.rs"),o=>o.replace("tauri_app_lib::run()",`${a}::run()`))}async function gr(e,t,r){v(i.join(e,"src-tauri/tauri.conf.json"),n=>{n.productName=t.projectName,n.identifier=t.identifier,n.build={...n.build,...r},n.app=n.app||{},n.app.windows=Array.isArray(n.app.windows)?n.app.windows:[{}];const a=n.app.windows[0]||{};return n.app.windows[0]={...a,title:t.projectName,center:!0,width:dr,height:mr},n})}const De="tauri-ui",Pe="b0",hr={vite:"Vite",next:"Next.js",start:"TanStack Start","react-router":"React Router",astro:"Astro"},wr={"windows-latest":"Windows","macos-latest":"macOS (Apple Silicon, Intel)","ubuntu-22.04":"Linux","ubuntu-latest":"Linux"};function g(e,t="Operation cancelled"){if(ie(e))throw new Error(t);return e}function vr(e){if(Q.includes(e))return e;throw new Error(`Unsupported template "${e}". Expected one of: ${Q.join(", ")}`)}function _e(e){try{return`com.${pe(se.userInfo().username)||"example"}.${e}`}catch{return`com.example.${e}`}}function B(e){return{placeholder:e,defaultValue:e}}function Ce(e){const t=e.trim().replace(/^['"]|['"]$/g,"");return(t.match(/^(?:--preset(?:=|\s+))?(.+)$/)?.[1]??t).trim()}async function xr(e,t=process.cwd()){let r=ze(e.targetDir);if(r||(r=g(await O({message:"Project name",...B(De)}))),r||(r=De),r===".")throw new Error("Scaffolding into the current directory is not supported yet.");const n=i.resolve(t,r),a=i.basename(n),o=Y(a)?a:pe(a);if(s.existsSync(n)&&!Fe(n))if(e.force)s.rmSync(n,{recursive:!0,force:!0});else{if(e.yes)throw new Error(`Target directory "${r}" is not empty. Re-run with --force to overwrite it.`);if(!g(await y({message:`Target directory "${r}" is not empty. Remove it and continue?`,initialValue:!1})))throw new Error("Operation cancelled");s.rmSync(n,{recursive:!0,force:!0})}let l=o;Y(a)||(e.yes?l=o:l=g(await O({message:"Package name",...B(o),validate(w){if(!w||!Y(w))return"Enter a valid package.json name"}})));const p=e.template?vr(e.template):e.yes?"vite":g(await Ie({message:"Frontend template",initialValue:"vite",options:Q.map(w=>({value:w,label:hr[w]}))})),d=e.identifier?e.identifier:e.yes?_e(l):g(await O({message:"App identifier",...B(_e(l))})),b=e.preset?Ce(e.preset):e.yes?Pe:Ce(g(await O({message:"shadcn preset",...B(Pe)}))),E=e.includeStarterUI??(e.yes?!0:g(await y({message:"Include starter UI?",initialValue:!0}))),Ge=e.includeSizeOptimization??(e.yes?!1:g(await y({message:"Optimize app size?",initialValue:!0}))),Ne=e.includeInvokeExample??(e.yes?!0:g(await y({message:"Include Rust invoke example?",initialValue:!0}))),ne=e.includeWorkflow??(e.yes?!0:g(await y({message:"Include GitHub release workflow?",initialValue:!0}))),Ae=ne?e.yes?[...S]:g(await oe({message:"GitHub workflow target operating systems",initialValues:[...S],required:!0,options:S.map(w=>({value:w,label:wr[w]??w}))})):[];return{projectName:a,packageName:l,template:p,identifier:d,preset:b,includeSizeOptimization:Ge,includeStarterUI:E,includeInvokeExample:Ne,includeWorkflow:ne,targetOS:Ae,targetDir:n}}function br(){const e=new URL("../package.json",import.meta.url);return JSON.parse(s.readFileSync(e,"utf-8")).version??"0.0.0"}const yr=new Set(["add","update","remove","list"]);function Le(){console.log(`Usage:
483
+ create-tauri-ui [target-dir] [options] scaffold a new project
484
+ create-tauri-ui <add|update|remove> <battery> manage batteries in an existing project
485
+ create-tauri-ui list list available batteries + install status
486
+
487
+ Scaffold options:
483
488
  -t, --template <name> vite | next | start | react-router | astro
484
489
  --identifier <value> set the Tauri app identifier
485
490
  --preset <value> set the shadcn preset (default: b0)
@@ -491,8 +496,14 @@ Options:
491
496
  --no-invoke-example skip the Rust invoke example
492
497
  --workflow include the GitHub release workflow
493
498
  --no-workflow skip the GitHub release workflow
494
- -f, --force overwrite an existing target directory
495
- -y, --yes accept defaults
499
+
500
+ Manage options:
501
+ --dir <path> project directory (default: current working dir)
502
+ --target-os <list> comma-separated platforms for workflow (windows-latest,macos-latest,ubuntu-latest)
503
+ -f, --force overwrite an existing target directory / battery
504
+ -y, --yes accept defaults / skip confirmations
496
505
  -v, --version display version
497
- -h, --help display help`)}function Qt(e){const t={},r=[],n=(i,o)=>{const l=e[i+1];if(!l||l.startsWith("-"))throw new Error(`Missing value for ${o}`);return l};for(let i=0;i<e.length;i+=1){const o=e[i];switch(o){case"-h":case"--help":t.help=!0;break;case"-v":case"--version":t.version=!0;break;case"-t":case"--template":t.template=n(i,o),i+=1;break;case"--identifier":t.identifier=n(i,o),i+=1;break;case"--preset":t.preset=n(i,o),i+=1;break;case"--size-optimize":t.includeSizeOptimization=!0;break;case"--no-size-optimize":t.includeSizeOptimization=!1;break;case"--starter":t.includeStarterUI=!0;break;case"--no-starter":t.includeStarterUI=!1;break;case"--invoke-example":case"--example":t.includeInvokeExample=!0;break;case"--no-invoke-example":case"--no-example":t.includeInvokeExample=!1;break;case"--workflow":t.includeWorkflow=!0;break;case"--no-workflow":t.includeWorkflow=!1;break;case"-f":case"--force":t.force=!0;break;case"-y":case"--yes":t.yes=!0;break;default:if(o.startsWith("-"))throw new Error(`Unknown flag: ${o}`);r.push(o)}}if(r.length>1)throw new Error("Only one target directory may be provided.");return r[0]&&(t.targetDir=r[0]),t}function er(e){const t=a.relative(P.cwd(),e)||".";return t.includes(" ")?`"${t}"`:t}function tr(e){s.rmSync(a.join(e,"node_modules"),{recursive:!0,force:!0})}function rr(e,t){const r=[`cd ${er(e)}`,"bun install","bun run tauri dev","bunx tauri icon app-icon.png"];K(r.join(`
498
- `),"Next steps"),t&&K("Configure the GitHub release workflow secrets before publishing builds.","Release workflow")}async function nr(){try{await T("bun",["--version"])}catch{throw new Error("bun is required. Install it from https://bun.sh.")}}function me(e){return e instanceof x?{message:e.message,detail:e.stderr.trim()}:e instanceof Error?{message:e.message,detail:""}:{message:"An unknown error occurred.",detail:""}}async function ir(){const e=Qt(P.argv.slice(2));if(e.help){Zt();return}if(e.version){console.log(qt());return}$e(A.bold("create-tauri-ui")),await nr();const t=await Xt(e);Le(),z(t.targetDir);const r=Ee();let n;try{r.start("Creating the shadcn frontend scaffold"),await Ye(t),r.message("Creating the Tauri native scaffold");const i=await Je(t);n=i.tempDir,r.message("Merging the native layer into the frontend project"),await Ht(t.targetDir,i.projectDir,t);const o=Ue(t.template);r.message(`Patching the ${t.template} project for Tauri`);try{await o.apply(t.targetDir,t)}catch(l){if(l instanceof u)v.warn(`${l.message} (${l.file})`);else throw l}if(await Wt(t.targetDir,t,o.tauriConfig()),t.includeSizeOptimization&&(r.message("Applying the app size optimization battery"),await Ot(t.targetDir,t)),r.message("Applying the startup flash-prevention battery"),await $t(t.targetDir),r.message("Applying the desktop scroll container battery"),await Gt(t.targetDir,t),r.message("Applying the external link guard battery"),await yt(t.targetDir,t),t.includeStarterUI){r.message("Installing the starter dashboard");try{await Xe(t.targetDir,t)}catch(l){if(l instanceof x)v.warn(l.message),l.stderr.trim()&&v.message(l.stderr.trim());else throw l}}r.message("Applying the development debug panel battery"),await dt(t.targetDir,t),r.message("Applying the desktop selection-behavior battery"),await Nt(t.targetDir,t),t.includeInvokeExample&&(r.message("Adding the Rust invoke example"),await Ct(t.targetDir,t)),t.includeWorkflow&&(r.message("Writing the GitHub release workflow"),await Vt(t.targetDir,t)),r.message("Copying the app icon source"),await St(t.targetDir),tr(t.targetDir),g(t.targetDir),r.stop("Project ready"),rr(t.targetDir,t.includeWorkflow),je(`Scaffolded ${A.cyan(t.projectName)} in ${A.dim(t.targetDir)}`)}catch(i){const o=me(i);r.error("Scaffolding failed"),W(o.message),o.detail&&v.message(o.detail),P.exitCode=1}finally{if(n){g(n);try{h(n)}catch{}}}}ir().catch(e=>{const t=me(e);W(t.message),t.detail&&v.message(t.detail),P.exit(1)});
506
+ -h, --help display help
507
+
508
+ Batteries: debug-panel, workflow`)}function kr(e){const[t,...r]=e,n=t,a={action:n},o=[],l=(p,d)=>{const b=r[p+1];if(!b||b.startsWith("-"))throw new Error(`Missing value for ${d}`);return b};for(let p=0;p<r.length;p+=1){const d=r[p];switch(d){case"-h":case"--help":Le(),h.exit(0);break;case"-f":case"--force":a.force=!0;break;case"-y":case"--yes":a.yes=!0;break;case"--dir":a.targetDir=l(p,d),p+=1;break;case"--target-os":{const b=l(p,d).split(",").map(E=>E.trim()).filter(Boolean);for(const E of b)if(!S.includes(E))throw new Error(`Unknown target OS "${E}". Allowed: ${S.join(", ")}`);a.targetOS=b,p+=1;break}default:if(d.startsWith("-"))throw new Error(`Unknown flag: ${d}`);o.push(d)}}if(n!=="list"&&o.length===0)throw new Error(`Missing battery name. Usage: create-tauri-ui ${n} <battery>`);if(o.length>1)throw new Error("Only one battery may be provided per command.");return o[0]&&(a.batteryId=o[0]),a}function $r(e){const t={},r=[],n=(a,o)=>{const l=e[a+1];if(!l||l.startsWith("-"))throw new Error(`Missing value for ${o}`);return l};for(let a=0;a<e.length;a+=1){const o=e[a];switch(o){case"-h":case"--help":t.help=!0;break;case"-v":case"--version":t.version=!0;break;case"-t":case"--template":t.template=n(a,o),a+=1;break;case"--identifier":t.identifier=n(a,o),a+=1;break;case"--preset":t.preset=n(a,o),a+=1;break;case"--size-optimize":t.includeSizeOptimization=!0;break;case"--no-size-optimize":t.includeSizeOptimization=!1;break;case"--starter":t.includeStarterUI=!0;break;case"--no-starter":t.includeStarterUI=!1;break;case"--invoke-example":case"--example":t.includeInvokeExample=!0;break;case"--no-invoke-example":case"--no-example":t.includeInvokeExample=!1;break;case"--workflow":t.includeWorkflow=!0;break;case"--no-workflow":t.includeWorkflow=!1;break;case"-f":case"--force":t.force=!0;break;case"-y":case"--yes":t.yes=!0;break;default:if(o.startsWith("-"))throw new Error(`Unknown flag: ${o}`);r.push(o)}}if(r.length>1)throw new Error("Only one target directory may be provided.");return r[0]&&(t.targetDir=r[0]),t}function jr(e){const t=i.relative(h.cwd(),e)||".";return t.includes(" ")?`"${t}"`:t}function Er(e){s.rmSync(i.join(e,"node_modules"),{recursive:!0,force:!0})}function Sr(e,t){const r=[`cd ${jr(e)}`,"bun install","bun run tauri dev","bunx tauri icon app-icon.png"];I(r.join(`
509
+ `),"Next steps"),t&&I("Configure the GitHub release workflow secrets before publishing builds.","Release workflow")}async function Dr(){try{await F("bun",["--version"])}catch{throw new Error("bun is required. Install it from https://bun.sh.")}}function Te(e){return e instanceof D?{message:e.message,detail:e.stderr.trim()}:e instanceof Error?{message:e.message,detail:""}:{message:"An unknown error occurred.",detail:""}}async function Pr(){const e=h.argv.slice(2),t=e[0];if(t&&yr.has(t)){const l=kr(e);await pr(l);return}const r=$r(e);if(r.help){Le();return}if(r.version){console.log(br());return}ae(f.bold("create-tauri-ui")),await Dr();const n=await xr(r);Me(),J(n.targetDir);const a=Oe();let o;try{a.start("Creating the shadcn frontend scaffold"),await ot(n),a.message("Creating the Tauri native scaffold");const l=await st(n);o=l.tempDir,a.message("Merging the native layer into the frontend project"),await fr(n.targetDir,l.projectDir,n);const p=Qe(n.template);a.message(`Patching the ${n.template} project for Tauri`);try{await p.apply(n.targetDir,n)}catch(d){if(d instanceof u)m.warn(`${d.message} (${d.file})`);else throw d}if(await gr(n.targetDir,n,p.tauriConfig()),n.includeSizeOptimization&&(a.message("Applying the app size optimization battery"),await Jt(n.targetDir,n)),a.message("Applying the startup flash-prevention battery"),await Nt(n.targetDir),a.message("Applying the desktop scroll container battery"),await Bt(n.targetDir,n),a.message("Applying the external link guard battery"),await Tt(n.targetDir,n),n.includeStarterUI){a.message("Installing the starter dashboard");try{await lt(n.targetDir,n)}catch(d){if(d instanceof D)m.warn(d.message),d.stderr.trim()&&m.message(d.stderr.trim());else throw d}}a.message("Applying the development debug panel battery"),await ye(n.targetDir,n),a.message("Applying the desktop selection-behavior battery"),await Ht(n.targetDir,n),n.includeInvokeExample&&(a.message("Adding the Rust invoke example"),await Mt(n.targetDir,n)),n.includeWorkflow&&(a.message("Writing the GitHub release workflow"),await $e(n.targetDir,n)),a.message("Copying the app icon source"),await Ot(n.targetDir),Er(n.targetDir),k(n.targetDir),a.stop("Project ready"),Sr(n.targetDir,n.includeWorkflow),H(`Scaffolded ${f.cyan(n.projectName)} in ${f.dim(n.targetDir)}`)}catch(l){const p=Te(l);a.error("Scaffolding failed"),W(p.message),p.detail&&m.message(p.detail),h.exitCode=1}finally{if(o){k(o);try{$(o)}catch{}}}}Pr().catch(e=>{const t=Te(e);W(t.message),t.detail&&m.message(t.detail),h.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tauri-ui",
3
- "version": "1.0.7",
3
+ "version": "1.1.0",
4
4
  "description": "🦀 Create modern Tauri desktop apps in just a few simple steps.",
5
5
  "homepage": "https://github.com/agmmnn/tauri-ui",
6
6
  "bugs": {