nstantpage-agent 0.5.11 → 0.5.13

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/cli.js CHANGED
@@ -25,7 +25,7 @@ const program = new Command();
25
25
  program
26
26
  .name('nstantpage')
27
27
  .description('Local development agent for nstantpage.com — run projects on your machine, preview in the cloud')
28
- .version('0.5.10');
28
+ .version('0.5.11');
29
29
  program
30
30
  .command('login')
31
31
  .description('Authenticate with nstantpage.com')
@@ -24,7 +24,8 @@ import { getConfig, getProjectConfig, setProjectConfig, clearProjectConfig, getD
24
24
  import { TunnelClient } from '../tunnel.js';
25
25
  import { LocalServer } from '../localServer.js';
26
26
  import { PackageInstaller } from '../packageInstaller.js';
27
- const VERSION = '0.5.10';
27
+ import { probeLocalPostgres, ensureLocalProjectDb, closeAdminPool, writeDatabaseUrlToEnv } from '../projectDb.js';
28
+ const VERSION = '0.5.13';
28
29
  /**
29
30
  * Resolve the backend API base URL.
30
31
  * - If --backend is passed, use it
@@ -274,12 +275,33 @@ export async function startCommand(directory, options) {
274
275
  if (!fs.existsSync(localConfigPath)) {
275
276
  fs.writeFileSync(localConfigPath, JSON.stringify({ projectId }, null, 2), 'utf-8');
276
277
  }
278
+ // 2.5. Auto-detect local PostgreSQL and provision project database
279
+ let databaseUrl = null;
280
+ try {
281
+ const hasPg = await probeLocalPostgres();
282
+ if (hasPg) {
283
+ databaseUrl = await ensureLocalProjectDb(projectId);
284
+ if (databaseUrl) {
285
+ console.log(chalk.green(` ✓ Database ready: project_${projectId}`));
286
+ writeDatabaseUrlToEnv(projectDir, databaseUrl);
287
+ }
288
+ }
289
+ }
290
+ catch (err) {
291
+ console.log(chalk.yellow(` ⚠ PostgreSQL setup failed: ${err.message} (will use PGlite fallback)`));
292
+ }
293
+ // Build env vars to pass to the dev server
294
+ const serverEnv = {};
295
+ if (databaseUrl) {
296
+ serverEnv['DATABASE_URL'] = databaseUrl;
297
+ }
277
298
  // 3. Start local server (API + dev server)
278
299
  const localServer = new LocalServer({
279
300
  projectDir,
280
301
  projectId,
281
302
  apiPort,
282
303
  devPort,
304
+ env: serverEnv,
283
305
  });
284
306
  // 4. Create tunnel client
285
307
  const tunnel = new TunnelClient({
@@ -373,6 +395,7 @@ export async function startCommand(directory, options) {
373
395
  tunnel.disconnect();
374
396
  await localServer.stop();
375
397
  await disconnectDevice();
398
+ await closeAdminPool();
376
399
  clearProjectConfig(projectId);
377
400
  process.exit(0);
378
401
  };
@@ -540,6 +563,7 @@ async function startStandbyMode(token, options, backendUrl, deviceId) {
540
563
  proj.tunnel.disconnect();
541
564
  await proj.localServer.stop();
542
565
  }
566
+ await closeAdminPool();
543
567
  try {
544
568
  await fetch(`${backendUrl}/api/agent/disconnect`, {
545
569
  method: 'POST',
@@ -584,9 +608,26 @@ async function startAdditionalProject(projectId, opts) {
584
608
  await new Promise(r => setTimeout(r, 50));
585
609
  // ── Phase 1: API server + file fetch + tunnel connect (all parallel) ──
586
610
  progress('fetching-files', 'Fetching project files...');
611
+ // Provision database if PostgreSQL is available
612
+ let databaseUrl = null;
613
+ try {
614
+ const hasPg = await probeLocalPostgres();
615
+ if (hasPg) {
616
+ databaseUrl = await ensureLocalProjectDb(projectId);
617
+ if (databaseUrl) {
618
+ console.log(chalk.green(` ✓ Database ready: project_${projectId}`));
619
+ writeDatabaseUrlToEnv(projectDir, databaseUrl);
620
+ }
621
+ }
622
+ }
623
+ catch { }
624
+ const serverEnv = {};
625
+ if (databaseUrl)
626
+ serverEnv['DATABASE_URL'] = databaseUrl;
587
627
  const localServer = new LocalServer({
588
628
  projectDir, projectId,
589
629
  apiPort: allocated.apiPort, devPort: allocated.devPort,
630
+ env: serverEnv,
590
631
  });
591
632
  const tunnel = new TunnelClient({
592
633
  gatewayUrl: opts.gatewayUrl,
package/dist/devServer.js CHANGED
@@ -65,6 +65,7 @@ export class DevServer {
65
65
  ...process.env,
66
66
  ...extraEnv,
67
67
  PORT: String(backendPort),
68
+ SERVER_PORT: String(backendPort),
68
69
  NODE_ENV: 'development',
69
70
  },
70
71
  shell: true,
@@ -100,7 +101,10 @@ export class DevServer {
100
101
  PORT: String(port),
101
102
  };
102
103
  if (hasBackend) {
103
- frontendEnv['VITE_BACKEND_PORT'] = String(port + 1000);
104
+ const backendPort = port + 1001;
105
+ frontendEnv['VITE_BACKEND_PORT'] = String(backendPort);
106
+ // SERVER_PORT is used by vite.config.ts proxy to route /api requests
107
+ frontendEnv['SERVER_PORT'] = String(backendPort);
104
108
  }
105
109
  console.log(` [DevServer] Starting: ${cmd} ${args.join(' ')} (port ${port})`);
106
110
  this.process = spawn(cmd, args, {
@@ -69,6 +69,12 @@ export declare class LocalServer {
69
69
  private packageInstaller;
70
70
  private lastHeartbeat;
71
71
  constructor(options: LocalServerOptions);
72
+ /**
73
+ * Ensure the project database is provisioned and DATABASE_URL is set in the DevServer env.
74
+ * Called lazily on /live/open and /live/dev to handle the case where PostgreSQL
75
+ * wasn't available during agent startup but is now (or was never probed).
76
+ */
77
+ private ensureDatabase;
72
78
  getDevServer(): DevServer;
73
79
  getApiPort(): number;
74
80
  getDevPort(): number;
@@ -22,6 +22,7 @@ import { FileManager } from './fileManager.js';
22
22
  import { Checker } from './checker.js';
23
23
  import { ErrorStore, structuredErrorToString } from './errorStore.js';
24
24
  import { PackageInstaller } from './packageInstaller.js';
25
+ import { probeLocalPostgres, ensureLocalProjectDb, writeDatabaseUrlToEnv } from './projectDb.js';
25
26
  // ─── Try to load node-pty for real PTY support ─────────────────
26
27
  let ptyModule = null;
27
28
  try {
@@ -112,6 +113,40 @@ export class LocalServer {
112
113
  this.errorStore = new ErrorStore();
113
114
  this.packageInstaller = new PackageInstaller({ projectDir: options.projectDir });
114
115
  }
116
+ /**
117
+ * Ensure the project database is provisioned and DATABASE_URL is set in the DevServer env.
118
+ * Called lazily on /live/open and /live/dev to handle the case where PostgreSQL
119
+ * wasn't available during agent startup but is now (or was never probed).
120
+ */
121
+ async ensureDatabase() {
122
+ // Skip if DATABASE_URL is already set in the env
123
+ if (this.options.env?.['DATABASE_URL'])
124
+ return;
125
+ try {
126
+ const hasPg = await probeLocalPostgres();
127
+ if (hasPg) {
128
+ const dbUrl = await ensureLocalProjectDb(this.options.projectId);
129
+ if (dbUrl) {
130
+ // Update env for future DevServer starts
131
+ if (!this.options.env)
132
+ this.options.env = {};
133
+ this.options.env['DATABASE_URL'] = dbUrl;
134
+ // Write to .env so manual `npm run dev` also works
135
+ writeDatabaseUrlToEnv(this.options.projectDir, dbUrl);
136
+ // Also update the DevServer's env
137
+ this.devServer = new DevServer({
138
+ projectDir: this.options.projectDir,
139
+ port: this.options.devPort,
140
+ env: this.options.env,
141
+ });
142
+ console.log(` [LocalServer] Database provisioned: project_${this.options.projectId}`);
143
+ }
144
+ }
145
+ }
146
+ catch (err) {
147
+ console.warn(` [LocalServer] Database provisioning failed: ${err.message}`);
148
+ }
149
+ }
115
150
  getDevServer() {
116
151
  return this.devServer;
117
152
  }
@@ -349,13 +384,14 @@ export class LocalServer {
349
384
  // ─── /live/terminal ──────────────────────────────────────────
350
385
  async handleTerminal(_req, res, body) {
351
386
  const data = JSON.parse(body);
352
- const { command, cwd } = data;
387
+ const { command, cwd, timeoutSeconds } = data;
353
388
  if (!command) {
354
389
  res.statusCode = 400;
355
390
  this.json(res, { error: 'Missing command' });
356
391
  return;
357
392
  }
358
- const result = await this.devServer.exec(command);
393
+ const timeoutMs = timeoutSeconds ? timeoutSeconds * 1000 : undefined;
394
+ const result = await this.devServer.exec(command, timeoutMs);
359
395
  this.json(res, {
360
396
  success: result.exitCode === 0,
361
397
  exitCode: result.exitCode,
@@ -396,10 +432,46 @@ export class LocalServer {
396
432
  parsed = body ? JSON.parse(body) : {};
397
433
  }
398
434
  catch { }
435
+ const isAiSession = parsed.isAiSession || false;
436
+ // Reuse existing AI session if available (prevents spawning new tab per AI command)
437
+ if (isAiSession) {
438
+ const existingAiSession = Array.from(terminalSessions.values())
439
+ .find(s => s.projectId === this.options.projectId && s.isAiSession && !s.exited);
440
+ if (existingAiSession) {
441
+ existingAiSession.lastActivity = Date.now();
442
+ if (parsed.label)
443
+ existingAiSession.label = parsed.label;
444
+ // Write the new command to the existing session's PTY
445
+ if (parsed.command) {
446
+ if (existingAiSession.ptyProcess) {
447
+ existingAiSession.ptyProcess.write(parsed.command + '\n');
448
+ }
449
+ else if (existingAiSession.shell?.stdin) {
450
+ existingAiSession.shell.stdin.write(parsed.command + '\n');
451
+ }
452
+ }
453
+ this.json(res, {
454
+ success: true,
455
+ reused: true,
456
+ session: {
457
+ id: existingAiSession.id,
458
+ projectId: existingAiSession.projectId,
459
+ isAiSession: existingAiSession.isAiSession,
460
+ label: existingAiSession.label,
461
+ createdAt: existingAiSession.createdAt,
462
+ lastActivity: existingAiSession.lastActivity,
463
+ exited: false,
464
+ exitCode: null,
465
+ cols: existingAiSession.cols,
466
+ rows: existingAiSession.rows,
467
+ },
468
+ });
469
+ return;
470
+ }
471
+ }
399
472
  const sessionId = generateSessionId();
400
473
  const cols = parsed.cols || 120;
401
474
  const rows = parsed.rows || 30;
402
- const isAiSession = parsed.isAiSession || false;
403
475
  // Determine shell
404
476
  const shellCmd = process.platform === 'win32' ? 'cmd.exe' : (process.env.SHELL || '/bin/bash');
405
477
  const shellEnv = { ...process.env, TERM: 'xterm-256color', COLUMNS: String(cols), LINES: String(rows) };
@@ -505,9 +577,19 @@ export class LocalServer {
505
577
  shell.on('exit', (code) => handleExit(code));
506
578
  }
507
579
  terminalSessions.set(sessionId, session);
580
+ // Write initial command to PTY if provided (AI session)
581
+ if (parsed.command) {
582
+ if (ptyProcess) {
583
+ ptyProcess.write(parsed.command + '\n');
584
+ }
585
+ else if (shell?.stdin) {
586
+ shell.stdin.write(parsed.command + '\n');
587
+ }
588
+ }
508
589
  // Return format matching frontend TerminalSessionInfo
509
590
  this.json(res, {
510
591
  success: true,
592
+ reused: false,
511
593
  session: {
512
594
  id: sessionId,
513
595
  projectId: this.options.projectId,
@@ -573,7 +655,7 @@ export class LocalServer {
573
655
  connected: true,
574
656
  projectId: this.options.projectId,
575
657
  agent: {
576
- version: '0.5.10',
658
+ version: '0.5.11',
577
659
  hostname: os.hostname(),
578
660
  platform: `${os.platform()} ${os.arch()}`,
579
661
  },
@@ -595,9 +677,10 @@ export class LocalServer {
595
677
  async handleContainerStats(_req, res) {
596
678
  const devStats = this.devServer.getStats();
597
679
  const totalMemMb = Math.round(os.totalmem() / (1024 * 1024));
598
- const freeMemMb = Math.round(os.freemem() / (1024 * 1024));
599
- const usedMemMb = totalMemMb - freeMemMb;
600
- const memPercent = totalMemMb > 0 ? Math.round((usedMemMb / totalMemMb) * 100) : 0;
680
+ // Use process-specific memory from devStats, not system-wide (os.freemem)
681
+ // os.freemem() on macOS counts filesystem cache as "used", showing ~100%
682
+ const processMemMb = Math.round(devStats.memoryMb);
683
+ const memPercent = totalMemMb > 0 ? Math.round((processMemMb / totalMemMb) * 1000) / 10 : 0;
601
684
  // Return in the same format as the container stats (ContainerStatsSnapshot)
602
685
  // so the frontend terminal panel can display it unchanged.
603
686
  this.json(res, {
@@ -605,10 +688,10 @@ export class LocalServer {
605
688
  running: this.devServer.isRunning,
606
689
  agentMode: true,
607
690
  stats: {
608
- cpuPercent: devStats.cpuPercent,
609
- memoryUsageBytes: usedMemMb * 1024 * 1024,
691
+ cpuPercent: Math.round(devStats.cpuPercent * 10) / 10,
692
+ memoryUsageBytes: processMemMb * 1024 * 1024,
610
693
  memoryLimitBytes: totalMemMb * 1024 * 1024,
611
- memoryUsageMb: usedMemMb,
694
+ memoryUsageMb: processMemMb,
612
695
  memoryLimitMb: totalMemMb,
613
696
  memoryPercent: memPercent,
614
697
  diskUsageMb: null,
@@ -640,6 +723,8 @@ export class LocalServer {
640
723
  // ─── /live/dev ───────────────────────────────────────────────
641
724
  async handleDev(_req, res, body) {
642
725
  try {
726
+ // Ensure database is provisioned before starting backend
727
+ await this.ensureDatabase();
643
728
  // Ensure dependencies are installed
644
729
  await this.packageInstaller.ensureDependencies();
645
730
  // Start dev server
@@ -675,6 +760,8 @@ export class LocalServer {
675
760
  // ─── /live/open ──────────────────────────────────────────────
676
761
  async handleOpen(_req, res) {
677
762
  try {
763
+ // Ensure database is provisioned before starting backend
764
+ await this.ensureDatabase();
678
765
  // Ensure deps are installed
679
766
  await this.packageInstaller.ensureDependencies();
680
767
  // Start dev server if not running
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Local PostgreSQL database provisioning for the nstantpage agent.
3
+ *
4
+ * Mirrors the PreviewGateway's projectDb.ts but for local (non-Docker) environments.
5
+ * On macOS, this detects Homebrew PostgreSQL (or any PG on localhost:5432).
6
+ * Each project gets an isolated database: project_{id}
7
+ *
8
+ * Usage:
9
+ * const url = await ensureLocalProjectDb('131');
10
+ * // → "postgresql://username:@127.0.0.1:5432/project_131"
11
+ */
12
+ /**
13
+ * Probe for a local PostgreSQL instance.
14
+ * Returns true if PG is accessible on localhost.
15
+ */
16
+ export declare function probeLocalPostgres(): Promise<boolean>;
17
+ /**
18
+ * Check if local PostgreSQL is available (must call probeLocalPostgres first).
19
+ */
20
+ export declare function isLocalPgAvailable(): boolean;
21
+ /**
22
+ * Ensure a project database exists and return its DATABASE_URL.
23
+ * Idempotent — safe to call multiple times.
24
+ * Returns null if PostgreSQL is not available.
25
+ */
26
+ export declare function ensureLocalProjectDb(projectId: string): Promise<string | null>;
27
+ /**
28
+ * Write DATABASE_URL to the project's .env file so manual `npm run dev` works.
29
+ * - Creates .env if it doesn't exist
30
+ * - Updates DATABASE_URL if already present but different
31
+ * - Appends DATABASE_URL if not present
32
+ * Idempotent — safe to call multiple times.
33
+ */
34
+ export declare function writeDatabaseUrlToEnv(projectDir: string, databaseUrl: string): void;
35
+ /**
36
+ * Close the admin pool (for graceful shutdown).
37
+ */
38
+ export declare function closeAdminPool(): Promise<void>;
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Local PostgreSQL database provisioning for the nstantpage agent.
3
+ *
4
+ * Mirrors the PreviewGateway's projectDb.ts but for local (non-Docker) environments.
5
+ * On macOS, this detects Homebrew PostgreSQL (or any PG on localhost:5432).
6
+ * Each project gets an isolated database: project_{id}
7
+ *
8
+ * Usage:
9
+ * const url = await ensureLocalProjectDb('131');
10
+ * // → "postgresql://username:@127.0.0.1:5432/project_131"
11
+ */
12
+ import os from 'os';
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ // Connection config — detect environment
16
+ const PG_HOST = process.env.PG_HOST || '127.0.0.1';
17
+ const PG_PORT = process.env.PG_PORT || '5432';
18
+ // Local macOS (Homebrew PG): current OS username, no password, trust auth
19
+ const PG_USER = process.env.PG_USER || os.userInfo().username;
20
+ const PG_PASS = process.env.PG_PASS || '';
21
+ let pgAvailable = null; // null = not yet probed
22
+ let adminPool = null;
23
+ const verifiedDbs = new Set();
24
+ /**
25
+ * Get or create the admin connection pool (connects to 'postgres' database).
26
+ */
27
+ async function getAdminPool() {
28
+ if (!adminPool) {
29
+ const pg = await import('pg');
30
+ adminPool = new pg.default.Pool({
31
+ host: PG_HOST,
32
+ port: parseInt(PG_PORT),
33
+ user: PG_USER,
34
+ password: PG_PASS,
35
+ database: 'postgres',
36
+ max: 2,
37
+ idleTimeoutMillis: 30000,
38
+ connectionTimeoutMillis: 5000,
39
+ });
40
+ }
41
+ return adminPool;
42
+ }
43
+ /**
44
+ * Probe for a local PostgreSQL instance.
45
+ * Returns true if PG is accessible on localhost.
46
+ */
47
+ export async function probeLocalPostgres() {
48
+ if (pgAvailable !== null)
49
+ return pgAvailable;
50
+ try {
51
+ const pool = await getAdminPool();
52
+ const client = await pool.connect();
53
+ await client.query('SELECT 1');
54
+ client.release();
55
+ pgAvailable = true;
56
+ console.log(` [ProjectDb] Auto-detected PostgreSQL at ${PG_HOST}:${PG_PORT} (user: ${PG_USER})`);
57
+ return true;
58
+ }
59
+ catch (err) {
60
+ pgAvailable = false;
61
+ // Reset admin pool so it doesn't hold broken connections
62
+ if (adminPool) {
63
+ adminPool.end().catch(() => { });
64
+ adminPool = null;
65
+ }
66
+ console.log(` [ProjectDb] No PostgreSQL found at ${PG_HOST}:${PG_PORT} — projects will use PGlite fallback (${err.message})`);
67
+ return false;
68
+ }
69
+ }
70
+ /**
71
+ * Check if local PostgreSQL is available (must call probeLocalPostgres first).
72
+ */
73
+ export function isLocalPgAvailable() {
74
+ return pgAvailable === true;
75
+ }
76
+ /**
77
+ * Sanitize project ID to safe database name.
78
+ */
79
+ function dbName(projectId) {
80
+ const sanitized = projectId.replace(/[^a-zA-Z0-9_]/g, '_');
81
+ return `project_${sanitized}`;
82
+ }
83
+ /**
84
+ * Build a DATABASE_URL for a project.
85
+ */
86
+ function buildDatabaseUrl(name) {
87
+ const passStr = PG_PASS ? `:${PG_PASS}` : '';
88
+ return `postgresql://${PG_USER}${passStr}@${PG_HOST}:${PG_PORT}/${name}`;
89
+ }
90
+ /**
91
+ * Ensure a project database exists and return its DATABASE_URL.
92
+ * Idempotent — safe to call multiple times.
93
+ * Returns null if PostgreSQL is not available.
94
+ */
95
+ export async function ensureLocalProjectDb(projectId) {
96
+ if (!pgAvailable)
97
+ return null;
98
+ const name = dbName(projectId);
99
+ // Fast path: already verified this session
100
+ if (verifiedDbs.has(name)) {
101
+ return buildDatabaseUrl(name);
102
+ }
103
+ try {
104
+ const pool = await getAdminPool();
105
+ // Check if database exists
106
+ const { rows } = await pool.query('SELECT 1 FROM pg_database WHERE datname = $1', [name]);
107
+ if (rows.length === 0) {
108
+ // Create database — CREATE DATABASE can't use parameterized queries
109
+ await pool.query(`CREATE DATABASE ${name}`);
110
+ console.log(` [ProjectDb] Created database '${name}' for project ${projectId}`);
111
+ }
112
+ verifiedDbs.add(name);
113
+ return buildDatabaseUrl(name);
114
+ }
115
+ catch (err) {
116
+ // Handle race condition: duplicate_database
117
+ if (err.code === '42P04') {
118
+ verifiedDbs.add(name);
119
+ return buildDatabaseUrl(name);
120
+ }
121
+ console.error(` [ProjectDb] Failed to ensure database for ${projectId}:`, err.message);
122
+ return null;
123
+ }
124
+ }
125
+ /**
126
+ * Write DATABASE_URL to the project's .env file so manual `npm run dev` works.
127
+ * - Creates .env if it doesn't exist
128
+ * - Updates DATABASE_URL if already present but different
129
+ * - Appends DATABASE_URL if not present
130
+ * Idempotent — safe to call multiple times.
131
+ */
132
+ export function writeDatabaseUrlToEnv(projectDir, databaseUrl) {
133
+ const envPath = path.join(projectDir, '.env');
134
+ try {
135
+ let content = '';
136
+ if (fs.existsSync(envPath)) {
137
+ content = fs.readFileSync(envPath, 'utf-8');
138
+ }
139
+ const lines = content.split('\n');
140
+ const dbLineIdx = lines.findIndex(l => l.startsWith('DATABASE_URL='));
141
+ if (dbLineIdx >= 0) {
142
+ // Already has DATABASE_URL — update if different
143
+ const existing = lines[dbLineIdx].split('=').slice(1).join('=');
144
+ if (existing === databaseUrl)
145
+ return; // already correct
146
+ lines[dbLineIdx] = `DATABASE_URL=${databaseUrl}`;
147
+ }
148
+ else {
149
+ // Append DATABASE_URL
150
+ // Ensure there's a newline before appending if file doesn't end with one
151
+ if (content.length > 0 && !content.endsWith('\n')) {
152
+ lines.push('');
153
+ }
154
+ lines.push(`DATABASE_URL=${databaseUrl}`);
155
+ }
156
+ fs.writeFileSync(envPath, lines.join('\n'), 'utf-8');
157
+ console.log(` [ProjectDb] Wrote DATABASE_URL to ${envPath}`);
158
+ }
159
+ catch (err) {
160
+ console.warn(` [ProjectDb] Failed to write .env: ${err.message}`);
161
+ }
162
+ }
163
+ /**
164
+ * Close the admin pool (for graceful shutdown).
165
+ */
166
+ export async function closeAdminPool() {
167
+ if (adminPool) {
168
+ await adminPool.end();
169
+ adminPool = null;
170
+ }
171
+ }
172
+ //# sourceMappingURL=projectDb.js.map
package/dist/tunnel.js CHANGED
@@ -63,7 +63,7 @@ export class TunnelClient {
63
63
  // Send enhanced agent info with capabilities and deviceId
64
64
  this.send({
65
65
  type: 'agent-info',
66
- version: '0.5.10',
66
+ version: '0.5.11',
67
67
  hostname: os.hostname(),
68
68
  platform: `${os.platform()} ${os.arch()}`,
69
69
  deviceId: getDeviceId(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nstantpage-agent",
3
- "version": "0.5.11",
3
+ "version": "0.5.13",
4
4
  "description": "Local development agent for nstantpage.com — run your projects locally, preview in the cloud. Replaces cloud containers for faster builds.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -49,12 +49,14 @@
49
49
  "express": "^4.21.0",
50
50
  "http-proxy": "^1.18.1",
51
51
  "open": "^10.1.0",
52
+ "pg": "^8.13.0",
52
53
  "ws": "^8.18.0"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@types/express": "^4.17.21",
56
57
  "@types/http-proxy": "^1.17.14",
57
58
  "@types/node": "^20.14.0",
59
+ "@types/pg": "^8.18.0",
58
60
  "@types/ws": "^8.5.10",
59
61
  "tsx": "^4.19.0",
60
62
  "typescript": "^5.5.0"