create-tauri-ui 1.0.5 → 1.0.7
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/README.md +93 -102
- package/assets/debug-panel/debug-panel.tsx.tmpl +647 -59
- package/dist/index.mjs +80 -65
- package/package.json +7 -7
package/dist/index.mjs
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import s from"node:fs";import
|
|
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
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,
|
|
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(`
|
|
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"}}},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 = {
|
|
8
8
|
output: "export",
|
|
9
9
|
images: {
|
|
10
10
|
unoptimized: true,
|
|
11
11
|
},
|
|
12
|
-
}`)}),f(
|
|
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(`
|
|
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 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(`
|
|
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 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(`
|
|
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 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"
|
|
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 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"
|
|
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"
|
|
@@ -75,10 +75,10 @@ ${n?` <div className="px-4 lg:px-6">
|
|
|
75
75
|
)
|
|
76
76
|
}
|
|
77
77
|
`}function He(e){return`import { createFileRoute } from "@tanstack/react-router"
|
|
78
|
-
${
|
|
78
|
+
${b("DashboardPage","@/","@/app/dashboard/data.json",e)}export const Route = createFileRoute("/")({
|
|
79
79
|
component: DashboardPage,
|
|
80
80
|
})
|
|
81
|
-
`}function We(e){return
|
|
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"),`---
|
|
82
82
|
import Layout from "@/layouts/main.astro"
|
|
83
83
|
import { DashboardShell } from "@/components/dashboard-shell"
|
|
84
84
|
---
|
|
@@ -87,8 +87,8 @@ import { DashboardShell } from "@/components/dashboard-shell"
|
|
|
87
87
|
<DashboardShell client:load />
|
|
88
88
|
</Layout>
|
|
89
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
|
-
`,
|
|
91
|
-
`,
|
|
90
|
+
`,ie=` log::info!("opening external link in system browser: {}", url);
|
|
91
|
+
`,ae=` log::info!("main webview finished loading");
|
|
92
92
|
`,qe=` .plugin(
|
|
93
93
|
tauri_plugin_log::Builder::new()
|
|
94
94
|
.targets([
|
|
@@ -98,33 +98,33 @@ import { DashboardShell } from "@/components/dashboard-shell"
|
|
|
98
98
|
])
|
|
99
99
|
.build(),
|
|
100
100
|
)
|
|
101
|
-
`;function
|
|
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]
|
|
102
102
|
${t}
|
|
103
|
-
`)}function
|
|
104
|
-
`)?
|
|
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;
|
|
105
105
|
`,`use tauri_plugin_opener::OpenerExt;
|
|
106
106
|
${G}
|
|
107
|
-
`):
|
|
108
|
-
`)?
|
|
107
|
+
`):i.includes(`use tauri::webview::PageLoadEvent;
|
|
108
|
+
`)?i=i.replace(`use tauri::webview::PageLoadEvent;
|
|
109
109
|
`,`use tauri::webview::PageLoadEvent;
|
|
110
110
|
${G}
|
|
111
|
-
`):
|
|
112
|
-
${
|
|
111
|
+
`):i=`${G}
|
|
112
|
+
${i}`),i.includes("tauri_plugin_log::Builder::new()"))return i;const o=i.replace(` tauri::Builder::default()
|
|
113
113
|
`,` tauri::Builder::default()
|
|
114
|
-
${qe}`);if(o===
|
|
115
|
-
`)&&(
|
|
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);
|
|
116
116
|
`,` let message = format!("Hello, {}! You've been greeted from Rust!", name);
|
|
117
|
-
${ne}`)),!
|
|
118
|
-
`)&&(
|
|
119
|
-
`,`${
|
|
120
|
-
`)),!
|
|
121
|
-
`)&&(
|
|
122
|
-
`,`${
|
|
123
|
-
`)),
|
|
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"
|
|
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
|
|
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"
|
|
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
|
|
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"
|
|
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
|
|
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"
|
|
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
|
|
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"
|
|
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
|
|
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> {
|
|
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
|
+
`,ft=`"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
|
|
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;
|
|
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
|
+
${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())
|
|
280
280
|
`,` .plugin(tauri_plugin_opener::init())
|
|
281
281
|
.plugin(external_navigation_plugin())
|
|
282
|
-
`)}return n})}function
|
|
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"
|
|
283
283
|
import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
|
|
284
|
-
`)),
|
|
284
|
+
`)),i.includes("<ExternalLinkGuard />"))return i;const o=i.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===
|
|
287
|
-
`)?
|
|
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"
|
|
288
288
|
`,`import { TooltipProvider } from "@/components/ui/tooltip"
|
|
289
289
|
import { ExternalLinkGuard } from "@/components/external-link-guard"
|
|
290
|
-
`):
|
|
290
|
+
`):i=i.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
|
+
`)),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"
|
|
294
294
|
`,`import appCss from "../styles.css?url"
|
|
295
295
|
import { ExternalLinkGuard } from "../components/external-link-guard"
|
|
296
|
-
`)),
|
|
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"
|
|
297
297
|
`,`import "./app.css"
|
|
298
298
|
import { ExternalLinkGuard } from "./components/external-link-guard"
|
|
299
|
-
`)),
|
|
299
|
+
`)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(`<body>
|
|
300
300
|
{children}`,`<body>
|
|
301
301
|
<ExternalLinkGuard />
|
|
302
|
-
{children}`);if(o===
|
|
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"
|
|
303
303
|
`,`import "@/styles/global.css"
|
|
304
304
|
import { ExternalLinkGuard } from "@/components/external-link-guard"
|
|
305
|
-
`)),
|
|
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>
|
|
306
306
|
<main data-ui-scroll-container><ExternalLinkGuard client:load /><slot /></main>
|
|
307
|
-
</body>`);if(o===
|
|
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| {
|
|
308
308
|
if webview.label() == "main" && matches!(payload.event(), PageLoadEvent::Finished) {
|
|
309
309
|
let _ = webview.window().show();
|
|
310
310
|
}
|
|
311
311
|
})
|
|
312
|
-
`;async function
|
|
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;
|
|
313
313
|
`)?n=n.replace(`use tauri::Manager;
|
|
314
|
-
`,`${
|
|
315
|
-
`):n=`${
|
|
316
|
-
${n}`),n.includes(".on_page_load("))return n;const
|
|
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"
|
|
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
|
|
359
|
+
`}function Pt(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
|
|
376
|
+
`}function Dt(){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
|
|
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),`---
|
|
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"?
|
|
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",$=`
|
|
417
417
|
/* Disable page-level overscroll and rubber-band scrolling so the UI feels more desktop-native. */
|
|
418
418
|
html,
|
|
419
419
|
body {
|
|
@@ -432,13 +432,13 @@ body {
|
|
|
432
432
|
overflow-y: auto;
|
|
433
433
|
overscroll-behavior-y: none;
|
|
434
434
|
}
|
|
435
|
-
`,
|
|
435
|
+
`,Tt=`
|
|
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
|
|
441
|
-
${t}`)}function
|
|
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=`
|
|
442
442
|
@layer base {
|
|
443
443
|
/* Desktop UIs often feel cleaner with accidental text selection disabled by default. */
|
|
444
444
|
body {
|
|
@@ -461,16 +461,30 @@ ${t}`)}function E(e,t,r){c(e,n=>{if(n.includes(`<main ${m}>`))return n;const a=n
|
|
|
461
461
|
@apply select-text;
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
|
-
`;function
|
|
465
|
-
${t}`)}async function
|
|
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=`
|
|
466
|
+
[profile.dev]
|
|
467
|
+
incremental = true # Compile your binary in smaller steps.
|
|
468
|
+
|
|
469
|
+
[profile.release]
|
|
470
|
+
codegen-units = 1 # Allows LLVM to perform better optimization.
|
|
471
|
+
lto = true # Enables link-time-optimizations.
|
|
472
|
+
opt-level = "s" # Prioritizes small binary size. Use \`3\` if you prefer speed.
|
|
473
|
+
panic = "abort" # Higher performance by disabling panic handlers.
|
|
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()}
|
|
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}"
|
|
466
478
|
platform: "${r.platform}"
|
|
467
479
|
args: "${r.args}"`).join(`
|
|
468
|
-
`)}async function
|
|
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]
|
|
469
481
|
|
|
470
482
|
Options:
|
|
471
483
|
-t, --template <name> vite | next | start | react-router | astro
|
|
472
484
|
--identifier <value> set the Tauri app identifier
|
|
473
485
|
--preset <value> set the shadcn preset (default: b0)
|
|
486
|
+
--size-optimize optimize the Tauri app for smaller release binaries
|
|
487
|
+
--no-size-optimize skip size optimization
|
|
474
488
|
--starter include the starter dashboard
|
|
475
489
|
--no-starter skip the starter dashboard
|
|
476
490
|
--invoke-example include the Rust invoke example
|
|
@@ -479,5 +493,6 @@ Options:
|
|
|
479
493
|
--no-workflow skip the GitHub release workflow
|
|
480
494
|
-f, --force overwrite an existing target directory
|
|
481
495
|
-y, --yes accept defaults
|
|
482
|
-
-
|
|
483
|
-
|
|
496
|
+
-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)});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-tauri-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
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": {
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
"updatesub": "git submodule update --init --recursive --remote"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@clack/prompts": "^1.
|
|
42
|
+
"@clack/prompts": "^1.2.0",
|
|
43
43
|
"picocolors": "^1.1.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/node": "^25.
|
|
47
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
48
|
-
"oxfmt": "^0.
|
|
49
|
-
"oxlint": "^1.
|
|
50
|
-
"typescript": "^6.0.
|
|
46
|
+
"@types/node": "^25.6.0",
|
|
47
|
+
"@typescript/native-preview": "7.0.0-dev.20260420.1",
|
|
48
|
+
"oxfmt": "^0.45.0",
|
|
49
|
+
"oxlint": "^1.60.0",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
51
|
"unbuild": "^3.6.1"
|
|
52
52
|
}
|
|
53
53
|
}
|