@vaiftech/cli 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-OB2QEQ2L.js → chunk-N7OY2COL.js} +65 -63
- package/dist/cli.cjs +94 -92
- package/dist/cli.js +2 -2
- package/dist/index.cjs +58 -56
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {d,c,b,a}from'./chunk-
|
|
2
|
+
import {d,c,b,a}from'./chunk-N7OY2COL.js';import'dotenv/config';import {program}from'commander';import l from'chalk';import D from'fs';import j from'path';import Be from'os';import {exec}from'child_process';import M from'ora';import le from'readline';var X=j.join(Be.homedir(),".vaif"),V=j.join(X,"auth.json"),J=process.env.VAIF_API_URL||"https://api.vaif.studio";function Ke(){D.existsSync(X)||D.mkdirSync(X,{recursive:true});}function ge(e){Ke(),D.writeFileSync(V,JSON.stringify(e,null,2),"utf-8"),D.chmodSync(V,384);}function I(){if(!D.existsSync(V))return null;try{let e=D.readFileSync(V,"utf-8");return JSON.parse(e)}catch{return null}}function qe(e){let o=le.createInterface({input:process.stdin,output:process.stdout});return new Promise(t=>{o.question(e,s=>{o.close(),t(s);});})}function We(e){return new Promise(o=>{let t=le.createInterface({input:process.stdin,output:process.stdout});process.stdin;let c=process.stdout.write.bind(process.stdout),r=false;process.stdout.write=((...i)=>r?true:c(...i)),t.question(e,i=>{r=false,process.stdout.write=c,console.log(""),t.close(),o(i);}),r=true;})}function Ge(e){let o=process.platform,t;o==="darwin"?t=`open "${e}"`:o==="win32"?t=`start "" "${e}"`:t=`xdg-open "${e}"`,exec(t,s=>{});}function Ye(e){return new Promise(o=>setTimeout(o,e))}async function Qe(e){try{let o=await fetch(`${J}/auth/me`,{headers:{Authorization:`Bearer ${e}`}});if(o.ok){let t=await o.json();return {valid:!0,email:t.user?.email||t.email}}return {valid:!1}}catch{return {valid:false}}}async function He(e){let o=M();o.start("Setting up authentication...");let t,s;try{let n=await fetch(`${J}/auth/cli/authorize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})});n.ok||(o.fail("Failed to initiate authentication"),console.log(l.red(`
|
|
3
3
|
Could not connect to VAIF API. Please try again later.`)),process.exit(1));let a=await n.json();t=a.code,s=a.url;}catch{o.fail("Failed to connect to VAIF API"),console.log(l.red(`
|
|
4
4
|
Could not connect to VAIF API.`)),console.log(l.gray("Check your internet connection or try: vaif login --email")),process.exit(1);}o.stop(),console.log(l.cyan(" Opening browser for authentication...")),console.log(""),console.log(l.gray(" If the browser doesn't open, visit this URL:")),console.log(l.white(` ${s}`)),console.log(""),Ge(s),o.start("Waiting for browser authentication...");let c=12e4,r=2e3,i=Date.now();for(;Date.now()-i<c;){await Ye(r);try{let n=await fetch(`${J}/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:t})});if(!n.ok){let f=await n.json();(f.error==="ExpiredCode"||f.error==="InvalidCode")&&(o.fail("Authentication expired"),console.log(l.red(`
|
|
5
5
|
The authentication session expired. Please try again.`)),process.exit(1));continue}let a=await n.json();if(a.ok&&a.accessToken){let f={token:a.accessToken,email:a.user?.email,projectId:e,expiresAt:new Date(Date.now()+a.expiresIn*1e3).toISOString()};ge(f),o.succeed("Logged in successfully"),console.log(""),a.user?.email&&console.log(l.green(` Authenticated as: ${a.user.email}`)),console.log(l.gray(` Config saved to: ${V}`)),console.log("");return}}catch{}}o.fail("Authentication timed out"),console.log(l.red(`
|
|
@@ -39,4 +39,4 @@ Error: ${r.message}`)),process.exit(1);}}async function Ne(e,o){let t=M(),s=W(),
|
|
|
39
39
|
Error: ${i.message}`)),process.exit(1);}}async function Ve(e,o){let t=M(),s=W(),c=await G(o.config),r=Y(o,c,s);console.log(""),console.log(l.bold("VAIF Delete Secret")),console.log(""),t.start("Finding secret...");try{let i=new URL(`${T}/functions/secrets/project/${r}`);o.envId&&i.searchParams.set("envId",o.envId);let n=await fetch(i.toString(),{headers:{Authorization:`Bearer ${s.token}`}});if(!n.ok)throw new Error(`Failed to fetch secrets: ${await n.text()}`);let f=(await n.json()).find(d=>d.key===e);f||(t.fail(`Secret "${e}" not found`),process.exit(1)),t.text=`Deleting secret "${e}"...`;let p=await fetch(`${T}/functions/secrets/${f.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${s.token}`}});if(!p.ok)throw new Error(`Failed to delete secret: ${await p.text()}`);t.succeed(`Deleted secret "${e}"`),console.log("");}catch(i){t.fail("Failed to delete secret"),i instanceof Error&&console.log(l.red(`
|
|
40
40
|
Error: ${i.message}`)),process.exit(1);}}var Te=process.env.VAIF_API_URL||"https://api.vaif.studio";function Io(e){try{let o=new URL(e);return o.password&&(o.password="****"),o.toString()}catch{return e.replace(/:[^@/]+@/,":****@")}}async function Le(e){let o=M(),t=I();(!t||!t.token)&&(console.log(l.red("Not logged in")),console.log(l.gray("Run `vaif login` first to authenticate")),process.exit(1));let s=e.config||"vaif.config.json",c=null;try{c=await a(s);}catch{}let r=e.projectId||c?.projectId||process.env.VAIF_PROJECT_ID||t.projectId;r||(console.log(l.red("No project ID specified")),console.log(l.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),o.start("Fetching project info...");try{let i=await fetch(`${Te}/v1/projects/${r}`,{headers:{Authorization:`Bearer ${t.token}`}});if(!i.ok){let p=await i.text();throw new Error(`Failed to fetch project: ${p}`)}let n=await i.json();o.stop(),console.log(""),console.log(l.bold("VAIF Project Info")),console.log("");let a=16,f=(p,d)=>{console.log(` ${l.gray(p.padEnd(a))} ${d}`);};f("Name:",l.white(n.name||"N/A")),f("Project ID:",l.white(r)),f("Region:",l.white(n.region||"us-east-1")),f("Plan:",l.white(n.plan||n.tier||"free")),f("Created:",l.white(n.createdAt?new Date(n.createdAt).toLocaleDateString():"N/A")),console.log(""),f("API URL:",l.cyan(n.apiUrl||`${Te}/v1`)),f("WS URL:",l.cyan(n.wsUrl||n.realtimeUrl||"N/A")),f("DB URL:",l.cyan(n.databaseUrl?Io(n.databaseUrl):"N/A")),f("Storage URL:",l.cyan(n.storageUrl||"N/A")),console.log("");}catch(i){o.fail("Failed to fetch project info"),i instanceof Error&&console.log(l.red(`
|
|
41
41
|
Error: ${i.message}`)),process.exit(1);}}var bo=process.env.VAIF_API_URL||"https://api.vaif.studio";async function _e(e){let o=M(),t=I();(!t||!t.token)&&(console.log(l.red("Not logged in")),console.log(l.gray("Run `vaif login` first to authenticate")),process.exit(1));let s=e.config||"vaif.config.json",c=null;try{c=await a(s);}catch{}let r=e.projectId||c?.projectId||process.env.VAIF_PROJECT_ID||t.projectId;r||(console.log(l.red("No project ID specified")),console.log(l.yellow("Set projectId in vaif.config.json or use --project-id flag.")),process.exit(1)),o.start("Fetching project status...");try{let i=await fetch(`${bo}/v1/projects/${r}?include=tables,functions,storage,connections`,{headers:{Authorization:`Bearer ${t.token}`}});if(!i.ok){let w=await i.text();throw new Error(`Failed to fetch project status: ${w}`)}let n=await i.json();o.stop(),console.log(""),console.log(l.bold("VAIF Project Status")),console.log("");let a=22,f=(w,E)=>{console.log(` ${l.gray(w.padEnd(a))} ${E}`);};f("Project:",l.white(n.name||r)),f("Plan:",l.white(n.plan||n.tier||"free")),console.log(""),console.log(l.gray(" --- Resources ---")),console.log("");let p=n.tableCount??n.tables?.length??"N/A",d=n.functionCount??n.functions?.length??"N/A",g=n.bucketCount??n.storage?.buckets?.length??"N/A",y=n.activeConnections??n.connections??"N/A";f("Tables:",l.white(String(p))),f("Functions:",l.white(String(d))),f("Storage Buckets:",l.white(String(g))),f("Active Connections:",l.white(String(y))),n.usage&&(console.log(""),console.log(l.gray(" --- Usage ---")),console.log(""),n.usage.dbSize&&f("Database Size:",l.white(n.usage.dbSize)),n.usage.storageSize&&f("Storage Size:",l.white(n.usage.storageSize)),n.usage.bandwidth&&f("Bandwidth:",l.white(n.usage.bandwidth)),n.usage.functionInvocations!=null&&f("Function Invocations:",l.white(String(n.usage.functionInvocations)))),console.log("");}catch(i){o.fail("Failed to fetch project status"),i instanceof Error&&console.log(l.red(`
|
|
42
|
-
Error: ${i.message}`)),process.exit(1);}}var Ue="1.7.
|
|
42
|
+
Error: ${i.message}`)),process.exit(1);}}var Ue="1.7.1",oe=l.hex("#00f0ff"),te=l.hex("#7b61ff"),ne=l.hex("#ff3dff"),se=l.hex("#00ff9d"),v=l.hex("#555570"),L=l.hex("#00f0ff");function So(){console.log(""),console.log(oe(" \u2566 \u2566")+te("\u2554\u2550\u2557\u2566")+ne("\u2554\u2550\u2557 ")+se("\u2554\u2550\u2557\u2566 \u2566")),console.log(oe(" \u255A\u2557\u2554\u255D")+te("\u2560\u2550\u2563\u2551")+ne("\u2560\u2563 ")+se("\u2551 \u2551 \u2551")),console.log(oe(" \u255A\u255D ")+te("\u2569 \u2569\u2569")+ne("\u255A ")+se("\u255A\u2550\u255D\u2569\u2550\u255D\u2569")),console.log(""),console.log(v(" \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(L(" VAIF Studio CLI")+v(` v${Ue}`)),console.log(v(" Build full-stack apps at lightning speed")),console.log(v(" \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(l.bold(" Quick Start")),console.log(v(" $ ")+L("vaif login")+v(" Authenticate")),console.log(v(" $ ")+L("vaif init -t react-spa")+v(" Scaffold project")),console.log(v(" $ ")+L("vaif db push")+v(" Push migrations")),console.log(v(" $ ")+L("vaif generate")+v(" Generate types")),console.log(v(" $ ")+L("vaif functions deploy")+v(" Deploy functions")),console.log(""),console.log(l.bold(" Categories")),console.log(v(" auth ")+l.white("login, logout, whoami")),console.log(v(" project ")+l.white("init, templates, info, status")),console.log(v(" schema ")+l.white("pull, push, generate")),console.log(v(" database ")+l.white("db push, db pull, db seed, db reset")),console.log(v(" deploy ")+l.white("functions deploy, functions list")),console.log(v(" security ")+l.white("keys, secrets")),console.log(""),console.log(v(" Run ")+L("vaif <command> --help")+v(" for details")),console.log(v(" Docs: ")+l.underline("https://docs.vaif.studio")),console.log("");}program.name("vaif").description("VAIF CLI - Type generation and development tools").version(Ue);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(fe);program.command("logout").description("Log out and remove stored credentials").action(de);program.command("whoami").description("Show current authenticated user").action(pe);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(d);program.command("templates").alias("tpl").description("List available project templates").action(c);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(Le);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(_e);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(ue);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(ye);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(b);var ze=program.command("functions").alias("fn").description("Manage serverless functions");ze.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(Ie);ze.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($e);var Q=program.command("db").description("Database management commands");Q.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(Ae);Q.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(Pe);Q.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(Se);Q.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(xe);var Je=program.command("keys").description("Manage API keys");Je.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(De);Je.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(Ee);var H=program.command("secrets").alias("sec").description("Manage function secrets");H.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(Re);H.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(Oe);H.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(Ne);H.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(Ve);process.argv.slice(2).length||(So(),process.exit(0));program.parse(process.argv);
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var v=require('fs'),w=require('path'),M=require('dotenv'),K=require('pg'),z=require('ora'),d=require('chalk'),q=require('prettier'),
|
|
1
|
+
'use strict';var v=require('fs'),w=require('path'),M=require('dotenv'),K=require('pg'),z=require('ora'),d=require('chalk'),q=require('prettier'),k=require('readline');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var v__default=/*#__PURE__*/_interopDefault(v);var w__default=/*#__PURE__*/_interopDefault(w);var M__default=/*#__PURE__*/_interopDefault(M);var K__default=/*#__PURE__*/_interopDefault(K);var z__default=/*#__PURE__*/_interopDefault(z);var d__default=/*#__PURE__*/_interopDefault(d);var q__default=/*#__PURE__*/_interopDefault(q);var k__default=/*#__PURE__*/_interopDefault(k);M__default.default.config();async function E(n){let a=w__default.default.resolve(n);if(!v__default.default.existsSync(a))return null;try{let t=v__default.default.readFileSync(a,"utf-8"),e=JSON.parse(t);return e.database?.url&&(e.database.url=V(e.database.url)),e.api?.apiKey&&(e.api.apiKey=V(e.api.apiKey)),e}catch{throw new Error(`Failed to parse config file: ${n}`)}}function V(n){return n.replace(/\$\{([^}]+)\}/g,(a,t)=>process.env[t]||a)}async function B(n,a){let t=await n.query(`
|
|
2
2
|
SELECT table_name, table_type
|
|
3
3
|
FROM information_schema.tables
|
|
4
4
|
WHERE table_schema = $1
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
ORDER BY t.typname, e.enumsortorder
|
|
47
47
|
`,[a]),c=new Map;for(let l of t.rows)c.set(l.table_name,[]);for(let l of e.rows){let s=c.get(l.table_name);s&&s.push(l);}let u=new Map;for(let l of r.rows){let s=u.get(l.enum_name)||[];s.push(l.enum_value),u.set(l.enum_name,s);}return {tables:c,enums:u,foreignKeys:i.rows}}var S={smallint:"number",integer:"number",bigint:"string",int2:"number",int4:"number",int8:"string",decimal:"string",numeric:"string",real:"number",float4:"number",float8:"number","double precision":"number",money:"string",boolean:"boolean",bool:"boolean",text:"string",varchar:"string",char:"string",character:"string","character varying":"string",name:"string",citext:"string",date:"string",time:"string",timetz:"string","time without time zone":"string","time with time zone":"string",timestamp:"string",timestamptz:"string","timestamp without time zone":"string","timestamp with time zone":"string",interval:"string",bytea:"Buffer",uuid:"string",json:"unknown",jsonb:"unknown",inet:"string",cidr:"string",macaddr:"string",macaddr8:"string",point:"{ x: number; y: number }",line:"string",lseg:"string",box:"string",path:"string",polygon:"string",circle:"string",ARRAY:"unknown[]"};function $(n,a){let{data_type:t,udt_name:e,is_nullable:i}=n;if(a.has(e)){let u=a.get(e).map(l=>`"${l}"`).join(" | ");return i==="YES"?`(${u}) | null`:u}if(t==="ARRAY"){let c=e.replace(/^_/,"");if(a.has(c)){let s=a.get(c).map(o=>`"${o}"`).join(" | ");return i==="YES"?`(${s})[] | null`:`(${s})[]`}let u=S[c]||"unknown";return i==="YES"?`${u}[] | null`:`${u}[]`}let r=S[t]||S[e]||"unknown";return i==="YES"&&(r=`${r} | null`),r}function x(n){return n.split(/[_\-\s]+/).map(a=>a.charAt(0).toUpperCase()+a.slice(1).toLowerCase()).join("")}function Y(n,a){let t=x(n),e=a.map(i=>` | "${i}"`).join(`
|
|
48
48
|
`);return `export type ${t} =
|
|
49
|
-
${e};`}function G(n,a,t){let e=x(n),i=[],r=[],c=[];for(let o of a){let p=$(o,t),m=o.column_name,g=o.column_default!==null||o.is_identity==="YES",
|
|
49
|
+
${e};`}function G(n,a,t){let e=x(n),i=[],r=[],c=[];for(let o of a){let p=$(o,t),m=o.column_name,g=o.column_default!==null||o.is_identity==="YES",b=o.is_nullable==="YES";i.push(` ${m}: ${p};`),g||o.column_name==="id"?r.push(` ${m}?: ${p.replace(" | null","")} | null;`):b?r.push(` ${m}?: ${p};`):r.push(` ${m}: ${p.replace(" | null","")};`),c.push(` ${m}?: ${p.replace(" | null","")} | null;`);}let u=`export interface ${e} {
|
|
50
50
|
${i.join(`
|
|
51
51
|
`)}
|
|
52
52
|
}`,l=`export interface ${e}Insert {
|
|
@@ -56,10 +56,10 @@ ${r.join(`
|
|
|
56
56
|
${c.join(`
|
|
57
57
|
`)}
|
|
58
58
|
}`;return {base:u,insert:l,update:s}}function H(n,a,t){let e=["/**"," * Auto-generated TypeScript types from database schema"," * Generated by @vaiftech/cli",` * Generated at: ${new Date().toISOString()}`," * "," * DO NOT EDIT MANUALLY - changes will be overwritten"," */",""];if(a.size>0){e.push("// ============ ENUMS ============"),e.push("");for(let[r,c]of a)e.push(Y(r,c)),e.push("");}e.push("// ============ TABLES ============"),e.push("");let i=[];for(let[r,c]of n){let{base:u,insert:l,update:s}=G(r,c,a);i.push(r),e.push(u),e.push(""),e.push(l),e.push(""),e.push(s),e.push("");}e.push("// ============ DATABASE SCHEMA ============"),e.push(""),e.push("export interface Database {");for(let r of i){let c=x(r);e.push(` ${r}: {`),e.push(` Row: ${c};`),e.push(` Insert: ${c}Insert;`),e.push(` Update: ${c}Update;`),e.push(" };");}return e.push("}"),e.push(""),e.push("export type TableName = keyof Database;"),e.push(""),e.push("// ============ HELPER TYPES ============"),e.push(""),e.push('export type Row<T extends TableName> = Database[T]["Row"];'),e.push('export type Insert<T extends TableName> = Database[T]["Insert"];'),e.push('export type Update<T extends TableName> = Database[T]["Update"];'),e.push(""),e.join(`
|
|
59
|
-
`)}async function
|
|
60
|
-
Provide a connection string via:`)),console.log(d__default.default.gray(" --connection
|
|
59
|
+
`)}async function W(n){let a=z__default.default("Loading configuration...").start();try{let t=await E(n.config),e=n.connection||t?.database?.url||process.env.DATABASE_URL;(!e||e.includes("${"))&&(a.fail("No database connection string provided"),console.log(d__default.default.yellow(`
|
|
60
|
+
Provide a connection string via:`)),console.log(d__default.default.gray(" --connection postgresql://user:pass@host:5432/db")),console.log(d__default.default.gray(" DATABASE_URL environment variable in .env")),console.log(d__default.default.gray(" database.url in vaif.config.json")),e?.includes("${")&&(console.log(d__default.default.yellow("\nYour vaif.config.json references ${DATABASE_URL} but the env var is not set.")),console.log(d__default.default.gray(" Add DATABASE_URL to your .env file or pass --connection directly."))),process.exit(1)),a.text="Connecting to database...";let i=new K__default.default.Client({connectionString:e});await i.connect(),a.text="Introspecting schema...";let{tables:r,enums:c,foreignKeys:u}=await B(i,n.schema);if(await i.end(),r.size===0){a.warn(`No tables found in schema "${n.schema}"`);return}a.text=`Generating types for ${r.size} tables...`;let l=H(r,c,u),s=await q__default.default.format(l,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100});if(n.dryRun){a.succeed("Generated types (dry run):"),console.log(""),console.log(d__default.default.gray("\u2500".repeat(60))),console.log(s),console.log(d__default.default.gray("\u2500".repeat(60)));return}let o=w__default.default.resolve(n.output),p=w__default.default.dirname(o);v__default.default.existsSync(p)||v__default.default.mkdirSync(p,{recursive:!0}),v__default.default.writeFileSync(o,s,"utf-8"),a.succeed(`Generated types for ${r.size} tables \u2192 ${d__default.default.cyan(n.output)}`),console.log(""),console.log(d__default.default.green("Generated:")),console.log(d__default.default.gray(` Tables: ${r.size}`)),console.log(d__default.default.gray(` Enums: ${c.size}`)),console.log(""),console.log(d__default.default.gray("Import in your code:")),console.log(d__default.default.cyan(` import type { Database, Row, Insert, Update } from "${n.output.replace(/\.ts$/,"")}";`));}catch(t){a.fail("Failed to generate types"),t instanceof Error&&(console.error(d__default.default.red(`
|
|
61
61
|
Error: ${t.message}`)),t.message.includes("ECONNREFUSED")&&console.log(d__default.default.yellow(`
|
|
62
|
-
Make sure your database is running and accessible.`))),process.exit(1);}}var
|
|
62
|
+
Make sure your database is running and accessible.`))),process.exit(1);}}var y=[{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"}],J={"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:`{
|
|
63
63
|
"name": "my-vaif-app",
|
|
64
64
|
"private": true,
|
|
65
65
|
"version": "0.1.0",
|
|
@@ -155,24 +155,27 @@ body {
|
|
|
155
155
|
|
|
156
156
|
// Browser client \u2013 safe to use in Client Components
|
|
157
157
|
export const vaif = createVaifClient({
|
|
158
|
-
|
|
158
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
159
159
|
apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
// Server client \u2013 use in Server Components, Route Handlers, Server Actions
|
|
163
163
|
export function createVaifServer() {
|
|
164
164
|
return createVaifClient({
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
166
|
+
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
169
|
`},{path:".env.local.example",content:`# VAIF Configuration
|
|
170
170
|
# Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
NEXT_PUBLIC_VAIF_API_KEY=your-
|
|
172
|
+
NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
173
|
+
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
174
174
|
VAIF_SECRET_KEY=your-secret-key
|
|
175
175
|
|
|
176
|
+
# Database connection (for vaif generate, vaif db push)
|
|
177
|
+
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
178
|
+
|
|
176
179
|
# CLI uses these (non-prefixed) for vaif db push, vaif secrets, etc.
|
|
177
180
|
VAIF_PROJECT_ID=your-project-id
|
|
178
181
|
`},{path:".gitignore",content:`node_modules
|
|
@@ -288,8 +291,8 @@ export async function middleware(request: NextRequest) {
|
|
|
288
291
|
if (!isProtected) return NextResponse.next();
|
|
289
292
|
|
|
290
293
|
const vaif = createVaifClient({
|
|
291
|
-
|
|
292
|
-
|
|
294
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
295
|
+
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
293
296
|
});
|
|
294
297
|
|
|
295
298
|
return authMiddleware(vaif, request, {
|
|
@@ -650,13 +653,13 @@ function Home() {
|
|
|
650
653
|
`},{path:"src/lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
|
|
651
654
|
|
|
652
655
|
export const vaif = createVaifClient({
|
|
653
|
-
|
|
656
|
+
baseUrl: import.meta.env.VITE_VAIF_API_URL || 'https://api.vaif.studio',
|
|
654
657
|
apiKey: import.meta.env.VITE_VAIF_API_KEY,
|
|
655
658
|
});
|
|
656
659
|
`},{path:"src/vite-env.d.ts",content:`/// <reference types="vite/client" />
|
|
657
660
|
|
|
658
661
|
interface ImportMetaEnv {
|
|
659
|
-
readonly
|
|
662
|
+
readonly VITE_VAIF_API_URL: string;
|
|
660
663
|
readonly VITE_VAIF_API_KEY: string;
|
|
661
664
|
}
|
|
662
665
|
|
|
@@ -664,13 +667,13 @@ interface ImportMeta {
|
|
|
664
667
|
readonly env: ImportMetaEnv;
|
|
665
668
|
}
|
|
666
669
|
`},{path:".env.example",content:`# VAIF Configuration
|
|
667
|
-
# Get these values from https://vaif.studio/app/security/api-keys
|
|
670
|
+
# Get these values from https://vaif.studio/app/security/api-keys
|
|
668
671
|
|
|
669
|
-
|
|
670
|
-
VITE_VAIF_API_KEY=your-
|
|
672
|
+
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
673
|
+
VITE_VAIF_API_KEY=your-api-key
|
|
671
674
|
|
|
672
|
-
#
|
|
673
|
-
|
|
675
|
+
# Database connection (for vaif generate, vaif db push)
|
|
676
|
+
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
674
677
|
`},{path:".gitignore",content:`node_modules
|
|
675
678
|
dist
|
|
676
679
|
.env
|
|
@@ -2609,7 +2612,7 @@ func HelloHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
2609
2612
|
`}]},postInstructions:["go mod tidy","# Copy .env.example to .env and add your VAIF credentials","go run main.go"]},"todo-app":{name:"Todo App",description:"Simple React todo app \u2013 great for learning VAIF basics",tag:"React Starter",defaultFeatures:["database"],files:[{path:"src/lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
|
|
2610
2613
|
|
|
2611
2614
|
export const vaif = createVaifClient({
|
|
2612
|
-
|
|
2615
|
+
baseUrl: import.meta.env.VITE_VAIF_API_URL || 'https://api.vaif.studio',
|
|
2613
2616
|
apiKey: import.meta.env.VITE_VAIF_API_KEY,
|
|
2614
2617
|
});
|
|
2615
2618
|
|
|
@@ -2661,13 +2664,13 @@ export async function deleteTodo(id: string): Promise<void> {
|
|
|
2661
2664
|
if (error) throw error;
|
|
2662
2665
|
}
|
|
2663
2666
|
`},{path:".env.example",content:`# VAIF Configuration
|
|
2664
|
-
# Get these values from https://vaif.studio/app/security/api-keys
|
|
2667
|
+
# Get these values from https://vaif.studio/app/security/api-keys
|
|
2665
2668
|
|
|
2666
|
-
|
|
2667
|
-
VITE_VAIF_API_KEY=your-
|
|
2669
|
+
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
2670
|
+
VITE_VAIF_API_KEY=your-api-key
|
|
2668
2671
|
|
|
2669
|
-
#
|
|
2670
|
-
|
|
2672
|
+
# Database connection (for vaif generate, vaif db push)
|
|
2673
|
+
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
2671
2674
|
`},{path:"README.md",content:`# Todo App \u2014 VAIF Starter
|
|
2672
2675
|
|
|
2673
2676
|
A simple React todo application for learning [VAIF Studio](https://vaif.studio) basics, including typed database queries and CRUD operations.
|
|
@@ -2803,15 +2806,8 @@ export const posts = pgTable("posts", {
|
|
|
2803
2806
|
`}]},dependencies:["@vaiftech/client","@vaiftech/react"],postInstructions:["Copy .env.example to .env and fill in your project credentials","Create a 'todos' table in your VAIF dashboard with columns: id (uuid), title (text), done (boolean), created_at (timestamptz)","Import helpers from './lib/vaif' in your components","Run: npx vaif generate to generate TypeScript types"]},"realtime-chat":{name:"Realtime Chat",description:"React chat app with VAIF realtime subscriptions for live messaging",tag:"React + Realtime",defaultFeatures:["database","realtime","auth"],files:[{path:"src/lib/vaif.ts",content:`import { createVaifClient } from "@vaiftech/client";
|
|
2804
2807
|
|
|
2805
2808
|
export const vaif = createVaifClient({
|
|
2806
|
-
|
|
2809
|
+
baseUrl: import.meta.env.VITE_VAIF_API_URL || 'https://api.vaif.studio',
|
|
2807
2810
|
apiKey: import.meta.env.VITE_VAIF_API_KEY,
|
|
2808
|
-
realtime: {
|
|
2809
|
-
enabled: true,
|
|
2810
|
-
// Automatically reconnect on connection loss
|
|
2811
|
-
reconnect: true,
|
|
2812
|
-
reconnectInterval: 1000,
|
|
2813
|
-
maxReconnectAttempts: 10,
|
|
2814
|
-
},
|
|
2815
2811
|
});
|
|
2816
2812
|
|
|
2817
2813
|
export interface Message {
|
|
@@ -2949,13 +2945,13 @@ export function useRealtimeMessages({
|
|
|
2949
2945
|
return { messages, isLoading, error, refresh };
|
|
2950
2946
|
}
|
|
2951
2947
|
`},{path:".env.example",content:`# VAIF Configuration
|
|
2952
|
-
# Get these values from https://vaif.studio/app/security/api-keys
|
|
2948
|
+
# Get these values from https://vaif.studio/app/security/api-keys
|
|
2953
2949
|
|
|
2954
|
-
|
|
2955
|
-
VITE_VAIF_API_KEY=your-
|
|
2950
|
+
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
2951
|
+
VITE_VAIF_API_KEY=your-api-key
|
|
2956
2952
|
|
|
2957
|
-
#
|
|
2958
|
-
|
|
2953
|
+
# Database connection (for vaif generate, vaif db push)
|
|
2954
|
+
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
2959
2955
|
`},{path:"README.md",content:`# Realtime Chat \u2014 VAIF Starter
|
|
2960
2956
|
|
|
2961
2957
|
A React chat application with live messaging powered by [VAIF Studio](https://vaif.studio) realtime subscriptions.
|
|
@@ -3106,15 +3102,15 @@ export const posts = pgTable("posts", {
|
|
|
3106
3102
|
|
|
3107
3103
|
// Browser client \u2013 use in Client Components
|
|
3108
3104
|
export const vaif = createVaifClient({
|
|
3109
|
-
|
|
3105
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3110
3106
|
apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
|
|
3111
3107
|
});
|
|
3112
3108
|
|
|
3113
3109
|
// Server client \u2013 use in Server Components, Route Handlers, Server Actions
|
|
3114
3110
|
export function createVaifServer() {
|
|
3115
3111
|
return createVaifClient({
|
|
3116
|
-
|
|
3117
|
-
|
|
3112
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3113
|
+
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
3118
3114
|
});
|
|
3119
3115
|
}
|
|
3120
3116
|
`},{path:"lib/auth.ts",content:`import { createVaifServer } from "./vaif";
|
|
@@ -3267,10 +3263,13 @@ export async function requireTeamRole(
|
|
|
3267
3263
|
`},{path:".env.example",content:`# VAIF Configuration
|
|
3268
3264
|
# Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
|
|
3269
3265
|
|
|
3270
|
-
|
|
3271
|
-
NEXT_PUBLIC_VAIF_API_KEY=your-
|
|
3266
|
+
NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
3267
|
+
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
3272
3268
|
VAIF_SECRET_KEY=your-secret-key
|
|
3273
3269
|
|
|
3270
|
+
# Database connection (for vaif generate, vaif db push)
|
|
3271
|
+
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
3272
|
+
|
|
3274
3273
|
# CLI uses these (non-prefixed) for vaif db push, vaif secrets, etc.
|
|
3275
3274
|
VAIF_PROJECT_ID=your-project-id
|
|
3276
3275
|
`},{path:"README.md",content:`# SaaS Starter \u2014 VAIF Studio
|
|
@@ -3419,15 +3418,15 @@ export const posts = pgTable("posts", {
|
|
|
3419
3418
|
|
|
3420
3419
|
// Browser client
|
|
3421
3420
|
export const vaif = createVaifClient({
|
|
3422
|
-
|
|
3421
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3423
3422
|
apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
|
|
3424
3423
|
});
|
|
3425
3424
|
|
|
3426
3425
|
// Server client
|
|
3427
3426
|
export function createVaifServer() {
|
|
3428
3427
|
return createVaifClient({
|
|
3429
|
-
|
|
3430
|
-
|
|
3428
|
+
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3429
|
+
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
3431
3430
|
});
|
|
3432
3431
|
}
|
|
3433
3432
|
`},{path:"lib/storage.ts",content:`import { createVaifServer } from "./vaif";
|
|
@@ -3542,10 +3541,13 @@ function getContentType(fileName: string): string {
|
|
|
3542
3541
|
`},{path:".env.example",content:`# VAIF Configuration
|
|
3543
3542
|
# Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
|
|
3544
3543
|
|
|
3545
|
-
|
|
3546
|
-
NEXT_PUBLIC_VAIF_API_KEY=your-
|
|
3544
|
+
NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
3545
|
+
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
3547
3546
|
VAIF_SECRET_KEY=your-secret-key
|
|
3548
3547
|
|
|
3548
|
+
# Database connection (for vaif generate, vaif db push)
|
|
3549
|
+
# DATABASE_URL=postgresql://user:password@host:5432/dbname
|
|
3550
|
+
|
|
3549
3551
|
# CLI uses these (non-prefixed) for vaif db push, vaif secrets, etc.
|
|
3550
3552
|
VAIF_PROJECT_ID=your-project-id
|
|
3551
3553
|
`},{path:"README.md",content:`# E-commerce API \u2014 VAIF Studio
|
|
@@ -3688,19 +3690,19 @@ export const posts = pgTable("posts", {
|
|
|
3688
3690
|
|
|
3689
3691
|
return Response.json({ message: \`Hello, \${name}!\` });
|
|
3690
3692
|
}
|
|
3691
|
-
`}]},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"]}};async function X(n){if(!process.stdin.isTTY||!process.stdout.isTTY)return n;let a=new Set(n.map(e=>
|
|
3692
|
-
? Which VAIF features do you want to include?`)),
|
|
3693
|
+
`}]},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"]}};async function X(n){if(!process.stdin.isTTY||!process.stdout.isTTY)return n;let a=new Set(n.map(e=>y.findIndex(i=>i.name===e)).filter(e=>e>=0)),t=0;return new Promise(e=>{let i=k__default.default.createInterface({input:process.stdin,output:process.stdout});k__default.default.emitKeypressEvents(process.stdin,i),process.stdin.setRawMode&&process.stdin.setRawMode(true);function r(){let u=y.length+2;process.stdout.write(`\x1B[${u}A`),c();}function c(){console.log(d__default.default.bold(`
|
|
3694
|
+
? Which VAIF features do you want to include?`)),y.forEach((u,l)=>{let s=a.has(l)?d__default.default.green("[x]"):"[ ]",o=l===t?d__default.default.cyan("> "):" ";console.log(`${o}${s} ${u.label} ${d__default.default.gray(`(${u.description})`)}`);}),console.log(d__default.default.gray(" (up/down to move, space to toggle, enter to confirm)"));}c(),process.stdin.on("keypress",(u,l)=>{if(l.name==="up"&&t>0)t--,r();else if(l.name==="down"&&t<y.length-1)t++,r();else if(l.name==="space")a.has(t)?a.delete(t):a.add(t),r();else if(l.name==="return"){process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close();let s=[...a].sort().map(o=>y[o].name);e(s.length>0?s:n);}else l.name==="c"&&l.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close(),process.exit(0));});})}async function F(n,a={}){let t=J[n];t||(console.log(d__default.default.red(`
|
|
3693
3695
|
Unknown template: ${n}`)),console.log(d__default.default.yellow(`Run 'vaif templates' to see available templates.
|
|
3694
|
-
`)),process.exit(1));let e;a.features&&a.features.length>0?e=a.features.filter(s=>
|
|
3695
|
-
No features specified.`)),console.log(d__default.default.yellow("Usage: vaif init --template <name> --add-features <features>")),console.log(d__default.default.gray("Available features: auth, database, realtime, storage, functions")),process.exit(1)):t.featureFiles&&Object.keys(t.featureFiles).length>0?e=await X(t.defaultFeatures??["database","auth"]):e=t.defaultFeatures??[],a.addOnly?(console.log(""),console.log(d__default.default.bold(`Adding features to ${d__default.default.cyan(t.name)} project...`)),console.log(d__default.default.gray(` Features: ${e.join(", ")}`)),console.log("")):(console.log(""),console.log(d__default.default.bold(`Scaffolding ${d__default.default.cyan(t.name)} template...`)),e.length>0&&console.log(d__default.default.gray(` Features: ${e.join(", ")}`)),console.log(""));let i=a.addOnly?[]:[...t.files];if(t.featureFiles)for(let s of e){let o=t.featureFiles[s];o&&i.push(...o);}let r=0,c=0;for(let s of i){let o=w__default.default.resolve(s.path),p=w__default.default.dirname(o);if(v__default.default.existsSync(p)||v__default.default.mkdirSync(p,{recursive:true}),s.path==="package.json"&&v__default.default.existsSync(o)&&!a.force)try{let m=JSON.parse(v__default.default.readFileSync(o,"utf-8")),g=JSON.parse(s.content),
|
|
3696
|
-
`,"utf-8"),console.log(d__default.default.green(` merge ${s.path} (added dependencies)`)),r++;continue}catch{}if(v__default.default.existsSync(o)&&!a.force){console.log(d__default.default.yellow(` skip ${s.path} (already exists)`)),c++;continue}v__default.default.writeFileSync(o,s.content,"utf-8"),console.log(d__default.default.green(` create ${s.path}`)),r++;}console.log(""),r>0&&console.log(d__default.default.green(`Created ${r} file${r!==1?"s":""}.`)),c>0&&console.log(d__default.default.yellow(`Skipped ${c} file${c!==1?"s":""} (use --force to overwrite).`));let u={auth:{"@vaiftech/auth":"^1.0.0"},database:{},realtime:{},storage:{},functions:{}},l=w__default.default.resolve("package.json");if(v__default.default.existsSync(l)&&e.length>0)try{let s=JSON.parse(v__default.default.readFileSync(l,"utf-8")),o=!1;for(let p of e){let m=u[p];if(m)for(let[g,
|
|
3696
|
+
`)),process.exit(1));let e;a.features&&a.features.length>0?e=a.features.filter(s=>y.some(o=>o.name===s)):a.addOnly?(console.log(d__default.default.red(`
|
|
3697
|
+
No features specified.`)),console.log(d__default.default.yellow("Usage: vaif init --template <name> --add-features <features>")),console.log(d__default.default.gray("Available features: auth, database, realtime, storage, functions")),process.exit(1)):t.featureFiles&&Object.keys(t.featureFiles).length>0?e=await X(t.defaultFeatures??["database","auth"]):e=t.defaultFeatures??[],a.addOnly?(console.log(""),console.log(d__default.default.bold(`Adding features to ${d__default.default.cyan(t.name)} project...`)),console.log(d__default.default.gray(` Features: ${e.join(", ")}`)),console.log("")):(console.log(""),console.log(d__default.default.bold(`Scaffolding ${d__default.default.cyan(t.name)} template...`)),e.length>0&&console.log(d__default.default.gray(` Features: ${e.join(", ")}`)),console.log(""));let i=a.addOnly?[]:[...t.files];if(t.featureFiles)for(let s of e){let o=t.featureFiles[s];o&&i.push(...o);}let r=0,c=0;for(let s of i){let o=w__default.default.resolve(s.path),p=w__default.default.dirname(o);if(v__default.default.existsSync(p)||v__default.default.mkdirSync(p,{recursive:true}),s.path==="package.json"&&v__default.default.existsSync(o)&&!a.force)try{let m=JSON.parse(v__default.default.readFileSync(o,"utf-8")),g=JSON.parse(s.content),b=U=>{if(!U)return {};let N={};for(let[j,A]of Object.entries(U))!A.startsWith("workspace:")&&!A.startsWith("link:")&&!A.startsWith("file:")&&(N[j]=A);return N};m.dependencies={...b(m.dependencies),...g.dependencies||{}},m.devDependencies={...b(m.devDependencies),...g.devDependencies||{}},g.scripts&&(m.scripts={...m.scripts||{},...g.scripts}),v__default.default.writeFileSync(o,JSON.stringify(m,null,2)+`
|
|
3698
|
+
`,"utf-8"),console.log(d__default.default.green(` merge ${s.path} (added dependencies)`)),r++;continue}catch{}if(v__default.default.existsSync(o)&&!a.force){console.log(d__default.default.yellow(` skip ${s.path} (already exists)`)),c++;continue}v__default.default.writeFileSync(o,s.content,"utf-8"),console.log(d__default.default.green(` create ${s.path}`)),r++;}console.log(""),r>0&&console.log(d__default.default.green(`Created ${r} file${r!==1?"s":""}.`)),c>0&&console.log(d__default.default.yellow(`Skipped ${c} file${c!==1?"s":""} (use --force to overwrite).`));let u={auth:{"@vaiftech/auth":"^1.0.0"},database:{},realtime:{},storage:{},functions:{}},l=w__default.default.resolve("package.json");if(v__default.default.existsSync(l)&&e.length>0)try{let s=JSON.parse(v__default.default.readFileSync(l,"utf-8")),o=!1;for(let p of e){let m=u[p];if(m)for(let[g,b]of Object.entries(m))s.dependencies?.[g]||(s.dependencies=s.dependencies||{},s.dependencies[g]=b,o=!0);}o&&v__default.default.writeFileSync(l,JSON.stringify(s,null,2)+`
|
|
3697
3699
|
`,"utf-8");}catch{}(t.dependencies?.length||t.devDependencies?.length)&&(console.log(""),console.log(d__default.default.bold("Install dependencies:")),t.dependencies?.length&&console.log(d__default.default.cyan(` npm install ${t.dependencies.join(" ")}`)),t.devDependencies?.length&&console.log(d__default.default.cyan(` npm install -D ${t.devDependencies.join(" ")}`))),console.log(""),console.log(d__default.default.bold.green("Project scaffolded successfully!")),console.log(""),console.log(d__default.default.bold(" Next steps:")),t.postInstructions.forEach(s=>{console.log(d__default.default.gray(` ${s}`));}),console.log(""),console.log(d__default.default.gray(" Get your project credentials at https://vaif.studio/app/security/api-keys")),console.log("");}var Z={$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 ee(n){if(n.addFeatures){n.template||(console.log(d__default.default.red(`
|
|
3698
3700
|
--add-features requires --template to know which template to use.`)),console.log(d__default.default.gray("Example: vaif init --template react-spa --add-features functions,storage")),process.exit(1));let e=n.addFeatures.split(",").map(i=>i.trim());await F(n.template,{force:n.force,features:e,addOnly:true});return}let a=z__default.default("Initializing VAIF configuration...").start(),t=w__default.default.resolve("vaif.config.json");v__default.default.existsSync(t)&&!n.force&&(a.fail("vaif.config.json already exists"),console.log(d__default.default.yellow(`
|
|
3699
3701
|
Use --force to overwrite existing configuration.`)),process.exit(1));try{if(v__default.default.writeFileSync(t,JSON.stringify(Z,null,2),"utf-8"),a.succeed("Created vaif.config.json"),n.template){let e=n.features?n.features.split(",").map(i=>i.trim()):void 0;await F(n.template,{force:n.force,features:e});}else {let e=w__default.default.resolve(".env.example");if(v__default.default.existsSync(e)||(v__default.default.writeFileSync(e,`# VAIF Configuration
|
|
3700
3702
|
DATABASE_URL=postgresql://user:password@localhost:5432/database
|
|
3701
3703
|
VAIF_API_KEY=your-api-key
|
|
3702
3704
|
`,"utf-8"),console.log(d__default.default.gray("Created .env.example"))),n.typescript){let i=w__default.default.resolve("src/types");v__default.default.existsSync(i)||(v__default.default.mkdirSync(i,{recursive:!0}),console.log(d__default.default.gray("Created src/types directory")));}console.log(""),console.log(d__default.default.green("VAIF initialized successfully!")),console.log(""),console.log(d__default.default.gray("Next steps:")),console.log(d__default.default.gray(" 1. Update vaif.config.json with your project ID")),console.log(d__default.default.gray(" 2. Set DATABASE_URL in your environment")),console.log(d__default.default.gray(" 3. Run: npx vaif generate")),console.log("");}}catch(e){a.fail("Failed to initialize"),e instanceof Error&&console.error(d__default.default.red(`
|
|
3703
|
-
Error: ${e.message}`)),process.exit(1);}}async function
|
|
3705
|
+
Error: ${e.message}`)),process.exit(1);}}async function Le(n){let{connectionString:a,schema:t="public"}=n,e=new K__default.default.Client({connectionString:a});await e.connect();try{let i=await e.query(`
|
|
3704
3706
|
SELECT table_name, table_type
|
|
3705
3707
|
FROM information_schema.tables
|
|
3706
3708
|
WHERE table_schema = $1
|
|
@@ -3732,7 +3734,7 @@ Error: ${e.message}`)),process.exit(1);}}async function Ve(n){let{connectionStri
|
|
|
3732
3734
|
ORDER BY t.typname, e.enumsortorder
|
|
3733
3735
|
`,[t]),u=new Map;for(let o of i.rows)u.set(o.table_name,[]);for(let o of r.rows){let p=u.get(o.table_name);p&&p.push(o);}let l=new Map;for(let o of c.rows){let p=l.get(o.enum_name)||[];p.push(o.enum_value),l.set(o.enum_name,p);}let s=ie(u,l);return q__default.default.format(s,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100})}finally{await e.end();}}var P={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",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",point:"{ x: number; y: number }",ARRAY:"unknown[]"};function ne(n,a){let{data_type:t,udt_name:e,is_nullable:i}=n;if(a.has(e)){let u=a.get(e).map(l=>`"${l}"`).join(" | ");return i==="YES"?`(${u}) | null`:u}if(t==="ARRAY"){let c=e.replace(/^_/,"");if(a.has(c)){let s=a.get(c).map(o=>`"${o}"`).join(" | ");return i==="YES"?`(${s})[] | null`:`(${s})[]`}let u=P[c]||"unknown";return i==="YES"?`${u}[] | null`:`${u}[]`}let r=P[t]||P[e]||"unknown";return i==="YES"&&(r=`${r} | null`),r}function C(n){return n.split(/[_\-\s]+/).map(a=>a.charAt(0).toUpperCase()+a.slice(1).toLowerCase()).join("")}function ie(n,a){let t=["/**"," * 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(a.size>0){t.push("// ============ ENUMS ============"),t.push("");for(let[i,r]of a){let c=C(i),u=r.map(l=>` | "${l}"`).join(`
|
|
3734
3736
|
`);t.push(`export type ${c} =
|
|
3735
|
-
${u};`),t.push("");}}t.push("// ============ TABLES ============"),t.push("");let e=[];for(let[i,r]of n){e.push(i);let c=C(i),u=[],l=[],s=[];for(let o of r){let p=ne(o,a),m=o.column_name,g=o.column_default!==null||o.is_identity==="YES",
|
|
3737
|
+
${u};`),t.push("");}}t.push("// ============ TABLES ============"),t.push("");let e=[];for(let[i,r]of n){e.push(i);let c=C(i),u=[],l=[],s=[];for(let o of r){let p=ne(o,a),m=o.column_name,g=o.column_default!==null||o.is_identity==="YES",b=o.is_nullable==="YES";u.push(` ${m}: ${p};`),g||o.column_name==="id"?l.push(` ${m}?: ${p.replace(" | null","")} | null;`):b?l.push(` ${m}?: ${p};`):l.push(` ${m}: ${p.replace(" | null","")};`),s.push(` ${m}?: ${p.replace(" | null","")} | null;`);}t.push(`export interface ${c} {
|
|
3736
3738
|
${u.join(`
|
|
3737
3739
|
`)}
|
|
3738
3740
|
}`),t.push(""),t.push(`export interface ${c}Insert {
|
|
@@ -3742,4 +3744,4 @@ ${l.join(`
|
|
|
3742
3744
|
${s.join(`
|
|
3743
3745
|
`)}
|
|
3744
3746
|
}`),t.push("");}t.push("// ============ DATABASE SCHEMA ============"),t.push(""),t.push("export interface Database {");for(let i of e){let r=C(i);t.push(` ${i}: {`),t.push(` Row: ${r};`),t.push(` Insert: ${r}Insert;`),t.push(` Update: ${r}Update;`),t.push(" };");}return t.push("}"),t.push(""),t.push("export type TableName = keyof Database;"),t.push(""),t.push("// ============ HELPER TYPES ============"),t.push(""),t.push('export type Row<T extends TableName> = Database[T]["Row"];'),t.push('export type Insert<T extends TableName> = Database[T]["Insert"];'),t.push('export type Update<T extends TableName> = Database[T]["Update"];'),t.push(""),t.join(`
|
|
3745
|
-
`)}exports.generateTypes=
|
|
3747
|
+
`)}exports.generateTypes=W;exports.generateTypesFromConnection=Le;exports.initConfig=ee;exports.loadConfig=E;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export{b as generateTypes,d as initConfig,a as loadConfig}from'./chunk-
|
|
1
|
+
export{b as generateTypes,d as initConfig,a as loadConfig}from'./chunk-N7OY2COL.js';import T from'pg';import $ from'prettier';async function S(p){let{connectionString:a,schema:e="public"}=p,r=new T.Client({connectionString:a});await r.connect();try{let t=await r.query(`
|
|
2
2
|
SELECT table_name, table_type
|
|
3
3
|
FROM information_schema.tables
|
|
4
4
|
WHERE table_schema = $1
|