@saplo/cli 0.1.0

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 (96) hide show
  1. package/README.md +112 -0
  2. package/bin/dev.js +5 -0
  3. package/bin/run.js +5 -0
  4. package/dist/commands/deploy.d.ts +13 -0
  5. package/dist/commands/deploy.d.ts.map +1 -0
  6. package/dist/commands/deploy.js +206 -0
  7. package/dist/commands/deploy.js.map +1 -0
  8. package/dist/commands/domain/add.d.ts +13 -0
  9. package/dist/commands/domain/add.d.ts.map +1 -0
  10. package/dist/commands/domain/add.js +44 -0
  11. package/dist/commands/domain/add.js.map +1 -0
  12. package/dist/commands/domain/ls.d.ts +10 -0
  13. package/dist/commands/domain/ls.d.ts.map +1 -0
  14. package/dist/commands/domain/ls.js +32 -0
  15. package/dist/commands/domain/ls.js.map +1 -0
  16. package/dist/commands/domain/rm.d.ts +13 -0
  17. package/dist/commands/domain/rm.d.ts.map +1 -0
  18. package/dist/commands/domain/rm.js +29 -0
  19. package/dist/commands/domain/rm.js.map +1 -0
  20. package/dist/commands/env/index.d.ts +10 -0
  21. package/dist/commands/env/index.d.ts.map +1 -0
  22. package/dist/commands/env/index.js +34 -0
  23. package/dist/commands/env/index.js.map +1 -0
  24. package/dist/commands/env/pull.d.ts +12 -0
  25. package/dist/commands/env/pull.d.ts.map +1 -0
  26. package/dist/commands/env/pull.js +62 -0
  27. package/dist/commands/env/pull.js.map +1 -0
  28. package/dist/commands/env/rm.d.ts +14 -0
  29. package/dist/commands/env/rm.d.ts.map +1 -0
  30. package/dist/commands/env/rm.js +36 -0
  31. package/dist/commands/env/rm.js.map +1 -0
  32. package/dist/commands/env/set.d.ts +14 -0
  33. package/dist/commands/env/set.d.ts.map +1 -0
  34. package/dist/commands/env/set.js +47 -0
  35. package/dist/commands/env/set.js.map +1 -0
  36. package/dist/commands/init.d.ts +13 -0
  37. package/dist/commands/init.d.ts.map +1 -0
  38. package/dist/commands/init.js +144 -0
  39. package/dist/commands/init.js.map +1 -0
  40. package/dist/commands/link.d.ts +10 -0
  41. package/dist/commands/link.d.ts.map +1 -0
  42. package/dist/commands/link.js +86 -0
  43. package/dist/commands/link.js.map +1 -0
  44. package/dist/commands/login.d.ts +12 -0
  45. package/dist/commands/login.d.ts.map +1 -0
  46. package/dist/commands/login.js +83 -0
  47. package/dist/commands/login.js.map +1 -0
  48. package/dist/commands/logs.d.ts +13 -0
  49. package/dist/commands/logs.d.ts.map +1 -0
  50. package/dist/commands/logs.js +63 -0
  51. package/dist/commands/logs.js.map +1 -0
  52. package/dist/commands/open.d.ts +10 -0
  53. package/dist/commands/open.d.ts.map +1 -0
  54. package/dist/commands/open.js +42 -0
  55. package/dist/commands/open.js.map +1 -0
  56. package/dist/commands/rollback.d.ts +16 -0
  57. package/dist/commands/rollback.d.ts.map +1 -0
  58. package/dist/commands/rollback.js +51 -0
  59. package/dist/commands/rollback.js.map +1 -0
  60. package/dist/commands/status.d.ts +10 -0
  61. package/dist/commands/status.d.ts.map +1 -0
  62. package/dist/commands/status.js +63 -0
  63. package/dist/commands/status.js.map +1 -0
  64. package/dist/commands/whoami.d.ts +7 -0
  65. package/dist/commands/whoami.d.ts.map +1 -0
  66. package/dist/commands/whoami.js +26 -0
  67. package/dist/commands/whoami.js.map +1 -0
  68. package/dist/index.d.ts +2 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +2 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/lib/api.d.ts +68 -0
  73. package/dist/lib/api.d.ts.map +1 -0
  74. package/dist/lib/api.js +117 -0
  75. package/dist/lib/api.js.map +1 -0
  76. package/dist/lib/config.d.ts +16 -0
  77. package/dist/lib/config.d.ts.map +1 -0
  78. package/dist/lib/config.js +74 -0
  79. package/dist/lib/config.js.map +1 -0
  80. package/dist/lib/detect.d.ts +9 -0
  81. package/dist/lib/detect.d.ts.map +1 -0
  82. package/dist/lib/detect.js +293 -0
  83. package/dist/lib/detect.js.map +1 -0
  84. package/dist/lib/packager.d.ts +18 -0
  85. package/dist/lib/packager.d.ts.map +1 -0
  86. package/dist/lib/packager.js +139 -0
  87. package/dist/lib/packager.js.map +1 -0
  88. package/dist/lib/saplo-config.d.ts +50 -0
  89. package/dist/lib/saplo-config.d.ts.map +1 -0
  90. package/dist/lib/saplo-config.js +203 -0
  91. package/dist/lib/saplo-config.js.map +1 -0
  92. package/dist/lib/ws-logs.d.ts +6 -0
  93. package/dist/lib/ws-logs.d.ts.map +1 -0
  94. package/dist/lib/ws-logs.js +112 -0
  95. package/dist/lib/ws-logs.js.map +1 -0
  96. package/package.json +80 -0
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # @saplo/cli
2
+
3
+ Official CLI for the [Saplo](https://saplo.pl) hosting platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @saplo/cli
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ # Authenticate
15
+ saplo login
16
+
17
+ # In your project directory
18
+ saplo init # generate saplo.yaml
19
+ saplo link # connect to existing app
20
+ saplo deploy # deploy!
21
+ ```
22
+
23
+ ## Commands
24
+
25
+ ### Authentication
26
+ - `saplo login [--token <token>]` - Authenticate with Saplo
27
+ - `saplo whoami` - Show current authenticated user
28
+
29
+ ### Project Setup
30
+ - `saplo init` - Initialize saplo.yaml in current directory
31
+ - `saplo link [--app-id <id>]` - Link directory to an existing application
32
+
33
+ ### Deployment
34
+ - `saplo deploy` - Deploy the current directory
35
+ - `saplo deploy --prebuilt` - Upload prebuilt output (skip server build)
36
+ - `saplo deploy --no-logs` - Deploy without streaming logs
37
+ - `saplo rollback [<deployment_id>]` - Roll back to previous deployment
38
+ - `saplo status` - Show current app status and recent deployments
39
+
40
+ ### Logs
41
+ - `saplo logs` - Show recent logs
42
+ - `saplo logs --follow` - Stream live logs
43
+ - `saplo logs --deployment <id>` - Logs for a specific deployment
44
+
45
+ ### Environment Variables
46
+ - `saplo env` - List all env vars
47
+ - `saplo env set KEY=value` - Set one or more env vars
48
+ - `saplo env rm KEY` - Remove an env var
49
+ - `saplo env pull` - Pull non-secret vars to .env.local
50
+
51
+ ### Domains
52
+ - `saplo domain ls` - List custom domains
53
+ - `saplo domain add example.com` - Add a custom domain
54
+ - `saplo domain rm example.com` - Remove a domain
55
+
56
+ ### Utilities
57
+ - `saplo open` - Open app URL in browser
58
+
59
+ ## saplo.yaml Reference
60
+
61
+ ```yaml
62
+ version: 1
63
+ name: my-app # lowercase slug
64
+ stack: nextjs # nextjs|react|django|static|docker|node|astro
65
+ app_id: 1234 # set by `saplo init` or `saplo link`
66
+
67
+ runtime:
68
+ node: "22" # node version
69
+ python: "3.13" # python version
70
+
71
+ build:
72
+ install: "npm ci"
73
+ command: "npm run build"
74
+ output: ".next"
75
+
76
+ start:
77
+ command: "npm run start"
78
+ port: 3000
79
+ healthcheck: "/api/health"
80
+ workers: 1
81
+
82
+ env:
83
+ MY_VAR: "value"
84
+
85
+ domains: [example.com, www.example.com]
86
+
87
+ hooks:
88
+ pre_build: "scripts/setup.sh"
89
+ post_deploy: "curl -X POST $NOTIFY_URL"
90
+
91
+ branches:
92
+ production: main
93
+
94
+ resources:
95
+ ram_mb: 2048
96
+ ssd_gb: 20
97
+ ```
98
+
99
+ ## .saploignore
100
+
101
+ Create a `.saploignore` file (like `.gitignore`) to exclude files from deployment:
102
+
103
+ ```
104
+ my-large-file.bin
105
+ local-only/
106
+ ```
107
+
108
+ Default ignores: `node_modules`, `.git`, `.next/cache`, `*.log`, `.env*`, `.DS_Store`
109
+
110
+ ## License
111
+
112
+ MIT - Studio Kalmus
package/bin/dev.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {execute} from '@oclif/core'
4
+
5
+ await execute({development: true, dir: import.meta.url})
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {execute} from '@oclif/core'
4
+
5
+ await execute({development: false, dir: import.meta.url})
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Deploy extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ 'app-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ 'no-logs': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
8
+ prebuilt: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
+ };
10
+ private ensureApplication;
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAQ,MAAM,aAAa,CAAA;AAW1C,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IACzC,OAAgB,WAAW,SAA0C;IAErE,OAAgB,QAAQ,WAIvB;IAED,OAAgB,KAAK;;;;MAapB;YAIa,iBAAiB;IA6CzB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAmI3B"}
@@ -0,0 +1,206 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { createReadStream, unlinkSync } from 'node:fs';
3
+ import FormData from 'form-data';
4
+ import chalk from 'chalk';
5
+ import ora from 'ora';
6
+ import { loadSaploConfig } from '../lib/saplo-config.js';
7
+ import { packageDirectory, formatSize } from '../lib/packager.js';
8
+ import { api } from '../lib/api.js';
9
+ import { requireToken, getProjectConfig, saveProjectConfig } from '../lib/config.js';
10
+ import { streamDeploymentLogs, defaultLogHandler } from '../lib/ws-logs.js';
11
+ export default class Deploy extends Command {
12
+ static description = 'Deploy the current directory to Saplo';
13
+ static examples = [
14
+ '<%= config.bin %> <%= command.id %>',
15
+ '<%= config.bin %> <%= command.id %> --app-id 42',
16
+ '<%= config.bin %> <%= command.id %> --no-logs',
17
+ ];
18
+ static flags = {
19
+ 'app-id': Flags.integer({
20
+ char: 'a',
21
+ description: 'Application ID (overrides .saplo/project.json)',
22
+ }),
23
+ 'no-logs': Flags.boolean({
24
+ description: 'Do not stream build logs',
25
+ default: false,
26
+ }),
27
+ prebuilt: Flags.boolean({
28
+ description: 'Skip server-side build (upload prebuilt output directory)',
29
+ default: false,
30
+ }),
31
+ };
32
+ // Znajduje istniejaca aplikacje o danej nazwie lub tworzy nowa.
33
+ // Po stworzeniu czeka az kontener wstanie (status running).
34
+ async ensureApplication(name, stack, cwd) {
35
+ const spinner = ora(`Szukam aplikacji ${name}...`).start();
36
+ try {
37
+ const apps = await api.listApplications();
38
+ const existing = apps.find((a) => a.name === name);
39
+ if (existing) {
40
+ spinner.succeed(`Znaleziono aplikacje ${name} (#${existing.id})`);
41
+ saveProjectConfig({ app_id: existing.id, app_name: name }, cwd);
42
+ return existing.id;
43
+ }
44
+ spinner.text = `Tworze aplikacje ${name} (${stack})...`;
45
+ const created = await api.createApplication({ name, stack });
46
+ spinner.succeed(`Utworzono aplikacje ${name} (#${created.id})`);
47
+ saveProjectConfig({ app_id: created.id, app_name: name }, cwd);
48
+ // Czekaj az kontener wstanie (clone + config + start, zwykle 1-2 min).
49
+ const waitSpinner = ora('Stawiam srodowisko (klonowanie kontenera, ~1-2 min)...').start();
50
+ const deadline = Date.now() + 6 * 60 * 1000;
51
+ while (Date.now() < deadline) {
52
+ await new Promise((r) => setTimeout(r, 5000));
53
+ try {
54
+ const app = await api.getApplication(created.id);
55
+ if (app.status === 'running') {
56
+ waitSpinner.succeed('Srodowisko gotowe');
57
+ return created.id;
58
+ }
59
+ if (app.status === 'error') {
60
+ waitSpinner.fail('Tworzenie srodowiska nie powiodlo sie');
61
+ this.error('Nie udalo sie postawic kontenera. Sprawdz panel: panel.saplo.pl');
62
+ }
63
+ waitSpinner.text = `Stawiam srodowisko (status: ${app.status})...`;
64
+ }
65
+ catch {
66
+ // przejsciowy blad odczytu - ponow
67
+ }
68
+ }
69
+ waitSpinner.warn('Srodowisko wciaz sie stawia - sprobuj `saplo deploy` za chwile');
70
+ this.exit(0);
71
+ return created.id;
72
+ }
73
+ catch (err) {
74
+ spinner.fail('Nie udalo sie przygotowac aplikacji');
75
+ this.error(err.message);
76
+ }
77
+ }
78
+ async run() {
79
+ const { flags } = await this.parse(Deploy);
80
+ requireToken();
81
+ const cwd = process.cwd();
82
+ // Load and validate saplo.yaml
83
+ let config;
84
+ try {
85
+ config = loadSaploConfig(cwd);
86
+ }
87
+ catch (err) {
88
+ this.error(err.message);
89
+ }
90
+ // Determine app ID - kolejnosc: flaga, saplo.yaml, project.json
91
+ let appId = flags['app-id'] ?? config.app_id;
92
+ if (!appId) {
93
+ const project = getProjectConfig(cwd);
94
+ appId = project?.app_id;
95
+ }
96
+ // Brak app - znajdz istniejaca o tej nazwie lub utworz nowa.
97
+ // To sprawia ze `saplo deploy` dziala bez wczesniejszego tworzenia w panelu.
98
+ if (!appId) {
99
+ appId = await this.ensureApplication(config.name, config.stack, cwd);
100
+ }
101
+ else {
102
+ // app_id podany - sprawdz czy aplikacja istnieje. Jesli nie (np. skasowana
103
+ // albo nieaktualny app_id w saplo.yaml), sprobuj znalezc/utworzyc.
104
+ try {
105
+ await api.getApplication(appId);
106
+ }
107
+ catch {
108
+ this.log(chalk.yellow(`Aplikacja #${appId} nie istnieje - szukam lub tworze nowa.`));
109
+ appId = await this.ensureApplication(config.name, config.stack, cwd);
110
+ }
111
+ }
112
+ this.log('');
113
+ this.log(chalk.bold(`Deploying ${chalk.cyan(config.name)} to Saplo`));
114
+ this.log(chalk.dim(`Stack: ${config.stack} | App ID: ${appId}`));
115
+ this.log('');
116
+ // Package directory
117
+ const spinner = ora('Packaging files...').start();
118
+ let tarballPath;
119
+ let fileCount;
120
+ let sizeBytes;
121
+ try {
122
+ const result = await packageDirectory(cwd, { prebuilt: flags.prebuilt });
123
+ tarballPath = result.tarballPath;
124
+ fileCount = result.fileCount;
125
+ sizeBytes = result.sizeBytes;
126
+ spinner.succeed(`Packaged ${fileCount} files (${formatSize(sizeBytes)})`);
127
+ }
128
+ catch (err) {
129
+ spinner.fail('Packaging failed');
130
+ this.error(err.message);
131
+ }
132
+ // Upload
133
+ const uploadSpinner = ora('Uploading...').start();
134
+ let deploymentId;
135
+ let logsWs;
136
+ try {
137
+ const formData = new FormData();
138
+ // Stream tarball directly - no buffering in memory
139
+ formData.append('tarball', createReadStream(tarballPath), { filename: 'app.tar.gz', contentType: 'application/gzip' });
140
+ formData.append('config', JSON.stringify(config));
141
+ if (flags.prebuilt) {
142
+ formData.append('prebuilt', 'true');
143
+ }
144
+ const result = await api.createDeployment(appId, formData, formData.getHeaders());
145
+ deploymentId = result.deployment_id;
146
+ logsWs = result.logs_ws ?? null;
147
+ uploadSpinner.succeed(`Uploaded (deployment #${deploymentId})`);
148
+ }
149
+ catch (err) {
150
+ uploadSpinner.fail('Upload failed');
151
+ // Clean up tarball
152
+ try {
153
+ unlinkSync(tarballPath);
154
+ }
155
+ catch { /* ignore */ }
156
+ const errCode = err.code;
157
+ const errMsg = err.message ?? '';
158
+ if (errCode === 'EPAYLOAD' || errMsg.includes('413') || errMsg.toLowerCase().includes('too large')) {
159
+ this.error(`Paczka jest za duza (${formatSize(sizeBytes)}). Serwer odrzuca zbyt duze archiwa.\n` +
160
+ `Wyklucz zbedne pliki/katalogi dodajac je do pliku .saploignore w katalogu projektu.\n` +
161
+ `Przyklad: echo "public/uploads" >> .saploignore`);
162
+ }
163
+ this.error(err.message);
164
+ }
165
+ // Clean up tarball
166
+ try {
167
+ unlinkSync(tarballPath);
168
+ }
169
+ catch { /* ignore */ }
170
+ if (!flags['no-logs']) {
171
+ this.log('');
172
+ this.log(chalk.dim('--- Build logs ---'));
173
+ const status = await streamDeploymentLogs(deploymentId, logsWs, defaultLogHandler);
174
+ this.log(chalk.dim('--- End of logs ---'));
175
+ this.log('');
176
+ if (['success', 'running', 'live'].includes(status)) {
177
+ try {
178
+ const app = await api.getApplication(appId);
179
+ this.log(chalk.green.bold('Deploy successful!'));
180
+ if (app.url) {
181
+ this.log(` Live at: ${chalk.cyan(app.url)}`);
182
+ }
183
+ }
184
+ catch {
185
+ this.log(chalk.green.bold('Deploy successful!'));
186
+ }
187
+ }
188
+ else if (status === 'failed') {
189
+ this.error('Build failed. Check logs above for details.');
190
+ }
191
+ else if (status === 'cancelled') {
192
+ this.warn('Deployment was cancelled.');
193
+ }
194
+ else {
195
+ this.log(chalk.yellow(`Deployment status: ${status}`));
196
+ this.log(chalk.dim(`Track it with: saplo status or saplo logs --deployment ${deploymentId}`));
197
+ }
198
+ }
199
+ else {
200
+ this.log(chalk.green(`Deployment queued (#${deploymentId})`));
201
+ this.log(chalk.dim(`Track it with: saplo logs --deployment ${deploymentId}`));
202
+ }
203
+ this.log('');
204
+ }
205
+ }
206
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DomainAdd extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ domain: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'app-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/commands/domain/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAc,MAAM,aAAa,CAAA;AAKhD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,OAAgB,WAAW,SAAmD;IAE9E,OAAgB,QAAQ,WAGvB;IAED,OAAgB,IAAI;;MAKnB;IAED,OAAgB,KAAK;;MAKpB;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAwB3B"}
@@ -0,0 +1,44 @@
1
+ import { Command, Args, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { api } from '../../lib/api.js';
4
+ import { requireToken, requireProjectConfig } from '../../lib/config.js';
5
+ export default class DomainAdd extends Command {
6
+ static description = 'Add a custom domain to the current application';
7
+ static examples = [
8
+ '<%= config.bin %> domain add example.com',
9
+ '<%= config.bin %> domain add www.example.com',
10
+ ];
11
+ static args = {
12
+ domain: Args.string({
13
+ description: 'Domain name to add',
14
+ required: true,
15
+ }),
16
+ };
17
+ static flags = {
18
+ 'app-id': Flags.integer({
19
+ char: 'a',
20
+ description: 'Application ID (overrides .saplo/project.json)',
21
+ }),
22
+ };
23
+ async run() {
24
+ const { args, flags } = await this.parse(DomainAdd);
25
+ requireToken();
26
+ const appId = flags['app-id'] ?? requireProjectConfig().app_id;
27
+ const domain = args.domain;
28
+ // Basic validation
29
+ if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(domain)) {
30
+ this.error(`Invalid domain: "${domain}"`);
31
+ }
32
+ const result = await api.addDomain(appId, domain);
33
+ this.log('');
34
+ this.log(chalk.green(`Domain ${chalk.bold(domain)} added!`));
35
+ this.log('');
36
+ this.log(chalk.bold('DNS Configuration required:'));
37
+ this.log('');
38
+ this.log(result.dns_instructions);
39
+ this.log('');
40
+ this.log(chalk.dim('SSL certificate will be provisioned automatically after DNS propagates (usually 1-5 minutes).'));
41
+ this.log('');
42
+ }
43
+ }
44
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/commands/domain/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAC,MAAM,qBAAqB,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAU,WAAW,GAAG,gDAAgD,CAAA;IAE9E,MAAM,CAAU,QAAQ,GAAG;QACzB,0CAA0C;QAC1C,8CAA8C;KAC/C,CAAA;IAED,MAAM,CAAU,IAAI,GAAG;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;YAClB,WAAW,EAAE,oBAAoB;YACjC,QAAQ,EAAE,IAAI;SACf,CAAC;KACH,CAAA;IAED,MAAM,CAAU,KAAK,GAAG;QACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,gDAAgD;SAC9D,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QACjD,YAAY,EAAE,CAAA;QAEd,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC,MAAM,CAAA;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAE1B,mBAAmB;QACnB,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,KAAK,CAAC,oBAAoB,MAAM,GAAG,CAAC,CAAA;QAC3C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAEjD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;QAC5D,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAA;QACnD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;QACjC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+FAA+F,CAAC,CAAC,CAAA;QACpH,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACd,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DomainLs extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ 'app-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=ls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/commands/domain/ls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAQ,MAAM,aAAa,CAAA;AAK1C,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,OAAgB,WAAW,SAAoD;IAE/E,OAAgB,QAAQ,WAAkC;IAE1D,OAAgB,KAAK;;MAKpB;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAoB3B"}
@@ -0,0 +1,32 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { api } from '../../lib/api.js';
4
+ import { requireToken, requireProjectConfig } from '../../lib/config.js';
5
+ export default class DomainLs extends Command {
6
+ static description = 'List custom domains for the current application';
7
+ static examples = ['<%= config.bin %> domain ls'];
8
+ static flags = {
9
+ 'app-id': Flags.integer({
10
+ char: 'a',
11
+ description: 'Application ID (overrides .saplo/project.json)',
12
+ }),
13
+ };
14
+ async run() {
15
+ const { flags } = await this.parse(DomainLs);
16
+ requireToken();
17
+ const appId = flags['app-id'] ?? requireProjectConfig().app_id;
18
+ const domains = await api.listDomains(appId);
19
+ if (domains.length === 0) {
20
+ this.log(chalk.dim('No custom domains configured.'));
21
+ this.log(chalk.dim('Add one with: saplo domain add example.com'));
22
+ return;
23
+ }
24
+ this.log('');
25
+ this.log(chalk.bold('Custom domains:'));
26
+ for (const d of domains) {
27
+ this.log(` ${chalk.cyan(d)}`);
28
+ }
29
+ this.log('');
30
+ }
31
+ }
32
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/commands/domain/ls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAC,MAAM,qBAAqB,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,MAAM,CAAU,WAAW,GAAG,iDAAiD,CAAA;IAE/E,MAAM,CAAU,QAAQ,GAAG,CAAC,6BAA6B,CAAC,CAAA;IAE1D,MAAM,CAAU,KAAK,GAAG;QACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,gDAAgD;SAC9D,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAC,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAC1C,YAAY,EAAE,CAAA;QAEd,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC,MAAM,CAAA;QAC9D,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAE5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAA;YACpD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC,CAAA;YACjE,OAAM;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAA;QACvC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAChC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACd,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DomainRm extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ domain: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'app-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=rm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rm.d.ts","sourceRoot":"","sources":["../../../src/commands/domain/rm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAc,MAAM,aAAa,CAAA;AAKhD,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,OAAgB,WAAW,SAAwD;IAEnF,OAAgB,QAAQ,WAA8C;IAEtE,OAAgB,IAAI;;MAKnB;IAED,OAAgB,KAAK;;MAKpB;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3B"}
@@ -0,0 +1,29 @@
1
+ import { Command, Args, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { api } from '../../lib/api.js';
4
+ import { requireToken, requireProjectConfig } from '../../lib/config.js';
5
+ export default class DomainRm extends Command {
6
+ static description = 'Remove a custom domain from the current application';
7
+ static examples = ['<%= config.bin %> domain rm example.com'];
8
+ static args = {
9
+ domain: Args.string({
10
+ description: 'Domain name to remove',
11
+ required: true,
12
+ }),
13
+ };
14
+ static flags = {
15
+ 'app-id': Flags.integer({
16
+ char: 'a',
17
+ description: 'Application ID (overrides .saplo/project.json)',
18
+ }),
19
+ };
20
+ async run() {
21
+ const { args, flags } = await this.parse(DomainRm);
22
+ requireToken();
23
+ const appId = flags['app-id'] ?? requireProjectConfig().app_id;
24
+ await api.removeDomain(appId, args.domain);
25
+ this.log(chalk.green(`Domain ${chalk.bold(args.domain)} removed.`));
26
+ this.log(chalk.dim('Remember to update your DNS records.'));
27
+ }
28
+ }
29
+ //# sourceMappingURL=rm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rm.js","sourceRoot":"","sources":["../../../src/commands/domain/rm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAC,MAAM,qBAAqB,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,MAAM,CAAU,WAAW,GAAG,qDAAqD,CAAA;IAEnF,MAAM,CAAU,QAAQ,GAAG,CAAC,yCAAyC,CAAC,CAAA;IAEtE,MAAM,CAAU,IAAI,GAAG;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;YAClB,WAAW,EAAE,uBAAuB;YACpC,QAAQ,EAAE,IAAI;SACf,CAAC;KACH,CAAA;IAED,MAAM,CAAU,KAAK,GAAG;QACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,gDAAgD;SAC9D,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAChD,YAAY,EAAE,CAAA;QAEd,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC,MAAM,CAAA;QAE9D,MAAM,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAE1C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;QACnE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAA;IAC7D,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class EnvList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ 'app-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAQ,MAAM,aAAa,CAAA;AAK1C,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,OAAgB,WAAW,SAA2D;IAEtF,OAAgB,QAAQ,WAAiE;IAEzF,OAAgB,KAAK;;MAKpB;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuB3B"}
@@ -0,0 +1,34 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { api } from '../../lib/api.js';
4
+ import { requireToken, requireProjectConfig } from '../../lib/config.js';
5
+ export default class EnvList extends Command {
6
+ static description = 'List environment variables for the current application';
7
+ static examples = ['<%= config.bin %> env', '<%= config.bin %> env --app-id 42'];
8
+ static flags = {
9
+ 'app-id': Flags.integer({
10
+ char: 'a',
11
+ description: 'Application ID (overrides .saplo/project.json)',
12
+ }),
13
+ };
14
+ async run() {
15
+ const { flags } = await this.parse(EnvList);
16
+ requireToken();
17
+ const appId = flags['app-id'] ?? requireProjectConfig().app_id;
18
+ const vars = await api.getEnvVars(appId);
19
+ if (vars.length === 0) {
20
+ this.log(chalk.dim('No environment variables set.'));
21
+ this.log(chalk.dim('Add one with: saplo env set KEY=value'));
22
+ return;
23
+ }
24
+ this.log('');
25
+ this.log(chalk.bold(`Environment variables (${vars.length}):`));
26
+ this.log('');
27
+ for (const v of vars) {
28
+ const value = v.is_secret ? chalk.dim('[secret]') : (v.value ?? '');
29
+ this.log(` ${chalk.cyan(v.key)}=${value}`);
30
+ }
31
+ this.log('');
32
+ }
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAC,MAAM,qBAAqB,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAU,WAAW,GAAG,wDAAwD,CAAA;IAEtF,MAAM,CAAU,QAAQ,GAAG,CAAC,uBAAuB,EAAE,mCAAmC,CAAC,CAAA;IAEzF,MAAM,CAAU,KAAK,GAAG;QACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,gDAAgD;SAC9D,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAC,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACzC,YAAY,EAAE,CAAA;QAEd,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC,MAAM,CAAA;QAC9D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QAExC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAA;YACpD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAA;YAC5D,OAAM;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;QAC/D,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAEZ,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;YACnE,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAA;QAC7C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACd,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class EnvPull extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ 'app-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ output: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/commands/env/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAQ,MAAM,aAAa,CAAA;AAO1C,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,OAAgB,WAAW,SAAsD;IAEjF,OAAgB,QAAQ,WAGvB;IAED,OAAgB,KAAK;;;;MAepB;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuC3B"}