@vaiftech/cli 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -44,22 +44,22 @@
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]),c=new Map;for(let l of t.rows)c.set(l.table_name,[]);for(let l of e.rows){let o=c.get(l.table_name);o&&o.push(l);}let u=new Map;for(let l of r.rows){let o=u.get(l.enum_name)||[];o.push(l.enum_value),u.set(l.enum_name,o);}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 o=a.get(c).map(s=>`"${s}"`).join(" | ");return i==="YES"?`(${o})[] | null`:`(${o})[]`}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(`
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 s of a){let d=$(s,t),p=s.column_name,g=s.column_default!==null||s.is_identity==="YES",b=s.is_nullable==="YES";i.push(` ${p}: ${d};`),g||s.column_name==="id"?r.push(` ${p}?: ${d.replace(" | null","")} | null;`):b?r.push(` ${p}?: ${d};`):r.push(` ${p}: ${d.replace(" | null","")};`),c.push(` ${p}?: ${d.replace(" | null","")} | null;`);}let u=`export interface ${e} {
49
+ ${e};`}function G(n,a,t){let e=x(n),i=[],r=[],c=[];for(let o of a){let d=$(o,t),p=o.column_name,g=o.column_default!==null||o.is_identity==="YES",y=o.is_nullable==="YES";i.push(` ${p}: ${d};`),g||o.column_name==="id"?r.push(` ${p}?: ${d.replace(" | null","")} | null;`):y?r.push(` ${p}?: ${d};`):r.push(` ${p}: ${d.replace(" | null","")};`),c.push(` ${p}?: ${d.replace(" | null","")} | null;`);}let u=`export interface ${e} {
50
50
  ${i.join(`
51
51
  `)}
52
52
  }`,l=`export interface ${e}Insert {
53
53
  ${r.join(`
54
54
  `)}
55
- }`,o=`export interface ${e}Update {
55
+ }`,s=`export interface ${e}Update {
56
56
  ${c.join(`
57
57
  `)}
58
- }`;return {base:u,insert:l,update:o}}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:o}=G(r,c,a);i.push(r),e.push(u),e.push(""),e.push(l),e.push(""),e.push(o),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(`
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
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||(a.fail("No database connection string provided"),console.log(m__default.default.yellow(`
60
- Provide a connection string via:`)),console.log(m__default.default.gray(" --connection <url>")),console.log(m__default.default.gray(" DATABASE_URL environment variable")),console.log(m__default.default.gray(" vaif.config.json database.url")),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),o=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(m__default.default.gray("\u2500".repeat(60))),console.log(o),console.log(m__default.default.gray("\u2500".repeat(60)));return}let s=w__default.default.resolve(n.output),d=w__default.default.dirname(s);h__default.default.existsSync(d)||h__default.default.mkdirSync(d,{recursive:!0}),h__default.default.writeFileSync(s,o,"utf-8"),a.succeed(`Generated types for ${r.size} tables \u2192 ${m__default.default.cyan(n.output)}`),console.log(""),console.log(m__default.default.green("Generated:")),console.log(m__default.default.gray(` Tables: ${r.size}`)),console.log(m__default.default.gray(` Enums: ${c.size}`)),console.log(""),console.log(m__default.default.gray("Import in your code:")),console.log(m__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(m__default.default.red(`
60
+ Provide a connection string via:`)),console.log(m__default.default.gray(" --connection <url>")),console.log(m__default.default.gray(" DATABASE_URL environment variable")),console.log(m__default.default.gray(" vaif.config.json database.url")),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(m__default.default.gray("\u2500".repeat(60))),console.log(s),console.log(m__default.default.gray("\u2500".repeat(60)));return}let o=w__default.default.resolve(n.output),d=w__default.default.dirname(o);h__default.default.existsSync(d)||h__default.default.mkdirSync(d,{recursive:!0}),h__default.default.writeFileSync(o,s,"utf-8"),a.succeed(`Generated types for ${r.size} tables \u2192 ${m__default.default.cyan(n.output)}`),console.log(""),console.log(m__default.default.green("Generated:")),console.log(m__default.default.gray(` Tables: ${r.size}`)),console.log(m__default.default.gray(` Enums: ${c.size}`)),console.log(""),console.log(m__default.default.gray("Import in your code:")),console.log(m__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(m__default.default.red(`
61
61
  Error: ${t.message}`)),t.message.includes("ECONNREFUSED")&&console.log(m__default.default.yellow(`
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:`{
62
+ Make sure your database is running and accessible.`))),process.exit(1);}}var b=[{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",
@@ -167,7 +167,7 @@ export function createVaifServer() {
167
167
  });
168
168
  }
169
169
  `},{path:".env.local.example",content:`# VAIF Configuration
170
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
170
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
171
171
 
172
172
  NEXT_PUBLIC_VAIF_PROJECT_ID=your-project-id
173
173
  NEXT_PUBLIC_VAIF_API_KEY=your-anon-key
@@ -204,7 +204,7 @@ A full-stack Next.js application powered by [VAIF Studio](https://vaif.studio),
204
204
  cp .env.local.example .env.local
205
205
  \\\`\\\`\\\`
206
206
 
207
- Get your Project ID, API Key, and Secret Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
207
+ Get your Project ID, API Key, and Secret Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
208
208
 
209
209
  3. **Install and log in to the VAIF CLI**
210
210
 
@@ -527,6 +527,11 @@ export const posts = pgTable("posts", {
527
527
  });
528
528
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
529
529
  const { name } = await req.json().catch(() => ({ name: "World" }));
530
+
531
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
532
+ // are available as environment variables at runtime:
533
+ // const apiKey = process.env.MY_API_KEY;
534
+
530
535
  return Response.json({ message: \`Hello, \${name}!\` });
531
536
  }
532
537
  `}]},dependencies:["@vaiftech/client","@vaiftech/auth","@vaiftech/react","next","react","react-dom"],devDependencies:["@types/node","@types/react","@types/react-dom","typescript"],postInstructions:["cd my-vaif-app","npm install","# Copy .env.local.example to .env.local and add your VAIF credentials","npm run dev"]},"react-spa":{name:"React SPA",description:"Single-page React app with Vite, VAIF client, and provider wrapper",tag:"React + Vite",defaultFeatures:["database","auth"],files:[{path:"package.json",content:`{
@@ -654,7 +659,7 @@ interface ImportMeta {
654
659
  readonly env: ImportMetaEnv;
655
660
  }
656
661
  `},{path:".env.example",content:`# VAIF Configuration
657
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
662
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
658
663
 
659
664
  VITE_VAIF_PROJECT_ID=your-project-id
660
665
  VITE_VAIF_API_KEY=your-anon-key
@@ -687,7 +692,7 @@ A single-page React application built with [Vite](https://vite.dev/) and powered
687
692
  cp .env.example .env
688
693
  \\\`\\\`\\\`
689
694
 
690
- Get your Project ID and API Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
695
+ Get your Project ID and API Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
691
696
 
692
697
  3. **Install and log in to the VAIF CLI**
693
698
 
@@ -1036,6 +1041,11 @@ export const posts = pgTable("posts", {
1036
1041
  });
1037
1042
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
1038
1043
  const { name } = await req.json().catch(() => ({ name: "World" }));
1044
+
1045
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
1046
+ // are available as environment variables at runtime:
1047
+ // const apiKey = process.env.MY_API_KEY;
1048
+
1039
1049
  return Response.json({ message: \`Hello, \${name}!\` });
1040
1050
  }
1041
1051
  `}]},dependencies:["@vaiftech/client","@vaiftech/react","react","react-dom","react-router-dom"],devDependencies:["@types/react","@types/react-dom","@vitejs/plugin-react","typescript","vite"],postInstructions:["cd my-vaif-app","npm install","# Copy .env.example to .env and add your VAIF credentials","npm run dev"]},"ios-swift-app":{name:"iOS Swift App",description:"Swift client manager for iOS/macOS apps using Swift Package Manager",tag:"Swift / iOS",defaultFeatures:["database","auth"],files:[{path:"VaifManager.swift",content:`import Foundation
@@ -1185,7 +1195,7 @@ An iOS/macOS application powered by [VAIF Studio](https://vaif.studio), using th
1185
1195
  <string>your-anon-key</string>
1186
1196
  \\\`\\\`\\\`
1187
1197
 
1188
- Get your credentials from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
1198
+ Get your credentials from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
1189
1199
 
1190
1200
  3. **Install and log in to the VAIF CLI** (for type generation)
1191
1201
 
@@ -1312,7 +1322,7 @@ export const vaif = createExpoClient({
1312
1322
  realtime: { enabled: true },
1313
1323
  });
1314
1324
  `},{path:".env.example",content:`# VAIF Configuration
1315
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
1325
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
1316
1326
 
1317
1327
  EXPO_PUBLIC_VAIF_PROJECT_ID=your-project-id
1318
1328
  EXPO_PUBLIC_VAIF_API_KEY=your-anon-key
@@ -1346,7 +1356,7 @@ A React Native / Expo mobile application powered by [VAIF Studio](https://vaif.s
1346
1356
  cp .env.example .env
1347
1357
  \\\`\\\`\\\`
1348
1358
 
1349
- Get your Project ID and API Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
1359
+ Get your Project ID and API Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
1350
1360
 
1351
1361
  3. **Install and log in to the VAIF CLI**
1352
1362
 
@@ -1625,6 +1635,11 @@ export const posts = pgTable("posts", {
1625
1635
  });
1626
1636
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
1627
1637
  const { name } = await req.json().catch(() => ({ name: "World" }));
1638
+
1639
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
1640
+ // are available as environment variables at runtime:
1641
+ // const apiKey = process.env.MY_API_KEY;
1642
+
1628
1643
  return Response.json({ message: \`Hello, \${name}!\` });
1629
1644
  }
1630
1645
  `}]},dependencies:["@vaiftech/sdk-expo","@react-native-async-storage/async-storage","expo","expo-router","react","react-native"],postInstructions:["cd my-vaif-app","npm install","# Copy .env.example to .env and add your VAIF credentials","npx expo start"]},"flutter-app":{name:"Flutter App",description:"Dart/Flutter client setup with environment configuration",tag:"Flutter / Dart",defaultFeatures:["database","auth"],files:[{path:"lib/main.dart",content:`import 'package:flutter/material.dart';
@@ -1736,7 +1751,7 @@ A Flutter application powered by [VAIF Studio](https://vaif.studio), with Dart c
1736
1751
  cp .env.example .env
1737
1752
  \\\`\\\`\\\`
1738
1753
 
1739
- Get your Project ID and API Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
1754
+ Get your Project ID and API Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
1740
1755
 
1741
1756
  3. **Install and log in to the VAIF CLI** (for schema and type generation)
1742
1757
 
@@ -1994,7 +2009,7 @@ fastapi>=0.110.0
1994
2009
  uvicorn[standard]>=0.27.0
1995
2010
  python-dotenv>=1.0.0
1996
2011
  `},{path:".env.example",content:`# VAIF Configuration
1997
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
2012
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
1998
2013
 
1999
2014
  VAIF_PROJECT_ID=your-project-id
2000
2015
  VAIF_API_KEY=your-anon-key
@@ -2036,7 +2051,7 @@ A FastAPI backend application powered by [VAIF Studio](https://vaif.studio), wit
2036
2051
  cp .env.example .env
2037
2052
  \\\`\\\`\\\`
2038
2053
 
2039
- Get your Project ID, API Key, and Secret Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
2054
+ Get your Project ID, API Key, and Secret Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
2040
2055
 
2041
2056
  4. **Install and log in to the VAIF CLI**
2042
2057
 
@@ -2236,6 +2251,7 @@ async def invoke_function(function_name: str, payload: dict = {}):
2236
2251
  `},{path:"functions/hello.py",content:`"""Example VAIF serverless function."""
2237
2252
 
2238
2253
  import json
2254
+ import os
2239
2255
 
2240
2256
 
2241
2257
  def handler(request):
@@ -2243,6 +2259,10 @@ def handler(request):
2243
2259
 
2244
2260
  Deploy with: vaif functions deploy
2245
2261
  """
2262
+ # Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
2263
+ # are available as environment variables at runtime:
2264
+ # api_key = os.environ.get("MY_API_KEY")
2265
+
2246
2266
  try:
2247
2267
  body = json.loads(request.body) if request.body else {}
2248
2268
  name = body.get("name", "World")
@@ -2354,7 +2374,7 @@ A Go backend API powered by [VAIF Studio](https://vaif.studio), with HTTP handle
2354
2374
  cp .env.example .env
2355
2375
  \\\`\\\`\\\`
2356
2376
 
2357
- Get your Project ID, API Key, and Secret Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
2377
+ Get your Project ID, API Key, and Secret Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
2358
2378
 
2359
2379
  3. **Install and log in to the VAIF CLI**
2360
2380
 
@@ -2557,6 +2577,11 @@ type HelloResponse struct {
2557
2577
  }
2558
2578
 
2559
2579
  // HelloHandler is an example VAIF serverless function.
2580
+ //
2581
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
2582
+ // are available as environment variables at runtime:
2583
+ //
2584
+ // apiKey := os.Getenv("MY_API_KEY") // import "os"
2560
2585
  func HelloHandler(w http.ResponseWriter, r *http.Request) {
2561
2586
  var req HelloRequest
2562
2587
  if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Name == "" {
@@ -2623,7 +2648,7 @@ export async function deleteTodo(id: string): Promise<void> {
2623
2648
  if (error) throw error;
2624
2649
  }
2625
2650
  `},{path:".env.example",content:`# VAIF Configuration
2626
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
2651
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
2627
2652
 
2628
2653
  VITE_VAIF_PROJECT_ID=your-project-id
2629
2654
  VITE_VAIF_API_KEY=your-anon-key
@@ -2651,7 +2676,7 @@ A simple React todo application for learning [VAIF Studio](https://vaif.studio)
2651
2676
  cp .env.example .env
2652
2677
  \\\`\\\`\\\`
2653
2678
 
2654
- Get your Project ID and API Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
2679
+ Get your Project ID and API Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
2655
2680
 
2656
2681
  3. **Install and log in to the VAIF CLI**
2657
2682
 
@@ -2752,6 +2777,11 @@ export const posts = pgTable("posts", {
2752
2777
  });
2753
2778
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
2754
2779
  const { name } = await req.json().catch(() => ({ name: "World" }));
2780
+
2781
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
2782
+ // are available as environment variables at runtime:
2783
+ // const apiKey = process.env.MY_API_KEY;
2784
+
2755
2785
  return Response.json({ message: \`Hello, \${name}!\` });
2756
2786
  }
2757
2787
  `}]},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 { createClient } from "@vaiftech/client";
