nivii 0.3.0 → 0.3.2

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.
Files changed (83) hide show
  1. package/README.md +142 -215
  2. package/dist/cli.js +1 -1
  3. package/dist/dist/cli.d.ts +3 -0
  4. package/dist/dist/cli.d.ts.map +1 -0
  5. package/dist/dist/cli.js +144 -0
  6. package/dist/dist/cli.js.map +1 -0
  7. package/dist/dist/commands/config.d.ts +2 -0
  8. package/dist/dist/commands/config.d.ts.map +1 -0
  9. package/dist/dist/commands/config.js +32 -0
  10. package/dist/dist/commands/config.js.map +1 -0
  11. package/dist/dist/commands/fullstack.d.ts +12 -0
  12. package/dist/dist/commands/fullstack.d.ts.map +1 -0
  13. package/dist/dist/commands/fullstack.js +173 -0
  14. package/dist/dist/commands/fullstack.js.map +1 -0
  15. package/dist/dist/commands/share.d.ts +18 -0
  16. package/dist/dist/commands/share.d.ts.map +1 -0
  17. package/dist/dist/commands/share.js +125 -0
  18. package/dist/dist/commands/share.js.map +1 -0
  19. package/dist/dist/commands/whoami.d.ts +2 -0
  20. package/dist/dist/commands/whoami.d.ts.map +1 -0
  21. package/dist/dist/commands/whoami.js +17 -0
  22. package/dist/dist/commands/whoami.js.map +1 -0
  23. package/dist/dist/core/analytics.d.ts +11 -0
  24. package/dist/dist/core/analytics.d.ts.map +1 -0
  25. package/dist/dist/core/analytics.js +47 -0
  26. package/dist/dist/core/analytics.js.map +1 -0
  27. package/dist/dist/core/backend.d.ts +26 -0
  28. package/dist/dist/core/backend.d.ts.map +1 -0
  29. package/dist/dist/core/backend.js +185 -0
  30. package/dist/dist/core/backend.js.map +1 -0
  31. package/dist/dist/core/build.d.ts +11 -0
  32. package/dist/dist/core/build.d.ts.map +1 -0
  33. package/dist/dist/core/build.js +34 -0
  34. package/dist/dist/core/build.js.map +1 -0
  35. package/dist/dist/core/detect.d.ts +12 -0
  36. package/dist/dist/core/detect.d.ts.map +1 -0
  37. package/dist/dist/core/detect.js +122 -0
  38. package/dist/dist/core/detect.js.map +1 -0
  39. package/dist/dist/core/env.d.ts +27 -0
  40. package/dist/dist/core/env.d.ts.map +1 -0
  41. package/dist/dist/core/env.js +164 -0
  42. package/dist/dist/core/env.js.map +1 -0
  43. package/dist/dist/core/fullstack.d.ts +29 -0
  44. package/dist/dist/core/fullstack.d.ts.map +1 -0
  45. package/dist/dist/core/fullstack.js +126 -0
  46. package/dist/dist/core/fullstack.js.map +1 -0
  47. package/dist/dist/core/qr.d.ts +4 -0
  48. package/dist/dist/core/qr.d.ts.map +1 -0
  49. package/dist/dist/core/qr.js +29 -0
  50. package/dist/dist/core/qr.js.map +1 -0
  51. package/dist/dist/core/tunnel.d.ts +9 -0
  52. package/dist/dist/core/tunnel.d.ts.map +1 -0
  53. package/dist/dist/core/tunnel.js +55 -0
  54. package/dist/dist/core/tunnel.js.map +1 -0
  55. package/dist/dist/core/upload.d.ts +22 -0
  56. package/dist/dist/core/upload.d.ts.map +1 -0
  57. package/dist/dist/core/upload.js +73 -0
  58. package/dist/dist/core/upload.js.map +1 -0
  59. package/dist/dist/ui/spinner.d.ts +8 -0
  60. package/dist/dist/ui/spinner.d.ts.map +1 -0
  61. package/dist/dist/ui/spinner.js +35 -0
  62. package/dist/dist/ui/spinner.js.map +1 -0
  63. package/dist/dist/ui/theme.d.ts +14 -0
  64. package/dist/dist/ui/theme.d.ts.map +1 -0
  65. package/dist/dist/ui/theme.js +32 -0
  66. package/dist/dist/ui/theme.js.map +1 -0
  67. package/dist/dist/ui/welcome.d.ts +4 -0
  68. package/dist/dist/ui/welcome.d.ts.map +1 -0
  69. package/dist/dist/ui/welcome.js +95 -0
  70. package/dist/dist/ui/welcome.js.map +1 -0
  71. package/dist/dist/utils/config.d.ts +19 -0
  72. package/dist/dist/utils/config.d.ts.map +1 -0
  73. package/dist/dist/utils/config.js +31 -0
  74. package/dist/dist/utils/config.js.map +1 -0
  75. package/dist/dist/utils/hash.d.ts +3 -0
  76. package/dist/dist/utils/hash.d.ts.map +1 -0
  77. package/dist/dist/utils/hash.js +10 -0
  78. package/dist/dist/utils/hash.js.map +1 -0
  79. package/dist/dist/utils/zip.d.ts +2 -0
  80. package/dist/dist/utils/zip.d.ts.map +1 -0
  81. package/dist/dist/utils/zip.js +19 -0
  82. package/dist/dist/utils/zip.js.map +1 -0
  83. package/package.json +8 -3
