@vaiftech/cli 1.7.4 → 1.7.6
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 +3 -1
- package/dist/{chunk-CMWHBLLZ.js → chunk-T7GOLIY4.js} +134 -51
- package/dist/cli.cjs +160 -77
- package/dist/cli.js +2 -2
- package/dist/index.cjs +138 -55
- 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 {c,d,e,h,g,f,b,a}from'./chunk-
|
|
2
|
+
import {c,d,e,h,g,f,b,a}from'./chunk-T7GOLIY4.js';import'dotenv/config';import {program}from'commander';import l from'chalk';import C from'fs';import w from'path';import U from'ora';import ze from'readline';var Te=process.env.VAIF_API_URL||"https://api.vaif.studio";async function Le(e,o,t="public"){let i=await fetch(`${Te}/v1/projects/${o}/schema?schema=${t}`,{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}});if(!i.ok){let r=await i.text();throw new Error(`Failed to fetch schema: ${r}`)}return i.json()}async function ie(e){let o=U(),t=b();(!t||!t.token)&&(console.log(l.red("Not logged in")),console.log(l.gray("Run `vaif login` first to authenticate")),process.exit(1));let i=e.config||"vaif.config.json",r=null;o.start("Loading configuration...");try{r=await a(i);}catch(s){o.fail("Failed to load config"),console.log(l.red(`
|
|
3
3
|
Error: ${s}`)),process.exit(1);}r||(o.fail("No configuration found"),console.log(l.yellow("\nRun `vaif init` to create a configuration file.")),process.exit(1));let c=e.projectId||r.projectId||process.env.VAIF_PROJECT_ID||t.projectId;c||(o.fail("No project ID specified"),console.log(l.yellow(`
|
|
4
4
|
Set projectId in vaif.config.json or use --project-id flag.`)),process.exit(1)),o.text="Fetching remote schema...";try{let s=e.schema||r.database?.schema||"public",n=await Le(t.token,c,s);o.succeed("Schema fetched successfully");let a=e.output||w.resolve("vaif.schema.json"),d={$schema:"https://vaif.studio/schemas/schema.json",projectId:c,schema:s,pulledAt:new Date().toISOString(),...n};C.writeFileSync(a,JSON.stringify(d,null,2),"utf-8"),console.log(""),console.log(l.green(`Schema saved to: ${a}`)),console.log(""),console.log(l.gray("Schema summary:")),console.log(l.gray(` Tables: ${(n.tables||[]).length}`)),console.log(l.gray(` Enums: ${(n.enums||[]).length}`)),console.log(l.gray(` Functions: ${(n.functions||[]).length}`)),console.log(""),console.log(l.gray("Next steps:")),console.log(l.gray(" - Run `vaif generate` to generate TypeScript types")),console.log(l.gray(" - Edit the schema and run `vaif push` to deploy changes")),console.log("");}catch(s){o.fail("Failed to fetch schema"),s instanceof Error&&console.log(l.red(`
|
|
5
5
|
Error: ${s.message}`)),process.exit(1);}}var ce=process.env.VAIF_API_URL||"https://api.vaif.studio";function Be(e){let o=ze.createInterface({input:process.stdin,output:process.stdout});return new Promise(t=>{o.question(e,i=>{o.close(),t(i);});})}async function Je(e,o,t){let i=await fetch(`${ce}/v1/projects/${o}/schema/preview`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({schema:t})});if(!i.ok){let r=await i.text();throw new Error(`Failed to preview changes: ${r}`)}return i.json()}async function Ke(e,o,t){let i=await fetch(`${ce}/v1/projects/${o}/schema/apply`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({schema:t})});if(!i.ok){let r=await i.text();throw new Error(`Failed to apply changes: ${r}`)}return i.json()}function Me(e){if(console.log(""),console.log(l.bold("Schema Changes:")),console.log(""),e.added.length===0&&e.modified.length===0&&e.removed.length===0){console.log(l.gray(" No changes detected. Schema is up to date."));return}if(e.added.length>0){console.log(l.green.bold(" + Added:"));for(let o of e.added)console.log(l.green(` + ${o.type}: ${o.name}`));console.log("");}if(e.modified.length>0){console.log(l.yellow.bold(" ~ Modified:"));for(let o of e.modified){console.log(l.yellow(` ~ ${o.type}: ${o.name}`));for(let t of o.changes)console.log(l.gray(` ${t}`));}console.log("");}if(e.removed.length>0){console.log(l.red.bold(" - Removed:"));for(let o of e.removed)console.log(l.red(` - ${o.type}: ${o.name}`));console.log("");}}async function ae(e){let o=U(),t=b();(!t||!t.token)&&(console.log(l.red("Not logged in")),console.log(l.gray("Run `vaif login` first to authenticate")),process.exit(1));let i=e.config||"vaif.config.json",r=null;o.start("Loading configuration...");try{r=await a(i);}catch(a){o.fail("Failed to load config"),console.log(l.red(`
|
|
@@ -30,4 +30,4 @@ Error: ${c.message}`)),process.exit(1);}}async function Pe(e,o){let t=U(),i=J(),
|
|
|
30
30
|
Error: ${s.message}`)),process.exit(1);}}async function xe(e,o){let t=U(),i=J(),r=await K(o.config),c=M(o,r,i);console.log(""),console.log(l.bold("VAIF Delete Secret")),console.log(""),t.start("Finding secret...");try{let s=new URL(`${N}/functions/secrets/project/${c}`);o.envId&&s.searchParams.set("envId",o.envId);let n=await fetch(s.toString(),{headers:{Authorization:`Bearer ${i.token}`}});if(!n.ok)throw new Error(`Failed to fetch secrets: ${await n.text()}`);let d=(await n.json()).find(f=>f.key===e);d||(t.fail(`Secret "${e}" not found`),process.exit(1)),t.text=`Deleting secret "${e}"...`;let p=await fetch(`${N}/functions/secrets/${d.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${i.token}`}});if(!p.ok)throw new Error(`Failed to delete secret: ${await p.text()}`);t.succeed(`Deleted secret "${e}"`),console.log("");}catch(s){t.fail("Failed to delete secret"),s instanceof Error&&console.log(l.red(`
|
|
31
31
|
Error: ${s.message}`)),process.exit(1);}}var Fe=process.env.VAIF_API_URL||"https://api.vaif.studio";function oo(e){try{let o=new URL(e);return o.password&&(o.password="****"),o.toString()}catch{return e.replace(/:[^@/]+@/,":****@")}}async function ke(e){let o=U(),t=b();(!t||!t.token)&&(console.log(l.red("Not logged in")),console.log(l.gray("Run `vaif login` first to authenticate")),process.exit(1));let i=e.config||"vaif.config.json",r=null;try{r=await a(i);}catch{}let c=e.projectId||r?.projectId||process.env.VAIF_PROJECT_ID||t.projectId;c||(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 s=await fetch(`${Fe}/v1/projects/${c}`,{headers:{Authorization:`Bearer ${t.token}`}});if(!s.ok){let p=await s.text();throw new Error(`Failed to fetch project: ${p}`)}let n=await s.json();o.stop(),console.log(""),console.log(l.bold("VAIF Project Info")),console.log("");let a=16,d=(p,f)=>{console.log(` ${l.gray(p.padEnd(a))} ${f}`);};d("Name:",l.white(n.name||"N/A")),d("Project ID:",l.white(c)),d("Region:",l.white(n.region||"us-east-1")),d("Plan:",l.white(n.plan||n.tier||"free")),d("Created:",l.white(n.createdAt?new Date(n.createdAt).toLocaleDateString():"N/A")),console.log(""),d("API URL:",l.cyan(n.apiUrl||`${Fe}/v1`)),d("WS URL:",l.cyan(n.wsUrl||n.realtimeUrl||"N/A")),d("DB URL:",l.cyan(n.databaseUrl?oo(n.databaseUrl):"N/A")),d("Storage URL:",l.cyan(n.storageUrl||"N/A")),console.log("");}catch(s){o.fail("Failed to fetch project info"),s instanceof Error&&console.log(l.red(`
|
|
32
32
|
Error: ${s.message}`)),process.exit(1);}}var no=process.env.VAIF_API_URL||"https://api.vaif.studio";async function Ce(e){let o=U(),t=b();(!t||!t.token)&&(console.log(l.red("Not logged in")),console.log(l.gray("Run `vaif login` first to authenticate")),process.exit(1));let i=e.config||"vaif.config.json",r=null;try{r=await a(i);}catch{}let c=e.projectId||r?.projectId||process.env.VAIF_PROJECT_ID||t.projectId;c||(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 s=await fetch(`${no}/v1/projects/${c}?include=tables,functions,storage,connections`,{headers:{Authorization:`Bearer ${t.token}`}});if(!s.ok){let y=await s.text();throw new Error(`Failed to fetch project status: ${y}`)}let n=await s.json();o.stop(),console.log(""),console.log(l.bold("VAIF Project Status")),console.log("");let a=22,d=(y,D)=>{console.log(` ${l.gray(y.padEnd(a))} ${D}`);};d("Project:",l.white(n.name||c)),d("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",f=n.functionCount??n.functions?.length??"N/A",g=n.bucketCount??n.storage?.buckets?.length??"N/A",h=n.activeConnections??n.connections??"N/A";d("Tables:",l.white(String(p))),d("Functions:",l.white(String(f))),d("Storage Buckets:",l.white(String(g))),d("Active Connections:",l.white(String(h))),n.usage&&(console.log(""),console.log(l.gray(" --- Usage ---")),console.log(""),n.usage.dbSize&&d("Database Size:",l.white(n.usage.dbSize)),n.usage.storageSize&&d("Storage Size:",l.white(n.usage.storageSize)),n.usage.bandwidth&&d("Bandwidth:",l.white(n.usage.bandwidth)),n.usage.functionInvocations!=null&&d("Function Invocations:",l.white(String(n.usage.functionInvocations)))),console.log("");}catch(s){o.fail("Failed to fetch project status"),s instanceof Error&&console.log(l.red(`
|
|
33
|
-
Error: ${s.message}`)),process.exit(1);}}var De="1.7.
|
|
33
|
+
Error: ${s.message}`)),process.exit(1);}}var De="1.7.6",Q=l.hex("#00f0ff"),Y=l.hex("#7b61ff"),H=l.hex("#ff3dff"),X=l.hex("#00ff9d"),j=l.hex("#555570"),O=l.hex("#00f0ff");function so(){console.log(""),console.log(Q(" \u2566 \u2566")+Y("\u2554\u2550\u2557\u2566")+H("\u2554\u2550\u2557 ")+X("\u2554\u2550\u2557\u2566 \u2566")),console.log(Q(" \u255A\u2557\u2554\u255D")+Y("\u2560\u2550\u2563\u2551")+H("\u2560\u2563 ")+X("\u2551 \u2551 \u2551")),console.log(Q(" \u255A\u255D ")+Y("\u2569 \u2569\u2569")+H("\u255A ")+X("\u255A\u2550\u255D\u2569\u2550\u255D\u2569")),console.log(""),console.log(j(" \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(O(" VAIF Studio CLI")+j(` v${De}`)),console.log(j(" Build full-stack apps at lightning speed")),console.log(j(" \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(j(" $ ")+O("vaif login")+j(" Authenticate")),console.log(j(" $ ")+O("vaif init -t react-spa")+j(" Scaffold project")),console.log(j(" $ ")+O("vaif db push")+j(" Push migrations")),console.log(j(" $ ")+O("vaif generate")+j(" Generate types")),console.log(j(" $ ")+O("vaif functions deploy")+j(" Deploy functions")),console.log(""),console.log(l.bold(" Categories")),console.log(j(" auth ")+l.white("login, logout, whoami")),console.log(j(" project ")+l.white("init, templates, info, status")),console.log(j(" schema ")+l.white("pull, push, generate")),console.log(j(" database ")+l.white("db push, db pull, db seed, db reset")),console.log(j(" deploy ")+l.white("functions deploy, functions list")),console.log(j(" security ")+l.white("keys, secrets")),console.log(""),console.log(j(" Run ")+O("vaif <command> --help")+j(" for details")),console.log(j(" Docs: ")+l.underline("https://docs.vaif.studio")),console.log("");}program.name("vaif").description("VAIF CLI - Type generation and development tools").version(De);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(c);program.command("logout").description("Log out and remove stored credentials").action(d);program.command("whoami").description("Show current authenticated user").action(e);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(h);program.command("templates").alias("tpl").description("List available project templates").action(g);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(ke);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(Ce);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(ie);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(ae);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(f);var Ee=program.command("functions").alias("fn").description("Manage serverless functions");Ee.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(de);Ee.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(pe);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(he);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(ye);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(me);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(we);var Re=program.command("keys").description("Manage API keys");Re.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($e);Re.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(be);var W=program.command("secrets").alias("sec").description("Manage function secrets");W.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(Se);W.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(Ae);W.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(Pe);W.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(xe);process.argv.slice(2).length||(so(),process.exit(0));program.parse(process.argv);
|
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var b=require('fs'),R=require('path'),G=require('dotenv'),W=require('pg'),X=require('ora'),d=require('chalk'),Q=require('prettier'),H=require('os'),B=require('readline');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var b__default=/*#__PURE__*/_interopDefault(b);var R__default=/*#__PURE__*/_interopDefault(R);var G__default=/*#__PURE__*/_interopDefault(G);var W__default=/*#__PURE__*/_interopDefault(W);var X__default=/*#__PURE__*/_interopDefault(X);var d__default=/*#__PURE__*/_interopDefault(d);var Q__default=/*#__PURE__*/_interopDefault(Q);var H__default=/*#__PURE__*/_interopDefault(H);var B__default=/*#__PURE__*/_interopDefault(B);G__default.default.config();async function S(n){let a=R__default.default.resolve(n);if(!b__default.default.existsSync(a))return null;try{let t=b__default.default.readFileSync(a,"utf-8"),e=JSON.parse(t);return e.database?.url&&(e.database.url=j(e.database.url)),e.api?.apiKey&&(e.api.apiKey=j(e.api.apiKey)),e}catch{throw new Error(`Failed to parse config file: ${n}`)}}function j(n){return n.replace(/\$\{([^}]+)\}/g,(a,t)=>process.env[t]||a)}var J=R__default.default.join(H__default.default.homedir(),".vaif"),M=R__default.default.join(J,"auth.json");process.env.VAIF_API_URL||"https://api.vaif.studio";function z(){if(!b__default.default.existsSync(M))return null;try{let n=b__default.default.readFileSync(M,"utf-8");return JSON.parse(n)}catch{return null}}var Z=process.env.VAIF_API_URL||"https://api.vaif.studio";async function ee(n,a){let t=await fetch(`${Z}/schema-engine/introspect/${a}`,{headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"}});if(!t.ok){let s=await t.text();throw new Error(`API introspection failed: ${s}`)}let e=await t.json();if(!e.ok||!e.schemaExists)throw new Error("Project schema does not exist yet. Push a migration first with `vaif db push`.");let i=new Map,o=[];for(let s of e.tables){let r=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,r);for(let l of s.foreignKeys)o.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:o}}async function te(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
|
|
5
5
|
AND table_type = 'BASE TABLE'
|
|
6
6
|
ORDER BY table_name
|
|
7
|
-
`,[a]),e=await
|
|
7
|
+
`,[a]),e=await n.query(`
|
|
8
8
|
SELECT
|
|
9
9
|
table_name,
|
|
10
10
|
column_name,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
FROM information_schema.columns
|
|
20
20
|
WHERE table_schema = $1
|
|
21
21
|
ORDER BY table_name, ordinal_position
|
|
22
|
-
`,[a]),
|
|
22
|
+
`,[a]),i=await n.query(`
|
|
23
23
|
SELECT
|
|
24
24
|
tc.constraint_name,
|
|
25
25
|
tc.table_name,
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
AND ccu.table_schema = tc.table_schema
|
|
36
36
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
37
37
|
AND tc.table_schema = $1
|
|
38
|
-
`,[a]),o=await
|
|
38
|
+
`,[a]),o=await n.query(`
|
|
39
39
|
SELECT
|
|
40
40
|
t.typname as enum_name,
|
|
41
41
|
e.enumlabel as enum_value
|
|
@@ -44,24 +44,24 @@
|
|
|
44
44
|
JOIN pg_namespace n ON n.oid = t.typnamespace
|
|
45
45
|
WHERE n.nspname = $1
|
|
46
46
|
ORDER BY t.typname, e.enumsortorder
|
|
47
|
-
`,[a]),
|
|
47
|
+
`,[a]),c=new Map;for(let r of t.rows)c.set(r.table_name,[]);for(let r of e.rows){let l=c.get(r.table_name);l&&l.push(r);}let s=new Map;for(let r of o.rows){let l=s.get(r.enum_name)||[];l.push(r.enum_value),s.set(r.enum_name,l);}return {tables:c,enums:s,foreignKeys:i.rows}}var F={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 ae(n,a){let{data_type:t,udt_name:e,is_nullable:i}=n;if(a.has(e)){let s=a.get(e).map(r=>`"${r}"`).join(" | ");return i==="YES"?`(${s}) | null`:s}if(t==="ARRAY"){let c=e.replace(/^_/,"");if(a.has(c)){let l=a.get(c).map(p=>`"${p}"`).join(" | ");return i==="YES"?`(${l})[] | null`:`(${l})[]`}let s=F[c]||"unknown";return i==="YES"?`${s}[] | null`:`${s}[]`}let o=F[t]||F[e]||"unknown";return i==="YES"&&(o=`${o} | null`),o}function P(n){return n.split(/[_\-\s]+/).map(a=>a.charAt(0).toUpperCase()+a.slice(1).toLowerCase()).join("")}function ne(n,a){let t=P(n),e=a.map(i=>` | "${i}"`).join(`
|
|
48
48
|
`);return `export type ${t} =
|
|
49
|
-
${e};`}function
|
|
50
|
-
${
|
|
49
|
+
${e};`}function ie(n,a,t){let e=P(n),i=[],o=[],c=[];for(let p of a){let m=ae(p,t),u=p.column_name,f=p.column_default!==null||p.is_identity==="YES",h=p.is_nullable==="YES";i.push(` ${u}: ${m};`),f||p.column_name==="id"?o.push(` ${u}?: ${m.replace(" | null","")} | null;`):h?o.push(` ${u}?: ${m};`):o.push(` ${u}: ${m.replace(" | null","")};`),c.push(` ${u}?: ${m.replace(" | null","")} | null;`);}let s=`export interface ${e} {
|
|
50
|
+
${i.join(`
|
|
51
51
|
`)}
|
|
52
|
-
}`,
|
|
52
|
+
}`,r=`export interface ${e}Insert {
|
|
53
53
|
${o.join(`
|
|
54
54
|
`)}
|
|
55
|
-
}`,
|
|
56
|
-
${
|
|
55
|
+
}`,l=`export interface ${e}Update {
|
|
56
|
+
${c.join(`
|
|
57
57
|
`)}
|
|
58
|
-
}`;return {base:
|
|
59
|
-
`)}async function
|
|
60
|
-
Either:`)),console.log(
|
|
61
|
-
Set projectId in vaif.config.json or use VAIF_PROJECT_ID env var.`)),process.exit(1)),a.text="Introspecting schema via API...",{tables:o,enums:
|
|
62
|
-
Push a migration first: vaif db push`));return}a.text=`Generating types for ${o.size} tables...`;let
|
|
63
|
-
Error: ${t.message}`)),t.message.includes("ECONNREFUSED")&&console.log(
|
|
64
|
-
Make sure your database is running and accessible.`))),process.exit(1);}}var
|
|
58
|
+
}`;return {base:s,insert:r,update:l}}function oe(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[o,c]of a)e.push(ne(o,c)),e.push("");}e.push("// ============ TABLES ============"),e.push("");let i=[];for(let[o,c]of n){let{base:s,insert:r,update:l}=ie(o,c,a);i.push(o),e.push(s),e.push(""),e.push(r),e.push(""),e.push(l),e.push("");}e.push("// ============ DATABASE SCHEMA ============"),e.push(""),e.push("export interface Database {");for(let o of i){let c=P(o);e.push(` ${o}: {`),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 re(n){let a=X__default.default("Loading configuration...").start();try{let t=await S(n.config),e=n.connection||t?.database?.url||process.env.DATABASE_URL,i=e&&!e.includes("${"),o,c,s;if(i){a.text="Connecting to database...";let u=new W__default.default.Client({connectionString:e});await u.connect(),a.text="Introspecting schema...",{tables:o,enums:c,foreignKeys:s}=await te(u,n.schema),await u.end();}else {let u=z();(!u||!u.token)&&(a.fail("No database connection and not logged in"),console.log(d__default.default.yellow(`
|
|
60
|
+
Either:`)),console.log(d__default.default.gray(" 1. Run `vaif login` to authenticate (no DATABASE_URL needed)")),console.log(d__default.default.gray(" 2. Set DATABASE_URL in your .env file")),console.log(d__default.default.gray(" 3. Pass --connection postgresql://user:pass@host:5432/db")),process.exit(1));let f=t?.projectId||process.env.VAIF_PROJECT_ID||u.projectId;f||(a.fail("No project ID specified"),console.log(d__default.default.yellow(`
|
|
61
|
+
Set projectId in vaif.config.json or use VAIF_PROJECT_ID env var.`)),process.exit(1)),a.text="Introspecting schema via API...",{tables:o,enums:c,foreignKeys:s}=await ee(u.token,f);}if(o.size===0){a.warn("No tables found"),console.log(d__default.default.yellow(`
|
|
62
|
+
Push a migration first: vaif db push`));return}a.text=`Generating types for ${o.size} tables...`;let r=oe(o,c,s),l=await Q__default.default.format(r,{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(l),console.log(d__default.default.gray("\u2500".repeat(60)));return}let p=R__default.default.resolve(n.output),m=R__default.default.dirname(p);b__default.default.existsSync(m)||b__default.default.mkdirSync(m,{recursive:!0}),b__default.default.writeFileSync(p,l,"utf-8"),a.succeed(`Generated types for ${o.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: ${o.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(`
|
|
63
|
+
Error: ${t.message}`)),t.message.includes("ECONNREFUSED")&&console.log(d__default.default.yellow(`
|
|
64
|
+
Make sure your database is running and accessible.`))),process.exit(1);}}var _=[{name:"database",label:"Database",description:"CRUD queries, type-safe operations"},{name:"auth",label:"Authentication",description:"login, signup, OAuth, sessions"},{name:"realtime",label:"Realtime",description:"live subscriptions, presence"},{name:"storage",label:"Storage",description:"file uploads, signed URLs"},{name:"functions",label:"Functions",description:"serverless function calls"}],se={"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:`{
|
|
65
65
|
"name": "my-vaif-app",
|
|
66
66
|
"private": true,
|
|
67
67
|
"version": "0.1.0",
|
|
@@ -158,6 +158,7 @@ body {
|
|
|
158
158
|
// Browser client \u2013 safe to use in Client Components
|
|
159
159
|
export const vaif = createVaifClient({
|
|
160
160
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
161
|
+
projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID,
|
|
161
162
|
apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
|
|
162
163
|
});
|
|
163
164
|
|
|
@@ -165,6 +166,7 @@ export const vaif = createVaifClient({
|
|
|
165
166
|
export function createVaifServer() {
|
|
166
167
|
return createVaifClient({
|
|
167
168
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
169
|
+
projectId: process.env.VAIF_PROJECT_ID,
|
|
168
170
|
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
169
171
|
});
|
|
170
172
|
}
|
|
@@ -172,6 +174,7 @@ export function createVaifServer() {
|
|
|
172
174
|
# Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
|
|
173
175
|
|
|
174
176
|
NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
177
|
+
NEXT_PUBLIC_VAIF_PROJECT_ID=your-project-id
|
|
175
178
|
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
176
179
|
VAIF_SECRET_KEY=your-secret-key
|
|
177
180
|
|
|
@@ -278,7 +281,21 @@ A full-stack Next.js application powered by [VAIF Studio](https://vaif.studio),
|
|
|
278
281
|
## Documentation
|
|
279
282
|
|
|
280
283
|
Full documentation is available at <https://docs.vaif.studio>.
|
|
281
|
-
`}],featureFiles:{auth:[{path:"
|
|
284
|
+
`}],featureFiles:{auth:[{path:"app/page.tsx",content:`import Link from "next/link";
|
|
285
|
+
|
|
286
|
+
export default function Home() {
|
|
287
|
+
return (
|
|
288
|
+
<main style={{ maxWidth: 600, margin: "80px auto", textAlign: "center" }}>
|
|
289
|
+
<h1>Welcome to VAIF</h1>
|
|
290
|
+
<p>Your Next.js app is ready. Start building!</p>
|
|
291
|
+
<p style={{ marginTop: 24 }}>
|
|
292
|
+
<Link href="/login" style={{ marginRight: 16 }}>Log in</Link>
|
|
293
|
+
<Link href="/signup">Sign up</Link>
|
|
294
|
+
</p>
|
|
295
|
+
</main>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
`},{path:"middleware.ts",content:`import { NextResponse, type NextRequest } from "next/server";
|
|
282
299
|
import { createVaifClient } from "@vaiftech/client";
|
|
283
300
|
import { authMiddleware } from "@vaiftech/auth/nextjs";
|
|
284
301
|
|
|
@@ -291,6 +308,7 @@ export async function middleware(request: NextRequest) {
|
|
|
291
308
|
|
|
292
309
|
const vaif = createVaifClient({
|
|
293
310
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
311
|
+
projectId: process.env.VAIF_PROJECT_ID,
|
|
294
312
|
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
295
313
|
});
|
|
296
314
|
|
|
@@ -653,12 +671,14 @@ function Home() {
|
|
|
653
671
|
|
|
654
672
|
export const vaif = createVaifClient({
|
|
655
673
|
baseUrl: import.meta.env.VITE_VAIF_API_URL || 'https://api.vaif.studio',
|
|
674
|
+
projectId: import.meta.env.VITE_VAIF_PROJECT_ID,
|
|
656
675
|
apiKey: import.meta.env.VITE_VAIF_API_KEY,
|
|
657
676
|
});
|
|
658
677
|
`},{path:"src/vite-env.d.ts",content:`/// <reference types="vite/client" />
|
|
659
678
|
|
|
660
679
|
interface ImportMetaEnv {
|
|
661
680
|
readonly VITE_VAIF_API_URL: string;
|
|
681
|
+
readonly VITE_VAIF_PROJECT_ID: string;
|
|
662
682
|
readonly VITE_VAIF_API_KEY: string;
|
|
663
683
|
}
|
|
664
684
|
|
|
@@ -669,6 +689,7 @@ interface ImportMeta {
|
|
|
669
689
|
# Get these values from https://vaif.studio/app/security/api-keys
|
|
670
690
|
|
|
671
691
|
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
692
|
+
VITE_VAIF_PROJECT_ID=your-project-id
|
|
672
693
|
VITE_VAIF_API_KEY=your-api-key
|
|
673
694
|
`},{path:".gitignore",content:`node_modules
|
|
674
695
|
dist
|
|
@@ -768,7 +789,33 @@ A single-page React application built with [Vite](https://vite.dev/) and powered
|
|
|
768
789
|
## Documentation
|
|
769
790
|
|
|
770
791
|
Full documentation is available at <https://docs.vaif.studio>.
|
|
771
|
-
`}],featureFiles:{auth:[{path:"src/
|
|
792
|
+
`}],featureFiles:{auth:[{path:"src/App.tsx",content:`import { Routes, Route, Link } from "react-router-dom";
|
|
793
|
+
import Login from "./pages/Login";
|
|
794
|
+
import Signup from "./pages/Signup";
|
|
795
|
+
|
|
796
|
+
export default function App() {
|
|
797
|
+
return (
|
|
798
|
+
<Routes>
|
|
799
|
+
<Route path="/" element={<Home />} />
|
|
800
|
+
<Route path="/login" element={<Login />} />
|
|
801
|
+
<Route path="/signup" element={<Signup />} />
|
|
802
|
+
</Routes>
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
function Home() {
|
|
807
|
+
return (
|
|
808
|
+
<div style={{ maxWidth: 600, margin: "80px auto", textAlign: "center" }}>
|
|
809
|
+
<h1>Welcome to VAIF</h1>
|
|
810
|
+
<p>Your app is ready. Start building!</p>
|
|
811
|
+
<p style={{ marginTop: 24 }}>
|
|
812
|
+
<Link to="/login" style={{ marginRight: 16 }}>Log in</Link>
|
|
813
|
+
<Link to="/signup">Sign up</Link>
|
|
814
|
+
</p>
|
|
815
|
+
</div>
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
`},{path:"src/pages/Login.tsx",content:`import { useState } from "react";
|
|
772
819
|
import { useNavigate } from "react-router-dom";
|
|
773
820
|
import { vaif } from "../lib/vaif";
|
|
774
821
|
|
|
@@ -873,21 +920,15 @@ export function AuthGuard({ children, fallback }: AuthGuardProps) {
|
|
|
873
920
|
const [authenticated, setAuthenticated] = useState(false);
|
|
874
921
|
|
|
875
922
|
useEffect(() => {
|
|
876
|
-
vaif.auth.
|
|
877
|
-
|
|
923
|
+
vaif.auth.getUser()
|
|
924
|
+
.then(() => {
|
|
878
925
|
setAuthenticated(true);
|
|
879
|
-
|
|
926
|
+
setLoading(false);
|
|
927
|
+
})
|
|
928
|
+
.catch(() => {
|
|
880
929
|
navigate("/login");
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
const { data: { subscription } } = vaif.auth.onAuthStateChange((_event, session) => {
|
|
886
|
-
setAuthenticated(!!session);
|
|
887
|
-
if (!session) navigate("/login");
|
|
888
|
-
});
|
|
889
|
-
|
|
890
|
-
return () => subscription.unsubscribe();
|
|
930
|
+
setLoading(false);
|
|
931
|
+
});
|
|
891
932
|
}, [navigate]);
|
|
892
933
|
|
|
893
934
|
if (loading) return fallback ?? <div>Loading...</div>;
|
|
@@ -1435,7 +1476,39 @@ A React Native / Expo mobile application powered by [VAIF Studio](https://vaif.s
|
|
|
1435
1476
|
## Documentation
|
|
1436
1477
|
|
|
1437
1478
|
Full documentation is available at <https://docs.vaif.studio>.
|
|
1438
|
-
`}],featureFiles:{auth:[{path:"app/
|
|
1479
|
+
`}],featureFiles:{auth:[{path:"app/index.tsx",content:`import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
|
|
1480
|
+
import { useRouter } from "expo-router";
|
|
1481
|
+
|
|
1482
|
+
export default function HomeScreen() {
|
|
1483
|
+
const router = useRouter();
|
|
1484
|
+
|
|
1485
|
+
return (
|
|
1486
|
+
<View style={styles.container}>
|
|
1487
|
+
<Text style={styles.title}>Welcome to VAIF</Text>
|
|
1488
|
+
<Text style={styles.subtitle}>Your mobile app is ready. Start building!</Text>
|
|
1489
|
+
<View style={styles.buttons}>
|
|
1490
|
+
<TouchableOpacity style={styles.button} onPress={() => router.push("/(auth)/login")}>
|
|
1491
|
+
<Text style={styles.buttonText}>Log In</Text>
|
|
1492
|
+
</TouchableOpacity>
|
|
1493
|
+
<TouchableOpacity style={[styles.button, styles.secondaryButton]} onPress={() => router.push("/(auth)/signup")}>
|
|
1494
|
+
<Text style={[styles.buttonText, styles.secondaryText]}>Sign Up</Text>
|
|
1495
|
+
</TouchableOpacity>
|
|
1496
|
+
</View>
|
|
1497
|
+
</View>
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
const styles = StyleSheet.create({
|
|
1502
|
+
container: { flex: 1, alignItems: "center", justifyContent: "center", padding: 24 },
|
|
1503
|
+
title: { fontSize: 28, fontWeight: "bold", marginBottom: 8 },
|
|
1504
|
+
subtitle: { fontSize: 16, color: "#666", textAlign: "center", marginBottom: 32 },
|
|
1505
|
+
buttons: { gap: 12, width: "100%" },
|
|
1506
|
+
button: { backgroundColor: "#0070f3", borderRadius: 8, padding: 14, alignItems: "center" },
|
|
1507
|
+
secondaryButton: { backgroundColor: "transparent", borderWidth: 1, borderColor: "#0070f3" },
|
|
1508
|
+
buttonText: { color: "#fff", fontSize: 16, fontWeight: "600" },
|
|
1509
|
+
secondaryText: { color: "#0070f3" },
|
|
1510
|
+
});
|
|
1511
|
+
`},{path:"app/(auth)/login.tsx",content:`import { useState } from "react";
|
|
1439
1512
|
import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert } from "react-native";
|
|
1440
1513
|
import { useRouter } from "expo-router";
|
|
1441
1514
|
import { vaif } from "../../lib/vaif";
|
|
@@ -2617,6 +2690,7 @@ func HelloHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
2617
2690
|
|
|
2618
2691
|
export const vaif = createVaifClient({
|
|
2619
2692
|
baseUrl: import.meta.env.VITE_VAIF_API_URL || 'https://api.vaif.studio',
|
|
2693
|
+
projectId: import.meta.env.VITE_VAIF_PROJECT_ID,
|
|
2620
2694
|
apiKey: import.meta.env.VITE_VAIF_API_KEY,
|
|
2621
2695
|
});
|
|
2622
2696
|
|
|
@@ -2671,6 +2745,7 @@ export async function deleteTodo(id: string): Promise<void> {
|
|
|
2671
2745
|
# Get these values from https://vaif.studio/app/security/api-keys
|
|
2672
2746
|
|
|
2673
2747
|
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
2748
|
+
VITE_VAIF_PROJECT_ID=your-project-id
|
|
2674
2749
|
VITE_VAIF_API_KEY=your-api-key
|
|
2675
2750
|
`},{path:"README.md",content:`# Todo App \u2014 VAIF Starter
|
|
2676
2751
|
|
|
@@ -2808,6 +2883,7 @@ export const posts = pgTable("posts", {
|
|
|
2808
2883
|
|
|
2809
2884
|
export const vaif = createVaifClient({
|
|
2810
2885
|
baseUrl: import.meta.env.VITE_VAIF_API_URL || 'https://api.vaif.studio',
|
|
2886
|
+
projectId: import.meta.env.VITE_VAIF_PROJECT_ID,
|
|
2811
2887
|
apiKey: import.meta.env.VITE_VAIF_API_KEY,
|
|
2812
2888
|
});
|
|
2813
2889
|
|
|
@@ -2949,6 +3025,7 @@ export function useRealtimeMessages({
|
|
|
2949
3025
|
# Get these values from https://vaif.studio/app/security/api-keys
|
|
2950
3026
|
|
|
2951
3027
|
VITE_VAIF_API_URL=https://api.vaif.studio
|
|
3028
|
+
VITE_VAIF_PROJECT_ID=your-project-id
|
|
2952
3029
|
VITE_VAIF_API_KEY=your-api-key
|
|
2953
3030
|
`},{path:"README.md",content:`# Realtime Chat \u2014 VAIF Starter
|
|
2954
3031
|
|
|
@@ -3101,6 +3178,7 @@ export const posts = pgTable("posts", {
|
|
|
3101
3178
|
// Browser client \u2013 use in Client Components
|
|
3102
3179
|
export const vaif = createVaifClient({
|
|
3103
3180
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3181
|
+
projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID,
|
|
3104
3182
|
apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
|
|
3105
3183
|
});
|
|
3106
3184
|
|
|
@@ -3108,6 +3186,7 @@ export const vaif = createVaifClient({
|
|
|
3108
3186
|
export function createVaifServer() {
|
|
3109
3187
|
return createVaifClient({
|
|
3110
3188
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3189
|
+
projectId: process.env.VAIF_PROJECT_ID,
|
|
3111
3190
|
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
3112
3191
|
});
|
|
3113
3192
|
}
|
|
@@ -3262,6 +3341,7 @@ export async function requireTeamRole(
|
|
|
3262
3341
|
# Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
|
|
3263
3342
|
|
|
3264
3343
|
NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
3344
|
+
NEXT_PUBLIC_VAIF_PROJECT_ID=your-project-id
|
|
3265
3345
|
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
3266
3346
|
VAIF_SECRET_KEY=your-secret-key
|
|
3267
3347
|
|
|
@@ -3414,6 +3494,7 @@ export const posts = pgTable("posts", {
|
|
|
3414
3494
|
// Browser client
|
|
3415
3495
|
export const vaif = createVaifClient({
|
|
3416
3496
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3497
|
+
projectId: process.env.NEXT_PUBLIC_VAIF_PROJECT_ID,
|
|
3417
3498
|
apiKey: process.env.NEXT_PUBLIC_VAIF_API_KEY!,
|
|
3418
3499
|
});
|
|
3419
3500
|
|
|
@@ -3421,6 +3502,7 @@ export const vaif = createVaifClient({
|
|
|
3421
3502
|
export function createVaifServer() {
|
|
3422
3503
|
return createVaifClient({
|
|
3423
3504
|
baseUrl: process.env.NEXT_PUBLIC_VAIF_API_URL || 'https://api.vaif.studio',
|
|
3505
|
+
projectId: process.env.VAIF_PROJECT_ID,
|
|
3424
3506
|
apiKey: process.env.VAIF_SECRET_KEY!,
|
|
3425
3507
|
});
|
|
3426
3508
|
}
|
|
@@ -3537,6 +3619,7 @@ function getContentType(fileName: string): string {
|
|
|
3537
3619
|
# Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
|
|
3538
3620
|
|
|
3539
3621
|
NEXT_PUBLIC_VAIF_API_URL=https://api.vaif.studio
|
|
3622
|
+
NEXT_PUBLIC_VAIF_PROJECT_ID=your-project-id
|
|
3540
3623
|
NEXT_PUBLIC_VAIF_API_KEY=your-api-key
|
|
3541
3624
|
VAIF_SECRET_KEY=your-secret-key
|
|
3542
3625
|
|
|
@@ -3682,19 +3765,19 @@ export const posts = pgTable("posts", {
|
|
|
3682
3765
|
|
|
3683
3766
|
return Response.json({ message: \`Hello, \${name}!\` });
|
|
3684
3767
|
}
|
|
3685
|
-
`}]},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
|
|
3686
|
-
? Which VAIF features do you want to include?`)),
|
|
3687
|
-
Unknown template: ${
|
|
3688
|
-
`)),process.exit(1));let e;a.features&&a.features.length>0?e=a.features.filter(
|
|
3689
|
-
No features specified.`)),console.log(
|
|
3690
|
-
`,"utf-8"),console.log(
|
|
3691
|
-
`,"utf-8");}catch{}(t.dependencies?.length||t.devDependencies?.length)&&(console.log(""),console.log(
|
|
3692
|
-
--add-features requires --template to know which template to use.`)),console.log(
|
|
3693
|
-
Use --force to overwrite existing configuration.`)),process.exit(1));try{if(
|
|
3768
|
+
`}]},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 le(n){if(!process.stdin.isTTY||!process.stdout.isTTY)return n;let a=new Set(n.map(e=>_.findIndex(i=>i.name===e)).filter(e=>e>=0)),t=0;return new Promise(e=>{let i=B__default.default.createInterface({input:process.stdin,output:process.stdout});B__default.default.emitKeypressEvents(process.stdin,i),process.stdin.setRawMode&&process.stdin.setRawMode(true);function o(){let s=_.length+2;process.stdout.write(`\x1B[${s}A`),c();}function c(){console.log(d__default.default.bold(`
|
|
3769
|
+
? Which VAIF features do you want to include?`)),_.forEach((s,r)=>{let l=a.has(r)?d__default.default.green("[x]"):"[ ]",p=r===t?d__default.default.cyan("> "):" ";console.log(`${p}${l} ${s.label} ${d__default.default.gray(`(${s.description})`)}`);}),console.log(d__default.default.gray(" (up/down to move, space to toggle, enter to confirm)"));}c(),process.stdin.on("keypress",(s,r)=>{if(r.name==="up"&&t>0)t--,o();else if(r.name==="down"&&t<_.length-1)t++,o();else if(r.name==="space")a.has(t)?a.delete(t):a.add(t),o();else if(r.name==="return"){process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close();let l=[...a].sort().map(p=>_[p].name);e(l.length>0?l:n);}else r.name==="c"&&r.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close(),process.exit(0));});})}async function C(n,a={}){let t=se[n];t||(console.log(d__default.default.red(`
|
|
3770
|
+
Unknown template: ${n}`)),console.log(d__default.default.yellow(`Run 'vaif templates' to see available templates.
|
|
3771
|
+
`)),process.exit(1));let e;a.features&&a.features.length>0?e=a.features.filter(u=>_.some(f=>f.name===u)):a.addOnly?(console.log(d__default.default.red(`
|
|
3772
|
+
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 le(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],o=new Set,c=[];if(t.featureFiles)for(let u of e){let f=t.featureFiles[u];if(f)for(let h of f)o.add(h.path),c.push(h);}let s=i.filter(u=>!o.has(u.path)).concat(c),r=0,l=0;for(let u of s){let f=R__default.default.resolve(u.path),h=R__default.default.dirname(f);if(b__default.default.existsSync(h)||b__default.default.mkdirSync(h,{recursive:true}),u.path==="package.json"&&b__default.default.existsSync(f)&&!a.force)try{let v=JSON.parse(b__default.default.readFileSync(f,"utf-8")),I=JSON.parse(u.content),T=U=>{if(!U)return {};let D={};for(let[q,x]of Object.entries(U))!x.startsWith("workspace:")&&!x.startsWith("link:")&&!x.startsWith("file:")&&(D[q]=x);return D};v.dependencies={...T(v.dependencies),...I.dependencies||{}},v.devDependencies={...T(v.devDependencies),...I.devDependencies||{}},I.scripts&&(v.scripts={...v.scripts||{},...I.scripts}),b__default.default.writeFileSync(f,JSON.stringify(v,null,2)+`
|
|
3773
|
+
`,"utf-8"),console.log(d__default.default.green(` merge ${u.path} (added dependencies)`)),r++;continue}catch{}if(b__default.default.existsSync(f)&&!a.force){console.log(d__default.default.yellow(` skip ${u.path} (already exists)`)),l++;continue}b__default.default.writeFileSync(f,u.content,"utf-8"),console.log(d__default.default.green(` create ${u.path}`)),r++;}console.log(""),r>0&&console.log(d__default.default.green(`Created ${r} file${r!==1?"s":""}.`)),l>0&&console.log(d__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:{}},m=R__default.default.resolve("package.json");if(b__default.default.existsSync(m)&&e.length>0)try{let u=JSON.parse(b__default.default.readFileSync(m,"utf-8")),f=!1;for(let h of e){let v=p[h];if(v)for(let[I,T]of Object.entries(v))u.dependencies?.[I]||(u.dependencies=u.dependencies||{},u.dependencies[I]=T,f=!0);}f&&b__default.default.writeFileSync(m,JSON.stringify(u,null,2)+`
|
|
3774
|
+
`,"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(u=>{console.log(d__default.default.gray(` ${u}`));}),console.log(""),console.log(d__default.default.gray(" Get your project credentials at https://vaif.studio/app/security/api-keys")),console.log("");}var ue={$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 pe(n){if(n.addFeatures){n.template||(console.log(d__default.default.red(`
|
|
3775
|
+
--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 C(n.template,{force:n.force,features:e,addOnly:true});return}let a=X__default.default("Initializing VAIF configuration...").start(),t=R__default.default.resolve("vaif.config.json");b__default.default.existsSync(t)&&!n.force&&(a.fail("vaif.config.json already exists"),console.log(d__default.default.yellow(`
|
|
3776
|
+
Use --force to overwrite existing configuration.`)),process.exit(1));try{if(b__default.default.writeFileSync(t,JSON.stringify(ue,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 C(n.template,{force:n.force,features:e});}else {let e=R__default.default.resolve(".env.example");if(b__default.default.existsSync(e)||(b__default.default.writeFileSync(e,`# VAIF Configuration
|
|
3694
3777
|
DATABASE_URL=postgresql://user:password@localhost:5432/database
|
|
3695
3778
|
VAIF_API_KEY=your-api-key
|
|
3696
|
-
`,"utf-8"),console.log(
|
|
3697
|
-
Error: ${e.message}`)),process.exit(1);}}async function
|
|
3779
|
+
`,"utf-8"),console.log(d__default.default.gray("Created .env.example"))),n.typescript){let i=R__default.default.resolve("src/types");b__default.default.existsSync(i)||(b__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(`
|
|
3780
|
+
Error: ${e.message}`)),process.exit(1);}}async function at(n){let{connectionString:a,schema:t="public"}=n,e=new W__default.default.Client({connectionString:a});await e.connect();try{let i=await e.query(`
|
|
3698
3781
|
SELECT table_name, table_type
|
|
3699
3782
|
FROM information_schema.tables
|
|
3700
3783
|
WHERE table_schema = $1
|
|
@@ -3715,7 +3798,7 @@ Error: ${e.message}`)),process.exit(1);}}async function Ze(i){let{connectionStri
|
|
|
3715
3798
|
FROM information_schema.columns
|
|
3716
3799
|
WHERE table_schema = $1
|
|
3717
3800
|
ORDER BY table_name, ordinal_position
|
|
3718
|
-
`,[t]),
|
|
3801
|
+
`,[t]),c=await e.query(`
|
|
3719
3802
|
SELECT
|
|
3720
3803
|
t.typname as enum_name,
|
|
3721
3804
|
e.enumlabel as enum_value
|
|
@@ -3724,16 +3807,16 @@ Error: ${e.message}`)),process.exit(1);}}async function Ze(i){let{connectionStri
|
|
|
3724
3807
|
JOIN pg_namespace n ON n.oid = t.typnamespace
|
|
3725
3808
|
WHERE n.nspname = $1
|
|
3726
3809
|
ORDER BY t.typname, e.enumsortorder
|
|
3727
|
-
`,[t]),
|
|
3728
|
-
`);t.push(`export type ${
|
|
3729
|
-
${
|
|
3730
|
-
${
|
|
3810
|
+
`,[t]),s=new Map;for(let p of i.rows)s.set(p.table_name,[]);for(let p of o.rows){let m=s.get(p.table_name);m&&m.push(p);}let r=new Map;for(let p of c.rows){let m=r.get(p.enum_name)||[];m.push(p.enum_value),r.set(p.enum_name,m);}let l=ge(s,r);return Q__default.default.format(l,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100})}finally{await e.end();}}var N={smallint:"number",integer:"number",bigint:"string",int2:"number",int4:"number",int8:"string",decimal:"string",numeric:"string",real:"number",float4:"number",float8:"number","double precision":"number",money:"string",boolean:"boolean",bool:"boolean",text:"string",varchar:"string",char:"string",character:"string","character varying":"string",name:"string",citext:"string",date:"string",time:"string",timetz:"string",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 fe(n,a){let{data_type:t,udt_name:e,is_nullable:i}=n;if(a.has(e)){let s=a.get(e).map(r=>`"${r}"`).join(" | ");return i==="YES"?`(${s}) | null`:s}if(t==="ARRAY"){let c=e.replace(/^_/,"");if(a.has(c)){let l=a.get(c).map(p=>`"${p}"`).join(" | ");return i==="YES"?`(${l})[] | null`:`(${l})[]`}let s=N[c]||"unknown";return i==="YES"?`${s}[] | null`:`${s}[]`}let o=N[t]||N[e]||"unknown";return i==="YES"&&(o=`${o} | null`),o}function V(n){return n.split(/[_\-\s]+/).map(a=>a.charAt(0).toUpperCase()+a.slice(1).toLowerCase()).join("")}function ge(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,o]of a){let c=V(i),s=o.map(r=>` | "${r}"`).join(`
|
|
3811
|
+
`);t.push(`export type ${c} =
|
|
3812
|
+
${s};`),t.push("");}}t.push("// ============ TABLES ============"),t.push("");let e=[];for(let[i,o]of n){e.push(i);let c=V(i),s=[],r=[],l=[];for(let p of o){let m=fe(p,a),u=p.column_name,f=p.column_default!==null||p.is_identity==="YES",h=p.is_nullable==="YES";s.push(` ${u}: ${m};`),f||p.column_name==="id"?r.push(` ${u}?: ${m.replace(" | null","")} | null;`):h?r.push(` ${u}?: ${m};`):r.push(` ${u}: ${m.replace(" | null","")};`),l.push(` ${u}?: ${m.replace(" | null","")} | null;`);}t.push(`export interface ${c} {
|
|
3813
|
+
${s.join(`
|
|
3731
3814
|
`)}
|
|
3732
|
-
}`),t.push(""),t.push(`export interface ${
|
|
3733
|
-
${
|
|
3815
|
+
}`),t.push(""),t.push(`export interface ${c}Insert {
|
|
3816
|
+
${r.join(`
|
|
3734
3817
|
`)}
|
|
3735
|
-
}`),t.push(""),t.push(`export interface ${
|
|
3736
|
-
${
|
|
3818
|
+
}`),t.push(""),t.push(`export interface ${c}Update {
|
|
3819
|
+
${l.join(`
|
|
3737
3820
|
`)}
|
|
3738
|
-
}`),t.push("");}t.push("// ============ DATABASE SCHEMA ============"),t.push(""),t.push("export interface Database {");for(let
|
|
3739
|
-
`)}exports.generateTypes=
|
|
3821
|
+
}`),t.push("");}t.push("// ============ DATABASE SCHEMA ============"),t.push(""),t.push("export interface Database {");for(let i of e){let o=V(i);t.push(` ${i}: {`),t.push(` Row: ${o};`),t.push(` Insert: ${o}Insert;`),t.push(` Update: ${o}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(`
|
|
3822
|
+
`)}exports.generateTypes=re;exports.generateTypesFromConnection=at;exports.initConfig=pe;exports.loadConfig=S;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export{f as generateTypes,h as initConfig,a as loadConfig}from'./chunk-
|
|
1
|
+
export{f as generateTypes,h as initConfig,a as loadConfig}from'./chunk-T7GOLIY4.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
|