nstantpage-agent 0.8.0 → 0.8.1

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
@@ -22,6 +22,7 @@ import { startCommand } from './commands/start.js';
22
22
  import { statusCommand } from './commands/status.js';
23
23
  import { serviceInstallCommand, serviceUninstallCommand, serviceStatusCommand, serviceStartCommand, serviceStopCommand } from './commands/service.js';
24
24
  import { updateCommand } from './commands/update.js';
25
+ import { runCommand } from './commands/run.js';
25
26
  import { syncCommand } from './commands/sync.js';
26
27
  import { getPackageVersion } from './version.js';
27
28
  const program = new Command();
@@ -32,6 +33,7 @@ program
32
33
  program
33
34
  .command('login')
34
35
  .description('Authenticate with nstantpage.com')
36
+ .option('--local [port]', 'Authenticate with local backend (default: 5001)')
35
37
  .option('--gateway <url>', 'Gateway URL (auto-detects local vs production)')
36
38
  .option('--force', 'Re-authenticate even if already logged in')
37
39
  .action(loginCommand);
@@ -45,6 +47,7 @@ program
45
47
  .argument('[directory]', 'Project directory (defaults to ~/.nstantpage/projects/<id>)', '.')
46
48
  .option('-p, --port <port>', 'Local dev server port', '3000')
47
49
  .option('-a, --api-port <port>', 'Local API server port (internal)', '18924')
50
+ .option('--local [port]', 'Connect to local backend (default: 5001)')
48
51
  .option('--project-id <id>', 'Link to a specific project ID')
49
52
  .option('--gateway <url>', 'Gateway URL (default: from login)')
50
53
  .option('--backend <url>', 'Backend API URL (auto-detected from gateway)')
@@ -52,6 +55,11 @@ program
52
55
  .option('--dir <path>', 'Project directory override')
53
56
  .option('--no-dev', 'Skip starting the dev server (start manually later)')
54
57
  .action(startCommand);
58
+ program
59
+ .command('run')
60
+ .description('Install background service and start the agent')
61
+ .option('--local [port]', 'Connect to local backend (default: 5001)')
62
+ .action(runCommand);
55
63
  program
56
64
  .command('sync')
57
65
  .description('Sync local directory to nstantpage and start agent')
@@ -2,6 +2,7 @@
2
2
  * Login command — authenticate with nstantpage.com
3
3
  */
4
4
  interface LoginOptions {
5
+ local?: string | boolean;
5
6
  gateway?: string;
6
7
  force?: boolean;
7
8
  }
@@ -46,6 +46,13 @@ function getEmailFromToken(token) {
46
46
  }
