optikit 1.2.0 → 1.2.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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,22 @@ We follow Semantic Versioning (SemVer) to indicate the nature of changes:
10
10
 
11
11
  Each section lists the changes in chronological order, with the most recent release at the top. We also include links to relevant discussions or issues when appropriate.
12
12
 
13
+ ## [1.2.1]
14
+
15
+ ### Added
16
+
17
+ - **Open Build Output Commands:** New commands to quickly access build artifacts:
18
+ - `open-ipa` - Opens the IPA build output directory (`build/ios/ipa/`)
19
+ - `open-apk` - Opens the APK build output directory (`build/app/outputs/flutter-apk/`)
20
+ - `open-bundle` - Opens the Android Bundle output directory (`build/app/outputs/bundle/release/`)
21
+ - **Cross-Platform Support:** All open commands work seamlessly on macOS (Finder), Windows (Explorer), and Linux (default file manager)
22
+ - **Smart Validation:** Commands check if build output exists before attempting to open, with helpful error messages
23
+
24
+ ### Improved
25
+
26
+ - **Documentation:** Updated USAGE.md with comprehensive open build output commands section
27
+ - **User Experience:** No need for shell aliases to access build outputs - built directly into the CLI
28
+
13
29
  ## [1.2.0]
14
30
 
15
31
  ### Added
package/USAGE.md CHANGED
@@ -330,6 +330,45 @@ optikit open-ios
330
330
 
331
331
  ---
332
332
 
333
+ ### Open Build Output Directories
334
+
335
+ Quickly access your build artifacts in Finder (macOS), File Explorer (Windows), or your default file manager (Linux).
336
+
337
+ **Open IPA build output:**
338
+
339
+ ```bash
340
+ optikit open-ipa
341
+ ```
342
+
343
+ Opens: `build/ios/ipa/`
344
+
345
+ **Open APK build output:**
346
+
347
+ ```bash
348
+ optikit open-apk
349
+ ```
350
+
351
+ Opens: `build/app/outputs/flutter-apk/`
352
+
353
+ **Open Android Bundle build output:**
354
+
355
+ ```bash
356
+ optikit open-bundle
357
+ ```
358
+
359
+ Opens: `build/app/outputs/bundle/release/`
360
+
361
+ **What it does:**
362
+
363
+ - Validates that you're in a Flutter project
364
+ - Checks if the build output directory exists
365
+ - Opens the directory in your system's default file manager
366
+ - Works cross-platform (macOS, Windows, Linux)
367
+
368
+ **Note:** You must build the respective artifact first before opening its output directory.
369
+
370
+ ---
371
+
333
372
  ### VS Code Setup Command
334
373
 
335
374
  Automatically create a `.vscode` folder with a `settings.json` file preconfigured for Flutter projects using FVM. This command streamlines your project setup by setting the Flutter SDK path to `.fvm/flutter_sdk`.
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import { cleanIosProject } from "./commands/clean/ios.js";
9
9
  import { updateFlutterVersion } from "./commands/version/update.js";
10
10
  import { buildFlutterApk, buildFlutterBundle, buildFlutterIos, buildFlutterIpa, } from "./commands/build/releases.js";
11
11
  import { boxenOptions } from "./styles.js";
12
- import { openIos, openAndroid } from "./commands/project/open.js";
12
+ import { openIos, openAndroid, openIpaOutput, openBundleOutput, openApkOutput } from "./commands/project/open.js";
13
13
  import { createRequire } from "module";
14
14
  import { createVscodeSettings } from "./commands/project/setup.js";
15
15
  import { initializeProject } from "./commands/config/init.js";
@@ -129,7 +129,17 @@ const options = yargs(hideBin(process.argv))
129
129
  })
