@vaiftech/cli 1.6.0 → 1.6.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.
package/README.md CHANGED
@@ -268,11 +268,15 @@ export default async function handler(req, ctx) {
268
268
 
269
269
  ## Environment Variables
270
270
 
271
+ The CLI automatically loads `.env` files from the current directory. You can set these variables in your `.env` or export them in your shell:
272
+
271
273
  | Variable | Description |
272
274
  |----------|-------------|
273
275
  | `VAIF_API_URL` | API base URL (default: `https://api.vaif.studio`) |
274
276
  | `VAIF_TOKEN` | API token (alternative to `vaif login`) |
275
- | `VAIF_PROJECT_ID` | Default project ID |
277
+ | `VAIF_PROJECT_ID` | Default project ID (also read from `vaif.config.json`) |
278
+
279
+ Project ID resolution order: `--project-id` flag > `vaif.config.json` > `VAIF_PROJECT_ID` env var > login session.
276
280
 
277
281
  ## Related Packages
278
282
 
@@ -1,4 +1,4 @@
1
- import g from'fs';import w from'path';import M from'dotenv';import K from'pg';import z from'ora';import r from'chalk';import q from'prettier';import V from'readline';M.config();async function U(n){let t=w.resolve(n);if(!g.existsSync(t))return null;try{let a=g.readFileSync(t,"utf-8"),e=JSON.parse(a);return e.database?.url&&(e.database.url=N(e.database.url)),e.api?.apiKey&&(e.api.apiKey=N(e.api.apiKey)),e}catch{throw new Error(`Failed to parse config file: ${n}`)}}function N(n){return n.replace(/\$\{([^}]+)\}/g,(t,a)=>process.env[a]||t)}async function B(n,t){let a=await n.query(`
1
+ import g from'fs';import w from'path';import M from'dotenv';import K from'pg';import z from'ora';import r from'chalk';import q from'prettier';import L from'readline';M.config();async function U(n){let t=w.resolve(n);if(!g.existsSync(t))return null;try{let a=g.readFileSync(t,"utf-8"),e=JSON.parse(a);return e.database?.url&&(e.database.url=N(e.database.url)),e.api?.apiKey&&(e.api.apiKey=N(e.api.apiKey)),e}catch{throw new Error(`Failed to parse config file: ${n}`)}}function N(n){return n.replace(/\$\{([^}]+)\}/g,(t,a)=>process.env[a]||t)}async function B(n,t){let a=await n.query(`
2
2
  SELECT table_name, table_type
3
3
  FROM information_schema.tables
4
4
  WHERE table_schema = $1
@@ -44,7 +44,7 @@ import g from'fs';import w from'path';import M from'dotenv';import K from'pg';im
44
44
  JOIN pg_namespace n ON n.oid = t.typnamespace
45
45
  WHERE n.nspname = $1
46
46
  ORDER BY t.typname, e.enumsortorder
47
- `,[t]),c=new Map;for(let l of a.rows)c.set(l.table_name,[]);for(let l of e.rows){let i=c.get(l.table_name);i&&i.push(l);}let d=new Map;for(let l of s.rows){let i=d.get(l.enum_name)||[];i.push(l.enum_value),d.set(l.enum_name,i);}return {tables:c,enums:d,foreignKeys:o.rows}}var T={smallint:"number",integer:"number",bigint:"string",int2:"number",int4:"number",int8:"string",decimal:"string",numeric:"string",real:"number",float4:"number",float8:"number","double precision":"number",money:"string",boolean:"boolean",bool:"boolean",text:"string",varchar:"string",char:"string",character:"string","character varying":"string",name:"string",citext:"string",date:"string",time:"string",timetz:"string","time without time zone":"string","time with time zone":"string",timestamp:"string",timestamptz:"string","timestamp without time zone":"string","timestamp with time zone":"string",interval:"string",bytea:"Buffer",uuid:"string",json:"unknown",jsonb:"unknown",inet:"string",cidr:"string",macaddr:"string",macaddr8:"string",point:"{ x: number; y: number }",line:"string",lseg:"string",box:"string",path:"string",polygon:"string",circle:"string",ARRAY:"unknown[]"};function Y(n,t){let{data_type:a,udt_name:e,is_nullable:o}=n;if(t.has(e)){let d=t.get(e).map(l=>`"${l}"`).join(" | ");return o==="YES"?`(${d}) | null`:d}if(a==="ARRAY"){let c=e.replace(/^_/,"");if(t.has(c)){let i=t.get(c).map(u=>`"${u}"`).join(" | ");return o==="YES"?`(${i})[] | null`:`(${i})[]`}let d=T[c]||"unknown";return o==="YES"?`${d}[] | null`:`${d}[]`}let s=T[a]||T[e]||"unknown";return o==="YES"&&(s=`${s} | null`),s}function x(n){return n.split(/[_\-\s]+/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function $(n,t){let a=x(n),e=t.map(o=>` | "${o}"`).join(`
47
+ `,[t]),c=new Map;for(let l of a.rows)c.set(l.table_name,[]);for(let l of e.rows){let i=c.get(l.table_name);i&&i.push(l);}let d=new Map;for(let l of s.rows){let i=d.get(l.enum_name)||[];i.push(l.enum_value),d.set(l.enum_name,i);}return {tables:c,enums:d,foreignKeys:o.rows}}var S={smallint:"number",integer:"number",bigint:"string",int2:"number",int4:"number",int8:"string",decimal:"string",numeric:"string",real:"number",float4:"number",float8:"number","double precision":"number",money:"string",boolean:"boolean",bool:"boolean",text:"string",varchar:"string",char:"string",character:"string","character varying":"string",name:"string",citext:"string",date:"string",time:"string",timetz:"string","time without time zone":"string","time with time zone":"string",timestamp:"string",timestamptz:"string","timestamp without time zone":"string","timestamp with time zone":"string",interval:"string",bytea:"Buffer",uuid:"string",json:"unknown",jsonb:"unknown",inet:"string",cidr:"string",macaddr:"string",macaddr8:"string",point:"{ x: number; y: number }",line:"string",lseg:"string",box:"string",path:"string",polygon:"string",circle:"string",ARRAY:"unknown[]"};function Y(n,t){let{data_type:a,udt_name:e,is_nullable:o}=n;if(t.has(e)){let d=t.get(e).map(l=>`"${l}"`).join(" | ");return o==="YES"?`(${d}) | null`:d}if(a==="ARRAY"){let c=e.replace(/^_/,"");if(t.has(c)){let i=t.get(c).map(u=>`"${u}"`).join(" | ");return o==="YES"?`(${i})[] | null`:`(${i})[]`}let d=S[c]||"unknown";return o==="YES"?`${d}[] | null`:`${d}[]`}let s=S[a]||S[e]||"unknown";return o==="YES"&&(s=`${s} | null`),s}function x(n){return n.split(/[_\-\s]+/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function $(n,t){let a=x(n),e=t.map(o=>` | "${o}"`).join(`
48
48
  `);return `export type ${a} =
49
49
  ${e};`}function G(n,t,a){let e=x(n),o=[],s=[],c=[];for(let u of t){let f=Y(u,a),p=u.column_name,h=u.column_default!==null||u.is_identity==="YES",y=u.is_nullable==="YES";o.push(` ${p}: ${f};`),h||u.column_name==="id"?s.push(` ${p}?: ${f.replace(" | null","")} | null;`):y?s.push(` ${p}?: ${f};`):s.push(` ${p}: ${f.replace(" | null","")};`),c.push(` ${p}?: ${f.replace(" | null","")} | null;`);}let d=`export interface ${e} {
50
50
  ${o.join(`
@@ -81,6 +81,7 @@ Make sure your database is running and accessible.`))),process.exit(1);}}var b=[
81
81
  "@types/node": "^22.0.0",
82
82
  "@types/react": "^19.0.0",
83
83
  "@types/react-dom": "^19.0.0",
84
+ "drizzle-kit": "^0.30.0",
84
85
  "typescript": "^5.7.0"
85
86
  }
