create-instant-app 0.22.95 → 0.22.96-experimental.add-posthog-frontend.20386914944.1

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 (2) hide show
  1. package/dist/index.js +15 -15
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Te,Option as l}from"commander";import*as M from"@clack/prompts";import{spawn as xe}from"child_process";import{execa as ke}from"execa";async function E(){return new Promise(e=>{let t=process.env.SHELL||"/bin/bash",n=xe(t,["-i","-c","which claude"],{stdio:["ignore","pipe","ignore"]}),o="";n.stdout.on("data",a=>{o+=a.toString()}),n.on("close",a=>{if(a===0){let r=o.trim();r.includes("aliased to ")?e(r.split("aliased to ")[1]||null):e(r)}else e(null)})})}var U=async(e,t)=>{let n=await E();if(!n)throw new Error("Claude not found in path");await ke(n,[e],{stdio:"inherit",cwd:t})};import{version as _e}from"@instantdb/version";import W from"path";var D=e=>(e.length>1&&e.endsWith("/")&&(e=e.slice(0,-1)),e),be=/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,L=e=>{let n=D(e).split("/"),o=n[n.length-1];if(o==="."){let i=W.resolve(process.cwd());o=W.basename(i)}let a=n.findIndex(i=>i.startsWith("@"));n.findIndex(i=>i.startsWith("@"))!==-1&&(o=n.slice(a).join("/"));let r=n.filter(i=>!i.startsWith("@")).join("/");return[o,r]},S=e=>e.trim(),$=e=>{let t=D(e),n=t.split("/"),o=n.findIndex(r=>r.startsWith("@")),a=n[n.length-1];if(n.findIndex(r=>r.startsWith("@"))!==-1&&(a=n.slice(o).join("/")),!(t==="."||be.test(a??"")))return"App name must consist of only lowercase alphanumeric characters, '-', and '_'"};import{renderUnwrap as I,UI as u}from"instant-cli/ui";var Ae={base:"next-js-app-dir",appName:"awesome-todos",ruleFiles:null,createRepo:!0,prompt:null},V=async()=>{let e=Ae,t=new Te().name("Create Instant App").description("A CLI for creating web/mobile applications with InstantDB").argument("[dir]","The name of the application, as well as the name of the directory to create").addOption(new l("-b --base <template>","The base template to scaffold from").choices(["next-js-app-dir","vite-vanilla","expo"])).addOption(new l("-g --git","Create a git repo in the new project").default(!0)).addOption(new l("--expo","Use the Expo starter template").default(!1)).addOption(new l("--next","Use the NextJS starter template").default(!1)).addOption(new l("--vanilla","Use the vanilla JS starter template").default(!1)).addOption(new l("--no-git","Don't create a git repo in the new project")).addOption(new l("--cursor","Include a Cursor rules file in the scaffold")).addOption(new l("--claude","Include a CLAUDE.md file in the scaffold")).addOption(new l("--codex","Include an AGENTS.md file in the scaffold")).addOption(new l("--gemini","Include a GEMINI.md file in the scaffold")).addOption(new l("--rules","Include an AGENTS.md file in the scaffold")).addOption(new l("--ai","Create a new InstantDB app based off of a prompt. (requires Claude Code)")).addOption(new l("-a --app <app-id>","Link to an existing InstantDB app by ID (requires login or --token)")).addOption(new l("-t --token <token>","Auth token override (use with --app when not logged in)")).version(_e).parse(process.argv),n=t.args[0]&&S(t.args[0]);if(n){let i=$(n);if(i)throw new Error("Invalid app name: "+i);e.appName=n}let o=t.opts();if(o.ai&&!await E())throw new Error("--ai only works with Claude Code, but we couldn't find it in your machine. Install it first, and run it again : ). Alternatively you can scaffold out a project without --ai");let a=await M.group({appName:async()=>{if(n)return n.trim();let i=await I(new u.TextInput({prompt:"What will your project/folder be called?",placeholder:"awesome-todos",defaultValue:"awesome-todos",validate:p=>$(S(p)),modifyOutput:u.ciaModifier()}));return S(i)},prompt:async()=>o.ai?await I(new u.TextInput({prompt:"What would you like to create?",placeholder:"Create an app that...",modifyOutput:u.modifiers.piped([u.ciaModifier()])})):null,base:async({results:i})=>o.base?o.base:o.vanilla?"vite-vanilla":o.next?"next-js-app-dir":o.expo?"expo":i.prompt?I(new u.Select({promptText:"What framework would you like to use?",options:[{value:"next-js-app-dir",label:"Next.js"},{value:"expo",label:"Expo: React Native"}],defaultValue:"next-js-app-dir",modifyOutput:u.modifiers.piped([u.ciaModifier()])})):I(new u.Select({promptText:"What framework would you like to use?",options:[{value:"next-js-app-dir",label:"Next.js"},{value:"vite-vanilla",label:"Vite: Vanilla TS"},{value:"expo",label:"Expo: React Native"}],defaultValue:"next-js-app-dir",modifyOutput:u.modifiers.piped([u.ciaModifier()])})),ruleFiles:async({results:i})=>i.prompt?"claude":o.cursor?"cursor":o.claude?"claude":o.codex?"codex":o.gemini?"gemini":o.rules?"codex":I(new u.Select({promptText:"Which AI tool would you like to add rule files for?",options:[{value:"cursor",label:"Cursor"},{value:"claude",label:"Claude"},{value:"codex",label:"Codex"},{value:"gemini",label:"Gemini"},{value:"zed",label:"Zed"},{value:"windsurf",label:"Windsurf"},{value:null,label:"None"}],defaultValue:null,modifyOutput:u.ciaModifier()})),createRepo:async()=>o.git!==void 0?o.git:!0},{onCancel(){process.exit(1)}}),r={app:o.app??null,token:o.token??null};return{project:a,appFlags:r}};import ge from"path";import he from"fs-extra";import{log as we,outro as st}from"@clack/prompts";import{intro as Pe}from"@clack/prompts";import z from"chalk";var ve=` _ _ _
2
+ import{Command as Te,Option as l}from"commander";import*as F from"@clack/prompts";import{spawn as xe}from"child_process";import{execa as be}from"execa";async function M(){return new Promise(e=>{let t=process.env.SHELL||"/bin/bash",n=xe(t,["-i","-c","which claude"],{stdio:["ignore","pipe","ignore"]}),o="";n.stdout.on("data",i=>{o+=i.toString()}),n.on("close",i=>{if(i===0){let a=o.trim();a.includes("aliased to ")?e(a.split("aliased to ")[1]||null):e(a)}else e(null)})})}var W=async(e,t)=>{let n=await M();if(!n)throw new Error("Claude not found in path");await be(n,[e],{stdio:"inherit",cwd:t})};import{version as _e}from"@instantdb/version";import D from"path";var V=e=>(e.length>1&&e.endsWith("/")&&(e=e.slice(0,-1)),e),ke=/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,L=e=>{let n=V(e).split("/"),o=n[n.length-1];if(o==="."){let r=D.resolve(process.cwd());o=D.basename(r)}let i=n.findIndex(r=>r.startsWith("@"));n.findIndex(r=>r.startsWith("@"))!==-1&&(o=n.slice(i).join("/"));let a=n.filter(r=>!r.startsWith("@")).join("/");return[o,a]},C=e=>e.trim(),$=e=>{let t=V(e),n=t.split("/"),o=n.findIndex(a=>a.startsWith("@")),i=n[n.length-1];if(n.findIndex(a=>a.startsWith("@"))!==-1&&(i=n.slice(o).join("/")),!(t==="."||ke.test(i??"")))return"App name must consist of only lowercase alphanumeric characters, '-', and '_'"};import{renderUnwrap as S,UI as u}from"instant-cli/ui";var Ae={base:"next-js-app-dir",appName:"awesome-todos",ruleFiles:null,createRepo:!0,prompt:null},z=async()=>{let e=Ae,t=new Te().name("Create Instant App").description("A CLI for creating web/mobile applications with InstantDB").argument("[dir]","The name of the application, as well as the name of the directory to create").addOption(new l("-b --base <template>","The base template to scaffold from").choices(["next-js-app-dir","vite-vanilla","expo"])).addOption(new l("-g --git","Create a git repo in the new project").default(!0)).addOption(new l("--expo","Use the Expo starter template").default(!1)).addOption(new l("--next","Use the NextJS starter template").default(!1)).addOption(new l("--vanilla","Use the vanilla JS starter template").default(!1)).addOption(new l("--no-git","Don't create a git repo in the new project")).addOption(new l("--cursor","Include a Cursor rules file in the scaffold")).addOption(new l("--claude","Include a CLAUDE.md file in the scaffold")).addOption(new l("--codex","Include an AGENTS.md file in the scaffold")).addOption(new l("--gemini","Include a GEMINI.md file in the scaffold")).addOption(new l("--rules","Include an AGENTS.md file in the scaffold")).addOption(new l("--ai","Create a new InstantDB app based off of a prompt. (requires Claude Code)")).addOption(new l("-a --app <app-id>","Link to an existing InstantDB app by ID (requires login or --token)")).addOption(new l("-t --token <token>","Auth token override (use with --app when not logged in)")).version(_e).parse(process.argv),n=t.args[0]&&C(t.args[0]);if(n){let r=$(n);if(r)throw new Error("Invalid app name: "+r);e.appName=n}let o=t.opts();if(o.ai&&!await M())throw new Error("--ai only works with Claude Code, but we couldn't find it in your machine. Install it first, and run it again : ). Alternatively you can scaffold out a project without --ai");let i=await F.group({appName:async()=>{if(n)return n.trim();let r=await S(new u.TextInput({prompt:"What will your project/folder be called?",placeholder:"awesome-todos",defaultValue:"awesome-todos",validate:s=>$(C(s)),modifyOutput:u.ciaModifier()}));return C(r)},prompt:async()=>o.ai?await S(new u.TextInput({prompt:"What would you like to create?",placeholder:"Create an app that...",modifyOutput:u.modifiers.piped([u.ciaModifier()])})):null,base:async({results:r})=>o.base?o.base:o.vanilla?"vite-vanilla":o.next?"next-js-app-dir":o.expo?"expo":r.prompt?S(new u.Select({promptText:"What framework would you like to use?",options:[{value:"next-js-app-dir",label:"Next.js"},{value:"expo",label:"Expo: React Native"}],defaultValue:"next-js-app-dir",modifyOutput:u.modifiers.piped([u.ciaModifier()])})):S(new u.Select({promptText:"What framework would you like to use?",options:[{value:"next-js-app-dir",label:"Next.js"},{value:"vite-vanilla",label:"Vite: Vanilla TS"},{value:"expo",label:"Expo: React Native"}],defaultValue:"next-js-app-dir",modifyOutput:u.modifiers.piped([u.ciaModifier()])})),ruleFiles:async({results:r})=>r.prompt?"claude":o.cursor?"cursor":o.claude?"claude":o.codex?"codex":o.gemini?"gemini":o.rules?"codex":S(new u.Select({promptText:"Which AI tool would you like to add rule files for?",options:[{value:"cursor",label:"Cursor"},{value:"claude",label:"Claude"},{value:"codex",label:"Codex"},{value:"gemini",label:"Gemini"},{value:"zed",label:"Zed"},{value:"windsurf",label:"Windsurf"},{value:null,label:"None"}],defaultValue:null,modifyOutput:u.ciaModifier()})),createRepo:async()=>o.git!==void 0?o.git:!0},{onCancel(){process.exit(1)}}),a={app:o.app??null,token:o.token??null};return{project:i,appFlags:a}};import he from"path";import we from"fs-extra";import{log as ye,outro as pt}from"@clack/prompts";import{intro as Ie}from"@clack/prompts";import H from"chalk";var Pe=` _ _ _
3
3
  \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 (_) | | | |
