@ollie-shop/cli 0.3.3 → 1.0.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.
- package/.turbo/turbo-build.log +6 -9
- package/CHANGELOG.md +27 -0
- package/dist/index.js +1003 -40565
- package/package.json +15 -37
- package/src/README.md +126 -0
- package/src/cli.tsx +45 -0
- package/src/commands/help.tsx +79 -0
- package/src/commands/login.tsx +92 -0
- package/src/commands/start.tsx +411 -0
- package/src/index.tsx +8 -0
- package/src/utils/auth.ts +218 -21
- package/src/utils/bundle.ts +177 -0
- package/src/utils/config.ts +123 -0
- package/src/utils/esbuild.ts +533 -0
- package/tsconfig.json +10 -15
- package/tsup.config.ts +8 -10
- package/CLAUDE_CLI.md +0 -265
- package/README.md +0 -711
- package/__tests__/mocks/console.ts +0 -22
- package/__tests__/mocks/core.ts +0 -137
- package/__tests__/mocks/index.ts +0 -4
- package/__tests__/mocks/inquirer.ts +0 -16
- package/__tests__/mocks/progress.ts +0 -19
- package/dist/index.d.ts +0 -1
- package/src/__tests__/helpers/cli-test-helper.ts +0 -281
- package/src/__tests__/mocks/index.ts +0 -142
- package/src/actions/component.actions.ts +0 -278
- package/src/actions/function.actions.ts +0 -220
- package/src/actions/project.actions.ts +0 -131
- package/src/actions/version.actions.ts +0 -233
- package/src/commands/__tests__/component-validation.test.ts +0 -250
- package/src/commands/__tests__/component.test.ts +0 -318
- package/src/commands/__tests__/function-validation.test.ts +0 -220
- package/src/commands/__tests__/function.test.ts +0 -286
- package/src/commands/__tests__/store-version-validation.test.ts +0 -414
- package/src/commands/__tests__/store-version.test.ts +0 -402
- package/src/commands/component.ts +0 -178
- package/src/commands/docs.ts +0 -24
- package/src/commands/function.ts +0 -201
- package/src/commands/help.ts +0 -18
- package/src/commands/index.ts +0 -27
- package/src/commands/login.ts +0 -267
- package/src/commands/project.ts +0 -107
- package/src/commands/store-version.ts +0 -242
- package/src/commands/version.ts +0 -51
- package/src/commands/whoami.ts +0 -46
- package/src/index.ts +0 -116
- package/src/prompts/component.prompts.ts +0 -94
- package/src/prompts/function.prompts.ts +0 -168
- package/src/schemas/command.schema.ts +0 -644
- package/src/types/index.ts +0 -183
- package/src/utils/__tests__/command-parser.test.ts +0 -159
- package/src/utils/__tests__/command-suggestions.test.ts +0 -185
- package/src/utils/__tests__/console.test.ts +0 -192
- package/src/utils/__tests__/context-detector.test.ts +0 -258
- package/src/utils/__tests__/enhanced-error-handler.test.ts +0 -137
- package/src/utils/__tests__/error-handler.test.ts +0 -107
- package/src/utils/__tests__/rich-progress.test.ts +0 -181
- package/src/utils/__tests__/validation-error-formatter.test.ts +0 -175
- package/src/utils/__tests__/validation-helpers.test.ts +0 -125
- package/src/utils/cli-progress-reporter.ts +0 -84
- package/src/utils/command-builder.ts +0 -390
- package/src/utils/command-helpers.ts +0 -83
- package/src/utils/command-parser.ts +0 -245
- package/src/utils/command-suggestions.ts +0 -176
- package/src/utils/console.ts +0 -320
- package/src/utils/constants.ts +0 -39
- package/src/utils/context-detector.ts +0 -177
- package/src/utils/deploy-helpers.ts +0 -357
- package/src/utils/enhanced-error-handler.ts +0 -264
- package/src/utils/error-handler.ts +0 -60
- package/src/utils/errors.ts +0 -256
- package/src/utils/interactive-builder.ts +0 -325
- package/src/utils/rich-progress.ts +0 -331
- package/src/utils/store.ts +0 -23
- package/src/utils/validation-error-formatter.ts +0 -337
- package/src/utils/validation-helpers.ts +0 -325
- package/vitest.config.ts +0 -35
- package/vitest.setup.ts +0 -29
package/package.json
CHANGED
|
@@ -1,43 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ollie-shop/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Ollie Shop CLI for
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Ollie Shop CLI - Development tools for custom checkouts",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
7
8
|
"bin": {
|
|
8
9
|
"ollieshop": "dist/index.js"
|
|
9
10
|
},
|
|
10
11
|
"dependencies": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"esbuild": "^0.19.8",
|
|
16
|
-
"glob": "^8.1.0",
|
|
17
|
-
"inquirer": "^8.2.6",
|
|
12
|
+
"archiver": "^7.0.1",
|
|
13
|
+
"esbuild": "^0.24.0",
|
|
14
|
+
"glob": "^11.0.0",
|
|
15
|
+
"ink": "^5.0.1",
|
|
18
16
|
"jwt-decode": "^4.0.0",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"semver": "^7.5.4",
|
|
23
|
-
"zod": "^3.22.4"
|
|
17
|
+
"open": "^10.1.0",
|
|
18
|
+
"react": "^18.3.1",
|
|
19
|
+
"zod": "^3.24.2"
|
|
24
20
|
},
|
|
25
21
|
"devDependencies": {
|
|
26
|
-
"@
|
|
27
|
-
"@
|
|
28
|
-
"@types/cli-progress": "^3.11.6",
|
|
29
|
-
"@types/inquirer": "^8.2.10",
|
|
22
|
+
"@types/archiver": "^6.0.3",
|
|
23
|
+
"@types/ink": "^2.0.3",
|
|
30
24
|
"@types/node": "^22.15.23",
|
|
31
|
-
"@types/
|
|
32
|
-
"@vitest/coverage-v8": "3.0.4",
|
|
33
|
-
"fishery": "^2.3.1",
|
|
34
|
-
"msw": "^2.10.3",
|
|
25
|
+
"@types/react": "^18.3.12",
|
|
35
26
|
"tsup": "^8.0.1",
|
|
36
|
-
"typescript": "^5.7.3"
|
|
37
|
-
"vitest": "^3.0.4",
|
|
38
|
-
"vitest-mock-extended": "^3.1.0",
|
|
39
|
-
"wait-for-expect": "^3.0.2",
|
|
40
|
-
"@ollie-shop/core": "1.0.2"
|
|
27
|
+
"typescript": "^5.7.3"
|
|
41
28
|
},
|
|
42
29
|
"publishConfig": {
|
|
43
30
|
"access": "public",
|
|
@@ -45,15 +32,6 @@
|
|
|
45
32
|
},
|
|
46
33
|
"scripts": {
|
|
47
34
|
"build": "tsup",
|
|
48
|
-
"dev": "tsup --watch"
|
|
49
|
-
"test": "vitest",
|
|
50
|
-
"test:coverage": "vitest run --coverage",
|
|
51
|
-
"lint": "eslint src/**/*.ts",
|
|
52
|
-
"type-check": "tsc --noEmit",
|
|
53
|
-
"cli": "npm run build && node dist/index.js",
|
|
54
|
-
"cli:help": "npm run cli -- --help",
|
|
55
|
-
"cli:version": "npm run cli -- --version",
|
|
56
|
-
"cli:component": "npm run cli -- component",
|
|
57
|
-
"cli:function": "npm run cli -- function"
|
|
35
|
+
"dev": "tsup --watch"
|
|
58
36
|
}
|
|
59
37
|
}
|
package/src/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# CLI Development Server
|
|
2
|
+
|
|
3
|
+
The CLI provides a local development server for building and serving custom components with hot reload capabilities.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ CLI (localhost:4000) │
|
|
10
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
11
|
+
│ │
|
|
12
|
+
│ ┌──────────────┐ ┌─────────────────┐ ┌───────────────────┐ │
|
|
13
|
+
│ │ Component │ │ esbuild │ │ Static Server │ │
|
|
14
|
+
│ │ Discovery │───▶│ Context │───▶│ (serve files) │ │
|
|
15
|
+
│ │ │ │ (watch+build) │ │ │ │
|
|
16
|
+
│ └──────────────┘ └────────┬────────┘ └───────────────────┘ │
|
|
17
|
+
│ │ │
|
|
18
|
+
│ │ SSE events │
|
|
19
|
+
│ ▼ │
|
|
20
|
+
│ ┌─────────────────┐ │
|
|
21
|
+
│ │ /esbuild │ │
|
|
22
|
+
│ │ (EventSource) │ │
|
|
23
|
+
│ └─────────────────┘ │
|
|
24
|
+
│ │
|
|
25
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Endpoints
|
|
29
|
+
|
|
30
|
+
| Endpoint | Description |
|
|
31
|
+
|----------|-------------|
|
|
32
|
+
| `GET /<component>/index.js` | Built component JS source |
|
|
33
|
+
| `GET /<component>/index.js.map` | Source map |
|
|
34
|
+
| `GET /<component>/index.css` | Component CSS (if any) |
|
|
35
|
+
| `GET /manifest.json` | Component manifest with IDs and metadata |
|
|
36
|
+
| `GET /esbuild` | Server-Sent Events for live reload |
|
|
37
|
+
|
|
38
|
+
## Component Discovery
|
|
39
|
+
|
|
40
|
+
Components are discovered from `./components/<name>/index.tsx`:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
components/
|
|
44
|
+
├── Header/
|
|
45
|
+
│ ├── index.tsx # Entry point (required)
|
|
46
|
+
│ └── meta.json # Metadata (optional)
|
|
47
|
+
├── Footer/
|
|
48
|
+
│ ├── index.tsx
|
|
49
|
+
│ └── meta.json
|
|
50
|
+
└── LocalOnly/
|
|
51
|
+
└── index.tsx # No meta.json = local-only component
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### meta.json Schema
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"id": "uuid-from-database", // Optional: links to deployed component
|
|
59
|
+
"slot": "header" // Optional: target slot for local components
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- Components WITH `id`: Override an existing deployed component
|
|
64
|
+
- Components WITHOUT `id`: Local-only, need `slot` to be placed in checkout
|
|
65
|
+
|
|
66
|
+
## Manifest Format
|
|
67
|
+
|
|
68
|
+
The CLI generates `/manifest.json` after each build:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
[
|
|
72
|
+
{
|
|
73
|
+
"id": "abc-123", // Component ID (from meta.json or generated)
|
|
74
|
+
"name": "Header", // Folder name
|
|
75
|
+
"js": "/Header/index.js", // JS path (always has leading slash)
|
|
76
|
+
"css": "/Header/index.css", // CSS path (optional)
|
|
77
|
+
"slot": "header", // Target slot (optional)
|
|
78
|
+
"isLocal": false // true if no meta.json id
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## SSE Change Events
|
|
84
|
+
|
|
85
|
+
The `/esbuild` endpoint emits events when files change:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"added": ["NewComponent/index.js"],
|
|
90
|
+
"removed": [],
|
|
91
|
+
"updated": ["Header/index.js"] // Note: NO leading slash
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Important:** Paths in SSE events do NOT have leading slashes, while paths in manifest.json DO have leading slashes. Consumers must handle both formats.
|
|
96
|
+
|
|
97
|
+
## Build Configuration
|
|
98
|
+
|
|
99
|
+
esbuild is configured to match production:
|
|
100
|
+
|
|
101
|
+
- **Format:** CommonJS (`module.exports.default`)
|
|
102
|
+
- **Platform:** Browser
|
|
103
|
+
- **Target:** ES2020
|
|
104
|
+
- **Externals:** react, react-dom, next, @ollie-shop/sdk, next-intl
|
|
105
|
+
- **Output:** `node_modules/.ollie/build/<component>/index.js`
|
|
106
|
+
|
|
107
|
+
## Flow Sequence
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
1. CLI starts
|
|
111
|
+
└─▶ Discover components in ./components/
|
|
112
|
+
└─▶ Create esbuild context with entry points
|
|
113
|
+
└─▶ Initial build (writes JS + manifest)
|
|
114
|
+
└─▶ Start serve + watch mode on port 4000
|
|
115
|
+
|
|
116
|
+
2. File changes detected
|
|
117
|
+
└─▶ esbuild rebuilds affected components
|
|
118
|
+
└─▶ manifest-plugin re-discovers components
|
|
119
|
+
└─▶ manifest.json updated
|
|
120
|
+
└─▶ SSE emits "change" event with paths
|
|
121
|
+
|
|
122
|
+
3. Consumer receives SSE event
|
|
123
|
+
└─▶ Fetch updated /manifest.json
|
|
124
|
+
└─▶ Fetch component source from /<name>/index.js
|
|
125
|
+
└─▶ Forward to checkout via postMessage
|
|
126
|
+
```
|
package/src/cli.tsx
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Box, Text } from "ink";
|
|
2
|
+
import { HelpCommand } from "./commands/help.js";
|
|
3
|
+
import { LoginCommand } from "./commands/login.js";
|
|
4
|
+
import { StartCommand } from "./commands/start.js";
|
|
5
|
+
|
|
6
|
+
interface AppProps {
|
|
7
|
+
command: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function App({ command, args }: AppProps) {
|
|
12
|
+
switch (command) {
|
|
13
|
+
case "login":
|
|
14
|
+
return <LoginCommand args={args} />;
|
|
15
|
+
case "start":
|
|
16
|
+
return <StartCommand args={args} />;
|
|
17
|
+
case "help":
|
|
18
|
+
case "--help":
|
|
19
|
+
case "-h":
|
|
20
|
+
return <HelpCommand />;
|
|
21
|
+
case "version":
|
|
22
|
+
case "--version":
|
|
23
|
+
case "-v":
|
|
24
|
+
return <VersionCommand />;
|
|
25
|
+
default:
|
|
26
|
+
return <UnknownCommand command={command} />;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function VersionCommand() {
|
|
31
|
+
return (
|
|
32
|
+
<Box>
|
|
33
|
+
<Text>ollie v0.1.0</Text>
|
|
34
|
+
</Box>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function UnknownCommand({ command }: { command: string }) {
|
|
39
|
+
return (
|
|
40
|
+
<Box flexDirection="column" gap={1}>
|
|
41
|
+
<Text color="red">Unknown command: {command}</Text>
|
|
42
|
+
<Text dimColor>Run `ollie help` for available commands.</Text>
|
|
43
|
+
</Box>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Box, Text } from "ink";
|
|
2
|
+
|
|
3
|
+
export function HelpCommand() {
|
|
4
|
+
return (
|
|
5
|
+
<Box flexDirection="column" gap={1}>
|
|
6
|
+
<Box marginBottom={1}>
|
|
7
|
+
<Text bold color="cyan">
|
|
8
|
+
Ollie CLI
|
|
9
|
+
</Text>
|
|
10
|
+
<Text dimColor> - Development tools for custom checkouts</Text>
|
|
11
|
+
</Box>
|
|
12
|
+
|
|
13
|
+
<Text bold>Usage:</Text>
|
|
14
|
+
<Box marginLeft={2} flexDirection="column">
|
|
15
|
+
<Text>ollieshop {"<command>"} [options]</Text>
|
|
16
|
+
</Box>
|
|
17
|
+
|
|
18
|
+
<Box marginTop={1}>
|
|
19
|
+
<Text bold>Commands:</Text>
|
|
20
|
+
</Box>
|
|
21
|
+
<Box marginLeft={2} flexDirection="column" gap={0}>
|
|
22
|
+
<Box>
|
|
23
|
+
<Box width={16}>
|
|
24
|
+
<Text color="green">login</Text>
|
|
25
|
+
</Box>
|
|
26
|
+
<Text>Authenticate with your Ollie Shop account</Text>
|
|
27
|
+
</Box>
|
|
28
|
+
<Box>
|
|
29
|
+
<Box width={16}>
|
|
30
|
+
<Text color="green">start</Text>
|
|
31
|
+
</Box>
|
|
32
|
+
<Text>Start the development server with hot reload</Text>
|
|
33
|
+
</Box>
|
|
34
|
+
<Box>
|
|
35
|
+
<Box width={16}>
|
|
36
|
+
<Text color="green">help</Text>
|
|
37
|
+
</Box>
|
|
38
|
+
<Text>Show this help message</Text>
|
|
39
|
+
</Box>
|
|
40
|
+
<Box>
|
|
41
|
+
<Box width={16}>
|
|
42
|
+
<Text color="green">version</Text>
|
|
43
|
+
</Box>
|
|
44
|
+
<Text>Show CLI version</Text>
|
|
45
|
+
</Box>
|
|
46
|
+
</Box>
|
|
47
|
+
|
|
48
|
+
<Box marginTop={1}>
|
|
49
|
+
<Text bold>Start Options:</Text>
|
|
50
|
+
</Box>
|
|
51
|
+
<Box marginLeft={2} flexDirection="column" gap={0}>
|
|
52
|
+
<Box>
|
|
53
|
+
<Box width={20}>
|
|
54
|
+
<Text color="yellow">--stage, -s</Text>
|
|
55
|
+
</Box>
|
|
56
|
+
<Text>Config stage (loads ollie.{"{stage}"}.json)</Text>
|
|
57
|
+
</Box>
|
|
58
|
+
</Box>
|
|
59
|
+
|
|
60
|
+
<Box marginTop={1}>
|
|
61
|
+
<Text bold>Configuration:</Text>
|
|
62
|
+
</Box>
|
|
63
|
+
<Box marginLeft={2} flexDirection="column">
|
|
64
|
+
<Text dimColor>ollie.json - Default config (prod)</Text>
|
|
65
|
+
<Text dimColor>ollie.dev.json - Dev stage config</Text>
|
|
66
|
+
<Text dimColor>ollie.{"{stage}"}.json - Custom stage config</Text>
|
|
67
|
+
</Box>
|
|
68
|
+
|
|
69
|
+
<Box marginTop={1}>
|
|
70
|
+
<Text bold>Examples:</Text>
|
|
71
|
+
</Box>
|
|
72
|
+
<Box marginLeft={2} flexDirection="column">
|
|
73
|
+
<Text dimColor>$ ollieshop login</Text>
|
|
74
|
+
<Text dimColor>$ ollieshop start</Text>
|
|
75
|
+
<Text dimColor>$ ollieshop start --stage dev</Text>
|
|
76
|
+
</Box>
|
|
77
|
+
</Box>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Box, Text, useApp } from "ink";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { saveCredentials, startWebAuthFlow } from "../utils/auth.js";
|
|
4
|
+
|
|
5
|
+
interface LoginCommandProps {
|
|
6
|
+
args: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type LoginState =
|
|
10
|
+
| { status: "idle" }
|
|
11
|
+
| { status: "waiting" }
|
|
12
|
+
| { status: "success"; email: string }
|
|
13
|
+
| { status: "error"; message: string };
|
|
14
|
+
|
|
15
|
+
export function LoginCommand({ args }: LoginCommandProps) {
|
|
16
|
+
const { exit } = useApp();
|
|
17
|
+
const [state, setState] = useState<LoginState>({ status: "idle" });
|
|
18
|
+
|
|
19
|
+
// Parse args for --port
|
|
20
|
+
const portIndex = args.findIndex((a) => a === "--port" || a === "-p");
|
|
21
|
+
const port =
|
|
22
|
+
portIndex !== -1 ? Number.parseInt(args[portIndex + 1], 10) : 7777;
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (state.status !== "idle") return;
|
|
26
|
+
|
|
27
|
+
setState({ status: "waiting" });
|
|
28
|
+
|
|
29
|
+
startWebAuthFlow({ port })
|
|
30
|
+
.then(async (token) => {
|
|
31
|
+
if (token) {
|
|
32
|
+
await saveCredentials(token);
|
|
33
|
+
setState({ status: "success", email: token.email || "unknown" });
|
|
34
|
+
} else {
|
|
35
|
+
setState({ status: "error", message: "Authentication failed" });
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
.catch((error) => {
|
|
39
|
+
setState({
|
|
40
|
+
status: "error",
|
|
41
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}, [state.status, port]);
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (state.status === "success" || state.status === "error") {
|
|
48
|
+
const timer = setTimeout(() => exit(), 1000);
|
|
49
|
+
return () => clearTimeout(timer);
|
|
50
|
+
}
|
|
51
|
+
}, [state.status, exit]);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Box flexDirection="column" gap={1}>
|
|
55
|
+
<Box>
|
|
56
|
+
<Text bold color="cyan">
|
|
57
|
+
Ollie Login
|
|
58
|
+
</Text>
|
|
59
|
+
</Box>
|
|
60
|
+
|
|
61
|
+
{state.status === "waiting" && (
|
|
62
|
+
<Box flexDirection="column" gap={1}>
|
|
63
|
+
<Box>
|
|
64
|
+
<Text color="yellow">⏳ </Text>
|
|
65
|
+
<Text>Waiting for authentication in browser...</Text>
|
|
66
|
+
</Box>
|
|
67
|
+
<Text dimColor>
|
|
68
|
+
A browser window should open. Complete the login there.
|
|
69
|
+
</Text>
|
|
70
|
+
<Text dimColor>Listening on port {port}</Text>
|
|
71
|
+
</Box>
|
|
72
|
+
)}
|
|
73
|
+
|
|
74
|
+
{state.status === "success" && (
|
|
75
|
+
<Box>
|
|
76
|
+
<Text color="green">✓ </Text>
|
|
77
|
+
<Text>Successfully logged in as </Text>
|
|
78
|
+
<Text bold>{state.email}</Text>
|
|
79
|
+
</Box>
|
|
80
|
+
)}
|
|
81
|
+
|
|
82
|
+
{state.status === "error" && (
|
|
83
|
+
<Box flexDirection="column">
|
|
84
|
+
<Box>
|
|
85
|
+
<Text color="red">✗ </Text>
|
|
86
|
+
<Text color="red">Login failed: {state.message}</Text>
|
|
87
|
+
</Box>
|
|
88
|
+
</Box>
|
|
89
|
+
)}
|
|
90
|
+
</Box>
|
|
91
|
+
);
|
|
92
|
+
}
|