@@ -2903,7 +2933,7 @@ export function useRealtimeMessages({
2903
2933
  return { messages, isLoading, error, refresh };
2904
2934
  }
2905
2935
  `},{path:".env.example",content:`# VAIF Configuration
2906
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
2936
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
2907
2937
 
2908
2938
  VITE_VAIF_PROJECT_ID=your-project-id
2909
2939
  VITE_VAIF_API_KEY=your-anon-key
@@ -2931,7 +2961,7 @@ A React chat application with live messaging powered by [VAIF Studio](https://va
2931
2961
  cp .env.example .env
2932
2962
  \\\`\\\`\\\`
2933
2963
 
2934
- Get your Project ID and API Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
2964
+ Get your Project ID and API Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
2935
2965
 
2936
2966
  3. **Install and log in to the VAIF CLI**
2937
2967
 
@@ -3046,6 +3076,11 @@ export const posts = pgTable("posts", {
3046
3076
  });
3047
3077
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
3048
3078
  const { name } = await req.json().catch(() => ({ name: "World" }));
3079
+
3080
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
3081
+ // are available as environment variables at runtime:
3082
+ // const apiKey = process.env.MY_API_KEY;
3083
+
3049
3084
  return Response.json({ message: \`Hello, \${name}!\` });
3050
3085
  }
3051
3086
  `}]},dependencies:["@vaiftech/client","@vaiftech/react"],postInstructions:["Copy .env.example to .env and fill in your project credentials","Create a 'messages' table with columns: id (uuid), content (text), user_id (text), username (text), channel_id (text), created_at (timestamptz)","Enable Realtime on the messages table in your VAIF dashboard","Use the useRealtimeMessages hook in your components","Run: npx vaif generate to generate TypeScript types"]},"saas-starter":{name:"SaaS Starter",description:"Full SaaS starter with VAIF auth, team/org support, and server-side helpers",tag:"Next.js SaaS",defaultFeatures:["database","auth","functions"],files:[{path:"lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
@@ -3212,7 +3247,7 @@ export async function requireTeamRole(
3212
3247
  return member as TeamMember;
3213
3248
  }
3214
3249
  `},{path:".env.example",content:`# VAIF Configuration
3215
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
3250
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
3216
3251
 
3217
3252
  NEXT_PUBLIC_VAIF_PROJECT_ID=your-project-id
3218
3253
  NEXT_PUBLIC_VAIF_API_KEY=your-anon-key
@@ -3241,7 +3276,7 @@ A full SaaS starter kit powered by [VAIF Studio](https://vaif.studio) with authe
3241
3276
  cp .env.example .env.local
3242
3277
  \\\`\\\`\\\`
3243
3278
 
3244
- Get your Project ID, API Key, and Secret Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
3279
+ Get your Project ID, API Key, and Secret Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
3245
3280
 
3246
3281
  3. **Install and log in to the VAIF CLI**
3247
3282
 
@@ -3352,6 +3387,11 @@ export const posts = pgTable("posts", {
3352
3387
  });
3353
3388
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
3354
3389
  const { name } = await req.json().catch(() => ({ name: "World" }));
3390
+
3391
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
3392
+ // are available as environment variables at runtime:
3393
+ // const apiKey = process.env.MY_API_KEY;
3394
+
3355
3395
  return Response.json({ message: \`Hello, \${name}!\` });
3356
3396
  }
3357
3397
  `}]},dependencies:["@vaiftech/client","@vaiftech/auth","@vaiftech/react"],postInstructions:["Copy .env.example to .env.local and fill in your project credentials","Create 'teams' and 'team_members' tables in your VAIF dashboard","Import auth helpers from '@/lib/auth' in your Server Components/Actions","Use requireUser() for authenticated routes and requireTeamRole() for role checks","Run: npx vaif generate to generate TypeScript types"]},"ecommerce-api":{name:"E-commerce API",description:"API-first e-commerce setup with VAIF storage for product images",tag:"Next.js E-commerce",defaultFeatures:["database","auth","storage"],files:[{path:"lib/vaif.ts",content:`import { createClient } from "@vaiftech/client";
@@ -3480,7 +3520,7 @@ function getContentType(fileName: string): string {
3480
3520
  return mimeTypes[ext ?? ""] ?? "application/octet-stream";
3481
3521
  }
3482
3522
  `},{path:".env.example",content:`# VAIF Configuration
3483
- # Get these values from https://vaif.studio/dashboard \u2192 Project Settings \u2192 API Keys
3523
+ # Get these values from https://vaif.studio/app/security/api-keys \u2192 Project Settings \u2192 API Keys
3484
3524
 
3485
3525
  NEXT_PUBLIC_VAIF_PROJECT_ID=your-project-id
3486
3526
  NEXT_PUBLIC_VAIF_API_KEY=your-anon-key
@@ -3509,7 +3549,7 @@ An API-first e-commerce setup powered by [VAIF Studio](https://vaif.studio) with
3509
3549
  cp .env.example .env.local
3510
3550
  \\\`\\\`\\\`
3511
3551
 
3512
- Get your Project ID, API Key, and Secret Key from <https://vaif.studio/dashboard> under **Project Settings > API Keys**.
3552
+ Get your Project ID, API Key, and Secret Key from <https://vaif.studio/app/security/api-keys> under **Project Settings > API Keys**.
3513
3553
 
3514
3554
  3. **Install and log in to the VAIF CLI**
3515
3555
 
@@ -3618,14 +3658,19 @@ export const posts = pgTable("posts", {
3618
3658
  });
3619
3659
  `}],functions:[{path:"functions/hello.ts",content:`export default async function handler(req: Request): Promise<Response> {
3620
3660
  const { name } = await req.json().catch(() => ({ name: "World" }));
3661
+
3662
+ // Secrets set via \\\`vaif secrets set\\\` or the Security > Secrets page
3663
+ // are available as environment variables at runtime:
3664
+ // const apiKey = process.env.MY_API_KEY;
3665
+
3621
3666
  return Response.json({ message: \`Hello, \${name}!\` });
3622
3667
  }
3623
- `}]},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=D__default.default.createInterface({input:process.stdin,output:process.stdout});D__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(m__default.default.bold(`
3624
- ? Which VAIF features do you want to include?`)),y.forEach((u,l)=>{let o=a.has(l)?m__default.default.green("[x]"):"[ ]",s=l===t?m__default.default.cyan("> "):" ";console.log(`${s}${o} ${u.label} ${m__default.default.gray(`(${u.description})`)}`);}),console.log(m__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 o=[...a].sort().map(s=>y[s].name);e(o.length>0?o:n);}else l.name==="c"&&l.ctrl&&(process.stdin.setRawMode&&process.stdin.setRawMode(false),i.close(),process.exit(0));});})}async function j(n,a={}){let t=J[n];t||(console.log(m__default.default.red(`
3668
+ `}]},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=>b.findIndex(i=>i.name===e)).filter(e=>e>=0)),t=0;return new Promise(e=>{let i=D__default.default.createInterface({input:process.stdin,output:process.stdout});D__default.default.emitKeypressEvents(process.stdin,i),process.stdin.setRawMode&&process.stdin.setRawMode(true);function r(){let u=b.length+2;process.stdout.write(`\x1B[${u}A`),c();}function c(){console.log(m__default.default.bold(`
3669
+ ? Which VAIF features do you want to include?`)),b.forEach((u,l)=>{let s=a.has(l)?m__default.default.green("[x]"):"[ ]",o=l===t?m__default.default.cyan("> "):" ";console.log(`${o}${s} ${u.label} ${m__default.default.gray(`(${u.description})`)}`);}),console.log(m__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<b.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=>b[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 j(n,a={}){let t=J[n];t||(console.log(m__default.default.red(`
3625
3670
  Unknown template: ${n}`)),console.log(m__default.default.yellow(`Run 'vaif templates' to see available templates.
3626
- `)),process.exit(1));let e;a.features&&a.features.length>0?e=a.features.filter(o=>y.some(s=>s.name===o)):t.featureFiles&&Object.keys(t.featureFiles).length>0?e=await X(t.defaultFeatures??["database","auth"]):e=t.defaultFeatures??[],console.log(""),console.log(m__default.default.bold(`Scaffolding ${m__default.default.cyan(t.name)} template...`)),e.length>0&&console.log(m__default.default.gray(` Features: ${e.join(", ")}`)),console.log("");let i=[...t.files];if(t.featureFiles)for(let o of e){let s=t.featureFiles[o];s&&i.push(...s);}let r=0,c=0;for(let o of i){let s=w__default.default.resolve(o.path),d=w__default.default.dirname(s);if(h__default.default.existsSync(d)||h__default.default.mkdirSync(d,{recursive:true}),o.path==="package.json"&&h__default.default.existsSync(s)&&!a.force)try{let p=JSON.parse(h__default.default.readFileSync(s,"utf-8")),g=JSON.parse(o.content),b=C=>{if(!C)return {};let N={};for(let[O,_]of Object.entries(C))!_.startsWith("workspace:")&&!_.startsWith("link:")&&!_.startsWith("file:")&&(N[O]=_);return N};p.dependencies={...b(p.dependencies),...g.dependencies||{}},p.devDependencies={...b(p.devDependencies),...g.devDependencies||{}},g.scripts&&(p.scripts={...p.scripts||{},...g.scripts}),h__default.default.writeFileSync(s,JSON.stringify(p,null,2)+`
3627
- `,"utf-8"),console.log(m__default.default.green(` merge ${o.path} (added dependencies)`)),r++;continue}catch{}if(h__default.default.existsSync(s)&&!a.force){console.log(m__default.default.yellow(` skip ${o.path} (already exists)`)),c++;continue}h__default.default.writeFileSync(s,o.content,"utf-8"),console.log(m__default.default.green(` create ${o.path}`)),r++;}console.log(""),r>0&&console.log(m__default.default.green(`Created ${r} file${r!==1?"s":""}.`)),c>0&&console.log(m__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(h__default.default.existsSync(l)&&e.length>0)try{let o=JSON.parse(h__default.default.readFileSync(l,"utf-8")),s=!1;for(let d of e){let p=u[d];if(p)for(let[g,b]of Object.entries(p))o.dependencies?.[g]||(o.dependencies=o.dependencies||{},o.dependencies[g]=b,s=!0);}s&&h__default.default.writeFileSync(l,JSON.stringify(o,null,2)+`
3628
- `,"utf-8");}catch{}(t.dependencies?.length||t.devDependencies?.length)&&(console.log(""),console.log(m__default.default.bold("Install dependencies:")),t.dependencies?.length&&console.log(m__default.default.cyan(` npm install ${t.dependencies.join(" ")}`)),t.devDependencies?.length&&console.log(m__default.default.cyan(` npm install -D ${t.devDependencies.join(" ")}`))),console.log(""),console.log(m__default.default.bold.green("Project scaffolded successfully!")),console.log(""),console.log(m__default.default.bold(" Next steps:")),t.postInstructions.forEach(o=>{console.log(m__default.default.gray(` ${o}`));}),console.log(""),console.log(m__default.default.gray(" Get your project credentials at https://vaif.studio")),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){let a=z__default.default("Initializing VAIF configuration...").start(),t=w__default.default.resolve("vaif.config.json");h__default.default.existsSync(t)&&!n.force&&(a.fail("vaif.config.json already exists"),console.log(m__default.default.yellow(`
3671
+ `)),process.exit(1));let e;a.features&&a.features.length>0?e=a.features.filter(s=>b.some(o=>o.name===s)):t.featureFiles&&Object.keys(t.featureFiles).length>0?e=await X(t.defaultFeatures??["database","auth"]):e=t.defaultFeatures??[],console.log(""),console.log(m__default.default.bold(`Scaffolding ${m__default.default.cyan(t.name)} template...`)),e.length>0&&console.log(m__default.default.gray(` Features: ${e.join(", ")}`)),console.log("");let i=[...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),d=w__default.default.dirname(o);if(h__default.default.existsSync(d)||h__default.default.mkdirSync(d,{recursive:true}),s.path==="package.json"&&h__default.default.existsSync(o)&&!a.force)try{let p=JSON.parse(h__default.default.readFileSync(o,"utf-8")),g=JSON.parse(s.content),y=C=>{if(!C)return {};let N={};for(let[k,_]of Object.entries(C))!_.startsWith("workspace:")&&!_.startsWith("link:")&&!_.startsWith("file:")&&(N[k]=_);return N};p.dependencies={...y(p.dependencies),...g.dependencies||{}},p.devDependencies={...y(p.devDependencies),...g.devDependencies||{}},g.scripts&&(p.scripts={...p.scripts||{},...g.scripts}),h__default.default.writeFileSync(o,JSON.stringify(p,null,2)+`
3672
+ `,"utf-8"),console.log(m__default.default.green(` merge ${s.path} (added dependencies)`)),r++;continue}catch{}if(h__default.default.existsSync(o)&&!a.force){console.log(m__default.default.yellow(` skip ${s.path} (already exists)`)),c++;continue}h__default.default.writeFileSync(o,s.content,"utf-8"),console.log(m__default.default.green(` create ${s.path}`)),r++;}console.log(""),r>0&&console.log(m__default.default.green(`Created ${r} file${r!==1?"s":""}.`)),c>0&&console.log(m__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(h__default.default.existsSync(l)&&e.length>0)try{let s=JSON.parse(h__default.default.readFileSync(l,"utf-8")),o=!1;for(let d of e){let p=u[d];if(p)for(let[g,y]of Object.entries(p))s.dependencies?.[g]||(s.dependencies=s.dependencies||{},s.dependencies[g]=y,o=!0);}o&&h__default.default.writeFileSync(l,JSON.stringify(s,null,2)+`
3673
+ `,"utf-8");}catch{}(t.dependencies?.length||t.devDependencies?.length)&&(console.log(""),console.log(m__default.default.bold("Install dependencies:")),t.dependencies?.length&&console.log(m__default.default.cyan(` npm install ${t.dependencies.join(" ")}`)),t.devDependencies?.length&&console.log(m__default.default.cyan(` npm install -D ${t.devDependencies.join(" ")}`))),console.log(""),console.log(m__default.default.bold.green("Project scaffolded successfully!")),console.log(""),console.log(m__default.default.bold(" Next steps:")),t.postInstructions.forEach(s=>{console.log(m__default.default.gray(` ${s}`));}),console.log(""),console.log(m__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){let a=z__default.default("Initializing VAIF configuration...").start(),t=w__default.default.resolve("vaif.config.json");h__default.default.existsSync(t)&&!n.force&&(a.fail("vaif.config.json already exists"),console.log(m__default.default.yellow(`
3629
3674
  Use --force to overwrite existing configuration.`)),process.exit(1));try{if(h__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 j(n.template,{force:n.force,features:e});}else {let e=w__default.default.resolve(".env.example");if(h__default.default.existsSync(e)||(h__default.default.writeFileSync(e,`# VAIF Configuration
3630
3675
  DATABASE_URL=postgresql://user:password@localhost:5432/database
3631
3676
  VAIF_API_KEY=your-api-key
@@ -3660,16 +3705,16 @@ Error: ${e.message}`)),process.exit(1);}}async function Le(n){let{connectionStri
3660
3705
  JOIN pg_namespace n ON n.oid = t.typnamespace
3661
3706
  WHERE n.nspname = $1
3662
3707
  ORDER BY t.typname, e.enumsortorder
3663
- `,[t]),u=new Map;for(let s of i.rows)u.set(s.table_name,[]);for(let s of r.rows){let d=u.get(s.table_name);d&&d.push(s);}let l=new Map;for(let s of c.rows){let d=l.get(s.enum_name)||[];d.push(s.enum_value),l.set(s.enum_name,d);}let o=ie(u,l);return q__default.default.format(o,{parser:"typescript",semi:!0,singleQuote:!1,trailingComma:"es5",printWidth:100})}finally{await e.end();}}var R={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 o=a.get(c).map(s=>`"${s}"`).join(" | ");return i==="YES"?`(${o})[] | null`:`(${o})[]`}let u=R[c]||"unknown";return i==="YES"?`${u}[] | null`:`${u}[]`}let r=R[t]||R[e]||"unknown";return i==="YES"&&(r=`${r} | null`),r}function P(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=P(i),u=r.map(l=>` | "${l}"`).join(`
3708
+ `,[t]),u=new Map;for(let o of i.rows)u.set(o.table_name,[]);for(let o of r.rows){let d=u.get(o.table_name);d&&d.push(o);}let l=new Map;for(let o of c.rows){let d=l.get(o.enum_name)||[];d.push(o.enum_value),l.set(o.enum_name,d);}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 R={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=R[c]||"unknown";return i==="YES"?`${u}[] | null`:`${u}[]`}let r=R[t]||R[e]||"unknown";return i==="YES"&&(r=`${r} | null`),r}function P(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=P(i),u=r.map(l=>` | "${l}"`).join(`
3664
3709
  `);t.push(`export type ${c} =
3665
- ${u};`),t.push("");}}t.push("// ============ TABLES ============"),t.push("");let e=[];for(let[i,r]of n){e.push(i);let c=P(i),u=[],l=[],o=[];for(let s of r){let d=ne(s,a),p=s.column_name,g=s.column_default!==null||s.is_identity==="YES",b=s.is_nullable==="YES";u.push(` ${p}: ${d};`),g||s.column_name==="id"?l.push(` ${p}?: ${d.replace(" | null","")} | null;`):b?l.push(` ${p}?: ${d};`):l.push(` ${p}: ${d.replace(" | null","")};`),o.push(` ${p}?: ${d.replace(" | null","")} | null;`);}t.push(`export interface ${c} {
3710
+ ${u};`),t.push("");}}t.push("// ============ TABLES ============"),t.push("");let e=[];for(let[i,r]of n){e.push(i);let c=P(i),u=[],l=[],s=[];for(let o of r){let d=ne(o,a),p=o.column_name,g=o.column_default!==null||o.is_identity==="YES",y=o.is_nullable==="YES";u.push(` ${p}: ${d};`),g||o.column_name==="id"?l.push(` ${p}?: ${d.replace(" | null","")} | null;`):y?l.push(` ${p}?: ${d};`):l.push(` ${p}: ${d.replace(" | null","")};`),s.push(` ${p}?: ${d.replace(" | null","")} | null;`);}t.push(`export interface ${c} {
3666
3711
  ${u.join(`
3667
3712
  `)}
3668
3713
  }`),t.push(""),t.push(`export interface ${c}Insert {
3669
3714
  ${l.join(`
3670
3715
  `)}
3671
3716
  }`),t.push(""),t.push(`export interface ${c}Update {
3672
- ${o.join(`
3717
+ ${s.join(`
3673
3718
  `)}
3674
3719
  }`),t.push("");}t.push("// ============ DATABASE SCHEMA ============"),t.push(""),t.push("export interface Database {");for(let i of e){let r=P(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(`
3675
3720
  `)}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-JRB5YVG7.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(`
1
+ export{b as generateTypes,d as initConfig,a as loadConfig}from'./chunk-UQZPP43V.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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaiftech/cli",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "VAIF CLI - Type generation and development tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",