@flowershow/publish 1.1.1 → 1.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/LICENSE +661 -0
- package/README.md +6 -8
- package/dist/cli.js +43 -41
- package/dist/cli.js.map +1 -1
- package/dist/lib/api-client.d.ts +3 -3
- package/dist/lib/api-client.js +27 -27
- package/dist/lib/auth.js +28 -28
- package/dist/lib/commands/auth-login.d.ts.map +1 -1
- package/dist/lib/commands/auth-login.js +30 -27
- package/dist/lib/commands/auth-login.js.map +1 -1
- package/dist/lib/commands/auth-logout.d.ts.map +1 -1
- package/dist/lib/commands/auth-logout.js +17 -14
- package/dist/lib/commands/auth-logout.js.map +1 -1
- package/dist/lib/commands/auth-status.d.ts.map +1 -1
- package/dist/lib/commands/auth-status.js +22 -19
- package/dist/lib/commands/auth-status.js.map +1 -1
- package/dist/lib/commands/delete.js +21 -21
- package/dist/lib/commands/list.js +17 -17
- package/dist/lib/commands/publish.js +31 -31
- package/dist/lib/commands/sync.js +35 -35
- package/dist/lib/const.d.ts +1 -1
- package/dist/lib/const.d.ts.map +1 -1
- package/dist/lib/const.js +6 -5
- package/dist/lib/const.js.map +1 -1
- package/dist/lib/files.js +33 -33
- package/dist/lib/telemetry.d.ts.map +1 -1
- package/dist/lib/telemetry.js +14 -14
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/utils.d.ts +1 -1
- package/dist/lib/utils.js +14 -14
- package/dist/package.json +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Flowershow Publish
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> **Note:** This package was previously named `flowershow` (and `flowershow-publish`). If you're migrating from the old package, see the [Migration Guide](MIGRATION.md).
|
|
3
|
+
The CLI tool for publishing Markdown files with Flowershow.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
@@ -59,7 +57,7 @@ publish sync ./my-note.md
|
|
|
59
57
|
|
|
60
58
|
#### `publish auth login`
|
|
61
59
|
|
|
62
|
-
Authenticate with
|
|
60
|
+
Authenticate with Flowershow via browser OAuth flow.
|
|
63
61
|
|
|
64
62
|
```bash
|
|
65
63
|
publish auth login
|
|
@@ -87,7 +85,7 @@ See [Authentication Documentation](docs/authentication.md) for detailed informat
|
|
|
87
85
|
|
|
88
86
|
#### `publish <path> [morePaths...] [options]`
|
|
89
87
|
|
|
90
|
-
Publish files or folders to
|
|
88
|
+
Publish files or folders to Flowershow.
|
|
91
89
|
|
|
92
90
|
**Options:**
|
|
93
91
|
|
|
@@ -120,7 +118,7 @@ publish ./my-notes --name my-custom-site --overwrite
|
|
|
120
118
|
|
|
121
119
|
1. Files are discovered and filtered (ignores `.git`, `node_modules`, etc.; also supports `.gitignore` and will ignore paths listed there)
|
|
122
120
|
2. Project name is derived from the first file name or the folder name
|
|
123
|
-
3. Site is created via the
|
|
121
|
+
3. Site is created via the Flowershow API
|
|
124
122
|
4. Presigned URLs are obtained for secure file uploads
|
|
125
123
|
5. Files are uploaded directly to Cloudflare R2 storage
|
|
126
124
|
6. CLI waits for markdown files to be processed
|
|
@@ -211,7 +209,7 @@ Delete a site and all its files.
|
|
|
211
209
|
publish delete my-notes
|
|
212
210
|
```
|
|
213
211
|
|
|
214
|
-
Removes the site and all its files via the
|
|
212
|
+
Removes the site and all its files via the Flowershow API.
|
|
215
213
|
|
|
216
214
|
## File Filtering
|
|
217
215
|
|
package/dist/cli.js
CHANGED
|
@@ -1,82 +1,84 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from
|
|
3
|
-
import chalk from
|
|
4
|
-
import { publishCommand } from
|
|
5
|
-
import { syncCommand } from
|
|
6
|
-
import { listCommand } from
|
|
7
|
-
import { deleteCommand } from
|
|
8
|
-
import { authLoginCommand } from
|
|
9
|
-
import { authLogoutCommand } from
|
|
10
|
-
import { authStatusCommand } from
|
|
11
|
-
import packageJson from
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { publishCommand } from './lib/commands/publish.js';
|
|
5
|
+
import { syncCommand } from './lib/commands/sync.js';
|
|
6
|
+
import { listCommand } from './lib/commands/list.js';
|
|
7
|
+
import { deleteCommand } from './lib/commands/delete.js';
|
|
8
|
+
import { authLoginCommand } from './lib/commands/auth-login.js';
|
|
9
|
+
import { authLogoutCommand } from './lib/commands/auth-logout.js';
|
|
10
|
+
import { authStatusCommand } from './lib/commands/auth-status.js';
|
|
11
|
+
import packageJson from './package.json' with { type: 'json' };
|
|
12
12
|
const program = new Command();
|
|
13
13
|
program
|
|
14
|
-
.name(
|
|
15
|
-
.description(
|
|
16
|
-
.version(packageJson.version)
|
|
14
|
+
.name('publish')
|
|
15
|
+
.description('CLI tool for publishing to Flowershow')
|
|
16
|
+
.version(packageJson.version)
|
|
17
|
+
.enablePositionalOptions()
|
|
18
|
+
.passThroughOptions();
|
|
17
19
|
program
|
|
18
|
-
.argument(
|
|
19
|
-
.argument(
|
|
20
|
-
.option(
|
|
21
|
-
.option(
|
|
20
|
+
.argument('[path]', 'File or folder to publish')
|
|
21
|
+
.argument('[morePaths...]', 'Additional files to publish')
|
|
22
|
+
.option('--overwrite', 'Overwrite existing site if it already exists')
|
|
23
|
+
.option('--name <siteName>', 'Custom name for the site')
|
|
22
24
|
.action(async (path, morePaths, options) => {
|
|
23
25
|
if (!path) {
|
|
24
26
|
program.help();
|
|
25
27
|
return;
|
|
26
28
|
}
|
|
27
|
-
console.log(chalk.bold(
|
|
29
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - Publish\n'));
|
|
28
30
|
const paths = [path, ...morePaths];
|
|
29
31
|
await publishCommand(paths, options.overwrite || false, options.name);
|
|
30
32
|
});
|
|
31
33
|
const auth = program
|
|
32
|
-
.command(
|
|
33
|
-
.description(
|
|
34
|
+
.command('auth')
|
|
35
|
+
.description('Manage authentication')
|
|
34
36
|
.action(() => {
|
|
35
37
|
auth.help();
|
|
36
38
|
});
|
|
37
39
|
auth
|
|
38
|
-
.command(
|
|
39
|
-
.description(
|
|
40
|
+
.command('login')
|
|
41
|
+
.description('Authenticate with Flowershow via browser')
|
|
40
42
|
.action(async () => {
|
|
41
|
-
console.log(chalk.bold(
|
|
43
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - Authentication\n'));
|
|
42
44
|
await authLoginCommand();
|
|
43
45
|
});
|
|
44
46
|
auth
|
|
45
|
-
.command(
|
|
46
|
-
.description(
|
|
47
|
+
.command('logout')
|
|
48
|
+
.description('Remove stored authentication token')
|
|
47
49
|
.action(async () => {
|
|
48
|
-
console.log(chalk.bold(
|
|
50
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - Logout\n'));
|
|
49
51
|
await authLogoutCommand();
|
|
50
52
|
});
|
|
51
53
|
auth
|
|
52
|
-
.command(
|
|
53
|
-
.description(
|
|
54
|
+
.command('status')
|
|
55
|
+
.description('Check authentication status')
|
|
54
56
|
.action(async () => {
|
|
55
|
-
console.log(chalk.bold(
|
|
57
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - Auth Status\n'));
|
|
56
58
|
await authStatusCommand();
|
|
57
59
|
});
|
|
58
60
|
program
|
|
59
|
-
.command(
|
|
60
|
-
.description(
|
|
61
|
-
.option(
|
|
62
|
-
.option(
|
|
63
|
-
.option(
|
|
61
|
+
.command('sync <path>')
|
|
62
|
+
.description('Sync changes to an existing published site')
|
|
63
|
+
.option('--name <siteName>', 'Specify site name if different from folder name')
|
|
64
|
+
.option('--dry-run', 'Show what would be synced without making changes')
|
|
65
|
+
.option('--verbose', 'Show detailed list of all files in each category')
|
|
64
66
|
.action(async (path, options) => {
|
|
65
|
-
console.log(chalk.bold(
|
|
67
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - Sync\n'));
|
|
66
68
|
await syncCommand(path, options);
|
|
67
69
|
});
|
|
68
70
|
program
|
|
69
|
-
.command(
|
|
70
|
-
.description(
|
|
71
|
+
.command('list')
|
|
72
|
+
.description('List all published sites')
|
|
71
73
|
.action(async () => {
|
|
72
|
-
console.log(chalk.bold(
|
|
74
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - List Sites\n'));
|
|
73
75
|
await listCommand();
|
|
74
76
|
});
|
|
75
77
|
program
|
|
76
|
-
.command(
|
|
77
|
-
.description(
|
|
78
|
+
.command('delete <project-name>')
|
|
79
|
+
.description('Delete a published site')
|
|
78
80
|
.action(async (projectName) => {
|
|
79
|
-
console.log(chalk.bold(
|
|
81
|
+
console.log(chalk.bold('\n💐 Flowershow CLI - Delete Site\n'));
|
|
80
82
|
await deleteCommand(projectName);
|
|
81
83
|
});
|
|
82
84
|
if (process.argv.length === 2) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,WAAW,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAE/D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/api-client.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ interface Site {
|
|
|
7
7
|
updatedAt?: string;
|
|
8
8
|
fileCount?: number;
|
|
9
9
|
totalSize?: number;
|
|
10
|
-
plan?:
|
|
10
|
+
plan?: 'FREE' | 'PREMIUM';
|
|
11
11
|
}
|
|
12
12
|
interface CreateSiteResponse {
|
|
13
13
|
site: Site;
|
|
@@ -51,13 +51,13 @@ export interface SyncFilesResponse {
|
|
|
51
51
|
interface BlobStatus {
|
|
52
52
|
id: string;
|
|
53
53
|
path: string;
|
|
54
|
-
syncStatus:
|
|
54
|
+
syncStatus: 'UPLOADING' | 'PROCESSING' | 'SUCCESS' | 'ERROR';
|
|
55
55
|
syncError: string | null;
|
|
56
56
|
extension: string | null;
|
|
57
57
|
}
|
|
58
58
|
interface SiteStatusResponse {
|
|
59
59
|
siteId: string;
|
|
60
|
-
status:
|
|
60
|
+
status: 'pending' | 'complete' | 'error';
|
|
61
61
|
files: {
|
|
62
62
|
total: number;
|
|
63
63
|
pending: number;
|
package/dist/lib/api-client.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import packageJson from
|
|
3
|
-
import { getAuthHeaders } from
|
|
4
|
-
import { API_URL } from
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import packageJson from '../package.json' with { type: 'json' };
|
|
3
|
+
import { getAuthHeaders } from './auth.js';
|
|
4
|
+
import { API_URL } from './const.js';
|
|
5
5
|
async function handleOutdatedClient(response) {
|
|
6
6
|
if (response.status === 426) {
|
|
7
7
|
const data = (await response
|
|
8
8
|
.clone()
|
|
9
9
|
.json()
|
|
10
10
|
.catch(() => ({})));
|
|
11
|
-
if (data.error ===
|
|
11
|
+
if (data.error === 'client_outdated') {
|
|
12
12
|
const lines = [
|
|
13
|
-
|
|
14
|
-
chalk.red.bold(` ! Your
|
|
15
|
-
|
|
16
|
-
` This version no longer works with the
|
|
13
|
+
'',
|
|
14
|
+
chalk.red.bold(` ! Your Flowershow CLI is outdated (v${data.currentVersion}) `),
|
|
15
|
+
'',
|
|
16
|
+
` This version no longer works with the Flowershow API.`,
|
|
17
17
|
` Please upgrade to v${data.minimumVersion} or newer.`,
|
|
18
|
-
|
|
18
|
+
'',
|
|
19
19
|
chalk.cyan(` → npm install -g @flowershow/publish`),
|
|
20
|
-
|
|
20
|
+
'',
|
|
21
21
|
];
|
|
22
22
|
const width = 56;
|
|
23
|
-
const top = chalk.red(`╔${
|
|
24
|
-
const bottom = chalk.red(`╚${
|
|
25
|
-
const border = chalk.red(
|
|
23
|
+
const top = chalk.red(`╔${'═'.repeat(width)}╗`);
|
|
24
|
+
const bottom = chalk.red(`╚${'═'.repeat(width)}╝`);
|
|
25
|
+
const border = chalk.red('║');
|
|
26
26
|
console.error();
|
|
27
27
|
console.error(top);
|
|
28
28
|
for (const line of lines) {
|
|
29
29
|
const padding = width - stripAnsi(line).length;
|
|
30
|
-
console.error(`${border}${line}${
|
|
30
|
+
console.error(`${border}${line}${' '.repeat(Math.max(0, padding))}${border}`);
|
|
31
31
|
}
|
|
32
32
|
console.error(bottom);
|
|
33
33
|
console.error();
|
|
@@ -36,13 +36,13 @@ async function handleOutdatedClient(response) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
function stripAnsi(str) {
|
|
39
|
-
return str.replace(/\x1b\[[0-9;]*m/g,
|
|
39
|
+
return str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
40
40
|
}
|
|
41
41
|
export async function apiRequest(endpoint, options = {}) {
|
|
42
42
|
const authHeaders = getAuthHeaders();
|
|
43
43
|
const url = `${API_URL}${endpoint}`;
|
|
44
44
|
const headers = {
|
|
45
|
-
|
|
45
|
+
'X-Flowershow-CLI-Version': packageJson.version,
|
|
46
46
|
...options.headers,
|
|
47
47
|
...(authHeaders || {}),
|
|
48
48
|
};
|
|
@@ -54,10 +54,10 @@ export async function apiRequest(endpoint, options = {}) {
|
|
|
54
54
|
return response;
|
|
55
55
|
}
|
|
56
56
|
export async function createSite(projectName, overwrite = false) {
|
|
57
|
-
const response = await apiRequest(
|
|
58
|
-
method:
|
|
57
|
+
const response = await apiRequest('/api/sites', {
|
|
58
|
+
method: 'POST',
|
|
59
59
|
headers: {
|
|
60
|
-
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
61
|
},
|
|
62
62
|
body: JSON.stringify({ projectName, overwrite }),
|
|
63
63
|
});
|
|
@@ -68,7 +68,7 @@ export async function createSite(projectName, overwrite = false) {
|
|
|
68
68
|
return (await response.json());
|
|
69
69
|
}
|
|
70
70
|
export async function getSites() {
|
|
71
|
-
const response = await apiRequest(
|
|
71
|
+
const response = await apiRequest('/api/sites');
|
|
72
72
|
if (!response.ok) {
|
|
73
73
|
const error = (await response.json().catch(() => ({})));
|
|
74
74
|
throw new Error(error.message || `Failed to fetch sites: ${response.statusText}`);
|
|
@@ -96,7 +96,7 @@ export async function getSiteByName(username, siteName) {
|
|
|
96
96
|
}
|
|
97
97
|
export async function deleteSite(siteId) {
|
|
98
98
|
const response = await apiRequest(`/api/sites/id/${siteId}`, {
|
|
99
|
-
method:
|
|
99
|
+
method: 'DELETE',
|
|
100
100
|
});
|
|
101
101
|
if (!response.ok) {
|
|
102
102
|
const error = (await response.json().catch(() => ({})));
|
|
@@ -105,11 +105,11 @@ export async function deleteSite(siteId) {
|
|
|
105
105
|
return (await response.json());
|
|
106
106
|
}
|
|
107
107
|
export async function syncFiles(siteId, files, dryRun = false) {
|
|
108
|
-
const url = `/api/sites/id/${siteId}/sync${dryRun ?
|
|
108
|
+
const url = `/api/sites/id/${siteId}/sync${dryRun ? '?dryRun=true' : ''}`;
|
|
109
109
|
const response = await apiRequest(url, {
|
|
110
|
-
method:
|
|
110
|
+
method: 'POST',
|
|
111
111
|
headers: {
|
|
112
|
-
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
113
|
},
|
|
114
114
|
body: JSON.stringify({ files }),
|
|
115
115
|
});
|
|
@@ -121,10 +121,10 @@ export async function syncFiles(siteId, files, dryRun = false) {
|
|
|
121
121
|
}
|
|
122
122
|
export async function uploadToR2(uploadUrl, content, contentType) {
|
|
123
123
|
const response = await fetch(uploadUrl, {
|
|
124
|
-
method:
|
|
124
|
+
method: 'PUT',
|
|
125
125
|
body: content,
|
|
126
126
|
headers: {
|
|
127
|
-
|
|
127
|
+
'Content-Type': contentType,
|
|
128
128
|
},
|
|
129
129
|
});
|
|
130
130
|
if (!response.ok) {
|
package/dist/lib/auth.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { homedir } from
|
|
2
|
-
import { join } from
|
|
3
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from
|
|
4
|
-
import chalk from
|
|
5
|
-
import { API_URL } from
|
|
6
|
-
const CONFIG_DIR = join(homedir(),
|
|
7
|
-
const TOKEN_FILE = join(CONFIG_DIR,
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { API_URL } from './const.js';
|
|
6
|
+
const CONFIG_DIR = join(homedir(), '.flowershow');
|
|
7
|
+
const TOKEN_FILE = join(CONFIG_DIR, 'token.json');
|
|
8
8
|
export function saveToken(token, username) {
|
|
9
9
|
if (!existsSync(CONFIG_DIR)) {
|
|
10
10
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
@@ -14,29 +14,29 @@ export function saveToken(token, username) {
|
|
|
14
14
|
username,
|
|
15
15
|
savedAt: new Date().toISOString(),
|
|
16
16
|
};
|
|
17
|
-
writeFileSync(TOKEN_FILE, JSON.stringify(data, null, 2),
|
|
17
|
+
writeFileSync(TOKEN_FILE, JSON.stringify(data, null, 2), 'utf-8');
|
|
18
18
|
}
|
|
19
19
|
export function getToken() {
|
|
20
20
|
if (!existsSync(TOKEN_FILE)) {
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
23
23
|
try {
|
|
24
|
-
const data = readFileSync(TOKEN_FILE,
|
|
24
|
+
const data = readFileSync(TOKEN_FILE, 'utf-8');
|
|
25
25
|
return JSON.parse(data);
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
|
-
console.error(chalk.yellow(
|
|
28
|
+
console.error(chalk.yellow('Warning: Failed to read token file'));
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
export async function removeToken() {
|
|
33
33
|
if (existsSync(TOKEN_FILE)) {
|
|
34
34
|
try {
|
|
35
|
-
const fs = await import(
|
|
35
|
+
const fs = await import('fs/promises');
|
|
36
36
|
await fs.unlink(TOKEN_FILE);
|
|
37
37
|
}
|
|
38
38
|
catch (error) {
|
|
39
|
-
if (error.code !==
|
|
39
|
+
if (error.code !== 'ENOENT') {
|
|
40
40
|
throw error;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -59,55 +59,55 @@ export async function pollForToken(apiUrl, deviceCode, interval, expiresIn) {
|
|
|
59
59
|
await new Promise((resolve) => setTimeout(resolve, currentInterval * 500));
|
|
60
60
|
try {
|
|
61
61
|
const response = await fetch(`${apiUrl}/api/cli/device/token`, {
|
|
62
|
-
method:
|
|
62
|
+
method: 'POST',
|
|
63
63
|
headers: {
|
|
64
|
-
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
65
|
},
|
|
66
66
|
body: JSON.stringify({
|
|
67
67
|
device_code: deviceCode,
|
|
68
|
-
grant_type:
|
|
68
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
69
69
|
}),
|
|
70
70
|
});
|
|
71
71
|
const data = (await response.json());
|
|
72
72
|
if (response.ok && data.access_token) {
|
|
73
73
|
return data.access_token;
|
|
74
74
|
}
|
|
75
|
-
if (data.error ===
|
|
75
|
+
if (data.error === 'authorization_pending') {
|
|
76
76
|
continue;
|
|
77
77
|
}
|
|
78
|
-
if (data.error ===
|
|
78
|
+
if (data.error === 'slow_down') {
|
|
79
79
|
currentInterval += 5;
|
|
80
80
|
continue;
|
|
81
81
|
}
|
|
82
|
-
if (data.error ===
|
|
83
|
-
throw new Error(
|
|
82
|
+
if (data.error === 'expired_token') {
|
|
83
|
+
throw new Error('The device code has expired. Please try again.');
|
|
84
84
|
}
|
|
85
|
-
if (data.error ===
|
|
86
|
-
throw new Error(
|
|
85
|
+
if (data.error === 'access_denied') {
|
|
86
|
+
throw new Error('Authorization was denied.');
|
|
87
87
|
}
|
|
88
|
-
throw new Error(data.error_description || data.error ||
|
|
88
|
+
throw new Error(data.error_description || data.error || 'Unknown error occurred');
|
|
89
89
|
}
|
|
90
90
|
catch (error) {
|
|
91
91
|
if (error instanceof Error &&
|
|
92
|
-
(error.message.includes(
|
|
92
|
+
(error.message.includes('expired') || error.message.includes('denied'))) {
|
|
93
93
|
throw error;
|
|
94
94
|
}
|
|
95
95
|
continue;
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
-
throw new Error(
|
|
98
|
+
throw new Error('Authorization timed out. Please try again.');
|
|
99
99
|
}
|
|
100
100
|
export async function requireAuth() {
|
|
101
101
|
try {
|
|
102
102
|
const tokenData = getToken();
|
|
103
103
|
if (!tokenData) {
|
|
104
|
-
throw new Error(
|
|
104
|
+
throw new Error('Not authenticated');
|
|
105
105
|
}
|
|
106
106
|
return await getUserInfo(tokenData.token);
|
|
107
107
|
}
|
|
108
108
|
catch (error) {
|
|
109
|
-
displayError(
|
|
110
|
-
|
|
109
|
+
displayError('You must be authenticated to use this command.\n' +
|
|
110
|
+
'Run `publish auth login` to authenticate.');
|
|
111
111
|
process.exit(0);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
@@ -118,7 +118,7 @@ export async function getUserInfo(token) {
|
|
|
118
118
|
},
|
|
119
119
|
});
|
|
120
120
|
if (!response.ok) {
|
|
121
|
-
throw new Error(
|
|
121
|
+
throw new Error('Failed to get user info');
|
|
122
122
|
}
|
|
123
123
|
return (await response.json());
|
|
124
124
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-login.d.ts","sourceRoot":"","sources":["../../../lib/commands/auth-login.ts"],"names":[],"mappings":"AAmBA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"auth-login.d.ts","sourceRoot":"","sources":["../../../lib/commands/auth-login.ts"],"names":[],"mappings":"AAmBA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiHtD"}
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import ora from
|
|
3
|
-
import { saveToken, pollForToken, getUserInfo } from
|
|
4
|
-
import { displayError } from
|
|
5
|
-
import { API_URL } from
|
|
6
|
-
import { capture, flushTelemetry, CLI_VERSION } from
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { saveToken, pollForToken, getUserInfo } from '../auth.js';
|
|
4
|
+
import { displayError } from '../utils.js';
|
|
5
|
+
import { API_URL } from '../const.js';
|
|
6
|
+
import { capture, flushTelemetry, CLI_VERSION } from '../telemetry.js';
|
|
7
7
|
export async function authLoginCommand() {
|
|
8
8
|
const startTime = Date.now();
|
|
9
|
-
capture(
|
|
9
|
+
capture('command_started', {
|
|
10
|
+
command: 'auth_login',
|
|
11
|
+
cli_version: CLI_VERSION,
|
|
12
|
+
});
|
|
10
13
|
try {
|
|
11
|
-
const spinner = ora(
|
|
14
|
+
const spinner = ora('Initiating authentication...').start();
|
|
12
15
|
const response = await fetch(`${API_URL}/api/cli/device/authorize`, {
|
|
13
|
-
method:
|
|
16
|
+
method: 'POST',
|
|
14
17
|
headers: {
|
|
15
|
-
|
|
18
|
+
'Content-Type': 'application/json',
|
|
16
19
|
},
|
|
17
20
|
body: JSON.stringify({
|
|
18
|
-
client_name:
|
|
21
|
+
client_name: 'flowershow-cli',
|
|
19
22
|
}),
|
|
20
23
|
});
|
|
21
24
|
if (!response.ok) {
|
|
@@ -24,44 +27,44 @@ export async function authLoginCommand() {
|
|
|
24
27
|
const data = (await response.json());
|
|
25
28
|
const { device_code, user_code, verification_uri, verification_uri_complete, expires_in, interval, } = data;
|
|
26
29
|
spinner.stop();
|
|
27
|
-
console.log(chalk.bold(
|
|
30
|
+
console.log(chalk.bold('\nPlease complete authentication in your browser:\n'));
|
|
28
31
|
console.log(chalk.cyan(` ${verification_uri_complete || verification_uri}\n`));
|
|
29
32
|
if (!verification_uri_complete) {
|
|
30
|
-
console.log(chalk.bold(
|
|
33
|
+
console.log(chalk.bold('Enter this code when prompted:\n'));
|
|
31
34
|
console.log(chalk.green.bold(` ${user_code}\n`));
|
|
32
35
|
}
|
|
33
36
|
console.log(chalk.gray(`This code expires in ${Math.floor(expires_in / 60)} minutes\n`));
|
|
34
|
-
spinner.start(
|
|
37
|
+
spinner.start('Waiting for authorization...');
|
|
35
38
|
const accessToken = await pollForToken(API_URL, device_code, interval, expires_in);
|
|
36
39
|
const user = await getUserInfo(accessToken);
|
|
37
|
-
saveToken(accessToken, user.username || user.email ||
|
|
38
|
-
spinner.succeed(
|
|
39
|
-
capture(
|
|
40
|
-
command:
|
|
40
|
+
saveToken(accessToken, user.username || user.email || 'user');
|
|
41
|
+
spinner.succeed('Successfully authenticated!');
|
|
42
|
+
capture('command_succeeded', {
|
|
43
|
+
command: 'auth_login',
|
|
41
44
|
cli_version: CLI_VERSION,
|
|
42
45
|
duration_ms: Date.now() - startTime,
|
|
43
46
|
});
|
|
44
|
-
console.log(chalk.gray(`Logged in as: ${chalk.cyan(user.username || user.email ||
|
|
45
|
-
console.log(chalk.gray(
|
|
47
|
+
console.log(chalk.gray(`Logged in as: ${chalk.cyan(user.username || user.email || 'user')}`));
|
|
48
|
+
console.log(chalk.gray('\nYou can now use the CLI to publish your sites.\n'));
|
|
46
49
|
}
|
|
47
50
|
catch (error) {
|
|
48
|
-
capture(
|
|
49
|
-
command:
|
|
51
|
+
capture('command_failed', {
|
|
52
|
+
command: 'auth_login',
|
|
50
53
|
cli_version: CLI_VERSION,
|
|
51
54
|
duration_ms: Date.now() - startTime,
|
|
52
|
-
error_type: error instanceof Error ? error.constructor.name :
|
|
55
|
+
error_type: error instanceof Error ? error.constructor.name : 'Unknown',
|
|
53
56
|
error_message: error instanceof Error ? error.message : String(error),
|
|
54
57
|
});
|
|
55
|
-
if (error instanceof Error && error.message.includes(
|
|
56
|
-
displayError(
|
|
57
|
-
|
|
58
|
+
if (error instanceof Error && error.message.includes('fetch')) {
|
|
59
|
+
displayError('Failed to connect to Flowershow API.\n' +
|
|
60
|
+
'Please check your internet connection and try again.');
|
|
58
61
|
}
|
|
59
62
|
else if (error instanceof Error) {
|
|
60
63
|
displayError(error.message);
|
|
61
64
|
console.error(chalk.gray(error.stack));
|
|
62
65
|
}
|
|
63
66
|
else {
|
|
64
|
-
displayError(
|
|
67
|
+
displayError('An unknown error occurred');
|
|
65
68
|
}
|
|
66
69
|
await flushTelemetry();
|
|
67
70
|
process.exit(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-login.js","sourceRoot":"","sources":["../../../lib/commands/auth-login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAcvE,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,OAAO,CAAC,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"auth-login.js","sourceRoot":"","sources":["../../../lib/commands/auth-login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAcvE,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,OAAO,CAAC,iBAAiB,EAAE;QACzB,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE,WAAW;KACzB,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,GAAG,CAAC,8BAA8B,CAAC,CAAC,KAAK,EAAE,CAAC;QAG5D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,2BAA2B,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,WAAW,EAAE,gBAAgB;aAC9B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,sCAAsC,QAAQ,CAAC,UAAU,EAAE,CAC5D,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;QAC3D,MAAM,EACJ,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,yBAAyB,EACzB,UAAU,EACV,QAAQ,GACT,GAAG,IAAI,CAAC;QAET,OAAO,CAAC,IAAI,EAAE,CAAC;QAGf,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAClE,CAAC;QACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,KAAK,yBAAyB,IAAI,gBAAgB,IAAI,CAAC,CACnE,CAAC;QAEF,IAAI,CAAC,yBAAyB,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CACR,wBAAwB,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,YAAY,CAChE,CACF,CAAC;QAEF,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAG9C,MAAM,WAAW,GAAG,MAAM,YAAY,CACpC,OAAO,EACP,WAAW,EACX,QAAQ,EACR,UAAU,CACX,CAAC;QAGF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;QAG5C,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;QAE9D,OAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAG/C,OAAO,CAAC,mBAAmB,EAAE;YAC3B,OAAO,EAAE,YAAY;YACrB,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACpC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CACR,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,CACrE,CACF,CAAC;QACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CACjE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,gBAAgB,EAAE;YACxB,OAAO,EAAE,YAAY;YACrB,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YACnC,UAAU,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACvE,aAAa,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SACtE,CAAC,CAAC;QACH,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9D,YAAY,CACV,wCAAwC;gBACtC,sDAAsD,CACzD,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAClC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,2BAA2B,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,cAAc,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;YAAS,CAAC;QACT,MAAM,cAAc,EAAE,CAAC;IACzB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-logout.d.ts","sourceRoot":"","sources":["../../../lib/commands/auth-logout.ts"],"names":[],"mappings":"AAQA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"auth-logout.d.ts","sourceRoot":"","sources":["../../../lib/commands/auth-logout.ts"],"names":[],"mappings":"AAQA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CvD"}
|