optikit 1.2.3 → 1.2.5

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,70 @@ 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.5]
14
+
15
+ ### Added
16
+
17
+ - **Simultaneous Build Number Bump:** New `bump-build` command that increments both Android and iOS build numbers simultaneously without changing the version number
18
+ - **Comprehensive Documentation:** Updated USAGE.md with detailed section for the new bump-build command
19
+
20
+ ### Improved
21
+
22
+ - **Build Number Management:** Enhanced flexibility for managing builds across both platforms with a single command
23
+
24
+ ## [1.2.4]
25
+
26
+ ### Fixed
27
+
28
+ - **iOS Build Number Tracking:** Fixed `bump-ios` command to increment the actual iOS build number from `project.pbxproj` instead of deriving from Android build number
29
+ - **Independent Platform Builds:** iOS and Android build numbers now tracked independently as intended
30
+
31
+ ### Added
32
+
33
+ - **iOS Build Number Reader:** New `getCurrentIosBuildNumber()` function to read actual iOS build number from `ios/Runner.xcodeproj/project.pbxproj`
34
+ - **Enhanced Version Display:** `version` command now shows both Android and iOS build numbers separately
35
+
36
+ ### Improved
37
+
38
+ - **Version Management Accuracy:** iOS build numbers now accurately reflect the actual project state
39
+
40
+ ## [1.2.3]
41
+
42
+ ### Fixed
43
+
44
+ - **Silent Validation:** Removed unwanted version number output during command execution by implementing silent validation checks
45
+
46
+ ### Added
47
+
48
+ - **Silent Command Execution:** New `execCommandSilent()` function for validation operations that don't need output logging
49
+
50
+ ### Improved
51
+
52
+ - **User Experience:** Cleaner command output without version information appearing during validation
53
+
54
+ ## [1.2.2]
55
+
56
+ ### Fixed
57
+
58
+ - **Command Naming Conflicts:** Resolved yargs command conflicts that prevented version bump commands from working correctly
59
+ - **Version Bump Accuracy:** Fixed issue where major/minor/patch bumps were only incrementing Android build numbers
60
+
61
+ ### Changed
62
+
63
+ - **Simplified Command Names:**
64
+ - `version bump <type>` renamed to `bump <type>` for major/minor/patch version bumps
65
+ - `version bump-ios` renamed to `bump-ios`
66
+ - `version bump-android` renamed to `bump-android`
67
+ - `version` command renamed to `version` for displaying current version
68
+
69
+ ### Added
70
+
71
+ - **FVM Default Configuration:** Changed default `useFvmByDefault` setting to `true` in `init` command configuration
72
+
73
+ ### Improved
74
+
75
+ - **Documentation:** Updated all documentation files (USAGE.md, VERSION_MANAGEMENT.md, README.md) with new command names and workflows
76
+
13
77
  ## [1.2.1]
14
78
 
15
79
  ### Added
package/USAGE.md CHANGED
@@ -188,6 +188,30 @@ After: 1.0.2+46 (iOS: 1 unchanged)
188
188
 
189
189
  ---
190
190
 
191
+ ### Bump Both Build Numbers
192
+
193
+ Increment both Android and iOS build numbers:
194
+
195
+ ```bash
196
+ optikit bump-build
197
+ ```
198
+
199
+ **What it does:**
200
+
201
+ - Keeps version unchanged
202
+ - Increments Android build number
203
+ - Increments iOS build number
204
+ - Perfect for simultaneous Android and iOS releases
205
+
206
+ **Example:**
207
+
208
+ ```text
209
+ Before: 1.0.2+45 (iOS: 3)
210
+ After: 1.0.2+46 (iOS: 4)
211
+ ```
212
+
213
+ ---
214
+
191
215
  ## Build Commands
192
216
 
193
217
  All build commands support FVM and create automatic backups.
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ import { createRequire } from "module";
14
14
  import { createVscodeSettings } from "./commands/project/setup.js";
15
15
  import { initializeProject } from "./commands/config/init.js";
16
16
  import { rollbackFiles, rollbackRestore } from "./commands/config/rollback.js";
17
- import { bumpVersion, bumpIosBuildOnly, bumpAndroidBuildOnly, showCurrentVersion } from "./commands/version/bump.js";
17
+ import { bumpVersion, bumpIosBuildOnly, bumpAndroidBuildOnly, bumpBothBuilds, showCurrentVersion } from "./commands/version/bump.js";
18
18
  import { listDevices, runApp, runAppInteractive } from "./commands/project/devices.js";
