@ollie-shop/cli 0.2.0 → 0.3.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 +2 -11
- package/CHANGELOG.md +13 -7
- package/CLAUDE_CLI.md +265 -0
- package/README.md +704 -8
- package/__tests__/mocks/console.ts +22 -0
- package/__tests__/mocks/core.ts +137 -0
- package/__tests__/mocks/index.ts +4 -0
- package/__tests__/mocks/inquirer.ts +16 -0
- package/__tests__/mocks/progress.ts +19 -0
- package/dist/__tests__/helpers/cli-test-helper.d.ts +89 -0
- package/dist/__tests__/helpers/cli-test-helper.d.ts.map +1 -0
- package/dist/__tests__/helpers/cli-test-helper.js +220 -0
- package/dist/__tests__/mocks/index.d.ts +69 -0
- package/dist/__tests__/mocks/index.d.ts.map +1 -0
- package/dist/__tests__/mocks/index.js +77 -0
- package/dist/actions/component.actions.d.ts +14 -0
- package/dist/actions/component.actions.d.ts.map +1 -0
- package/dist/actions/component.actions.js +273 -0
- package/dist/actions/function.actions.d.ts +15 -0
- package/dist/actions/function.actions.d.ts.map +1 -0
- package/dist/actions/function.actions.js +254 -0
- package/dist/actions/project.actions.d.ts +17 -0
- package/dist/actions/project.actions.d.ts.map +1 -0
- package/dist/actions/project.actions.js +97 -0
- package/dist/actions/version.actions.d.ts +19 -0
- package/dist/actions/version.actions.d.ts.map +1 -0
- package/dist/actions/version.actions.js +216 -0
- package/dist/commands/component.d.ts +3 -0
- package/dist/commands/component.d.ts.map +1 -0
- package/dist/commands/component.js +192 -0
- package/dist/commands/docs.d.ts +3 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +16 -0
- package/dist/commands/function.d.ts +3 -0
- package/dist/commands/function.d.ts.map +1 -0
- package/dist/commands/function.js +243 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +20 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +26 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +175 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +78 -0
- package/dist/commands/store-version.d.ts +3 -0
- package/dist/commands/store-version.d.ts.map +1 -0
- package/dist/commands/store-version.js +241 -0
- package/dist/commands/version.d.ts +3 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +46 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +41 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +88 -478
- package/dist/prompts/component.prompts.d.ts +14 -0
- package/dist/prompts/component.prompts.d.ts.map +1 -0
- package/dist/prompts/component.prompts.js +75 -0
- package/dist/prompts/function.prompts.d.ts +21 -0
- package/dist/prompts/function.prompts.d.ts.map +1 -0
- package/dist/prompts/function.prompts.js +127 -0
- package/dist/schemas/command.schema.d.ts +516 -0
- package/dist/schemas/command.schema.d.ts.map +1 -0
- package/dist/schemas/command.schema.js +267 -0
- package/dist/types/index.d.ts +147 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/utils/auth.d.ts +4 -0
- package/dist/utils/auth.d.ts.map +1 -0
- package/dist/utils/auth.js +26 -0
- package/dist/utils/cli-progress-reporter.d.ts +12 -0
- package/dist/utils/cli-progress-reporter.d.ts.map +1 -0
- package/dist/utils/cli-progress-reporter.js +77 -0
- package/dist/utils/command-builder.d.ts +22 -0
- package/dist/utils/command-builder.d.ts.map +1 -0
- package/dist/utils/command-builder.js +268 -0
- package/dist/utils/command-helpers.d.ts +19 -0
- package/dist/utils/command-helpers.d.ts.map +1 -0
- package/dist/utils/command-helpers.js +79 -0
- package/dist/utils/command-parser.d.ts +146 -0
- package/dist/utils/command-parser.d.ts.map +1 -0
- package/dist/utils/command-parser.js +179 -0
- package/dist/utils/command-suggestions.d.ts +35 -0
- package/dist/utils/command-suggestions.d.ts.map +1 -0
- package/dist/utils/command-suggestions.js +152 -0
- package/dist/utils/console.d.ts +44 -0
- package/dist/utils/console.d.ts.map +1 -0
- package/dist/utils/console.js +233 -0
- package/dist/utils/constants.d.ts +8 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +10 -0
- package/dist/utils/context-detector.d.ts +12 -0
- package/dist/utils/context-detector.d.ts.map +1 -0
- package/dist/utils/context-detector.js +155 -0
- package/dist/utils/enhanced-error-handler.d.ts +47 -0
- package/dist/utils/enhanced-error-handler.d.ts.map +1 -0
- package/dist/utils/enhanced-error-handler.js +221 -0
- package/dist/utils/error-handler.d.ts +3 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +55 -0
- package/dist/utils/errors.d.ts +44 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +76 -0
- package/dist/utils/interactive-builder.d.ts +22 -0
- package/dist/utils/interactive-builder.d.ts.map +1 -0
- package/dist/utils/interactive-builder.js +246 -0
- package/dist/utils/rich-progress.d.ts +59 -0
- package/dist/utils/rich-progress.d.ts.map +1 -0
- package/dist/utils/rich-progress.js +234 -0
- package/dist/utils/store.d.ts +11 -0
- package/dist/utils/store.d.ts.map +1 -0
- package/dist/utils/store.js +19 -0
- package/dist/utils/validation-error-formatter.d.ts +25 -0
- package/dist/utils/validation-error-formatter.d.ts.map +1 -0
- package/dist/utils/validation-error-formatter.js +258 -0
- package/dist/utils/validation-helpers.d.ts +60 -0
- package/dist/utils/validation-helpers.d.ts.map +1 -0
- package/dist/utils/validation-helpers.js +152 -0
- package/package.json +43 -11
- package/src/__tests__/helpers/cli-test-helper.ts +281 -0
- package/src/__tests__/mocks/index.ts +142 -0
- package/src/actions/component.actions.ts +334 -0
- package/src/actions/function.actions.ts +313 -0
- package/src/actions/project.actions.ts +126 -0
- package/src/actions/version.actions.ts +233 -0
- package/src/commands/__tests__/component-validation.test.ts +250 -0
- package/src/commands/__tests__/component.test.ts +321 -0
- package/src/commands/__tests__/function-validation.test.ts +220 -0
- package/src/commands/__tests__/function.test.ts +286 -0
- package/src/commands/__tests__/store-version-validation.test.ts +414 -0
- package/src/commands/__tests__/store-version.test.ts +405 -0
- package/src/commands/__tests__/version.test.ts +71 -0
- package/src/commands/component.ts +188 -0
- package/src/commands/docs.ts +11 -11
- package/src/commands/function.ts +252 -0
- package/src/commands/help.ts +8 -18
- package/src/commands/index.ts +14 -7
- package/src/commands/login.ts +19 -79
- package/src/commands/project.ts +107 -0
- package/src/commands/store-version.ts +242 -0
- package/src/commands/version.ts +45 -8
- package/src/commands/whoami.ts +8 -13
- package/src/index.ts +108 -34
- package/src/prompts/component.prompts.ts +94 -0
- package/src/prompts/function.prompts.ts +168 -0
- package/src/schemas/command.schema.ts +354 -0
- package/src/types/index.ts +183 -0
- package/src/utils/__tests__/command-parser.test.ts +159 -0
- package/src/utils/__tests__/command-suggestions.test.ts +185 -0
- package/src/utils/__tests__/console.test.ts +192 -0
- package/src/utils/__tests__/context-detector.test.ts +258 -0
- package/src/utils/__tests__/enhanced-error-handler.test.ts +137 -0
- package/src/utils/__tests__/error-handler.test.ts +107 -0
- package/src/utils/__tests__/rich-progress.test.ts +170 -0
- package/src/utils/__tests__/validation-error-formatter.test.ts +175 -0
- package/src/utils/__tests__/validation-helpers.test.ts +125 -0
- package/src/utils/auth.ts +0 -1
- package/src/utils/cli-progress-reporter.ts +84 -0
- package/src/utils/command-builder.ts +390 -0
- package/src/utils/command-helpers.ts +83 -0
- package/src/utils/command-parser.ts +250 -0
- package/src/utils/command-suggestions.ts +176 -0
- package/src/utils/console.ts +291 -0
- package/src/utils/context-detector.ts +177 -0
- package/src/utils/enhanced-error-handler.ts +264 -0
- package/src/utils/error-handler.ts +60 -0
- package/src/utils/errors.ts +125 -0
- package/src/utils/interactive-builder.ts +271 -0
- package/src/utils/rich-progress.ts +320 -0
- package/src/utils/validation-error-formatter.ts +337 -0
- package/src/utils/validation-helpers.ts +192 -0
- package/tsconfig.json +13 -7
- package/vitest.config.ts +28 -0
- package/vitest.setup.ts +29 -0
- package/src/commands/validate.ts +0 -62
- package/src/utils/core.ts +0 -105
- package/tsup.config.ts +0 -15
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import type { Command } from "@commander-js/extra-typings";
|
|
2
|
+
import {
|
|
3
|
+
storeFactory,
|
|
4
|
+
versionFactory,
|
|
5
|
+
} from "@ollie-shop/core/__tests__/factories";
|
|
6
|
+
import {
|
|
7
|
+
createTestProgram,
|
|
8
|
+
executeCLI,
|
|
9
|
+
resetCLIMocks,
|
|
10
|
+
} from "@tests/helpers/cli-test-helper";
|
|
11
|
+
import { createMockCore } from "@tests/mocks";
|
|
12
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
13
|
+
import { registerStoreVersionCommands } from "../store-version";
|
|
14
|
+
|
|
15
|
+
// Mock the version actions module
|
|
16
|
+
vi.mock("../../actions/version.actions", () => ({
|
|
17
|
+
create: vi.fn(),
|
|
18
|
+
list: vi.fn(),
|
|
19
|
+
get: vi.fn(),
|
|
20
|
+
setDefault: vi.fn(),
|
|
21
|
+
activate: vi.fn(),
|
|
22
|
+
deactivate: vi.fn(),
|
|
23
|
+
clone: vi.fn(),
|
|
24
|
+
deleteVersion: vi.fn(),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
// Import mocked actions
|
|
28
|
+
import * as versionActions from "../../actions/version.actions";
|
|
29
|
+
|
|
30
|
+
describe("Store Version Command", () => {
|
|
31
|
+
let program: Command;
|
|
32
|
+
let _mockCore: ReturnType<typeof createMockCore>;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
const testSetup = createTestProgram();
|
|
36
|
+
program = testSetup.program;
|
|
37
|
+
_mockCore = createMockCore();
|
|
38
|
+
|
|
39
|
+
// Register the store-version commands
|
|
40
|
+
registerStoreVersionCommands(program);
|
|
41
|
+
|
|
42
|
+
// Reset all mocks
|
|
43
|
+
vi.clearAllMocks();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
resetCLIMocks();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("create subcommand", () => {
|
|
51
|
+
it("should create a version with required options", async () => {
|
|
52
|
+
// Arrange
|
|
53
|
+
const newVersion = versionFactory.build({
|
|
54
|
+
name: "test-version",
|
|
55
|
+
template: "default",
|
|
56
|
+
active: true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
vi.mocked(versionActions.create).mockResolvedValue(newVersion);
|
|
60
|
+
|
|
61
|
+
// Act
|
|
62
|
+
const result = await executeCLI(program, [
|
|
63
|
+
"store-version",
|
|
64
|
+
"create",
|
|
65
|
+
"--store",
|
|
66
|
+
"123e4567-e89b-12d3-a456-426614174000",
|
|
67
|
+
"--name",
|
|
68
|
+
"test-version",
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
// Assert
|
|
72
|
+
expect(result.exitCode).toBe(0);
|
|
73
|
+
expect(versionActions.create).toHaveBeenCalledWith({
|
|
74
|
+
store: "123e4567-e89b-12d3-a456-426614174000",
|
|
75
|
+
name: "test-version",
|
|
76
|
+
template: "default",
|
|
77
|
+
active: true,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should create an inactive version when --no-active is specified", async () => {
|
|
82
|
+
// Arrange
|
|
83
|
+
const newVersion = versionFactory.build({
|
|
84
|
+
name: "test-version",
|
|
85
|
+
active: false,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
vi.mocked(versionActions.create).mockResolvedValue(newVersion);
|
|
89
|
+
|
|
90
|
+
// Act
|
|
91
|
+
const result = await executeCLI(program, [
|
|
92
|
+
"store-version",
|
|
93
|
+
"create",
|
|
94
|
+
"--store",
|
|
95
|
+
"123e4567-e89b-12d3-a456-426614174000",
|
|
96
|
+
"--name",
|
|
97
|
+
"test-version",
|
|
98
|
+
"--no-active",
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
// Assert
|
|
102
|
+
expect(result.exitCode).toBe(0);
|
|
103
|
+
expect(versionActions.create).toHaveBeenCalledWith({
|
|
104
|
+
store: "123e4567-e89b-12d3-a456-426614174000",
|
|
105
|
+
name: "test-version",
|
|
106
|
+
template: "default",
|
|
107
|
+
active: false,
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should handle validation errors for invalid store ID", async () => {
|
|
112
|
+
// Act
|
|
113
|
+
const result = await executeCLI(program, [
|
|
114
|
+
"store-version",
|
|
115
|
+
"create",
|
|
116
|
+
"--store",
|
|
117
|
+
"invalid-uuid",
|
|
118
|
+
"--name",
|
|
119
|
+
"test-version",
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
// Assert
|
|
123
|
+
expect(result.exitCode).toBe(1);
|
|
124
|
+
expect(versionActions.create).not.toHaveBeenCalled();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should handle missing required options", async () => {
|
|
128
|
+
// Act
|
|
129
|
+
const result = await executeCLI(program, ["store-version", "create"]);
|
|
130
|
+
|
|
131
|
+
// Assert
|
|
132
|
+
expect(result.exitCode).toBe(1);
|
|
133
|
+
expect(versionActions.create).not.toHaveBeenCalled();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe("list subcommand", () => {
|
|
138
|
+
it("should list versions for a store", async () => {
|
|
139
|
+
// Arrange
|
|
140
|
+
const store = storeFactory.build();
|
|
141
|
+
const versions = [
|
|
142
|
+
versionFactory.build({
|
|
143
|
+
storeId: store.id,
|
|
144
|
+
name: "Production",
|
|
145
|
+
default: true,
|
|
146
|
+
}),
|
|
147
|
+
versionFactory.build({
|
|
148
|
+
storeId: store.id,
|
|
149
|
+
name: "Staging",
|
|
150
|
+
default: false,
|
|
151
|
+
}),
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
vi.mocked(versionActions.list).mockResolvedValue(versions);
|
|
155
|
+
|
|
156
|
+
// Act
|
|
157
|
+
const result = await executeCLI(program, [
|
|
158
|
+
"store-version",
|
|
159
|
+
"list",
|
|
160
|
+
"--store",
|
|
161
|
+
store.id,
|
|
162
|
+
]);
|
|
163
|
+
|
|
164
|
+
// Assert
|
|
165
|
+
expect(result.exitCode).toBe(0);
|
|
166
|
+
expect(versionActions.list).toHaveBeenCalledWith({
|
|
167
|
+
store: store.id,
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should handle validation errors for invalid store ID", async () => {
|
|
172
|
+
// Act
|
|
173
|
+
const result = await executeCLI(program, [
|
|
174
|
+
"store-version",
|
|
175
|
+
"list",
|
|
176
|
+
"--store",
|
|
177
|
+
"invalid-uuid",
|
|
178
|
+
]);
|
|
179
|
+
|
|
180
|
+
// Assert
|
|
181
|
+
expect(result.exitCode).toBe(1);
|
|
182
|
+
expect(versionActions.list).not.toHaveBeenCalled();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe("get subcommand", () => {
|
|
187
|
+
it("should get version details by ID", async () => {
|
|
188
|
+
// Arrange
|
|
189
|
+
const version = versionFactory.build();
|
|
190
|
+
vi.mocked(versionActions.get).mockResolvedValue(version);
|
|
191
|
+
|
|
192
|
+
// Act
|
|
193
|
+
const result = await executeCLI(program, [
|
|
194
|
+
"store-version",
|
|
195
|
+
"get",
|
|
196
|
+
version.id,
|
|
197
|
+
]);
|
|
198
|
+
|
|
199
|
+
// Assert
|
|
200
|
+
expect(result.exitCode).toBe(0);
|
|
201
|
+
expect(versionActions.get).toHaveBeenCalledWith(version.id);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("should handle validation errors for invalid version ID", async () => {
|
|
205
|
+
// Act
|
|
206
|
+
const result = await executeCLI(program, [
|
|
207
|
+
"store-version",
|
|
208
|
+
"get",
|
|
209
|
+
"invalid-uuid",
|
|
210
|
+
]);
|
|
211
|
+
|
|
212
|
+
// Assert
|
|
213
|
+
expect(result.exitCode).toBe(1);
|
|
214
|
+
expect(versionActions.get).not.toHaveBeenCalled();
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe("set-default subcommand", () => {
|
|
219
|
+
it("should set a version as default", async () => {
|
|
220
|
+
// Arrange
|
|
221
|
+
const version = versionFactory.build();
|
|
222
|
+
const defaultVersion = { ...version, default: true };
|
|
223
|
+
vi.mocked(versionActions.setDefault).mockResolvedValue(defaultVersion);
|
|
224
|
+
|
|
225
|
+
// Act
|
|
226
|
+
const result = await executeCLI(program, [
|
|
227
|
+
"store-version",
|
|
228
|
+
"set-default",
|
|
229
|
+
version.id,
|
|
230
|
+
]);
|
|
231
|
+
|
|
232
|
+
// Assert
|
|
233
|
+
expect(result.exitCode).toBe(0);
|
|
234
|
+
expect(versionActions.setDefault).toHaveBeenCalledWith(version.id);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe("activate subcommand", () => {
|
|
239
|
+
it("should activate a version", async () => {
|
|
240
|
+
// Arrange
|
|
241
|
+
const version = versionFactory.build({ active: false });
|
|
242
|
+
const activeVersion = { ...version, active: true };
|
|
243
|
+
vi.mocked(versionActions.activate).mockResolvedValue(activeVersion);
|
|
244
|
+
|
|
245
|
+
// Act
|
|
246
|
+
const result = await executeCLI(program, [
|
|
247
|
+
"store-version",
|
|
248
|
+
"activate",
|
|
249
|
+
version.id,
|
|
250
|
+
]);
|
|
251
|
+
|
|
252
|
+
// Assert
|
|
253
|
+
expect(result.exitCode).toBe(0);
|
|
254
|
+
expect(versionActions.activate).toHaveBeenCalledWith(version.id);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe("deactivate subcommand", () => {
|
|
259
|
+
it("should deactivate a version", async () => {
|
|
260
|
+
// Arrange
|
|
261
|
+
const version = versionFactory.build({ active: true });
|
|
262
|
+
const inactiveVersion = { ...version, active: false };
|
|
263
|
+
vi.mocked(versionActions.deactivate).mockResolvedValue(inactiveVersion);
|
|
264
|
+
|
|
265
|
+
// Act
|
|
266
|
+
const result = await executeCLI(program, [
|
|
267
|
+
"store-version",
|
|
268
|
+
"deactivate",
|
|
269
|
+
version.id,
|
|
270
|
+
]);
|
|
271
|
+
|
|
272
|
+
// Assert
|
|
273
|
+
expect(result.exitCode).toBe(0);
|
|
274
|
+
expect(versionActions.deactivate).toHaveBeenCalledWith(version.id);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe("clone subcommand", () => {
|
|
279
|
+
it("should clone a version with a new name", async () => {
|
|
280
|
+
// Arrange
|
|
281
|
+
const originalVersion = versionFactory.build();
|
|
282
|
+
const clonedVersion = versionFactory.build({ name: "Cloned Version" });
|
|
283
|
+
vi.mocked(versionActions.clone).mockResolvedValue(clonedVersion);
|
|
284
|
+
|
|
285
|
+
// Act
|
|
286
|
+
const result = await executeCLI(program, [
|
|
287
|
+
"store-version",
|
|
288
|
+
"clone",
|
|
289
|
+
originalVersion.id,
|
|
290
|
+
"--name",
|
|
291
|
+
"Cloned Version",
|
|
292
|
+
]);
|
|
293
|
+
|
|
294
|
+
// Assert
|
|
295
|
+
expect(result.exitCode).toBe(0);
|
|
296
|
+
expect(versionActions.clone).toHaveBeenCalledWith(
|
|
297
|
+
originalVersion.id,
|
|
298
|
+
"Cloned Version",
|
|
299
|
+
);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it("should handle missing name option", async () => {
|
|
303
|
+
// Arrange
|
|
304
|
+
const version = versionFactory.build();
|
|
305
|
+
|
|
306
|
+
// Act
|
|
307
|
+
const result = await executeCLI(program, [
|
|
308
|
+
"store-version",
|
|
309
|
+
"clone",
|
|
310
|
+
version.id,
|
|
311
|
+
]);
|
|
312
|
+
|
|
313
|
+
// Assert
|
|
314
|
+
expect(result.exitCode).toBe(1);
|
|
315
|
+
expect(versionActions.clone).not.toHaveBeenCalled();
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe("delete subcommand", () => {
|
|
320
|
+
it("should delete a version", async () => {
|
|
321
|
+
// Arrange
|
|
322
|
+
const version = versionFactory.build();
|
|
323
|
+
vi.mocked(versionActions.deleteVersion).mockResolvedValue(undefined);
|
|
324
|
+
|
|
325
|
+
// Act
|
|
326
|
+
const result = await executeCLI(program, [
|
|
327
|
+
"store-version",
|
|
328
|
+
"delete",
|
|
329
|
+
version.id,
|
|
330
|
+
]);
|
|
331
|
+
|
|
332
|
+
// Assert
|
|
333
|
+
expect(result.exitCode).toBe(0);
|
|
334
|
+
expect(versionActions.deleteVersion).toHaveBeenCalledWith(
|
|
335
|
+
version.id,
|
|
336
|
+
undefined,
|
|
337
|
+
);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("should delete a version with force flag", async () => {
|
|
341
|
+
// Arrange
|
|
342
|
+
const version = versionFactory.build();
|
|
343
|
+
vi.mocked(versionActions.deleteVersion).mockResolvedValue(undefined);
|
|
344
|
+
|
|
345
|
+
// Act
|
|
346
|
+
const result = await executeCLI(program, [
|
|
347
|
+
"store-version",
|
|
348
|
+
"delete",
|
|
349
|
+
version.id,
|
|
350
|
+
"--force",
|
|
351
|
+
]);
|
|
352
|
+
|
|
353
|
+
// Assert
|
|
354
|
+
expect(result.exitCode).toBe(0);
|
|
355
|
+
expect(versionActions.deleteVersion).toHaveBeenCalledWith(
|
|
356
|
+
version.id,
|
|
357
|
+
true,
|
|
358
|
+
);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
describe("error handling", () => {
|
|
363
|
+
it("should handle action errors gracefully", async () => {
|
|
364
|
+
// Arrange
|
|
365
|
+
const error = new Error("Version creation failed");
|
|
366
|
+
vi.mocked(versionActions.create).mockRejectedValue(error);
|
|
367
|
+
|
|
368
|
+
// Act
|
|
369
|
+
const result = await executeCLI(program, [
|
|
370
|
+
"store-version",
|
|
371
|
+
"create",
|
|
372
|
+
"--store",
|
|
373
|
+
"123e4567-e89b-12d3-a456-426614174000",
|
|
374
|
+
"--name",
|
|
375
|
+
"test-version",
|
|
376
|
+
]);
|
|
377
|
+
|
|
378
|
+
// Assert
|
|
379
|
+
expect(result.exitCode).toBe(1);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
describe("alias support", () => {
|
|
384
|
+
it("should work with sv alias", async () => {
|
|
385
|
+
// Arrange
|
|
386
|
+
const store = storeFactory.build();
|
|
387
|
+
const versions = [versionFactory.build({ storeId: store.id })];
|
|
388
|
+
vi.mocked(versionActions.list).mockResolvedValue(versions);
|
|
389
|
+
|
|
390
|
+
// Act
|
|
391
|
+
const result = await executeCLI(program, [
|
|
392
|
+
"sv",
|
|
393
|
+
"list",
|
|
394
|
+
"--store",
|
|
395
|
+
store.id,
|
|
396
|
+
]);
|
|
397
|
+
|
|
398
|
+
// Assert
|
|
399
|
+
expect(result.exitCode).toBe(0);
|
|
400
|
+
expect(versionActions.list).toHaveBeenCalledWith({
|
|
401
|
+
store: store.id,
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Command } from "@commander-js/extra-typings";
|
|
2
|
+
import {
|
|
3
|
+
createTestProgram,
|
|
4
|
+
executeCLI,
|
|
5
|
+
resetCLIMocks,
|
|
6
|
+
} from "@tests/helpers/cli-test-helper";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { configureVersionCommand } from "../version";
|
|
9
|
+
|
|
10
|
+
// Mock the package.json to provide a test version
|
|
11
|
+
vi.mock("../../package.json", () => ({
|
|
12
|
+
default: { version: "0.2.0" },
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Mock the console utility
|
|
16
|
+
vi.mock("../../utils/console", () => ({
|
|
17
|
+
console: {
|
|
18
|
+
info: vi.fn(),
|
|
19
|
+
error: vi.fn(),
|
|
20
|
+
success: vi.fn(),
|
|
21
|
+
warn: vi.fn(),
|
|
22
|
+
log: vi.fn(),
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
// Import the mocked console
|
|
27
|
+
import { console as mockConsole } from "../../utils/console";
|
|
28
|
+
|
|
29
|
+
describe("Version Command", () => {
|
|
30
|
+
let program: Command;
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
const testSetup = createTestProgram();
|
|
34
|
+
program = testSetup.program;
|
|
35
|
+
|
|
36
|
+
// Configure the version command
|
|
37
|
+
configureVersionCommand(program);
|
|
38
|
+
|
|
39
|
+
// Reset all mocks
|
|
40
|
+
vi.clearAllMocks();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
resetCLIMocks();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("version command", () => {
|
|
48
|
+
it("should display the CLI version", async () => {
|
|
49
|
+
// Act
|
|
50
|
+
const result = await executeCLI(program, ["version"]);
|
|
51
|
+
|
|
52
|
+
// Assert
|
|
53
|
+
expect(result.exitCode).toBe(0);
|
|
54
|
+
expect(mockConsole.info).toHaveBeenCalledWith(
|
|
55
|
+
"Ollie Shop CLI version: 0.2.0",
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should call the version command action", async () => {
|
|
60
|
+
// Act
|
|
61
|
+
const result = await executeCLI(program, ["version"]);
|
|
62
|
+
|
|
63
|
+
// Assert
|
|
64
|
+
expect(result.exitCode).toBe(0);
|
|
65
|
+
expect(mockConsole.info).toHaveBeenCalledTimes(1);
|
|
66
|
+
expect(mockConsole.info).toHaveBeenCalledWith(
|
|
67
|
+
expect.stringContaining("Ollie Shop CLI version:"),
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { Command } from "@commander-js/extra-typings";
|
|
2
|
+
import * as componentActions from "../actions/component.actions";
|
|
3
|
+
import {
|
|
4
|
+
ComponentBuildOptionsSchema,
|
|
5
|
+
type ComponentCreateOptions,
|
|
6
|
+
ComponentCreateOptionsSchema,
|
|
7
|
+
type ComponentDeployOptions,
|
|
8
|
+
ComponentDeployOptionsSchema,
|
|
9
|
+
ComponentValidateOptionsSchema,
|
|
10
|
+
} from "../schemas/command.schema";
|
|
11
|
+
import { buildCommand, buildCommandGroup } from "../utils/command-builder";
|
|
12
|
+
import { COMMON_OPTIONS } from "../utils/command-parser";
|
|
13
|
+
|
|
14
|
+
export function registerComponentCommands(program: Command): void {
|
|
15
|
+
const cmd = buildCommandGroup(
|
|
16
|
+
program,
|
|
17
|
+
"component",
|
|
18
|
+
"Manage Ollie Shop components",
|
|
19
|
+
["comp"],
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// Create component command
|
|
23
|
+
buildCommand(cmd, {
|
|
24
|
+
name: "create",
|
|
25
|
+
description: "Create a new component",
|
|
26
|
+
options: [
|
|
27
|
+
COMMON_OPTIONS.componentName,
|
|
28
|
+
COMMON_OPTIONS.componentSlot,
|
|
29
|
+
COMMON_OPTIONS.tests,
|
|
30
|
+
COMMON_OPTIONS.noTests,
|
|
31
|
+
{
|
|
32
|
+
flags: "-i, --interactive",
|
|
33
|
+
description: "Use interactive mode",
|
|
34
|
+
defaultValue: false,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
schema: ComponentCreateOptionsSchema,
|
|
38
|
+
examples: [
|
|
39
|
+
{
|
|
40
|
+
description: "Create a header component",
|
|
41
|
+
command: "ollieshop component create --name header --slot header",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
description: "Create a component with TypeScript",
|
|
45
|
+
command: "ollieshop component create --name product-list --typescript",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
description: "Interactive mode",
|
|
49
|
+
command: "ollieshop component create --interactive",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
description: "Create with tests",
|
|
53
|
+
command: "ollieshop component create --name product-list",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
handler: async (options, console) => {
|
|
57
|
+
// Use interactive mode if requested
|
|
58
|
+
if ("interactive" in options && options.interactive) {
|
|
59
|
+
const { runInteractiveCommand } = await import(
|
|
60
|
+
"../utils/interactive-builder.js"
|
|
61
|
+
);
|
|
62
|
+
await runInteractiveCommand("component-create", console);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await componentActions.createComponent(
|
|
67
|
+
options as ComponentCreateOptions,
|
|
68
|
+
console,
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Validate component command
|
|
74
|
+
buildCommand(cmd, {
|
|
75
|
+
name: "validate",
|
|
76
|
+
description: "Validate a component",
|
|
77
|
+
options: [COMMON_OPTIONS.path],
|
|
78
|
+
schema: ComponentValidateOptionsSchema,
|
|
79
|
+
examples: [
|
|
80
|
+
{
|
|
81
|
+
description: "Validate current directory",
|
|
82
|
+
command: "ollieshop component validate",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
description: "Validate specific component",
|
|
86
|
+
command: "ollieshop component validate --path ./components/header",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
handler: async (options, console) => {
|
|
90
|
+
await componentActions.validateComponent(
|
|
91
|
+
{
|
|
92
|
+
path: options.path || process.cwd(),
|
|
93
|
+
strict: options.strict ?? false,
|
|
94
|
+
fix: options.fix ?? false,
|
|
95
|
+
},
|
|
96
|
+
console,
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Build component command
|
|
102
|
+
buildCommand(cmd, {
|
|
103
|
+
name: "build",
|
|
104
|
+
description: "Build a component",
|
|
105
|
+
options: [COMMON_OPTIONS.path, COMMON_OPTIONS.watch],
|
|
106
|
+
schema: ComponentBuildOptionsSchema,
|
|
107
|
+
examples: [
|
|
108
|
+
{
|
|
109
|
+
description: "Build current directory",
|
|
110
|
+
command: "ollieshop component build",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
description: "Build specific component",
|
|
114
|
+
command: "ollieshop component build --path ./components/header",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
description: "Build with watch mode",
|
|
118
|
+
command: "ollieshop component build --watch",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
handler: async (options, console) => {
|
|
122
|
+
await componentActions.buildComponent(
|
|
123
|
+
{
|
|
124
|
+
path: options.path || process.cwd(),
|
|
125
|
+
watch: options.watch ?? false,
|
|
126
|
+
},
|
|
127
|
+
console,
|
|
128
|
+
);
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Deploy component command
|
|
133
|
+
buildCommand(cmd, {
|
|
134
|
+
name: "deploy",
|
|
135
|
+
description: "Deploy a component",
|
|
136
|
+
options: [
|
|
137
|
+
{
|
|
138
|
+
flags: "--id <id>",
|
|
139
|
+
description: "Component ID",
|
|
140
|
+
required: true,
|
|
141
|
+
},
|
|
142
|
+
COMMON_OPTIONS.path,
|
|
143
|
+
{
|
|
144
|
+
flags: "--wait",
|
|
145
|
+
description: "Wait for deployment to complete",
|
|
146
|
+
defaultValue: false,
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
schema: ComponentDeployOptionsSchema,
|
|
150
|
+
examples: [
|
|
151
|
+
{
|
|
152
|
+
description: "Deploy a component",
|
|
153
|
+
command: "ollieshop component deploy --id comp-123",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
description: "Deploy and wait for completion",
|
|
157
|
+
command: "ollieshop component deploy --id comp-123 --wait",
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
handler: async (options: ComponentDeployOptions, console) => {
|
|
161
|
+
// Map id to componentId if provided
|
|
162
|
+
const deployOptions = {
|
|
163
|
+
path: options.path,
|
|
164
|
+
componentId: options.id || options.componentId,
|
|
165
|
+
wait: options.wait,
|
|
166
|
+
};
|
|
167
|
+
await componentActions.deployComponent(deployOptions, console);
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// List components command
|
|
172
|
+
buildCommand(cmd, {
|
|
173
|
+
name: "list",
|
|
174
|
+
description: "List all components",
|
|
175
|
+
aliases: ["ls"],
|
|
176
|
+
examples: [
|
|
177
|
+
{
|
|
178
|
+
description: "List all components",
|
|
179
|
+
command: "ollieshop component list",
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
handler: async (_, console) => {
|
|
183
|
+
await componentActions.listComponents(console);
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Add more commands as needed
|
|
188
|
+
}
|
package/src/commands/docs.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import type { Command } from "@commander-js/extra-typings";
|
|
2
|
+
import { console as cliConsole } from "../utils/console";
|
|
3
3
|
|
|
4
4
|
export function configureDocsCommand(program: Command): void {
|
|
5
5
|
program
|
|
6
6
|
.command("docs")
|
|
7
7
|
.description("Show documentation links for Ollie Shop")
|
|
8
8
|
.action(() => {
|
|
9
|
-
|
|
9
|
+
cliConsole.info("Ollie Shop Documentation\n");
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
`${
|
|
11
|
+
cliConsole.info(
|
|
12
|
+
`${"Main Docs:".padEnd(20)} https://docs.ollie.shop/ollie-shop`,
|
|
13
13
|
);
|
|
14
|
-
|
|
15
|
-
`${
|
|
14
|
+
cliConsole.info(
|
|
15
|
+
`${"Components:".padEnd(20)} https://docs.ollie.shop/ollie-shop/concepts/component`,
|
|
16
16
|
);
|
|
17
|
-
|
|
18
|
-
`${
|
|
17
|
+
cliConsole.info(
|
|
18
|
+
`${"Functions:".padEnd(20)} https://docs.ollie.shop/ollie-shop/concepts/function`,
|
|
19
19
|
);
|
|
20
|
-
|
|
21
|
-
`${
|
|
20
|
+
cliConsole.info(
|
|
21
|
+
`${"Versions:".padEnd(20)} https://docs.ollie.shop/ollie-shop/concepts/version\n`,
|
|
22
22
|
);
|
|
23
23
|
});
|
|
24
24
|
}
|