@vaiftech/cli 1.7.2 → 1.7.4
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-KXD5F33V.js → chunk-CMWHBLLZ.js} +52 -62
- package/dist/cli.cjs +62 -72
- package/dist/cli.js +2 -2
- package/dist/index.cjs +61 -71
- 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.4) — 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
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import y from'fs';import
|
|
1
|
+
import y from'fs';import U from'path';import J from'dotenv';import X from'os';import {exec}from'child_process';import P from'ora';import c from'chalk';import q from'readline';import se from'pg';import ce from'prettier';J.config();async function K(a){let t=U.resolve(a);if(!y.existsSync(t))return null;try{let n=y.readFileSync(t,"utf-8"),e=JSON.parse(n);return e.database?.url&&(e.database.url=M(e.database.url)),e.api?.apiKey&&(e.api.apiKey=M(e.api.apiKey)),e}catch{throw new Error(`Failed to parse config file: ${a}`)}}function M(a){return a.replace(/\$\{([^}]+)\}/g,(t,n)=>process.env[n]||t)}var F=U.join(X.homedir(),".vaif"),I=U.join(F,"auth.json"),w=process.env.VAIF_API_URL||"https://api.vaif.studio";function Z(){y.existsSync(F)||y.mkdirSync(F,{recursive:true});}function B(a){Z(),y.writeFileSync(I,JSON.stringify(a,null,2),"utf-8"),y.chmodSync(I,384);}function R(){if(!y.existsSync(I))return null;try{let a=y.readFileSync(I,"utf-8");return JSON.parse(a)}catch{return null}}function ee(a){let t=q.createInterface({input:process.stdin,output:process.stdout});return new Promise(n=>{t.question(a,e=>{t.close(),n(e);});})}function te(a){return new Promise(t=>{let n=q.createInterface({input:process.stdin,output:process.stdout});process.stdin;let r=process.stdout.write.bind(process.stdout),o=false;process.stdout.write=((...l)=>o?true:r(...l)),n.question(a,l=>{o=false,process.stdout.write=r,console.log(""),n.close(),t(l);}),o=true;})}function ae(a){let t=process.platform,n;t==="darwin"?n=`open "${a}"`:t==="win32"?n=`start "" "${a}"`:n=`xdg-open "${a}"`,exec(n,e=>{});}function ne(a){return new Promise(t=>setTimeout(t,a))}async function ie(a){try{let t=await fetch(`${w}/auth/me`,{headers:{Authorization:`Bearer ${a}`}});if(t.ok){let n=await t.json();return {valid:!0,email:n.user?.email||n.email}}return {valid:!1}}catch{return {valid:false}}}async function oe(a){let t=P();t.start("Setting up authentication...");let n,e;try{let u=await fetch(`${w}/auth/cli/authorize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})});u.ok||(t.fail("Failed to initiate authentication"),console.log(c.red(`
|
|
2
2
|
Could not connect to VAIF API. Please try again later.`)),process.exit(1));let s=await u.json();n=s.code,e=s.url;}catch{t.fail("Failed to connect to VAIF API"),console.log(c.red(`
|
|
3
3
|
Could not connect to VAIF API.`)),console.log(c.gray("Check your internet connection or try: vaif login --email")),process.exit(1);}t.stop(),console.log(c.cyan(" Opening browser for authentication...")),console.log(""),console.log(c.gray(" If the browser doesn't open, visit this URL:")),console.log(c.white(` ${e}`)),console.log(""),ae(e),t.start("Waiting for browser authentication...");let r=12e4,o=2e3,l=Date.now();for(;Date.now()-l<r;){await ne(o);try{let u=await fetch(`${w}/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:n})});if(!u.ok){let i=await u.json();(i.error==="ExpiredCode"||i.error==="InvalidCode")&&(t.fail("Authentication expired"),console.log(c.red(`
|
|
4
4
|
The authentication session expired. Please try again.`)),process.exit(1));continue}let s=await u.json();if(s.ok&&s.accessToken){let i={token:s.accessToken,email:s.user?.email,projectId:a,expiresAt:new Date(Date.now()+s.expiresIn*1e3).toISOString()};B(i),t.succeed("Logged in successfully"),console.log(""),s.user?.email&&console.log(c.green(` Authenticated as: ${s.user.email}`)),console.log(c.gray(` Config saved to: ${I}`)),console.log("");return}}catch{}}t.fail("Authentication timed out"),console.log(c.red(`
|
|
@@ -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 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
|
|
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 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
|
|
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,11 +64,11 @@ ${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(`
|
|
71
|
-
Push a migration first: vaif db push`));return}t.text=`Generating types for ${o.size} tables...`;let s=he(o,l,u),i=await ce.format(s,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100});if(a.dryRun){t.succeed("Generated types (dry run):"),console.log(""),console.log(c.gray("\u2500".repeat(60))),console.log(i),console.log(c.gray("\u2500".repeat(60)));return}let p=
|
|
71
|
+
Push a migration first: vaif db push`));return}t.text=`Generating types for ${o.size} tables...`;let s=he(o,l,u),i=await ce.format(s,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100});if(a.dryRun){t.succeed("Generated types (dry run):"),console.log(""),console.log(c.gray("\u2500".repeat(60))),console.log(i),console.log(c.gray("\u2500".repeat(60)));return}let p=U.resolve(a.output),g=U.dirname(p);y.existsSync(g)||y.mkdirSync(g,{recursive:!0}),y.writeFileSync(p,i,"utf-8"),t.succeed(`Generated types for ${o.size} tables \u2192 ${c.cyan(a.output)}`),console.log(""),console.log(c.green("Generated:")),console.log(c.gray(` Tables: ${o.size}`)),console.log(c.gray(` Enums: ${l.size}`)),console.log(""),console.log(c.gray("Import in your code:")),console.log(c.cyan(` import type { Database, Row, Insert, Update } from "${a.output.replace(/\.ts$/,"")}";`));}catch(n){t.fail("Failed to generate types"),n instanceof Error&&(console.error(c.red(`
|
|
72
72
|
Error: ${n.message}`)),n.message.includes("ECONNREFUSED")&&console.log(c.yellow(`
|
|
73
73
|
Make sure your database is running and accessible.`))),process.exit(1);}}var _=[{name:"database",label:"Database",description:"CRUD queries, type-safe operations"},{name:"auth",label:"Authentication",description:"login, signup, OAuth, sessions"},{name:"realtime",label:"Realtime",description:"live subscriptions, presence"},{name:"storage",label:"Storage",description:"file uploads, signed URLs"},{name:"functions",label:"Functions",description:"serverless function calls"}],G={"nextjs-fullstack":{name:"Next.js Full-Stack",description:"Next.js app with server/client VAIF client, auth middleware, and React hooks",tag:"Next.js",defaultFeatures:["database","auth"],files:[{path:"package.json",content:`{
|
|
74
74
|
"name": "my-vaif-app",
|
|
@@ -184,10 +184,7 @@ NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
|
184
184
|
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
185
185
|
VAIF_SECRET_KEY=your-secret-key
|
|
186
186
|
|
|
187
|
-
#
|
|
188
|
-
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
189
|
-
|
|
190
|
-
# CLI uses these (non-prefixed) for vaif db push, vaif secrets, etc.
|
|
187
|
+
# CLI project ID (for vaif generate, vaif pull, vaif secrets, etc.)
|
|
191
188
|
VAIF_PROJECT_ID=your-project-id
|
|
192
189
|
`},{path:".gitignore",content:`node_modules
|
|
193
190
|
.next
|
|
@@ -337,12 +334,12 @@ export default function LoginPage() {
|
|
|
337
334
|
setLoading(true);
|
|
338
335
|
setError(null);
|
|
339
336
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
setError(error.message);
|
|
343
|
-
setLoading(false);
|
|
344
|
-
} else {
|
|
337
|
+
try {
|
|
338
|
+
await vaif.auth.login(email, password);
|
|
345
339
|
router.push("/dashboard");
|
|
340
|
+
} catch (err: any) {
|
|
341
|
+
setError(err.message || "Login failed");
|
|
342
|
+
setLoading(false);
|
|
346
343
|
}
|
|
347
344
|
}
|
|
348
345
|
|
|
@@ -384,12 +381,12 @@ export default function SignupPage() {
|
|
|
384
381
|
setLoading(true);
|
|
385
382
|
setError(null);
|
|
386
383
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
setError(error.message);
|
|
390
|
-
setLoading(false);
|
|
391
|
-
} else {
|
|
384
|
+
try {
|
|
385
|
+
await vaif.auth.signUp(email, password);
|
|
392
386
|
router.push("/");
|
|
387
|
+
} catch (err: any) {
|
|
388
|
+
setError(err.message || "Sign up failed");
|
|
389
|
+
setLoading(false);
|
|
393
390
|
}
|
|
394
391
|
}
|
|
395
392
|
|
|
@@ -682,9 +679,6 @@ interface ImportMeta {
|
|
|
682
679
|
|
|
683
680
|
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
684
681
|
VITE_VAIF_API_KEY=your-api-key
|
|
685
|
-
|
|
686
|
-
# Database connection (for vaif generate, vaif db push)
|
|
687
|
-
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
688
682
|
`},{path:".gitignore",content:`node_modules
|
|
689
683
|
dist
|
|
690
684
|
.env
|
|
@@ -799,12 +793,12 @@ export default function Login() {
|
|
|
799
793
|
setLoading(true);
|
|
800
794
|
setError(null);
|
|
801
795
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
setError(error.message);
|
|
805
|
-
setLoading(false);
|
|
806
|
-
} else {
|
|
796
|
+
try {
|
|
797
|
+
await vaif.auth.login(email, password);
|
|
807
798
|
navigate("/");
|
|
799
|
+
} catch (err: any) {
|
|
800
|
+
setError(err.message || "Login failed");
|
|
801
|
+
setLoading(false);
|
|
808
802
|
}
|
|
809
803
|
}
|
|
810
804
|
|
|
@@ -844,12 +838,12 @@ export default function Signup() {
|
|
|
844
838
|
setLoading(true);
|
|
845
839
|
setError(null);
|
|
846
840
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
setError(error.message);
|
|
850
|
-
setLoading(false);
|
|
851
|
-
} else {
|
|
841
|
+
try {
|
|
842
|
+
await vaif.auth.signUp(email, password);
|
|
852
843
|
navigate("/");
|
|
844
|
+
} catch (err: any) {
|
|
845
|
+
setError(err.message || "Sign up failed");
|
|
846
|
+
setLoading(false);
|
|
853
847
|
}
|
|
854
848
|
}
|
|
855
849
|
|
|
@@ -1463,10 +1457,14 @@ export default function LoginScreen() {
|
|
|
1463
1457
|
|
|
1464
1458
|
async function handleLogin() {
|
|
1465
1459
|
setLoading(true);
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1460
|
+
try {
|
|
1461
|
+
await vaif.auth.login(email, password);
|
|
1462
|
+
router.replace("/");
|
|
1463
|
+
} catch (err: any) {
|
|
1464
|
+
Alert.alert("Error", err.message || "Login failed");
|
|
1465
|
+
} finally {
|
|
1466
|
+
setLoading(false);
|
|
1467
|
+
}
|
|
1470
1468
|
}
|
|
1471
1469
|
|
|
1472
1470
|
return (
|
|
@@ -1501,10 +1499,14 @@ export default function SignupScreen() {
|
|
|
1501
1499
|
|
|
1502
1500
|
async function handleSignup() {
|
|
1503
1501
|
setLoading(true);
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1502
|
+
try {
|
|
1503
|
+
await vaif.auth.signUp(email, password);
|
|
1504
|
+
router.replace("/");
|
|
1505
|
+
} catch (err: any) {
|
|
1506
|
+
Alert.alert("Error", err.message || "Sign up failed");
|
|
1507
|
+
} finally {
|
|
1508
|
+
setLoading(false);
|
|
1509
|
+
}
|
|
1508
1510
|
}
|
|
1509
1511
|
|
|
1510
1512
|
return (
|
|
@@ -1851,7 +1853,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|
|
1851
1853
|
setState(() { _loading = true; _error = null; });
|
|
1852
1854
|
|
|
1853
1855
|
try {
|
|
1854
|
-
await vaif.auth.
|
|
1856
|
+
await vaif.auth.login(
|
|
1855
1857
|
email: _emailController.text,
|
|
1856
1858
|
password: _passwordController.text,
|
|
1857
1859
|
);
|
|
@@ -2679,9 +2681,6 @@ export async function deleteTodo(id: string): Promise<void> {
|
|
|
2679
2681
|
|
|
2680
2682
|
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
2681
2683
|
VITE_VAIF_API_KEY=your-api-key
|
|
2682
|
-
|
|
2683
|
-
# Database connection (for vaif generate, vaif db push)
|
|
2684
|
-
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
2685
2684
|
`},{path:"README.md",content:`# Todo App \u2014 VAIF Starter
|
|
2686
2685
|
|
|
2687
2686
|
A simple React todo application for learning [VAIF Studio](https://vaif.studio) basics, including typed database queries and CRUD operations.
|
|
@@ -2960,9 +2959,6 @@ export function useRealtimeMessages({
|
|
|
2960
2959
|
|
|
2961
2960
|
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
2962
2961
|
VITE_VAIF_API_KEY=your-api-key
|
|
2963
|
-
|
|
2964
|
-
# Database connection (for vaif generate, vaif db push)
|
|
2965
|
-
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
2966
2962
|
`},{path:"README.md",content:`# Realtime Chat \u2014 VAIF Starter
|
|
2967
2963
|
|
|
2968
2964
|
A React chat application with live messaging powered by [VAIF Studio](https://vaif.studio) realtime subscriptions.
|
|
@@ -3278,10 +3274,7 @@ NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
|
3278
3274
|
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
3279
3275
|
VAIF_SECRET_KEY=your-secret-key
|
|
3280
3276
|
|
|
3281
|
-
#
|
|
3282
|
-
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
3283
|
-
|
|
3284
|
-
# CLI uses these (non-prefixed) for vaif db push, vaif secrets, etc.
|
|
3277
|
+
# CLI project ID (for vaif generate, vaif pull, vaif secrets, etc.)
|
|
3285
3278
|
VAIF_PROJECT_ID=your-project-id
|
|
3286
3279
|
`},{path:"README.md",content:`# SaaS Starter \u2014 VAIF Studio
|
|
3287
3280
|
|
|
@@ -3556,10 +3549,7 @@ NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
|
3556
3549
|
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
3557
3550
|
VAIF_SECRET_KEY=your-secret-key
|
|
3558
3551
|
|
|
3559
|
-
#
|
|
3560
|
-
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
3561
|
-
|
|
3562
|
-
# CLI uses these (non-prefixed) for vaif db push, vaif secrets, etc.
|
|
3552
|
+
# CLI project ID (for vaif generate, vaif pull, vaif secrets, etc.)
|
|
3563
3553
|
VAIF_PROJECT_ID=your-project-id
|
|
3564
3554
|
`},{path:"README.md",content:`# E-commerce API \u2014 VAIF Studio
|
|
3565
3555
|
|
|
@@ -3705,12 +3695,12 @@ export const posts = pgTable("posts", {
|
|
|
3705
3695
|
? 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(`
|
|
3706
3696
|
Unknown template: ${a}`)),console.log(c.yellow(`Run 'vaif templates' to see available templates.
|
|
3707
3697
|
`)),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(`
|
|
3708
|
-
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=
|
|
3709
|
-
`,"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=
|
|
3698
|
+
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)+`
|
|
3699
|
+
`,"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)+`
|
|
3710
3700
|
`,"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(`
|
|
3711
|
-
--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=
|
|
3712
|
-
Use --force to overwrite existing configuration.`)),process.exit(1));try{if(y.writeFileSync(n,JSON.stringify(be,null,2),"utf-8"),t.succeed("Created vaif.config.json"),a.template){let e=a.features?a.features.split(",").map(r=>r.trim()):void 0;await V(a.template,{force:a.force,features:e});}else {let e=
|
|
3701
|
+
--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(`
|
|
3702
|
+
Use --force to overwrite existing configuration.`)),process.exit(1));try{if(y.writeFileSync(n,JSON.stringify(be,null,2),"utf-8"),t.succeed("Created vaif.config.json"),a.template){let e=a.features?a.features.split(",").map(r=>r.trim()):void 0;await V(a.template,{force:a.force,features:e});}else {let e=U.resolve(".env.example");if(y.existsSync(e)||(y.writeFileSync(e,`# VAIF Configuration
|
|
3713
3703
|
DATABASE_URL=postgresql://user:password@localhost:5432/database
|
|
3714
3704
|
VAIF_API_KEY=your-api-key
|
|
3715
|
-
`,"utf-8"),console.log(c.gray("Created .env.example"))),a.typescript){let r=
|
|
3716
|
-
Error: ${e.message}`)),process.exit(1);}}export{K as a,R as b,Le as c,
|
|
3705
|
+
`,"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(`
|
|
3706
|
+
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};
|