create-tauri-ui 1.0.4 → 1.0.5
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/assets/debug-panel/debug-panel.tsx.tmpl +293 -203
- package/dist/index.mjs +84 -79
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import s from"node:fs";import
|
|
2
|
-
`);s.writeFileSync(e,t(r),"utf-8")}function
|
|
3
|
-
`)}async function
|
|
1
|
+
import s from"node:fs";import i from"node:path";import _ from"node:process";import{text as P,confirm as D,select as xe,multiselect as be,isCancel as ye,cancel as K,log as w,intro as ke,spinner as $e,outro as Ee,note as z}from"@clack/prompts";import A from"picocolors";import Y from"node:os";import{execFile as je}from"node:child_process";import{fileURLToPath as R}from"node:url";const L=new Set;let X=!1,q=!1;class C extends Error{constructor(t,r,n,a){super(t),this.stdout=r,this.stderr=n,this.code=a}}class v 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 Se(e){return e?.trim().replace(/\/+$/g,"")}function J(e,t){s.statSync(e).isDirectory()?Q(e,t):(s.mkdirSync(i.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=i.resolve(e,r),a=i.resolve(t,r);J(n,a)}}function _e(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,a)=>{je(e,t,{cwd:r?.cwd,env:{...process.env,...r?.env},maxBuffer:1024*1024*10},(o,l,I)=>{if(o){a(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(i.join(Y.tmpdir(),e))}function F(e){L.add(e)}function g(e){L.delete(e)}function h(e){s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0})}function Pe(){const e=[...L].sort((t,r)=>r.length-t.length);for(const t of e)try{h(t)}catch{}finally{L.delete(t)}}function De(){if(X)return;X=!0;const e=(t,r)=>{q&&process.exit(r),q=!0,Pe(),process.exit(r)};process.once("SIGINT",()=>e("SIGINT",130)),process.once("SIGTERM",()=>e("SIGTERM",143))}function Le(e){return e.replace(/^@[^/]+\//,"").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}const Ce={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"}}},
|
|
7
|
+
},${r.slice(n)}`})},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Te={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
|
-
}`)}),
|
|
12
|
+
}`)}),f(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 Ge(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
|
|
17
|
+
},${e.slice(t)}`}const Ne={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"),Ge)},tauriConfig(){return{frontendDist:"../build/client",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ie(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
|
|
22
|
+
},${e.slice(t)}`}const Ae={name:"start",async apply(e,t){c(i.join(e,"vite.config.ts"),r=>{let n=Ie(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(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 Re(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
|
|
27
|
+
},${e.slice(t)}`}const Oe={name:"vite",async apply(e,t){c(i.join(e,"vite.config.ts"),Re)},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Fe={vite:Oe,next:Te,start:Ae,"react-router":Ne,astro:Ce};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 v("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=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
|
|
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 Me(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: "${Ve}"`))}function x(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
|
|
78
|
-
${
|
|
77
|
+
`}function He(e){return`import { createFileRoute } from "@tanstack/react-router"
|
|
78
|
+
${x("DashboardPage","@/","@/app/dashboard/data.json",e)}export const Route = createFileRoute("/")({
|
|
79
79
|
component: DashboardPage,
|
|
80
80
|
})
|
|
81
|
-
`}function
|
|
81
|
+
`}function We(e){return x("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 ze(e){s.mkdirSync(i.dirname(e.targetDir),{recursive:!0});const t=ee("create-tauri-ui-frontend-"),r=i.join(t,e.projectName);F(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(i.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 v("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 Ye(e){const t=ee("create-tauri-ui-"),r="tauri-native";F(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 v("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:i.join(t,r)}}async function Xe(e,t){await te(e,["add","dashboard-01","--yes"]),Me(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":Be(e),s.writeFileSync(i.join(e,"app/page.tsx"),x("Page","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"vite":s.writeFileSync(i.join(e,"src/App.tsx"),x("App","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"start":s.writeFileSync(i.join(e,"src/routes/index.tsx"),He(t.includeInvokeExample));return;case"react-router":s.writeFileSync(i.join(e,"app/routes/home.tsx"),x("Home","~/","~/dashboard/data.json",t.includeInvokeExample));return;case"astro":s.writeFileSync(i.join(e,"src/components/dashboard-shell.tsx"),We(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
|
|
90
|
-
`,
|
|
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
|
+
`,ae=` log::info!("opening external link in system browser: {}", url);
|
|
91
91
|
`,ie=` log::info!("main webview finished loading");
|
|
92
|
-
`,
|
|
92
|
+
`,qe=` .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
|
|
101
|
+
`;function Je(){const e=i.dirname(R(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 Ze=Je();function Qe(e){return e==="react-router"?"~/":"@/"}function oe(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 et(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 tt(e,t){return i.join(oe(e,t),"ui")}function b(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 rt(e,t){for(const r of["button","badge","dropdown-menu","tabs"]){const n=i.join(tt(e,t),`${r}.tsx`);s.existsSync(n)||await re(e,r)}}function U(e){return s.readFileSync(i.join(Ze,e),"utf-8")}function nt(e,t){const r=i.join(oe(e,t),"debug-panel.tsx"),n=et(e,t);s.mkdirSync(i.dirname(r),{recursive:!0}),s.mkdirSync(n,{recursive:!0}),s.writeFileSync(r,U("debug-panel.tsx.tmpl").split("__ALIAS_PREFIX__").join(Qe(t.template)),"utf-8"),s.writeFileSync(i.join(n,"debug-events.ts"),U("debug-events.ts.tmpl"),"utf-8"),s.writeFileSync(i.join(n,"tauri.ts"),U("tauri.ts.tmpl"),"utf-8")}function at(e){f(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 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]
|
|
102
102
|
${t}
|
|
103
|
-
`)}function
|
|
104
|
-
`)?
|
|
103
|
+
`)}function it(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=se(a,'tauri-plugin-log = "2"'),a=se(a,'log = "0.4"'),a}),f(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(G)||(a.includes(`use tauri_plugin_opener::OpenerExt;
|
|
104
|
+
`)?a=a.replace(`use tauri_plugin_opener::OpenerExt;
|
|
105
105
|
`,`use tauri_plugin_opener::OpenerExt;
|
|
106
|
-
${
|
|
107
|
-
`):
|
|
108
|
-
`)?
|
|
106
|
+
${G}
|
|
107
|
+
`):a.includes(`use tauri::webview::PageLoadEvent;
|
|
108
|
+
`)?a=a.replace(`use tauri::webview::PageLoadEvent;
|
|
109
109
|
`,`use tauri::webview::PageLoadEvent;
|
|
110
|
-
${
|
|
111
|
-
`):
|
|
112
|
-
${
|
|
110
|
+
${G}
|
|
111
|
+
`):a=`${G}
|
|
112
|
+
${a}`),a.includes("tauri_plugin_log::Builder::new()"))return a;const o=a.replace(` tauri::Builder::default()
|
|
113
113
|
`,` tauri::Builder::default()
|
|
114
|
-
${
|
|
115
|
-
`)&&(
|
|
114
|
+
${qe}`);if(o===a)throw new u(r,"Could not register the Tauri log plugin.");return a=o,!a.includes(ne.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
|
-
${
|
|
118
|
-
`)&&(
|
|
119
|
-
`,`${
|
|
120
|
-
`)),!
|
|
121
|
-
`)&&(
|
|
117
|
+
${ne}`)),!a.includes(ae.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
|
+
`,`${ae} let _ = webview.opener().open_url(url.as_str(), None::<&str>);
|
|
120
|
+
`)),!a.includes(ie.trim())&&a.includes(` let _ = webview.window().show();
|
|
121
|
+
`)&&(a=a.replace(` let _ = webview.window().show();
|
|
122
122
|
`,`${ie} let _ = webview.window().show();
|
|
123
|
-
`)),
|
|
123
|
+
`)),a})}function ot(e,t){const r=i.join(e,"src/main.tsx"),n=b(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
|
-
`)),o.includes("<DebugPanel />"))return o;const
|
|
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><App /></main>`);if(
|
|
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 st(e,t){const r=i.join(e,"app/layout.tsx"),n=b(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
|
|
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 lt(e,t){const r=i.join(e,"src/routes/__root.tsx"),n=b(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
|
|
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 ct(e,t){const r=i.join(e,"app/root.tsx"),n=b(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
|
-
`)),o.includes("<DebugPanel />"))return o;const
|
|
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(
|
|
144
|
+
{children}`);if(l===o)throw new u(r,"Could not mount DebugPanel in the React Router root layout.");return l})}function ut(e,t){const r=i.join(e,"src/layouts/main.astro"),n=b(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
|
|
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 pt(e,t){switch(await rt(e,t),nt(e,t),at(e),it(e),t.template){case"vite":ot(e,t);return;case"next":st(e,t);return;case"start":lt(e,t);return;case"react-router":ct(e,t);return;case"astro":ut(e,t);return}}const V="use tauri_plugin_opener::OpenerExt;",dt=`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
|
-
`,
|
|
173
|
+
`,mt=`"use client"
|
|
174
174
|
|
|
175
175
|
import { useEffect } from "react"
|
|
176
176
|
|
|
@@ -271,51 +271,49 @@ export function ExternalLinkGuard() {
|
|
|
271
271
|
|
|
272
272
|
return null
|
|
273
273
|
}
|
|
274
|
-
`;function y(e){s.mkdirSync(
|
|
274
|
+
`;function y(e){s.mkdirSync(i.dirname(e),{recursive:!0}),s.writeFileSync(e,mt,"utf-8")}function ft(e){const t=i.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(V)||(n.includes(`use tauri::webview::PageLoadEvent;
|
|
275
275
|
`)?n=n.replace(`use tauri::webview::PageLoadEvent;
|
|
276
276
|
`,`use tauri::webview::PageLoadEvent;
|
|
277
|
-
${
|
|
278
|
-
`):n=`${
|
|
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)]",`${
|
|
277
|
+
${V}
|
|
278
|
+
`):n=`${V}
|
|
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)]",`${dt}#[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
|
|
282
|
+
`)}return n})}function gt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/main.tsx");y(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
|
-
`)),
|
|
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><App /></main>`);if(o===
|
|
287
|
-
`)?
|
|
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 ht(e){const t=i.join(e,"components/external-link-guard.tsx"),r=i.join(e,"app/layout.tsx");y(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
|
-
`):
|
|
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
|
-
`)),
|
|
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 wt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/routes/__root.tsx");y(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
|
-
`)),
|
|
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 vt(e){const t=i.join(e,"app/components/external-link-guard.tsx"),r=i.join(e,"app/root.tsx");y(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
|
-
`)),
|
|
299
|
+
`)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(`<body>
|
|
300
300
|
{children}`,`<body>
|
|
301
301
|
<ExternalLinkGuard />
|
|
302
|
-
{children}`);if(o===
|
|
302
|
+
{children}`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the React Router root layout.");return o})}function xt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/layouts/main.astro");y(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
|
-
`)),
|
|
306
|
-
<main><slot /></main>
|
|
307
|
-
</body
|
|
308
|
-
<main><ExternalLinkGuard client:load /><slot /></main>
|
|
309
|
-
</body>`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Astro layout.");return o})}async function vt(e,t){switch(dt(e),t.template){case"vite":mt(e);return;case"next":ft(e);return;case"start":gt(e);return;case"react-router":ht(e);return;case"astro":wt(e);return}}const V="use tauri::webview::PageLoadEvent;",xt=` .on_page_load(|webview, payload| {
|
|
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
|
+
<main data-ui-scroll-container><ExternalLinkGuard client:load /><slot /></main>
|
|
307
|
+
</body>`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Astro layout.");return o})}async function bt(e,t){switch(ft(e),t.template){case"vite":gt(e);return;case"next":ht(e);return;case"start":wt(e);return;case"react-router":vt(e);return;case"astro":xt(e);return}}const B="use tauri::webview::PageLoadEvent;",yt=` .on_page_load(|webview, payload| {
|
|
310
308
|
if webview.label() == "main" && matches!(payload.event(), PageLoadEvent::Finished) {
|
|
311
309
|
let _ = webview.window().show();
|
|
312
310
|
}
|
|
313
311
|
})
|
|
314
|
-
`;async function
|
|
312
|
+
`;async function kt(e){f(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(B)||(n.includes(`use tauri::Manager;
|
|
315
313
|
`)?n=n.replace(`use tauri::Manager;
|
|
316
|
-
`,`${
|
|
317
|
-
`):n=`${
|
|
318
|
-
${n}`),n.includes(".on_page_load("))return n;const
|
|
314
|
+
`,`${B}
|
|
315
|
+
`):n=`${B}
|
|
316
|
+
${n}`),n.includes(".on_page_load("))return n;const a=n.replace(" .run(tauri::generate_context!())",`${yt} .run(tauri::generate_context!())`);if(a===n)throw new u(t,"Could not insert the startup flash-prevention page-load hook.");return a})}function $t(){const e=i.dirname(R(import.meta.url)),t=[i.resolve(e,"../assets"),i.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const Et=$t();async function jt(e){J(i.join(Et,"app-icon.png"),i.join(e,"app-icon.png"))}function St(e){return`"use client"
|
|
319
317
|
|
|
320
318
|
import { useState } from "react"
|
|
321
319
|
import { Button } from "${e}components/ui/button"
|
|
@@ -358,7 +356,7 @@ export function Greet() {
|
|
|
358
356
|
</div>
|
|
359
357
|
)
|
|
360
358
|
}
|
|
361
|
-
`}function
|
|
359
|
+
`}function _t(e,t){return`import { Greet } from "${t}components/greet"
|
|
362
360
|
|
|
363
361
|
export default function ${e}() {
|
|
364
362
|
return (
|
|
@@ -375,7 +373,7 @@ export default function ${e}() {
|
|
|
375
373
|
</div>
|
|
376
374
|
)
|
|
377
375
|
}
|
|
378
|
-
`}function
|
|
376
|
+
`}function Pt(){return`import { createFileRoute } from "@tanstack/react-router"
|
|
379
377
|
import { Greet } from "@/components/greet"
|
|
380
378
|
|
|
381
379
|
export const Route = createFileRoute("/")({
|
|
@@ -397,7 +395,7 @@ function Home() {
|
|
|
397
395
|
</div>
|
|
398
396
|
)
|
|
399
397
|
}
|
|
400
|
-
`}function
|
|
398
|
+
`}function le(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 Dt(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 Lt(e,t){t.includeStarterUI||await re(e,"input");const r=t.template==="react-router"?"~/":"@/";if(s.writeFileSync(Dt(t.template,e),St(r)),t.includeStarterUI)return;if(t.template==="astro"){s.writeFileSync(le(t.template,e),`---
|
|
401
399
|
import Layout from "@/layouts/main.astro"
|
|
402
400
|
import { Greet } from "@/components/greet"
|
|
403
401
|
---
|
|
@@ -415,33 +413,39 @@ import { Greet } from "@/components/greet"
|
|
|
415
413
|
</div>
|
|
416
414
|
</div>
|
|
417
415
|
</Layout>
|
|
418
|
-
`);return}const n=t.template==="start"?
|
|
416
|
+
`);return}const n=t.template==="start"?Pt():_t(t.template==="vite"?"App":t.template==="react-router"?"Home":"Page",r);s.writeFileSync(le(t.template,e),n)}const m="data-ui-scroll-container",k=`
|
|
417
|
+
/* Disable page-level overscroll and rubber-band scrolling so the UI feels more desktop-native. */
|
|
419
418
|
html,
|
|
420
419
|
body {
|
|
421
420
|
height: 100%;
|
|
422
|
-
overscroll-behavior: none;
|
|
423
421
|
}
|
|
424
422
|
|
|
425
423
|
body {
|
|
426
424
|
overflow: hidden;
|
|
427
425
|
}
|
|
428
426
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
427
|
+
/* Scope the desktop scroll shell to the generated root container only. */
|
|
428
|
+
[${m}] {
|
|
429
|
+
height: 100vh;
|
|
430
|
+
height: 100dvh;
|
|
431
|
+
overflow-x: hidden;
|
|
432
|
+
overflow-y: auto;
|
|
433
|
+
overscroll-behavior-y: none;
|
|
433
434
|
}
|
|
434
|
-
`,
|
|
435
|
+
`,Ct=`
|
|
436
|
+
/* Vite mounts into #root, so it needs to inherit the full-height desktop shell. */
|
|
435
437
|
#root {
|
|
436
438
|
height: 100%;
|
|
437
439
|
}
|
|
438
|
-
`;function
|
|
439
|
-
${t}`)}function
|
|
440
|
+
`;function $(e,t){c(e,r=>r.includes("Disable page-level overscroll and rubber-band scrolling")?r:`${r.trimEnd()}
|
|
441
|
+
${t}`)}function E(e,t,r){c(e,n=>{if(n.includes(`<main ${m}>`))return n;const a=n.replace(new RegExp(`<main(?![^>]*${m})([^>]*)>`),`<main ${m}$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 Tt(e,t){switch(t.template){case"next":$(i.join(e,"app/globals.css"),k),E(i.join(e,"app/layout.tsx"),/\{children\}/,`<main ${m}>{children}</main>`);return;case"vite":$(i.join(e,"src/index.css"),`${k}${Ct}`),E(i.join(e,"src/main.tsx"),/<App \/>/,`<main ${m}><App /></main>`);return;case"start":$(i.join(e,"src/styles.css"),k),E(i.join(e,"src/routes/__root.tsx"),/\{children\}/,`<main ${m}>{children}</main>`);return;case"react-router":$(i.join(e,"app/app.css"),k),E(i.join(e,"app/root.tsx"),/return <Outlet \/>/,`return <main ${m}><Outlet /></main>`);return;case"astro":$(i.join(e,"src/styles/global.css"),k),E(i.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 j=`
|
|
440
442
|
@layer base {
|
|
443
|
+
/* Desktop UIs often feel cleaner with accidental text selection disabled by default. */
|
|
441
444
|
body {
|
|
442
445
|
@apply select-none;
|
|
443
446
|
}
|
|
444
447
|
|
|
448
|
+
/* Keep editing and code surfaces selectable so inputs and diagnostics still work normally. */
|
|
445
449
|
input,
|
|
446
450
|
textarea,
|
|
447
451
|
[contenteditable="true"],
|
|
@@ -452,15 +456,16 @@ ${t}`)}function $(e,t,r){l(e,n=>{if(n.includes("<main>"))return n;const i=n.repl
|
|
|
452
456
|
}
|
|
453
457
|
|
|
454
458
|
@layer utilities {
|
|
459
|
+
/* Opt back into selection for any generated UI surface that should behave like regular text. */
|
|
455
460
|
.ui-selectable {
|
|
456
461
|
@apply select-text;
|
|
457
462
|
}
|
|
458
463
|
}
|
|
459
|
-
`;function
|
|
460
|
-
${t}`)}async function
|
|
464
|
+
`;function S(e,t){c(e,r=>r.includes(".ui-selectable")?r:`${r.trimEnd()}
|
|
465
|
+
${t}`)}async function Gt(e,t){switch(t.template){case"next":S(i.join(e,"app/globals.css"),j);return;case"vite":S(i.join(e,"src/index.css"),j);return;case"start":S(i.join(e,"src/styles.css"),j);return;case"react-router":S(i.join(e,"app/app.css"),j);return;case"astro":S(i.join(e,"src/styles/global.css"),j);return;default:throw new u(e,`No selection behavior battery implementation exists for template "${t.template}".`)}}function Nt(){const e=i.dirname(R(import.meta.url)),t=[i.resolve(e,"../assets"),i.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const It=Nt();function At(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}"
|
|
461
466
|
platform: "${r.platform}"
|
|
462
467
|
args: "${r.args}"`).join(`
|
|
463
|
-
`)}async function
|
|
468
|
+
`)}async function Rt(e,t){const r=s.readFileSync(i.join(It,"release.yml.tmpl"),"utf-8").replace("{{PLATFORMS}}",At(t.targetOS)),n=i.join(e,".github/workflows");s.mkdirSync(n,{recursive:!0}),s.writeFileSync(i.join(n,"release.yml"),r)}const Ot=1400,Ft=918;async function Ut(e,t,r){Q(i.join(t,"src-tauri"),i.join(e,"src-tauri")),f(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=Le(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 Vt(e,t,r){f(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:Ot,height:Ft},n})}const M=["vite","next","start","react-router","astro"],H=["windows-latest","macos-latest","ubuntu-latest"],ce="tauri-ui",ue="b0",Bt={vite:"Vite",next:"Next.js",start:"TanStack Start","react-router":"React Router",astro:"Astro"},Mt={"windows-latest":"Windows","macos-latest":"macOS (Apple Silicon, Intel)","ubuntu-22.04":"Linux","ubuntu-latest":"Linux"};function p(e,t="Operation cancelled"){if(ye(e))throw new Error(t);return e}function Ht(e){if(M.includes(e))return e;throw new Error(`Unsupported template "${e}". Expected one of: ${M.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 Wt(e,t=process.cwd()){let r=Se(e.targetDir);if(r||(r=p(await P({message:"Project name",...N(ce)}))),r||(r=ce),r===".")throw new Error("Scaffolding into the current directory is not supported yet.");const n=i.resolve(t,r),a=i.basename(n),o=O(a)?a:Z(a);if(s.existsSync(n)&&!_e(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 D({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(a)||(e.yes?l=o:l=p(await P({message:"Package name",...N(o),validate(d){if(!d||!O(d))return"Enter a valid package.json name"}})));const I=e.template?Ht(e.template):e.yes?"vite":p(await xe({message:"Frontend template",initialValue:"vite",options:M.map(d=>({value:d,label:Bt[d]}))})),fe=e.identifier?e.identifier:e.yes?pe(l):p(await P({message:"App identifier",...N(pe(l))})),ge=e.preset?de(e.preset):e.yes?ue:de(p(await P({message:"shadcn preset",...N(ue)}))),he=e.includeStarterUI??(e.yes?!0:p(await D({message:"Include starter UI?",initialValue:!0}))),we=e.includeInvokeExample??(e.yes?!0:p(await D({message:"Include Rust invoke example?",initialValue:!0}))),W=e.includeWorkflow??(e.yes?!0:p(await D({message:"Include GitHub release workflow?",initialValue:!0}))),ve=W?e.yes?[...H]:p(await be({message:"GitHub workflow target operating systems",initialValues:[...H],required:!0,options:H.map(d=>({value:d,label:Mt[d]??d}))})):[];return{projectName:a,packageName:l,template:I,identifier:fe,preset:ge,includeStarterUI:he,includeInvokeExample:we,includeWorkflow:W,targetOS:ve,targetDir:n}}function Kt(){console.log(`Usage: create-tauri-ui [target-dir] [options]
|
|
464
469
|
|
|
465
470
|
Options:
|
|
466
471
|
-t, --template <name> vite | next | start | react-router | astro
|
|
@@ -474,5 +479,5 @@ Options:
|
|
|
474
479
|
--no-workflow skip the GitHub release workflow
|
|
475
480
|
-f, --force overwrite an existing target directory
|
|
476
481
|
-y, --yes accept defaults
|
|
477
|
-
-h, --help display help`)}function
|
|
478
|
-
`),"Next steps"),t&&
|
|
482
|
+
-h, --help display help`)}function zt(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"-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"--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 Yt(e){const t=i.relative(_.cwd(),e)||".";return t.includes(" ")?`"${t}"`:t}function Xt(e){s.rmSync(i.join(e,"node_modules"),{recursive:!0,force:!0})}function qt(e,t){const r=[`cd ${Yt(e)}`,"bun install","bun run tauri dev","bunx tauri icon app-icon.png"];z(r.join(`
|
|
483
|
+
`),"Next steps"),t&&z("Configure the GitHub release workflow secrets before publishing builds.","Release workflow")}async function Jt(){try{await T("bun",["--version"])}catch{throw new Error("bun is required. Install it from https://bun.sh.")}}function me(e){return e instanceof v?{message:e.message,detail:e.stderr.trim()}:e instanceof Error?{message:e.message,detail:""}:{message:"An unknown error occurred.",detail:""}}async function Zt(){const e=zt(_.argv.slice(2));if(e.help){Kt();return}ke(A.bold("create-tauri-ui")),await Jt();const t=await Wt(e);De(),F(t.targetDir);const r=$e();let n;try{r.start("Creating the shadcn frontend scaffold"),await ze(t),r.message("Creating the Tauri native scaffold");const a=await Ye(t);n=a.tempDir,r.message("Merging the native layer into the frontend project"),await Ut(t.targetDir,a.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)w.warn(`${l.message} (${l.file})`);else throw l}if(await Vt(t.targetDir,t,o.tauriConfig()),r.message("Applying the startup flash-prevention battery"),await kt(t.targetDir),r.message("Applying the desktop scroll container battery"),await Tt(t.targetDir,t),r.message("Applying the external link guard battery"),await bt(t.targetDir,t),t.includeStarterUI){r.message("Installing the starter dashboard");try{await Xe(t.targetDir,t)}catch(l){if(l instanceof v)w.warn(l.message),l.stderr.trim()&&w.message(l.stderr.trim());else throw l}}r.message("Applying the development debug panel battery"),await pt(t.targetDir,t),r.message("Applying the desktop selection-behavior battery"),await Gt(t.targetDir,t),t.includeInvokeExample&&(r.message("Adding the Rust invoke example"),await Lt(t.targetDir,t)),t.includeWorkflow&&(r.message("Writing the GitHub release workflow"),await Rt(t.targetDir,t)),r.message("Copying the app icon source"),await jt(t.targetDir),Xt(t.targetDir),g(t.targetDir),r.stop("Project ready"),qt(t.targetDir,t.includeWorkflow),Ee(`Scaffolded ${A.cyan(t.projectName)} in ${A.dim(t.targetDir)}`)}catch(a){const o=me(a);r.error("Scaffolding failed"),K(o.message),o.detail&&w.message(o.detail),_.exitCode=1}finally{if(n){g(n);try{h(n)}catch{}}}}Zt().catch(e=>{const t=me(e);K(t.message),t.detail&&w.message(t.detail),_.exit(1)});
|