@ollie-shop/cli 0.3.4 → 1.0.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.
Files changed (79) hide show
  1. package/.turbo/turbo-build.log +6 -9
  2. package/CHANGELOG.md +27 -0
  3. package/dist/index.js +993 -3956
  4. package/package.json +15 -37
  5. package/src/README.md +126 -0
  6. package/src/cli.tsx +45 -0
  7. package/src/commands/help.tsx +79 -0
  8. package/src/commands/login.tsx +92 -0
  9. package/src/commands/start.tsx +411 -0
  10. package/src/index.tsx +8 -0
  11. package/src/utils/auth.ts +218 -21
  12. package/src/utils/bundle.ts +177 -0
  13. package/src/utils/config.ts +123 -0
  14. package/src/utils/esbuild.ts +541 -0
  15. package/tsconfig.json +10 -15
  16. package/tsup.config.ts +7 -7
  17. package/CLAUDE_CLI.md +0 -265
  18. package/README.md +0 -711
  19. package/__tests__/mocks/console.ts +0 -22
  20. package/__tests__/mocks/core.ts +0 -137
  21. package/__tests__/mocks/index.ts +0 -4
  22. package/__tests__/mocks/inquirer.ts +0 -16
  23. package/__tests__/mocks/progress.ts +0 -19
  24. package/dist/index.d.ts +0 -1
  25. package/src/__tests__/helpers/cli-test-helper.ts +0 -281
  26. package/src/__tests__/mocks/index.ts +0 -142
  27. package/src/actions/component.actions.ts +0 -278
  28. package/src/actions/function.actions.ts +0 -220
  29. package/src/actions/project.actions.ts +0 -131
  30. package/src/actions/version.actions.ts +0 -233
  31. package/src/commands/__tests__/component-validation.test.ts +0 -250
  32. package/src/commands/__tests__/component.test.ts +0 -318
  33. package/src/commands/__tests__/function-validation.test.ts +0 -220
  34. package/src/commands/__tests__/function.test.ts +0 -286
  35. package/src/commands/__tests__/store-version-validation.test.ts +0 -414
  36. package/src/commands/__tests__/store-version.test.ts +0 -402
  37. package/src/commands/component.ts +0 -178
  38. package/src/commands/docs.ts +0 -24
  39. package/src/commands/function.ts +0 -201
  40. package/src/commands/help.ts +0 -18
  41. package/src/commands/index.ts +0 -27
  42. package/src/commands/login.ts +0 -267
  43. package/src/commands/project.ts +0 -107
  44. package/src/commands/store-version.ts +0 -242
  45. package/src/commands/version.ts +0 -51
  46. package/src/commands/whoami.ts +0 -46
  47. package/src/index.ts +0 -116
  48. package/src/prompts/component.prompts.ts +0 -94
  49. package/src/prompts/function.prompts.ts +0 -168
  50. package/src/schemas/command.schema.ts +0 -644
  51. package/src/types/index.ts +0 -183
  52. package/src/utils/__tests__/command-parser.test.ts +0 -159
  53. package/src/utils/__tests__/command-suggestions.test.ts +0 -185
  54. package/src/utils/__tests__/console.test.ts +0 -192
  55. package/src/utils/__tests__/context-detector.test.ts +0 -258
  56. package/src/utils/__tests__/enhanced-error-handler.test.ts +0 -137
  57. package/src/utils/__tests__/error-handler.test.ts +0 -107
  58. package/src/utils/__tests__/rich-progress.test.ts +0 -181
  59. package/src/utils/__tests__/validation-error-formatter.test.ts +0 -175
  60. package/src/utils/__tests__/validation-helpers.test.ts +0 -125
  61. package/src/utils/cli-progress-reporter.ts +0 -84
  62. package/src/utils/command-builder.ts +0 -390
  63. package/src/utils/command-helpers.ts +0 -83
  64. package/src/utils/command-parser.ts +0 -245
  65. package/src/utils/command-suggestions.ts +0 -176
  66. package/src/utils/console.ts +0 -320
  67. package/src/utils/constants.ts +0 -39
  68. package/src/utils/context-detector.ts +0 -177
  69. package/src/utils/deploy-helpers.ts +0 -357
  70. package/src/utils/enhanced-error-handler.ts +0 -264
  71. package/src/utils/error-handler.ts +0 -60
  72. package/src/utils/errors.ts +0 -256
  73. package/src/utils/interactive-builder.ts +0 -325
  74. package/src/utils/rich-progress.ts +0 -331
  75. package/src/utils/store.ts +0 -23
  76. package/src/utils/validation-error-formatter.ts +0 -337
  77. package/src/utils/validation-helpers.ts +0 -325
  78. package/vitest.config.ts +0 -35
  79. 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.3.4",
4
- "description": "Ollie Shop CLI for building custom checkouts",
3
+ "version": "1.0.1",
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
- "@commander-js/extra-typings": "^12.0.1",
12
- "chalk": "^4.1.2",
13
- "chokidar": "^3.5.3",
14
- "cli-progress": "^3.12.0",
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
- "latest-version": "^5.1.0",
20
- "open": "^8.4.2",
21
- "ora": "^5.4.1",
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
- "@anatine/zod-mock": "^3.14.0",
27
- "@faker-js/faker": "^8.0.0",
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/semver": "^7.5.6",
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.2.11"
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
+ }