86
87
  }
@@ -150,18 +151,17 @@ body {
150
151
  -webkit-font-smoothing: antialiased;
151
152
  -moz-osx-font-smoothing: grayscale;
152
153
  }
153
- `},{path:"lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
154
- import { createServerClient } from "@vaiftech/client/server";
154
+ `},{path:"lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
155
155
 
156
156
  // Browser client \u2013 safe to use in Client Components
157
- export const vaif = createClient({
157
+ export const vaif = createVaifClient({
158
158
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
159
159
  apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
160
160
  });
161
161
 
162
162
  // Server client \u2013 use in Server Components, Route Handlers, Server Actions
163
163
  export function createVaifServer() {
164
- return createServerClient({
164
+ return createVaifClient({
165
165
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
166
166
  secretKey: process.env.VAIF_SECRET_KEY!,
167
167
  });
@@ -274,7 +274,7 @@ A full-stack Next.js application powered by [VAIF Studio](https://vaif.studio),
274
274
 
275
275
  Full documentation is available at <https://docs.vaif.studio>.
276
276
  `}],featureFiles:{auth:[{path:"middleware.ts",content:`import { NextResponse, type NextRequest } from "next/server";
277
- import { createServerClient } from "@vaiftech/client/server";
277
+ import { createVaifClient } from "@vaiftech/client";
278
278
  import { authMiddleware } from "@vaiftech/auth/nextjs";
279
279
 
280
280
  const protectedRoutes = ["/dashboard", "/settings", "/api/protected"];
@@ -284,7 +284,7 @@ export async function middleware(request: NextRequest) {
284
284
  const isProtected = protectedRoutes.some((route) => pathname.startsWith(route));
285
285
  if (!isProtected) return NextResponse.next();
286
286
 
287
- const vaif = createServerClient({
287
+ const vaif = createVaifClient({
288
288
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
289
289
  secretKey: process.env.VAIF_SECRET_KEY!,
290
290
  });
@@ -552,9 +552,11 @@ export const posts = pgTable("posts", {
552
552
  "react-router-dom": "^7.0.0"
553
553
  },
554
554
  "devDependencies": {
555
+ "@types/node": "^22.0.0",
555
556
  "@types/react": "^19.0.0",
556
557
  "@types/react-dom": "^19.0.0",
557
558
  "@vitejs/plugin-react": "^4.4.0",
559
+ "drizzle-kit": "^0.30.0",
558
560
  "typescript": "^5.7.0",
559
561
  "vite": "^6.0.0"
560
562
  }
@@ -642,9 +644,9 @@ function Home() {
642
644
  </div>
643
645
  );
644
646
  }
645
- `},{path:"src/lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
647
+ `},{path:"src/lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
646
648
 
647
- export const vaif = createClient({
649
+ export const vaif = createVaifClient({
648
650
  projectId: import.meta.env.VITE_VAIF_PROJECT_ID,
649
651
  apiKey: import.meta.env.VITE_VAIF_API_KEY,
650
652
  });
@@ -1269,7 +1271,9 @@ Full documentation is available at <https://docs.vaif.studio>.
1269
1271
  "react-native": "~0.76.0"
1270
1272
  },
1271
1273
  "devDependencies": {
1274
+ "@types/node": "^22.0.0",
1272
1275
  "@types/react": "^19.0.0",
1276
+ "drizzle-kit": "^0.30.0",
1273
1277
  "typescript": "^5.7.0"
1274
1278
  }
1275
1279
  }
@@ -2593,9 +2597,9 @@ func HelloHandler(w http.ResponseWriter, r *http.Request) {
2593
2597
  Message: fmt.Sprintf("Hello, %s!", req.Name),
2594
2598
  })
2595
2599
  }
2596
- `}]},postInstructions:["go mod tidy","# Copy .env.example to .env and add your VAIF credentials","go run main.go"]},"todo-app":{name:"Todo App",description:"Simple React todo app \u2013 great for learning VAIF basics",tag:"React Starter",defaultFeatures:["database"],files:[{path:"src/lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
2600
+ `}]},postInstructions:["go mod tidy","# Copy .env.example to .env and add your VAIF credentials","go run main.go"]},"todo-app":{name:"Todo App",description:"Simple React todo app \u2013 great for learning VAIF basics",tag:"React Starter",defaultFeatures:["database"],files:[{path:"src/lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
2597
2601
 
2598
- export const vaif = createClient({
2602
+ export const vaif = createVaifClient({
2599
2603
  projectId: import.meta.env.VITE_VAIF_PROJECT_ID,
2600
2604
  apiKey: import.meta.env.VITE_VAIF_API_KEY,
2601
2605
  });
@@ -2784,9 +2788,9 @@ export const posts = pgTable("posts", {
2784
2788
 
2785
2789
  return Response.json({ message: \`Hello, \${name}!\` });
2786
2790
  }
2787
- `}]},dependencies:["@vaiftech/client","@vaiftech/react"],postInstructions:["Copy .env.example to .env and fill in your project credentials","Create a 'todos' table in your VAIF dashboard with columns: id (uuid), title (text), done (boolean), created_at (timestamptz)","Import helpers from './lib/vaif' in your components","Run: npx vaif generate to generate TypeScript types"]},"realtime-chat":{name:"Realtime Chat",description:"React chat app with VAIF realtime subscriptions for live messaging",tag:"React + Realtime",defaultFeatures:["database","realtime","auth"],files:[{path:"src/lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
2791
+ `}]},dependencies:["@vaiftech/client","@vaiftech/react"],postInstructions:["Copy .env.example to .env and fill in your project credentials","Create a 'todos' table in your VAIF dashboard with columns: id (uuid), title (text), done (boolean), created_at (timestamptz)","Import helpers from './lib/vaif' in your components","Run: npx vaif generate to generate TypeScript types"]},"realtime-chat":{name:"Realtime Chat",description:"React chat app with VAIF realtime subscriptions for live messaging",tag:"React + Realtime",defaultFeatures:["database","realtime","auth"],files:[{path:"src/lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
2788
2792
 
2789
- export const vaif = createClient({
2793
+ export const vaif = createVaifClient({
2790
2794
  projectId: import.meta.env.VITE_VAIF_PROJECT_ID,
2791
2795
  apiKey: import.meta.env.VITE_VAIF_API_KEY,
2792
2796
  realtime: {
@@ -3083,18 +3087,17 @@ export const posts = pgTable("posts", {
3083
3087
 
3084
3088
  return Response.json({ message: \`Hello, \${name}!\` });
3085
3089
  }
3086
- `}]},dependencies:["@vaiftech/client","@vaiftech/react"],postInstructions:["Copy .env.example to .env and fill in your project credentials","Create a 'messages' table with columns: id (uuid), content (text), user_id (text), username (text), channel_id (text), created_at (timestamptz)","Enable Realtime on the messages table in your VAIF dashboard","Use the useRealtimeMessages hook in your components","Run: npx vaif generate to generate TypeScript types"]},"saas-starter":{name:"SaaS Starter",description:"Full SaaS starter with VAIF auth, team/org support, and server-side helpers",tag:"Next.js SaaS",defaultFeatures:["database","auth","functions"],files:[{path:"lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
3087
- import { createServerClient } from "@vaiftech/client/server";
3090
+ `}]},dependencies:["@vaiftech/client","@vaiftech/react"],postInstructions:["Copy .env.example to .env and fill in your project credentials","Create a 'messages' table with columns: id (uuid), content (text), user_id (text), username (text), channel_id (text), created_at (timestamptz)","Enable Realtime on the messages table in your VAIF dashboard","Use the useRealtimeMessages hook in your components","Run: npx vaif generate to generate TypeScript types"]},"saas-starter":{name:"SaaS Starter",description:"Full SaaS starter with VAIF auth, team/org support, and server-side helpers",tag:"Next.js SaaS",defaultFeatures:["database","auth","functions"],files:[{path:"lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
3088
3091
 
3089
3092
  // Browser client \u2013 use in Client Components
3090
- export const vaif = createClient({
3093
+ export const vaif = createVaifClient({
3091
3094
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
3092
3095
  apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
3093
3096
  });
3094
3097
 
3095
3098
  // Server client \u2013 use in Server Components, Route Handlers, Server Actions
3096
3099
  export function createVaifServer() {
3097
- return createServerClient({
3100
+ return createVaifClient({
3098
3101
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
3099
3102
  secretKey: process.env.VAIF_SECRET_KEY!,
3100
3103
  });
@@ -3394,18 +3397,17 @@ export const posts = pgTable("posts", {
3394
3397
 
3395
3398
  return Response.json({ message: \`Hello, \${name}!\` });
3396
3399
  }
3397
- `}]},dependencies:["@vaiftech/client","@vaiftech/auth","@vaiftech/react"],postInstructions:["Copy .env.example to .env.local and fill in your project credentials","Create 'teams' and 'team_members' tables in your VAIF dashboard","Import auth helpers from '@/lib/auth' in your Server Components/Actions","Use requireUser() for authenticated routes and requireTeamRole() for role checks","Run: npx vaif generate to generate TypeScript types"]},"ecommerce-api":{name:"E-commerce API",description:"API-first e-commerce setup with VAIF storage for product images",tag:"Next.js E-commerce",defaultFeatures:["database","auth","storage"],files:[{path:"lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
3398
- import { createServerClient } from "@vaiftech/client/server";
3400
+ `}]},dependencies:["@vaiftech/client","@vaiftech/auth","@vaiftech/react"],postInstructions:["Copy .env.example to .env.local and fill in your project credentials","Create 'teams' and 'team_members' tables in your VAIF dashboard","Import auth helpers from '@/lib/auth' in your Server Components/Actions","Use requireUser() for authenticated routes and requireTeamRole() for role checks","Run: npx vaif generate to generate TypeScript types"]},"ecommerce-api":{name:"E-commerce API",description:"API-first e-commerce setup with VAIF storage for product images",tag:"Next.js E-commerce",defaultFeatures:["database","auth","storage"],files:[{path:"lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
3399
3401
 
3400
3402
  // Browser client
3401
- export const vaif = createClient({
3403
+ export const vaif = createVaifClient({
3402
3404
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
3403
3405
  apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
3404
3406
  });
3405
3407
 
3406
3408
  // Server client
3407
3409
  export function createVaifServer() {
3408
- return createServerClient({
3410
+ return createVaifClient({
3409
3411
  projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID!,
3410
3412
  secretKey: process.env.VAIF_SECRET_KEY!,
3411
3413
  });
@@ -3665,14 +3667,14 @@ export const posts = pgTable("posts", {
3665
3667
 
3666
3668
  return Response.json({ message: \`Hello, \${name}!\` });
3667
3669
  }
3668
- `}]},dependencies:["@vaiftech/client","@vaiftech/auth"],postInstructions:["Copy .env.example to .env.local and fill in your project credentials","Create a 'product-images' storage bucket in your VAIF dashboard","Import storage helpers from '@/lib/storage' in your API routes","Use uploadProductImage() in your product creation flow","Run: npx vaif generate to generate TypeScript types"]}};function ve(){console.log(""),console.log(r.bold("Available project templates")),console.log("");let n=26,t=22;console.log(` ${r.gray("Template".padEnd(n))}${r.gray("Stack".padEnd(t))}${r.gray("Description")}`),console.log(r.gray(" "+"-".repeat(n+t+40)));for(let[a,e]of Object.entries(D))console.log(` ${r.cyan(a.padEnd(n))}${r.yellow(e.tag.padEnd(t))}${r.white(e.description)}`);console.log(""),console.log(r.gray("Usage:")),console.log(r.gray(" npx @vaiftech/cli init --template <name>")),console.log(r.gray(" npx @vaiftech/cli init -t nextjs-fullstack")),console.log(r.gray(" npx @vaiftech/cli init -t react-spa --features auth,database,realtime")),console.log(""),console.log(r.gray("Available features: auth, database, realtime, storage, functions")),console.log("");}async function W(n){if(!process.stdin.isTTY||!process.stdout.isTTY)return n;let t=new Set(n.map(e=>b.findIndex(o=>o.name===e)).filter(e=>e>=0)),a=0;return new Promise(e=>{let o=V.createInterface({input:process.stdin,output:process.stdout});V.emitKeypressEvents(process.stdin,o),process.stdin.setRawMode&&process.stdin.setRawMode(true);function s(){let d=b.length+2;process.stdout.write(`\x1B[${d}A`),c();}function c(){console.log(r.bold(`
3669
- ? Which VAIF features do you want to include?`)),b.forEach((d,l)=>{let i=t.has(l)?r.green("[x]"):"[ ]",u=l===a?r.cyan("> "):" ";console.log(`${u}${i} ${d.label} ${r.gray(`(${d.description})`)}`);}),console.log(r.gray(" (up/down to move, space to toggle, enter to confirm)"));}c(),process.stdin.on("keypress",(d,l)=>{if(l.name==="up"&&a>0)a--,s();else if(l.name==="down"&&a<b.length-1)a++,s();else if(l.name==="space")t.has(a)?t.delete(a):t.add(a),s();else if(l.name==="return"){process.stdin.setRawMode&&process.stdin.setRawMode(false),o.close();let i=[...t].sort().map(u=>b[u].name);e(i.length>0?i:n);}else l.name==="c"&&l.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),o.close(),process.exit(0));});})}async function j(n,t={}){let a=D[n];a||(console.log(r.red(`
3670
+ `}]},dependencies:["@vaiftech/client","@vaiftech/auth"],postInstructions:["Copy .env.example to .env.local and fill in your project credentials","Create a 'product-images' storage bucket in your VAIF dashboard","Import storage helpers from '@/lib/storage' in your API routes","Use uploadProductImage() in your product creation flow","Run: npx vaif generate to generate TypeScript types"]}};function ve(){console.log(""),console.log(r.bold("Available project templates")),console.log("");let n=26,t=22;console.log(` ${r.gray("Template".padEnd(n))}${r.gray("Stack".padEnd(t))}${r.gray("Description")}`),console.log(r.gray(" "+"-".repeat(n+t+40)));for(let[a,e]of Object.entries(D))console.log(` ${r.cyan(a.padEnd(n))}${r.yellow(e.tag.padEnd(t))}${r.white(e.description)}`);console.log(""),console.log(r.gray("Usage:")),console.log(r.gray(" npx @vaiftech/cli init --template <name>")),console.log(r.gray(" npx @vaiftech/cli init -t nextjs-fullstack")),console.log(r.gray(" npx @vaiftech/cli init -t react-spa --features auth,database,realtime")),console.log(""),console.log(r.gray("Available features: auth, database, realtime, storage, functions")),console.log("");}async function W(n){if(!process.stdin.isTTY||!process.stdout.isTTY)return n;let t=new Set(n.map(e=>b.findIndex(o=>o.name===e)).filter(e=>e>=0)),a=0;return new Promise(e=>{let o=L.createInterface({input:process.stdin,output:process.stdout});L.emitKeypressEvents(process.stdin,o),process.stdin.setRawMode&&process.stdin.setRawMode(true);function s(){let d=b.length+2;process.stdout.write(`\x1B[${d}A`),c();}function c(){console.log(r.bold(`
3671
+ ? Which VAIF features do you want to include?`)),b.forEach((d,l)=>{let i=t.has(l)?r.green("[x]"):"[ ]",u=l===a?r.cyan("> "):" ";console.log(`${u}${i} ${d.label} ${r.gray(`(${d.description})`)}`);}),console.log(r.gray(" (up/down to move, space to toggle, enter to confirm)"));}c(),process.stdin.on("keypress",(d,l)=>{if(l.name==="up"&&a>0)a--,s();else if(l.name==="down"&&a<b.length-1)a++,s();else if(l.name==="space")t.has(a)?t.delete(a):t.add(a),s();else if(l.name==="return"){process.stdin.setRawMode&&process.stdin.setRawMode(false),o.close();let i=[...t].sort().map(u=>b[u].name);e(i.length>0?i:n);}else l.name==="c"&&l.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),o.close(),process.exit(0));});})}async function k(n,t={}){let a=D[n];a||(console.log(r.red(`
3670
3672
  Unknown template: ${n}`)),console.log(r.yellow(`Run 'vaif templates' to see available templates.
3671
- `)),process.exit(1));let e;t.features&&t.features.length>0?e=t.features.filter(i=>b.some(u=>u.name===i)):a.featureFiles&&Object.keys(a.featureFiles).length>0?e=await W(a.defaultFeatures??["database","auth"]):e=a.defaultFeatures??[],console.log(""),console.log(r.bold(`Scaffolding ${r.cyan(a.name)} template...`)),e.length>0&&console.log(r.gray(` Features: ${e.join(", ")}`)),console.log("");let o=[...a.files];if(a.featureFiles)for(let i of e){let u=a.featureFiles[i];u&&o.push(...u);}let s=0,c=0;for(let i of o){let u=w.resolve(i.path),f=w.dirname(u);if(g.existsSync(f)||g.mkdirSync(f,{recursive:true}),i.path==="package.json"&&g.existsSync(u)&&!t.force)try{let p=JSON.parse(g.readFileSync(u,"utf-8")),h=JSON.parse(i.content),y=P=>{if(!P)return {};let R={};for(let[k,A]of Object.entries(P))!A.startsWith("workspace:")&&!A.startsWith("link:")&&!A.startsWith("file:")&&(R[k]=A);return R};p.dependencies={...y(p.dependencies),...h.dependencies||{}},p.devDependencies={...y(p.devDependencies),...h.devDependencies||{}},h.scripts&&(p.scripts={...p.scripts||{},...h.scripts}),g.writeFileSync(u,JSON.stringify(p,null,2)+`
3673
+ `)),process.exit(1));let e;t.features&&t.features.length>0?e=t.features.filter(i=>b.some(u=>u.name===i)):a.featureFiles&&Object.keys(a.featureFiles).length>0?e=await W(a.defaultFeatures??["database","auth"]):e=a.defaultFeatures??[],console.log(""),console.log(r.bold(`Scaffolding ${r.cyan(a.name)} template...`)),e.length>0&&console.log(r.gray(` Features: ${e.join(", ")}`)),console.log("");let o=[...a.files];if(a.featureFiles)for(let i of e){let u=a.featureFiles[i];u&&o.push(...u);}let s=0,c=0;for(let i of o){let u=w.resolve(i.path),f=w.dirname(u);if(g.existsSync(f)||g.mkdirSync(f,{recursive:true}),i.path==="package.json"&&g.existsSync(u)&&!t.force)try{let p=JSON.parse(g.readFileSync(u,"utf-8")),h=JSON.parse(i.content),y=P=>{if(!P)return {};let R={};for(let[j,A]of Object.entries(P))!A.startsWith("workspace:")&&!A.startsWith("link:")&&!A.startsWith("file:")&&(R[j]=A);return R};p.dependencies={...y(p.dependencies),...h.dependencies||{}},p.devDependencies={...y(p.devDependencies),...h.devDependencies||{}},h.scripts&&(p.scripts={...p.scripts||{},...h.scripts}),g.writeFileSync(u,JSON.stringify(p,null,2)+`
3672
3674
  `,"utf-8"),console.log(r.green(` merge ${i.path} (added dependencies)`)),s++;continue}catch{}if(g.existsSync(u)&&!t.force){console.log(r.yellow(` skip ${i.path} (already exists)`)),c++;continue}g.writeFileSync(u,i.content,"utf-8"),console.log(r.green(` create ${i.path}`)),s++;}console.log(""),s>0&&console.log(r.green(`Created ${s} file${s!==1?"s":""}.`)),c>0&&console.log(r.yellow(`Skipped ${c} file${c!==1?"s":""} (use --force to overwrite).`));let d={auth:{"@vaiftech/auth":"^1.0.0"},database:{},realtime:{},storage:{},functions:{}},l=w.resolve("package.json");if(g.existsSync(l)&&e.length>0)try{let i=JSON.parse(g.readFileSync(l,"utf-8")),u=!1;for(let f of e){let p=d[f];if(p)for(let[h,y]of Object.entries(p))i.dependencies?.[h]||(i.dependencies=i.dependencies||{},i.dependencies[h]=y,u=!0);}u&&g.writeFileSync(l,JSON.stringify(i,null,2)+`
3673
- `,"utf-8");}catch{}(a.dependencies?.length||a.devDependencies?.length)&&(console.log(""),console.log(r.bold("Install dependencies:")),a.dependencies?.length&&console.log(r.cyan(` npm install ${a.dependencies.join(" ")}`)),a.devDependencies?.length&&console.log(r.cyan(` npm install -D ${a.devDependencies.join(" ")}`))),console.log(""),console.log(r.bold.green("Project scaffolded successfully!")),console.log(""),console.log(r.bold(" Next steps:")),a.postInstructions.forEach(i=>{console.log(r.gray(` ${i}`));}),console.log(""),console.log(r.gray(" Get your project credentials at https://vaif.studio/app/security/api-keys")),console.log("");}var X={$schema:"https://vaif.studio/schemas/config.json",projectId:"",database:{url:"${DATABASE_URL}",schema:"public"},types:{output:"./src/types/database.ts"},api:{baseUrl:"https://api.vaif.studio"}};async function Te(n){let t=z("Initializing VAIF configuration...").start(),a=w.resolve("vaif.config.json");g.existsSync(a)&&!n.force&&(t.fail("vaif.config.json already exists"),console.log(r.yellow(`
3674
- Use --force to overwrite existing configuration.`)),process.exit(1));try{if(g.writeFileSync(a,JSON.stringify(X,null,2),"utf-8"),t.succeed("Created vaif.config.json"),n.template){let e=n.features?n.features.split(",").map(o=>o.trim()):void 0;await j(n.template,{force:n.force,features:e});}else {let e=w.resolve(".env.example");if(g.existsSync(e)||(g.writeFileSync(e,`# VAIF Configuration
3675
+ `,"utf-8");}catch{}(a.dependencies?.length||a.devDependencies?.length)&&(console.log(""),console.log(r.bold("Install dependencies:")),a.dependencies?.length&&console.log(r.cyan(` npm install ${a.dependencies.join(" ")}`)),a.devDependencies?.length&&console.log(r.cyan(` npm install -D ${a.devDependencies.join(" ")}`))),console.log(""),console.log(r.bold.green("Project scaffolded successfully!")),console.log(""),console.log(r.bold(" Next steps:")),a.postInstructions.forEach(i=>{console.log(r.gray(` ${i}`));}),console.log(""),console.log(r.gray(" Get your project credentials at https://vaif.studio/app/security/api-keys")),console.log("");}var X={$schema:"https://vaif.studio/schemas/config.json",projectId:"",database:{url:"${DATABASE_URL}",schema:"public"},types:{output:"./src/types/database.ts"},api:{baseUrl:"https://api.vaif.studio"}};async function Se(n){let t=z("Initializing VAIF configuration...").start(),a=w.resolve("vaif.config.json");g.existsSync(a)&&!n.force&&(t.fail("vaif.config.json already exists"),console.log(r.yellow(`
3676
+ Use --force to overwrite existing configuration.`)),process.exit(1));try{if(g.writeFileSync(a,JSON.stringify(X,null,2),"utf-8"),t.succeed("Created vaif.config.json"),n.template){let e=n.features?n.features.split(",").map(o=>o.trim()):void 0;await k(n.template,{force:n.force,features:e});}else {let e=w.resolve(".env.example");if(g.existsSync(e)||(g.writeFileSync(e,`# VAIF Configuration
3675
3677
  DATABASE_URL=postgresql://user:password@localhost:5432/database
3676
3678
  VAIF_API_KEY=your-api-key
3677
3679
  `,"utf-8"),console.log(r.gray("Created .env.example"))),n.typescript){let o=w.resolve("src/types");g.existsSync(o)||(g.mkdirSync(o,{recursive:!0}),console.log(r.gray("Created src/types directory")));}console.log(""),console.log(r.green("VAIF initialized successfully!")),console.log(""),console.log(r.gray("Next steps:")),console.log(r.gray(" 1. Update vaif.config.json with your project ID")),console.log(r.gray(" 2. Set DATABASE_URL in your environment")),console.log(r.gray(" 3. Run: npx vaif generate")),console.log("");}}catch(e){t.fail("Failed to initialize"),e instanceof Error&&console.error(r.red(`
3678
- Error: ${e.message}`)),process.exit(1);}}export{U as a,ue as b,ve as c,Te as d};
3680
+ Error: ${e.message}`)),process.exit(1);}}export{U as a,ue as b,ve as c,Se as d};