@vaiftech/cli 1.7.3 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@vaiftech/cli)](https://www.npmjs.com/package/@vaiftech/cli)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- Command-line tools for [VAIF Studio](https://vaif.studio) (v1.7.3) — scaffold full projects from templates with feature selection, browser-based authentication, manage schemas, deploy functions, generate TypeScript types, and more.
6
+ Command-line tools for [VAIF Studio](https://vaif.studio) (v1.7.5) — scaffold full projects from templates with feature selection, browser-based authentication, manage schemas, deploy functions, generate TypeScript types, and more.
7
7
 
8
8
  ## Installation
9
9
 
@@ -6,7 +6,7 @@ Timed out waiting for browser authentication.`)),console.log(c.gray("Try again o
6
6
  No email provided. Login cancelled.`)),process.exit(1));let n=await te(c.cyan(" Password: "));(!n||n.trim()==="")&&(console.log(c.red(`
7
7
  No password provided. Login cancelled.`)),process.exit(1));let e=P("Authenticating...").start();try{let r=await fetch(`${w}/auth/cli/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:t.trim(),password:n})}),o=await r.json();(!r.ok||!o.ok)&&(e.fail("Login failed"),console.log(c.red(`
8
8
  ${o.message||"Invalid email or password."}`)),process.exit(1));let l={token:o.accessToken,email:o.user?.email,projectId:a,expiresAt:new Date(Date.now()+o.expiresIn*1e3).toISOString()};B(l),e.succeed("Logged in successfully"),console.log(""),o.user?.email&&console.log(c.green(` Authenticated as: ${o.user.email}`)),console.log(c.gray(` Config saved to: ${I}`)),console.log("");}catch{e.fail("Failed to connect to VAIF API"),console.log(c.red(`
9
- Could not connect to VAIF API. Please try again later.`)),process.exit(1);}}async function Ne(a){console.log(""),console.log(c.bold("Welcome to VAIF CLI")),console.log(c.gray("Authenticate to access your VAIF projects")),console.log(""),a.email?await re(a.projectId):await oe(a.projectId),console.log(c.gray("You can now use VAIF CLI commands like:")),console.log(c.gray(" vaif pull - Pull remote schema")),console.log(c.gray(" vaif push - Push schema changes")),console.log(c.gray(" vaif generate - Generate TypeScript types")),console.log("");}async function Le(){y.existsSync(I)?(y.unlinkSync(I),console.log(c.green("Logged out successfully"))):console.log(c.yellow("Not currently logged in"));}async function Ue(){let a=R();(!a||!a.token)&&(console.log(c.yellow("Not logged in")),console.log(c.gray("Run `vaif login` to authenticate")),process.exit(1));let t=P("Checking authentication...").start(),{valid:n,email:e}=await ie(a.token);n||(t.fail("Session expired"),console.log(c.yellow(`
9
+ Could not connect to VAIF API. Please try again later.`)),process.exit(1);}}async function Le(a){console.log(""),console.log(c.bold("Welcome to VAIF CLI")),console.log(c.gray("Authenticate to access your VAIF projects")),console.log(""),a.email?await re(a.projectId):await oe(a.projectId),console.log(c.gray("You can now use VAIF CLI commands like:")),console.log(c.gray(" vaif pull - Pull remote schema")),console.log(c.gray(" vaif push - Push schema changes")),console.log(c.gray(" vaif generate - Generate TypeScript types")),console.log("");}async function Ne(){y.existsSync(I)?(y.unlinkSync(I),console.log(c.green("Logged out successfully"))):console.log(c.yellow("Not currently logged in"));}async function Ue(){let a=R();(!a||!a.token)&&(console.log(c.yellow("Not logged in")),console.log(c.gray("Run `vaif login` to authenticate")),process.exit(1));let t=P("Checking authentication...").start(),{valid:n,email:e}=await ie(a.token);n||(t.fail("Session expired"),console.log(c.yellow(`
10
10
  Your session has expired. Please login again.`)),process.exit(1)),t.succeed("Authenticated"),console.log(""),console.log(c.green(` Email: ${e||a.email||"Unknown"}`)),a.projectId&&console.log(c.green(` Project: ${a.projectId}`)),console.log("");}var ue=process.env.VAIF_API_URL||"https://api.vaif.studio";async function de(a,t){let n=await fetch(`${ue}/schema-engine/introspect/${t}`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"}});if(!n.ok){let u=await n.text();throw new Error(`API introspection failed: ${u}`)}let e=await n.json();if(!e.ok||!e.schemaExists)throw new Error("Project schema does not exist yet. Push a migration first with `vaif db push`.");let r=new Map,o=[];for(let u of e.tables){let s=u.columns.map(i=>({column_name:i.name,data_type:i.type,is_nullable:i.nullable?"YES":"NO",column_default:i.default,udt_name:i.type,is_identity:i.primaryKey&&i.default?.includes("gen_random_uuid")?"YES":"NO",character_maximum_length:null,numeric_precision:null,numeric_scale:null}));r.set(u.name,s);for(let i of u.foreignKeys)o.push({constraint_name:i.constraintName,table_name:u.name,column_name:i.columnName,foreign_table_name:i.refTable,foreign_column_name:i.refColumn});}return {tables:r,enums:new Map,foreignKeys:o}}async function pe(a,t){let n=await a.query(`
11
11
  SELECT table_name, table_type
12
12
  FROM information_schema.tables
@@ -53,9 +53,9 @@ Your session has expired. Please login again.`)),process.exit(1)),t.succeed("Aut
53
53
  JOIN pg_namespace n ON n.oid = t.typnamespace
54
54
  WHERE n.nspname = $1
55
55
  ORDER BY t.typname, e.enumsortorder
56
- `,[t]),l=new Map;for(let s of n.rows)l.set(s.table_name,[]);for(let s of e.rows){let i=l.get(s.table_name);i&&i.push(s);}let u=new Map;for(let s of o.rows){let i=u.get(s.enum_name)||[];i.push(s.enum_value),u.set(s.enum_name,i);}return {tables:l,enums:u,foreignKeys:r.rows}}var N={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 me(a,t){let{data_type:n,udt_name:e,is_nullable:r}=a;if(t.has(e)){let u=t.get(e).map(s=>`"${s}"`).join(" | ");return r==="YES"?`(${u}) | null`:u}if(n==="ARRAY"){let l=e.replace(/^_/,"");if(t.has(l)){let i=t.get(l).map(p=>`"${p}"`).join(" | ");return r==="YES"?`(${i})[] | null`:`(${i})[]`}let u=N[l]||"unknown";return r==="YES"?`${u}[] | null`:`${u}[]`}let o=N[n]||N[e]||"unknown";return r==="YES"&&(o=`${o} | null`),o}function L(a){return a.split(/[_\-\s]+/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function fe(a,t){let n=L(a),e=t.map(r=>` | "${r}"`).join(`
56
+ `,[t]),l=new Map;for(let s of n.rows)l.set(s.table_name,[]);for(let s of e.rows){let i=l.get(s.table_name);i&&i.push(s);}let u=new Map;for(let s of o.rows){let i=u.get(s.enum_name)||[];i.push(s.enum_value),u.set(s.enum_name,i);}return {tables:l,enums:u,foreignKeys:r.rows}}var L={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 me(a,t){let{data_type:n,udt_name:e,is_nullable:r}=a;if(t.has(e)){let u=t.get(e).map(s=>`"${s}"`).join(" | ");return r==="YES"?`(${u}) | null`:u}if(n==="ARRAY"){let l=e.replace(/^_/,"");if(t.has(l)){let i=t.get(l).map(p=>`"${p}"`).join(" | ");return r==="YES"?`(${i})[] | null`:`(${i})[]`}let u=L[l]||"unknown";return r==="YES"?`${u}[] | null`:`${u}[]`}let o=L[n]||L[e]||"unknown";return r==="YES"&&(o=`${o} | null`),o}function N(a){return a.split(/[_\-\s]+/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function fe(a,t){let n=N(a),e=t.map(r=>` | "${r}"`).join(`
57
57
  `);return `export type ${n} =
58
- ${e};`}function ge(a,t,n){let e=L(a),r=[],o=[],l=[];for(let p of t){let g=me(p,n),m=p.column_name,h=p.column_default!==null||p.is_identity==="YES",A=p.is_nullable==="YES";r.push(` ${m}: ${g};`),h||p.column_name==="id"?o.push(` ${m}?: ${g.replace(" | null","")} | null;`):A?o.push(` ${m}?: ${g};`):o.push(` ${m}: ${g.replace(" | null","")};`),l.push(` ${m}?: ${g.replace(" | null","")} | null;`);}let u=`export interface ${e} {
58
+ ${e};`}function ge(a,t,n){let e=N(a),r=[],o=[],l=[];for(let p of t){let g=me(p,n),m=p.column_name,h=p.column_default!==null||p.is_identity==="YES",A=p.is_nullable==="YES";r.push(` ${m}: ${g};`),h||p.column_name==="id"?o.push(` ${m}?: ${g.replace(" | null","")} | null;`):A?o.push(` ${m}?: ${g};`):o.push(` ${m}: ${g.replace(" | null","")};`),l.push(` ${m}?: ${g.replace(" | null","")} | null;`);}let u=`export interface ${e} {
59
59
  ${r.join(`
60
60
  `)}
61
61
  }`,s=`export interface ${e}Insert {
@@ -64,7 +64,7 @@ ${o.join(`
64
64
  }`,i=`export interface ${e}Update {
65
65
  ${l.join(`
66
66
  `)}
67
- }`;return {base:u,insert:s,update:i}}function he(a,t,n){let e=["/**"," * Auto-generated TypeScript types from database schema"," * Generated by @vaiftech/cli",` * Generated at: ${new Date().toISOString()}`," * "," * DO NOT EDIT MANUALLY - changes will be overwritten"," */",""];if(t.size>0){e.push("// ============ ENUMS ============"),e.push("");for(let[o,l]of t)e.push(fe(o,l)),e.push("");}e.push("// ============ TABLES ============"),e.push("");let r=[];for(let[o,l]of a){let{base:u,insert:s,update:i}=ge(o,l,t);r.push(o),e.push(u),e.push(""),e.push(s),e.push(""),e.push(i),e.push("");}e.push("// ============ DATABASE SCHEMA ============"),e.push(""),e.push("export interface Database {");for(let o of r){let l=L(o);e.push(` ${o}: {`),e.push(` Row: ${l};`),e.push(` Insert: ${l}Insert;`),e.push(` Update: ${l}Update;`),e.push(" };");}return e.push("}"),e.push(""),e.push("export type TableName = keyof Database;"),e.push(""),e.push("// ============ HELPER TYPES ============"),e.push(""),e.push('export type Row<T extends TableName> = Database[T]["Row"];'),e.push('export type Insert<T extends TableName> = Database[T]["Insert"];'),e.push('export type Update<T extends TableName> = Database[T]["Update"];'),e.push(""),e.join(`
67
+ }`;return {base:u,insert:s,update:i}}function he(a,t,n){let e=["/**"," * Auto-generated TypeScript types from database schema"," * Generated by @vaiftech/cli",` * Generated at: ${new Date().toISOString()}`," * "," * DO NOT EDIT MANUALLY - changes will be overwritten"," */",""];if(t.size>0){e.push("// ============ ENUMS ============"),e.push("");for(let[o,l]of t)e.push(fe(o,l)),e.push("");}e.push("// ============ TABLES ============"),e.push("");let r=[];for(let[o,l]of a){let{base:u,insert:s,update:i}=ge(o,l,t);r.push(o),e.push(u),e.push(""),e.push(s),e.push(""),e.push(i),e.push("");}e.push("// ============ DATABASE SCHEMA ============"),e.push(""),e.push("export interface Database {");for(let o of r){let l=N(o);e.push(` ${o}: {`),e.push(` Row: ${l};`),e.push(` Insert: ${l}Insert;`),e.push(` Update: ${l}Update;`),e.push(" };");}return e.push("}"),e.push(""),e.push("export type TableName = keyof Database;"),e.push(""),e.push("// ============ HELPER TYPES ============"),e.push(""),e.push('export type Row<T extends TableName> = Database[T]["Row"];'),e.push('export type Insert<T extends TableName> = Database[T]["Insert"];'),e.push('export type Update<T extends TableName> = Database[T]["Update"];'),e.push(""),e.join(`
68
68
  `)}async function Ye(a){let t=P("Loading configuration...").start();try{let n=await K(a.config),e=a.connection||n?.database?.url||process.env.DATABASE_URL,r=e&&!e.includes("${"),o,l,u;if(r){t.text="Connecting to database...";let m=new se.Client({connectionString:e});await m.connect(),t.text="Introspecting schema...",{tables:o,enums:l,foreignKeys:u}=await pe(m,a.schema),await m.end();}else {let m=R();(!m||!m.token)&&(t.fail("No database connection and not logged in"),console.log(c.yellow(`
69
69
  Either:`)),console.log(c.gray(" 1. Run `vaif login` to authenticate (no DATABASE_URL needed)")),console.log(c.gray(" 2. Set DATABASE_URL in your .env file")),console.log(c.gray(" 3. Pass --connection postgresql://user:pass@host:5432/db")),process.exit(1));let h=n?.projectId||process.env.VAIF_PROJECT_ID||m.projectId;h||(t.fail("No project ID specified"),console.log(c.yellow(`
70
70
  Set projectId in vaif.config.json or use VAIF_PROJECT_ID env var.`)),process.exit(1)),t.text="Introspecting schema via API...",{tables:o,enums:l,foreignKeys:u}=await de(m.token,h);}if(o.size===0){t.warn("No tables found"),console.log(c.yellow(`
@@ -287,7 +287,21 @@ A full-stack Next.js application powered by [VAIF Studio](https://vaif.studio),
287
287
  ## Documentation
288
288
 
289
289
  Full documentation is available at <https://docs.vaif.studio>.
290
- `}],featureFiles:{auth:[{path:"middleware.ts",content:`import { NextResponse, type NextRequest } from "next/server";
290
+ `}],featureFiles:{auth:[{path:"app/page.tsx",content:`import Link from "next/link";
291
+
292
+ export default function Home() {
293
+ return (
294
+ <main style={{ maxWidth: 600, margin: "80px auto", textAlign: "center" }}>
295
+ <h1>Welcome to VAIF</h1>
296
+ <p>Your Next.js app is ready. Start building!</p>
297
+ <p style={{ marginTop: 24 }}>
298
+ <Link href="/login" style={{ marginRight: 16 }}>Log in</Link>
299
+ <Link href="/signup">Sign up</Link>
300
+ </p>
301
+ </main>
302
+ );
303
+ }
304
+ `},{path:"middleware.ts",content:`import { NextResponse, type NextRequest } from "next/server";
291
305
  import { createVaifClient } from "@vaiftech/client";
292
306
  import { authMiddleware } from "@vaiftech/auth/nextjs";
293
307
 
@@ -334,12 +348,12 @@ export default function LoginPage() {
334
348
  setLoading(true);
335
349
  setError(null);
336
350
 
337
- const { error } = await vaif.auth.signInWithPassword({ email, password });
338
- if (error) {
339
- setError(error.message);
340
- setLoading(false);
341
- } else {
351
+ try {
352
+ await vaif.auth.login(email, password);
342
353
  router.push("/dashboard");
354
+ } catch (err: any) {
355
+ setError(err.message || "Login failed");
356
+ setLoading(false);
343
357
  }
344
358
  }
345
359
 
@@ -381,12 +395,12 @@ export default function SignupPage() {
381
395
  setLoading(true);
382
396
  setError(null);
383
397
 
384
- const { error } = await vaif.auth.signUp({ email, password });
385
- if (error) {
386
- setError(error.message);
387
- setLoading(false);
388
- } else {
398
+ try {
399
+ await vaif.auth.signUp(email, password);
389
400
  router.push("/");
401
+ } catch (err: any) {
402
+ setError(err.message || "Sign up failed");
403
+ setLoading(false);
390
404
  }
391
405
  }
392
406
 
@@ -777,7 +791,33 @@ A single-page React application built with [Vite](https://vite.dev/) and powered
777
791
  ## Documentation
778
792
 
779
793
  Full documentation is available at <https://docs.vaif.studio>.
780
- `}],featureFiles:{auth:[{path:"src/pages/Login.tsx",content:`import { useState } from "react";
794
+ `}],featureFiles:{auth:[{path:"src/App.tsx",content:`import { Routes, Route, Link } from "react-router-dom";
795
+ import Login from "./pages/Login";
796
+ import Signup from "./pages/Signup";
797
+
798
+ export default function App() {
799
+ return (
800
+ <Routes>
801
+ <Route path="/" element={<Home />} />
802
+ <Route path="/login" element={<Login />} />
803
+ <Route path="/signup" element={<Signup />} />
804
+ </Routes>
805
+ );
806
+ }
807
+
808
+ function Home() {
809
+ return (
810
+ <div style={{ maxWidth: 600, margin: "80px auto", textAlign: "center" }}>
811
+ <h1>Welcome to VAIF</h1>
812
+ <p>Your app is ready. Start building!</p>
813
+ <p style={{ marginTop: 24 }}>
814
+ <Link to="/login" style={{ marginRight: 16 }}>Log in</Link>
815
+ <Link to="/signup">Sign up</Link>
816
+ </p>
817
+ </div>
818
+ );
819
+ }
820
+ `},{path:"src/pages/Login.tsx",content:`import { useState } from "react";
781
821
  import { useNavigate } from "react-router-dom";
782
822
  import { vaif } from "../lib/vaif";
783
823
 
@@ -793,12 +833,12 @@ export default function Login() {
793
833
  setLoading(true);
794
834
  setError(null);
795
835
 
796
- const { error } = await vaif.auth.signInWithPassword({ email, password });
797
- if (error) {
798
- setError(error.message);
799
- setLoading(false);
800
- } else {
836
+ try {
837
+ await vaif.auth.login(email, password);
801
838
  navigate("/");
839
+ } catch (err: any) {
840
+ setError(err.message || "Login failed");
841
+ setLoading(false);
802
842
  }
803
843
  }
804
844
 
@@ -838,12 +878,12 @@ export default function Signup() {
838
878
  setLoading(true);
839
879
  setError(null);
840
880
 
841
- const { error } = await vaif.auth.signUp({ email, password });
842
- if (error) {
843
- setError(error.message);
844
- setLoading(false);
845
- } else {
881
+ try {
882
+ await vaif.auth.signUp(email, password);
846
883
  navigate("/");
884
+ } catch (err: any) {
885
+ setError(err.message || "Sign up failed");
886
+ setLoading(false);
847
887
  }
848
888
  }
849
889
 
@@ -882,21 +922,15 @@ export function AuthGuard({ children, fallback }: AuthGuardProps) {
882
922
  const [authenticated, setAuthenticated] = useState(false);
883
923
 
884
924
  useEffect(() => {
885
- vaif.auth.getSession().then(({ data }) => {
886
- if (data.session) {
925
+ vaif.auth.getUser()
926
+ .then(() => {
887
927
  setAuthenticated(true);
888
- } else {
928
+ setLoading(false);
929
+ })
930
+ .catch(() => {
889
931
  navigate("/login");
890
- }
891
- setLoading(false);
892
- });
893
-
894
- const { data: { subscription } } = vaif.auth.onAuthStateChange((_event, session) => {
895
- setAuthenticated(!!session);
896
- if (!session) navigate("/login");
897
- });
898
-
899
- return () => subscription.unsubscribe();
932
+ setLoading(false);
933
+ });
900
934
  }, [navigate]);
901
935
 
902
936
  if (loading) return fallback ?? <div>Loading...</div>;
@@ -1444,7 +1478,39 @@ A React Native / Expo mobile application powered by [VAIF Studio](https://vaif.s
1444
1478
  ## Documentation
1445
1479
 
1446
1480
  Full documentation is available at <https://docs.vaif.studio>.
1447
- `}],featureFiles:{auth:[{path:"app/(auth)/login.tsx",content:`import { useState } from "react";
1481
+ `}],featureFiles:{auth:[{path:"app/index.tsx",content:`import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
1482
+ import { useRouter } from "expo-router";
1483
+
1484
+ export default function HomeScreen() {
1485
+ const router = useRouter();
1486
+
1487
+ return (
1488
+ <View style={styles.container}>
1489
+ <Text style={styles.title}>Welcome to VAIF</Text>
1490
+ <Text style={styles.subtitle}>Your mobile app is ready. Start building!</Text>
1491
+ <View style={styles.buttons}>
1492
+ <TouchableOpacity style={styles.button} onPress={() => router.push("/(auth)/login")}>
1493
+ <Text style={styles.buttonText}>Log In</Text>
1494
+ </TouchableOpacity>
1495
+ <TouchableOpacity style={[styles.button, styles.secondaryButton]} onPress={() => router.push("/(auth)/signup")}>
1496
+ <Text style={[styles.buttonText, styles.secondaryText]}>Sign Up</Text>
1497
+ </TouchableOpacity>
1498
+ </View>
1499
+ </View>
1500
+ );
1501
+ }
1502
+
1503
+ const styles = StyleSheet.create({
1504
+ container: { flex: 1, alignItems: "center", justifyContent: "center", padding: 24 },
1505
+ title: { fontSize: 28, fontWeight: "bold", marginBottom: 8 },
1506
+ subtitle: { fontSize: 16, color: "#666", textAlign: "center", marginBottom: 32 },
1507
+ buttons: { gap: 12, width: "100%" },
1508
+ button: { backgroundColor: "#0070f3", borderRadius: 8, padding: 14, alignItems: "center" },
1509
+ secondaryButton: { backgroundColor: "transparent", borderWidth: 1, borderColor: "#0070f3" },
1510
+ buttonText: { color: "#fff", fontSize: 16, fontWeight: "600" },
1511
+ secondaryText: { color: "#0070f3" },
1512
+ });
1513
+ `},{path:"app/(auth)/login.tsx",content:`import { useState } from "react";
1448
1514
  import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert } from "react-native";
1449
1515
  import { useRouter } from "expo-router";
1450
1516
  import { vaif } from "../../lib/vaif";
@@ -1457,10 +1523,14 @@ export default function LoginScreen() {
1457
1523
 
1458
1524
  async function handleLogin() {
1459
1525
  setLoading(true);
1460
- const { error } = await vaif.auth.signInWithPassword({ email, password });
1461
- setLoading(false);
1462
- if (error) Alert.alert("Error", error.message);
1463
- else router.replace("/");
1526
+ try {
1527
+ await vaif.auth.login(email, password);
1528
+ router.replace("/");
1529
+ } catch (err: any) {
1530
+ Alert.alert("Error", err.message || "Login failed");
1531
+ } finally {
1532
+ setLoading(false);
1533
+ }
1464
1534
  }
1465
1535
 
1466
1536
  return (
@@ -1495,10 +1565,14 @@ export default function SignupScreen() {
1495
1565
 
1496
1566
  async function handleSignup() {
1497
1567
  setLoading(true);
1498
- const { error } = await vaif.auth.signUp({ email, password });
1499
- setLoading(false);
1500
- if (error) Alert.alert("Error", error.message);
1501
- else router.replace("/");
1568
+ try {
1569
+ await vaif.auth.signUp(email, password);
1570
+ router.replace("/");
1571
+ } catch (err: any) {
1572
+ Alert.alert("Error", err.message || "Sign up failed");
1573
+ } finally {
1574
+ setLoading(false);
1575
+ }
1502
1576
  }
1503
1577
 
1504
1578
  return (
@@ -1845,7 +1919,7 @@ class _LoginScreenState extends State<LoginScreen> {
1845
1919
  setState(() { _loading = true; _error = null; });
1846
1920
 
1847
1921
  try {
1848
- await vaif.auth.signInWithPassword(
1922
+ await vaif.auth.login(
1849
1923
  email: _emailController.text,
1850
1924
  password: _passwordController.text,
1851
1925
  );
@@ -3687,7 +3761,7 @@ export const posts = pgTable("posts", {
3687
3761
  ? Which VAIF features do you want to include?`)),_.forEach((u,s)=>{let i=t.has(s)?c.green("[x]"):"[ ]",p=s===n?c.cyan("> "):" ";console.log(`${p}${i} ${u.label} ${c.gray(`(${u.description})`)}`);}),console.log(c.gray(" (up/down to move, space to toggle, enter to confirm)"));}l(),process.stdin.on("keypress",(u,s)=>{if(s.name==="up"&&n>0)n--,o();else if(s.name==="down"&&n<_.length-1)n++,o();else if(s.name==="space")t.has(n)?t.delete(n):t.add(n),o();else if(s.name==="return"){process.stdin.setRawMode&&process.stdin.setRawMode(false),r.close();let i=[...t].sort().map(p=>_[p].name);e(i.length>0?i:a);}else s.name==="c"&&s.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),r.close(),process.exit(0));});})}async function V(a,t={}){let n=G[a];n||(console.log(c.red(`
3688
3762
  Unknown template: ${a}`)),console.log(c.yellow(`Run 'vaif templates' to see available templates.
3689
3763
  `)),process.exit(1));let e;t.features&&t.features.length>0?e=t.features.filter(i=>_.some(p=>p.name===i)):t.addOnly?(console.log(c.red(`
3690
- No features specified.`)),console.log(c.yellow("Usage: vaif init --template <name> --add-features <features>")),console.log(c.gray("Available features: auth, database, realtime, storage, functions")),process.exit(1)):n.featureFiles&&Object.keys(n.featureFiles).length>0?e=await ve(n.defaultFeatures??["database","auth"]):e=n.defaultFeatures??[],t.addOnly?(console.log(""),console.log(c.bold(`Adding features to ${c.cyan(n.name)} project...`)),console.log(c.gray(` Features: ${e.join(", ")}`)),console.log("")):(console.log(""),console.log(c.bold(`Scaffolding ${c.cyan(n.name)} template...`)),e.length>0&&console.log(c.gray(` Features: ${e.join(", ")}`)),console.log(""));let r=t.addOnly?[]:[...n.files];if(n.featureFiles)for(let i of e){let p=n.featureFiles[i];p&&r.push(...p);}let o=0,l=0;for(let i of r){let p=U.resolve(i.path),g=U.dirname(p);if(y.existsSync(g)||y.mkdirSync(g,{recursive:true}),i.path==="package.json"&&y.existsSync(p)&&!t.force)try{let m=JSON.parse(y.readFileSync(p,"utf-8")),h=JSON.parse(i.content),A=k=>{if(!k)return {};let j={};for(let[H,S]of Object.entries(k))!S.startsWith("workspace:")&&!S.startsWith("link:")&&!S.startsWith("file:")&&(j[H]=S);return j};m.dependencies={...A(m.dependencies),...h.dependencies||{}},m.devDependencies={...A(m.devDependencies),...h.devDependencies||{}},h.scripts&&(m.scripts={...m.scripts||{},...h.scripts}),y.writeFileSync(p,JSON.stringify(m,null,2)+`
3764
+ No features specified.`)),console.log(c.yellow("Usage: vaif init --template <name> --add-features <features>")),console.log(c.gray("Available features: auth, database, realtime, storage, functions")),process.exit(1)):n.featureFiles&&Object.keys(n.featureFiles).length>0?e=await ve(n.defaultFeatures??["database","auth"]):e=n.defaultFeatures??[],t.addOnly?(console.log(""),console.log(c.bold(`Adding features to ${c.cyan(n.name)} project...`)),console.log(c.gray(` Features: ${e.join(", ")}`)),console.log("")):(console.log(""),console.log(c.bold(`Scaffolding ${c.cyan(n.name)} template...`)),e.length>0&&console.log(c.gray(` Features: ${e.join(", ")}`)),console.log(""));let r=t.addOnly?[]:[...n.files];if(n.featureFiles)for(let i of e){let p=n.featureFiles[i];p&&r.push(...p);}let o=0,l=0;for(let i of r){let p=U.resolve(i.path),g=U.dirname(p);if(y.existsSync(g)||y.mkdirSync(g,{recursive:true}),i.path==="package.json"&&y.existsSync(p)&&!t.force)try{let m=JSON.parse(y.readFileSync(p,"utf-8")),h=JSON.parse(i.content),A=k=>{if(!k)return {};let j={};for(let[H,x]of Object.entries(k))!x.startsWith("workspace:")&&!x.startsWith("link:")&&!x.startsWith("file:")&&(j[H]=x);return j};m.dependencies={...A(m.dependencies),...h.dependencies||{}},m.devDependencies={...A(m.devDependencies),...h.devDependencies||{}},h.scripts&&(m.scripts={...m.scripts||{},...h.scripts}),y.writeFileSync(p,JSON.stringify(m,null,2)+`
3691
3765
  `,"utf-8"),console.log(c.green(` merge ${i.path} (added dependencies)`)),o++;continue}catch{}if(y.existsSync(p)&&!t.force){console.log(c.yellow(` skip ${i.path} (already exists)`)),l++;continue}y.writeFileSync(p,i.content,"utf-8"),console.log(c.green(` create ${i.path}`)),o++;}console.log(""),o>0&&console.log(c.green(`Created ${o} file${o!==1?"s":""}.`)),l>0&&console.log(c.yellow(`Skipped ${l} file${l!==1?"s":""} (use --force to overwrite).`));let u={auth:{"@vaiftech/auth":"^1.0.0"},database:{},realtime:{},storage:{},functions:{}},s=U.resolve("package.json");if(y.existsSync(s)&&e.length>0)try{let i=JSON.parse(y.readFileSync(s,"utf-8")),p=!1;for(let g of e){let m=u[g];if(m)for(let[h,A]of Object.entries(m))i.dependencies?.[h]||(i.dependencies=i.dependencies||{},i.dependencies[h]=A,p=!0);}p&&y.writeFileSync(s,JSON.stringify(i,null,2)+`
3692
3766
  `,"utf-8");}catch{}(n.dependencies?.length||n.devDependencies?.length)&&(console.log(""),console.log(c.bold("Install dependencies:")),n.dependencies?.length&&console.log(c.cyan(` npm install ${n.dependencies.join(" ")}`)),n.devDependencies?.length&&console.log(c.cyan(` npm install -D ${n.devDependencies.join(" ")}`))),console.log(""),console.log(c.bold.green("Project scaffolded successfully!")),console.log(""),console.log(c.bold(" Next steps:")),n.postInstructions.forEach(i=>{console.log(c.gray(` ${i}`));}),console.log(""),console.log(c.gray(" Get your project credentials at https://vaif.studio/app/security/api-keys")),console.log("");}var be={$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 rt(a){if(a.addFeatures){a.template||(console.log(c.red(`
3693
3767
  --add-features requires --template to know which template to use.`)),console.log(c.gray("Example: vaif init --template react-spa --add-features functions,storage")),process.exit(1));let e=a.addFeatures.split(",").map(r=>r.trim());await V(a.template,{force:a.force,features:e,addOnly:true});return}let t=P("Initializing VAIF configuration...").start(),n=U.resolve("vaif.config.json");y.existsSync(n)&&!a.force&&(t.fail("vaif.config.json already exists"),console.log(c.yellow(`
@@ -3695,4 +3769,4 @@ Use --force to overwrite existing configuration.`)),process.exit(1));try{if(y.wr
3695
3769
  DATABASE_URL=postgresql://user:password@localhost:5432/database
3696
3770
  VAIF_API_KEY=your-api-key
3697
3771
  `,"utf-8"),console.log(c.gray("Created .env.example"))),a.typescript){let r=U.resolve("src/types");y.existsSync(r)||(y.mkdirSync(r,{recursive:!0}),console.log(c.gray("Created src/types directory")));}console.log(""),console.log(c.green("VAIF initialized successfully!")),console.log(""),console.log(c.gray("Next steps:")),console.log(c.gray(" 1. Update vaif.config.json with your project ID")),console.log(c.gray(" 2. Set DATABASE_URL in your environment")),console.log(c.gray(" 3. Run: npx vaif generate")),console.log("");}}catch(e){t.fail("Failed to initialize"),e instanceof Error&&console.error(c.red(`
3698
- Error: ${e.message}`)),process.exit(1);}}export{K as a,R as b,Ne as c,Le as d,Ue as e,Ye as f,Qe as g,rt as h};
3772
+ Error: ${e.message}`)),process.exit(1);}}export{K as a,R as b,Le as c,Ne as d,Ue as e,Ye as f,Qe as g,rt as h};