@vaiftech/cli 1.9.9 → 1.10.0
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 +57 -1
- package/dist/{chunk-KHEM3PLW.js → chunk-6Y62OF5M.js} +1378 -38
- package/dist/cli.cjs +869 -126
- package/dist/cli.js +80 -677
- package/dist/index.cjs +1380 -40
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/dist/cli.cjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';require('dotenv/config');var module$1=require('module'),commander=require('commander'),f=require('chalk'),
|
|
3
|
-
Could not connect to VAIF API. Please try again later.`)),process.exit(1));let
|
|
4
|
-
Could not connect to VAIF API.`)),console.log(f__default.default.gray("Check your internet connection or try: vaif login --email")),process.exit(1);}e.stop(),console.log(f__default.default.cyan(" Opening browser for authentication...")),console.log(""),console.log(f__default.default.gray(" If the browser doesn't open, visit this URL:")),console.log(f__default.default.white(` ${
|
|
5
|
-
The authentication session expired. Please try again.`)),process.exit(1));continue}let
|
|
6
|
-
Timed out waiting for browser authentication.`)),console.log(f__default.default.gray("Try again or use: vaif login --email")),process.exit(1);}async function
|
|
7
|
-
No email provided. Login cancelled.`)),process.exit(1));let
|
|
8
|
-
No password provided. Login cancelled.`)),process.exit(1));let
|
|
9
|
-
${
|
|
10
|
-
Could not connect to VAIF API. Please try again later.`)),process.exit(1);}}async function
|
|
11
|
-
Your session has expired. Please login again.`)),process.exit(1)),e.succeed("Authenticated"),console.log(""),console.log(f__default.default.green(` Email: ${
|
|
2
|
+
'use strict';require('dotenv/config');var module$1=require('module'),commander=require('commander'),f=require('chalk'),A=require('fs'),S=require('path'),Vt=require('pg'),ie=require('ora'),Ot=require('prettier'),xt=require('dotenv'),Pt=require('os'),child_process=require('child_process'),Re=require('readline');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var f__default=/*#__PURE__*/_interopDefault(f);var A__default=/*#__PURE__*/_interopDefault(A);var S__default=/*#__PURE__*/_interopDefault(S);var Vt__default=/*#__PURE__*/_interopDefault(Vt);var ie__default=/*#__PURE__*/_interopDefault(ie);var Ot__default=/*#__PURE__*/_interopDefault(Ot);var xt__default=/*#__PURE__*/_interopDefault(xt);var Pt__default=/*#__PURE__*/_interopDefault(Pt);var Re__default=/*#__PURE__*/_interopDefault(Re);var St=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,N=St();xt__default.default.config();async function w(t){let e=S__default.default.resolve(t);if(!A__default.default.existsSync(e))return null;try{let o=A__default.default.readFileSync(e,"utf-8"),n=JSON.parse(o);return n.database?.url&&(n.database.url=Ce(n.database.url)),n.api?.apiKey&&(n.api.apiKey=Ce(n.api.apiKey)),n}catch{throw new Error(`Failed to parse config file: ${t}`)}}function Ce(t){return t.replace(/\$\{([^}]+)\}/g,(e,o)=>process.env[o]||e)}var fe=S__default.default.join(Pt__default.default.homedir(),".vaif"),J=S__default.default.join(fe,"auth.json"),te=process.env.VAIF_API_URL||"https://api.vaif.studio";function Ct(){A__default.default.existsSync(fe)||A__default.default.mkdirSync(fe,{recursive:true});}function Ue(t){Ct(),A__default.default.writeFileSync(J,JSON.stringify(t,null,2),"utf-8"),A__default.default.chmodSync(J,384);}function E(){if(!A__default.default.existsSync(J))return null;try{let t=A__default.default.readFileSync(J,"utf-8");return JSON.parse(t)}catch{return null}}function jt(t){let e=Re__default.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(o=>{e.question(t,n=>{e.close(),o(n);});})}function Rt(t){return new Promise(e=>{let o=Re__default.default.createInterface({input:process.stdin,output:process.stdout});process.stdin;let i=process.stdout.write.bind(process.stdout),a=false;process.stdout.write=((...r)=>a?true:i(...r)),o.question(t,r=>{a=false,process.stdout.write=i,console.log(""),o.close(),e(r);}),a=true;})}function Ut(t){let e=process.platform,o;e==="darwin"?o=`open "${t}"`:e==="win32"?o=`start "" "${t}"`:o=`xdg-open "${t}"`,child_process.exec(o,n=>{});}function kt(t){return new Promise(e=>setTimeout(e,t))}async function Nt(t){try{let e=await fetch(`${te}/auth/me`,{headers:{Authorization:`Bearer ${t}`}});if(e.ok){let o=await e.json();return {valid:!0,email:o.user?.email||o.email}}return {valid:!1}}catch{return {valid:false}}}async function Lt(t){let e=ie__default.default();e.start("Setting up authentication...");let o,n;try{let s=await fetch(`${te}/auth/cli/authorize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})});s.ok||(e.fail("Failed to initiate authentication"),console.log(f__default.default.red(`
|
|
3
|
+
Could not connect to VAIF API. Please try again later.`)),process.exit(1));let c=await s.json();o=c.code,n=c.url;}catch{e.fail("Failed to connect to VAIF API"),console.log(f__default.default.red(`
|
|
4
|
+
Could not connect to VAIF API.`)),console.log(f__default.default.gray("Check your internet connection or try: vaif login --email")),process.exit(1);}e.stop(),console.log(f__default.default.cyan(" Opening browser for authentication...")),console.log(""),console.log(f__default.default.gray(" If the browser doesn't open, visit this URL:")),console.log(f__default.default.white(` ${n}`)),console.log(""),Ut(n),e.start("Waiting for browser authentication...");let i=12e4,a=2e3,r=Date.now();for(;Date.now()-r<i;){await kt(a);try{let s=await fetch(`${te}/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:o})});if(!s.ok){let l=await s.json();(l.error==="ExpiredCode"||l.error==="InvalidCode")&&(e.fail("Authentication expired"),console.log(f__default.default.red(`
|
|
5
|
+
The authentication session expired. Please try again.`)),process.exit(1));continue}let c=await s.json();if(c.ok&&c.accessToken){let l={token:c.accessToken,email:c.user?.email,projectId:t,expiresAt:new Date(Date.now()+c.expiresIn*1e3).toISOString()};Ue(l),e.succeed("Logged in successfully"),console.log(""),c.user?.email&&console.log(f__default.default.green(` Authenticated as: ${c.user.email}`)),console.log(f__default.default.gray(` Config saved to: ${J}`)),console.log("");return}}catch{}}e.fail("Authentication timed out"),console.log(f__default.default.red(`
|
|
6
|
+
Timed out waiting for browser authentication.`)),console.log(f__default.default.gray("Try again or use: vaif login --email")),process.exit(1);}async function Dt(t){console.log(""),console.log(f__default.default.bold("VAIF CLI Login")),console.log(f__default.default.gray("Enter your VAIF account credentials")),console.log("");let e=await jt(f__default.default.cyan(" Email: "));(!e||e.trim()==="")&&(console.log(f__default.default.red(`
|
|
7
|
+
No email provided. Login cancelled.`)),process.exit(1));let o=await Rt(f__default.default.cyan(" Password: "));(!o||o.trim()==="")&&(console.log(f__default.default.red(`
|
|
8
|
+
No password provided. Login cancelled.`)),process.exit(1));let n=ie__default.default("Authenticating...").start();try{let i=await fetch(`${te}/auth/cli/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e.trim(),password:o})}),a=await i.json();(!i.ok||!a.ok)&&(n.fail("Login failed"),console.log(f__default.default.red(`
|
|
9
|
+
${a.message||"Invalid email or password."}`)),process.exit(1));let r={token:a.accessToken,email:a.user?.email,projectId:t,expiresAt:new Date(Date.now()+a.expiresIn*1e3).toISOString()};Ue(r),n.succeed("Logged in successfully"),console.log(""),a.user?.email&&console.log(f__default.default.green(` Authenticated as: ${a.user.email}`)),console.log(f__default.default.gray(` Config saved to: ${J}`)),console.log("");}catch{n.fail("Failed to connect to VAIF API"),console.log(f__default.default.red(`
|
|
10
|
+
Could not connect to VAIF API. Please try again later.`)),process.exit(1);}}async function ke(t){console.log(""),console.log(f__default.default.bold("Welcome to VAIF CLI")),console.log(f__default.default.gray("Authenticate to access your VAIF projects")),console.log(""),t.email?await Dt(t.projectId):await Lt(t.projectId),console.log(f__default.default.gray("You can now use VAIF CLI commands like:")),console.log(f__default.default.gray(" vaif pull - Pull remote schema")),console.log(f__default.default.gray(" vaif push - Push schema changes")),console.log(f__default.default.gray(" vaif generate - Generate TypeScript types")),console.log("");}async function Ne(){A__default.default.existsSync(J)?(A__default.default.unlinkSync(J),console.log(f__default.default.green("Logged out successfully"))):console.log(f__default.default.yellow("Not currently logged in"));}async function Le(){let t=E();(!t||!t.token)&&(console.log(f__default.default.yellow("Not logged in")),console.log(f__default.default.gray("Run `vaif login` to authenticate")),process.exit(1));let e=ie__default.default("Checking authentication...").start(),{valid:o,email:n}=await Nt(t.token);o||(e.fail("Session expired"),console.log(f__default.default.yellow(`
|
|
11
|
+
Your session has expired. Please login again.`)),process.exit(1)),e.succeed("Authenticated"),console.log(""),console.log(f__default.default.green(` Email: ${n||t.email||"Unknown"}`)),t.projectId&&console.log(f__default.default.green(` Project: ${t.projectId}`)),console.log("");}var Mt=process.env.VAIF_API_URL||"https://api.vaif.studio";async function Kt(t,e){let o=await fetch(`${Mt}/schema-engine/introspect/${e}`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!o.ok){let s=await o.text();throw new Error(`API introspection failed: ${s}`)}let n=await o.json();if(!n.ok||!n.schemaExists)throw new Error("Project schema does not exist yet. Push a migration first with `vaif db push`.");let i=new Map,a=[];for(let s of n.tables){let c=s.columns.map(l=>({column_name:l.name,data_type:l.type,is_nullable:l.nullable?"YES":"NO",column_default:l.default,udt_name:l.type,is_identity:l.primaryKey&&l.default?.includes("gen_random_uuid")?"YES":"NO",character_maximum_length:null,numeric_precision:null,numeric_scale:null}));i.set(s.name,c);for(let l of s.foreignKeys)a.push({constraint_name:l.constraintName,table_name:s.name,column_name:l.columnName,foreign_table_name:l.refTable,foreign_column_name:l.refColumn});}return {tables:i,enums:new Map,foreignKeys:a}}async function Bt(t,e){let o=await t.query(`
|
|
12
12
|
SELECT table_name, table_type
|
|
13
13
|
FROM information_schema.tables
|
|
14
14
|
WHERE table_schema = $1
|
|
15
15
|
AND table_type = 'BASE TABLE'
|
|
16
16
|
ORDER BY table_name
|
|
17
|
-
`,[e]),
|
|
17
|
+
`,[e]),n=await t.query(`
|
|
18
18
|
SELECT
|
|
19
19
|
table_name,
|
|
20
20
|
column_name,
|
|
@@ -29,7 +29,7 @@ Your session has expired. Please login again.`)),process.exit(1)),e.succeed("Aut
|
|
|
29
29
|
FROM information_schema.columns
|
|
30
30
|
WHERE table_schema = $1
|
|
31
31
|
ORDER BY table_name, ordinal_position
|
|
32
|
-
`,[e]),
|
|
32
|
+
`,[e]),i=await t.query(`
|
|
33
33
|
SELECT
|
|
34
34
|
tc.constraint_name,
|
|
35
35
|
tc.table_name,
|
|
@@ -45,7 +45,7 @@ Your session has expired. Please login again.`)),process.exit(1)),e.succeed("Aut
|
|
|
45
45
|
AND ccu.table_schema = tc.table_schema
|
|
46
46
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
47
47
|
AND tc.table_schema = $1
|
|
48
|
-
`,[e]),
|
|
48
|
+
`,[e]),a=await t.query(`
|
|
49
49
|
SELECT
|
|
50
50
|
t.typname as enum_name,
|
|
51
51
|
e.enumlabel as enum_value
|
|
@@ -54,24 +54,24 @@ Your session has expired. Please login again.`)),process.exit(1)),e.succeed("Aut
|
|
|
54
54
|
JOIN pg_namespace n ON n.oid = t.typnamespace
|
|
55
55
|
WHERE n.nspname = $1
|
|
56
56
|
ORDER BY t.typname, e.enumsortorder
|
|
57
|
-
`,[e]),r=new Map;for(let
|
|
58
|
-
`);return `export type ${
|
|
59
|
-
${
|
|
60
|
-
${s.join(`
|
|
61
|
-
`)}
|
|
62
|
-
}`,l=`export interface ${o}Insert {
|
|
57
|
+
`,[e]),r=new Map;for(let c of o.rows)r.set(c.table_name,[]);for(let c of n.rows){let l=r.get(c.table_name);l&&l.push(c);}let s=new Map;for(let c of a.rows){let l=s.get(c.enum_name)||[];l.push(c.enum_value),s.set(c.enum_name,l);}return {tables:r,enums:s,foreignKeys:i.rows}}var he={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 zt(t,e){let{data_type:o,udt_name:n,is_nullable:i}=t;if(e.has(n)){let s=e.get(n).map(c=>`"${c}"`).join(" | ");return i==="YES"?`(${s}) | null`:s}if(o==="ARRAY"){let r=n.replace(/^_/,"");if(e.has(r)){let l=e.get(r).map(p=>`"${p}"`).join(" | ");return i==="YES"?`(${l})[] | null`:`(${l})[]`}let s=he[r]||"unknown";return i==="YES"?`${s}[] | null`:`${s}[]`}let a=he[o]||he[n]||"unknown";return i==="YES"&&(a=`${a} | null`),a}function ye(t){return t.split(/[_\-\s]+/).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join("")}function qt(t,e){let o=ye(t),n=e.map(i=>` | "${i}"`).join(`
|
|
58
|
+
`);return `export type ${o} =
|
|
59
|
+
${n};`}function Yt(t,e,o){let n=ye(t),i=[],a=[],r=[];for(let p of e){let u=zt(p,o),d=p.column_name,g=p.column_default!==null||p.is_identity==="YES",y=p.is_nullable==="YES";i.push(` ${d}: ${u};`),g||p.column_name==="id"?a.push(` ${d}?: ${u.replace(" | null","")} | null;`):y?a.push(` ${d}?: ${u};`):a.push(` ${d}: ${u.replace(" | null","")};`),r.push(` ${d}?: ${u.replace(" | null","")} | null;`);}let s=`export interface ${n} {
|
|
63
60
|
${i.join(`
|
|
64
61
|
`)}
|
|
65
|
-
}`,
|
|
62
|
+
}`,c=`export interface ${n}Insert {
|
|
63
|
+
${a.join(`
|
|
64
|
+
`)}
|
|
65
|
+
}`,l=`export interface ${n}Update {
|
|
66
66
|
${r.join(`
|
|
67
67
|
`)}
|
|
68
|
-
}`;return {base:
|
|
69
|
-
`)}async function
|
|
70
|
-
Either:`)),console.log(f__default.default.gray(" 1. Run `vaif login` to authenticate (no DATABASE_URL needed)")),console.log(f__default.default.gray(" 2. Set DATABASE_URL in your .env file")),console.log(f__default.default.gray(" 3. Pass --connection postgresql://user:pass@host:5432/db")),process.exit(1));let g=
|
|
71
|
-
Set projectId in vaif.config.json or use VAIF_PROJECT_ID env var.`)),process.exit(1)),e.text="Introspecting schema via API...",{tables:
|
|
72
|
-
Push a migration first: vaif db push`));return}e.text=`Generating types for ${
|
|
73
|
-
Error: ${
|
|
74
|
-
Make sure your database is running and accessible.`))),process.exit(1);}}var
|
|
68
|
+
}`;return {base:s,insert:c,update:l}}function Jt(t,e,o){let n=["/**"," * 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(e.size>0){n.push("// ============ ENUMS ============"),n.push("");for(let[a,r]of e)n.push(qt(a,r)),n.push("");}n.push("// ============ TABLES ============"),n.push("");let i=[];for(let[a,r]of t){let{base:s,insert:c,update:l}=Yt(a,r,e);i.push(a),n.push(s),n.push(""),n.push(c),n.push(""),n.push(l),n.push("");}n.push("// ============ DATABASE SCHEMA ============"),n.push(""),n.push("export interface Database {");for(let a of i){let r=ye(a);n.push(` ${a}: {`),n.push(` Row: ${r};`),n.push(` Insert: ${r}Insert;`),n.push(` Update: ${r}Update;`),n.push(" };");}return n.push("}"),n.push(""),n.push("export type TableName = keyof Database;"),n.push(""),n.push("// ============ HELPER TYPES ============"),n.push(""),n.push('export type Row<T extends TableName> = Database[T]["Row"];'),n.push('export type Insert<T extends TableName> = Database[T]["Insert"];'),n.push('export type Update<T extends TableName> = Database[T]["Update"];'),n.push(""),n.join(`
|
|
69
|
+
`)}async function Ve(t){let e=ie__default.default("Loading configuration...").start();try{let o=await w(t.config),n=t.connection||o?.database?.url||process.env.DATABASE_URL,i=n&&!n.includes("${"),a,r,s;if(i){e.text="Connecting to database...";let d=new Vt__default.default.Client({connectionString:n});await d.connect(),e.text="Introspecting schema...",{tables:a,enums:r,foreignKeys:s}=await Bt(d,t.schema),await d.end();}else {let d=E();(!d||!d.token)&&(e.fail("No database connection and not logged in"),console.log(f__default.default.yellow(`
|
|
70
|
+
Either:`)),console.log(f__default.default.gray(" 1. Run `vaif login` to authenticate (no DATABASE_URL needed)")),console.log(f__default.default.gray(" 2. Set DATABASE_URL in your .env file")),console.log(f__default.default.gray(" 3. Pass --connection postgresql://user:pass@host:5432/db")),process.exit(1));let g=o?.projectId||process.env.VAIF_PROJECT_ID||d.projectId;g||(e.fail("No project ID specified"),console.log(f__default.default.yellow(`
|
|
71
|
+
Set projectId in vaif.config.json or use VAIF_PROJECT_ID env var.`)),process.exit(1)),e.text="Introspecting schema via API...",{tables:a,enums:r,foreignKeys:s}=await Kt(d.token,g);}if(a.size===0){e.warn("No tables found"),console.log(f__default.default.yellow(`
|
|
72
|
+
Push a migration first: vaif db push`));return}e.text=`Generating types for ${a.size} tables...`;let c=Jt(a,r,s),l=await Ot__default.default.format(c,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100});if(t.dryRun){e.succeed("Generated types (dry run):"),console.log(""),console.log(f__default.default.gray("\u2500".repeat(60))),console.log(l),console.log(f__default.default.gray("\u2500".repeat(60)));return}let p=S__default.default.resolve(t.output),u=S__default.default.dirname(p);A__default.default.existsSync(u)||A__default.default.mkdirSync(u,{recursive:!0}),A__default.default.writeFileSync(p,l,"utf-8"),e.succeed(`Generated types for ${a.size} tables \u2192 ${f__default.default.cyan(t.output)}`),console.log(""),console.log(f__default.default.green("Generated:")),console.log(f__default.default.gray(` Tables: ${a.size}`)),console.log(f__default.default.gray(` Enums: ${r.size}`)),console.log(""),console.log(f__default.default.gray("Import in your code:")),console.log(f__default.default.cyan(` import type { Database, Row, Insert, Update } from "${t.output.replace(/\.ts$/,"")}";`));}catch(o){e.fail("Failed to generate types"),o instanceof Error&&(console.error(f__default.default.red(`
|
|
73
|
+
Error: ${o.message}`)),o.message.includes("ECONNREFUSED")&&console.log(f__default.default.yellow(`
|
|
74
|
+
Make sure your database is running and accessible.`))),process.exit(1);}}var X=[{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"}],Oe={"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:`{
|
|
75
75
|
"name": "my-vaif-app",
|
|
76
76
|
"private": true,
|
|
77
77
|
"version": "0.1.0",
|
|
@@ -3775,94 +3775,57 @@ export const posts = pgTable("posts", {
|
|
|
3775
3775
|
|
|
3776
3776
|
return Response.json({ message: \`Hello, \${name}!\` });
|
|
3777
3777
|
}
|
|
3778
|
-
`}]},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
|
|
3779
|
-
? Which VAIF features do you want to include?`)),
|
|
3778
|
+
`}]},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 Me(){console.log(""),console.log(f__default.default.bold("Available project templates")),console.log("");let t=26,e=22;console.log(` ${f__default.default.gray("Template".padEnd(t))}${f__default.default.gray("Stack".padEnd(e))}${f__default.default.gray("Description")}`),console.log(f__default.default.gray(" "+"-".repeat(t+e+40)));for(let[o,n]of Object.entries(Oe))console.log(` ${f__default.default.cyan(o.padEnd(t))}${f__default.default.yellow(n.tag.padEnd(e))}${f__default.default.white(n.description)}`);console.log(""),console.log(f__default.default.gray("Usage:")),console.log(f__default.default.gray(" npx @vaiftech/cli init --template <name>")),console.log(f__default.default.gray(" npx @vaiftech/cli init -t nextjs-fullstack")),console.log(f__default.default.gray(" npx @vaiftech/cli init -t react-spa --features auth,database,realtime")),console.log(""),console.log(f__default.default.gray("Available features: auth, database, realtime, storage, functions")),console.log("");}async function Gt(t){if(!process.stdin.isTTY||!process.stdout.isTTY)return t;let e=new Set(t.map(n=>X.findIndex(i=>i.name===n)).filter(n=>n>=0)),o=0;return new Promise(n=>{let i=Re__default.default.createInterface({input:process.stdin,output:process.stdout});Re__default.default.emitKeypressEvents(process.stdin,i),process.stdin.setRawMode&&process.stdin.setRawMode(true);function a(){let s=X.length+2;process.stdout.write(`\x1B[${s}A`),r();}function r(){console.log(f__default.default.bold(`
|
|
3779
|
+
? Which VAIF features do you want to include?`)),X.forEach((s,c)=>{let l=e.has(c)?f__default.default.green("[x]"):"[ ]",p=c===o?f__default.default.cyan("> "):" ";console.log(`${p}${l} ${s.label} ${f__default.default.gray(`(${s.description})`)}`);}),console.log(f__default.default.gray(" (up/down to move, space to toggle, enter to confirm)"));}r(),process.stdin.on("keypress",(s,c)=>{if(c.name==="up"&&o>0)o--,a();else if(c.name==="down"&&o<X.length-1)o++,a();else if(c.name==="space")e.has(o)?e.delete(o):e.add(o),a();else if(c.name==="return"){process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close();let l=[...e].sort().map(p=>X[p].name);n(l.length>0?l:t);}else c.name==="c"&&c.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close(),process.exit(0));});})}async function be(t,e={}){let o=Oe[t];o||(console.log(f__default.default.red(`
|
|
3780
3780
|
Unknown template: ${t}`)),console.log(f__default.default.yellow(`Run 'vaif templates' to see available templates.
|
|
3781
|
-
`)),process.exit(1));let
|
|
3782
|
-
No features specified.`)),console.log(f__default.default.yellow("Usage: vaif init --template <name> --add-features <features>")),console.log(f__default.default.gray("Available features: auth, database, realtime, storage, functions")),process.exit(1)):
|
|
3783
|
-
`,"utf-8"),console.log(f__default.default.green(` merge ${
|
|
3784
|
-
`,"utf-8");}catch{}(
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
DATABASE_URL=postgresql://user:password@localhost:5432/database
|
|
3788
|
-
VAIF_API_KEY=your-api-key
|
|
3789
|
-
`,"utf-8"),console.log(f__default.default.gray("Created .env.example"))),t.typescript){let s=___default.default.resolve("src/types");U__default.default.existsSync(s)||(U__default.default.mkdirSync(s,{recursive:!0}),console.log(f__default.default.gray("Created src/types directory")));}console.log(""),console.log(f__default.default.green("VAIF initialized successfully!")),console.log(""),console.log(f__default.default.gray("Next steps:")),console.log(f__default.default.gray(" 1. Update vaif.config.json with your project ID")),console.log(f__default.default.gray(" 2. Set DATABASE_URL in your environment")),console.log(f__default.default.gray(" 3. Run: npx vaif generate")),console.log("");}}catch(o){e.fail("Failed to initialize"),o instanceof Error&&console.error(f__default.default.red(`
|
|
3790
|
-
Error: ${o.message}`)),process.exit(1);}}var Bt=process.env.VAIF_API_URL||"https://api.vaif.studio";async function qt(t,e,n="public"){let o=await fetch(`${Bt}/projects/${e}/schema?schema=${n}`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!o.ok){let s=await o.text();throw new Error(`Failed to fetch schema: ${s}`)}return o.json()}async function De(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;e.start("Loading configuration...");try{s=await A(o);}catch(r){e.fail("Failed to load config"),console.log(f__default.default.red(`
|
|
3791
|
-
Error: ${r}`)),process.exit(1);}s||(e.fail("No configuration found"),console.log(f__default.default.yellow("\nRun `vaif init` to create a configuration file.")),process.exit(1));let i=t.projectId||s.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(e.fail("No project ID specified"),console.log(f__default.default.yellow(`
|
|
3792
|
-
Set projectId in vaif.config.json or use --project-id flag.`)),process.exit(1)),e.text="Fetching remote schema...";try{let r=t.schema||s.database?.schema||"public",a=await qt(n.token,i,r);e.succeed("Schema fetched successfully");let l=t.output||___default.default.resolve("vaif.schema.json"),d={$schema:"https://vaif.studio/schemas/schema.json",projectId:i,schema:r,pulledAt:new Date().toISOString(),...a};U__default.default.writeFileSync(l,JSON.stringify(d,null,2),"utf-8"),console.log(""),console.log(f__default.default.green(`Schema saved to: ${l}`)),console.log(""),console.log(f__default.default.gray("Schema summary:")),console.log(f__default.default.gray(` Tables: ${(a.tables||[]).length}`)),console.log(f__default.default.gray(` Enums: ${(a.enums||[]).length}`)),console.log(f__default.default.gray(` Functions: ${(a.functions||[]).length}`)),console.log(""),console.log(f__default.default.gray("Next steps:")),console.log(f__default.default.gray(" - Run `vaif generate` to generate TypeScript types")),console.log(f__default.default.gray(" - Edit the schema and run `vaif push` to deploy changes")),console.log("");}catch(r){e.fail("Failed to fetch schema"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3793
|
-
Error: ${r.message}`)),process.exit(1);}}var Ue=process.env.VAIF_API_URL||"https://api.vaif.studio";function Wt(t){let e=Ee__default.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(n=>{e.question(t,o=>{e.close(),n(o);});})}async function Ht(t,e,n){let o=await fetch(`${Ue}/projects/${e}/schema/preview`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({schema:n})});if(!o.ok){let s=await o.text();throw new Error(`Failed to preview changes: ${s}`)}return o.json()}async function Xt(t,e,n){let o=await fetch(`${Ue}/projects/${e}/schema/apply`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({schema:n})});if(!o.ok){let s=await o.text();throw new Error(`Failed to apply changes: ${s}`)}return o.json()}function Qt(t){if(console.log(""),console.log(f__default.default.bold("Schema Changes:")),console.log(""),t.added.length===0&&t.modified.length===0&&t.removed.length===0){console.log(f__default.default.gray(" No changes detected. Schema is up to date."));return}if(t.added.length>0){console.log(f__default.default.green.bold(" + Added:"));for(let e of t.added)console.log(f__default.default.green(` + ${e.type}: ${e.name}`));console.log("");}if(t.modified.length>0){console.log(f__default.default.yellow.bold(" ~ Modified:"));for(let e of t.modified){console.log(f__default.default.yellow(` ~ ${e.type}: ${e.name}`));for(let n of e.changes)console.log(f__default.default.gray(` ${n}`));}console.log("");}if(t.removed.length>0){console.log(f__default.default.red.bold(" - Removed:"));for(let e of t.removed)console.log(f__default.default.red(` - ${e.type}: ${e.name}`));console.log("");}}async function $e(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;e.start("Loading configuration...");try{s=await A(o);}catch(l){e.fail("Failed to load config"),console.log(f__default.default.red(`
|
|
3794
|
-
Error: ${l}`)),process.exit(1);}s||(e.fail("No configuration found"),console.log(f__default.default.yellow("\nRun `vaif init` to create a configuration file.")),process.exit(1));let i=t.projectId||s.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(e.fail("No project ID specified"),console.log(f__default.default.yellow(`
|
|
3795
|
-
Set projectId in vaif.config.json or use --project-id flag.`)),process.exit(1));let r=t.schema||___default.default.resolve("vaif.schema.json");U__default.default.existsSync(r)||(e.fail("No local schema found"),console.log(f__default.default.yellow(`
|
|
3796
|
-
Expected schema file at: ${r}`)),console.log(f__default.default.gray("Run `vaif pull` first to fetch the current schema.")),process.exit(1));let a;try{let l=U__default.default.readFileSync(r,"utf-8");a=JSON.parse(l);}catch(l){e.fail("Failed to parse schema file"),l instanceof Error&&console.log(f__default.default.red(`
|
|
3797
|
-
Error: ${l.message}`)),process.exit(1);}e.text="Calculating schema changes...";try{let{diff:l,sql:d}=await Ht(n.token,i,a);if(e.stop(),Qt(l),l.added.length===0&&l.modified.length===0&&l.removed.length===0){console.log("");return}if(d.length>0){console.log(f__default.default.bold("SQL Migrations:")),console.log("");for(let u of d)console.log(f__default.default.gray(` ${u}`));console.log("");}if(t.dryRun){console.log(f__default.default.yellow("Dry run mode - no changes applied.")),console.log(f__default.default.gray("Remove --dry-run to apply these changes."));return}if(!t.force){l.removed.length>0&&(console.log(f__default.default.red.bold("\u26A0\uFE0F Warning: This will remove tables/columns from your database.")),console.log(f__default.default.red(" This action cannot be undone!")),console.log(""));let c=await Wt(f__default.default.cyan("Apply these changes? [y/N] "));if(c.toLowerCase()!=="y"&&c.toLowerCase()!=="yes"){console.log(f__default.default.yellow(`
|
|
3798
|
-
Cancelled. No changes applied.`));return}}e.start("Applying schema changes...");let p=await Xt(n.token,i,a);if(p.success){if(e.succeed("Schema changes applied successfully"),console.log(""),p.migrations.length>0){console.log(f__default.default.gray("Migrations applied:"));for(let u of p.migrations)console.log(f__default.default.gray(` - ${u}`));console.log("");}console.log(f__default.default.green("Your database schema is now up to date.")),console.log(f__default.default.gray("Run `vaif generate` to update your TypeScript types.")),console.log("");}else e.fail("Failed to apply some changes");}catch(l){e.fail("Failed to push schema changes"),l instanceof Error&&console.log(f__default.default.red(`
|
|
3799
|
-
Error: ${l.message}`)),process.exit(1);}}var X=process.env.VAIF_API_URL||"https://api.vaif.studio";async function Zt(t,e,n,o){let s=new URL(`${X}/functions/project/${e}`);o&&s.searchParams.set("envId",o);let i=await fetch(s.toString(),{headers:{Authorization:`Bearer ${t}`}});if(!i.ok)return null;let r=await i.json(),a=r.functions||r;return Array.isArray(a)&&a.find(l=>l.name===n)||null}async function eo(t,e,n){let o=await fetch(`${X}/functions/`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({projectId:e,name:n.name,runtime:n.runtime,entrypoint:n.entrypoint,envId:n.envId})});if(!o.ok){let s=await o.text();throw new Error(`Failed to create function: ${s}`)}return o.json()}async function to(t,e,n){let o=await fetch(`${X}/functions/${e}/source`,{method:"PUT",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({sourceCode:n})});if(!o.ok){let s=await o.text();throw new Error(`Failed to deploy source: ${s}`)}}async function oo(t,e,n){let o=new URL(`${X}/functions/project/${e}`);n&&o.searchParams.set("envId",n);let s=await fetch(o.toString(),{headers:{Authorization:`Bearer ${t}`}});if(!s.ok){let r=await s.text();throw new Error(`Failed to list functions: ${r}`)}let i=await s.json();return i.functions||i}function Oe(t){switch(___default.default.extname(t).toLowerCase()){case ".ts":return "typescript";case ".js":case ".mjs":return "nodejs";case ".py":return "python";case ".go":return "go";case ".rs":return "rust";default:return "nodejs"}}function Me(t){let e=[],n=[".ts",".js",".mjs",".py",".go",".rs"],o=["drizzle.config.ts","tsconfig.json","package.json"];if(!U__default.default.existsSync(t))return e;let s=U__default.default.readdirSync(t,{withFileTypes:true});for(let i of s){let r=___default.default.join(t,i.name);if(i.isDirectory()){if(i.name!=="node_modules"&&!i.name.startsWith(".")){let a=U__default.default.readdirSync(r,{withFileTypes:true});for(let l of a)if(l.isFile()){let d=___default.default.extname(l.name).toLowerCase();if(n.includes(d)){e.push(___default.default.join(r,l.name));break}}}}else if(i.isFile()){let a=___default.default.extname(i.name).toLowerCase();n.includes(a)&&!o.includes(i.name)&&e.push(r);}}return e}async function ze(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF Functions Deploy")),console.log(""),e.start("Scanning for function files...");let r=___default.default.resolve("functions"),a=___default.default.resolve("src/functions"),l=[];if(t.entrypoint){let c=___default.default.resolve(t.entrypoint);U__default.default.existsSync(c)||(e.fail(`File not found: ${t.entrypoint}`),process.exit(1)),l=[c];}else l=[...Me(r),...Me(a)];l.length===0&&(e.fail("No function files found"),console.log(f__default.default.yellow(`
|
|
3800
|
-
Place your functions in:`)),console.log(f__default.default.gray(" - ./functions/")),console.log(f__default.default.gray(" - ./src/functions/")),console.log(f__default.default.gray(`
|
|
3801
|
-
Or specify an entrypoint with --entrypoint`)),process.exit(1)),e.succeed(`Found ${l.length} function(s)`),t.name&&(l=l.filter(c=>___default.default.basename(c,___default.default.extname(c)).includes(t.name)),l.length===0&&(console.log(f__default.default.yellow(`
|
|
3802
|
-
No functions matching "${t.name}" found`)),process.exit(1))),console.log(""),console.log(f__default.default.gray("Functions to deploy:"));for(let c of l){let g=___default.default.basename(___default.default.dirname(c)),h=g==="functions"||g==="src"?___default.default.basename(c,___default.default.extname(c)):g,T=t.runtime||Oe(c);console.log(f__default.default.gray(` - ${h} (${T})`));}if(console.log(""),t.dryRun){console.log(f__default.default.yellow("Dry run mode - no functions deployed."));return}let d=[];for(let c of l){let g=___default.default.basename(___default.default.dirname(c)),h=g==="functions"||g==="src"?___default.default.basename(c,___default.default.extname(c)):g,T=t.runtime||Oe(c);e.start(`Deploying ${h}...`);try{let D=U__default.default.readFileSync(c,"utf-8"),$=await Zt(n.token,i,h,t.envId);$||(e.text=`Creating ${h}...`,$=await eo(n.token,i,{name:h,runtime:T,entrypoint:___default.default.basename(c),envId:t.envId})),e.text=`Deploying ${h}...`,await to(n.token,$.id,D),e.succeed(`Deployed ${h}`),d.push({name:h,success:!0});}catch(D){let $=D instanceof Error?D.message:"Unknown error";e.fail(`Failed to deploy ${h}`),d.push({name:h,success:false,error:$});}}console.log("");let p=d.filter(c=>c.success).length;if(d.filter(c=>!c.success).length===0)console.log(f__default.default.green(`\u2713 Successfully deployed ${p} function(s)`));else {console.log(f__default.default.yellow(`Deployed ${p}/${d.length} function(s)`)),console.log(""),console.log(f__default.default.red("Failed deployments:"));for(let c of d.filter(g=>!g.success))console.log(f__default.default.red(` - ${c.name}: ${c.error}`));}console.log("");}async function Be(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),process.exit(1)),e.start("Fetching functions...");try{let r=await oo(n.token,i,t.envId);if(e.stop(),r.length===0){console.log(f__default.default.yellow(`
|
|
3803
|
-
No functions found`)),console.log(f__default.default.gray("Deploy your first function with: vaif functions deploy"));return}console.log(""),console.log(f__default.default.bold(`Functions (${r.length}):`)),console.log(""),console.log(f__default.default.gray(" "+"NAME".padEnd(25)+"RUNTIME".padEnd(15)+"STATUS".padEnd(12)+"INVOCATIONS".padEnd(14)+"LAST DEPLOYED")),console.log(f__default.default.gray(" "+"-".repeat(80)));for(let a of r){let l=a.deployStatus==="deployed"?f__default.default.green:a.deployStatus==="deploying"?f__default.default.yellow:a.deployStatus==="failed"?f__default.default.red:f__default.default.gray;console.log(" "+a.name.padEnd(25)+a.runtime.padEnd(15)+l(a.deployStatus.padEnd(12))+String(a.invocationCount??0).padEnd(14)+(a.deployedAt?new Date(a.deployedAt).toLocaleDateString():"-"));}console.log("");}catch(r){e.fail("Failed to fetch functions"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3804
|
-
Error: ${r.message}`)),process.exit(1);}}var Z=process.env.VAIF_API_URL||"https://api.vaif.studio";async function no(t,e,n,o,s){let i=await fetch(`${Z}/projects/${e}/db/seed`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({table:n,records:o,truncate:s?.truncate??false})});if(!i.ok){let r=await i.text();throw new Error(`Failed to seed ${n}: ${r}`)}return i.json()}async function ao(t,e){let n=await fetch(`${Z}/projects/${e}/db/reset`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!n.ok){let o=await n.text();throw new Error(`Failed to reset database: ${o}`)}return n.json()}function ge(t){let e=[];if(!U__default.default.existsSync(t))return e;let n=U__default.default.readdirSync(t,{withFileTypes:true});for(let o of n)if(o.isFile()){let s=___default.default.extname(o.name).toLowerCase();(s===".json"||s===".ts"||s===".js")&&e.push(___default.default.join(t,o.name));}return e.sort()}async function qe(t){let e=___default.default.extname(t).toLowerCase();if(e===".json"){let n=U__default.default.readFileSync(t,"utf-8"),o=JSON.parse(n);return Array.isArray(o)?[{table:___default.default.basename(t,e),data:o}]:o.table&&o.data?[o]:Object.entries(o).map(([s,i])=>({table:s,data:i}))}else if(e===".ts"||e===".js"){let n=await import(t),o=n.default||n;return typeof o=="function"?o():o}throw new Error(`Unsupported file format: ${e}`)}async function Ye(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF Database Seed")),console.log("");let r=[];if(t.file){let p=___default.default.resolve(t.file);U__default.default.existsSync(p)||(console.log(f__default.default.red(`File not found: ${t.file}`)),process.exit(1)),r=[p];}else {let p=___default.default.resolve("seeds"),u=___default.default.resolve("prisma/seed"),c=___default.default.resolve("db/seeds");r=[...ge(p),...ge(u),...ge(c)];}r.length===0&&(console.log(f__default.default.yellow("No seed files found")),console.log(f__default.default.gray(`
|
|
3805
|
-
Place your seed files in one of these directories:`)),console.log(f__default.default.gray(" - ./seeds/")),console.log(f__default.default.gray(" - ./prisma/seed/")),console.log(f__default.default.gray(" - ./db/seeds/")),console.log(f__default.default.gray(`
|
|
3806
|
-
Or specify a file with --file`)),console.log(f__default.default.gray(`
|
|
3807
|
-
Example seed file (seeds/users.json):`)),console.log(f__default.default.gray(" [")),console.log(f__default.default.gray(' { "name": "John Doe", "email": "john@example.com" },')),console.log(f__default.default.gray(' { "name": "Jane Doe", "email": "jane@example.com" }')),console.log(f__default.default.gray(" ]")),process.exit(1)),console.log(f__default.default.gray("Seed files found:"));for(let p of r)console.log(f__default.default.gray(` - ${___default.default.relative(process.cwd(),p)}`));if(console.log(""),t.truncate&&(console.log(f__default.default.yellow("\u26A0\uFE0F Tables will be truncated before seeding")),console.log("")),t.dryRun){console.log(f__default.default.yellow("Dry run mode - no data will be inserted.")),console.log("");for(let p of r){e.start(`Loading ${___default.default.basename(p)}...`);try{let u=await qe(p);e.stop();for(let c of u)t.table&&c.table!==t.table||(console.log(f__default.default.cyan(`Table: ${c.table}`)),console.log(f__default.default.gray(` Records: ${c.data.length}`)),c.data.length>0&&console.log(f__default.default.gray(` Sample: ${JSON.stringify(c.data[0],null,2).slice(0,100)}...`)),console.log(""));}catch(u){e.fail(`Failed to load ${___default.default.basename(p)}`),u instanceof Error&&console.log(f__default.default.red(` Error: ${u.message}`));}}return}let a=[];for(let p of r){e.start(`Processing ${___default.default.basename(p)}...`);try{let u=await qe(p);e.stop();for(let c of u)if(!(t.table&&c.table!==t.table)){if(c.data.length===0){console.log(f__default.default.gray(` Skipping ${c.table} (no records)`));continue}e.start(`Seeding ${c.table} (${c.data.length} records)...`);try{let g=await no(n.token,i,c.table,c.data,{truncate:t.truncate});e.succeed(`Seeded ${c.table}: ${g.inserted} records`),a.push({table:c.table,inserted:g.inserted});}catch(g){let h=g instanceof Error?g.message:"Unknown error";e.fail(`Failed to seed ${c.table}`),a.push({table:c.table,inserted:0,error:h});}}}catch(u){e.fail(`Failed to load ${___default.default.basename(p)}`),u instanceof Error&&console.log(f__default.default.red(` Error: ${u.message}`));}}console.log("");let l=a.reduce((p,u)=>p+u.inserted,0),d=a.filter(p=>p.error).length;if(d===0)console.log(f__default.default.green(`\u2713 Successfully seeded ${l} records across ${a.length} table(s)`));else {console.log(f__default.default.yellow(`Seeded ${l} records with ${d} error(s)`)),console.log(""),console.log(f__default.default.red("Errors:"));for(let p of a.filter(u=>u.error))console.log(f__default.default.red(` - ${p.table}: ${p.error}`));}console.log("");}async function Je(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1));let r=___default.default.resolve(t.dir||"./drizzle");if(console.log(""),console.log(f__default.default.bold("VAIF Database Push")),console.log(""),!U__default.default.existsSync(r)){let u=___default.default.resolve("./migrations");U__default.default.existsSync(u)?console.log(f__default.default.gray(`Using migrations from: ${u}`)):(console.log(f__default.default.red(`Migrations directory not found: ${r}`)),console.log(f__default.default.gray(`
|
|
3808
|
-
Expected one of:`)),console.log(f__default.default.gray(" - ./drizzle/")),console.log(f__default.default.gray(" - ./migrations/")),console.log(f__default.default.gray(`
|
|
3809
|
-
Or specify with: vaif db push --dir <path>`)),process.exit(1));}let a=[],l=U__default.default.readdirSync(r,{withFileTypes:true});for(let u of l)if(u.isFile()&&u.name.endsWith(".sql"))a.push(___default.default.join(r,u.name));else if(u.isDirectory()){let c=U__default.default.readdirSync(___default.default.join(r,u.name),{withFileTypes:true});for(let g of c)g.isFile()&&g.name.endsWith(".sql")&&a.push(___default.default.join(r,u.name,g.name));}a.sort(),a.length===0&&(console.log(f__default.default.yellow("No SQL migration files found")),process.exit(1)),console.log(f__default.default.gray(`Found ${a.length} migration(s):`));for(let u of a)console.log(f__default.default.gray(` - ${___default.default.relative(process.cwd(),u)}`));if(console.log(""),t.dryRun){console.log(f__default.default.yellow("Dry run mode - no migrations will be applied.")),console.log("");for(let u of a){let c=U__default.default.readFileSync(u,"utf-8");console.log(f__default.default.cyan(`--- ${___default.default.basename(u)} ---`)),console.log(f__default.default.gray(c.slice(0,500))),c.length>500&&console.log(f__default.default.gray("...")),console.log("");}return}let d=0,p=0;for(let u of a){let c=U__default.default.readFileSync(u,"utf-8"),g=___default.default.relative(process.cwd(),u);e.start(`Applying ${g}...`);try{let h=await fetch(`${Z}/schema-engine/query/${i}`,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"Content-Type":"application/json"},body:JSON.stringify({sql:c})});if(!h.ok){let T=await h.text();throw new Error(T)}e.succeed(`Applied ${g}`),d++;}catch(h){let T=h instanceof Error?h.message:"Unknown error";e.fail(`Failed ${g}: ${T}`),p++;}}console.log(""),console.log(p===0?f__default.default.green(`Successfully applied ${d} migration(s)`):f__default.default.yellow(`Applied ${d}, failed ${p} migration(s)`)),console.log("");}async function Ge(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1));let r=___default.default.resolve(t.output||"vaif.schema.json");console.log(""),console.log(f__default.default.bold("VAIF Database Pull")),console.log(""),e.start("Pulling schema from remote...");try{let a=await fetch(`${Z}/schema-engine/introspect/${i}`,{headers:{Authorization:`Bearer ${n.token}`}});if(!a.ok){let p=await a.text();throw new Error(`Failed to pull schema: ${p}`)}let l=await a.json();U__default.default.writeFileSync(r,JSON.stringify(l,null,2),"utf-8"),e.succeed(`Schema written to ${___default.default.relative(process.cwd(),r)}`);let d=l.tables?.length??Object.keys(l).length;console.log(f__default.default.gray(` ${d} table(s) pulled`)),console.log("");}catch(a){e.fail("Failed to pull schema"),a instanceof Error&&console.log(f__default.default.red(`
|
|
3810
|
-
Error: ${a.message}`)),process.exit(1);}}async function We(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),process.exit(1)),console.log(""),console.log(f__default.default.red.bold("\u26A0\uFE0F DATABASE RESET")),console.log(""),console.log(f__default.default.red("This will:")),console.log(f__default.default.red(" - Drop all tables")),console.log(f__default.default.red(" - Delete all data")),console.log(f__default.default.red(" - Reset migrations")),console.log(""),console.log(f__default.default.red.bold("This action cannot be undone!")),console.log(""),t.force||(console.log(f__default.default.yellow("Use --force to confirm this action.")),process.exit(1)),e.start("Resetting database...");try{await ao(n.token,i),e.succeed("Database reset complete"),console.log(""),console.log(f__default.default.gray("Your database is now empty.")),console.log(f__default.default.gray("Run `vaif push` to apply your schema, then `vaif db seed` to seed data.")),console.log("");}catch(r){e.fail("Failed to reset database"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3811
|
-
Error: ${r.message}`)),process.exit(1);}}var Xe=process.env.VAIF_API_URL||"https://api.vaif.studio";function Qe(t,e,n){return t.projectId||e?.projectId||process.env.VAIF_PROJECT_ID||n.projectId||null}async function Ze(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=Qe(t,s,n);i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1));let r=t.name||`cli-key-${Date.now()}`;console.log(""),console.log(f__default.default.bold("VAIF Generate API Key")),console.log(""),e.start("Generating API key...");try{let a=await fetch(`${Xe}/projects/${i}/api-keys`,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"Content-Type":"application/json"},body:JSON.stringify({name:r})});if(!a.ok){let d=await a.text();throw new Error(`Failed to generate key: ${d}`)}let l=await a.json();e.succeed("API key generated"),console.log(""),console.log(f__default.default.green(` Name: ${l.name}`)),console.log(f__default.default.green(` Key: ${l.key}`)),console.log(""),console.log(f__default.default.yellow.bold(" Save this key now - it will not be shown again!")),console.log("");}catch(a){e.fail("Failed to generate API key"),a instanceof Error&&console.log(f__default.default.red(`
|
|
3812
|
-
Error: ${a.message}`)),process.exit(1);}}async function et(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=Qe(t,s,n);i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF API Keys")),console.log(""),e.start("Fetching API keys...");try{let r=await fetch(`${Xe}/projects/${i}/api-keys`,{headers:{Authorization:`Bearer ${n.token}`}});if(!r.ok){let u=await r.text();throw new Error(`Failed to list keys: ${u}`)}let a=await r.json(),l=a.keys||a;if(e.stop(),!Array.isArray(l)||l.length===0){console.log(f__default.default.yellow("No API keys found")),console.log(f__default.default.gray(`
|
|
3813
|
-
Generate one with: vaif keys generate`));return}let d=Math.max(8,...l.map(u=>(u.name||"").length)),p=` ${"Name".padEnd(d)} ${"Key".padEnd(24)} Created`;console.log(f__default.default.gray(p)),console.log(f__default.default.gray(" "+"-".repeat(p.length-2)));for(let u of l){let c=(u.name||"unnamed").padEnd(d),g=u.maskedKey||u.prefix||`${(u.key||"").slice(0,12)}...`,h=u.createdAt?new Date(u.createdAt).toLocaleDateString():"N/A";console.log(` ${c} ${g.padEnd(24)} ${h}`);}console.log(""),console.log(f__default.default.gray(` ${l.length} key(s) total`)),console.log("");}catch(r){e.fail("Failed to list API keys"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3814
|
-
Error: ${r.message}`)),process.exit(1);}}var z=process.env.VAIF_API_URL||"https://api.vaif.studio";function so(t,e,n){return t.projectId||e?.projectId||process.env.VAIF_PROJECT_ID||n.projectId||null}function te(){let t=I();return (!t||!t.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1)),t}async function oe(t){try{return await A(t||"vaif.config.json")}catch{return null}}function ne(t,e,n){let o=so(t,e,n);return o||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),o}async function tt(t,e,n){let o=Q__default.default(),s=te(),i=await oe(n.config),r=ne(n,i,s),a=e;if(n.fromFile)try{a=U__default.default.readFileSync(n.fromFile,"utf-8");}catch(l){console.log(f__default.default.red(`Failed to read file: ${n.fromFile}`)),l instanceof Error&&console.log(f__default.default.gray(l.message)),process.exit(1);}a||(console.log(f__default.default.red("No value provided")),console.log(f__default.default.gray("Provide a value as argument or use --from-file <path>")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF Set Secret")),console.log(""),o.start("Checking for existing secret...");try{let l=new URL(`${z}/functions/secrets/project/${r}`);n.envId&&l.searchParams.set("envId",n.envId);let d=await fetch(l.toString(),{headers:{Authorization:`Bearer ${s.token}`}});if(!d.ok)throw new Error(`Failed to check existing secrets: ${await d.text()}`);let u=(await d.json()).find(c=>c.key===t);if(u){o.text=`Updating secret "${t}"...`;let c=await fetch(`${z}/functions/secrets/${u.id}`,{method:"PUT",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({value:a})});if(!c.ok)throw new Error(`Failed to update secret: ${await c.text()}`);o.succeed(`Updated secret "${t}"`);}else {o.text=`Creating secret "${t}"...`;let c=await fetch(`${z}/functions/secrets`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({projectId:r,envId:n.envId,key:t,value:a})});if(!c.ok)throw new Error(`Failed to create secret: ${await c.text()}`);o.succeed(`Created secret "${t}"`);}console.log("");}catch(l){o.fail("Failed to set secret"),l instanceof Error&&console.log(f__default.default.red(`
|
|
3815
|
-
Error: ${l.message}`)),process.exit(1);}}async function ot(t){let e=Q__default.default(),n=te(),o=await oe(t.config),s=ne(t,o,n);console.log(""),console.log(f__default.default.bold("VAIF Secrets")),console.log(""),e.start("Fetching secrets...");try{let i=new URL(`${z}/functions/secrets/project/${s}`);t.envId&&i.searchParams.set("envId",t.envId);let r=await fetch(i.toString(),{headers:{Authorization:`Bearer ${n.token}`}});if(!r.ok)throw new Error(`Failed to list secrets: ${await r.text()}`);let a=await r.json();if(e.stop(),a.length===0){console.log(f__default.default.yellow("No secrets found")),console.log(f__default.default.gray(`
|
|
3816
|
-
Create one with: vaif secrets set <name> <value>`));return}let l=Math.max(8,...a.map(p=>p.key.length)),d=` ${"Name".padEnd(l)} Created`;console.log(f__default.default.gray(d)),console.log(f__default.default.gray(" "+"-".repeat(d.length-2)));for(let p of a){let u=p.key.padEnd(l),c=p.createdAt?new Date(p.createdAt).toLocaleDateString():"N/A";console.log(` ${u} ${c}`);}console.log(""),console.log(f__default.default.gray(` ${a.length} secret(s) total`)),console.log(f__default.default.gray(" Values are hidden. Use `vaif secrets get <name>` to reveal.")),console.log("");}catch(i){e.fail("Failed to list secrets"),i instanceof Error&&console.log(f__default.default.red(`
|
|
3817
|
-
Error: ${i.message}`)),process.exit(1);}}async function nt(t,e){let n=Q__default.default(),o=te(),s=await oe(e.config),i=ne(e,s,o);console.log(""),n.start("Fetching secret...");try{let r=new URL(`${z}/functions/secrets/project/${i}`);e.envId&&r.searchParams.set("envId",e.envId);let a=await fetch(r.toString(),{headers:{Authorization:`Bearer ${o.token}`}});if(!a.ok)throw new Error(`Failed to fetch secrets: ${await a.text()}`);let d=(await a.json()).find(c=>c.key===t);d||(n.fail(`Secret "${t}" not found`),process.exit(1));let p=await fetch(`${z}/functions/secrets/${d.id}/value`,{headers:{Authorization:`Bearer ${o.token}`}});if(!p.ok)throw new Error(`Failed to get secret value: ${await p.text()}`);let u=await p.json();n.stop(),console.log(u.value);}catch(r){n.fail("Failed to get secret"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3818
|
-
Error: ${r.message}`)),process.exit(1);}}async function at(t,e){let n=Q__default.default(),o=te(),s=await oe(e.config),i=ne(e,s,o);console.log(""),console.log(f__default.default.bold("VAIF Delete Secret")),console.log(""),n.start("Finding secret...");try{let r=new URL(`${z}/functions/secrets/project/${i}`);e.envId&&r.searchParams.set("envId",e.envId);let a=await fetch(r.toString(),{headers:{Authorization:`Bearer ${o.token}`}});if(!a.ok)throw new Error(`Failed to fetch secrets: ${await a.text()}`);let d=(await a.json()).find(u=>u.key===t);d||(n.fail(`Secret "${t}" not found`),process.exit(1)),n.text=`Deleting secret "${t}"...`;let p=await fetch(`${z}/functions/secrets/${d.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${o.token}`}});if(!p.ok)throw new Error(`Failed to delete secret: ${await p.text()}`);n.succeed(`Deleted secret "${t}"`),console.log("");}catch(r){n.fail("Failed to delete secret"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3819
|
-
Error: ${r.message}`)),process.exit(1);}}var it=process.env.VAIF_API_URL||"https://api.vaif.studio";function lo(t){try{let e=new URL(t);return e.password&&(e.password="****"),e.toString()}catch{return t.replace(/:[^@/]+@/,":****@")}}async function st(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),e.start("Fetching project info...");try{let r=await fetch(`${it}/projects/${i}`,{headers:{Authorization:`Bearer ${n.token}`}});if(!r.ok){let p=await r.text();throw new Error(`Failed to fetch project: ${p}`)}let a=await r.json();e.stop(),console.log(""),console.log(f__default.default.bold("VAIF Project Info")),console.log("");let l=16,d=(p,u)=>{console.log(` ${f__default.default.gray(p.padEnd(l))} ${u}`);};d("Name:",f__default.default.white(a.name||"N/A")),d("Project ID:",f__default.default.white(i)),d("Region:",f__default.default.white(a.region||"us-east-1")),d("Plan:",f__default.default.white(a.plan||a.tier||"free")),d("Created:",f__default.default.white(a.createdAt?new Date(a.createdAt).toLocaleDateString():"N/A")),console.log(""),d("API URL:",f__default.default.cyan(a.apiUrl||`${it}/v1`)),d("WS URL:",f__default.default.cyan(a.wsUrl||a.realtimeUrl||"N/A")),d("DB URL:",f__default.default.cyan(a.databaseUrl?lo(a.databaseUrl):"N/A")),d("Storage URL:",f__default.default.cyan(a.storageUrl||"N/A")),console.log("");}catch(r){e.fail("Failed to fetch project info"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3820
|
-
Error: ${r.message}`)),process.exit(1);}}var uo=process.env.VAIF_API_URL||"https://api.vaif.studio";async function rt(t){let e=Q__default.default(),n=I();(!n||!n.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let o=t.config||"vaif.config.json",s=null;try{s=await A(o);}catch{}let i=t.projectId||s?.projectId||process.env.VAIF_PROJECT_ID||n.projectId;i||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),e.start("Fetching project status...");try{let r=await fetch(`${uo}/projects/${i}?include=tables,functions,storage,connections`,{headers:{Authorization:`Bearer ${n.token}`}});if(!r.ok){let h=await r.text();throw new Error(`Failed to fetch project status: ${h}`)}let a=await r.json();e.stop(),console.log(""),console.log(f__default.default.bold("VAIF Project Status")),console.log("");let l=22,d=(h,T)=>{console.log(` ${f__default.default.gray(h.padEnd(l))} ${T}`);};d("Project:",f__default.default.white(a.name||i)),d("Plan:",f__default.default.white(a.plan||a.tier||"free")),console.log(""),console.log(f__default.default.gray(" --- Resources ---")),console.log("");let p=a.tableCount??a.tables?.length??"N/A",u=a.functionCount??a.functions?.length??"N/A",c=a.bucketCount??a.storage?.buckets?.length??"N/A",g=a.activeConnections??a.connections??"N/A";d("Tables:",f__default.default.white(String(p))),d("Functions:",f__default.default.white(String(u))),d("Storage Buckets:",f__default.default.white(String(c))),d("Active Connections:",f__default.default.white(String(g))),a.usage&&(console.log(""),console.log(f__default.default.gray(" --- Usage ---")),console.log(""),a.usage.dbSize&&d("Database Size:",f__default.default.white(a.usage.dbSize)),a.usage.storageSize&&d("Storage Size:",f__default.default.white(a.usage.storageSize)),a.usage.bandwidth&&d("Bandwidth:",f__default.default.white(a.usage.bandwidth)),a.usage.functionInvocations!=null&&d("Function Invocations:",f__default.default.white(String(a.usage.functionInvocations)))),console.log("");}catch(r){e.fail("Failed to fetch project status"),r instanceof Error&&console.log(f__default.default.red(`
|
|
3821
|
-
Error: ${r.message}`)),process.exit(1);}}var J=process.env.VAIF_API_URL||"https://api.vaif.studio";function fo(t){let e=Ee__default.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(n=>{e.question(t,o=>{e.close(),n(o.trim());});})}function go(t,e,n){return t.projectId||e?.projectId||process.env.VAIF_PROJECT_ID||n.projectId||null}async function mo(t){let e=Q__default.default("Fetching your projects...").start();try{let n=await fetch(`${J}/projects`,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok)return e.fail("Could not fetch projects"),null;let o=await n.json();if(!o||o.length===0)return e.fail("No projects found. Create a project at https://vaif.studio first."),null;if(o.length===1)return e.succeed(`Found project: ${f__default.default.cyan(o[0].name)} (${o[0].id})`),o[0].id;e.succeed(`Found ${o.length} projects
|
|
3822
|
-
`);for(let r=0;r<o.length;r++)console.log(f__default.default.gray(` ${r+1}.`)+` ${f__default.default.white(o[r].name)} ${f__default.default.gray(`(${o[r].id})`)}`);console.log("");let s=await fo(f__default.default.cyan(` Select a project [1-${o.length}]: `)),i=parseInt(s,10)-1;return isNaN(i)||i<0||i>=o.length?(console.log(f__default.default.red(`
|
|
3823
|
-
Invalid selection.`)),null):o[i].id}catch{return e.fail("Could not fetch projects"),null}}function ho(t){if(!t||t.length===0)return "*No tables found. Create tables in the VAIF Studio dashboard.*";let e="";for(let n of t){e+=`### \`${n.name}\`
|
|
3781
|
+
`)),process.exit(1));let n;e.features&&e.features.length>0?n=e.features.filter(d=>X.some(g=>g.name===d)):e.addOnly?(console.log(f__default.default.red(`
|
|
3782
|
+
No features specified.`)),console.log(f__default.default.yellow("Usage: vaif init --template <name> --add-features <features>")),console.log(f__default.default.gray("Available features: auth, database, realtime, storage, functions")),process.exit(1)):o.featureFiles&&Object.keys(o.featureFiles).length>0?n=await Gt(o.defaultFeatures??["database","auth"]):n=o.defaultFeatures??[],e.addOnly?(console.log(""),console.log(f__default.default.bold(`Adding features to ${f__default.default.cyan(o.name)} project...`)),console.log(f__default.default.gray(` Features: ${n.join(", ")}`)),console.log("")):(console.log(""),console.log(f__default.default.bold(`Scaffolding ${f__default.default.cyan(o.name)} template...`)),n.length>0&&console.log(f__default.default.gray(` Features: ${n.join(", ")}`)),console.log(""));let i=e.addOnly?[]:[...o.files],a=new Set,r=[];if(o.featureFiles)for(let d of n){let g=o.featureFiles[d];if(g)for(let y of g)a.add(y.path),r.push(y);}let s=i.filter(d=>!a.has(d.path)).concat(r),c=0,l=0;for(let d of s){let g=S__default.default.resolve(d.path),y=S__default.default.dirname(g);if(A__default.default.existsSync(y)||A__default.default.mkdirSync(y,{recursive:true}),d.path==="package.json"&&A__default.default.existsSync(g)&&!e.force)try{let P=JSON.parse(A__default.default.readFileSync(g,"utf-8")),O=JSON.parse(d.content),B=W=>{if(!W)return {};let Pe={};for(let[_t,ee]of Object.entries(W))!ee.startsWith("workspace:")&&!ee.startsWith("link:")&&!ee.startsWith("file:")&&(Pe[_t]=ee);return Pe};P.dependencies={...B(P.dependencies),...O.dependencies||{}},P.devDependencies={...B(P.devDependencies),...O.devDependencies||{}},O.scripts&&(P.scripts={...P.scripts||{},...O.scripts}),A__default.default.writeFileSync(g,JSON.stringify(P,null,2)+`
|
|
3783
|
+
`,"utf-8"),console.log(f__default.default.green(` merge ${d.path} (added dependencies)`)),c++;continue}catch{}if(A__default.default.existsSync(g)&&!e.force){console.log(f__default.default.yellow(` skip ${d.path} (already exists)`)),l++;continue}A__default.default.writeFileSync(g,d.content,"utf-8"),console.log(f__default.default.green(` create ${d.path}`)),c++;}console.log(""),c>0&&console.log(f__default.default.green(`Created ${c} file${c!==1?"s":""}.`)),l>0&&console.log(f__default.default.yellow(`Skipped ${l} file${l!==1?"s":""} (use --force to overwrite).`));let p={auth:{"@vaiftech/auth":"^1.0.0"},database:{},realtime:{},storage:{},functions:{}},u=S__default.default.resolve("package.json");if(A__default.default.existsSync(u)&&n.length>0)try{let d=JSON.parse(A__default.default.readFileSync(u,"utf-8")),g=!1;for(let y of n){let P=p[y];if(P)for(let[O,B]of Object.entries(P))d.dependencies?.[O]||(d.dependencies=d.dependencies||{},d.dependencies[O]=B,g=!0);}g&&A__default.default.writeFileSync(u,JSON.stringify(d,null,2)+`
|
|
3784
|
+
`,"utf-8");}catch{}(o.dependencies?.length||o.devDependencies?.length)&&(console.log(""),console.log(f__default.default.bold("Install dependencies:")),o.dependencies?.length&&console.log(f__default.default.cyan(` npm install ${o.dependencies.join(" ")}`)),o.devDependencies?.length&&console.log(f__default.default.cyan(` npm install -D ${o.devDependencies.join(" ")}`))),console.log(""),console.log(f__default.default.bold.green("Project scaffolded successfully!")),console.log(""),console.log(f__default.default.bold(" Next steps:")),o.postInstructions.forEach(d=>{console.log(f__default.default.gray(` ${d}`));}),console.log(""),console.log(f__default.default.gray(" Get your project credentials at https://console.vaif.studio/security/api-keys")),console.log("");}var Q=process.env.VAIF_API_URL||"https://api.vaif.studio";function Ht(t){let e=Re__default.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(o=>{e.question(t,n=>{e.close(),o(n.trim());});})}function Xt(t,e,o){return t.projectId||e?.projectId||process.env.VAIF_PROJECT_ID||o.projectId||null}async function Qt(t){let e=ie__default.default("Fetching your projects...").start();try{let o=await fetch(`${Q}/projects`,{headers:{Authorization:`Bearer ${t}`}});if(!o.ok)return e.fail("Could not fetch projects"),null;let n=await o.json();if(!n||n.length===0)return e.fail("No projects found. Create a project at https://vaif.studio first."),null;if(n.length===1)return e.succeed(`Found project: ${f__default.default.cyan(n[0].name)} (${n[0].id})`),n[0].id;e.succeed(`Found ${n.length} projects
|
|
3785
|
+
`);for(let r=0;r<n.length;r++)console.log(f__default.default.gray(` ${r+1}.`)+` ${f__default.default.white(n[r].name)} ${f__default.default.gray(`(${n[r].id})`)}`);console.log("");let i=await Ht(f__default.default.cyan(` Select a project [1-${n.length}]: `)),a=parseInt(i,10)-1;return isNaN(a)||a<0||a>=n.length?(console.log(f__default.default.red(`
|
|
3786
|
+
Invalid selection.`)),null):n[a].id}catch{return e.fail("Could not fetch projects"),null}}function Zt(t){if(!t||t.length===0)return "*No tables found. Create tables in the VAIF Studio dashboard.*";let e="";for(let o of t){e+=`### \`${o.name}\`
|
|
3824
3787
|
|
|
3825
3788
|
`,e+=`| Column | Type | Nullable | Default | Constraints |
|
|
3826
3789
|
`,e+=`|--------|------|----------|---------|-------------|
|
|
3827
|
-
`;for(let
|
|
3790
|
+
`;for(let n of o.columns){let i=[];n.isPrimaryKey&&i.push("PK"),n.nullable||i.push("NOT NULL");let a=o.foreignKeys?.find(r=>r.column===n.name);a&&i.push(`FK \u2192 ${a.foreignTable}.${a.foreignColumn}`),e+=`| ${n.name} | ${n.type} | ${n.nullable?"yes":"no"} | ${n.defaultValue||"-"} | ${i.join(", ")||"-"} |
|
|
3828
3791
|
`;}e+=`
|
|
3829
|
-
`;}return e}function
|
|
3830
|
-
`);
|
|
3792
|
+
`;}return e}function eo(t,e,o){let n=t.slice(0,3);if(n.length===0)return "";let i="";for(let a of n){let r=a.columns.filter(c=>!c.isPrimaryKey&&c.name!=="created_at"&&c.name!=="updated_at"),s=r.slice(0,3).map(c=>` ${c.name}: ${to(c)}`).join(`,
|
|
3793
|
+
`);i+=`### \`${a.name}\`
|
|
3831
3794
|
|
|
3832
|
-
`,
|
|
3833
|
-
const ${
|
|
3795
|
+
`,i+="```typescript\n",i+=`// Select all
|
|
3796
|
+
const ${a.name} = await vaif.from("${a.name}").select();
|
|
3834
3797
|
|
|
3835
|
-
`,
|
|
3836
|
-
const filtered = await vaif.from("${
|
|
3798
|
+
`,i+=`// Select with filter
|
|
3799
|
+
const filtered = await vaif.from("${a.name}").select().eq("${r[0]?.name||"id"}", value);
|
|
3837
3800
|
|
|
3838
|
-
`,
|
|
3839
|
-
const created = await vaif.from("${
|
|
3840
|
-
${
|
|
3801
|
+
`,i+=`// Insert
|
|
3802
|
+
const created = await vaif.from("${a.name}").insert({
|
|
3803
|
+
${s}
|
|
3841
3804
|
});
|
|
3842
3805
|
|
|
3843
|
-
`,
|
|
3844
|
-
await vaif.from("${
|
|
3806
|
+
`,i+=`// Update
|
|
3807
|
+
await vaif.from("${a.name}").update(recordId, {
|
|
3845
3808
|
${r[0]?.name||"name"}: newValue
|
|
3846
3809
|
});
|
|
3847
3810
|
|
|
3848
|
-
`,
|
|
3849
|
-
await vaif.from("${
|
|
3850
|
-
`,
|
|
3811
|
+
`,i+=`// Delete
|
|
3812
|
+
await vaif.from("${a.name}").delete(recordId);
|
|
3813
|
+
`,i+="```\n\n",a===n[0]&&(i+=`#### Direct REST API (fetch)
|
|
3851
3814
|
|
|
3852
|
-
`,
|
|
3853
|
-
`,
|
|
3854
|
-
`,
|
|
3855
|
-
`,
|
|
3856
|
-
`,
|
|
3815
|
+
`,i+="```typescript\n",i+=`// GET all rows (returns { data: [...], count: N })
|
|
3816
|
+
`,i+=`const res = await fetch("${e}/generated/${a.name}", {
|
|
3817
|
+
`,i+=` headers: { "x-vaif-key": "${o}" },
|
|
3818
|
+
`,i+=`});
|
|
3819
|
+
`,i+=`const { data } = await res.json();
|
|
3857
3820
|
|
|
3858
|
-
`,
|
|
3859
|
-
`,
|
|
3860
|
-
`,
|
|
3861
|
-
`,
|
|
3862
|
-
`,
|
|
3863
|
-
`,
|
|
3821
|
+
`,i+=`// GET single row (returns { data: {...} })
|
|
3822
|
+
`,i+=`const res2 = await fetch("${e}/generated/${a.name}/\${id}", {
|
|
3823
|
+
`,i+=` headers: { "x-vaif-key": "${o}" },
|
|
3824
|
+
`,i+=`});
|
|
3825
|
+
`,i+=`const { data: record } = await res2.json();
|
|
3826
|
+
`,i+="```\n\n");}return i}function to(t){let e=t.type.toLowerCase();return e.includes("uuid")?'"crypto.randomUUID()"':e.includes("int")||e.includes("serial")?"42":e.includes("bool")?"true":e.includes("timestamp")||e.includes("date")?'"new Date().toISOString()"':e.includes("json")?"{}":e.includes("float")||e.includes("numeric")||e.includes("decimal")||e.includes("double")?"3.14":`"example_${t.name}"`}function oo(t){let{projectId:e,apiKey:o,apiUrl:n,projectName:i,schema:a}=t,r=Zt(a.tables),s=eo(a.tables,n,o);return `# VAIF Studio Backend
|
|
3864
3827
|
|
|
3865
|
-
This project uses **VAIF Studio** as its backend. Project: **${
|
|
3828
|
+
This project uses **VAIF Studio** as its backend. Project: **${i}** (\`${e}\`).
|
|
3866
3829
|
|
|
3867
3830
|
## SDK Setup
|
|
3868
3831
|
|
|
@@ -3874,9 +3837,9 @@ npm install @vaiftech/client
|
|
|
3874
3837
|
import { createVaifClient } from "@vaiftech/client";
|
|
3875
3838
|
|
|
3876
3839
|
const vaif = createVaifClient({
|
|
3877
|
-
baseUrl: "${
|
|
3840
|
+
baseUrl: "${n}",
|
|
3878
3841
|
projectId: "${e}",
|
|
3879
|
-
apiKey: "${
|
|
3842
|
+
apiKey: "${o}",
|
|
3880
3843
|
});
|
|
3881
3844
|
\`\`\`
|
|
3882
3845
|
|
|
@@ -3886,7 +3849,7 @@ ${r}
|
|
|
3886
3849
|
|
|
3887
3850
|
## CRUD Examples
|
|
3888
3851
|
|
|
3889
|
-
${
|
|
3852
|
+
${s}
|
|
3890
3853
|
|
|
3891
3854
|
## Authentication (End-User Auth)
|
|
3892
3855
|
|
|
@@ -3903,7 +3866,7 @@ VAIF provides **project-scoped** authentication for your app's end-users. All au
|
|
|
3903
3866
|
### Signup
|
|
3904
3867
|
|
|
3905
3868
|
\`\`\`typescript
|
|
3906
|
-
const res = await fetch("${
|
|
3869
|
+
const res = await fetch("${n}/projects/${e}/auth/signup", {
|
|
3907
3870
|
method: "POST",
|
|
3908
3871
|
headers: { "Content-Type": "application/json" },
|
|
3909
3872
|
body: JSON.stringify({
|
|
@@ -3919,7 +3882,7 @@ const { accessToken, expiresIn, user } = await res.json();
|
|
|
3919
3882
|
### Login
|
|
3920
3883
|
|
|
3921
3884
|
\`\`\`typescript
|
|
3922
|
-
const res = await fetch("${
|
|
3885
|
+
const res = await fetch("${n}/projects/${e}/auth/login", {
|
|
3923
3886
|
method: "POST",
|
|
3924
3887
|
headers: { "Content-Type": "application/json" },
|
|
3925
3888
|
body: JSON.stringify({
|
|
@@ -3935,7 +3898,7 @@ const { accessToken, expiresIn, user } = await res.json();
|
|
|
3935
3898
|
\`\`\`typescript
|
|
3936
3899
|
// Refresh token is stored as httpOnly cookie (project_refresh_token)
|
|
3937
3900
|
// and sent automatically with same-origin requests
|
|
3938
|
-
const res = await fetch("${
|
|
3901
|
+
const res = await fetch("${n}/projects/${e}/auth/refresh", {
|
|
3939
3902
|
method: "POST",
|
|
3940
3903
|
credentials: "include", // sends the httpOnly cookie
|
|
3941
3904
|
});
|
|
@@ -3948,7 +3911,7 @@ const { accessToken, expiresIn, user } = await res.json();
|
|
|
3948
3911
|
// Store the access token and use it for authenticated requests
|
|
3949
3912
|
const headers = {
|
|
3950
3913
|
Authorization: \\\`Bearer \\\${accessToken}\\\`,
|
|
3951
|
-
"x-vaif-key": "${
|
|
3914
|
+
"x-vaif-key": "${o}",
|
|
3952
3915
|
};
|
|
3953
3916
|
|
|
3954
3917
|
// The JWT contains: { sub: userId, email, projectId, type: "project_user" }
|
|
@@ -4055,7 +4018,7 @@ Enable realtime on your tables, then subscribe to live changes:
|
|
|
4055
4018
|
|
|
4056
4019
|
\`\`\`typescript
|
|
4057
4020
|
// 1. Enable realtime on tables via API
|
|
4058
|
-
await fetch("${
|
|
4021
|
+
await fetch("${n}/realtime/install", {
|
|
4059
4022
|
method: "POST",
|
|
4060
4023
|
headers: {
|
|
4061
4024
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4104,7 +4067,7 @@ Control who can access storage buckets with RLS-style policies:
|
|
|
4104
4067
|
|
|
4105
4068
|
\`\`\`typescript
|
|
4106
4069
|
// Create a policy: only the uploader can read their own files
|
|
4107
|
-
await fetch("${
|
|
4070
|
+
await fetch("${n}/storage/buckets/\${bucketId}/policies", {
|
|
4108
4071
|
method: "POST",
|
|
4109
4072
|
headers: {
|
|
4110
4073
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4118,7 +4081,7 @@ await fetch("${o}/storage/buckets/\${bucketId}/policies", {
|
|
|
4118
4081
|
});
|
|
4119
4082
|
|
|
4120
4083
|
// Create a policy: authenticated users can upload
|
|
4121
|
-
await fetch("${
|
|
4084
|
+
await fetch("${n}/storage/buckets/\${bucketId}/policies", {
|
|
4122
4085
|
method: "POST",
|
|
4123
4086
|
headers: {
|
|
4124
4087
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4138,7 +4101,7 @@ Create and deploy serverless functions:
|
|
|
4138
4101
|
|
|
4139
4102
|
\`\`\`typescript
|
|
4140
4103
|
// 1. Create a function
|
|
4141
|
-
const fn = await fetch("${
|
|
4104
|
+
const fn = await fetch("${n}/functions", {
|
|
4142
4105
|
method: "POST",
|
|
4143
4106
|
headers: {
|
|
4144
4107
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4154,7 +4117,7 @@ const fn = await fetch("${o}/functions", {
|
|
|
4154
4117
|
});
|
|
4155
4118
|
|
|
4156
4119
|
// 2. Deploy source code
|
|
4157
|
-
await fetch(\`${
|
|
4120
|
+
await fetch(\`${n}/functions/\${fn.id}/source\`, {
|
|
4158
4121
|
method: "PUT",
|
|
4159
4122
|
headers: {
|
|
4160
4123
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4228,7 +4191,7 @@ API keys are project-scoped and used for data-plane authentication (CRUD, storag
|
|
|
4228
4191
|
|
|
4229
4192
|
\`\`\`typescript
|
|
4230
4193
|
// Create a new API key
|
|
4231
|
-
const { key } = await fetch("${
|
|
4194
|
+
const { key } = await fetch("${n}/projects/${e}/api-keys", {
|
|
4232
4195
|
method: "POST",
|
|
4233
4196
|
headers: {
|
|
4234
4197
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4238,18 +4201,18 @@ const { key } = await fetch("${o}/projects/${e}/api-keys", {
|
|
|
4238
4201
|
}).then(r => r.json());
|
|
4239
4202
|
|
|
4240
4203
|
// List keys
|
|
4241
|
-
const keys = await fetch("${
|
|
4204
|
+
const keys = await fetch("${n}/projects/${e}/api-keys", {
|
|
4242
4205
|
headers: { Authorization: \`Bearer \${token}\` },
|
|
4243
4206
|
}).then(r => r.json());
|
|
4244
4207
|
|
|
4245
4208
|
// Rotate a key (generates new secret, old key stops working)
|
|
4246
|
-
await fetch(\`${
|
|
4209
|
+
await fetch(\`${n}/projects/${e}/api-keys/\${keyId}/rotate\`, {
|
|
4247
4210
|
method: "POST",
|
|
4248
4211
|
headers: { Authorization: \`Bearer \${token}\` },
|
|
4249
4212
|
});
|
|
4250
4213
|
|
|
4251
4214
|
// Revoke a key
|
|
4252
|
-
await fetch(\`${
|
|
4215
|
+
await fetch(\`${n}/projects/${e}/api-keys/\${keyId}/revoke\`, {
|
|
4253
4216
|
method: "POST",
|
|
4254
4217
|
headers: { Authorization: \`Bearer \${token}\` },
|
|
4255
4218
|
});
|
|
@@ -4261,7 +4224,7 @@ Secrets are encrypted at rest and injected into function invocations at runtime.
|
|
|
4261
4224
|
|
|
4262
4225
|
\`\`\`typescript
|
|
4263
4226
|
// Set a secret (via API)
|
|
4264
|
-
await fetch("${
|
|
4227
|
+
await fetch("${n}/functions/secrets", {
|
|
4265
4228
|
method: "POST",
|
|
4266
4229
|
headers: {
|
|
4267
4230
|
Authorization: \`Bearer \${token}\`,
|
|
@@ -4333,9 +4296,9 @@ This generates: \\\`WHERE status = 'active' AND (role = 'admin' OR role = 'moder
|
|
|
4333
4296
|
### Full-Text Search
|
|
4334
4297
|
|
|
4335
4298
|
\`\`\`typescript
|
|
4336
|
-
const results = await fetch("${
|
|
4299
|
+
const results = await fetch("${n}/generated/posts/search", {
|
|
4337
4300
|
method: "POST",
|
|
4338
|
-
headers: { "x-vaif-key": "${
|
|
4301
|
+
headers: { "x-vaif-key": "${o}", "Content-Type": "application/json" },
|
|
4339
4302
|
body: JSON.stringify({
|
|
4340
4303
|
query: "search term",
|
|
4341
4304
|
columns: ["title", "body"],
|
|
@@ -4348,9 +4311,9 @@ const results = await fetch("${o}/generated/posts/search", {
|
|
|
4348
4311
|
### Aggregation
|
|
4349
4312
|
|
|
4350
4313
|
\`\`\`typescript
|
|
4351
|
-
const stats = await fetch("${
|
|
4314
|
+
const stats = await fetch("${n}/generated/orders/aggregate", {
|
|
4352
4315
|
method: "POST",
|
|
4353
|
-
headers: { "x-vaif-key": "${
|
|
4316
|
+
headers: { "x-vaif-key": "${o}", "Content-Type": "application/json" },
|
|
4354
4317
|
body: JSON.stringify({
|
|
4355
4318
|
aggregates: [
|
|
4356
4319
|
{ fn: "count", column: "*" },
|
|
@@ -4377,9 +4340,9 @@ Returns posts with \\\`author_id_included\\\` and \\\`category_id_included\\\` o
|
|
|
4377
4340
|
Insert or update on conflict:
|
|
4378
4341
|
|
|
4379
4342
|
\`\`\`typescript
|
|
4380
|
-
const result = await fetch("${
|
|
4343
|
+
const result = await fetch("${n}/generated/users", {
|
|
4381
4344
|
method: "POST",
|
|
4382
|
-
headers: { "x-vaif-key": "${
|
|
4345
|
+
headers: { "x-vaif-key": "${o}", "Content-Type": "application/json" },
|
|
4383
4346
|
body: JSON.stringify({
|
|
4384
4347
|
email: "alice@example.com",
|
|
4385
4348
|
name: "Alice",
|
|
@@ -4464,7 +4427,787 @@ The \`.mcp.json\` file configures an MCP server that gives Claude Code direct ac
|
|
|
4464
4427
|
| \`enable_realtime\`, \`realtime_status\` | Realtime subscriptions |
|
|
4465
4428
|
|
|
4466
4429
|
> **Note**: MCP tools are only available to the main Claude Code session, not to spawned sub-agents (Task tool). The main session should handle all VAIF backend operations directly.
|
|
4467
|
-
`}async function
|
|
4468
|
-
`)),
|
|
4469
|
-
Tip: pass --project-id <id> or set projectId in vaif.config.json`)),process.exit(1)));let r=
|
|
4470
|
-
`,"utf-8"),e.succeed(`Written ${f__default.default.cyan(".mcp.json")}`);}if(!t.skipClaudeMd){e.start("Writing CLAUDE.md...");let u=bo({projectId:i,apiKey:p,apiUrl:d,projectName:l,schema:a}),c=___default.default.join(r,"CLAUDE.md");U__default.default.writeFileSync(c,u,"utf-8"),e.succeed(`Written ${f__default.default.cyan("CLAUDE.md")}`);}console.log(""),console.log(f__default.default.green.bold(" Claude Code integration configured!")),console.log(""),t.skipMcp||console.log(f__default.default.gray(" MCP Server: ")+f__default.default.white(".mcp.json")),t.skipClaudeMd||console.log(f__default.default.gray(" Context: ")+f__default.default.white("CLAUDE.md")),console.log(""),console.log(f__default.default.bold(" Next steps:")),console.log(f__default.default.gray(" 1. Open this project in Claude Code")),console.log(f__default.default.gray(" 2. The MCP server auto-connects to your VAIF project")),console.log(f__default.default.gray(" 3. Ask Claude to query, modify, or build against your schema")),console.log("");}var Ao=module$1.createRequire(j),{version:ut}=Ao("../package.json"),he=f__default.default.hex("#00f0ff"),ye=f__default.default.hex("#7b61ff"),ve=f__default.default.hex("#ff3dff"),be=f__default.default.hex("#00ff9d"),S=f__default.default.hex("#555570"),B=f__default.default.hex("#00f0ff");function wo(){console.log(""),console.log(he(" \u2566 \u2566")+ye("\u2554\u2550\u2557\u2566")+ve("\u2554\u2550\u2557 ")+be("\u2554\u2550\u2557\u2566 \u2566")),console.log(he(" \u255A\u2557\u2554\u255D")+ye("\u2560\u2550\u2563\u2551")+ve("\u2560\u2563 ")+be("\u2551 \u2551 \u2551")),console.log(he(" \u255A\u255D ")+ye("\u2569 \u2569\u2569")+ve("\u255A ")+be("\u255A\u2550\u255D\u2569\u2550\u255D\u2569")),console.log(""),console.log(S(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(B(" VAIF Studio CLI")+S(` v${ut}`)),console.log(S(" Build full-stack apps at lightning speed")),console.log(S(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(""),console.log(f__default.default.bold(" Quick Start")),console.log(S(" $ ")+B("vaif login")+S(" Authenticate")),console.log(S(" $ ")+B("vaif init -t react-spa")+S(" Scaffold project")),console.log(S(" $ ")+B("vaif db push")+S(" Push migrations")),console.log(S(" $ ")+B("vaif generate")+S(" Generate types")),console.log(S(" $ ")+B("vaif functions deploy")+S(" Deploy functions")),console.log(""),console.log(f__default.default.bold(" Categories")),console.log(S(" auth ")+f__default.default.white("login, logout, whoami")),console.log(S(" project ")+f__default.default.white("init, templates, info, status")),console.log(S(" schema ")+f__default.default.white("pull, push, generate")),console.log(S(" database ")+f__default.default.white("db push, db pull, db seed, db reset")),console.log(S(" deploy ")+f__default.default.white("functions deploy, functions list")),console.log(S(" security ")+f__default.default.white("keys, secrets")),console.log(S(" ai ")+f__default.default.white("claude-setup")),console.log(""),console.log(S(" Run ")+B("vaif <command> --help")+S(" for details")),console.log(S(" Docs: ")+f__default.default.underline("https://docs.vaif.studio")),console.log("");}commander.program.name("vaif").description("VAIF CLI - Type generation and development tools").version(ut);commander.program.command("login").description("Authenticate with VAIF (opens browser)").option("-e, --email","Login with email/password instead of browser").option("-p, --project-id <id>","Default project ID").action(xe);commander.program.command("logout").description("Log out and remove stored credentials").action(Pe);commander.program.command("whoami").description("Show current authenticated user").action(Fe);commander.program.command("init").description("Initialize VAIF configuration in your project").option("--typescript","Setup for TypeScript project").option("-f, --force","Overwrite existing config").option("-t, --template <name>","Scaffold from a template (run vaif templates for list)").option("--features <features>","Comma-separated features to include: auth,database,realtime,storage,functions").option("--add-features <features>","Add features to an existing project (requires --template)").action(Le);commander.program.command("templates").alias("tpl").description("List available project templates").action(Ne);commander.program.command("info").description("Show project information (name, region, URLs)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").action(st);commander.program.command("status").description("Show project status (tables, functions, storage, connections)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").action(rt);commander.program.command("pull").description("Pull database schema from your VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-o, --output <path>","Output file path","vaif.schema.json").option("-s, --schema <name>","Schema name","public").option("-p, --project-id <id>","Project ID (overrides config)").action(De);commander.program.command("push").description("Push local schema changes to your VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-s, --schema <path>","Schema file path","vaif.schema.json").option("-p, --project-id <id>","Project ID (overrides config)").option("--dry-run","Preview changes without applying").option("-f, --force","Apply changes without confirmation").action($e);commander.program.command("generate").alias("gen").description("Generate TypeScript types from your database schema").option("-c, --connection <url>","Database connection string").option("-o, --output <path>","Output file path","./src/types/database.ts").option("--schema <name>","Schema name","public").option("--config <path>","Config file path","vaif.config.json").option("--dry-run","Preview generated types without writing").action(je);var pt=commander.program.command("functions").alias("fn").description("Manage serverless functions");pt.command("deploy").description("Deploy functions to your VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID").option("-n, --name <name>","Function name filter").option("-r, --runtime <runtime>","Runtime (nodejs, typescript, python)").option("--entrypoint <file>","Specific entrypoint file").option("--dry-run","Preview deployment without deploying").action(ze);pt.command("list").alias("ls").description("List deployed functions").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID").action(Be);var ae=commander.program.command("db").description("Database management commands");ae.command("push").description("Push local Drizzle migrations to VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-d, --dir <path>","Migrations directory","./drizzle").option("--dry-run","Preview without applying").action(Je);ae.command("pull").description("Pull schema from VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-o, --output <path>","Output file","vaif.schema.json").action(Ge);ae.command("seed").description("Seed your database with test data").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-f, --file <path>","Specific seed file").option("-t, --table <name>","Seed specific table only").option("--truncate","Truncate tables before seeding").option("--dry-run","Preview seeding without inserting data").action(Ye);ae.command("reset").description("Reset database (drop all tables and data)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-f, --force","Confirm reset (required)").action(We);var ft=commander.program.command("keys").description("Manage API keys");ft.command("generate").description("Generate a new API key").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-n, --name <name>","Key name").action(Ze);ft.command("list").alias("ls").description("List API keys").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").action(et);var ie=commander.program.command("secrets").alias("sec").description("Manage function secrets");ie.command("set <name> [value]").description("Create or update a secret").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").option("--from-file <path>","Read secret value from a file").action(tt);ie.command("list").alias("ls").description("List all secrets (names only)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").action(ot);ie.command("get <name>").description("Reveal a secret value").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").action(nt);ie.command("delete <name>").description("Delete a secret").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").action(at);commander.program.command("claude-setup").description("Configure Claude Code integration (MCP server + CLAUDE.md)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID").option("-k, --api-key <key>","API key for MCP server").option("--skip-mcp","Skip generating .mcp.json").option("--skip-claude-md","Skip generating CLAUDE.md").option("-o, --output-dir <dir>","Output directory",".").action(dt);process.argv.slice(2).length||(wo(),process.exit(0));commander.program.parse(process.argv);
|
|
4430
|
+
`}async function oe(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=Xt(t,i,o);a||(console.log(f__default.default.yellow(`No project ID specified \u2014 fetching your projects...
|
|
4431
|
+
`)),a=await Qt(o.token),a||(console.log(f__default.default.gray(`
|
|
4432
|
+
Tip: pass --project-id <id> or set projectId in vaif.config.json`)),process.exit(1)));let r=S__default.default.resolve(t.outputDir||".");console.log(""),console.log(f__default.default.bold("VAIF Claude Code Setup")),console.log(f__default.default.gray(` Project: ${a}`)),console.log(""),e.start("Fetching database schema...");let s={tables:[]};try{let u=await fetch(`${Q}/schema-engine/introspect/${a}`,{headers:{Authorization:`Bearer ${o.token}`}});u.ok?(s=await u.json(),e.succeed(`Fetched schema (${s.tables?.length||0} tables)`)):e.warn("Could not fetch schema \u2014 continuing without it");}catch{e.warn("Could not fetch schema \u2014 continuing without it");}e.start("Fetching project info...");let c=a,l=Q;try{let u=await fetch(`${Q}/projects/${a}`,{headers:{Authorization:`Bearer ${o.token}`}});if(u.ok){let d=await u.json(),g=d.project||d;c=g.name||a,l=g.apiUrl||Q,e.succeed(`Project: ${c}`);}else e.warn("Could not fetch project info \u2014 using defaults");}catch{e.warn("Could not fetch project info \u2014 using defaults");}let p=t.apiKey||i?.api?.apiKey||"";if(!p){e.start("Generating API key for Claude Code...");try{let u=`claude-code-${Date.now()}`,d=await fetch(`${Q}/projects/${a}/api-keys`,{method:"POST",headers:{Authorization:`Bearer ${o.token}`,"Content-Type":"application/json"},body:JSON.stringify({name:u,scopes:["crud","realtime","functions","storage"]})});if(d.ok){let g=await d.json();p=g.apiKey||g.key,e.succeed(`Generated API key: ${u}`);}else e.fail("Could not auto-generate API key"),console.log(f__default.default.yellow(" Pass one with --api-key or generate via `vaif keys generate`")),process.exit(1);}catch{e.fail("Could not auto-generate API key"),console.log(f__default.default.yellow(" Pass one with --api-key or generate via `vaif keys generate`")),process.exit(1);}}if(!t.skipMcp){e.start("Writing .mcp.json...");let u={mcpServers:{"vaif-studio":{command:"npx",args:["@vaiftech/mcp"],env:{VAIF_API_KEY:p,VAIF_PROJECT_ID:a,VAIF_API_URL:l,VAIF_AUTH_TOKEN:o.token}}}},d=S__default.default.join(r,".mcp.json");A__default.default.writeFileSync(d,JSON.stringify(u,null,2)+`
|
|
4433
|
+
`,"utf-8"),e.succeed(`Written ${f__default.default.cyan(".mcp.json")}`);}if(!t.skipClaudeMd){e.start("Writing CLAUDE.md...");let u=oo({projectId:a,apiKey:p,apiUrl:l,projectName:c,schema:s}),d=S__default.default.join(r,"CLAUDE.md");A__default.default.writeFileSync(d,u,"utf-8"),e.succeed(`Written ${f__default.default.cyan("CLAUDE.md")}`);}console.log(""),console.log(f__default.default.green.bold(" Claude Code integration configured!")),console.log(""),t.skipMcp||console.log(f__default.default.gray(" MCP Server: ")+f__default.default.white(".mcp.json")),t.skipClaudeMd||console.log(f__default.default.gray(" Context: ")+f__default.default.white("CLAUDE.md")),console.log(""),console.log(f__default.default.bold(" Next steps:")),console.log(f__default.default.gray(" 1. Open this project in Claude Code")),console.log(f__default.default.gray(" 2. The MCP server auto-connects to your VAIF project")),console.log(f__default.default.gray(" 3. Ask Claude to query, modify, or build against your schema")),console.log("");}var ne={base:`# VAIF Studio Backend
|
|
4434
|
+
|
|
4435
|
+
This project uses **VAIF Studio** as its backend.
|
|
4436
|
+
|
|
4437
|
+
## SDK Setup
|
|
4438
|
+
|
|
4439
|
+
\`\`\`bash
|
|
4440
|
+
npm install @vaiftech/client
|
|
4441
|
+
\`\`\`
|
|
4442
|
+
|
|
4443
|
+
\`\`\`typescript
|
|
4444
|
+
import { createVaifClient } from "@vaiftech/client";
|
|
4445
|
+
|
|
4446
|
+
const vaif = createVaifClient({
|
|
4447
|
+
baseUrl: "https://api.vaif.studio",
|
|
4448
|
+
projectId: process.env.VAIF_PROJECT_ID!,
|
|
4449
|
+
apiKey: process.env.VAIF_API_KEY!,
|
|
4450
|
+
});
|
|
4451
|
+
\`\`\`
|
|
4452
|
+
|
|
4453
|
+
## MCP Server
|
|
4454
|
+
|
|
4455
|
+
This project includes an MCP server for Claude Code integration. Tools available:
|
|
4456
|
+
|
|
4457
|
+
- **Database**: list_tables, describe_table, query_rows, insert_row, update_row, delete_row
|
|
4458
|
+
- **Schema**: get_schema, create_tables
|
|
4459
|
+
- **Storage**: list_buckets, create_bucket, list_files, get_signed_url
|
|
4460
|
+
- **Functions**: list_functions, invoke_function, create_function, deploy_function
|
|
4461
|
+
- **Auth**: list_api_keys, create_api_key
|
|
4462
|
+
- **Realtime**: realtime_status, enable_realtime
|
|
4463
|
+
|
|
4464
|
+
## Database
|
|
4465
|
+
|
|
4466
|
+
\`\`\`typescript
|
|
4467
|
+
// Query
|
|
4468
|
+
const { data } = await vaif.from("table_name").select().eq("column", value);
|
|
4469
|
+
|
|
4470
|
+
// Insert
|
|
4471
|
+
const { data } = await vaif.from("table_name").insert({ column: value });
|
|
4472
|
+
|
|
4473
|
+
// Update
|
|
4474
|
+
await vaif.from("table_name").update({ column: newValue }).eq("id", recordId);
|
|
4475
|
+
|
|
4476
|
+
// Delete
|
|
4477
|
+
await vaif.from("table_name").delete().eq("id", recordId);
|
|
4478
|
+
\`\`\`
|
|
4479
|
+
|
|
4480
|
+
## Authentication
|
|
4481
|
+
|
|
4482
|
+
\`\`\`typescript
|
|
4483
|
+
// Sign up
|
|
4484
|
+
await vaif.auth.signUp({ email, password });
|
|
4485
|
+
|
|
4486
|
+
// Sign in
|
|
4487
|
+
const { data } = await vaif.auth.signIn({ email, password });
|
|
4488
|
+
|
|
4489
|
+
// OAuth
|
|
4490
|
+
await vaif.auth.signInWithOAuth({ provider: "google", redirectTo: callbackUrl });
|
|
4491
|
+
|
|
4492
|
+
// Get current user
|
|
4493
|
+
const user = await vaif.auth.getUser();
|
|
4494
|
+
\`\`\`
|
|
4495
|
+
|
|
4496
|
+
## Storage
|
|
4497
|
+
|
|
4498
|
+
\`\`\`typescript
|
|
4499
|
+
// Upload
|
|
4500
|
+
await vaif.storage.from("bucket").upload("path/file.png", file);
|
|
4501
|
+
|
|
4502
|
+
// Signed URL
|
|
4503
|
+
const { url } = await vaif.storage.from("bucket").createSignedUrl("path/file.png", 3600);
|
|
4504
|
+
|
|
4505
|
+
// List files
|
|
4506
|
+
const { data } = await vaif.storage.from("bucket").list("path/");
|
|
4507
|
+
\`\`\`
|
|
4508
|
+
|
|
4509
|
+
## Functions
|
|
4510
|
+
|
|
4511
|
+
\`\`\`typescript
|
|
4512
|
+
// Invoke
|
|
4513
|
+
const result = await vaif.functions.invoke("function_name", { body: { key: "value" } });
|
|
4514
|
+
\`\`\`
|
|
4515
|
+
|
|
4516
|
+
> Function names must be alphanumeric + underscores only (\`^[a-zA-Z0-9_]+$\`).
|
|
4517
|
+
|
|
4518
|
+
## Realtime
|
|
4519
|
+
|
|
4520
|
+
\`\`\`typescript
|
|
4521
|
+
const subscription = vaif.realtime
|
|
4522
|
+
.channel("table_name")
|
|
4523
|
+
.on("INSERT", (payload) => console.log("New:", payload.new))
|
|
4524
|
+
.on("UPDATE", (payload) => console.log("Updated:", payload.new))
|
|
4525
|
+
.on("DELETE", (payload) => console.log("Removed:", payload.old))
|
|
4526
|
+
.subscribe();
|
|
4527
|
+
\`\`\`
|
|
4528
|
+
|
|
4529
|
+
## Filter Operators
|
|
4530
|
+
|
|
4531
|
+
| Operator | Description | Example |
|
|
4532
|
+
|----------|-------------|---------|
|
|
4533
|
+
| eq | Equal | \`.eq("status", "active")\` |
|
|
4534
|
+
| neq | Not equal | \`.neq("status", "deleted")\` |
|
|
4535
|
+
| gt / gte | Greater than | \`.gt("age", 18)\` |
|
|
4536
|
+
| lt / lte | Less than | \`.lt("price", 100)\` |
|
|
4537
|
+
| in | In array | \`.in("role", ["admin", "editor"])\` |
|
|
4538
|
+
| like / ilike | Pattern match | \`.ilike("name", "%john%")\` |
|
|
4539
|
+
| is | IS NULL check | \`.is("deleted_at", null)\` |
|
|
4540
|
+
|
|
4541
|
+
## Auth Headers
|
|
4542
|
+
|
|
4543
|
+
| Mode | Header | Used For |
|
|
4544
|
+
|------|--------|----------|
|
|
4545
|
+
| API Key | \`x-vaif-key: vk_xxx\` | Data-plane: CRUD, storage, functions |
|
|
4546
|
+
| JWT Token | \`Authorization: Bearer <jwt>\` | Control-plane: schema, project management |
|
|
4547
|
+
|
|
4548
|
+
## Environment Variables
|
|
4549
|
+
|
|
4550
|
+
\`\`\`bash
|
|
4551
|
+
VAIF_API_URL=https://api.vaif.studio
|
|
4552
|
+
VAIF_PROJECT_ID=proj_xxx
|
|
4553
|
+
VAIF_API_KEY=vk_xxx
|
|
4554
|
+
\`\`\`
|
|
4555
|
+
`,saas:`# VAIF Studio \u2014 SaaS Backend
|
|
4556
|
+
|
|
4557
|
+
This project uses **VAIF Studio** as its backend for a SaaS application.
|
|
4558
|
+
|
|
4559
|
+
## SDK Setup
|
|
4560
|
+
|
|
4561
|
+
\`\`\`bash
|
|
4562
|
+
npm install @vaiftech/client @vaiftech/react
|
|
4563
|
+
\`\`\`
|
|
4564
|
+
|
|
4565
|
+
\`\`\`typescript
|
|
4566
|
+
import { createVaifClient } from "@vaiftech/client";
|
|
4567
|
+
|
|
4568
|
+
const vaif = createVaifClient({
|
|
4569
|
+
baseUrl: "https://api.vaif.studio",
|
|
4570
|
+
projectId: process.env.VAIF_PROJECT_ID!,
|
|
4571
|
+
apiKey: process.env.VAIF_API_KEY!,
|
|
4572
|
+
});
|
|
4573
|
+
\`\`\`
|
|
4574
|
+
|
|
4575
|
+
## Common SaaS Schema Patterns
|
|
4576
|
+
|
|
4577
|
+
### Multi-Tenant with Organizations
|
|
4578
|
+
|
|
4579
|
+
\`\`\`sql
|
|
4580
|
+
-- Organizations (tenants)
|
|
4581
|
+
CREATE TABLE orgs (
|
|
4582
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4583
|
+
name TEXT NOT NULL,
|
|
4584
|
+
slug TEXT UNIQUE NOT NULL,
|
|
4585
|
+
plan TEXT DEFAULT 'free',
|
|
4586
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
4587
|
+
);
|
|
4588
|
+
|
|
4589
|
+
-- Organization members
|
|
4590
|
+
CREATE TABLE org_members (
|
|
4591
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4592
|
+
org_id UUID REFERENCES orgs(id) ON DELETE CASCADE,
|
|
4593
|
+
user_id UUID NOT NULL,
|
|
4594
|
+
role TEXT DEFAULT 'member', -- owner, admin, member
|
|
4595
|
+
created_at TIMESTAMPTZ DEFAULT now(),
|
|
4596
|
+
UNIQUE(org_id, user_id)
|
|
4597
|
+
);
|
|
4598
|
+
|
|
4599
|
+
-- Tenant-scoped data
|
|
4600
|
+
CREATE TABLE projects (
|
|
4601
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4602
|
+
org_id UUID REFERENCES orgs(id) ON DELETE CASCADE,
|
|
4603
|
+
name TEXT NOT NULL,
|
|
4604
|
+
settings JSONB DEFAULT '{}',
|
|
4605
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
4606
|
+
);
|
|
4607
|
+
CREATE INDEX idx_projects_org ON projects(org_id);
|
|
4608
|
+
\`\`\`
|
|
4609
|
+
|
|
4610
|
+
### Row-Level Security for Multi-Tenancy
|
|
4611
|
+
|
|
4612
|
+
\`\`\`typescript
|
|
4613
|
+
// Scope all queries to the current organization
|
|
4614
|
+
const projects = await vaif.from("projects").select().eq("org_id", currentOrgId);
|
|
4615
|
+
|
|
4616
|
+
// Or use RLS headers for automatic scoping
|
|
4617
|
+
const data = await vaif.from("projects").select({
|
|
4618
|
+
headers: { "x-vaif-rls": \\\`org_id:\${currentOrgId}\\\` },
|
|
4619
|
+
});
|
|
4620
|
+
\`\`\`
|
|
4621
|
+
|
|
4622
|
+
### Auth Flows
|
|
4623
|
+
|
|
4624
|
+
\`\`\`typescript
|
|
4625
|
+
// Sign up \u2192 create org \u2192 add as owner
|
|
4626
|
+
const { data: user } = await vaif.auth.signUp({ email, password });
|
|
4627
|
+
const { data: org } = await vaif.from("orgs").insert({ name: orgName, slug });
|
|
4628
|
+
await vaif.from("org_members").insert({ org_id: org.id, user_id: user.id, role: "owner" });
|
|
4629
|
+
\`\`\`
|
|
4630
|
+
|
|
4631
|
+
### Billing Integration
|
|
4632
|
+
|
|
4633
|
+
\`\`\`typescript
|
|
4634
|
+
// Store Stripe customer/subscription IDs
|
|
4635
|
+
CREATE TABLE billing_accounts (
|
|
4636
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4637
|
+
org_id UUID UNIQUE REFERENCES orgs(id),
|
|
4638
|
+
stripe_customer_id TEXT,
|
|
4639
|
+
stripe_subscription_id TEXT,
|
|
4640
|
+
plan TEXT DEFAULT 'free',
|
|
4641
|
+
period_start TIMESTAMPTZ,
|
|
4642
|
+
period_end TIMESTAMPTZ
|
|
4643
|
+
);
|
|
4644
|
+
|
|
4645
|
+
// Webhook handler (VAIF Function)
|
|
4646
|
+
export default async function handler(req, ctx) {
|
|
4647
|
+
const event = req.body;
|
|
4648
|
+
if (event.type === "customer.subscription.updated") {
|
|
4649
|
+
const sub = event.data.object;
|
|
4650
|
+
await vaif.from("billing_accounts")
|
|
4651
|
+
.update({ plan: sub.metadata.plan, period_end: sub.current_period_end })
|
|
4652
|
+
.eq("stripe_subscription_id", sub.id);
|
|
4653
|
+
}
|
|
4654
|
+
return { received: true };
|
|
4655
|
+
}
|
|
4656
|
+
\`\`\`
|
|
4657
|
+
|
|
4658
|
+
### Invite System
|
|
4659
|
+
|
|
4660
|
+
\`\`\`sql
|
|
4661
|
+
CREATE TABLE invites (
|
|
4662
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4663
|
+
org_id UUID REFERENCES orgs(id) ON DELETE CASCADE,
|
|
4664
|
+
email TEXT NOT NULL,
|
|
4665
|
+
role TEXT DEFAULT 'member',
|
|
4666
|
+
token TEXT UNIQUE NOT NULL,
|
|
4667
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
4668
|
+
accepted_at TIMESTAMPTZ
|
|
4669
|
+
);
|
|
4670
|
+
\`\`\`
|
|
4671
|
+
|
|
4672
|
+
## API Key Scoping
|
|
4673
|
+
|
|
4674
|
+
\`\`\`
|
|
4675
|
+
x-vaif-key: vk_xxx \u2192 Data-plane (CRUD, storage, functions)
|
|
4676
|
+
Authorization: Bearer <jwt> \u2192 Control-plane (schema, project management)
|
|
4677
|
+
\`\`\`
|
|
4678
|
+
|
|
4679
|
+
## Environment Variables
|
|
4680
|
+
|
|
4681
|
+
\`\`\`bash
|
|
4682
|
+
VAIF_API_URL=https://api.vaif.studio
|
|
4683
|
+
VAIF_PROJECT_ID=proj_xxx
|
|
4684
|
+
VAIF_API_KEY=vk_xxx
|
|
4685
|
+
STRIPE_SECRET_KEY=sk_live_xxx
|
|
4686
|
+
STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
4687
|
+
\`\`\`
|
|
4688
|
+
`,mobile:`# VAIF Studio \u2014 Mobile App Backend
|
|
4689
|
+
|
|
4690
|
+
This project uses **VAIF Studio** as its backend for a mobile application (React Native/Expo, Flutter, or Swift).
|
|
4691
|
+
|
|
4692
|
+
## SDK Setup
|
|
4693
|
+
|
|
4694
|
+
### React Native / Expo
|
|
4695
|
+
\`\`\`bash
|
|
4696
|
+
npm install @vaiftech/sdk-expo
|
|
4697
|
+
\`\`\`
|
|
4698
|
+
|
|
4699
|
+
\`\`\`typescript
|
|
4700
|
+
import { VaifProvider, useVaif } from "@vaiftech/sdk-expo";
|
|
4701
|
+
|
|
4702
|
+
export default function App() {
|
|
4703
|
+
return (
|
|
4704
|
+
<VaifProvider
|
|
4705
|
+
config={{
|
|
4706
|
+
baseUrl: "https://api.vaif.studio",
|
|
4707
|
+
projectId: "proj_xxx",
|
|
4708
|
+
apiKey: "vk_xxx",
|
|
4709
|
+
}}
|
|
4710
|
+
>
|
|
4711
|
+
<MainApp />
|
|
4712
|
+
</VaifProvider>
|
|
4713
|
+
);
|
|
4714
|
+
}
|
|
4715
|
+
\`\`\`
|
|
4716
|
+
|
|
4717
|
+
### Flutter / Dart
|
|
4718
|
+
\`\`\`yaml
|
|
4719
|
+
# pubspec.yaml
|
|
4720
|
+
dependencies:
|
|
4721
|
+
vaif_client: ^1.0.0
|
|
4722
|
+
\`\`\`
|
|
4723
|
+
|
|
4724
|
+
\`\`\`dart
|
|
4725
|
+
import 'package:vaif_client/vaif_client.dart';
|
|
4726
|
+
|
|
4727
|
+
final vaif = VaifClient(
|
|
4728
|
+
baseUrl: 'https://api.vaif.studio',
|
|
4729
|
+
projectId: 'proj_xxx',
|
|
4730
|
+
apiKey: 'vk_xxx',
|
|
4731
|
+
);
|
|
4732
|
+
\`\`\`
|
|
4733
|
+
|
|
4734
|
+
### Swift / iOS
|
|
4735
|
+
\`\`\`swift
|
|
4736
|
+
// Package.swift
|
|
4737
|
+
.package(url: "https://github.com/vaifllc/vaif-swift", from: "0.2.0")
|
|
4738
|
+
|
|
4739
|
+
import VaifClient
|
|
4740
|
+
|
|
4741
|
+
let vaif = VaifClient(
|
|
4742
|
+
baseUrl: "https://api.vaif.studio",
|
|
4743
|
+
projectId: "proj_xxx",
|
|
4744
|
+
apiKey: "vk_xxx"
|
|
4745
|
+
)
|
|
4746
|
+
\`\`\`
|
|
4747
|
+
|
|
4748
|
+
## Common Mobile Patterns
|
|
4749
|
+
|
|
4750
|
+
### User Profiles with Avatars
|
|
4751
|
+
|
|
4752
|
+
\`\`\`sql
|
|
4753
|
+
CREATE TABLE profiles (
|
|
4754
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4755
|
+
user_id UUID UNIQUE NOT NULL,
|
|
4756
|
+
display_name TEXT,
|
|
4757
|
+
avatar_url TEXT,
|
|
4758
|
+
bio TEXT,
|
|
4759
|
+
push_token TEXT,
|
|
4760
|
+
device_type TEXT, -- ios, android
|
|
4761
|
+
last_seen TIMESTAMPTZ DEFAULT now()
|
|
4762
|
+
);
|
|
4763
|
+
\`\`\`
|
|
4764
|
+
|
|
4765
|
+
### Push Notifications
|
|
4766
|
+
|
|
4767
|
+
\`\`\`typescript
|
|
4768
|
+
// Store push tokens
|
|
4769
|
+
await vaif.from("profiles").update({
|
|
4770
|
+
push_token: expoPushToken,
|
|
4771
|
+
device_type: Platform.OS,
|
|
4772
|
+
}).eq("user_id", userId);
|
|
4773
|
+
|
|
4774
|
+
// Send notification (VAIF Function)
|
|
4775
|
+
export default async function handler(req, ctx) {
|
|
4776
|
+
const { userId, title, body } = req.body;
|
|
4777
|
+
const { data: profile } = await vaif.from("profiles")
|
|
4778
|
+
.select("push_token, device_type")
|
|
4779
|
+
.eq("user_id", userId)
|
|
4780
|
+
.single();
|
|
4781
|
+
|
|
4782
|
+
// Send via Expo Push API or APNs/FCM
|
|
4783
|
+
await fetch("https://exp.host/--/api/v2/push/send", {
|
|
4784
|
+
method: "POST",
|
|
4785
|
+
headers: { "Content-Type": "application/json" },
|
|
4786
|
+
body: JSON.stringify({
|
|
4787
|
+
to: profile.push_token,
|
|
4788
|
+
title, body,
|
|
4789
|
+
}),
|
|
4790
|
+
});
|
|
4791
|
+
return { sent: true };
|
|
4792
|
+
}
|
|
4793
|
+
\`\`\`
|
|
4794
|
+
|
|
4795
|
+
### Offline-First with Sync
|
|
4796
|
+
|
|
4797
|
+
\`\`\`typescript
|
|
4798
|
+
// Cache data locally, sync when online
|
|
4799
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
4800
|
+
|
|
4801
|
+
// Fetch and cache
|
|
4802
|
+
const { data } = await vaif.from("items").select();
|
|
4803
|
+
await AsyncStorage.setItem("items_cache", JSON.stringify(data));
|
|
4804
|
+
|
|
4805
|
+
// Read from cache when offline
|
|
4806
|
+
const cached = JSON.parse(await AsyncStorage.getItem("items_cache") || "[]");
|
|
4807
|
+
\`\`\`
|
|
4808
|
+
|
|
4809
|
+
### Image Upload from Camera
|
|
4810
|
+
|
|
4811
|
+
\`\`\`typescript
|
|
4812
|
+
import * as ImagePicker from "expo-image-picker";
|
|
4813
|
+
|
|
4814
|
+
const result = await ImagePicker.launchCameraAsync({ quality: 0.8 });
|
|
4815
|
+
if (!result.canceled) {
|
|
4816
|
+
const uri = result.assets[0].uri;
|
|
4817
|
+
const response = await fetch(uri);
|
|
4818
|
+
const blob = await response.blob();
|
|
4819
|
+
|
|
4820
|
+
await vaif.storage.from("avatars").upload(
|
|
4821
|
+
\\\`\${userId}/avatar.jpg\\\`,
|
|
4822
|
+
blob,
|
|
4823
|
+
{ contentType: "image/jpeg" }
|
|
4824
|
+
);
|
|
4825
|
+
}
|
|
4826
|
+
\`\`\`
|
|
4827
|
+
|
|
4828
|
+
### Realtime Chat
|
|
4829
|
+
|
|
4830
|
+
\`\`\`typescript
|
|
4831
|
+
// Subscribe to new messages
|
|
4832
|
+
const subscription = vaif.realtime
|
|
4833
|
+
.channel("messages")
|
|
4834
|
+
.on("INSERT", (payload) => {
|
|
4835
|
+
setMessages(prev => [...prev, payload.new]);
|
|
4836
|
+
})
|
|
4837
|
+
.subscribe();
|
|
4838
|
+
|
|
4839
|
+
// Send a message
|
|
4840
|
+
await vaif.from("messages").insert({
|
|
4841
|
+
room_id: roomId,
|
|
4842
|
+
user_id: userId,
|
|
4843
|
+
content: messageText,
|
|
4844
|
+
});
|
|
4845
|
+
\`\`\`
|
|
4846
|
+
|
|
4847
|
+
## Auth with Secure Token Storage
|
|
4848
|
+
|
|
4849
|
+
The Expo SDK automatically stores auth tokens in SecureStore (iOS Keychain / Android Keystore).
|
|
4850
|
+
|
|
4851
|
+
\`\`\`typescript
|
|
4852
|
+
const { useAuth } = require("@vaiftech/sdk-expo");
|
|
4853
|
+
|
|
4854
|
+
function LoginScreen() {
|
|
4855
|
+
const { signIn, signUp, user, loading } = useAuth();
|
|
4856
|
+
|
|
4857
|
+
const handleLogin = async () => {
|
|
4858
|
+
const { error } = await signIn({ email, password });
|
|
4859
|
+
if (error) Alert.alert("Error", error.message);
|
|
4860
|
+
};
|
|
4861
|
+
}
|
|
4862
|
+
\`\`\`
|
|
4863
|
+
|
|
4864
|
+
## Environment Variables
|
|
4865
|
+
|
|
4866
|
+
\`\`\`bash
|
|
4867
|
+
VAIF_API_URL=https://api.vaif.studio
|
|
4868
|
+
VAIF_PROJECT_ID=proj_xxx
|
|
4869
|
+
VAIF_API_KEY=vk_xxx
|
|
4870
|
+
EXPO_PUBLIC_VAIF_PROJECT_ID=proj_xxx
|
|
4871
|
+
EXPO_PUBLIC_VAIF_API_KEY=vk_xxx
|
|
4872
|
+
\`\`\`
|
|
4873
|
+
`,ecommerce:`# VAIF Studio \u2014 E-Commerce Backend
|
|
4874
|
+
|
|
4875
|
+
This project uses **VAIF Studio** as its backend for an e-commerce application.
|
|
4876
|
+
|
|
4877
|
+
## SDK Setup
|
|
4878
|
+
|
|
4879
|
+
\`\`\`bash
|
|
4880
|
+
npm install @vaiftech/client
|
|
4881
|
+
\`\`\`
|
|
4882
|
+
|
|
4883
|
+
\`\`\`typescript
|
|
4884
|
+
import { createVaifClient } from "@vaiftech/client";
|
|
4885
|
+
|
|
4886
|
+
const vaif = createVaifClient({
|
|
4887
|
+
baseUrl: "https://api.vaif.studio",
|
|
4888
|
+
projectId: process.env.VAIF_PROJECT_ID!,
|
|
4889
|
+
apiKey: process.env.VAIF_API_KEY!,
|
|
4890
|
+
});
|
|
4891
|
+
\`\`\`
|
|
4892
|
+
|
|
4893
|
+
## E-Commerce Schema
|
|
4894
|
+
|
|
4895
|
+
\`\`\`sql
|
|
4896
|
+
-- Products
|
|
4897
|
+
CREATE TABLE products (
|
|
4898
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4899
|
+
name TEXT NOT NULL,
|
|
4900
|
+
slug TEXT UNIQUE NOT NULL,
|
|
4901
|
+
description TEXT,
|
|
4902
|
+
price NUMERIC(10,2) NOT NULL,
|
|
4903
|
+
compare_at_price NUMERIC(10,2),
|
|
4904
|
+
currency TEXT DEFAULT 'USD',
|
|
4905
|
+
sku TEXT UNIQUE,
|
|
4906
|
+
inventory_count INTEGER DEFAULT 0,
|
|
4907
|
+
category_id UUID REFERENCES categories(id),
|
|
4908
|
+
images JSONB DEFAULT '[]', -- [{url, alt, position}]
|
|
4909
|
+
metadata JSONB DEFAULT '{}',
|
|
4910
|
+
status TEXT DEFAULT 'draft', -- draft, active, archived
|
|
4911
|
+
created_at TIMESTAMPTZ DEFAULT now(),
|
|
4912
|
+
updated_at TIMESTAMPTZ DEFAULT now()
|
|
4913
|
+
);
|
|
4914
|
+
CREATE INDEX idx_products_category ON products(category_id);
|
|
4915
|
+
CREATE INDEX idx_products_status ON products(status);
|
|
4916
|
+
|
|
4917
|
+
-- Categories
|
|
4918
|
+
CREATE TABLE categories (
|
|
4919
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4920
|
+
name TEXT NOT NULL,
|
|
4921
|
+
slug TEXT UNIQUE NOT NULL,
|
|
4922
|
+
parent_id UUID REFERENCES categories(id),
|
|
4923
|
+
sort_order INTEGER DEFAULT 0
|
|
4924
|
+
);
|
|
4925
|
+
|
|
4926
|
+
-- Orders
|
|
4927
|
+
CREATE TABLE orders (
|
|
4928
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4929
|
+
user_id UUID NOT NULL,
|
|
4930
|
+
status TEXT DEFAULT 'pending', -- pending, confirmed, shipped, delivered, cancelled
|
|
4931
|
+
subtotal NUMERIC(10,2) NOT NULL,
|
|
4932
|
+
tax NUMERIC(10,2) DEFAULT 0,
|
|
4933
|
+
shipping NUMERIC(10,2) DEFAULT 0,
|
|
4934
|
+
total NUMERIC(10,2) NOT NULL,
|
|
4935
|
+
currency TEXT DEFAULT 'USD',
|
|
4936
|
+
shipping_address JSONB,
|
|
4937
|
+
billing_address JSONB,
|
|
4938
|
+
stripe_payment_intent_id TEXT,
|
|
4939
|
+
notes TEXT,
|
|
4940
|
+
created_at TIMESTAMPTZ DEFAULT now(),
|
|
4941
|
+
updated_at TIMESTAMPTZ DEFAULT now()
|
|
4942
|
+
);
|
|
4943
|
+
CREATE INDEX idx_orders_user ON orders(user_id);
|
|
4944
|
+
CREATE INDEX idx_orders_status ON orders(status);
|
|
4945
|
+
|
|
4946
|
+
-- Order items
|
|
4947
|
+
CREATE TABLE order_items (
|
|
4948
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4949
|
+
order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
|
|
4950
|
+
product_id UUID REFERENCES products(id),
|
|
4951
|
+
quantity INTEGER NOT NULL,
|
|
4952
|
+
unit_price NUMERIC(10,2) NOT NULL,
|
|
4953
|
+
total NUMERIC(10,2) NOT NULL
|
|
4954
|
+
);
|
|
4955
|
+
CREATE INDEX idx_order_items_order ON order_items(order_id);
|
|
4956
|
+
|
|
4957
|
+
-- Cart (session-based)
|
|
4958
|
+
CREATE TABLE carts (
|
|
4959
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4960
|
+
user_id UUID,
|
|
4961
|
+
session_id TEXT,
|
|
4962
|
+
items JSONB DEFAULT '[]', -- [{productId, quantity, price}]
|
|
4963
|
+
created_at TIMESTAMPTZ DEFAULT now(),
|
|
4964
|
+
updated_at TIMESTAMPTZ DEFAULT now()
|
|
4965
|
+
);
|
|
4966
|
+
|
|
4967
|
+
-- Reviews
|
|
4968
|
+
CREATE TABLE reviews (
|
|
4969
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4970
|
+
product_id UUID REFERENCES products(id) ON DELETE CASCADE,
|
|
4971
|
+
user_id UUID NOT NULL,
|
|
4972
|
+
rating INTEGER CHECK (rating >= 1 AND rating <= 5),
|
|
4973
|
+
title TEXT,
|
|
4974
|
+
body TEXT,
|
|
4975
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
4976
|
+
);
|
|
4977
|
+
CREATE INDEX idx_reviews_product ON reviews(product_id);
|
|
4978
|
+
\`\`\`
|
|
4979
|
+
|
|
4980
|
+
## Common Patterns
|
|
4981
|
+
|
|
4982
|
+
### Product Listing with Filters
|
|
4983
|
+
|
|
4984
|
+
\`\`\`typescript
|
|
4985
|
+
// Browse products with category filter and pagination
|
|
4986
|
+
const { data: products } = await vaif
|
|
4987
|
+
.from("products")
|
|
4988
|
+
.select("id, name, slug, price, compare_at_price, images, category:categories(name)")
|
|
4989
|
+
.eq("status", "active")
|
|
4990
|
+
.eq("category_id", categoryId)
|
|
4991
|
+
.order("created_at", { ascending: false })
|
|
4992
|
+
.limit(20)
|
|
4993
|
+
.offset(page * 20);
|
|
4994
|
+
\`\`\`
|
|
4995
|
+
|
|
4996
|
+
### Cart Management
|
|
4997
|
+
|
|
4998
|
+
\`\`\`typescript
|
|
4999
|
+
// Add to cart
|
|
5000
|
+
const cart = await vaif.from("carts").select().eq("user_id", userId).single();
|
|
5001
|
+
const items = [...(cart.data?.items || [])];
|
|
5002
|
+
const existing = items.findIndex(i => i.productId === productId);
|
|
5003
|
+
if (existing >= 0) {
|
|
5004
|
+
items[existing].quantity += quantity;
|
|
5005
|
+
} else {
|
|
5006
|
+
items.push({ productId, quantity, price });
|
|
5007
|
+
}
|
|
5008
|
+
await vaif.from("carts").update({ items, updated_at: new Date().toISOString() }).eq("id", cart.data.id);
|
|
5009
|
+
\`\`\`
|
|
5010
|
+
|
|
5011
|
+
### Order Creation
|
|
5012
|
+
|
|
5013
|
+
\`\`\`typescript
|
|
5014
|
+
// Create order from cart
|
|
5015
|
+
const { data: order } = await vaif.from("orders").insert({
|
|
5016
|
+
user_id: userId,
|
|
5017
|
+
subtotal, tax, shipping,
|
|
5018
|
+
total: subtotal + tax + shipping,
|
|
5019
|
+
shipping_address: addressData,
|
|
5020
|
+
});
|
|
5021
|
+
|
|
5022
|
+
// Create order items
|
|
5023
|
+
const orderItems = cartItems.map(item => ({
|
|
5024
|
+
order_id: order.id,
|
|
5025
|
+
product_id: item.productId,
|
|
5026
|
+
quantity: item.quantity,
|
|
5027
|
+
unit_price: item.price,
|
|
5028
|
+
total: item.price * item.quantity,
|
|
5029
|
+
}));
|
|
5030
|
+
await vaif.from("order_items").insert(orderItems);
|
|
5031
|
+
\`\`\`
|
|
5032
|
+
|
|
5033
|
+
### Inventory Management
|
|
5034
|
+
|
|
5035
|
+
\`\`\`typescript
|
|
5036
|
+
// Decrement inventory on order (VAIF Function)
|
|
5037
|
+
export default async function handler(req, ctx) {
|
|
5038
|
+
const { items } = req.body; // [{productId, quantity}]
|
|
5039
|
+
for (const item of items) {
|
|
5040
|
+
const { data: product } = await vaif.from("products")
|
|
5041
|
+
.select("inventory_count")
|
|
5042
|
+
.eq("id", item.productId)
|
|
5043
|
+
.single();
|
|
5044
|
+
|
|
5045
|
+
if (product.inventory_count < item.quantity) {
|
|
5046
|
+
return { error: \\\`Insufficient stock for \${item.productId}\\\` };
|
|
5047
|
+
}
|
|
5048
|
+
|
|
5049
|
+
await vaif.from("products")
|
|
5050
|
+
.update({ inventory_count: product.inventory_count - item.quantity })
|
|
5051
|
+
.eq("id", item.productId);
|
|
5052
|
+
}
|
|
5053
|
+
return { success: true };
|
|
5054
|
+
}
|
|
5055
|
+
\`\`\`
|
|
5056
|
+
|
|
5057
|
+
### Payment Webhooks
|
|
5058
|
+
|
|
5059
|
+
\`\`\`typescript
|
|
5060
|
+
// Stripe webhook handler (VAIF Function)
|
|
5061
|
+
export default async function handler(req, ctx) {
|
|
5062
|
+
const sig = req.headers["stripe-signature"];
|
|
5063
|
+
const event = stripe.webhooks.constructEvent(req.rawBody, sig, ctx.secrets.STRIPE_WEBHOOK_SECRET);
|
|
5064
|
+
|
|
5065
|
+
switch (event.type) {
|
|
5066
|
+
case "payment_intent.succeeded":
|
|
5067
|
+
await vaif.from("orders")
|
|
5068
|
+
.update({ status: "confirmed" })
|
|
5069
|
+
.eq("stripe_payment_intent_id", event.data.object.id);
|
|
5070
|
+
break;
|
|
5071
|
+
case "payment_intent.payment_failed":
|
|
5072
|
+
await vaif.from("orders")
|
|
5073
|
+
.update({ status: "cancelled" })
|
|
5074
|
+
.eq("stripe_payment_intent_id", event.data.object.id);
|
|
5075
|
+
break;
|
|
5076
|
+
}
|
|
5077
|
+
return { received: true };
|
|
5078
|
+
}
|
|
5079
|
+
\`\`\`
|
|
5080
|
+
|
|
5081
|
+
### Product Image Upload
|
|
5082
|
+
|
|
5083
|
+
\`\`\`typescript
|
|
5084
|
+
// Upload product images to storage
|
|
5085
|
+
const { url } = await vaif.storage
|
|
5086
|
+
.from("product-images")
|
|
5087
|
+
.upload(\\\`\${productId}/\${fileName}\\\`, file, { contentType: "image/webp" });
|
|
5088
|
+
|
|
5089
|
+
// Update product images array
|
|
5090
|
+
const { data: product } = await vaif.from("products").select("images").eq("id", productId).single();
|
|
5091
|
+
const images = [...(product.images || []), { url, alt: altText, position: product.images.length }];
|
|
5092
|
+
await vaif.from("products").update({ images }).eq("id", productId);
|
|
5093
|
+
\`\`\`
|
|
5094
|
+
|
|
5095
|
+
## Environment Variables
|
|
5096
|
+
|
|
5097
|
+
\`\`\`bash
|
|
5098
|
+
VAIF_API_URL=https://api.vaif.studio
|
|
5099
|
+
VAIF_PROJECT_ID=proj_xxx
|
|
5100
|
+
VAIF_API_KEY=vk_xxx
|
|
5101
|
+
STRIPE_SECRET_KEY=sk_live_xxx
|
|
5102
|
+
STRIPE_PUBLISHABLE_KEY=pk_live_xxx
|
|
5103
|
+
STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
5104
|
+
\`\`\`
|
|
5105
|
+
|
|
5106
|
+
> **Note**: \`numeric\` columns (like \`price\`) serialize to JSON strings to preserve precision. Parse with \`parseFloat()\` before arithmetic.
|
|
5107
|
+
`};var no={$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 qe(t){if(t.claude!==void 0){let n=typeof t.claude=="string"?t.claude:null;if(n&&n in ne){let a=ie__default.default("Generating CLAUDE.md from template...").start(),r=ne[n],s=io();s&&(r+=`
|
|
5108
|
+
## Team Conventions
|
|
5109
|
+
|
|
5110
|
+
${s}
|
|
5111
|
+
`);let c=S__default.default.resolve("CLAUDE.md");A__default.default.existsSync(c)&&!t.force&&(a.fail("CLAUDE.md already exists"),console.log(f__default.default.yellow(`
|
|
5112
|
+
Use --force to overwrite.`)),process.exit(1)),A__default.default.writeFileSync(c,r,"utf-8"),a.succeed(`Created CLAUDE.md (${n} template)`),s&&console.log(f__default.default.gray(" Imported team conventions from existing config files.")),console.log(f__default.default.gray(`
|
|
5113
|
+
Customize the generated CLAUDE.md with your project details.`)),console.log(f__default.default.gray(` For a personalized version from live data, run: vaif claude-setup
|
|
5114
|
+
`));return}n&&!(n in ne)&&(console.log(f__default.default.red(`
|
|
5115
|
+
Unknown template type: "${n}"`)),console.log(f__default.default.gray(" Available types: base, saas, mobile, ecommerce")),console.log(f__default.default.gray(` Or omit the type to auto-generate from your live project: vaif init --claude
|
|
5116
|
+
`)),process.exit(1));let i=ao();i?(console.log(f__default.default.gray(`
|
|
5117
|
+
Detected project type: ${f__default.default.cyan(i)}`)),console.log(f__default.default.gray(` Generating from live project data with template context...
|
|
5118
|
+
`))):console.log(f__default.default.gray(`
|
|
5119
|
+
Generating from live project data...
|
|
5120
|
+
`)),await oe({skipMcp:false});return}if(t.addFeatures){t.template||(console.log(f__default.default.red(`
|
|
5121
|
+
--add-features requires --template to know which template to use.`)),console.log(f__default.default.gray("Example: vaif init --template react-spa --add-features functions,storage")),process.exit(1));let n=t.addFeatures.split(",").map(i=>i.trim());await be(t.template,{force:t.force,features:n,addOnly:true});return}let e=ie__default.default("Initializing VAIF configuration...").start(),o=S__default.default.resolve("vaif.config.json");A__default.default.existsSync(o)&&!t.force&&(e.fail("vaif.config.json already exists"),console.log(f__default.default.yellow(`
|
|
5122
|
+
Use --force to overwrite existing configuration.`)),process.exit(1));try{if(A__default.default.writeFileSync(o,JSON.stringify(no,null,2),"utf-8"),e.succeed("Created vaif.config.json"),t.template){let n=t.features?t.features.split(",").map(i=>i.trim()):void 0;await be(t.template,{force:t.force,features:n});}else {let n=S__default.default.resolve(".env.example");if(A__default.default.existsSync(n)||(A__default.default.writeFileSync(n,`# VAIF Configuration
|
|
5123
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/database
|
|
5124
|
+
VAIF_API_KEY=your-api-key
|
|
5125
|
+
`,"utf-8"),console.log(f__default.default.gray("Created .env.example"))),t.typescript){let i=S__default.default.resolve("src/types");A__default.default.existsSync(i)||(A__default.default.mkdirSync(i,{recursive:!0}),console.log(f__default.default.gray("Created src/types directory")));}console.log(""),console.log(f__default.default.green("VAIF initialized successfully!")),console.log(""),console.log(f__default.default.gray("Next steps:")),console.log(f__default.default.gray(" 1. Update vaif.config.json with your project ID")),console.log(f__default.default.gray(" 2. Set DATABASE_URL in your environment")),console.log(f__default.default.gray(" 3. Run: npx vaif generate")),console.log("");}}catch(n){e.fail("Failed to initialize"),n instanceof Error&&console.error(f__default.default.red(`
|
|
5126
|
+
Error: ${n.message}`)),process.exit(1);}}function ao(){try{let t=S__default.default.resolve("package.json");if(!A__default.default.existsSync(t))return null;let e=JSON.parse(A__default.default.readFileSync(t,"utf-8")),o={...e.dependencies,...e.devDependencies};return o.expo||o["react-native"]||o["@vaiftech/sdk-expo"]||A__default.default.existsSync(S__default.default.resolve("pubspec.yaml"))||A__default.default.existsSync(S__default.default.resolve("Package.swift"))||A__default.default.existsSync(S__default.default.resolve("*.xcodeproj"))?"mobile":(o.stripe||o["@stripe/stripe-js"]||o["shopify-api-node"]||o["@shopify/shopify-api"])&&(A__default.default.existsSync(S__default.default.resolve("src/models/product.ts"))||A__default.default.existsSync(S__default.default.resolve("src/models/order.ts"))||A__default.default.existsSync(S__default.default.resolve("src/pages/products"))||A__default.default.existsSync(S__default.default.resolve("src/pages/cart")))?"ecommerce":o.stripe||o["@stripe/stripe-js"]||e.name?.includes("saas")||e.description?.toLowerCase().includes("saas")?"saas":"base"}catch{return null}}function io(){let t=[{path:".cursorrules",label:"Cursor Rules"},{path:".github/copilot-instructions.md",label:"GitHub Copilot Instructions"},{path:".windsurfrules",label:"Windsurf Rules"},{path:".clinerules",label:"Cline Rules"}],e=[];for(let o of t){let n=S__default.default.resolve(o.path);if(A__default.default.existsSync(n))try{let i=A__default.default.readFileSync(n,"utf-8").trim();i.length>0&&i.length<1e4&&e.push(`### From ${o.label} (\`${o.path}\`)
|
|
5127
|
+
|
|
5128
|
+
${i}`);}catch{}}return e.length>0?e.join(`
|
|
5129
|
+
|
|
5130
|
+
`):null}var lo=process.env.VAIF_API_URL||"https://api.vaif.studio";async function uo(t,e,o="public"){let n=await fetch(`${lo}/projects/${e}/schema?schema=${o}`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!n.ok){let i=await n.text();throw new Error(`Failed to fetch schema: ${i}`)}return n.json()}async function Ye(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;e.start("Loading configuration...");try{i=await w(n);}catch(r){e.fail("Failed to load config"),console.log(f__default.default.red(`
|
|
5131
|
+
Error: ${r}`)),process.exit(1);}i||(e.fail("No configuration found"),console.log(f__default.default.yellow("\nRun `vaif init` to create a configuration file.")),process.exit(1));let a=t.projectId||i.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(e.fail("No project ID specified"),console.log(f__default.default.yellow(`
|
|
5132
|
+
Set projectId in vaif.config.json or use --project-id flag.`)),process.exit(1)),e.text="Fetching remote schema...";try{let r=t.schema||i.database?.schema||"public",s=await uo(o.token,a,r);e.succeed("Schema fetched successfully");let c=t.output||S__default.default.resolve("vaif.schema.json"),l={$schema:"https://vaif.studio/schemas/schema.json",projectId:a,schema:r,pulledAt:new Date().toISOString(),...s};A__default.default.writeFileSync(c,JSON.stringify(l,null,2),"utf-8"),console.log(""),console.log(f__default.default.green(`Schema saved to: ${c}`)),console.log(""),console.log(f__default.default.gray("Schema summary:")),console.log(f__default.default.gray(` Tables: ${(s.tables||[]).length}`)),console.log(f__default.default.gray(` Enums: ${(s.enums||[]).length}`)),console.log(f__default.default.gray(` Functions: ${(s.functions||[]).length}`)),console.log(""),console.log(f__default.default.gray("Next steps:")),console.log(f__default.default.gray(" - Run `vaif generate` to generate TypeScript types")),console.log(f__default.default.gray(" - Edit the schema and run `vaif push` to deploy changes")),console.log("");}catch(r){e.fail("Failed to fetch schema"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5133
|
+
Error: ${r.message}`)),process.exit(1);}}var Ge=process.env.VAIF_API_URL||"https://api.vaif.studio";function mo(t){let e=Re__default.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(o=>{e.question(t,n=>{e.close(),o(n);});})}async function ho(t,e,o){let n=await fetch(`${Ge}/projects/${e}/schema/preview`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({schema:o})});if(!n.ok){let i=await n.text();throw new Error(`Failed to preview changes: ${i}`)}return n.json()}async function yo(t,e,o){let n=await fetch(`${Ge}/projects/${e}/schema/apply`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({schema:o})});if(!n.ok){let i=await n.text();throw new Error(`Failed to apply changes: ${i}`)}return n.json()}function vo(t){if(console.log(""),console.log(f__default.default.bold("Schema Changes:")),console.log(""),t.added.length===0&&t.modified.length===0&&t.removed.length===0){console.log(f__default.default.gray(" No changes detected. Schema is up to date."));return}if(t.added.length>0){console.log(f__default.default.green.bold(" + Added:"));for(let e of t.added)console.log(f__default.default.green(` + ${e.type}: ${e.name}`));console.log("");}if(t.modified.length>0){console.log(f__default.default.yellow.bold(" ~ Modified:"));for(let e of t.modified){console.log(f__default.default.yellow(` ~ ${e.type}: ${e.name}`));for(let o of e.changes)console.log(f__default.default.gray(` ${o}`));}console.log("");}if(t.removed.length>0){console.log(f__default.default.red.bold(" - Removed:"));for(let e of t.removed)console.log(f__default.default.red(` - ${e.type}: ${e.name}`));console.log("");}}async function We(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;e.start("Loading configuration...");try{i=await w(n);}catch(c){e.fail("Failed to load config"),console.log(f__default.default.red(`
|
|
5134
|
+
Error: ${c}`)),process.exit(1);}i||(e.fail("No configuration found"),console.log(f__default.default.yellow("\nRun `vaif init` to create a configuration file.")),process.exit(1));let a=t.projectId||i.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(e.fail("No project ID specified"),console.log(f__default.default.yellow(`
|
|
5135
|
+
Set projectId in vaif.config.json or use --project-id flag.`)),process.exit(1));let r=t.schema||S__default.default.resolve("vaif.schema.json");A__default.default.existsSync(r)||(e.fail("No local schema found"),console.log(f__default.default.yellow(`
|
|
5136
|
+
Expected schema file at: ${r}`)),console.log(f__default.default.gray("Run `vaif pull` first to fetch the current schema.")),process.exit(1));let s;try{let c=A__default.default.readFileSync(r,"utf-8");s=JSON.parse(c);}catch(c){e.fail("Failed to parse schema file"),c instanceof Error&&console.log(f__default.default.red(`
|
|
5137
|
+
Error: ${c.message}`)),process.exit(1);}e.text="Calculating schema changes...";try{let{diff:c,sql:l}=await ho(o.token,a,s);if(e.stop(),vo(c),c.added.length===0&&c.modified.length===0&&c.removed.length===0){console.log("");return}if(l.length>0){console.log(f__default.default.bold("SQL Migrations:")),console.log("");for(let u of l)console.log(f__default.default.gray(` ${u}`));console.log("");}if(t.dryRun){console.log(f__default.default.yellow("Dry run mode - no changes applied.")),console.log(f__default.default.gray("Remove --dry-run to apply these changes."));return}if(!t.force){c.removed.length>0&&(console.log(f__default.default.red.bold("\u26A0\uFE0F Warning: This will remove tables/columns from your database.")),console.log(f__default.default.red(" This action cannot be undone!")),console.log(""));let d=await mo(f__default.default.cyan("Apply these changes? [y/N] "));if(d.toLowerCase()!=="y"&&d.toLowerCase()!=="yes"){console.log(f__default.default.yellow(`
|
|
5138
|
+
Cancelled. No changes applied.`));return}}e.start("Applying schema changes...");let p=await yo(o.token,a,s);if(p.success){if(e.succeed("Schema changes applied successfully"),console.log(""),p.migrations.length>0){console.log(f__default.default.gray("Migrations applied:"));for(let u of p.migrations)console.log(f__default.default.gray(` - ${u}`));console.log("");}console.log(f__default.default.green("Your database schema is now up to date.")),console.log(f__default.default.gray("Run `vaif generate` to update your TypeScript types.")),console.log("");}else e.fail("Failed to apply some changes");}catch(c){e.fail("Failed to push schema changes"),c instanceof Error&&console.log(f__default.default.red(`
|
|
5139
|
+
Error: ${c.message}`)),process.exit(1);}}var ae=process.env.VAIF_API_URL||"https://api.vaif.studio";async function bo(t,e,o,n){let i=new URL(`${ae}/functions/project/${e}`);n&&i.searchParams.set("envId",n);let a=await fetch(i.toString(),{headers:{Authorization:`Bearer ${t}`}});if(!a.ok)return null;let r=await a.json(),s=r.functions||r;return Array.isArray(s)&&s.find(c=>c.name===o)||null}async function Io(t,e,o){let n=await fetch(`${ae}/functions/`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({projectId:e,name:o.name,runtime:o.runtime,entrypoint:o.entrypoint,envId:o.envId})});if(!n.ok){let i=await n.text();throw new Error(`Failed to create function: ${i}`)}return n.json()}async function Ao(t,e,o){let n=await fetch(`${ae}/functions/${e}/source`,{method:"PUT",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({sourceCode:o})});if(!n.ok){let i=await n.text();throw new Error(`Failed to deploy source: ${i}`)}}async function Eo(t,e,o){let n=new URL(`${ae}/functions/project/${e}`);o&&n.searchParams.set("envId",o);let i=await fetch(n.toString(),{headers:{Authorization:`Bearer ${t}`}});if(!i.ok){let r=await i.text();throw new Error(`Failed to list functions: ${r}`)}let a=await i.json();return a.functions||a}function He(t){switch(S__default.default.extname(t).toLowerCase()){case ".ts":return "typescript";case ".js":case ".mjs":return "nodejs";case ".py":return "python";case ".go":return "go";case ".rs":return "rust";default:return "nodejs"}}function Xe(t){let e=[],o=[".ts",".js",".mjs",".py",".go",".rs"],n=["drizzle.config.ts","tsconfig.json","package.json"];if(!A__default.default.existsSync(t))return e;let i=A__default.default.readdirSync(t,{withFileTypes:true});for(let a of i){let r=S__default.default.join(t,a.name);if(a.isDirectory()){if(a.name!=="node_modules"&&!a.name.startsWith(".")){let s=A__default.default.readdirSync(r,{withFileTypes:true});for(let c of s)if(c.isFile()){let l=S__default.default.extname(c.name).toLowerCase();if(o.includes(l)){e.push(S__default.default.join(r,c.name));break}}}}else if(a.isFile()){let s=S__default.default.extname(a.name).toLowerCase();o.includes(s)&&!n.includes(a.name)&&e.push(r);}}return e}async function Ze(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF Functions Deploy")),console.log(""),e.start("Scanning for function files...");let r=S__default.default.resolve("functions"),s=S__default.default.resolve("src/functions"),c=[];if(t.entrypoint){let d=S__default.default.resolve(t.entrypoint);A__default.default.existsSync(d)||(e.fail(`File not found: ${t.entrypoint}`),process.exit(1)),c=[d];}else c=[...Xe(r),...Xe(s)];c.length===0&&(e.fail("No function files found"),console.log(f__default.default.yellow(`
|
|
5140
|
+
Place your functions in:`)),console.log(f__default.default.gray(" - ./functions/")),console.log(f__default.default.gray(" - ./src/functions/")),console.log(f__default.default.gray(`
|
|
5141
|
+
Or specify an entrypoint with --entrypoint`)),process.exit(1)),e.succeed(`Found ${c.length} function(s)`),t.name&&(c=c.filter(d=>S__default.default.basename(d,S__default.default.extname(d)).includes(t.name)),c.length===0&&(console.log(f__default.default.yellow(`
|
|
5142
|
+
No functions matching "${t.name}" found`)),process.exit(1))),console.log(""),console.log(f__default.default.gray("Functions to deploy:"));for(let d of c){let g=S__default.default.basename(S__default.default.dirname(d)),y=g==="functions"||g==="src"?S__default.default.basename(d,S__default.default.extname(d)):g,P=t.runtime||He(d);console.log(f__default.default.gray(` - ${y} (${P})`));}if(console.log(""),t.dryRun){console.log(f__default.default.yellow("Dry run mode - no functions deployed."));return}let l=[];for(let d of c){let g=S__default.default.basename(S__default.default.dirname(d)),y=g==="functions"||g==="src"?S__default.default.basename(d,S__default.default.extname(d)):g,P=t.runtime||He(d);e.start(`Deploying ${y}...`);try{let O=A__default.default.readFileSync(d,"utf-8"),B=await bo(o.token,a,y,t.envId);B||(e.text=`Creating ${y}...`,B=await Io(o.token,a,{name:y,runtime:P,entrypoint:S__default.default.basename(d),envId:t.envId})),e.text=`Deploying ${y}...`,await Ao(o.token,B.id,O),e.succeed(`Deployed ${y}`),l.push({name:y,success:!0});}catch(O){let B=O instanceof Error?O.message:"Unknown error";e.fail(`Failed to deploy ${y}`),l.push({name:y,success:false,error:B});}}console.log("");let p=l.filter(d=>d.success).length;if(l.filter(d=>!d.success).length===0)console.log(f__default.default.green(`\u2713 Successfully deployed ${p} function(s)`));else {console.log(f__default.default.yellow(`Deployed ${p}/${l.length} function(s)`)),console.log(""),console.log(f__default.default.red("Failed deployments:"));for(let d of l.filter(g=>!g.success))console.log(f__default.default.red(` - ${d.name}: ${d.error}`));}console.log("");}async function et(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),process.exit(1)),e.start("Fetching functions...");try{let r=await Eo(o.token,a,t.envId);if(e.stop(),r.length===0){console.log(f__default.default.yellow(`
|
|
5143
|
+
No functions found`)),console.log(f__default.default.gray("Deploy your first function with: vaif functions deploy"));return}console.log(""),console.log(f__default.default.bold(`Functions (${r.length}):`)),console.log(""),console.log(f__default.default.gray(" "+"NAME".padEnd(25)+"RUNTIME".padEnd(15)+"STATUS".padEnd(12)+"INVOCATIONS".padEnd(14)+"LAST DEPLOYED")),console.log(f__default.default.gray(" "+"-".repeat(80)));for(let s of r){let c=s.deployStatus==="deployed"?f__default.default.green:s.deployStatus==="deploying"?f__default.default.yellow:s.deployStatus==="failed"?f__default.default.red:f__default.default.gray;console.log(" "+s.name.padEnd(25)+s.runtime.padEnd(15)+c(s.deployStatus.padEnd(12))+String(s.invocationCount??0).padEnd(14)+(s.deployedAt?new Date(s.deployedAt).toLocaleDateString():"-"));}console.log("");}catch(r){e.fail("Failed to fetch functions"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5144
|
+
Error: ${r.message}`)),process.exit(1);}}var se=process.env.VAIF_API_URL||"https://api.vaif.studio";async function wo(t,e,o,n,i){let a=await fetch(`${se}/projects/${e}/db/seed`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({table:o,records:n,truncate:i?.truncate??false})});if(!a.ok){let r=await a.text();throw new Error(`Failed to seed ${o}: ${r}`)}return a.json()}async function _o(t,e){let o=await fetch(`${se}/projects/${e}/db/reset`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!o.ok){let n=await o.text();throw new Error(`Failed to reset database: ${n}`)}return o.json()}function Ae(t){let e=[];if(!A__default.default.existsSync(t))return e;let o=A__default.default.readdirSync(t,{withFileTypes:true});for(let n of o)if(n.isFile()){let i=S__default.default.extname(n.name).toLowerCase();(i===".json"||i===".ts"||i===".js")&&e.push(S__default.default.join(t,n.name));}return e.sort()}async function tt(t){let e=S__default.default.extname(t).toLowerCase();if(e===".json"){let o=A__default.default.readFileSync(t,"utf-8"),n=JSON.parse(o);return Array.isArray(n)?[{table:S__default.default.basename(t,e),data:n}]:n.table&&n.data?[n]:Object.entries(n).map(([i,a])=>({table:i,data:a}))}else if(e===".ts"||e===".js"){let o=await import(t),n=o.default||o;return typeof n=="function"?n():n}throw new Error(`Unsupported file format: ${e}`)}async function ot(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF Database Seed")),console.log("");let r=[];if(t.file){let p=S__default.default.resolve(t.file);A__default.default.existsSync(p)||(console.log(f__default.default.red(`File not found: ${t.file}`)),process.exit(1)),r=[p];}else {let p=S__default.default.resolve("seeds"),u=S__default.default.resolve("prisma/seed"),d=S__default.default.resolve("db/seeds");r=[...Ae(p),...Ae(u),...Ae(d)];}r.length===0&&(console.log(f__default.default.yellow("No seed files found")),console.log(f__default.default.gray(`
|
|
5145
|
+
Place your seed files in one of these directories:`)),console.log(f__default.default.gray(" - ./seeds/")),console.log(f__default.default.gray(" - ./prisma/seed/")),console.log(f__default.default.gray(" - ./db/seeds/")),console.log(f__default.default.gray(`
|
|
5146
|
+
Or specify a file with --file`)),console.log(f__default.default.gray(`
|
|
5147
|
+
Example seed file (seeds/users.json):`)),console.log(f__default.default.gray(" [")),console.log(f__default.default.gray(' { "name": "John Doe", "email": "john@example.com" },')),console.log(f__default.default.gray(' { "name": "Jane Doe", "email": "jane@example.com" }')),console.log(f__default.default.gray(" ]")),process.exit(1)),console.log(f__default.default.gray("Seed files found:"));for(let p of r)console.log(f__default.default.gray(` - ${S__default.default.relative(process.cwd(),p)}`));if(console.log(""),t.truncate&&(console.log(f__default.default.yellow("\u26A0\uFE0F Tables will be truncated before seeding")),console.log("")),t.dryRun){console.log(f__default.default.yellow("Dry run mode - no data will be inserted.")),console.log("");for(let p of r){e.start(`Loading ${S__default.default.basename(p)}...`);try{let u=await tt(p);e.stop();for(let d of u)t.table&&d.table!==t.table||(console.log(f__default.default.cyan(`Table: ${d.table}`)),console.log(f__default.default.gray(` Records: ${d.data.length}`)),d.data.length>0&&console.log(f__default.default.gray(` Sample: ${JSON.stringify(d.data[0],null,2).slice(0,100)}...`)),console.log(""));}catch(u){e.fail(`Failed to load ${S__default.default.basename(p)}`),u instanceof Error&&console.log(f__default.default.red(` Error: ${u.message}`));}}return}let s=[];for(let p of r){e.start(`Processing ${S__default.default.basename(p)}...`);try{let u=await tt(p);e.stop();for(let d of u)if(!(t.table&&d.table!==t.table)){if(d.data.length===0){console.log(f__default.default.gray(` Skipping ${d.table} (no records)`));continue}e.start(`Seeding ${d.table} (${d.data.length} records)...`);try{let g=await wo(o.token,a,d.table,d.data,{truncate:t.truncate});e.succeed(`Seeded ${d.table}: ${g.inserted} records`),s.push({table:d.table,inserted:g.inserted});}catch(g){let y=g instanceof Error?g.message:"Unknown error";e.fail(`Failed to seed ${d.table}`),s.push({table:d.table,inserted:0,error:y});}}}catch(u){e.fail(`Failed to load ${S__default.default.basename(p)}`),u instanceof Error&&console.log(f__default.default.red(` Error: ${u.message}`));}}console.log("");let c=s.reduce((p,u)=>p+u.inserted,0),l=s.filter(p=>p.error).length;if(l===0)console.log(f__default.default.green(`\u2713 Successfully seeded ${c} records across ${s.length} table(s)`));else {console.log(f__default.default.yellow(`Seeded ${c} records with ${l} error(s)`)),console.log(""),console.log(f__default.default.red("Errors:"));for(let p of s.filter(u=>u.error))console.log(f__default.default.red(` - ${p.table}: ${p.error}`));}console.log("");}async function nt(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1));let r=S__default.default.resolve(t.dir||"./drizzle");if(console.log(""),console.log(f__default.default.bold("VAIF Database Push")),console.log(""),!A__default.default.existsSync(r)){let u=S__default.default.resolve("./migrations");A__default.default.existsSync(u)?console.log(f__default.default.gray(`Using migrations from: ${u}`)):(console.log(f__default.default.red(`Migrations directory not found: ${r}`)),console.log(f__default.default.gray(`
|
|
5148
|
+
Expected one of:`)),console.log(f__default.default.gray(" - ./drizzle/")),console.log(f__default.default.gray(" - ./migrations/")),console.log(f__default.default.gray(`
|
|
5149
|
+
Or specify with: vaif db push --dir <path>`)),process.exit(1));}let s=[],c=A__default.default.readdirSync(r,{withFileTypes:true});for(let u of c)if(u.isFile()&&u.name.endsWith(".sql"))s.push(S__default.default.join(r,u.name));else if(u.isDirectory()){let d=A__default.default.readdirSync(S__default.default.join(r,u.name),{withFileTypes:true});for(let g of d)g.isFile()&&g.name.endsWith(".sql")&&s.push(S__default.default.join(r,u.name,g.name));}s.sort(),s.length===0&&(console.log(f__default.default.yellow("No SQL migration files found")),process.exit(1)),console.log(f__default.default.gray(`Found ${s.length} migration(s):`));for(let u of s)console.log(f__default.default.gray(` - ${S__default.default.relative(process.cwd(),u)}`));if(console.log(""),t.dryRun){console.log(f__default.default.yellow("Dry run mode - no migrations will be applied.")),console.log("");for(let u of s){let d=A__default.default.readFileSync(u,"utf-8");console.log(f__default.default.cyan(`--- ${S__default.default.basename(u)} ---`)),console.log(f__default.default.gray(d.slice(0,500))),d.length>500&&console.log(f__default.default.gray("...")),console.log("");}return}let l=0,p=0;for(let u of s){let d=A__default.default.readFileSync(u,"utf-8"),g=S__default.default.relative(process.cwd(),u);e.start(`Applying ${g}...`);try{let y=await fetch(`${se}/schema-engine/query/${a}`,{method:"POST",headers:{Authorization:`Bearer ${o.token}`,"Content-Type":"application/json"},body:JSON.stringify({sql:d})});if(!y.ok){let P=await y.text();throw new Error(P)}e.succeed(`Applied ${g}`),l++;}catch(y){let P=y instanceof Error?y.message:"Unknown error";e.fail(`Failed ${g}: ${P}`),p++;}}console.log(""),console.log(p===0?f__default.default.green(`Successfully applied ${l} migration(s)`):f__default.default.yellow(`Applied ${l}, failed ${p} migration(s)`)),console.log("");}async function at(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1));let r=S__default.default.resolve(t.output||"vaif.schema.json");console.log(""),console.log(f__default.default.bold("VAIF Database Pull")),console.log(""),e.start("Pulling schema from remote...");try{let s=await fetch(`${se}/schema-engine/introspect/${a}`,{headers:{Authorization:`Bearer ${o.token}`}});if(!s.ok){let p=await s.text();throw new Error(`Failed to pull schema: ${p}`)}let c=await s.json();A__default.default.writeFileSync(r,JSON.stringify(c,null,2),"utf-8"),e.succeed(`Schema written to ${S__default.default.relative(process.cwd(),r)}`);let l=c.tables?.length??Object.keys(c).length;console.log(f__default.default.gray(` ${l} table(s) pulled`)),console.log("");}catch(s){e.fail("Failed to pull schema"),s instanceof Error&&console.log(f__default.default.red(`
|
|
5150
|
+
Error: ${s.message}`)),process.exit(1);}}async function it(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),process.exit(1)),console.log(""),console.log(f__default.default.red.bold("\u26A0\uFE0F DATABASE RESET")),console.log(""),console.log(f__default.default.red("This will:")),console.log(f__default.default.red(" - Drop all tables")),console.log(f__default.default.red(" - Delete all data")),console.log(f__default.default.red(" - Reset migrations")),console.log(""),console.log(f__default.default.red.bold("This action cannot be undone!")),console.log(""),t.force||(console.log(f__default.default.yellow("Use --force to confirm this action.")),process.exit(1)),e.start("Resetting database...");try{await _o(o.token,a),e.succeed("Database reset complete"),console.log(""),console.log(f__default.default.gray("Your database is now empty.")),console.log(f__default.default.gray("Run `vaif push` to apply your schema, then `vaif db seed` to seed data.")),console.log("");}catch(r){e.fail("Failed to reset database"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5151
|
+
Error: ${r.message}`)),process.exit(1);}}var rt=process.env.VAIF_API_URL||"https://api.vaif.studio";function ct(t,e,o){return t.projectId||e?.projectId||process.env.VAIF_PROJECT_ID||o.projectId||null}async function lt(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=ct(t,i,o);a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1));let r=t.name||`cli-key-${Date.now()}`;console.log(""),console.log(f__default.default.bold("VAIF Generate API Key")),console.log(""),e.start("Generating API key...");try{let s=await fetch(`${rt}/projects/${a}/api-keys`,{method:"POST",headers:{Authorization:`Bearer ${o.token}`,"Content-Type":"application/json"},body:JSON.stringify({name:r})});if(!s.ok){let l=await s.text();throw new Error(`Failed to generate key: ${l}`)}let c=await s.json();e.succeed("API key generated"),console.log(""),console.log(f__default.default.green(` Name: ${c.name}`)),console.log(f__default.default.green(` Key: ${c.key}`)),console.log(""),console.log(f__default.default.yellow.bold(" Save this key now - it will not be shown again!")),console.log("");}catch(s){e.fail("Failed to generate API key"),s instanceof Error&&console.log(f__default.default.red(`
|
|
5152
|
+
Error: ${s.message}`)),process.exit(1);}}async function dt(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=ct(t,i,o);a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF API Keys")),console.log(""),e.start("Fetching API keys...");try{let r=await fetch(`${rt}/projects/${a}/api-keys`,{headers:{Authorization:`Bearer ${o.token}`}});if(!r.ok){let u=await r.text();throw new Error(`Failed to list keys: ${u}`)}let s=await r.json(),c=s.keys||s;if(e.stop(),!Array.isArray(c)||c.length===0){console.log(f__default.default.yellow("No API keys found")),console.log(f__default.default.gray(`
|
|
5153
|
+
Generate one with: vaif keys generate`));return}let l=Math.max(8,...c.map(u=>(u.name||"").length)),p=` ${"Name".padEnd(l)} ${"Key".padEnd(24)} Created`;console.log(f__default.default.gray(p)),console.log(f__default.default.gray(" "+"-".repeat(p.length-2)));for(let u of c){let d=(u.name||"unnamed").padEnd(l),g=u.maskedKey||u.prefix||`${(u.key||"").slice(0,12)}...`,y=u.createdAt?new Date(u.createdAt).toLocaleDateString():"N/A";console.log(` ${d} ${g.padEnd(24)} ${y}`);}console.log(""),console.log(f__default.default.gray(` ${c.length} key(s) total`)),console.log("");}catch(r){e.fail("Failed to list API keys"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5154
|
+
Error: ${r.message}`)),process.exit(1);}}var G=process.env.VAIF_API_URL||"https://api.vaif.studio";function To(t,e,o){return t.projectId||e?.projectId||process.env.VAIF_PROJECT_ID||o.projectId||null}function ce(){let t=E();return (!t||!t.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1)),t}async function le(t){try{return await w(t||"vaif.config.json")}catch{return null}}function de(t,e,o){let n=To(t,e,o);return n||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),n}async function ut(t,e,o){let n=ie__default.default(),i=ce(),a=await le(o.config),r=de(o,a,i),s=e;if(o.fromFile)try{s=A__default.default.readFileSync(o.fromFile,"utf-8");}catch(c){console.log(f__default.default.red(`Failed to read file: ${o.fromFile}`)),c instanceof Error&&console.log(f__default.default.gray(c.message)),process.exit(1);}s||(console.log(f__default.default.red("No value provided")),console.log(f__default.default.gray("Provide a value as argument or use --from-file <path>")),process.exit(1)),console.log(""),console.log(f__default.default.bold("VAIF Set Secret")),console.log(""),n.start("Checking for existing secret...");try{let c=new URL(`${G}/functions/secrets/project/${r}`);o.envId&&c.searchParams.set("envId",o.envId);let l=await fetch(c.toString(),{headers:{Authorization:`Bearer ${i.token}`}});if(!l.ok)throw new Error(`Failed to check existing secrets: ${await l.text()}`);let u=(await l.json()).find(d=>d.key===t);if(u){n.text=`Updating secret "${t}"...`;let d=await fetch(`${G}/functions/secrets/${u.id}`,{method:"PUT",headers:{Authorization:`Bearer ${i.token}`,"Content-Type":"application/json"},body:JSON.stringify({value:s})});if(!d.ok)throw new Error(`Failed to update secret: ${await d.text()}`);n.succeed(`Updated secret "${t}"`);}else {n.text=`Creating secret "${t}"...`;let d=await fetch(`${G}/functions/secrets`,{method:"POST",headers:{Authorization:`Bearer ${i.token}`,"Content-Type":"application/json"},body:JSON.stringify({projectId:r,envId:o.envId,key:t,value:s})});if(!d.ok)throw new Error(`Failed to create secret: ${await d.text()}`);n.succeed(`Created secret "${t}"`);}console.log("");}catch(c){n.fail("Failed to set secret"),c instanceof Error&&console.log(f__default.default.red(`
|
|
5155
|
+
Error: ${c.message}`)),process.exit(1);}}async function pt(t){let e=ie__default.default(),o=ce(),n=await le(t.config),i=de(t,n,o);console.log(""),console.log(f__default.default.bold("VAIF Secrets")),console.log(""),e.start("Fetching secrets...");try{let a=new URL(`${G}/functions/secrets/project/${i}`);t.envId&&a.searchParams.set("envId",t.envId);let r=await fetch(a.toString(),{headers:{Authorization:`Bearer ${o.token}`}});if(!r.ok)throw new Error(`Failed to list secrets: ${await r.text()}`);let s=await r.json();if(e.stop(),s.length===0){console.log(f__default.default.yellow("No secrets found")),console.log(f__default.default.gray(`
|
|
5156
|
+
Create one with: vaif secrets set <name> <value>`));return}let c=Math.max(8,...s.map(p=>p.key.length)),l=` ${"Name".padEnd(c)} Created`;console.log(f__default.default.gray(l)),console.log(f__default.default.gray(" "+"-".repeat(l.length-2)));for(let p of s){let u=p.key.padEnd(c),d=p.createdAt?new Date(p.createdAt).toLocaleDateString():"N/A";console.log(` ${u} ${d}`);}console.log(""),console.log(f__default.default.gray(` ${s.length} secret(s) total`)),console.log(f__default.default.gray(" Values are hidden. Use `vaif secrets get <name>` to reveal.")),console.log("");}catch(a){e.fail("Failed to list secrets"),a instanceof Error&&console.log(f__default.default.red(`
|
|
5157
|
+
Error: ${a.message}`)),process.exit(1);}}async function ft(t,e){let o=ie__default.default(),n=ce(),i=await le(e.config),a=de(e,i,n);console.log(""),o.start("Fetching secret...");try{let r=new URL(`${G}/functions/secrets/project/${a}`);e.envId&&r.searchParams.set("envId",e.envId);let s=await fetch(r.toString(),{headers:{Authorization:`Bearer ${n.token}`}});if(!s.ok)throw new Error(`Failed to fetch secrets: ${await s.text()}`);let l=(await s.json()).find(d=>d.key===t);l||(o.fail(`Secret "${t}" not found`),process.exit(1));let p=await fetch(`${G}/functions/secrets/${l.id}/value`,{headers:{Authorization:`Bearer ${n.token}`}});if(!p.ok)throw new Error(`Failed to get secret value: ${await p.text()}`);let u=await p.json();o.stop(),console.log(u.value);}catch(r){o.fail("Failed to get secret"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5158
|
+
Error: ${r.message}`)),process.exit(1);}}async function gt(t,e){let o=ie__default.default(),n=ce(),i=await le(e.config),a=de(e,i,n);console.log(""),console.log(f__default.default.bold("VAIF Delete Secret")),console.log(""),o.start("Finding secret...");try{let r=new URL(`${G}/functions/secrets/project/${a}`);e.envId&&r.searchParams.set("envId",e.envId);let s=await fetch(r.toString(),{headers:{Authorization:`Bearer ${n.token}`}});if(!s.ok)throw new Error(`Failed to fetch secrets: ${await s.text()}`);let l=(await s.json()).find(u=>u.key===t);l||(o.fail(`Secret "${t}" not found`),process.exit(1)),o.text=`Deleting secret "${t}"...`;let p=await fetch(`${G}/functions/secrets/${l.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${n.token}`}});if(!p.ok)throw new Error(`Failed to delete secret: ${await p.text()}`);o.succeed(`Deleted secret "${t}"`),console.log("");}catch(r){o.fail("Failed to delete secret"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5159
|
+
Error: ${r.message}`)),process.exit(1);}}var mt=process.env.VAIF_API_URL||"https://api.vaif.studio";function Po(t){try{let e=new URL(t);return e.password&&(e.password="****"),e.toString()}catch{return t.replace(/:[^@/]+@/,":****@")}}async function ht(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),e.start("Fetching project info...");try{let r=await fetch(`${mt}/projects/${a}`,{headers:{Authorization:`Bearer ${o.token}`}});if(!r.ok){let p=await r.text();throw new Error(`Failed to fetch project: ${p}`)}let s=await r.json();e.stop(),console.log(""),console.log(f__default.default.bold("VAIF Project Info")),console.log("");let c=16,l=(p,u)=>{console.log(` ${f__default.default.gray(p.padEnd(c))} ${u}`);};l("Name:",f__default.default.white(s.name||"N/A")),l("Project ID:",f__default.default.white(a)),l("Region:",f__default.default.white(s.region||"us-east-1")),l("Plan:",f__default.default.white(s.plan||s.tier||"free")),l("Created:",f__default.default.white(s.createdAt?new Date(s.createdAt).toLocaleDateString():"N/A")),console.log(""),l("API URL:",f__default.default.cyan(s.apiUrl||`${mt}/v1`)),l("WS URL:",f__default.default.cyan(s.wsUrl||s.realtimeUrl||"N/A")),l("DB URL:",f__default.default.cyan(s.databaseUrl?Po(s.databaseUrl):"N/A")),l("Storage URL:",f__default.default.cyan(s.storageUrl||"N/A")),console.log("");}catch(r){e.fail("Failed to fetch project info"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5160
|
+
Error: ${r.message}`)),process.exit(1);}}var Co=process.env.VAIF_API_URL||"https://api.vaif.studio";async function yt(t){let e=ie__default.default(),o=E();(!o||!o.token)&&(console.log(f__default.default.red("Not logged in")),console.log(f__default.default.gray("Run `vaif login` first to authenticate")),process.exit(1));let n=t.config||"vaif.config.json",i=null;try{i=await w(n);}catch{}let a=t.projectId||i?.projectId||process.env.VAIF_PROJECT_ID||o.projectId;a||(console.log(f__default.default.red("No project ID specified")),console.log(f__default.default.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),e.start("Fetching project status...");try{let r=await fetch(`${Co}/projects/${a}?include=tables,functions,storage,connections`,{headers:{Authorization:`Bearer ${o.token}`}});if(!r.ok){let y=await r.text();throw new Error(`Failed to fetch project status: ${y}`)}let s=await r.json();e.stop(),console.log(""),console.log(f__default.default.bold("VAIF Project Status")),console.log("");let c=22,l=(y,P)=>{console.log(` ${f__default.default.gray(y.padEnd(c))} ${P}`);};l("Project:",f__default.default.white(s.name||a)),l("Plan:",f__default.default.white(s.plan||s.tier||"free")),console.log(""),console.log(f__default.default.gray(" --- Resources ---")),console.log("");let p=s.tableCount??s.tables?.length??"N/A",u=s.functionCount??s.functions?.length??"N/A",d=s.bucketCount??s.storage?.buckets?.length??"N/A",g=s.activeConnections??s.connections??"N/A";l("Tables:",f__default.default.white(String(p))),l("Functions:",f__default.default.white(String(u))),l("Storage Buckets:",f__default.default.white(String(d))),l("Active Connections:",f__default.default.white(String(g))),s.usage&&(console.log(""),console.log(f__default.default.gray(" --- Usage ---")),console.log(""),s.usage.dbSize&&l("Database Size:",f__default.default.white(s.usage.dbSize)),s.usage.storageSize&&l("Storage Size:",f__default.default.white(s.usage.storageSize)),s.usage.bandwidth&&l("Bandwidth:",f__default.default.white(s.usage.bandwidth)),s.usage.functionInvocations!=null&&l("Function Invocations:",f__default.default.white(String(s.usage.functionInvocations)))),console.log("");}catch(r){e.fail("Failed to fetch project status"),r instanceof Error&&console.log(f__default.default.red(`
|
|
5161
|
+
Error: ${r.message}`)),process.exit(1);}}function jo(t){let e=[S__default.default.join(t,".env.local"),S__default.default.join(t,".env")],o={};for(let i of e)if(A__default.default.existsSync(i)){let a=A__default.default.readFileSync(i,"utf-8");for(let r of a.split(`
|
|
5162
|
+
`)){let s=r.match(/^([^#=]+)=(.*)$/);if(!s)continue;let[,c,l]=s,p=c.trim(),u=l.trim().replace(/^["']|["']$/g,"");if(p==="SUPABASE_URL"||p==="NEXT_PUBLIC_SUPABASE_URL"){o.api={...o.api,url:u};let d=u.match(/https:\/\/([^.]+)\.supabase\./);d&&(o.projectId=d[1]);}(p==="SUPABASE_ANON_KEY"||p==="NEXT_PUBLIC_SUPABASE_ANON_KEY")&&(o.api={...o.api,anonKey:u}),p==="SUPABASE_SERVICE_ROLE_KEY"&&(o.api={...o.api,serviceKey:u});}break}let n=S__default.default.join(t,"supabase","config.toml");if(A__default.default.existsSync(n)){let a=A__default.default.readFileSync(n,"utf-8").match(/project_id\s*=\s*"([^"]+)"/);a&&(o.projectId=a[1]);}return o.projectId||o.api?.url?o:null}function Ro(t){let e=S__default.default.join(t,"supabase","migrations"),o=new Map;if(!A__default.default.existsSync(e))return [];let n=A__default.default.readdirSync(e).filter(i=>i.endsWith(".sql")).sort();for(let i of n){let a=A__default.default.readFileSync(S__default.default.join(e,i),"utf-8");Uo(a,o),ko(a,o);}return Array.from(o.values())}function Uo(t,e){let o=/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:public\.)?(\w+)\s*\(([\s\S]*?)\);/gi,n;for(;(n=o.exec(t))!==null;){let a=n[1],r=n[2];if(["schema_migrations","_prisma_migrations","supabase_migrations"].includes(a))continue;let s=[],c=r.split(`,
|
|
5163
|
+
`).map(l=>l.trim()).filter(Boolean);for(let l of c){if(/^\s*(PRIMARY\s+KEY|FOREIGN\s+KEY|UNIQUE|CHECK|CONSTRAINT)/i.test(l))continue;let p=l.match(/^(\w+)\s+(\w+(?:\([^)]*\))?(?:\[\])?)\s*(.*)/i);if(!p)continue;let[,u,d,g]=p,y=/PRIMARY\s+KEY/i.test(g),P=/UNIQUE/i.test(g),O=!/NOT\s+NULL/i.test(g)&&!y,B=g.match(/DEFAULT\s+(.+?)(?:\s+|$)/i),W=g.match(/REFERENCES\s+(?:public\.)?(\w+)\s*\((\w+)\)(?:\s+ON\s+DELETE\s+(\w+))?/i);s.push({name:u,type:No(d),nullable:O,isPrimaryKey:y,isUnique:P,defaultValue:B?.[1],references:W?{table:W[1],column:W[2],onDelete:W[3]?.toUpperCase()}:void 0});}s.length>0&&e.set(a,{name:a,columns:s,indexes:[],rlsPolicies:[]});}let i=/CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s+ON\s+(?:public\.)?(\w+)\s*\(([^)]+)\)/gi;for(;(n=i.exec(t))!==null;){let[,a,r,s]=n,c=e.get(r);c&&(c.indexes=c.indexes||[],c.indexes.push({name:a,columns:s.split(",").map(l=>l.trim()),unique:/UNIQUE/i.test(n[0])}));}}function ko(t,e){let o=/CREATE\s+POLICY\s+"([^"]+)"\s+ON\s+(?:public\.)?(\w+)\s+(?:FOR\s+(\w+)\s+)?(?:USING\s+\((.+?)\)|WITH\s+CHECK\s+\((.+?)\))/gi,n;for(;(n=o.exec(t))!==null;){let[,i,a,r,s,c]=n,l=e.get(a);l&&(l.rlsPolicies=l.rlsPolicies||[],l.rlsPolicies.push({name:i,command:r||"ALL",definition:(s||c||"").replace(/auth\.uid\(\)/g,"vaif.auth_uid()")}));}}function No(t){let e=t.toLowerCase();return e.includes("serial")?"integer":e.includes("bigserial")?"bigint":t}function Lo(t){let e=S__default.default.join(t,"supabase","config.toml"),o=[];if(A__default.default.existsSync(e)){let n=A__default.default.readFileSync(e,"utf-8"),i=/\[storage\.buckets\.(\w+)\]/g,a;for(;(a=i.exec(n))!==null;){let r=a[1],s=n.slice(a.index),c=/public\s*=\s*true/i.test(s.split(/\[/)[0]);o.push({name:r,public:c});}}return o}function Do(t){let e=S__default.default.join(t,"supabase","functions"),o=[];if(!A__default.default.existsSync(e))return [];let n=A__default.default.readdirSync(e,{withFileTypes:true});for(let i of n){if(!i.isDirectory()||i.name.startsWith("_"))continue;let a=S__default.default.join(e,i.name,"index.ts"),r=A__default.default.existsSync(a);o.push({name:i.name.replace(/-/g,"_"),runtime:"nodejs20",entrypoint:"index.ts",sourceHint:r?`Source found at supabase/functions/${i.name}/index.ts \u2014 convert Deno imports to Node.js`:void 0});}return o}function Vo(t){let e=[],o=Ro(t);o.length===0&&e.push("No migration files found in supabase/migrations/. Add your schema SQL files or export with: supabase db dump --schema public > supabase/migrations/schema.sql");let n=Lo(t),i=Do(t);i.length>0&&e.push("Supabase Edge Functions use Deno runtime. VAIF functions use Node.js by default. You will need to convert Deno-specific imports (e.g., std/http/server) to Node.js equivalents.");let a=[],r=S__default.default.join(t,"supabase","config.toml");if(A__default.default.existsSync(r)){let s=A__default.default.readFileSync(r,"utf-8");s.includes("[auth.external.google]")&&a.push("google"),s.includes("[auth.external.github]")&&a.push("github"),s.includes("[auth.external.apple]")&&a.push("apple"),s.includes("[auth.external.azure]")&&a.push("microsoft"),(s.includes("[auth.sms]")||s.includes("[auth.external.phone]"))&&a.push("phone");}return {source:"supabase",tables:o,buckets:n,functions:i,authProviders:a,warnings:e}}function bt(t){let e=S__default.default.join(t,"firebase.json"),o={};if(A__default.default.existsSync(e))try{let a=JSON.parse(A__default.default.readFileSync(e,"utf-8"));a.projectId&&(o.projectId=a.projectId);}catch{}let n=S__default.default.join(t,".firebaserc");if(A__default.default.existsSync(n))try{let r=JSON.parse(A__default.default.readFileSync(n,"utf-8")).projects?.default;r&&(o.projectId=r);}catch{}let i=S__default.default.join(t,".env");if(A__default.default.existsSync(i)){let a=A__default.default.readFileSync(i,"utf-8");for(let r of a.split(`
|
|
5164
|
+
`)){let s=r.match(/^([^#=]+)=(.*)$/);if(!s)continue;let[,c,l]=s;c.trim().includes("STORAGE_BUCKET")&&(o.storageBucket=l.trim().replace(/^["']|["']$/g,""));}}return o.projectId?o:null}function $o(t){let e=S__default.default.join(t,"firestore.rules"),o=[];if(!A__default.default.existsSync(e))return [];let n=A__default.default.readFileSync(e,"utf-8"),i=/match\s+\/([a-zA-Z_]\w*)\s*\/\{(\w+)\}/g,a,r=new Set;for(;(a=i.exec(n))!==null;){let s=a[1];r.has(s)||(r.add(s),!s.startsWith("_")&&o.push({name:s,columns:[{name:"id",type:"uuid",nullable:false,isPrimaryKey:true,defaultValue:"gen_random_uuid()"},{name:"created_at",type:"timestamptz",nullable:false,defaultValue:"now()"},{name:"updated_at",type:"timestamptz",nullable:false,defaultValue:"now()"},{name:"data",type:"jsonb",nullable:true,defaultValue:"'{}'"}],indexes:[],rlsPolicies:[]}));}return o}function Oo(t){let e=S__default.default.join(t,"functions"),o=[];if(!A__default.default.existsSync(e))return [];let i=[S__default.default.join(e,"src","index.ts"),S__default.default.join(e,"index.ts"),S__default.default.join(e,"src","index.js"),S__default.default.join(e,"index.js")].find(c=>A__default.default.existsSync(c));if(!i)return [];let a=A__default.default.readFileSync(i,"utf-8"),r=/(?:exports\.(\w+)\s*=|export\s+(?:const|function)\s+(\w+))/g,s;for(;(s=r.exec(a))!==null;){let c=(s[1]||s[2]).replace(/-/g,"_");o.push({name:c,runtime:"nodejs20",entrypoint:"index.ts",sourceHint:`Exported from ${S__default.default.relative(t,i)} \u2014 needs manual conversion from Firebase Functions SDK to VAIF handler format`});}return o}function Mo(t,e){let o=[];e.storageBucket&&o.push({name:"default",public:false});let n=S__default.default.join(t,"storage.rules");if(A__default.default.existsSync(n)){let i=A__default.default.readFileSync(n,"utf-8"),a=/match\s+\/([a-zA-Z]\w*)\s*\/\{/g,r;for(;(r=a.exec(i))!==null;){let s=r[1];s!=="b"&&!o.find(c=>c.name===s)&&o.push({name:s,public:false});}}return o}function Ko(t){let e=[],o=bt(t)||{},n=$o(t);n.length===0?e.push("No firestore.rules found. Add your Firestore rules file or manually specify your collection structure."):e.push("Firestore collections were detected from firestore.rules. Each collection is mapped to a table with a JSONB 'data' column. You should replace the 'data' column with specific typed columns matching your document structure. See docs/migration/from-firebase.md for schema design patterns.");let i=Oo(t);i.length>0&&e.push("Firebase Cloud Functions use the Firebase Admin SDK and trigger patterns (auth.user().onCreate, firestore.document().onWrite). VAIF functions use a simpler handler(req, ctx) pattern. Each function needs manual conversion.");let a=Mo(t,o),r=["email"],s=S__default.default.join(t,"firebase.json");if(A__default.default.existsSync(s))try{let c=JSON.parse(A__default.default.readFileSync(s,"utf-8"));c.auth?.providers&&r.push(...c.auth.providers.filter(l=>l!=="email"));}catch{}return {source:"firebase",tables:n,buckets:a,functions:i,authProviders:r,warnings:e}}function Bo(t){if(console.log(""),console.log(f__default.default.bold.cyan(` Migration Plan (from ${t.source})`)),console.log(f__default.default.gray(" \u2500".repeat(30))),console.log(""),t.tables.length>0){console.log(f__default.default.bold(` \u{1F4E6} Tables (${t.tables.length})`));for(let e of t.tables){let o=e.columns.length,n=e.columns.filter(r=>r.references).length,i=e.rlsPolicies?.length||0,a=[`${o} columns`];n>0&&a.push(`${n} foreign keys`),i>0&&a.push(`${i} RLS policies`),console.log(f__default.default.white(` ${e.name}`)+f__default.default.gray(` \u2014 ${a.join(", ")}`));}console.log("");}if(t.buckets.length>0){console.log(f__default.default.bold(` \u{1F5C4}\uFE0F Storage Buckets (${t.buckets.length})`));for(let e of t.buckets)console.log(f__default.default.white(` ${e.name}`)+f__default.default.gray(` \u2014 ${e.public?"public":"private"}`));console.log("");}if(t.functions.length>0){console.log(f__default.default.bold(` \u26A1 Functions (${t.functions.length})`));for(let e of t.functions)console.log(f__default.default.white(` ${e.name}`)+f__default.default.gray(` \u2014 ${e.runtime}`)),e.sourceHint&&console.log(f__default.default.yellow(` \u26A0 ${e.sourceHint}`));console.log("");}if(t.authProviders.length>0&&(console.log(f__default.default.bold(` \u{1F510} Auth Providers (${t.authProviders.length})`)),console.log(f__default.default.white(` ${t.authProviders.join(", ")}`)),console.log("")),t.warnings.length>0){console.log(f__default.default.bold.yellow(" \u26A0 Warnings"));for(let e of t.warnings)console.log(f__default.default.yellow(` \u2022 ${e}`));console.log("");}}function vt(t,e){let o=`# VAIF Migration Plan
|
|
5165
|
+
|
|
5166
|
+
`;if(o+=`**Source:** ${t.source}
|
|
5167
|
+
`,o+=`**Generated:** ${new Date().toISOString()}
|
|
5168
|
+
|
|
5169
|
+
`,t.tables.length>0){o+=`## Tables (${t.tables.length})
|
|
5170
|
+
|
|
5171
|
+
`;for(let i of t.tables){o+=`### ${i.name}
|
|
5172
|
+
|
|
5173
|
+
`,o+=`| Column | Type | Nullable | Default | Constraints |
|
|
5174
|
+
`,o+=`|--------|------|----------|---------|-------------|
|
|
5175
|
+
`;for(let a of i.columns){let r=[];a.isPrimaryKey&&r.push("PK"),a.isUnique&&r.push("UNIQUE"),a.references&&r.push(`FK \u2192 ${a.references.table}.${a.references.column}`),o+=`| ${a.name} | ${a.type} | ${a.nullable?"yes":"no"} | ${a.defaultValue||"-"} | ${r.join(", ")||"-"} |
|
|
5176
|
+
`;}if(o+=`
|
|
5177
|
+
`,i.rlsPolicies&&i.rlsPolicies.length>0){o+=`**RLS Policies:**
|
|
5178
|
+
`;for(let a of i.rlsPolicies)o+=`- \`${a.name}\` (${a.command}): \`${a.definition}\`
|
|
5179
|
+
`;o+=`
|
|
5180
|
+
`;}}}if(t.buckets.length>0){o+=`## Storage Buckets (${t.buckets.length})
|
|
5181
|
+
|
|
5182
|
+
`;for(let i of t.buckets)o+=`- **${i.name}** \u2014 ${i.public?"public":"private"}
|
|
5183
|
+
`;o+=`
|
|
5184
|
+
`;}if(t.functions.length>0){o+=`## Functions (${t.functions.length})
|
|
5185
|
+
|
|
5186
|
+
`;for(let i of t.functions)o+=`- **${i.name}** \u2014 ${i.runtime}
|
|
5187
|
+
`,i.sourceHint&&(o+=` - \u26A0 ${i.sourceHint}
|
|
5188
|
+
`);o+=`
|
|
5189
|
+
`;}if(t.authProviders.length>0&&(o+=`## Auth Providers
|
|
5190
|
+
|
|
5191
|
+
`,o+=t.authProviders.map(i=>`- ${i}`).join(`
|
|
5192
|
+
`)+`
|
|
5193
|
+
|
|
5194
|
+
`),t.warnings.length>0){o+=`## Warnings
|
|
5195
|
+
|
|
5196
|
+
`;for(let i of t.warnings)o+=`- \u26A0 ${i}
|
|
5197
|
+
`;o+=`
|
|
5198
|
+
`;}o+=`## Next Steps
|
|
5199
|
+
|
|
5200
|
+
`,o+=`1. Review the tables above and adjust column types as needed
|
|
5201
|
+
`,o+=`2. Run \`vaif migrate --from ${t.source}\` without \`--dry-run\` to execute
|
|
5202
|
+
`,o+=`3. Verify tables were created in the VAIF dashboard
|
|
5203
|
+
`,o+=`4. Migrate your data using the export/import scripts in docs/migration/from-${t.source}.md
|
|
5204
|
+
`,o+="5. Update your application code to use `@vaiftech/client`\n";let n=S__default.default.join(e,"vaif-migration-plan.md");return A__default.default.writeFileSync(n,o,"utf-8"),n}var we=process.env.VAIF_API_URL||"https://api.vaif.studio";async function zo(t,e,o){if(t.tables.length>0){let n=ie__default.default(`Creating ${t.tables.length} tables...`).start();try{let i=t.tables.map(r=>({name:r.name,columns:r.columns.map(s=>({name:s.name,type:s.type,nullable:s.nullable,primaryKey:s.isPrimaryKey||!1,unique:s.isUnique||!1,default:s.defaultValue,references:s.references?{table:s.references.table,column:s.references.column,onDelete:s.references.onDelete||"SET NULL"}:void 0})),indexes:r.indexes})),a=await fetch(`${we}/schema-engine/${e}/tables`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({tables:i})});if(a.ok)n.succeed(`Created ${t.tables.length} tables`);else {let r=await a.text();n.fail(`Failed to create tables: ${r}`);}}catch(i){n.fail(`Failed to create tables: ${i instanceof Error?i.message:String(i)}`);}}for(let n of t.buckets){let i=ie__default.default(`Creating bucket: ${n.name}...`).start();try{let a=await fetch(`${we}/storage/buckets`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","x-project-id":e},body:JSON.stringify({name:n.name,public:n.public,fileSizeLimit:n.fileSizeLimit,allowedMimeTypes:n.allowedMimeTypes})});if(a.ok)i.succeed(`Created bucket: ${n.name}`);else {let r=await a.text();i.warn(`Bucket ${n.name}: ${r}`);}}catch(a){i.warn(`Bucket ${n.name}: ${a instanceof Error?a.message:String(a)}`);}}for(let n of t.functions){let i=ie__default.default(`Creating function: ${n.name}...`).start();try{let a=await fetch(`${we}/functions`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({projectId:e,name:n.name,runtime:n.runtime,entrypoint:n.entrypoint})});if(a.ok)i.succeed(`Created function stub: ${n.name}`);else {let r=await a.text();i.warn(`Function ${n.name}: ${r}`);}}catch(a){i.warn(`Function ${n.name}: ${a instanceof Error?a.message:String(a)}`);}}}async function It(t){let e=t.outputDir?S__default.default.resolve(t.outputDir):process.cwd(),o=t.from;console.log(""),console.log(f__default.default.bold(` Analyzing ${o} project...`));let n;if(o==="supabase"?(jo(e)||(console.log(f__default.default.yellow(`
|
|
5205
|
+
No Supabase configuration found.`)),console.log(f__default.default.gray(" Expected: .env with SUPABASE_URL, or supabase/config.toml")),console.log(f__default.default.gray(` Make sure you're in a Supabase project directory.
|
|
5206
|
+
`)),process.exit(1)),n=Vo(e)):o==="firebase"?(bt(e)||(console.log(f__default.default.yellow(`
|
|
5207
|
+
No Firebase configuration found.`)),console.log(f__default.default.gray(" Expected: firebase.json or .firebaserc in project root")),console.log(f__default.default.gray(` Make sure you're in a Firebase project directory.
|
|
5208
|
+
`)),process.exit(1)),n=Ko(e)):(console.log(f__default.default.red(`
|
|
5209
|
+
Unknown source: "${o}"`)),console.log(f__default.default.gray(` Supported: supabase, firebase
|
|
5210
|
+
`)),process.exit(1)),Bo(n),t.dryRun){let s=vt(n,e);console.log(f__default.default.green(` \u2713 Migration plan written to ${f__default.default.cyan(S__default.default.relative(process.cwd(),s))}`)),console.log(f__default.default.gray(` Review the plan, then run without --dry-run to execute.
|
|
5211
|
+
`));return}let i=E();(!i||!i.token)&&(console.log(f__default.default.red(" Not logged in. Run `vaif login` first.")),process.exit(1));let a=t.projectId;if(!a)try{a=(await w(t.config||"vaif.config.json")).projectId;}catch{}a||(a=process.env.VAIF_PROJECT_ID),a||(console.log(f__default.default.red(" No VAIF project ID specified.")),console.log(f__default.default.gray(` Pass --project-id <id>, set in vaif.config.json, or set VAIF_PROJECT_ID env var.
|
|
5212
|
+
`)),process.exit(1)),console.log(f__default.default.bold(` Executing migration to VAIF project: ${a}
|
|
5213
|
+
`)),await zo(n,a,i.token);let r=vt(n,e);console.log(""),console.log(f__default.default.green.bold(" \u2713 Migration complete!")),console.log(f__default.default.gray(` Plan saved to ${S__default.default.relative(process.cwd(),r)}`)),console.log(""),console.log(f__default.default.bold(" Next steps:")),console.log(f__default.default.gray(" 1. Verify tables in the VAIF dashboard")),console.log(f__default.default.gray(" 2. Migrate data using scripts in docs/migration/from-"+o+".md")),console.log(f__default.default.gray(" 3. Update your app code to use @vaiftech/client")),console.log(f__default.default.gray(" 4. Run `vaif claude-setup` to configure AI tools for your project\n"));}var Yo=module$1.createRequire(N),{version:At}=Yo("../package.json"),_e=f__default.default.hex("#00f0ff"),Se=f__default.default.hex("#7b61ff"),Te=f__default.default.hex("#ff3dff"),xe=f__default.default.hex("#00ff9d"),T=f__default.default.hex("#555570"),H=f__default.default.hex("#00f0ff");function Jo(){console.log(""),console.log(_e(" \u2566 \u2566")+Se("\u2554\u2550\u2557\u2566")+Te("\u2554\u2550\u2557 ")+xe("\u2554\u2550\u2557\u2566 \u2566")),console.log(_e(" \u255A\u2557\u2554\u255D")+Se("\u2560\u2550\u2563\u2551")+Te("\u2560\u2563 ")+xe("\u2551 \u2551 \u2551")),console.log(_e(" \u255A\u255D ")+Se("\u2569 \u2569\u2569")+Te("\u255A ")+xe("\u255A\u2550\u255D\u2569\u2550\u255D\u2569")),console.log(""),console.log(T(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(H(" VAIF Studio CLI")+T(` v${At}`)),console.log(T(" Build full-stack apps at lightning speed")),console.log(T(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(""),console.log(f__default.default.bold(" Quick Start")),console.log(T(" $ ")+H("vaif login")+T(" Authenticate")),console.log(T(" $ ")+H("vaif init -t react-spa")+T(" Scaffold project")),console.log(T(" $ ")+H("vaif db push")+T(" Push migrations")),console.log(T(" $ ")+H("vaif generate")+T(" Generate types")),console.log(T(" $ ")+H("vaif functions deploy")+T(" Deploy functions")),console.log(""),console.log(f__default.default.bold(" Categories")),console.log(T(" auth ")+f__default.default.white("login, logout, whoami")),console.log(T(" project ")+f__default.default.white("init, templates, info, status")),console.log(T(" schema ")+f__default.default.white("pull, push, generate")),console.log(T(" database ")+f__default.default.white("db push, db pull, db seed, db reset")),console.log(T(" deploy ")+f__default.default.white("functions deploy, functions list")),console.log(T(" security ")+f__default.default.white("keys, secrets")),console.log(T(" migrate ")+f__default.default.white("migrate --from supabase|firebase")),console.log(T(" ai ")+f__default.default.white("claude-setup, init --claude")),console.log(""),console.log(T(" Run ")+H("vaif <command> --help")+T(" for details")),console.log(T(" Docs: ")+f__default.default.underline("https://docs.vaif.studio")),console.log("");}commander.program.name("vaif").description("VAIF CLI - Type generation and development tools").version(At);commander.program.command("login").description("Authenticate with VAIF (opens browser)").option("-e, --email","Login with email/password instead of browser").option("-p, --project-id <id>","Default project ID").action(ke);commander.program.command("logout").description("Log out and remove stored credentials").action(Ne);commander.program.command("whoami").description("Show current authenticated user").action(Le);commander.program.command("init").description("Initialize VAIF configuration in your project").option("--typescript","Setup for TypeScript project").option("-f, --force","Overwrite existing config").option("-t, --template <name>","Scaffold from a template (run vaif templates for list)").option("--features <features>","Comma-separated features to include: auth,database,realtime,storage,functions").option("--add-features <features>","Add features to an existing project (requires --template)").option("--claude [type]","Generate CLAUDE.md for AI assistants (types: base, saas, mobile, ecommerce). Omit type to auto-detect or use live project data.").action(qe);commander.program.command("templates").alias("tpl").description("List available project templates").action(Me);commander.program.command("info").description("Show project information (name, region, URLs)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").action(ht);commander.program.command("status").description("Show project status (tables, functions, storage, connections)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").action(yt);commander.program.command("pull").description("Pull database schema from your VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-o, --output <path>","Output file path","vaif.schema.json").option("-s, --schema <name>","Schema name","public").option("-p, --project-id <id>","Project ID (overrides config)").action(Ye);commander.program.command("push").description("Push local schema changes to your VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-s, --schema <path>","Schema file path","vaif.schema.json").option("-p, --project-id <id>","Project ID (overrides config)").option("--dry-run","Preview changes without applying").option("-f, --force","Apply changes without confirmation").action(We);commander.program.command("generate").alias("gen").description("Generate TypeScript types from your database schema").option("-c, --connection <url>","Database connection string").option("-o, --output <path>","Output file path","./src/types/database.ts").option("--schema <name>","Schema name","public").option("--config <path>","Config file path","vaif.config.json").option("--dry-run","Preview generated types without writing").action(Ve);var Et=commander.program.command("functions").alias("fn").description("Manage serverless functions");Et.command("deploy").description("Deploy functions to your VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID").option("-n, --name <name>","Function name filter").option("-r, --runtime <runtime>","Runtime (nodejs, typescript, python)").option("--entrypoint <file>","Specific entrypoint file").option("--dry-run","Preview deployment without deploying").action(Ze);Et.command("list").alias("ls").description("List deployed functions").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID").action(et);var ue=commander.program.command("db").description("Database management commands");ue.command("push").description("Push local Drizzle migrations to VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-d, --dir <path>","Migrations directory","./drizzle").option("--dry-run","Preview without applying").action(nt);ue.command("pull").description("Pull schema from VAIF project").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-o, --output <path>","Output file","vaif.schema.json").action(at);ue.command("seed").description("Seed your database with test data").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-f, --file <path>","Specific seed file").option("-t, --table <name>","Seed specific table only").option("--truncate","Truncate tables before seeding").option("--dry-run","Preview seeding without inserting data").action(ot);ue.command("reset").description("Reset database (drop all tables and data)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-f, --force","Confirm reset (required)").action(it);var wt=commander.program.command("keys").description("Manage API keys");wt.command("generate").description("Generate a new API key").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-n, --name <name>","Key name").action(lt);wt.command("list").alias("ls").description("List API keys").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").action(dt);var pe=commander.program.command("secrets").alias("sec").description("Manage function secrets");pe.command("set <name> [value]").description("Create or update a secret").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").option("--from-file <path>","Read secret value from a file").action(ut);pe.command("list").alias("ls").description("List all secrets (names only)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").action(pt);pe.command("get <name>").description("Reveal a secret value").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").action(ft);pe.command("delete <name>").description("Delete a secret").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID (overrides config)").option("-e, --env-id <id>","Environment ID or name").action(gt);commander.program.command("migrate").description("Migrate from Supabase or Firebase to VAIF Studio").requiredOption("--from <platform>","Source platform: supabase or firebase").option("--dry-run","Show migration plan without executing").option("-c, --config <path>","VAIF config file path","vaif.config.json").option("-p, --project-id <id>","Target VAIF project ID").option("-o, --output-dir <dir>","Source project directory to analyze",".").action(It);commander.program.command("claude-setup").description("Configure Claude Code integration (MCP server + CLAUDE.md)").option("-c, --config <path>","Config file path","vaif.config.json").option("-p, --project-id <id>","Project ID").option("-k, --api-key <key>","API key for MCP server").option("--skip-mcp","Skip generating .mcp.json").option("--skip-claude-md","Skip generating CLAUDE.md").option("-o, --output-dir <dir>","Output directory",".").action(oe);process.argv.slice(2).length||(Jo(),process.exit(0));commander.program.parse(process.argv);
|