@@ -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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"}
@@ -0,0 +1,4 @@
1
+ export declare function showQR(url: string): Promise<void>;
2
+ export declare function copyToClipboard(text: string): Promise<boolean>;
3
+ export declare function openBrowser(url: string): Promise<void>;
4
+ //# sourceMappingURL=qr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../../src/core/qr.ts"],"names":[],"mappings":"AAIA,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvD;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQpE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D"}
@@ -0,0 +1,29 @@
1
+ import qrcode from 'qrcode-terminal';
2
+ import { theme } from '../ui/theme.js';
3
+ export async function showQR(url) {
4
+ console.log('');
5
+ console.log(theme.muted(' ┌─────────────────────────────────┐'));
6
+ console.log(theme.muted(' │') + ' ' + theme.accent('Scan to open on mobile') + ' ' + theme.muted('│'));
7
+ console.log(theme.muted(' └─────────────────────────────────┘'));
8
+ console.log('');
9
+ qrcode.generate(url, { small: true });
10
+ console.log('');
11
+ }
12
+ export async function copyToClipboard(text) {
13
+ try {
14
+ const { default: clipboardy } = await import('clipboardy');
15
+ await clipboardy.write(text);
16
+ return true;
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ export async function openBrowser(url) {
23
+ try {
24
+ const { default: open } = await import('open');
25
+ await open(url);
26
+ }
27
+ catch { }
28
+ }
29
+ //# sourceMappingURL=qr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.js","sourceRoot":"","sources":["../../src/core/qr.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,iBAAiB,CAAC;AAErC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAW;IACtC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,GAAG,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACnH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC3D,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface LiveSyncOptions {
2
+ watchDir: string;
3
+ slug: string;
4
+ liveToken: string;
5
+ wsBase?: string;
6
+ onUpdate?: () => Promise<void>;
7
+ }
8
+ export declare function startLiveSync(opts: LiveSyncOptions): () => void;
9
+ //# sourceMappingURL=tunnel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/core/tunnel.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,IAAI,CAuD/D"}
@@ -0,0 +1,55 @@
1
+ import WebSocket from 'ws';
2
+ import chokidar from 'chokidar';
3
+ import path from 'path';
4
+ import chalk from 'chalk';
5
+ import { theme } from '../ui/theme.js';
6
+ export function startLiveSync(opts) {
7
+ const wsUrl = opts.wsBase || 'wss://live.nivii.app';
8
+ let ws = null;
9
+ let reconnectTimer = null;
10
+ function connect() {
11
+ ws = new WebSocket(`${wsUrl}/live/${opts.slug}?token=${opts.liveToken}`);
12
+ ws.on('open', () => {
13
+ console.log(theme.success(' ⚡') + ' ' + chalk.white('Live sync connected'));
14
+ });
15
+ ws.on('close', () => {
16
+ console.log(theme.muted(' ↻ Live sync reconnecting…'));
17
+ reconnectTimer = setTimeout(connect, 3000);
18
+ });
19
+ ws.on('error', () => {
20
+ // silent
21
+ });
22
+ }
23
+ connect();
24
+ // Watch for file changes
25
+ const watcher = chokidar.watch(opts.watchDir, {
26
+ ignored: /(^|[/\\])\..|(node_modules)/,
27
+ persistent: true,
28
+ ignoreInitial: true,
29
+ });
30
+ let debounceTimer = null;
31
+ const triggerUpdate = (filePath) => {
32
+ if (debounceTimer)
33
+ clearTimeout(debounceTimer);
34
+ debounceTimer = setTimeout(async () => {
35
+ console.log('');
36
+ console.log(theme.accent(' ⚡') + ' ' + chalk.white('Change detected: ') + chalk.hex('#6B7280')(path.relative(opts.watchDir, filePath)));
37
+ if (opts.onUpdate) {
38
+ await opts.onUpdate();
39
+ }
40
+ if (ws?.readyState === WebSocket.OPEN) {
41
+ ws.send(JSON.stringify({ type: 'reload', slug: opts.slug }));
42
+ }
43
+ }, 300);
44
+ };
45
+ watcher.on('change', triggerUpdate);
46
+ watcher.on('add', triggerUpdate);
47
+ watcher.on('unlink', triggerUpdate);
48
+ return () => {
49
+ watcher.close();
50
+ if (reconnectTimer)
51
+ clearTimeout(reconnectTimer);
52
+ ws?.close();
53
+ };
54
+ }
55
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../src/core/tunnel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface UploadOptions {
2
+ buildDir: string;
3
+ slug: string;
4
+ token?: string;
5
+ password?: string;
6
+ otp?: boolean;
7
+ expires?: string;
8
+ live?: boolean;
9
+ collab?: boolean;
10
+ maxViews?: number;
11
+ selfDestruct?: boolean;
12
+ }
13
+ export interface DeployResult {
14
+ url: string;
15
+ slug: string;
16
+ liveToken?: string;
17
+ collabToken?: string;
18
+ otpCode?: string;
19
+ expiresAt?: string;
20
+ }
21
+ export declare function uploadDeploy(opts: UploadOptions): Promise<DeployResult>;
22
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +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,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAiD7E"}
@@ -0,0 +1,73 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import fetch from 'node-fetch';
4
+ import FormData from 'form-data';
5
+ import { createSpinner } from '../ui/spinner.js';
6
+ import { API_BASE } from '../utils/config.js';
7
+ import chalk from 'chalk';
8
+ /** Recursively collect all files under a directory */
9
+ function collectFiles(dir, base = dir) {
10
+ const results = [];
11
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
12
+ const abs = path.join(dir, entry.name);
13
+ if (entry.isDirectory()) {
14
+ results.push(...collectFiles(abs, base));
15
+ }
16
+ else {
17
+ results.push({ abs, rel: path.relative(base, abs).replace(/\\/g, '/') });
18
+ }
19
+ }
20
+ return results;
21
+ }
22
+ export async function uploadDeploy(opts) {
23
+ const spinner = createSpinner('Uploading to edge network…');
24
+ spinner.start();
25
+ try {
26
+ const files = collectFiles(opts.buildDir);
27
+ if (files.length === 0) {
28
+ throw new Error('No files found in build directory');
29
+ }
30
+ const form = new FormData();
31
+ form.append('slug', opts.slug);
32
+ form.append('fileCount', String(files.length));
33
+ if (opts.password)
34
+ form.append('password', opts.password);
35
+ if (opts.otp)
36
+ form.append('otp', 'true');
37
+ if (opts.expires)
38
+ form.append('expires', opts.expires);
39
+ if (opts.live)
40
+ form.append('live', 'true');
41
+ if (opts.collab)
42
+ form.append('collab', 'true');
43
+ if (opts.maxViews)
44
+ form.append('maxViews', String(opts.maxViews));
45
+ if (opts.selfDestruct)
46
+ form.append('selfDestruct', 'true');
47
+ // Attach each file with its relative path as the field name
48
+ for (const { abs, rel } of files) {
49
+ form.append('file[]', fs.createReadStream(abs), { filename: rel });
50
+ form.append('path[]', rel);
51
+ }
52
+ const res = await fetch(`${API_BASE}/deploy`, {
53
+ method: 'POST',
54
+ headers: {
55
+ ...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
56
+ ...form.getHeaders(),
57
+ },
58
+ body: form,
59
+ });
60
+ if (!res.ok) {
61
+ const body = await res.text();
62
+ throw new Error(`Upload failed: ${res.status} ${body}`);
63
+ }
64
+ const result = await res.json();
65
+ spinner.succeed(chalk.hex('#10B981')('Deployed to edge ') + chalk.hex('#6B7280')(`(${opts.slug})`));
66
+ return result;
67
+ }
68
+ catch (err) {
69
+ spinner.fail(chalk.hex('#EF4444')('Upload failed'));
70
+ throw err;
71
+ }
72
+ }
73
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/core/upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Ora } from 'ora';
2
+ export declare function createSpinner(text: string): Ora;
3
+ export declare function step(emoji: string, text: string, detail?: string): void;
4
+ export declare function success(text: string): void;
5
+ export declare function warn(text: string): void;
6
+ export declare function error(text: string): void;
7
+ export declare function info(text: string): void;
8
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +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;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,QAEhC"}
@@ -0,0 +1,35 @@
1
+ import ora from 'ora';
2
+ import chalk from 'chalk';
3
+ const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
4
+ export function createSpinner(text) {
5
+ return ora({
6
+ text: chalk.hex('#A78BFA')(text),
7
+ spinner: {
8
+ interval: 80,
9
+ frames: FRAMES.map(f => chalk.hex('#7C3AED')(f)),
10
+ },
11
+ color: 'magenta',
12
+ });
13
+ }
14
+ export function step(emoji, text, detail) {
15
+ const msg = chalk.hex('#A78BFA')(emoji + ' ' + chalk.white(text));
16
+ if (detail) {
17
+ console.log(msg + ' ' + chalk.hex('#6B7280')(detail));
18
+ }
19
+ else {
20
+ console.log(msg);
21
+ }
22
+ }
23
+ export function success(text) {
24
+ console.log(chalk.hex('#10B981')(' ✓ ') + chalk.white(text));
25
+ }
26
+ export function warn(text) {
27
+ console.log(chalk.hex('#F59E0B')(' ⚠ ') + chalk.white(text));
28
+ }
29
+ export function error(text) {
30
+ console.log(chalk.hex('#EF4444')(' ✗ ') + chalk.white(text));
31
+ }
32
+ export function info(text) {
33
+ console.log(chalk.hex('#60A5FA')(' ℹ ') + chalk.white(text));
34
+ }
35
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,GAAY,MAAM,KAAK,CAAC;AAC/B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,GAAG,CAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,GAAG,CAAC;QACT,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;QAChC,OAAO,EAAE;YACP,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;SACjD;QACD,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,KAAa,EAAE,IAAY,EAAE,MAAe;IAC/D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACnE,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE,CAAC"}