@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 +1 -1
- package/dist/{chunk-M2UHM7B7.js → chunk-WYTLXCHQ.js} +125 -51
- package/dist/cli.cjs +167 -93
- package/dist/cli.js +2 -2
- package/dist/index.cjs +140 -66
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@vaiftech/cli)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
Command-line tools for [VAIF Studio](https://vaif.studio) (v1.7.
|
|
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
|
|
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
|
|
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=
|
|
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=
|
|
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:"
|
|
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
|
-
|
|
338
|
-
|
|
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
|
-
|
|
385
|
-
|
|
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/
|
|
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
|
-
|
|
797
|
-
|
|
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
|
-
|
|
842
|
-
|
|
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.
|
|
886
|
-
|
|
925
|
+
vaif.auth.getUser()
|
|
926
|
+
.then(() => {
|
|
887
927
|
setAuthenticated(true);
|
|
888
|
-
|
|
928
|
+
setLoading(false);
|
|
929
|
+
})
|
|
930
|
+
.catch(() => {
|
|
889
931
|
navigate("/login");
|
|
890
|
-
|
|
891
|
-
|
|
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/
|
|
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
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
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
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
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.
|
|
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,
|
|
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,
|
|
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};
|