19
19
  const require = createRequire(import.meta.url);
20
20
  const packageInfo = require("../package.json");
@@ -175,6 +175,9 @@ const options = yargs(hideBin(process.argv))
175
175
  })
176
176
  .command("bump-android", "Increment Android build number only", () => { }, async () => {
177
177
  await bumpAndroidBuildOnly();
178
+ })
179
+ .command("bump-build", "Increment both Android and iOS build numbers", () => { }, async () => {
180
+ await bumpBothBuilds();
178
181
  })
179
182
  .command("version", "Show current version information", () => { }, async () => {
180
183
  await showCurrentVersion();
@@ -1,9 +1,9 @@
1
1
  import { validateFlutterProject } from "../../utils/validators/validation.js";
2
2
  import { LoggerHelpers } from "../../utils/services/logger.js";
3
- import { getCurrentVersion, incrementVersion, formatVersion } from "../../utils/helpers/version.js";
3
+ import { getCurrentVersion, incrementVersion, formatVersion, getCurrentIosBuildNumber } from "../../utils/helpers/version.js";
4
4
  import { updateFlutterVersion } from "./update.js";
5
5
  import chalk from "chalk";
6
- export { bumpVersion, bumpIosBuildOnly, bumpAndroidBuildOnly, showCurrentVersion };
6
+ export { bumpVersion, bumpIosBuildOnly, bumpAndroidBuildOnly, bumpBothBuilds, showCurrentVersion };
7
7
  /**
8
8
  * Bumps version with semantic versioning (major, minor, patch)
9
9
  * Android build number increments with version
@@ -62,14 +62,15 @@ async function bumpIosBuildOnly() {
62
62
  try {
63
63
  const current = getCurrentVersion();
64
64
  const currentVersionString = `${current.major}.${current.minor}.${current.patch}`;
65
- // iOS build number increments from current Android build number
66
- const nextIosBuild = current.buildNumber + 1;
65
+ // Read actual iOS build number from project.pbxproj
66
+ const currentIosBuild = getCurrentIosBuildNumber();
67
+ const nextIosBuild = currentIosBuild + 1;
67
68
  LoggerHelpers.info(`Current version: ${formatVersion(current)}`);
68
69
  LoggerHelpers.info("Incrementing iOS build number only (for TestFlight)...");
69
70
  console.log(chalk.cyan("\nBuild number changes:"));
70
71
  console.log(chalk.gray(" Version:"), chalk.white(`${currentVersionString} (unchanged)`));
71
72
  console.log(chalk.gray(" Android:"), chalk.white(`${current.buildNumber} (unchanged)`));
72
- console.log(chalk.gray(" iOS:"), chalk.white(`${current.buildNumber} → ${nextIosBuild}`), chalk.green("(incremented)"));
73
+ console.log(chalk.gray(" iOS:"), chalk.white(`${currentIosBuild} → ${nextIosBuild}`), chalk.green("(incremented)"));
73
74
  console.log();
74
75
  // Update only iOS build number
75
76
  await updateFlutterVersion(currentVersionString, "", // Empty string means don't update Android
@@ -123,6 +124,46 @@ async function bumpAndroidBuildOnly() {
123
124
  process.exit(1);
124
125
  }
125
126
  }
127
+ /**
128
+ * Increments BOTH Android and iOS build numbers
129
+ * Keeps version unchanged
130
+ * Perfect for updating both platforms simultaneously
131
+ */
132
+ async function bumpBothBuilds() {
133
+ // Pre-flight validation
134
+ if (!validateFlutterProject()) {
135
+ process.exit(1);
136
+ }
137
+ try {
138
+ const current = getCurrentVersion();
139
+ const currentVersionString = `${current.major}.${current.minor}.${current.patch}`;
140
+ // Read actual iOS build number from project.pbxproj
141
+ const currentIosBuild = getCurrentIosBuildNumber();
142
+ const nextAndroidBuild = current.buildNumber + 1;
143
+ const nextIosBuild = currentIosBuild + 1;
144
+ LoggerHelpers.info(`Current version: ${formatVersion(current)}`);
145
+ LoggerHelpers.info("Incrementing both Android and iOS build numbers...");
146
+ console.log(chalk.cyan("\nBuild number changes:"));
147
+ console.log(chalk.gray(" Version:"), chalk.white(`${currentVersionString} (unchanged)`));
148
+ console.log(chalk.gray(" Android:"), chalk.white(`${current.buildNumber} → ${nextAndroidBuild}`), chalk.green("(incremented)"));
149
+ console.log(chalk.gray(" iOS:"), chalk.white(`${currentIosBuild} → ${nextIosBuild}`), chalk.green("(incremented)"));
150
+ console.log();
151
+ // Update both Android and iOS build numbers
152
+ await updateFlutterVersion(currentVersionString, nextAndroidBuild.toString(), nextIosBuild.toString());
153
+ LoggerHelpers.success(`Both build numbers incremented successfully`);
154
+ console.log(chalk.gray("\nResult:"), chalk.white(`${currentVersionString}+${nextAndroidBuild} (iOS: ${nextIosBuild})`));
155
+ console.log(chalk.gray("Use this for:"), chalk.white("Simultaneous Android and iOS releases"));
156
+ }
157
+ catch (error) {
158
+ if (error instanceof Error) {
159
+ LoggerHelpers.error(`Error incrementing build numbers: ${error.message}`);
160
+ }
161
+ else {
162
+ LoggerHelpers.error(`Error incrementing build numbers: ${error}`);
163
+ }
164
+ process.exit(1);
165
+ }
166
+ }
126
167
  /**
127
168
  * Shows current version information
128
169
  */
@@ -130,12 +171,14 @@ async function showCurrentVersion() {
130
171
  try {
131
172
  const current = getCurrentVersion();
132
173
  const versionString = formatVersion(current);
174
+ const currentIosBuild = getCurrentIosBuildNumber();
133
175
  console.log(chalk.bold("\n📱 Current Version Information\n"));
134
176
  console.log(chalk.cyan("Version:"), chalk.white.bold(versionString));
135
177
  console.log(chalk.gray(" Major:"), chalk.white(current.major));
136
178
  console.log(chalk.gray(" Minor:"), chalk.white(current.minor));
137
179
  console.log(chalk.gray(" Patch:"), chalk.white(current.patch));
138
- console.log(chalk.gray(" Build:"), chalk.white(current.buildNumber));
180
+ console.log(chalk.gray(" Android Build:"), chalk.white(current.buildNumber));
181
+ console.log(chalk.gray(" iOS Build:"), chalk.white(currentIosBuild));
139
182
  console.log();
140
183
  }
141
184
  catch (error) {
@@ -1,6 +1,7 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- export { parseVersion, incrementVersion, getCurrentVersion };
3
+ import { LoggerHelpers } from "../services/logger.js";
4
+ export { parseVersion, incrementVersion, getCurrentVersion, getCurrentIosBuildNumber };
4
5
  /**
5
6
  * Parses a version string in format "X.Y.Z+B"
6
7
  * @param versionString - Version string (e.g., "1.2.3+45")
@@ -78,3 +79,28 @@ export function getNextBuildNumber() {
78
79
  const current = getCurrentVersion();
79
80
  return current.buildNumber + 1;
80
81
  }
82
+ /**
83
+ * Gets the current iOS build number from project.pbxproj
84
+ * @returns Current iOS build number, or 1 if not found
85
+ */
86
+ function getCurrentIosBuildNumber() {
87
+ try {
88
+ const projectPbxProjPath = path.join(process.cwd(), "ios/Runner.xcodeproj/project.pbxproj");
89
+ if (!fs.existsSync(projectPbxProjPath)) {
90
+ LoggerHelpers.warning("iOS project.pbxproj not found. Defaulting to build number 1.");
91
+ return 1;
92
+ }
93
+ const projectContent = fs.readFileSync(projectPbxProjPath, 'utf8');
94
+ // Match CURRENT_PROJECT_VERSION = <number>;
95
+ const buildMatch = projectContent.match(/CURRENT_PROJECT_VERSION\s*=\s*(\d+);/);
96
+ if (!buildMatch) {
97
+ LoggerHelpers.warning("CURRENT_PROJECT_VERSION not found in project.pbxproj. Defaulting to build number 1.");
98
+ return 1;
99
+ }
100
+ return parseInt(buildMatch[1], 10);
101
+ }
102
+ catch (error) {
103
+ LoggerHelpers.warning(`Error reading iOS build number: ${error instanceof Error ? error.message : error}. Defaulting to 1.`);
104
+ return 1;
105
+ }
106
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "optikit",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "OptiKit CLI",
5
5
  "main": "src/cli.ts",
6
6
  "type": "module",
package/src/cli.ts CHANGED
@@ -24,6 +24,7 @@ import {
24
24
  bumpVersion,
25
25
  bumpIosBuildOnly,
26
26
  bumpAndroidBuildOnly,
27
+ bumpBothBuilds,
27
28
  showCurrentVersion
28
29
  } from "./commands/version/bump.js";
29
30
  import { listDevices, runApp, runAppInteractive } from "./commands/project/devices.js";
@@ -283,6 +284,14 @@ const options = yargs(hideBin(process.argv))
283
284
  await bumpAndroidBuildOnly();
284
285
  }
285
286
  )
287
+ .command(
288
+ "bump-build",
289
+ "Increment both Android and iOS build numbers",
290
+ () => {},
291
+ async () => {
292
+ await bumpBothBuilds();
293
+ }
294
+ )
286
295
  .command(
287
296
  "version",
288
297
  "Show current version information",
@@ -4,7 +4,8 @@ import {
4
4
  getCurrentVersion,
5
5
  incrementVersion,
6
6
  formatVersion,
7
- getNextBuildNumber
7
+ getNextBuildNumber,
8
+ getCurrentIosBuildNumber
8
9
  } from "../../utils/helpers/version.js";
9
10
  import { updateFlutterVersion } from "./update.js";
10
11
  import chalk from "chalk";
@@ -13,6 +14,7 @@ export {
13
14
  bumpVersion,
14
15
  bumpIosBuildOnly,
15
16
  bumpAndroidBuildOnly,
17
+ bumpBothBuilds,
16
18
  showCurrentVersion
17
19
  };
18
20
 
@@ -87,8 +89,9 @@ async function bumpIosBuildOnly(): Promise<void> {
87
89
  const current = getCurrentVersion();
88
90
  const currentVersionString = `${current.major}.${current.minor}.${current.patch}`;
89
91
 
90
- // iOS build number increments from current Android build number
91
- const nextIosBuild = current.buildNumber + 1;
92
+ // Read actual iOS build number from project.pbxproj
93
+ const currentIosBuild = getCurrentIosBuildNumber();
94
+ const nextIosBuild = currentIosBuild + 1;
92
95
 
93
96
  LoggerHelpers.info(`Current version: ${formatVersion(current)}`);
94
97
  LoggerHelpers.info("Incrementing iOS build number only (for TestFlight)...");
@@ -96,7 +99,7 @@ async function bumpIosBuildOnly(): Promise<void> {
96
99
  console.log(chalk.cyan("\nBuild number changes:"));
97
100
  console.log(chalk.gray(" Version:"), chalk.white(`${currentVersionString} (unchanged)`));
98
101
  console.log(chalk.gray(" Android:"), chalk.white(`${current.buildNumber} (unchanged)`));
99
- console.log(chalk.gray(" iOS:"), chalk.white(`${current.buildNumber} → ${nextIosBuild}`), chalk.green("(incremented)"));
102
+ console.log(chalk.gray(" iOS:"), chalk.white(`${currentIosBuild} → ${nextIosBuild}`), chalk.green("(incremented)"));
100
103
  console.log();
101
104
 
102
105
  // Update only iOS build number
@@ -163,6 +166,56 @@ async function bumpAndroidBuildOnly(): Promise<void> {
163
166
  }
164
167
  }
165
168
 
169
+ /**
170
+ * Increments BOTH Android and iOS build numbers
171
+ * Keeps version unchanged
172
+ * Perfect for updating both platforms simultaneously
173
+ */
174
+ async function bumpBothBuilds(): Promise<void> {
175
+ // Pre-flight validation
176
+ if (!validateFlutterProject()) {
177
+ process.exit(1);
178
+ }
179
+
180
+ try {
181
+ const current = getCurrentVersion();
182
+ const currentVersionString = `${current.major}.${current.minor}.${current.patch}`;
183
+
184
+ // Read actual iOS build number from project.pbxproj
185
+ const currentIosBuild = getCurrentIosBuildNumber();
186
+ const nextAndroidBuild = current.buildNumber + 1;
187
+ const nextIosBuild = currentIosBuild + 1;
188
+
189
+ LoggerHelpers.info(`Current version: ${formatVersion(current)}`);
190
+ LoggerHelpers.info("Incrementing both Android and iOS build numbers...");
191
+
192
+ console.log(chalk.cyan("\nBuild number changes:"));
193
+ console.log(chalk.gray(" Version:"), chalk.white(`${currentVersionString} (unchanged)`));
194
+ console.log(chalk.gray(" Android:"), chalk.white(`${current.buildNumber} → ${nextAndroidBuild}`), chalk.green("(incremented)"));
195
+ console.log(chalk.gray(" iOS:"), chalk.white(`${currentIosBuild} → ${nextIosBuild}`), chalk.green("(incremented)"));
196
+ console.log();
197
+
198
+ // Update both Android and iOS build numbers
199
+ await updateFlutterVersion(
200
+ currentVersionString,
201
+ nextAndroidBuild.toString(),
202
+ nextIosBuild.toString()
203
+ );
204
+
205
+ LoggerHelpers.success(`Both build numbers incremented successfully`);
206
+ console.log(chalk.gray("\nResult:"), chalk.white(`${currentVersionString}+${nextAndroidBuild} (iOS: ${nextIosBuild})`));
207
+ console.log(chalk.gray("Use this for:"), chalk.white("Simultaneous Android and iOS releases"));
208
+
209
+ } catch (error) {
210
+ if (error instanceof Error) {
211
+ LoggerHelpers.error(`Error incrementing build numbers: ${error.message}`);
212
+ } else {
213
+ LoggerHelpers.error(`Error incrementing build numbers: ${error}`);
214
+ }
215
+ process.exit(1);
216
+ }
217
+ }
218
+
166
219
  /**
167
220
  * Shows current version information
168
221
  */
@@ -170,13 +223,15 @@ async function showCurrentVersion(): Promise<void> {
170
223
  try {
171
224
  const current = getCurrentVersion();
172
225
  const versionString = formatVersion(current);
226
+ const currentIosBuild = getCurrentIosBuildNumber();
173
227
 
174
228
  console.log(chalk.bold("\n📱 Current Version Information\n"));
175
229
  console.log(chalk.cyan("Version:"), chalk.white.bold(versionString));
176
230
  console.log(chalk.gray(" Major:"), chalk.white(current.major));
177
231
  console.log(chalk.gray(" Minor:"), chalk.white(current.minor));
178
232
  console.log(chalk.gray(" Patch:"), chalk.white(current.patch));
179
- console.log(chalk.gray(" Build:"), chalk.white(current.buildNumber));
233
+ console.log(chalk.gray(" Android Build:"), chalk.white(current.buildNumber));
234
+ console.log(chalk.gray(" iOS Build:"), chalk.white(currentIosBuild));
180
235
  console.log();
181
236
 
182
237
  } catch (error) {
@@ -2,7 +2,7 @@ import fs from "fs";
2
2
  import path from "path";
3
3
  import { LoggerHelpers } from "../services/logger.js";
4
4
 
5
- export { parseVersion, incrementVersion, getCurrentVersion, VersionInfo };
5
+ export { parseVersion, incrementVersion, getCurrentVersion, getCurrentIosBuildNumber, VersionInfo };
6
6
 
7
7
  /**
8
8
  * Version information structure
@@ -107,3 +107,33 @@ export function getNextBuildNumber(): number {
107
107
  const current = getCurrentVersion();
108
108
  return current.buildNumber + 1;
109
109
  }
110
+
111
+ /**
112
+ * Gets the current iOS build number from project.pbxproj
113
+ * @returns Current iOS build number, or 1 if not found
114
+ */
115
+ function getCurrentIosBuildNumber(): number {
116
+ try {
117
+ const projectPbxProjPath = path.join(process.cwd(), "ios/Runner.xcodeproj/project.pbxproj");
118
+
119
+ if (!fs.existsSync(projectPbxProjPath)) {
120
+ LoggerHelpers.warning("iOS project.pbxproj not found. Defaulting to build number 1.");
121
+ return 1;
122
+ }
123
+
124
+ const projectContent = fs.readFileSync(projectPbxProjPath, 'utf8');
125
+
126
+ // Match CURRENT_PROJECT_VERSION = <number>;
127
+ const buildMatch = projectContent.match(/CURRENT_PROJECT_VERSION\s*=\s*(\d+);/);
128
+
129
+ if (!buildMatch) {
130
+ LoggerHelpers.warning("CURRENT_PROJECT_VERSION not found in project.pbxproj. Defaulting to build number 1.");
131
+ return 1;
132
+ }
133
+
134
+ return parseInt(buildMatch[1], 10);
135
+ } catch (error) {
136
+ LoggerHelpers.warning(`Error reading iOS build number: ${error instanceof Error ? error.message : error}. Defaulting to 1.`);
137
+ return 1;
138
+ }
139
+ }