create-alta-app 1.9.0 → 2.1.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/index.mjs +51 -101
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
|
-
import os from 'node:os';
|
|
6
5
|
import path from 'node:path';
|
|
7
6
|
import prompts from 'prompts';
|
|
8
7
|
import ora from 'ora';
|
|
@@ -149,17 +148,9 @@ export default function Root() {
|
|
|
149
148
|
|
|
150
149
|
fs.writeFileSync(
|
|
151
150
|
path.join(appDir, 'components', 'layout', 'header.tsx'),
|
|
152
|
-
`
|
|
153
|
-
import { Text } from '@alta/design-system/components/ui/text';
|
|
154
|
-
|
|
155
|
-
export function Header() {
|
|
151
|
+
`export function Header() {
|
|
156
152
|
return (
|
|
157
|
-
<header className="flex h-14 items-center
|
|
158
|
-
<Separator orientation="vertical" className="h-4" />
|
|
159
|
-
<div className="ml-auto flex items-center gap-3">
|
|
160
|
-
<Text variant="muted">Alta App</Text>
|
|
161
|
-
</div>
|
|
162
|
-
</header>
|
|
153
|
+
<header className="flex h-14 items-center justify-end border-b px-4" />
|
|
163
154
|
);
|
|
164
155
|
}
|
|
165
156
|
`
|
|
@@ -167,49 +158,10 @@ export function Header() {
|
|
|
167
158
|
|
|
168
159
|
fs.writeFileSync(
|
|
169
160
|
path.join(appDir, 'routes', 'app', 'dashboard.tsx'),
|
|
170
|
-
`
|
|
171
|
-
import { Text } from '@alta/design-system/components/ui/text';
|
|
172
|
-
import { Badge } from '@alta/design-system/components/ui/badge';
|
|
173
|
-
import { Separator } from '@alta/design-system/components/ui/separator';
|
|
174
|
-
|
|
175
|
-
export default function DashboardRoute() {
|
|
161
|
+
`export default function DashboardRoute() {
|
|
176
162
|
return (
|
|
177
163
|
<div className="space-y-6">
|
|
178
|
-
<
|
|
179
|
-
<Text variant="heading3">Dashboard</Text>
|
|
180
|
-
<Text variant="muted" className="mt-1">Welcome to your app</Text>
|
|
181
|
-
</div>
|
|
182
|
-
<Separator />
|
|
183
|
-
<div className="grid gap-4 md:grid-cols-3">
|
|
184
|
-
<Card>
|
|
185
|
-
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
|
186
|
-
<CardTitle className="text-sm font-medium text-muted-foreground">Status</CardTitle>
|
|
187
|
-
<Badge variant="default">Active</Badge>
|
|
188
|
-
</CardHeader>
|
|
189
|
-
<CardContent>
|
|
190
|
-
<Text variant="heading3">All systems go</Text>
|
|
191
|
-
<Text variant="small" className="mt-1 text-muted-foreground">Your app is running smoothly</Text>
|
|
192
|
-
</CardContent>
|
|
193
|
-
</Card>
|
|
194
|
-
<Card>
|
|
195
|
-
<CardHeader className="pb-2">
|
|
196
|
-
<CardTitle className="text-sm font-medium text-muted-foreground">Environment</CardTitle>
|
|
197
|
-
</CardHeader>
|
|
198
|
-
<CardContent>
|
|
199
|
-
<Text variant="heading3">Development</Text>
|
|
200
|
-
<Text variant="small" className="mt-1 text-muted-foreground">Local dev server</Text>
|
|
201
|
-
</CardContent>
|
|
202
|
-
</Card>
|
|
203
|
-
<Card>
|
|
204
|
-
<CardHeader className="pb-2">
|
|
205
|
-
<CardTitle className="text-sm font-medium text-muted-foreground">Framework</CardTitle>
|
|
206
|
-
</CardHeader>
|
|
207
|
-
<CardContent>
|
|
208
|
-
<Text variant="heading3">Alta</Text>
|
|
209
|
-
<Text variant="small" className="mt-1 text-muted-foreground">React + Supabase + Vercel</Text>
|
|
210
|
-
</CardContent>
|
|
211
|
-
</Card>
|
|
212
|
-
</div>
|
|
164
|
+
<h1 className="text-2xl font-bold">Dashboard</h1>
|
|
213
165
|
</div>
|
|
214
166
|
);
|
|
215
167
|
}
|
|
@@ -218,24 +170,10 @@ export default function DashboardRoute() {
|
|
|
218
170
|
|
|
219
171
|
fs.writeFileSync(
|
|
220
172
|
path.join(appDir, 'routes', 'app', 'settings.tsx'),
|
|
221
|
-
`
|
|
222
|
-
import { Text } from '@alta/design-system/components/ui/text';
|
|
223
|
-
|
|
224
|
-
export default function SettingsRoute() {
|
|
173
|
+
`export default function SettingsRoute() {
|
|
225
174
|
return (
|
|
226
175
|
<div className="space-y-6">
|
|
227
|
-
<
|
|
228
|
-
<Text variant="heading3">Settings</Text>
|
|
229
|
-
<Text variant="muted" className="mt-1">Manage your app preferences</Text>
|
|
230
|
-
</div>
|
|
231
|
-
<Card>
|
|
232
|
-
<CardHeader>
|
|
233
|
-
<CardTitle>App Settings</CardTitle>
|
|
234
|
-
</CardHeader>
|
|
235
|
-
<CardContent>
|
|
236
|
-
<Text variant="paragraph">Configure your app here.</Text>
|
|
237
|
-
</CardContent>
|
|
238
|
-
</Card>
|
|
176
|
+
<h1 className="text-2xl font-bold">Settings</h1>
|
|
239
177
|
</div>
|
|
240
178
|
);
|
|
241
179
|
}
|
|
@@ -431,46 +369,17 @@ async function main() {
|
|
|
431
369
|
credentials = null;
|
|
432
370
|
}
|
|
433
371
|
|
|
434
|
-
// ── Step 4:
|
|
435
|
-
const shellRc = path.join(os.homedir(), '.zshrc');
|
|
436
|
-
const tokensToSet = {
|
|
437
|
-
SUPABASE_ACCESS_TOKEN: 'sbp_66e351be37d4e570fe4347ea7c78bbebc8988219',
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
try {
|
|
441
|
-
let rcContent = fs.existsSync(shellRc) ? fs.readFileSync(shellRc, 'utf-8') : '';
|
|
442
|
-
|
|
443
|
-
for (const [key, value] of Object.entries(tokensToSet)) {
|
|
444
|
-
const regex = new RegExp(`^export ${key}=.*$`, 'm');
|
|
445
|
-
const line = `export ${key}=${value}`;
|
|
446
|
-
|
|
447
|
-
if (regex.test(rcContent)) {
|
|
448
|
-
rcContent = rcContent.replace(regex, line);
|
|
449
|
-
} else {
|
|
450
|
-
rcContent += `\n# Alta\n${line}\n`;
|
|
451
|
-
}
|
|
452
|
-
process.env[key] = value;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
const spinnerShell = ora({ text: 'Setting up shell credentials...', indent: 2 }).start();
|
|
456
|
-
fs.writeFileSync(shellRc, rcContent);
|
|
457
|
-
spinnerShell.succeed(pc.green('Shell credentials configured'));
|
|
458
|
-
} catch {
|
|
459
|
-
console.log(` ${pc.dim('Could not update ~/.zshrc — add SUPABASE_ACCESS_TOKEN manually')}`);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// ── Step 5: Wait for Supabase project to provision & get anon key ──
|
|
372
|
+
// ── Step 4: Wait for Supabase project to provision & get anon key ──
|
|
463
373
|
let anonKey = '';
|
|
464
374
|
if (credentials) {
|
|
465
375
|
const spinnerKeys = ora({ text: 'Waiting for Supabase project to provision...', indent: 2 }).start();
|
|
466
|
-
const token = process.env.SUPABASE_ACCESS_TOKEN;
|
|
467
376
|
const ref = credentials.supabaseProjectRef;
|
|
468
377
|
|
|
469
378
|
for (let i = 0; i < 24; i++) {
|
|
470
379
|
await new Promise((r) => setTimeout(r, 5000));
|
|
471
380
|
try {
|
|
472
381
|
const res = await fetch(`https://api.supabase.com/v1/projects/${ref}/api-keys`, {
|
|
473
|
-
headers: { Authorization: `Bearer ${
|
|
382
|
+
headers: { Authorization: `Bearer ${credentials.supabaseToken}` },
|
|
474
383
|
});
|
|
475
384
|
if (res.ok) {
|
|
476
385
|
const keys = await res.json();
|
|
@@ -539,6 +448,47 @@ async function main() {
|
|
|
539
448
|
}
|
|
540
449
|
|
|
541
450
|
|
|
451
|
+
// ── Step 6: Login & link Supabase + Vercel ──
|
|
452
|
+
if (credentials) {
|
|
453
|
+
const spinnerLink = ora({ text: 'Linking Supabase project...', indent: 2 }).start();
|
|
454
|
+
try {
|
|
455
|
+
run(`npx supabase login --token ${credentials.supabaseToken}`, targetDir);
|
|
456
|
+
run(`npx supabase link --project-ref ${credentials.supabaseProjectRef}`, targetDir);
|
|
457
|
+
spinnerLink.succeed(pc.green('Supabase project linked'));
|
|
458
|
+
} catch {
|
|
459
|
+
spinnerLink.warn(pc.yellow('Could not link Supabase project'));
|
|
460
|
+
console.log(` ${pc.dim(`Run manually: npx supabase login && npx supabase link --project-ref ${credentials.supabaseProjectRef}`)}`);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const spinnerVercel = ora({ text: 'Authenticating Vercel CLI...', indent: 2 }).start();
|
|
464
|
+
try {
|
|
465
|
+
// Persist Vercel auth globally so user doesn't need --token on every command
|
|
466
|
+
const vercelConfigDir = path.join(process.env.HOME, 'Library', 'Application Support', 'com.vercel.cli');
|
|
467
|
+
if (!fs.existsSync(vercelConfigDir)) fs.mkdirSync(vercelConfigDir, { recursive: true });
|
|
468
|
+
|
|
469
|
+
fs.writeFileSync(
|
|
470
|
+
path.join(vercelConfigDir, 'auth.json'),
|
|
471
|
+
JSON.stringify({ token: credentials.vercelToken }) + '\n'
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
// Set current team scope
|
|
475
|
+
const configPath = path.join(vercelConfigDir, 'config.json');
|
|
476
|
+
let vercelConfig = {};
|
|
477
|
+
if (fs.existsSync(configPath)) {
|
|
478
|
+
vercelConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
479
|
+
}
|
|
480
|
+
vercelConfig.currentTeam = credentials.vercelTeamId;
|
|
481
|
+
fs.writeFileSync(configPath, JSON.stringify(vercelConfig, null, 2) + '\n');
|
|
482
|
+
|
|
483
|
+
// Link the project to Vercel
|
|
484
|
+
run(`npx vercel link --project ${projectName} --yes`, targetDir);
|
|
485
|
+
spinnerVercel.succeed(pc.green('Vercel authenticated & project linked'));
|
|
486
|
+
} catch {
|
|
487
|
+
spinnerVercel.warn(pc.yellow('Could not link Vercel project'));
|
|
488
|
+
console.log(` ${pc.dim('Deploy manually: cd ' + projectName + ' && pnpm run deploy')}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
542
492
|
// ── Step 7: Write project-specific MCP config ──
|
|
543
493
|
if (credentials) {
|
|
544
494
|
const spinnerMcp = ora({ text: 'Configuring Claude MCP...', indent: 2 }).start();
|
|
@@ -551,7 +501,7 @@ async function main() {
|
|
|
551
501
|
supabase: {
|
|
552
502
|
url: `https://mcp.supabase.com/mcp`,
|
|
553
503
|
headers: {
|
|
554
|
-
'x-supabase-access-token':
|
|
504
|
+
'x-supabase-access-token': credentials.supabaseToken,
|
|
555
505
|
'x-project-ref': credentials.supabaseProjectRef,
|
|
556
506
|
},
|
|
557
507
|
},
|
|
@@ -605,7 +555,7 @@ async function main() {
|
|
|
605
555
|
spinnerDeploy.succeed(pc.green('Deployed to Vercel'));
|
|
606
556
|
} catch {
|
|
607
557
|
spinnerDeploy.warn(pc.yellow('Could not deploy to Vercel'));
|
|
608
|
-
console.log(` ${pc.dim('Deploy manually: cd ' + projectName + ' && pnpm deploy')}`);
|
|
558
|
+
console.log(` ${pc.dim('Deploy manually: cd ' + projectName + ' && pnpm run deploy')}`);
|
|
609
559
|
}
|
|
610
560
|
}
|
|
611
561
|
|