@ollie-shop/cli 0.3.4 → 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.
Files changed (79) hide show
  1. package/.turbo/turbo-build.log +6 -9
  2. package/CHANGELOG.md +21 -0
  3. package/dist/index.js +986 -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 +533 -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
@@ -0,0 +1,177 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { PassThrough } from "node:stream";
4
+ import archiver from "archiver";
5
+
6
+ // TODO: Implement .ollieignore file support for custom exclusions
7
+
8
+ export interface BundleOptions {
9
+ /** Project root directory */
10
+ cwd?: string;
11
+ /** Component name (folder name in components/) */
12
+ componentName: string;
13
+ }
14
+
15
+ export interface BundleResult {
16
+ /** Readable stream of the zip file */
17
+ stream: PassThrough;
18
+ /** Size of the zip in bytes (available after stream ends) */
19
+ size: number;
20
+ }
21
+
22
+ /**
23
+ * Creates a zip bundle for a component with a synthetic entry point.
24
+ *
25
+ * The bundle includes:
26
+ * - index.tsx: synthetic entry point that re-exports the component
27
+ * - package.json: project dependencies
28
+ * - components/: all component source files
29
+ * - Any other user directories (utils/, hooks/, etc.)
30
+ *
31
+ * Excludes: node_modules, .git, .next, dist, build, etc.
32
+ */
33
+ export async function createComponentBundle(
34
+ options: BundleOptions,
35
+ ): Promise<PassThrough> {
36
+ const { cwd = process.cwd(), componentName } = options;
37
+
38
+ // Verify component exists
39
+ const componentDir = path.join(cwd, "components", componentName);
40
+ try {
41
+ await fs.access(componentDir);
42
+ } catch {
43
+ throw new Error(`Component "${componentName}" not found in components/`);
44
+ }
45
+
46
+ // Verify package.json exists
47
+ const packageJsonPath = path.join(cwd, "package.json");
48
+ try {
49
+ await fs.access(packageJsonPath);
50
+ } catch {
51
+ throw new Error("package.json not found in project root");
52
+ }
53
+
54
+ // Create archive with max compression
55
+ const archive = archiver("zip", {
56
+ zlib: { level: 9 },
57
+ });
58
+
59
+ // Create output stream
60
+ const output = new PassThrough();
61
+
62
+ archive.pipe(output);
63
+
64
+ // Handle archive errors
65
+ archive.on("error", (err) => {
66
+ output.destroy(err);
67
+ });
68
+
69
+ // Add synthetic entry point
70
+ const entryPoint = `export { default } from './components/${componentName}';\n`;
71
+ archive.append(entryPoint, { name: "index.tsx" });
72
+
73
+ // Add package.json
74
+ archive.file(packageJsonPath, { name: "package.json" });
75
+
76
+ // Add all directories from project root (excluding defaults)
77
+ const entries = await fs.readdir(cwd, { withFileTypes: true });
78
+
79
+ for (const entry of entries) {
80
+ // Skip excluded patterns
81
+ if (shouldExclude(entry.name)) {
82
+ continue;
83
+ }
84
+
85
+ const entryPath = path.join(cwd, entry.name);
86
+
87
+ if (entry.isDirectory()) {
88
+ // Add directory recursively
89
+ archive.directory(entryPath, entry.name, (data) => {
90
+ // Filter out excluded patterns within directories
91
+ const relativePath = path.relative(cwd, data.name || "");
92
+ if (shouldExcludeFile(relativePath)) {
93
+ return false;
94
+ }
95
+ return data;
96
+ });
97
+ } else if (entry.isFile() && isSourceFile(entry.name)) {
98
+ // Add root-level source files (but not package.json, already added)
99
+ if (entry.name !== "package.json") {
100
+ archive.file(entryPath, { name: entry.name });
101
+ }
102
+ }
103
+ }
104
+
105
+ // Finalize the archive
106
+ archive.finalize();
107
+
108
+ return output;
109
+ }
110
+
111
+ /**
112
+ * Check if a file/directory should be excluded at the root level
113
+ */
114
+ function shouldExclude(name: string): boolean {
115
+ const excludeRoots = [
116
+ "node_modules",
117
+ ".git",
118
+ ".next",
119
+ "dist",
120
+ "build",
121
+ ".turbo",
122
+ ".cache",
123
+ "coverage",
124
+ ];
125
+ return excludeRoots.includes(name) || name.startsWith(".");
126
+ }
127
+
128
+ /**
129
+ * Check if a file path should be excluded
130
+ */
131
+ function shouldExcludeFile(relativePath: string): boolean {
132
+ // Exclude node_modules anywhere in the tree
133
+ if (relativePath.includes("node_modules")) {
134
+ return true;
135
+ }
136
+
137
+ // Exclude common build artifacts
138
+ const excludePatterns = [
139
+ /\.tsbuildinfo$/,
140
+ /\.d\.ts$/,
141
+ /\.js\.map$/,
142
+ /\.next\//,
143
+ /dist\//,
144
+ /build\//,
145
+ ];
146
+
147
+ return excludePatterns.some((pattern) => pattern.test(relativePath));
148
+ }
149
+
150
+ /**
151
+ * Check if a file is a source file we want to include
152
+ */
153
+ function isSourceFile(name: string): boolean {
154
+ const sourceExtensions = [
155
+ ".ts",
156
+ ".tsx",
157
+ ".js",
158
+ ".jsx",
159
+ ".json",
160
+ ".css",
161
+ ".scss",
162
+ ".less",
163
+ ".svg",
164
+ ".png",
165
+ ".jpg",
166
+ ".jpeg",
167
+ ".gif",
168
+ ".webp",
169
+ ".ico",
170
+ ".woff",
171
+ ".woff2",
172
+ ".ttf",
173
+ ".eot",
174
+ ];
175
+
176
+ return sourceExtensions.some((ext) => name.endsWith(ext));
177
+ }
@@ -0,0 +1,123 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { z } from "zod";
4
+
5
+ const OllieConfigSchema = z
6
+ .object({
7
+ storeId: z.string().uuid(),
8
+ versionId: z.string().uuid().optional(),
9
+ })
10
+ .passthrough(); // Allow any other fields without validation
11
+
12
+ export type OllieConfig = z.infer<typeof OllieConfigSchema>;
13
+
14
+ const CONFIG_FILE = "ollie.json";
15
+
16
+ /**
17
+ * Gets the config file name for a given stage.
18
+ * - No stage or "prod" → ollie.json
19
+ * - Other stages → ollie.{stage}.json
20
+ */
21
+ function getConfigFileName(stage?: string): string {
22
+ if (!stage || stage === "prod") {
23
+ return CONFIG_FILE;
24
+ }
25
+ return `ollie.${stage}.json`;
26
+ }
27
+
28
+ /**
29
+ * Loads a single config file (without stage resolution).
30
+ */
31
+ async function loadConfigFile(
32
+ filePath: string,
33
+ ): Promise<Record<string, unknown> | null> {
34
+ try {
35
+ const content = await fs.readFile(filePath, "utf-8");
36
+ return JSON.parse(content);
37
+ } catch (error) {
38
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
39
+ return null;
40
+ }
41
+ throw error;
42
+ }
43
+ }
44
+
45
+ export interface LoadConfigOptions {
46
+ cwd?: string;
47
+ stage?: string;
48
+ }
49
+
50
+ /**
51
+ * Loads the config for a given stage.
52
+ * - Loads ollie.json as base config
53
+ * - If stage is provided (and not "prod"), merges ollie.{stage}.json on top
54
+ */
55
+ export async function loadConfig(
56
+ options: LoadConfigOptions = {},
57
+ ): Promise<OllieConfig | null> {
58
+ const { cwd = process.cwd(), stage } = options;
59
+
60
+ // Load base config (ollie.json)
61
+ const basePath = path.join(cwd, CONFIG_FILE);
62
+ const baseConfig = await loadConfigFile(basePath);
63
+
64
+ if (!baseConfig) {
65
+ return null;
66
+ }
67
+
68
+ // If no stage or stage is "prod", return base config
69
+ if (!stage || stage === "prod") {
70
+ return OllieConfigSchema.parse(baseConfig);
71
+ }
72
+
73
+ // Load stage-specific config
74
+ const stageFileName = getConfigFileName(stage);
75
+ const stagePath = path.join(cwd, stageFileName);
76
+ const stageConfig = await loadConfigFile(stagePath);
77
+
78
+ if (!stageConfig) {
79
+ throw new Error(
80
+ `Stage config not found: ${stageFileName}. Create it or use --stage prod (default).`,
81
+ );
82
+ }
83
+
84
+ // Merge: stage config overrides base config
85
+ const merged = {
86
+ ...baseConfig,
87
+ ...stageConfig,
88
+ };
89
+
90
+ return OllieConfigSchema.parse(merged);
91
+ }
92
+
93
+ export interface SaveConfigOptions {
94
+ cwd?: string;
95
+ stage?: string;
96
+ }
97
+
98
+ export async function saveConfig(
99
+ config: Partial<OllieConfig>,
100
+ options: SaveConfigOptions = {},
101
+ ): Promise<void> {
102
+ const { cwd = process.cwd(), stage } = options;
103
+ const fileName = getConfigFileName(stage);
104
+ const configPath = path.join(cwd, fileName);
105
+
106
+ // Load existing config for this specific file
107
+ const existing = await loadConfigFile(configPath);
108
+
109
+ const merged = {
110
+ ...existing,
111
+ ...config,
112
+ };
113
+
114
+ await fs.writeFile(configPath, JSON.stringify(merged, null, 2));
115
+ }
116
+
117
+ /**
118
+ * Returns the resolved stage from CLI args or environment.
119
+ * Priority: CLI arg > OLLIE_STAGE env > undefined (defaults to prod behavior)
120
+ */
121
+ export function resolveStage(cliStage?: string): string | undefined {
122
+ return cliStage || process.env.OLLIE_STAGE || undefined;
123
+ }