4
4
  \u2588 \u2588\u2588\u2588\u2588 _ _ __ ___| |_ __ _ _ _ _| |_
5
5
  \u2588 \u2588\u2588\u2588\u2588 | | '_ \\/ __| __/ _\\\`| '_ \\| __|
6
6
  \u2588 \u2588\u2588\u2588\u2588 | | | | \\__ \\ || (_| | | | | |_
7
- \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 |_|_| |_|___/\\__\\__,_|_| |_|\\__|`,H=()=>{Pe(`
8
- `+ve.split(`
9
- `).map(e=>`${z.gray("\u2502")}${z.hex("#EA580D").bold(" "+e)}`).join(`
10
- `))};import m from"path";import g from"fs-extra";import J from"path";import{fileURLToPath as Ie}from"url";var Ne=Ie(import.meta.url),Se=J.dirname(Ne),f=J.join(Se,"../");import _ from"chalk";var y=()=>{let e=process.env.npm_config_user_agent;return e?e.startsWith("yarn")?"yarn":e.startsWith("pnpm")?"pnpm":e.startsWith("bun")?"bun":"npm":"npm"};import{renderUnwrap as je,UI as x}from"instant-cli/ui";import Ce from"slugify";var K=async(e,t)=>{let n=m.resolve(process.cwd(),t),o=m.join(f,`template/base/${e.base}`);if(g.existsSync(n))if(g.readdirSync(n).length===0)x.log(`${_.cyan.bold(e.appName)} exists but is empty, continuing...`,x.ciaModifier(null));else{let r=await je(new x.Select({promptText:_.redBright(`${_.bold("Warning:")} ${_.bold(e.appName)} already exists and isn't empty. How would you like to proceed?`),options:[{label:"Abort installation",value:"abort"},{label:"Clear the directory and continue installation",value:"clear"}],defaultValue:"abort",modifyOutput:x.ciaModifier()}));r==="abort"&&(x.log("Aborting installation..."),process.exit(1)),r==="clear"&&g.emptyDirSync(n)}if(g.copySync(o,n),g.renameSync(m.join(n,"_gitignore"),m.join(n,".gitignore")),g.renameSync(m.join(n,"_env"),m.join(n,".env")),y()==="pnpm"&&e.base==="expo"&&g.appendFile(m.join(n,".npmrc"),`node-linker=hoisted
11
- enable-pre-post-scripts=true`),e.base==="expo"){let r=Ce.default(t);F(m.join(n,"app.json"),'"name": "expo-template"',`"name": "${t}"`),F(m.join(n,"app.json"),'"slug": "expo-template"',`"slug": "${r}"`),F(m.join(n,"app/_layout.tsx"),'"My Instant App"',`"${t}"`)}let a=e.appName==="."?"App":_.hex("#EA570B").bold(e.appName);return x.log(_.dim(`${a} scaffolded successfully!`),x.ciaModifier(null)),n},F=(e,t,n)=>{let a=g.readFileSync(e,"utf8").replaceAll(t,n);g.writeFileSync(e,a)};import{execa as Oe}from"execa";import{renderUnwrap as Ee,UI as j}from"instant-cli/ui";var Y=async(e,t)=>{let n=Oe(e,["install"],{cwd:t}),o=await Ee(new j.Spinner({promise:n,workingText:`Installing dependencies with ${e}...`,doneText:"Successfully installed dependencies!",modifyOutput:j.ciaModifier(null)}));o.exitCode!==0&&(j.log(o.stderr,j.ciaModifier(null)),process.exit(1))};import pt from"chalk";import w from"fs-extra";import c from"path";var q=({projectDir:e,ruleFilesToAdd:t})=>{if(t!==null)switch(t){case"cursor":w.ensureDirSync(c.join(e,".cursor/rules")),w.copyFileSync(c.join(f,"template/rules/cursor-rules.md"),c.join(e,".cursor/rules/instant.mdc"));break;case"claude":w.copyFileSync(c.join(f,"template/rules/AGENTS.md"),c.join(e,"CLAUDE.md"));break;case"codex":w.copyFileSync(c.join(f,"template/rules/AGENTS.md"),c.join(e,"AGENTS.md"));break;case"gemini":w.copyFileSync(c.join(f,"template/rules/AGENTS.md"),c.join(e,"GEMINI.md"));break;case"zed":w.copyFileSync(c.join(f,"template/rules/AGENTS.md"),c.join(e,"AGENTS.md"));break;case"windsurf":w.ensureDirSync(c.join(e,".windsurf/rules")),w.copyFileSync(c.join(f,"template/rules/windsurf-rules.md"),c.join(e,".windsurf/rules/instant.md"));break}};import{execSync as R}from"child_process";import G from"path";import*as Q from"@clack/prompts";import X from"chalk";import{execa as P}from"execa";import ee from"fs-extra";import{renderUnwrap as Z,UI as A}from"instant-cli/ui";var $e=e=>{try{return R("git --version",{cwd:e}),!0}catch{return!1}},Me=e=>ee.existsSync(G.join(e,".git")),Fe=async e=>{try{return await P("git",["rev-parse","--is-inside-work-tree"],{cwd:e,stdout:"ignore"}),!0}catch{return!1}},Ge=()=>{let t=R("git --version").toString().trim().split(" ")[2],n=t?.split(".")[0],o=t?.split(".")[1];return{major:Number(n),minor:Number(o)}},Re=()=>R("git config --global init.defaultBranch || echo main").toString().trim(),te=async e=>{if(!$e(e)){Q.log.warn("Git is not installed. Skipping Git initialization.");return}let t=Me(e),n=await Fe(e),o=G.parse(e).name;if(n&&t){if(!await Z(new A.Confirmation({promptText:`${X.redBright.bold("Warning:")} Git is already initialized in "${o}". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`,defaultValue:!1,modifyOutput:A.ciaModifier()})))return;ee.removeSync(G.join(e,".git"))}else if(n&&!t&&!await Z(new A.Confirmation({promptText:`${X.redBright.bold("Warning:")} "${o}" is already in a git worktree.
7
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 |_|_| |_|___/\\__\\__,_|_| |_|\\__|`,J=()=>{Ie(`
8
+ `+Pe.split(`
9
+ `).map(e=>`${H.gray("\u2502")}${H.hex("#EA580D").bold(" "+e)}`).join(`
10
+ `))};import f from"path";import h from"fs-extra";import K from"path";import{fileURLToPath as ve}from"url";var Se=ve(import.meta.url),Ne=K.dirname(Se),g=K.join(Ne,"../");import A from"chalk";var x=()=>{let e=process.env.npm_config_user_agent;return e?e.startsWith("yarn")?"yarn":e.startsWith("pnpm")?"pnpm":e.startsWith("bun")?"bun":"npm":"npm"};import{renderUnwrap as Ce,UI as b}from"instant-cli/ui";import je from"slugify";var Y=async(e,t)=>{let n=f.resolve(process.cwd(),t),o=f.join(g,`template/base/${e.base}`);if(h.existsSync(n))if(h.readdirSync(n).length===0)b.log(`${A.cyan.bold(e.appName)} exists but is empty, continuing...`,b.ciaModifier(null));else{let a=await Ce(new b.Select({promptText:A.redBright(`${A.bold("Warning:")} ${A.bold(e.appName)} already exists and isn't empty. How would you like to proceed?`),options:[{label:"Abort installation",value:"abort"},{label:"Clear the directory and continue installation",value:"clear"}],defaultValue:"abort",modifyOutput:b.ciaModifier()}));a==="abort"&&(b.log("Aborting installation..."),process.exit(1)),a==="clear"&&h.emptyDirSync(n)}if(h.copySync(o,n),h.renameSync(f.join(n,"_gitignore"),f.join(n,".gitignore")),h.renameSync(f.join(n,"_env"),f.join(n,".env")),x()==="pnpm"&&e.base==="expo"&&h.appendFile(f.join(n,".npmrc"),`node-linker=hoisted
11
+ enable-pre-post-scripts=true`),e.base==="expo"){let a=je.default(t);G(f.join(n,"app.json"),'"name": "expo-template"',`"name": "${t}"`),G(f.join(n,"app.json"),'"slug": "expo-template"',`"slug": "${a}"`),G(f.join(n,"app/_layout.tsx"),'"My Instant App"',`"${t}"`)}let i=e.appName==="."?"App":A.hex("#EA570B").bold(e.appName);return b.log(A.dim(`${i} scaffolded successfully!`),b.ciaModifier(null)),n},G=(e,t,n)=>{let i=h.readFileSync(e,"utf8").replaceAll(t,n);h.writeFileSync(e,i)};import{execa as Oe}from"execa";import{renderUnwrap as Ee,UI as j}from"instant-cli/ui";var X=async(e,t)=>{let n=Oe(e,["install"],{cwd:t}),o=await Ee(new j.Spinner({promise:n,workingText:`Installing dependencies with ${e}...`,doneText:"Successfully installed dependencies!",modifyOutput:j.ciaModifier(null)}));o.exitCode!==0&&(j.log(o.stderr,j.ciaModifier(null)),process.exit(1))};import lt from"chalk";import y from"fs-extra";import c from"path";var q=({projectDir:e,ruleFilesToAdd:t})=>{if(t!==null)switch(t){case"cursor":y.ensureDirSync(c.join(e,".cursor/rules")),y.copyFileSync(c.join(g,"template/rules/cursor-rules.md"),c.join(e,".cursor/rules/instant.mdc"));break;case"claude":y.copyFileSync(c.join(g,"template/rules/AGENTS.md"),c.join(e,"CLAUDE.md"));break;case"codex":y.copyFileSync(c.join(g,"template/rules/AGENTS.md"),c.join(e,"AGENTS.md"));break;case"gemini":y.copyFileSync(c.join(g,"template/rules/AGENTS.md"),c.join(e,"GEMINI.md"));break;case"zed":y.copyFileSync(c.join(g,"template/rules/AGENTS.md"),c.join(e,"AGENTS.md"));break;case"windsurf":y.ensureDirSync(c.join(e,".windsurf/rules")),y.copyFileSync(c.join(g,"template/rules/windsurf-rules.md"),c.join(e,".windsurf/rules/instant.md"));break}};import{execSync as B}from"child_process";import R from"path";import*as ee from"@clack/prompts";import Z from"chalk";import{execa as P}from"execa";import te from"fs-extra";import{renderUnwrap as Q,UI as I}from"instant-cli/ui";var Me=e=>{try{return B("git --version",{cwd:e}),!0}catch{return!1}},$e=e=>te.existsSync(R.join(e,".git")),Fe=async e=>{try{return await P("git",["rev-parse","--is-inside-work-tree"],{cwd:e,stdout:"ignore"}),!0}catch{return!1}},Ge=()=>{let t=B("git --version").toString().trim().split(" ")[2],n=t?.split(".")[0],o=t?.split(".")[1];return{major:Number(n),minor:Number(o)}},Re=()=>B("git config --global init.defaultBranch || echo main").toString().trim(),ne=async e=>{if(!Me(e)){ee.log.warn("Git is not installed. Skipping Git initialization.");return}let t=$e(e),n=await Fe(e),o=R.parse(e).name;if(n&&t){if(!await Q(new I.Confirmation({promptText:`${Z.redBright.bold("Warning:")} Git is already initialized in "${o}". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`,defaultValue:!1,modifyOutput:I.ciaModifier()})))return;te.removeSync(R.join(e,".git"))}else if(n&&!t&&!await Q(new I.Confirmation({promptText:`${Z.redBright.bold("Warning:")} "${o}" is already in a git worktree.
12
12
  Would you still like to initialize a new git repository in this directory?
13
- `,defaultValue:!1,modifyOutput:A.ciaModifier()})))return;try{let a=Re(),{major:r,minor:i}=Ge();r<2||r==2&&i<28?(await P("git",["init"],{cwd:e}),await P("git",["symbolic-ref","HEAD",`refs/heads/${a}`],{cwd:e})):await P("git",["init",`--initial-branch=${a}`],{cwd:e}),await P("git",["add","."],{cwd:e}),await P("git",["commit","-m","Initial commit (create-instant-app)"],{cwd:e}),A.log("Git repository initialized successfully.",A.ciaModifier(null))}catch{}};import Be from"env-paths";import*as Ue from"@clack/prompts";import{mkdir as We,readFile as De,writeFile as Le}from"node:fs/promises";import Ve from"open";import{join as ze}from"node:path";import{randomUUID as re}from"node:crypto";var ne=!!process.env.INSTANT_CLI_DEV,oe=ne?"http://localhost:3000":"https://instantdb.com",B=process.env.INSTANT_CLI_API_URI||(ne?"http://localhost:8888":"https://api.instantdb.com");async function k({path:e,body:t,method:n="GET",authToken:o}){let r=await fetch(`${B}${e}`,{method:n??"GET",headers:{Authorization:o?`Bearer ${o}`:"","Content-Type":"application/json"},body:t?JSON.stringify(t):void 0,signal:AbortSignal.timeout(3e5)}),i;try{i=await r.json()}catch{i=null}if(!r.ok){let s=i.message||i.hint?.errors?.[0]?.message||"There was an error";throw new Error(s)}return i}import{renderUnwrap as C,UI as d}from"instant-cli/ui";var He=!!process.env.INSTANT_CLI_DEV,Je=!!process.env.INSTANT_CLI_FORCE_EPHEMERAL;function ae(){let e=`instantdb-${He?"dev":"prod"}`,{config:t}=Be(e);return{authConfigFilePath:ze(t,"a"),appConfigDirPath:t}}var Ke=async(e,t,n)=>{let o=re(),a=re();return await k({method:"POST",authToken:t,path:"/dash/apps",body:{id:o,title:e,admin_token:a,org_id:n}}),{appID:o,adminToken:a,source:"created"}},se=async e=>await k({method:"GET",path:"/dash",authToken:e}),pe=async(e,t)=>await k({method:"GET",path:`/dash/orgs/${t}`,authToken:e});var Ye=async(e,t)=>{try{let n=await se(e),o=n.apps.find(a=>a.id===t);if(o)return{appId:o.id,adminToken:o.admin_token};for(let a of n.orgs){let{apps:r}=await pe(e,a.id),i=r.find(s=>s.id===t);if(i)return{appId:i.id,adminToken:i.admin_token}}return null}catch{return null}},qe=async(e,t)=>{try{return await k({method:"GET",path:`/dash/apps/${e}/schema/pull`,authToken:t}),!0}catch{return!1}},Xe=async()=>Je?null:process.env.INSTANT_CLI_AUTH_TOKEN?process.env.INSTANT_CLI_AUTH_TOKEN:await De(ae().authConfigFilePath,"utf-8").catch(()=>null),ie=async e=>{let t=await k({authToken:null,method:"POST",path:"/dash/apps/ephemeral",body:{title:e,rules:{$users:{view:"true"},$files:{allow:{view:"true",create:"true",delete:"true"}}}}});return{appId:t.app.id,adminToken:t.app["admin-token"]}},le=async e=>{let t=await Xe();if(e?.app){if(e.token){if(!await qe(e.app,e.token))throw new Error("Invalid app ID and token combination. Please verify both the app ID and token are correct.");return d.log(`Linking to app: ${e.app}`,d.ciaModifier(null)),{appId:e.app,adminToken:e.token,approach:"import"}}if(t){let r=await Ye(t,e.app);if(!r)throw new Error(`You don't have access to app "${e.app}". Please check the app ID or use --token to provide a token.`);return d.log(`Linking to app: ${e.app}`,d.ciaModifier(null)),{appId:r.appId,adminToken:r.adminToken,approach:"import"}}throw new Error(`You must be logged in or provide --token when using --app. Either run 'npx instant-cli login' first, or use: --app ${e.app} --token <token>`)}if(!t){let r=await C(new d.Select({promptText:"You are not logged in.",options:[{label:"Create temporary app",value:"ephemeral"},{label:"Login to choose existing app",value:"login"},{label:"Create app later",value:"skip"}],modifyOutput:d.ciaModifier()}));if(r==="login"){let i=await k({authToken:null,method:"POST",path:"/dash/cli/auth/register"}),{secret:s,ticket:p}=i;Ve(`${oe}/dash?ticket=${p}`);let T=Qe({secret:s}),h=await C(new d.Spinner({promise:T,workingText:"Waiting for login in browser",disappearWhenDone:!0,modifyOutput:d.ciaModifier(null)}));await et(h.token),t=h.token}if(r==="skip")return d.log("Skipping app link step",d.ciaModifier(null)),null;if(r==="ephemeral"){let i=await C(new d.TextInput({defaultValue:"my-cool-app",prompt:"Enter a name for your temporary app:",placeholder:"my-cool-app",modifyOutput:d.ciaModifier()}));return{...await ie(i),approach:"ephemeral"}}}if(!t)return null;let n=await se(t),o=n.orgs.filter(r=>r.role!=="app-member");return n.orgs=o,await C(new d.AppSelector({startingMenuIndex:0,allowCreate:!0,allowEphemeral:!0,api:{getDash(){return n},createEphemeralApp(r){return ie(r)},getAppsForOrg:async r=>{let{apps:i}=await pe(t,r);return{apps:i}},createApp:async(r,i)=>{let{appID:s,adminToken:p}=await Ke(r,t,i);return{appId:s,adminToken:p}}},modifyOutput:d.ciaModifier()}))};function Ze(e){return new Promise(t=>setTimeout(t,e))}async function Qe({secret:e}){for(let t=1;t<=120;t++){await Ze(1e3);let n=await fetch(`${B}/dash/cli/auth/check`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({secret:e})});if(!(!n.ok&&(await n.json()).hint.errors?.[0]?.issue==="waiting-for-user")&&n.ok)return n.json()}throw new Error("Timed out waiting for login")}async function et(e){let t=ae();return await We(t.appConfigDirPath,{recursive:!0}),Le(t.authConfigFilePath,e,"utf-8")}import tt from"fs-extra";import nt from"path";var ot={"next-js-app-dir":"NEXT_PUBLIC_INSTANT_APP_ID","vite-vanilla":"VITE_INSTANT_APP_ID",expo:"EXPO_PUBLIC_INSTANT_APP_ID"},ce=(e,t,n,o)=>{let a=nt.join(t,".env"),i=`${ot[e.base]}=${n}
14
- INSTANT_APP_ADMIN_TOKEN=${o}`;tt.writeFileSync(a,i)};import{stdin as b,stdout as de}from"process";import{setRawModeWindowsFriendly as ue}from"instant-cli/ui";async function rt(){return new Promise(e=>{if(!de.isTTY||!b.isTTY){e(null);return}let t=b.isRaw;t||ue(b,!0);let n=setTimeout(()=>{a(),e(null)},100),o="",a=()=>{clearTimeout(n),b.removeListener("data",r),!t&&b.isTTY&&ue(b,!1)},r=i=>{let s=i.toString();o+=s;let p=o.match(/\x1b\]11;rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)(?:\x1b\\|\x07)/);if(p){a();let[,T,h,ye]=p;e(`rgb:${T}/${h}/${ye}`)}};b.on("data",r),de.write("\x1B]11;?\x1B\\")})}function it(e){let t=e.match(/rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)/);if(!t)return null;let[,n,o,a]=t,r=Math.round(parseInt(n,16)/257),i=Math.round(parseInt(o,16)/257),s=Math.round(parseInt(a,16)/257);return{r,g:i,b:s}}function at(e){return(.299*e.r+.587*e.g+.114*e.b)/255>.5}async function me(){try{let e=await rt();if(!e)return"unknown";let t=it(e);return t?at(t)?"light":"dark":"unknown"}catch(e){return console.error("Error detecting terminal theme:",e),"unknown"}}import N from"chalk";var v=(e,t)=>e==="light"?N.bgYellowBright(t):N.bgBlackBright(t),fe=(e,t=console.log,n=!1)=>{let o=(process.stdout.columns||80)-4,a=e.split(`
15
- `),r=!0;a.forEach(i=>{if(i.length===0){r?(t(""),r=!1):console.log(N.gray("\u2502"));return}for(let s=0;s<i.length;s+=o){let p=i.slice(s,s+o);s+o<i.length&&p.length===o&&(p=p+"-"),r?(t(p),r=!1):console.log(N.gray("\u2502 ")+p)}}),n&&console.log(N.gray("\u2502"))};var O="\x1B[?25h";import{execa as lt}from"execa";var ct=async()=>{process.argv.some(h=>["-h","--help","--version","-V"].includes(h))||H();let e=await me(),{project:t,appFlags:n}=await V(),[o,a]=L(t.appName),r=y(),i=await K(t,a);q({projectDir:i,ruleFilesToAdd:t.ruleFiles});let s=await le(n);s&&ce(t,i,s.appId,s.adminToken),await Y(y(),i);let p=he.readJSONSync(ge.join(i,"package.json"));if(p.name=o,r!=="bun"){let{stdout:h}=await lt(r,["-v"],{cwd:i});p.packageManager=`${r}@${h.trim()}`}he.writeJSONSync(ge.join(i,"package.json"),p,{spaces:2}),t.createRepo&&await te(i),t.prompt&&(await U(t.prompt,i),process.stdout.write(O)),st("Done!");let T=t.base==="expo"?"start":"dev";s?(console.log(`
13
+ `,defaultValue:!1,modifyOutput:I.ciaModifier()})))return;try{let i=Re(),{major:a,minor:r}=Ge();a<2||a==2&&r<28?(await P("git",["init"],{cwd:e}),await P("git",["symbolic-ref","HEAD",`refs/heads/${i}`],{cwd:e})):await P("git",["init",`--initial-branch=${i}`],{cwd:e}),await P("git",["add","."],{cwd:e}),await P("git",["commit","-m","Initial commit (create-instant-app)"],{cwd:e}),I.log("Git repository initialized successfully.",I.ciaModifier(null))}catch{}};import Ue from"env-paths";import*as We from"@clack/prompts";import{mkdir as De,readFile as Ve,writeFile as Le}from"node:fs/promises";import ze from"open";import{join as He}from"node:path";import{randomUUID as ie}from"node:crypto";import{version as Be}from"@instantdb/version";var oe=!!process.env.INSTANT_CLI_DEV,re=oe?"http://localhost:3000":"https://instantdb.com",U=process.env.INSTANT_CLI_API_URI||(oe?"http://localhost:8888":"https://api.instantdb.com");async function k({path:e,body:t,method:n="GET",authToken:o,metadata:i}){let r={"Content-Type":"application/json","X-Instant-Source":"create-instant-app","X-Instant-Version":Be,"X-Instant-Command":"create"};o&&(r.Authorization=`Bearer ${o}`),i&&(r["X-Instant-Metadata"]=JSON.stringify(i));let p=await fetch(`${U}${e}`,{method:n??"GET",headers:r,body:t?JSON.stringify(t):void 0,signal:AbortSignal.timeout(3e5)}),s;try{s=await p.json()}catch{s=null}if(!p.ok){let m=s.message||s.hint?.errors?.[0]?.message||"There was an error";throw new Error(m)}return s}import{renderUnwrap as O,UI as d}from"instant-cli/ui";var Je=!!process.env.INSTANT_CLI_DEV,Ke=!!process.env.INSTANT_CLI_FORCE_EPHEMERAL;function se(){let e=`instantdb-${Je?"dev":"prod"}`,{config:t}=Ue(e);return{authConfigFilePath:He(t,"a"),appConfigDirPath:t}}var Ye=async(e,t,n,o)=>{let i=ie(),a=ie();return await k({method:"POST",authToken:t,path:"/dash/apps",body:{id:i,title:e,admin_token:a,org_id:n},metadata:o}),{appID:i,adminToken:a,source:"created"}},pe=async e=>await k({method:"GET",path:"/dash",authToken:e}),le=async(e,t)=>await k({method:"GET",path:`/dash/orgs/${t}`,authToken:e});var Xe=async(e,t)=>{try{let n=await pe(e),o=n.apps.find(i=>i.id===t);if(o)return{appId:o.id,adminToken:o.admin_token};for(let i of n.orgs){let{apps:a}=await le(e,i.id),r=a.find(p=>p.id===t);if(r)return{appId:r.id,adminToken:r.admin_token}}return null}catch{return null}},qe=async(e,t)=>{try{return await k({method:"GET",path:`/dash/apps/${e}/schema/pull`,authToken:t}),!0}catch{return!1}},Ze=async()=>Ke?null:process.env.INSTANT_CLI_AUTH_TOKEN?process.env.INSTANT_CLI_AUTH_TOKEN:await Ve(se().authConfigFilePath,"utf-8").catch(()=>null),ae=async(e,t)=>{let n=await k({authToken:null,method:"POST",path:"/dash/apps/ephemeral",body:{title:e,rules:{$users:{view:"true"},$files:{allow:{view:"true",create:"true",delete:"true"}}}},metadata:t});return{appId:n.app.id,adminToken:n.app["admin-token"]}},ce=async(e,t)=>{let n=await Ze();if(e?.app){if(e.token){if(!await qe(e.app,e.token))throw new Error("Invalid app ID and token combination. Please verify both the app ID and token are correct.");return d.log(`Linking to app: ${e.app}`,d.ciaModifier(null)),{appId:e.app,adminToken:e.token,approach:"import"}}if(n){let r=await Xe(n,e.app);if(!r)throw new Error(`You don't have access to app "${e.app}". Please check the app ID or use --token to provide a token.`);return d.log(`Linking to app: ${e.app}`,d.ciaModifier(null)),{appId:r.appId,adminToken:r.adminToken,approach:"import"}}throw new Error(`You must be logged in or provide --token when using --app. Either run 'npx instant-cli login' first, or use: --app ${e.app} --token <token>`)}if(!n){let r=await O(new d.Select({promptText:"You are not logged in.",options:[{label:"Create temporary app",value:"ephemeral"},{label:"Login to choose existing app",value:"login"},{label:"Create app later",value:"skip"}],modifyOutput:d.ciaModifier()}));if(r==="login"){let p=await k({authToken:null,method:"POST",path:"/dash/cli/auth/register"}),{secret:s,ticket:m}=p;ze(`${re}/dash?ticket=${m}`);let _=et({secret:s}),w=await O(new d.Spinner({promise:_,workingText:"Waiting for login in browser",disappearWhenDone:!0,modifyOutput:d.ciaModifier(null)}));await tt(w.token),n=w.token}if(r==="skip")return d.log("Skipping app link step",d.ciaModifier(null)),null;if(r==="ephemeral"){let p=await O(new d.TextInput({defaultValue:"my-cool-app",prompt:"Enter a name for your temporary app:",placeholder:"my-cool-app",modifyOutput:d.ciaModifier()}));return{...await ae(p,t),approach:"ephemeral"}}}if(!n)return null;let o=await pe(n),i=o.orgs.filter(r=>r.role!=="app-member");return o.orgs=i,await O(new d.AppSelector({startingMenuIndex:0,allowCreate:!0,allowEphemeral:!0,api:{getDash(){return o},createEphemeralApp(r){return ae(r,t)},getAppsForOrg:async r=>{let{apps:p}=await le(n,r);return{apps:p}},createApp:async(r,p)=>{let{appID:s,adminToken:m}=await Ye(r,n,p,t);return{appId:s,adminToken:m}}},modifyOutput:d.ciaModifier()}))};function Qe(e){return new Promise(t=>setTimeout(t,e))}async function et({secret:e}){for(let t=1;t<=120;t++){await Qe(1e3);let n=await fetch(`${U}/dash/cli/auth/check`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({secret:e})});if(!(!n.ok&&(await n.json()).hint.errors?.[0]?.issue==="waiting-for-user")&&n.ok)return n.json()}throw new Error("Timed out waiting for login")}async function tt(e){let t=se();return await De(t.appConfigDirPath,{recursive:!0}),Le(t.authConfigFilePath,e,"utf-8")}import nt from"fs-extra";import ot from"path";var rt={"next-js-app-dir":"NEXT_PUBLIC_INSTANT_APP_ID","vite-vanilla":"VITE_INSTANT_APP_ID",expo:"EXPO_PUBLIC_INSTANT_APP_ID"},de=(e,t,n,o)=>{let i=ot.join(t,".env"),r=`${rt[e.base]}=${n}
14
+ INSTANT_APP_ADMIN_TOKEN=${o}`;nt.writeFileSync(i,r)};import{stdin as T,stdout as ue}from"process";import{setRawModeWindowsFriendly as me}from"instant-cli/ui";async function it(){return new Promise(e=>{if(!ue.isTTY||!T.isTTY){e(null);return}let t=T.isRaw;t||me(T,!0);let n=setTimeout(()=>{i(),e(null)},100),o="",i=()=>{clearTimeout(n),T.removeListener("data",a),!t&&T.isTTY&&me(T,!1)},a=r=>{let p=r.toString();o+=p;let s=o.match(/\x1b\]11;rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)(?:\x1b\\|\x07)/);if(s){i();let[,m,_,w]=s;e(`rgb:${m}/${_}/${w}`)}};T.on("data",a),ue.write("\x1B]11;?\x1B\\")})}function at(e){let t=e.match(/rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)/);if(!t)return null;let[,n,o,i]=t,a=Math.round(parseInt(n,16)/257),r=Math.round(parseInt(o,16)/257),p=Math.round(parseInt(i,16)/257);return{r:a,g:r,b:p}}function st(e){return(.299*e.r+.587*e.g+.114*e.b)/255>.5}async function fe(){try{let e=await it();if(!e)return"unknown";let t=at(e);return t?st(t)?"light":"dark":"unknown"}catch(e){return console.error("Error detecting terminal theme:",e),"unknown"}}import N from"chalk";var v=(e,t)=>e==="light"?N.bgYellowBright(t):N.bgBlackBright(t),ge=(e,t=console.log,n=!1)=>{let o=(process.stdout.columns||80)-4,i=e.split(`
15
+ `),a=!0;i.forEach(r=>{if(r.length===0){a?(t(""),a=!1):console.log(N.gray("\u2502"));return}for(let p=0;p<r.length;p+=o){let s=r.slice(p,p+o);p+o<r.length&&s.length===o&&(s=s+"-"),a?(t(s),a=!1):console.log(N.gray("\u2502 ")+s)}}),n&&console.log(N.gray("\u2502"))};var E="\x1B[?25h";import{execa as ct}from"execa";var dt=async()=>{process.argv.some(w=>["-h","--help","--version","-V"].includes(w))||J();let e=await fe(),{project:t,appFlags:n}=await z(),[o,i]=L(t.appName),a=x(),r=await Y(t,i);q({projectDir:r,ruleFilesToAdd:t.ruleFiles});let p={template:t.base,aiTool:t.ruleFiles??"none",usedAiPrompt:!!t.prompt},s=await ce(n,p);s&&de(t,r,s.appId,s.adminToken),await X(x(),r);let m=we.readJSONSync(he.join(r,"package.json"));if(m.name=o,a!=="bun"){let{stdout:w}=await ct(a,["-v"],{cwd:r});m.packageManager=`${a}@${w.trim()}`}we.writeJSONSync(he.join(r,"package.json"),m,{spaces:2}),t.createRepo&&await ne(r),t.prompt&&(await W(t.prompt,r),process.stdout.write(E)),pt("Done!");let _=t.base==="expo"?"start":"dev";s?(console.log(`
16
16
  \u{1F389} Success! Your project is ready to go!
17
17
 
18
18
  To get started:
19
- 1. ${v(e,"cd "+a)}
20
- 2. ${v(e,y()+" run "+T)}
19
+ 1. ${v(e,"cd "+i)}
20
+ 2. ${v(e,x()+" run "+_)}
21
21
  `),s.approach==="ephemeral"&&console.log(`
22
22
  An ephemeral app has been created and added to your .env file.
23
23
  It will expire in two weeks. For a permanent app, sign in and use ${v(e,"npx instant-cli claim")}
@@ -25,8 +25,8 @@ INSTANT_APP_ADMIN_TOKEN=${o}`;tt.writeFileSync(a,i)};import{stdin as b,stdout as
25
25
  \u{1F389} Success! Your project is ready to go!
26
26
 
27
27
  To get started:
28
- 1. ${v(e,"cd "+a)}
29
- 2. Create a new app on ${pt.underline("www.instantdb.com")}
28
+ 1. ${v(e,"cd "+i)}
29
+ 2. Create a new app on ${lt.underline("www.instantdb.com")}
30
30
  3. Add your APP_ID to the .env file
31
- 4. ${v(e,y()+" run "+T)}
32
- `)};ct().catch(e=>{we.error("Aborting installation..."),fe(e.message,we.error),process.stdout.write(O),process.exit(1)});process.on("SIGINT",()=>{process.stdout.write(O),process.exit(0)});
31
+ 4. ${v(e,x()+" run "+_)}
32
+ `)};dt().catch(e=>{ye.error("Aborting installation..."),ge(e.message,ye.error),process.stdout.write(E),process.exit(1)});process.on("SIGINT",()=>{process.stdout.write(E),process.exit(0)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-instant-app",
3
- "version": "0.22.95",
3
+ "version": "0.22.96-experimental.add-posthog-frontend.20386914944.1",
4
4
  "description": "Scaffold a new web/mobile app with InstantDB",
5
5
  "homepage": "https://github.com/instantdb/instant/tree/main/client/packages/create-instant-app",
6
6
  "repository": {
@@ -33,8 +33,8 @@
33
33
  "ora": "6.3.1",
34
34
  "slugify": "^1.6.6",
35
35
  "sort-package-json": "^2.10.0",
36
- "@instantdb/version": "0.22.95",
37
- "instant-cli": "0.22.95"
36
+ "@instantdb/version": "0.22.96-experimental.add-posthog-frontend.20386914944.1",
37
+ "instant-cli": "0.22.96-experimental.add-posthog-frontend.20386914944.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@anthropic-ai/sdk": "^0.60.0",