nivii 0.3.1 → 0.3.3
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 +142 -215
- package/dist/cli.js +48 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/fullstack.d.ts +12 -0
- package/dist/commands/fullstack.d.ts.map +1 -0
- package/dist/commands/fullstack.js +173 -0
- package/dist/commands/fullstack.js.map +1 -0
- package/dist/commands/pro.d.ts +2 -0
- package/dist/commands/pro.d.ts.map +1 -0
- package/dist/commands/pro.js +174 -0
- package/dist/commands/pro.js.map +1 -0
- package/dist/commands/share.d.ts.map +1 -1
- package/dist/commands/share.js +5 -4
- package/dist/commands/share.js.map +1 -1
- package/dist/core/backend.d.ts +26 -0
- package/dist/core/backend.d.ts.map +1 -0
- package/dist/core/backend.js +185 -0
- package/dist/core/backend.js.map +1 -0
- package/dist/core/env.d.ts +27 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/env.js +164 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/fullstack.d.ts +29 -0
- package/dist/core/fullstack.d.ts.map +1 -0
- package/dist/core/fullstack.js +126 -0
- package/dist/core/fullstack.js.map +1 -0
- package/dist/core/upload.d.ts +2 -1
- package/dist/core/upload.d.ts.map +1 -1
- package/dist/core/upload.js +2 -0
- package/dist/core/upload.js.map +1 -1
- package/dist/ui/spinner.d.ts +1 -0
- package/dist/ui/spinner.d.ts.map +1 -1
- package/dist/ui/spinner.js +3 -0
- package/dist/ui/spinner.js.map +1 -1
- package/dist/ui/welcome.d.ts.map +1 -1
- package/dist/ui/welcome.js +6 -3
- package/dist/ui/welcome.js.map +1 -1
- package/dist/utils/config.d.ts +3 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js.map +1 -1
- package/package.json +9 -4
- package/src/cli.ts +0 -118
- package/src/commands/config.ts +0 -33
- package/src/commands/share.ts +0 -159
- package/src/commands/whoami.ts +0 -16
- package/src/core/analytics.ts +0 -64
- package/src/core/build.ts +0 -46
- package/src/core/detect.ts +0 -159
- package/src/core/qr.ts +0 -30
- package/src/core/tunnel.ts +0 -70
- package/src/core/upload.ts +0 -95
- package/src/ui/spinner.ts +0 -36
- package/src/ui/theme.ts +0 -35
- package/src/ui/welcome.ts +0 -104
- package/src/utils/config.ts +0 -47
- package/src/utils/hash.ts +0 -11
- package/src/utils/zip.ts +0 -22
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fetch from 'node-fetch';
|
|
4
|
+
import { createSpinner } from '../ui/spinner.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
const FLY_API = 'https://api.machines.dev/v1';
|
|
7
|
+
const FLY_DEPLOY_API = 'https://fly.io/api/v1';
|
|
8
|
+
/** Generate a minimal Dockerfile for the backend */
|
|
9
|
+
export function generateDockerfile(framework, port) {
|
|
10
|
+
const portStr = String(port);
|
|
11
|
+
if (framework === 'hono') {
|
|
12
|
+
return `FROM node:20-alpine
|
|
13
|
+
WORKDIR /app
|
|
14
|
+
COPY package*.json ./
|
|
15
|
+
RUN npm ci --production
|
|
16
|
+
COPY . .
|
|
17
|
+
EXPOSE ${portStr}
|
|
18
|
+
CMD ["node", "src/index.js"]
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
21
|
+
// Express / Fastify / generic Node
|
|
22
|
+
return `FROM node:20-alpine
|
|
23
|
+
WORKDIR /app
|
|
24
|
+
COPY package*.json ./
|
|
25
|
+
RUN npm ci --production
|
|
26
|
+
COPY . .
|
|
27
|
+
EXPOSE ${portStr}
|
|
28
|
+
CMD ["node", "index.js"]
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
/** Generate fly.toml for the app */
|
|
32
|
+
export function generateFlyToml(appName, port) {
|
|
33
|
+
return `app = "${appName}"
|
|
34
|
+
primary_region = "sin"
|
|
35
|
+
|
|
36
|
+
[build]
|
|
37
|
+
|
|
38
|
+
[http_service]
|
|
39
|
+
internal_port = ${port}
|
|
40
|
+
force_https = true
|
|
41
|
+
auto_stop_machines = true
|
|
42
|
+
auto_start_machines = true
|
|
43
|
+
min_machines_running = 0
|
|
44
|
+
|
|
45
|
+
[env]
|
|
46
|
+
PORT = "${port}"
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
/** Create a Fly.io app via API */
|
|
50
|
+
async function createFlyApp(name, token) {
|
|
51
|
+
const res = await fetch('https://api.fly.io/graphql', {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: {
|
|
54
|
+
'Authorization': `Bearer ${token}`,
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
query: `
|
|
59
|
+
mutation CreateApp($input: CreateAppInput!) {
|
|
60
|
+
createApp(input: $input) {
|
|
61
|
+
app { name }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
`,
|
|
65
|
+
variables: {
|
|
66
|
+
input: {
|
|
67
|
+
name,
|
|
68
|
+
organizationSlug: 'personal',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
const json = await res.json();
|
|
74
|
+
if (json.errors && json.errors.length > 0) {
|
|
75
|
+
// App might already exist — that's OK
|
|
76
|
+
if (!json.errors[0].message.includes('already exists')) {
|
|
77
|
+
throw new Error(`Fly app creation failed: ${json.errors[0].message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Deploy backend to Fly.io using flyctl via CLI subprocess */
|
|
82
|
+
export async function deployBackend(opts) {
|
|
83
|
+
const spinner = createSpinner('Deploying backend to Fly.io…');
|
|
84
|
+
spinner.start();
|
|
85
|
+
const appName = `nivii-${opts.slug}-api`;
|
|
86
|
+
const port = opts.port || 3000;
|
|
87
|
+
const tmpDir = path.join('/tmp', `nivii-backend-${opts.slug}`);
|
|
88
|
+
try {
|
|
89
|
+
// Copy project to temp dir
|
|
90
|
+
if (fs.existsSync(tmpDir))
|
|
91
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
92
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
93
|
+
copyDir(opts.projectDir, tmpDir, ['node_modules', '.git', '.next', 'dist', 'build']);
|
|
94
|
+
// Generate Dockerfile if missing
|
|
95
|
+
const dockerfilePath = path.join(tmpDir, 'Dockerfile');
|
|
96
|
+
if (!fs.existsSync(dockerfilePath)) {
|
|
97
|
+
fs.writeFileSync(dockerfilePath, generateDockerfile(opts.framework, port));
|
|
98
|
+
}
|
|
99
|
+
// Generate fly.toml
|
|
100
|
+
fs.writeFileSync(path.join(tmpDir, 'fly.toml'), generateFlyToml(appName, port));
|
|
101
|
+
// Write .env file for the deployment
|
|
102
|
+
if (opts.envVars.length > 0) {
|
|
103
|
+
const envContent = opts.envVars
|
|
104
|
+
.map(v => `${v.key}=${v.value}`)
|
|
105
|
+
.join('\n');
|
|
106
|
+
fs.writeFileSync(path.join(tmpDir, '.env'), envContent);
|
|
107
|
+
}
|
|
108
|
+
// Use flyctl to deploy (must be installed)
|
|
109
|
+
const { execSync } = await import('child_process');
|
|
110
|
+
// Check flyctl available
|
|
111
|
+
try {
|
|
112
|
+
execSync('flyctl version', { stdio: 'ignore' });
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new Error('flyctl not found. Install it: curl -L https://fly.io/install.sh | sh');
|
|
116
|
+
}
|
|
117
|
+
// Set env vars as args
|
|
118
|
+
const envArgs = opts.envVars
|
|
119
|
+
.map(v => `--env ${v.key}="${v.value}"`)
|
|
120
|
+
.join(' ');
|
|
121
|
+
// Deploy
|
|
122
|
+
execSync(`flyctl deploy --app ${appName} --remote-only --yes ${envArgs}`, {
|
|
123
|
+
cwd: tmpDir,
|
|
124
|
+
stdio: 'pipe',
|
|
125
|
+
env: { ...process.env, FLY_API_TOKEN: opts.flyToken },
|
|
126
|
+
});
|
|
127
|
+
const url = `https://${appName}.fly.dev`;
|
|
128
|
+
spinner.succeed(chalk.hex('#10B981')('Backend deployed ') + chalk.hex('#6B7280')(`(${appName})`));
|
|
129
|
+
return { url, appName, machineId: '' };
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
spinner.fail(chalk.hex('#EF4444')('Backend deploy failed'));
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
// Cleanup temp dir
|
|
137
|
+
try {
|
|
138
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
139
|
+
}
|
|
140
|
+
catch { }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Schedule auto-destruction of a Fly.io app after N hours */
|
|
144
|
+
export async function scheduleBackendDestroy(appName, flyToken, afterHours = 48) {
|
|
145
|
+
// We store this intent locally — a cron/timeout will handle it
|
|
146
|
+
// In production this would be a CF Worker scheduled task
|
|
147
|
+
const destroyAt = Date.now() + afterHours * 60 * 60 * 1000;
|
|
148
|
+
const record = { appName, flyToken: '[redacted]', destroyAt };
|
|
149
|
+
// Write to ~/.nivii/pending-destroys.json
|
|
150
|
+
const home = process.env.HOME || '/tmp';
|
|
151
|
+
const file = path.join(home, '.nivii', 'pending-destroys.json');
|
|
152
|
+
let existing = [];
|
|
153
|
+
try {
|
|
154
|
+
existing = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
155
|
+
}
|
|
156
|
+
catch { }
|
|
157
|
+
existing.push(record);
|
|
158
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
159
|
+
fs.writeFileSync(file, JSON.stringify(existing, null, 2));
|
|
160
|
+
}
|
|
161
|
+
/** Destroy a Fly.io app */
|
|
162
|
+
export async function destroyBackend(appName, flyToken) {
|
|
163
|
+
const { execSync } = await import('child_process');
|
|
164
|
+
execSync(`flyctl apps destroy ${appName} --yes`, {
|
|
165
|
+
stdio: 'pipe',
|
|
166
|
+
env: { ...process.env, FLY_API_TOKEN: flyToken },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function copyDir(src, dest, skip = []) {
|
|
170
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
171
|
+
for (const entry of entries) {
|
|
172
|
+
if (skip.includes(entry.name))
|
|
173
|
+
continue;
|
|
174
|
+
const srcPath = path.join(src, entry.name);
|
|
175
|
+
const destPath = path.join(dest, entry.name);
|
|
176
|
+
if (entry.isDirectory()) {
|
|
177
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
178
|
+
copyDir(srcPath, destPath, skip);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
fs.copyFileSync(srcPath, destPath);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/core/backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface EnvVar {
|
|
2
|
+
key: string;
|
|
3
|
+
value: string;
|
|
4
|
+
isFrontendSafe: boolean;
|
|
5
|
+
source: string;
|
|
6
|
+
}
|
|
7
|
+
export interface EnvScanResult {
|
|
8
|
+
vars: EnvVar[];
|
|
9
|
+
files: string[];
|
|
10
|
+
localhostRefs: LocalhostRef[];
|
|
11
|
+
}
|
|
12
|
+
export interface LocalhostRef {
|
|
13
|
+
file: string;
|
|
14
|
+
line: number;
|
|
15
|
+
original: string;
|
|
16
|
+
envKey: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function scanEnvFiles(cwd: string): EnvScanResult;
|
|
19
|
+
/** Scan source files for hardcoded localhost references */
|
|
20
|
+
export declare function scanLocalhostRefs(cwd: string): LocalhostRef[];
|
|
21
|
+
/** Filter which env vars to send to backend deployment */
|
|
22
|
+
export declare function filterBackendVars(vars: EnvVar[]): EnvVar[];
|
|
23
|
+
/** Replace localhost URLs in source code with env var references */
|
|
24
|
+
export declare function injectEnvIntoSource(cwd: string, frontendDir: string, backendUrl: string, frontendUrl: string): void;
|
|
25
|
+
/** Print a formatted summary of found env vars */
|
|
26
|
+
export declare function formatEnvSummary(result: EnvScanResult): string;
|
|
27
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AA+CD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAiCvD;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CAiC7D;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAQ1D;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,IAAI,CA2BN;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAS9D"}
|
package/dist/core/env.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const ENV_FILES = [
|
|
4
|
+
'.env',
|
|
5
|
+
'.env.local',
|
|
6
|
+
'.env.development',
|
|
7
|
+
'.env.development.local',
|
|
8
|
+
'.env.production',
|
|
9
|
+
'.env.production.local',
|
|
10
|
+
];
|
|
11
|
+
/** Prefixes that are safe to expose to the frontend */
|
|
12
|
+
const FRONTEND_SAFE_PREFIXES = [
|
|
13
|
+
'NEXT_PUBLIC_',
|
|
14
|
+
'VITE_',
|
|
15
|
+
'REACT_APP_',
|
|
16
|
+
'NUXT_PUBLIC_',
|
|
17
|
+
'PUBLIC_',
|
|
18
|
+
'EXPO_PUBLIC_',
|
|
19
|
+
];
|
|
20
|
+
/** Keys that should NEVER be sent anywhere */
|
|
21
|
+
const SENSITIVE_PATTERNS = [
|
|
22
|
+
/secret/i,
|
|
23
|
+
/password/i,
|
|
24
|
+
/passwd/i,
|
|
25
|
+
/private_key/i,
|
|
26
|
+
/api_key/i,
|
|
27
|
+
/access_key/i,
|
|
28
|
+
/token/i,
|
|
29
|
+
/auth/i,
|
|
30
|
+
/credential/i,
|
|
31
|
+
/cert/i,
|
|
32
|
+
/database_url/i,
|
|
33
|
+
/db_url/i,
|
|
34
|
+
/mongo/i,
|
|
35
|
+
/postgres/i,
|
|
36
|
+
/mysql/i,
|
|
37
|
+
/redis/i,
|
|
38
|
+
/stripe/i,
|
|
39
|
+
/twilio/i,
|
|
40
|
+
/sendgrid/i,
|
|
41
|
+
/aws_/i,
|
|
42
|
+
/gcp_/i,
|
|
43
|
+
/azure_/i,
|
|
44
|
+
];
|
|
45
|
+
export function scanEnvFiles(cwd) {
|
|
46
|
+
const vars = [];
|
|
47
|
+
const files = [];
|
|
48
|
+
for (const filename of ENV_FILES) {
|
|
49
|
+
const filePath = path.join(cwd, filename);
|
|
50
|
+
if (!fs.existsSync(filePath))
|
|
51
|
+
continue;
|
|
52
|
+
files.push(filename);
|
|
53
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
54
|
+
for (const line of content.split('\n')) {
|
|
55
|
+
const trimmed = line.trim();
|
|
56
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
57
|
+
continue;
|
|
58
|
+
const eqIdx = trimmed.indexOf('=');
|
|
59
|
+
if (eqIdx === -1)
|
|
60
|
+
continue;
|
|
61
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
62
|
+
const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, '');
|
|
63
|
+
if (!key)
|
|
64
|
+
continue;
|
|
65
|
+
const isFrontendSafe = FRONTEND_SAFE_PREFIXES.some(p => key.startsWith(p));
|
|
66
|
+
// Don't override if already added (prefer more specific .env files)
|
|
67
|
+
if (!vars.find(v => v.key === key)) {
|
|
68
|
+
vars.push({ key, value, isFrontendSafe, source: filename });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { vars, files, localhostRefs: [] };
|
|
73
|
+
}
|
|
74
|
+
/** Scan source files for hardcoded localhost references */
|
|
75
|
+
export function scanLocalhostRefs(cwd) {
|
|
76
|
+
const refs = [];
|
|
77
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.vue', '.svelte'];
|
|
78
|
+
const skipDirs = ['node_modules', '.next', 'dist', 'build', 'out', '.git'];
|
|
79
|
+
function scan(dir) {
|
|
80
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
81
|
+
for (const entry of entries) {
|
|
82
|
+
if (skipDirs.includes(entry.name))
|
|
83
|
+
continue;
|
|
84
|
+
const full = path.join(dir, entry.name);
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
scan(full);
|
|
87
|
+
}
|
|
88
|
+
else if (extensions.includes(path.extname(entry.name))) {
|
|
89
|
+
const content = fs.readFileSync(full, 'utf-8');
|
|
90
|
+
const lines = content.split('\n');
|
|
91
|
+
lines.forEach((line, idx) => {
|
|
92
|
+
const match = line.match(/['"`](https?:\/\/localhost:\d+[^'"`]*?)['"`]/);
|
|
93
|
+
if (match) {
|
|
94
|
+
const port = match[1].match(/:(\d+)/)?.[1] || '3000';
|
|
95
|
+
refs.push({
|
|
96
|
+
file: path.relative(cwd, full),
|
|
97
|
+
line: idx + 1,
|
|
98
|
+
original: match[1],
|
|
99
|
+
envKey: `NEXT_PUBLIC_API_URL`,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
scan(cwd);
|
|
108
|
+
}
|
|
109
|
+
catch { }
|
|
110
|
+
return refs;
|
|
111
|
+
}
|
|
112
|
+
/** Filter which env vars to send to backend deployment */
|
|
113
|
+
export function filterBackendVars(vars) {
|
|
114
|
+
return vars.filter(v => {
|
|
115
|
+
// Always include – these are meant to be public/config
|
|
116
|
+
if (v.isFrontendSafe)
|
|
117
|
+
return true;
|
|
118
|
+
// Exclude obviously sensitive values
|
|
119
|
+
const looksSecret = SENSITIVE_PATTERNS.some(p => p.test(v.key));
|
|
120
|
+
return !looksSecret;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/** Replace localhost URLs in source code with env var references */
|
|
124
|
+
export function injectEnvIntoSource(cwd, frontendDir, backendUrl, frontendUrl) {
|
|
125
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.vue', '.svelte', '.env', '.env.local'];
|
|
126
|
+
const skipDirs = ['node_modules', '.next', 'dist', 'build', 'out', '.git'];
|
|
127
|
+
// Write/update .env.local with injected URLs
|
|
128
|
+
const envLocalPath = path.join(frontendDir, '.env.local');
|
|
129
|
+
let envContent = '';
|
|
130
|
+
if (fs.existsSync(envLocalPath)) {
|
|
131
|
+
envContent = fs.readFileSync(envLocalPath, 'utf-8');
|
|
132
|
+
}
|
|
133
|
+
// Inject or replace NEXT_PUBLIC_API_URL / VITE_API_URL
|
|
134
|
+
const apiUrlLine = `NEXT_PUBLIC_API_URL=${backendUrl}`;
|
|
135
|
+
const viteApiUrlLine = `VITE_API_URL=${backendUrl}`;
|
|
136
|
+
if (!envContent.includes('NEXT_PUBLIC_API_URL')) {
|
|
137
|
+
envContent += `\n${apiUrlLine}`;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
envContent = envContent.replace(/NEXT_PUBLIC_API_URL=.*/g, apiUrlLine);
|
|
141
|
+
}
|
|
142
|
+
if (!envContent.includes('VITE_API_URL')) {
|
|
143
|
+
envContent += `\n${viteApiUrlLine}`;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
envContent = envContent.replace(/VITE_API_URL=.*/g, viteApiUrlLine);
|
|
147
|
+
}
|
|
148
|
+
fs.writeFileSync(envLocalPath, envContent.trim() + '\n');
|
|
149
|
+
}
|
|
150
|
+
/** Print a formatted summary of found env vars */
|
|
151
|
+
export function formatEnvSummary(result) {
|
|
152
|
+
if (result.files.length === 0)
|
|
153
|
+
return ' No .env files found';
|
|
154
|
+
const lines = [];
|
|
155
|
+
lines.push(` Found ${result.vars.length} vars in: ${result.files.join(', ')}`);
|
|
156
|
+
const pub = result.vars.filter(v => v.isFrontendSafe);
|
|
157
|
+
const priv = result.vars.filter(v => !v.isFrontendSafe);
|
|
158
|
+
if (pub.length)
|
|
159
|
+
lines.push(` ✓ ${pub.length} frontend-safe (NEXT_PUBLIC_* / VITE_*)`);
|
|
160
|
+
if (priv.length)
|
|
161
|
+
lines.push(` 🔒 ${priv.length} server-only (secrets, DB URLs, etc.)`);
|
|
162
|
+
return lines.join('\n');
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DetectResult } from './detect.js';
|
|
2
|
+
import { scanEnvFiles, scanLocalhostRefs } from './env.js';
|
|
3
|
+
export interface FullStackProject {
|
|
4
|
+
frontend: {
|
|
5
|
+
dir: string;
|
|
6
|
+
detect: DetectResult;
|
|
7
|
+
} | null;
|
|
8
|
+
backend: {
|
|
9
|
+
dir: string;
|
|
10
|
+
detect: DetectResult;
|
|
11
|
+
} | null;
|
|
12
|
+
envResult: ReturnType<typeof scanEnvFiles>;
|
|
13
|
+
localhostRefs: ReturnType<typeof scanLocalhostRefs>;
|
|
14
|
+
}
|
|
15
|
+
/** Detect frontend + backend in a monorepo or single project */
|
|
16
|
+
export declare function detectFullStack(cwd: string): FullStackProject;
|
|
17
|
+
/** Auto-wire frontend + backend env vars after both are deployed */
|
|
18
|
+
export declare function wireEnvVars(opts: {
|
|
19
|
+
frontendDir: string;
|
|
20
|
+
backendUrl: string;
|
|
21
|
+
frontendUrl: string;
|
|
22
|
+
existingVars: ReturnType<typeof scanEnvFiles>['vars'];
|
|
23
|
+
}): {
|
|
24
|
+
injected: string[];
|
|
25
|
+
warning: string[];
|
|
26
|
+
};
|
|
27
|
+
/** Print full-stack detection summary */
|
|
28
|
+
export declare function printFullStackSummary(project: FullStackProject): void;
|
|
29
|
+
//# sourceMappingURL=fullstack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fullstack.d.ts","sourceRoot":"","sources":["../../src/core/fullstack.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAA4D,MAAM,UAAU,CAAC;AAKrH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE;QACR,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,YAAY,CAAC;KACtB,GAAG,IAAI,CAAC;IACT,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,YAAY,CAAC;KACtB,GAAG,IAAI,CAAC;IACT,SAAS,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IAC3C,aAAa,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;CACrD;AAKD,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAsD7D;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;CACvD,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAqC5C;AAED,yCAAyC;AACzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAiCrE"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { detectFramework } from './detect.js';
|
|
4
|
+
import { scanEnvFiles, scanLocalhostRefs, formatEnvSummary } from './env.js';
|
|
5
|
+
import { theme } from '../ui/theme.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
const SERVER_FRAMEWORKS = ['express', 'fastify', 'hono'];
|
|
8
|
+
const CLIENT_FRAMEWORKS = ['nextjs', 'vite', 'react-cra', 'vue', 'svelte', 'sveltekit', 'astro', 'remix', 'nuxt', 'solid', 'static'];
|
|
9
|
+
/** Detect frontend + backend in a monorepo or single project */
|
|
10
|
+
export function detectFullStack(cwd) {
|
|
11
|
+
// Check if it's a monorepo (has packages/ or apps/ subdirs)
|
|
12
|
+
const subdirs = fs.readdirSync(cwd, { withFileTypes: true })
|
|
13
|
+
.filter(e => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules')
|
|
14
|
+
.map(e => e.name);
|
|
15
|
+
const monorepoFolders = ['frontend', 'client', 'web', 'app', 'apps/web', 'packages/web',
|
|
16
|
+
'backend', 'server', 'api', 'apps/api', 'packages/api'];
|
|
17
|
+
let frontendDir = null;
|
|
18
|
+
let backendDir = null;
|
|
19
|
+
let frontendDetect = null;
|
|
20
|
+
let backendDetect = null;
|
|
21
|
+
// Try monorepo detection first
|
|
22
|
+
for (const sub of subdirs) {
|
|
23
|
+
const subPath = path.join(cwd, sub);
|
|
24
|
+
if (!fs.existsSync(path.join(subPath, 'package.json')))
|
|
25
|
+
continue;
|
|
26
|
+
const detected = detectFramework(subPath);
|
|
27
|
+
if (!frontendDir && CLIENT_FRAMEWORKS.includes(detected.framework)) {
|
|
28
|
+
frontendDir = subPath;
|
|
29
|
+
frontendDetect = detected;
|
|
30
|
+
}
|
|
31
|
+
if (!backendDir && (SERVER_FRAMEWORKS.includes(detected.framework) || detected.isServer)) {
|
|
32
|
+
backendDir = subPath;
|
|
33
|
+
backendDetect = detected;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Fallback: root-level detection
|
|
37
|
+
if (!frontendDir && !backendDir) {
|
|
38
|
+
const rootDetect = detectFramework(cwd);
|
|
39
|
+
if (SERVER_FRAMEWORKS.includes(rootDetect.framework) || rootDetect.isServer) {
|
|
40
|
+
backendDir = cwd;
|
|
41
|
+
backendDetect = rootDetect;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
frontendDir = cwd;
|
|
45
|
+
frontendDetect = rootDetect;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Env scanning (from both dirs)
|
|
49
|
+
const scanDir = frontendDir || backendDir || cwd;
|
|
50
|
+
const envResult = scanEnvFiles(scanDir);
|
|
51
|
+
const localhostRefs = scanLocalhostRefs(scanDir);
|
|
52
|
+
return {
|
|
53
|
+
frontend: frontendDir && frontendDetect ? { dir: frontendDir, detect: frontendDetect } : null,
|
|
54
|
+
backend: backendDir && backendDetect ? { dir: backendDir, detect: backendDetect } : null,
|
|
55
|
+
envResult,
|
|
56
|
+
localhostRefs,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Auto-wire frontend + backend env vars after both are deployed */
|
|
60
|
+
export function wireEnvVars(opts) {
|
|
61
|
+
const injected = [];
|
|
62
|
+
const warning = [];
|
|
63
|
+
const envLocalPath = path.join(opts.frontendDir, '.env.local');
|
|
64
|
+
let envContent = '';
|
|
65
|
+
if (fs.existsSync(envLocalPath)) {
|
|
66
|
+
envContent = fs.readFileSync(envLocalPath, 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
const apiVars = [
|
|
69
|
+
{ key: 'NEXT_PUBLIC_API_URL', value: opts.backendUrl },
|
|
70
|
+
{ key: 'VITE_API_URL', value: opts.backendUrl },
|
|
71
|
+
{ key: 'REACT_APP_API_URL', value: opts.backendUrl },
|
|
72
|
+
{ key: 'PUBLIC_API_URL', value: opts.backendUrl },
|
|
73
|
+
];
|
|
74
|
+
for (const v of apiVars) {
|
|
75
|
+
if (envContent.includes(v.key)) {
|
|
76
|
+
// Replace existing
|
|
77
|
+
envContent = envContent.replace(new RegExp(`${v.key}=.*`, 'g'), `${v.key}=${v.value}`);
|
|
78
|
+
injected.push(`Updated ${v.key}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
envContent += `\n${v.key}=${v.value}`;
|
|
82
|
+
injected.push(`Added ${v.key}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Add CORS_ORIGIN for backend to allow frontend
|
|
86
|
+
// (this gets passed to backend deploy env vars)
|
|
87
|
+
if (opts.frontendUrl) {
|
|
88
|
+
envContent += `\nCORS_ORIGIN=${opts.frontendUrl}`;
|
|
89
|
+
injected.push('Added CORS_ORIGIN');
|
|
90
|
+
}
|
|
91
|
+
fs.writeFileSync(envLocalPath, envContent.trim() + '\n');
|
|
92
|
+
return { injected, warning };
|
|
93
|
+
}
|
|
94
|
+
/** Print full-stack detection summary */
|
|
95
|
+
export function printFullStackSummary(project) {
|
|
96
|
+
console.log('');
|
|
97
|
+
console.log(chalk.hex('#A78BFA')(' ⚡ Full-Stack Detection'));
|
|
98
|
+
console.log('');
|
|
99
|
+
if (project.frontend) {
|
|
100
|
+
const { detect, dir } = project.frontend;
|
|
101
|
+
console.log(` ${chalk.green('✓')} Frontend ${chalk.cyan(detect.framework)} ${theme.muted(`→ ${path.basename(dir)}`)}`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.log(` ${chalk.yellow('⚠')} Frontend ${theme.muted('not detected')}`);
|
|
105
|
+
}
|
|
106
|
+
if (project.backend) {
|
|
107
|
+
const { detect, dir } = project.backend;
|
|
108
|
+
console.log(` ${chalk.green('✓')} Backend ${chalk.cyan(detect.framework)} ${theme.muted(`→ ${path.basename(dir)}`)}`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(` ${chalk.yellow('⚠')} Backend ${theme.muted('not detected')}`);
|
|
112
|
+
}
|
|
113
|
+
if (project.envResult.files.length > 0) {
|
|
114
|
+
console.log('');
|
|
115
|
+
console.log(formatEnvSummary(project.envResult));
|
|
116
|
+
}
|
|
117
|
+
if (project.localhostRefs.length > 0) {
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log(` ${chalk.yellow('⚠')} Found ${project.localhostRefs.length} hardcoded localhost URL(s) — will auto-replace`);
|
|
120
|
+
project.localhostRefs.slice(0, 3).forEach(r => {
|
|
121
|
+
console.log(` ${theme.muted(r.file + ':' + r.line)} → ${chalk.dim(r.original)}`);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
console.log('');
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=fullstack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fullstack.js","sourceRoot":"","sources":["../../src/core/fullstack.ts"],"names":[],"mappings":"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"}
|
package/dist/core/upload.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export interface UploadOptions {
|
|
|
2
2
|
buildDir: string;
|
|
3
3
|
slug: string;
|
|
4
4
|
token?: string;
|
|
5
|
+
proEmail?: string;
|
|
5
6
|
password?: string;
|
|
6
7
|
otp?: boolean;
|
|
7
8
|
expires?: string;
|
|
@@ -14,7 +15,7 @@ export interface DeployResult {
|
|
|
14
15
|
url: string;
|
|
15
16
|
slug: string;
|
|
16
17
|
liveToken?: string;
|
|
17
|
-
|
|
18
|
+
collabId?: string;
|
|
18
19
|
otpCode?: string;
|
|
19
20
|
expiresAt?: string;
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/core/upload.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/core/upload.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAkD7E"}
|
package/dist/core/upload.js
CHANGED
|
@@ -44,6 +44,8 @@ export async function uploadDeploy(opts) {
|
|
|
44
44
|
form.append('maxViews', String(opts.maxViews));
|
|
45
45
|
if (opts.selfDestruct)
|
|
46
46
|
form.append('selfDestruct', 'true');
|
|
47
|
+
if (opts.proEmail)
|
|
48
|
+
form.append('proEmail', opts.proEmail);
|
|
47
49
|
// Attach each file with its relative path as the field name
|
|
48
50
|
for (const { abs, rel } of files) {
|
|
49
51
|
form.append('file[]', fs.createReadStream(abs), { filename: rel });
|
package/dist/core/upload.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/core/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/core/upload.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/spinner.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export declare function step(emoji: string, text: string, detail?: string): void
|
|
|
4
4
|
export declare function success(text: string): void;
|
|
5
5
|
export declare function warn(text: string): void;
|
|
6
6
|
export declare function error(text: string): void;
|
|
7
|
+
export declare function info(text: string): void;
|
|
7
8
|
//# sourceMappingURL=spinner.d.ts.map
|
package/dist/ui/spinner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAK/B,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAS/C;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,QAOhE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,QAEnC;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,QAEhC;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,QAEjC"}
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAK/B,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAS/C;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,QAOhE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,QAEnC;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,QAEhC;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,QAEjC;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,QAEhC"}
|
package/dist/ui/spinner.js
CHANGED
|
@@ -29,4 +29,7 @@ export function warn(text) {
|
|
|
29
29
|
export function error(text) {
|
|
30
30
|
console.log(chalk.hex('#EF4444')(' ✗ ') + chalk.white(text));
|
|
31
31
|
}
|
|
32
|
+
export function info(text) {
|
|
33
|
+
console.log(chalk.hex('#60A5FA')(' ℹ ') + chalk.white(text));
|
|
34
|
+
}
|
|
32
35
|
//# sourceMappingURL=spinner.js.map
|