47
47
  export async function loginCommand(options = {}) {
48
48
  const conf = getConfig();
49
+ // Handle --local flag: set gateway to point at local server
50
+ if (options.local !== undefined && options.local !== false) {
51
+ const port = (typeof options.local === 'string') ? options.local : '5001';
52
+ options.gateway = `ws://localhost:4000`;
53
+ // Also store the backend URL for other commands
54
+ conf.set('localBackendUrl', `http://localhost:${port}`);
55
+ }
49
56
  // Check if already logged in (unless --force)
50
57
  const existingToken = conf.get('token');
51
58
  if (existingToken && !options.force) {
@@ -1,10 +1,14 @@
1
1
  /**
2
- * Run command — open the nstantpage desktop app.
2
+ * Run command — install the background service and start the agent.
3
3
  *
4
4
  * Usage:
5
- * nstantpage run — Open desktop app (loads nstantpage.com)
6
- * nstantpage run --local — Open desktop app pointing at localhost:5001
7
- * nstantpage run --local 3000 — Open desktop app pointing at localhost:3000
5
+ * nstantpage run — Install service + start agent (connects to nstantpage.com)
6
+ * nstantpage run --local — Same but targeting localhost:5001
7
+ * nstantpage run --local 3000 — Same but targeting localhost:3000
8
+ *
9
+ * This is the main entry point for users. It:
10
+ * 1. Installs the agent as a background service (auto-start on boot)
11
+ * 2. Starts the agent immediately in standby mode
8
12
  */
9
13
  interface RunOptions {
10
14
  local?: string | boolean;
@@ -1,82 +1,59 @@
1
1
  /**
2
- * Run command — open the nstantpage desktop app.
2
+ * Run command — install the background service and start the agent.
3
3
  *
4
4
  * Usage:
5
- * nstantpage run — Open desktop app (loads nstantpage.com)
6
- * nstantpage run --local — Open desktop app pointing at localhost:5001
7
- * nstantpage run --local 3000 — Open desktop app pointing at localhost:3000
5
+ * nstantpage run — Install service + start agent (connects to nstantpage.com)
6
+ * nstantpage run --local — Same but targeting localhost:5001
7
+ * nstantpage run --local 3000 — Same but targeting localhost:3000
8
+ *
9
+ * This is the main entry point for users. It:
10
+ * 1. Installs the agent as a background service (auto-start on boot)
11
+ * 2. Starts the agent immediately in standby mode
8
12
  */
9
13
  import chalk from 'chalk';
10
- import fs from 'fs';
11
- import path from 'path';
12
- import os from 'os';
13
- import { execSync } from 'child_process';
14
- /**
15
- * Find the Electron desktop app on disk.
16
- * Same logic as service.ts findElectronApp() — check postinstall location first.
17
- */
18
- function findElectronApp() {
19
- const platform = os.platform();
20
- if (platform === 'darwin') {
21
- const candidates = [
22
- path.join(os.homedir(), '.nstantpage', 'desktop', 'nstantpage.app'),
23
- '/Applications/nstantpage.app',
24
- path.join(os.homedir(), 'Applications', 'nstantpage.app'),
25
- ];
26
- for (const p of candidates) {
27
- if (fs.existsSync(p))
28
- return p;
29
- }
30
- }
31
- else if (platform === 'win32') {
32
- const candidates = [
33
- path.join(os.homedir(), '.nstantpage', 'desktop', 'nstantpage.exe'),
34
- path.join(os.homedir(), 'AppData', 'Local', 'Programs', 'nstantpage', 'nstantpage.exe'),
35
- path.join('C:\\Program Files', 'nstantpage', 'nstantpage.exe'),
36
- ];
37
- for (const p of candidates) {
38
- if (fs.existsSync(p))
39
- return p;
40
- }
41
- }
42
- return null;
43
- }
14
+ import { getConfig } from '../config.js';
15
+ import { serviceInstallCommand } from './service.js';
16
+ import { startCommand } from './start.js';
44
17
  export async function runCommand(options = {}) {
45
- const appPath = findElectronApp();
46
- if (!appPath) {
47
- console.log(chalk.red(' ✗ Desktop app not found.'));
48
- console.log(chalk.gray(' Run "nstantpage update --desktop" to download it.'));
49
- process.exit(1);
50
- }
51
- const platform = os.platform();
52
- // Build args to pass to the Electron app
53
- const extraArgs = [];
18
+ const conf = getConfig();
19
+ // Resolve gateway based on --local flag
20
+ let gateway;
54
21
  if (options.local !== undefined && options.local !== false) {
55
22
  const port = (typeof options.local === 'string') ? options.local : '5001';
56
- extraArgs.push(`--local-url=http://localhost:${port}`);
23
+ gateway = `ws://localhost:4000`;
24
+ // Store backend override for the start command
25
+ conf.set('localBackendUrl', `http://localhost:${port}`);
57
26
  }
58
- console.log(chalk.blue(`\n Opening nstantpage desktop app...`));
59
- if (extraArgs.length) {
60
- console.log(chalk.gray(` Args: ${extraArgs.join(' ')}`));
27
+ else {
28
+ gateway = conf.get('gatewayUrl') || 'wss://webprev.live';
61
29
  }
30
+ const token = conf.get('token');
31
+ const isLocal = /^wss?:\/\/(localhost|127\.0\.0\.1)/.test(gateway);
32
+ if (!token && !isLocal) {
33
+ console.log(chalk.red(' ✗ Not authenticated. Run "nstantpage login" first.'));
34
+ process.exit(1);
35
+ }
36
+ console.log(chalk.blue(`\n 🚀 nstantpage run\n`));
37
+ console.log(chalk.gray(` Server: ${isLocal ? 'localhost (dev)' : 'nstantpage.com'}`));
38
+ // 1. Install background service (auto-start on boot)
39
+ console.log(chalk.gray(' Installing background service...'));
62
40
  try {
63
- if (platform === 'darwin') {
64
- const argsStr = extraArgs.length ? ` --args ${extraArgs.join(' ')}` : '';
65
- execSync(`open -a "${appPath}"${argsStr}`, { stdio: 'inherit' });
66
- }
67
- else if (platform === 'win32') {
68
- const argsStr = extraArgs.join(' ');
69
- execSync(`"${appPath}" ${argsStr}`, { stdio: 'inherit' });
70
- }
71
- else {
72
- console.log(chalk.yellow(' ⚠ Desktop app not supported on this platform yet.'));
73
- process.exit(1);
74
- }
75
- console.log(chalk.green(' ✓ App launched\n'));
41
+ await serviceInstallCommand({ gateway });
76
42
  }
77
43
  catch (err) {
78
- console.log(chalk.red(` Failed to launch: ${err.message}`));
79
- process.exit(1);
44
+ console.log(chalk.yellow(` Service install skipped: ${err.message}`));
80
45
  }
46
+ // 2. Start agent in standby mode
47
+ console.log(chalk.gray('\n Starting agent...\n'));
48
+ const backendUrl = isLocal
49
+ ? (conf.get('localBackendUrl') || 'http://localhost:5001')
50
+ : undefined;
51
+ await startCommand('.', {
52
+ port: '3000',
53
+ apiPort: '18924',
54
+ gateway,
55
+ token: token || 'local-dev',
56
+ backend: backendUrl,
57
+ });
81
58
  }
82
59
  //# sourceMappingURL=run.js.map
@@ -18,6 +18,7 @@
18
18
  interface StartOptions {
19
19
  port: string;
20
20
  apiPort: string;
21
+ local?: string | boolean;
21
22
  projectId?: string;
22
23
  gateway: string;
23
24
  backend?: string;
@@ -182,6 +182,12 @@ function cleanupPreviousAgent(projectId, apiPort, devPort) {
182
182
  }
183
183
  export async function startCommand(directory, options) {
184
184
  const conf = getConfig();
185
+ // Handle --local flag: override backend & gateway to point at localhost
186
+ if (options.local !== undefined && options.local !== false) {
187
+ const localPort = (typeof options.local === 'string') ? options.local : '5001';
188
+ options.backend = `http://localhost:${localPort}`;
189
+ options.gateway = `ws://localhost:4000`;
190
+ }
185
191
  // If --token was passed, persist it
186
192
  if (options.token) {
187
193
  conf.set('token', options.token);
@@ -136,7 +136,10 @@ export async function syncCommand(directory, options) {
136
136
  const parts = token.split('.');
137
137
  if (parts.length === 3) {
138
138
  const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf-8'));
139
- userId = payload.sub;
139
+ // .NET uses full claim type URIs; also check standard 'sub' claim
140
+ userId = payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier']
141
+ || payload['sub']
142
+ || payload['nameid'];
140
143
  }
141
144
  }
142
145
  catch { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nstantpage-agent",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
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": {