130
130
  .command("open-android", "Open the Android project in Android Studio", {}, async () => {
131
131
  await openAndroid();
132
- }).command("setup-vscode", "Create a .vscode folder with recommended Flutter settings", () => { }, async () => {
132
+ })
133
+ .command("open-ipa", "Open the IPA build output directory", {}, async () => {
134
+ await openIpaOutput();
135
+ })
136
+ .command("open-apk", "Open the APK build output directory", {}, async () => {
137
+ await openApkOutput();
138
+ })
139
+ .command("open-bundle", "Open the Android Bundle build output directory", {}, async () => {
140
+ await openBundleOutput();
141
+ })
142
+ .command("setup-vscode", "Create a .vscode folder with recommended Flutter settings", () => { }, async () => {
133
143
  await createVscodeSettings();
134
144
  })
135
145
  .command("init", "Initialize OptiKit configuration in the current project", () => { }, async () => {
@@ -2,7 +2,9 @@ import { LoggerHelpers } from "../../utils/services/logger.js";
2
2
  import { execCommand } from "../../utils/services/exec.js";
3
3
  import { platform } from "os";
4
4
  import { validateFlutterProject, validateIosProject, validateAndroidProject } from "../../utils/validators/validation.js";
5
- export { openIos, openAndroid };
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ export { openIos, openAndroid, openIpaOutput, openBundleOutput, openApkOutput };
6
8
  async function openIos() {
7
9
  LoggerHelpers.info("Opening the iOS project in Xcode...");
8
10
  // Pre-flight validation
@@ -61,3 +63,101 @@ async function openAndroid() {
61
63
  process.exit(1);
62
64
  }
63
65
  }
66
+ /**
67
+ * Opens the IPA build output directory in Finder (macOS) or File Explorer (Windows/Linux)
68
+ */
69
+ async function openIpaOutput() {
70
+ if (!validateFlutterProject()) {
71
+ process.exit(1);
72
+ }
73
+ const ipaPath = path.join(process.cwd(), "build", "ios", "ipa");
74
+ if (!fs.existsSync(ipaPath)) {
75
+ LoggerHelpers.warning(`IPA output directory not found: ${ipaPath}`);
76
+ LoggerHelpers.info("Build an IPA first using: optikit flutter-build-ipa");
77
+ process.exit(1);
78
+ }
79
+ try {
80
+ const openCommand = getOpenCommand();
81
+ await execCommand(`${openCommand} "${ipaPath}"`);
82
+ LoggerHelpers.success(`Opened IPA output directory`);
83
+ }
84
+ catch (error) {
85
+ if (error instanceof Error) {
86
+ LoggerHelpers.error(`Error opening IPA directory: ${error.message}`);
87
+ }
88
+ else {
89
+ LoggerHelpers.error(`Error opening IPA directory: ${error}`);
90
+ }
91
+ process.exit(1);
92
+ }
93
+ }
94
+ /**
95
+ * Opens the Android App Bundle output directory in Finder (macOS) or File Explorer (Windows/Linux)
96
+ */
97
+ async function openBundleOutput() {
98
+ if (!validateFlutterProject()) {
99
+ process.exit(1);
100
+ }
101
+ const bundlePath = path.join(process.cwd(), "build", "app", "outputs", "bundle", "release");
102
+ if (!fs.existsSync(bundlePath)) {
103
+ LoggerHelpers.warning(`Bundle output directory not found: ${bundlePath}`);
104
+ LoggerHelpers.info("Build a bundle first using: optikit flutter-build-bundle");
105
+ process.exit(1);
106
+ }
107
+ try {
108
+ const openCommand = getOpenCommand();
109
+ await execCommand(`${openCommand} "${bundlePath}"`);
110
+ LoggerHelpers.success(`Opened Bundle output directory`);
111
+ }
112
+ catch (error) {
113
+ if (error instanceof Error) {
114
+ LoggerHelpers.error(`Error opening Bundle directory: ${error.message}`);
115
+ }
116
+ else {
117
+ LoggerHelpers.error(`Error opening Bundle directory: ${error}`);
118
+ }
119
+ process.exit(1);
120
+ }
121
+ }
122
+ /**
123
+ * Opens the APK build output directory in Finder (macOS) or File Explorer (Windows/Linux)
124
+ */
125
+ async function openApkOutput() {
126
+ if (!validateFlutterProject()) {
127
+ process.exit(1);
128
+ }
129
+ const apkPath = path.join(process.cwd(), "build", "app", "outputs", "flutter-apk");
130
+ if (!fs.existsSync(apkPath)) {
131
+ LoggerHelpers.warning(`APK output directory not found: ${apkPath}`);
132
+ LoggerHelpers.info("Build an APK first using: optikit flutter-build-apk");
133
+ process.exit(1);
134
+ }
135
+ try {
136
+ const openCommand = getOpenCommand();
137
+ await execCommand(`${openCommand} "${apkPath}"`);
138
+ LoggerHelpers.success(`Opened APK output directory`);
139
+ }
140
+ catch (error) {
141
+ if (error instanceof Error) {
142
+ LoggerHelpers.error(`Error opening APK directory: ${error.message}`);
143
+ }
144
+ else {
145
+ LoggerHelpers.error(`Error opening APK directory: ${error}`);
146
+ }
147
+ process.exit(1);
148
+ }
149
+ }
150
+ /**
151
+ * Returns the appropriate command to open a directory based on the platform
152
+ */
153
+ function getOpenCommand() {
154
+ const osPlatform = platform();
155
+ switch (osPlatform) {
156
+ case "darwin": // macOS
157
+ return "open";
158
+ case "win32": // Windows
159
+ return "start";
160
+ default: // Linux and others
161
+ return "xdg-open";
162
+ }
163
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "optikit",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "OptiKit CLI",
5
5
  "main": "src/cli.ts",
6
6
  "type": "module",
package/src/cli.ts CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  buildFlutterIpa,
16
16
  } from "./commands/build/releases.js";
17
17
  import { boxenOptions } from "./styles.js";
18
- import { openIos, openAndroid } from "./commands/project/open.js";
18
+ import { openIos, openAndroid, openIpaOutput, openBundleOutput, openApkOutput } from "./commands/project/open.js";
19
19
  import { createRequire } from "module";
20
20
  import { createVscodeSettings } from "./commands/project/setup.js";
21
21
  import { initializeProject } from "./commands/config/init.js";
@@ -192,7 +192,32 @@ const options = yargs(hideBin(process.argv))
192
192
  async () => {
193
193
  await openAndroid();
194
194
  }
195
- ).command(
195
+ )
196
+ .command(
197
+ "open-ipa",
198
+ "Open the IPA build output directory",
199
+ {},
200
+ async () => {
201
+ await openIpaOutput();
202
+ }
203
+ )
204
+ .command(
205
+ "open-apk",
206
+ "Open the APK build output directory",
207
+ {},
208
+ async () => {
209
+ await openApkOutput();
210
+ }
211
+ )
212
+ .command(
213
+ "open-bundle",
214
+ "Open the Android Bundle build output directory",
215
+ {},
216
+ async () => {
217
+ await openBundleOutput();
218
+ }
219
+ )
220
+ .command(
196
221
  "setup-vscode",
197
222
  "Create a .vscode folder with recommended Flutter settings",
198
223
  () => {},
@@ -2,8 +2,10 @@ import { LoggerHelpers } from "../../utils/services/logger.js";
2
2
  import { execCommand } from "../../utils/services/exec.js";
3
3
  import { platform } from "os";
4
4
  import { validateFlutterProject, validateIosProject, validateAndroidProject } from "../../utils/validators/validation.js";
5
+ import * as fs from "fs";
6
+ import * as path from "path";
5
7
 
6
- export { openIos, openAndroid };
8
+ export { openIos, openAndroid, openIpaOutput, openBundleOutput, openApkOutput };
7
9
 
8
10
  async function openIos() {
9
11
  LoggerHelpers.info("Opening the iOS project in Xcode...");
@@ -70,3 +72,122 @@ async function openAndroid() {
70
72
  process.exit(1);
71
73
  }
72
74
  }
75
+
76
+ /**
77
+ * Opens the IPA build output directory in Finder (macOS) or File Explorer (Windows/Linux)
78
+ */
79
+ async function openIpaOutput(): Promise<void> {
80
+ if (!validateFlutterProject()) {
81
+ process.exit(1);
82
+ }
83
+
84
+ const ipaPath = path.join(process.cwd(), "build", "ios", "ipa");
85
+
86
+ if (!fs.existsSync(ipaPath)) {
87
+ LoggerHelpers.warning(`IPA output directory not found: ${ipaPath}`);
88
+ LoggerHelpers.info("Build an IPA first using: optikit flutter-build-ipa");
89
+ process.exit(1);
90
+ }
91
+
92
+ try {
93
+ const openCommand = getOpenCommand();
94
+ await execCommand(`${openCommand} "${ipaPath}"`);
95
+ LoggerHelpers.success(`Opened IPA output directory`);
96
+ } catch (error) {
97
+ if (error instanceof Error) {
98
+ LoggerHelpers.error(`Error opening IPA directory: ${error.message}`);
99
+ } else {
100
+ LoggerHelpers.error(`Error opening IPA directory: ${error}`);
101
+ }
102
+ process.exit(1);
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Opens the Android App Bundle output directory in Finder (macOS) or File Explorer (Windows/Linux)
108
+ */
109
+ async function openBundleOutput(): Promise<void> {
110
+ if (!validateFlutterProject()) {
111
+ process.exit(1);
112
+ }
113
+
114
+ const bundlePath = path.join(
115
+ process.cwd(),
116
+ "build",
117
+ "app",
118
+ "outputs",
119
+ "bundle",
120
+ "release"
121
+ );
122
+
123
+ if (!fs.existsSync(bundlePath)) {
124
+ LoggerHelpers.warning(`Bundle output directory not found: ${bundlePath}`);
125
+ LoggerHelpers.info("Build a bundle first using: optikit flutter-build-bundle");
126
+ process.exit(1);
127
+ }
128
+
129
+ try {
130
+ const openCommand = getOpenCommand();
131
+ await execCommand(`${openCommand} "${bundlePath}"`);
132
+ LoggerHelpers.success(`Opened Bundle output directory`);
133
+ } catch (error) {
134
+ if (error instanceof Error) {
135
+ LoggerHelpers.error(`Error opening Bundle directory: ${error.message}`);
136
+ } else {
137
+ LoggerHelpers.error(`Error opening Bundle directory: ${error}`);
138
+ }
139
+ process.exit(1);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Opens the APK build output directory in Finder (macOS) or File Explorer (Windows/Linux)
145
+ */
146
+ async function openApkOutput(): Promise<void> {
147
+ if (!validateFlutterProject()) {
148
+ process.exit(1);
149
+ }
150
+
151
+ const apkPath = path.join(
152
+ process.cwd(),
153
+ "build",
154
+ "app",
155
+ "outputs",
156
+ "flutter-apk"
157
+ );
158
+
159
+ if (!fs.existsSync(apkPath)) {
160
+ LoggerHelpers.warning(`APK output directory not found: ${apkPath}`);
161
+ LoggerHelpers.info("Build an APK first using: optikit flutter-build-apk");
162
+ process.exit(1);
163
+ }
164
+
165
+ try {
166
+ const openCommand = getOpenCommand();
167
+ await execCommand(`${openCommand} "${apkPath}"`);
168
+ LoggerHelpers.success(`Opened APK output directory`);
169
+ } catch (error) {
170
+ if (error instanceof Error) {
171
+ LoggerHelpers.error(`Error opening APK directory: ${error.message}`);
172
+ } else {
173
+ LoggerHelpers.error(`Error opening APK directory: ${error}`);
174
+ }
175
+ process.exit(1);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Returns the appropriate command to open a directory based on the platform
181
+ */
182
+ function getOpenCommand(): string {
183
+ const osPlatform = platform();
184
+
185
+ switch (osPlatform) {
186
+ case "darwin": // macOS
187
+ return "open";
188
+ case "win32": // Windows
189
+ return "start";
190
+ default: // Linux and others
191
+ return "xdg-open";
192
+ }
193
+ }