staticx 0.1.2 → 0.1.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 CHANGED
@@ -30,9 +30,27 @@ staticx create --workspace-id WORKSPACE_ID --name "Marketing Site"
30
30
  staticx create --name "Imported Site" --archive site.zip
31
31
  staticx create --name "Imported Site" --source-url "https://example.com"
32
32
  staticx deploy --site-id SITE_ID --dir dist
33
+ staticx domain --site-id SITE_ID --domain app.example.com
34
+ staticx domain-status --site-id SITE_ID
33
35
  staticx logs --site-id SITE_ID
34
36
  ```
35
37
 
38
+ ## Custom domains
39
+
40
+ Use the CLI when you want to connect a domain without opening the dashboard.
41
+
42
+ ```bash
43
+ staticx domain --site-id SITE_ID --domain app.example.com
44
+ ```
45
+
46
+ The command moves the site to that domain and prints the single DNS record to create. After the DNS record is added, StaticX detects it and activates SSL automatically.
47
+
48
+ Check progress any time:
49
+
50
+ ```bash
51
+ staticx domain-status --site-id SITE_ID
52
+ ```
53
+
36
54
  ## Token scopes
37
55
 
38
56
  - Global token: account-wide access for internal operator tools.
@@ -50,3 +68,4 @@ Generate those tokens from:
50
68
  - `staticx login` stores the base URL and bearer token locally.
51
69
  - `staticx whoami` verifies the token with `GET /user`.
52
70
  - `staticx deploy` zips the contents of the given build directory, uploads them, and publishes a new release. The directory must contain `index.html` or `index.htm` plus `404.html` at its root.
71
+ - `staticx domain` calls `POST /projects/{project}/domain` and returns the DNS record plus activation status.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "staticx",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Public CLI for STATICX using token-authenticated /api/v1 routes.",
5
5
  "type": "module",
6
6
  "publishConfig": {
package/src/index.js CHANGED
@@ -10,13 +10,14 @@ import {
10
10
  cliGuideJson,
11
11
  formatTokenSummary,
12
12
  printCliGuide,
13
+ printDomainSetup,
13
14
  printJson,
14
15
  printKeyValue,
15
16
  printLoginSuccess,
16
17
  printTable,
17
18
  } from './output.js';
18
19
 
19
- const CLI_VERSION = '0.1.2';
20
+ const CLI_VERSION = '0.1.3';
20
21
 
21
22
  export async function run(argv) {
22
23
  const program = new Command();
@@ -32,6 +33,7 @@ Common workflow:
32
33
  staticx login --base-url "https://staticx.site/api/v1" --token "STATICX_API_TOKEN"
33
34
  staticx guide
34
35
  staticx deploy --site-id SITE_ID --dir dist
36
+ staticx domain --site-id SITE_ID --domain app.example.com
35
37
 
36
38
  Deploy rule:
37
39
  The build directory must contain index.html or index.htm and 404.html at its root.
@@ -276,6 +278,47 @@ Deploy rule:
276
278
  })));
277
279
  });
278
280
 
281
+ program
282
+ .command('domain')
283
+ .description('Move a site to a custom domain and print the one DNS record to create.')
284
+ .requiredOption('--site-id <id>', 'Site ID')
285
+ .requiredOption('--domain <domain>', 'Custom domain, for example app.example.com')
286
+ .option('--json', 'Print JSON output')
287
+ .option('--base-url <url>', 'Override the stored STATICX API base URL')
288
+ .option('--token <token>', 'Override the stored STATICX bearer token')
289
+ .action(async (options, command) => {
290
+ const client = await clientFromCommand(command);
291
+ const response = await client.post(`/projects/${options.siteId}/domain`, {
292
+ json: { domain: options.domain },
293
+ });
294
+
295
+ if (options.json) {
296
+ printJson(response);
297
+ return;
298
+ }
299
+
300
+ printDomainSetup(response);
301
+ });
302
+
303
+ program
304
+ .command('domain-status')
305
+ .description('Check the custom domain status for one site.')
306
+ .requiredOption('--site-id <id>', 'Site ID')
307
+ .option('--json', 'Print JSON output')
308
+ .option('--base-url <url>', 'Override the stored STATICX API base URL')
309
+ .option('--token <token>', 'Override the stored STATICX bearer token')
310
+ .action(async (options, command) => {
311
+ const client = await clientFromCommand(command);
312
+ const response = await client.get(`/projects/${options.siteId}/domain`);
313
+
314
+ if (options.json) {
315
+ printJson(response);
316
+ return;
317
+ }
318
+
319
+ printDomainSetup({ message: 'Custom domain status.', data: response?.data ?? response }, { statusOnly: true });
320
+ });
321
+
279
322
  await program.parseAsync(argv);
280
323
  }
281
324
 
package/src/output.js CHANGED
@@ -10,6 +10,46 @@ export function printTable(rows) {
10
10
  console.table(rows);
11
11
  }
12
12
 
13
+ export function printDomainSetup(response, { statusOnly = false } = {}) {
14
+ const data = response?.data ?? {};
15
+ const project = data.project ?? {};
16
+ const domain = data.custom_domain ?? null;
17
+ const records = data.dns?.records ?? [];
18
+ const steps = Array.isArray(data.steps) ? data.steps : [];
19
+
20
+ console.log(response?.message || (statusOnly ? 'Custom domain status.' : 'Custom domain setup started.'));
21
+ console.log('');
22
+ printAlignedRows([
23
+ ['Site', project.name || project.id || 'Unknown'],
24
+ ['Current URL', project.public_url || 'Pending'],
25
+ ['Custom domain', domain?.host || 'Not connected'],
26
+ ['Status', domain?.status_label || data.status?.label || 'Pending'],
27
+ ]);
28
+
29
+ if (domain?.status_message || data.status?.message) {
30
+ console.log('');
31
+ console.log(domain?.status_message || data.status?.message);
32
+ }
33
+
34
+ if (records.length > 0) {
35
+ console.log('');
36
+ console.log('Create this DNS record:');
37
+ printTable(records.map((record) => ({
38
+ type: record.type,
39
+ name: record.name,
40
+ value: record.value,
41
+ })));
42
+ }
43
+
44
+ if (steps.length > 0) {
45
+ console.log('');
46
+ console.log('Next steps');
47
+ steps.forEach((step, index) => {
48
+ console.log(` ${index + 1}. ${step}`);
49
+ });
50
+ }
51
+ }
52
+
13
53
  export function printLoginSuccess({ baseUrl, user, token }) {
14
54
  printBanner();
15
55
  console.log('Successfully authenticated.');
@@ -25,6 +65,7 @@ export function printLoginSuccess({ baseUrl, user, token }) {
25
65
  ['staticx guide', 'Show the complete CLI workflow.'],
26
66
  ['staticx sites', 'List the sites visible to this token.'],
27
67
  ['staticx deploy --site-id SITE_ID --dir dist', 'Upload and publish a build folder.'],
68
+ ['staticx domain --site-id SITE_ID --domain app.example.com', 'Move a site to a custom domain.'],
28
69
  ]);
29
70
  console.log('');
30
71
  console.log('Build rule: deploy folders must include index.html or index.htm and 404.html at the root.');
@@ -53,6 +94,11 @@ export function printCliGuide() {
53
94
  ['staticx deploy --site-id SITE_ID --dir dist', 'Zip, upload, and publish a build folder.'],
54
95
  ]);
55
96
  console.log('');
97
+ printCommandGroup('Custom domains', [
98
+ ['staticx domain --site-id SITE_ID --domain app.example.com', 'Move a site to a custom domain and print the DNS record.'],
99
+ ['staticx domain-status --site-id SITE_ID', 'Check DNS, SSL, and activation status.'],
100
+ ]);
101
+ console.log('');
56
102
  printCommandGroup('Inspect', [
57
103
  ['staticx logs --site-id SITE_ID', 'Read recent site activity.'],
58
104
  ['staticx logs --site-id SITE_ID --limit 50', 'Read more rows.'],
@@ -82,6 +128,10 @@ export function cliGuideJson() {
82
128
  'staticx create --name "Imported Site" --source-url "https://example.com"',
83
129
  'staticx deploy --site-id SITE_ID --dir dist',
84
130
  ],
131
+ domains: [
132
+ 'staticx domain --site-id SITE_ID --domain app.example.com',
133
+ 'staticx domain-status --site-id SITE_ID',
134
+ ],
85
135
  inspect: [
86
136
  'staticx logs --site-id SITE_ID',
87
137
  'staticx logs --site-id SITE_ID --limit 50',