@microtronics/studio-cli 0.32.2 → 0.33.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/CHANGELOG.md CHANGED
@@ -1,10 +1,21 @@
1
+ # Changelog
1
2
 
2
-
3
- ## 0.32.2 (2025-06-02)
4
-
3
+ ## 0.33.0 (2025-09-01)
5
4
 
6
- ### Bug Fixes
5
+ ### Features
7
6
 
7
+ * **cli:** add description to CLI tool usage ([97e8562](https://bitbucket.org/microtronics-core/vscode-studio/commits/97e85625a7c6d11070e2713f3ec3d2c24691854a))
8
+ * **cli:** add support for parsing unknown long options ([fa6523c](https://bitbucket.org/microtronics-core/vscode-studio/commits/fa6523caef791d508b31ed5d563452b616e99ae0))
9
+ * **cli:** support custom ini file in manifest ([5ae2741](https://bitbucket.org/microtronics-core/vscode-studio/commits/5ae2741ad379258fee95311fd28acc8b3dd1bdb6))
10
+ * **cli:** support manifest overwrites with deep merge ([10b69e2](https://bitbucket.org/microtronics-core/vscode-studio/commits/10b69e29c9426bec08022610b66e85b86cee79c9))
11
+
12
+ ## 0.32.3 (2025-06-11)
13
+
14
+ ## 0.32.2 (2025-06-02)
15
+
16
+
17
+ ### Bug Fixes
18
+
8
19
  * **studio-cli:** improve semver validation in dependency check ([2238827](https://bitbucket.org/microtronics-core/vscode-studio/commits/2238827380cdbe56fa5798c6de50c284df4da4c7))
9
20
 
10
21
  ## 0.32.1 (2025-06-02)
@@ -183,7 +194,7 @@
183
194
 
184
195
  ## 0.19.1 (2025-02-20)
185
196
 
186
- # Changelog
197
+
187
198
 
188
199
  ## 0.19.0 (2025-02-19)
189
200
 
@@ -2196,6 +2196,7 @@ export declare namespace Manifest {
2196
2196
  dlo?: {
2197
2197
  mainFile: string;
2198
2198
  compileOptions: string[];
2199
+ iniFile?: string;
2199
2200
  };
2200
2201
  registry?: {
2201
2202
  id?: string;
@@ -2234,6 +2235,8 @@ export declare namespace Manifest {
2234
2235
  embedded = "$embedded",
2235
2236
  pure = "$pure"
2236
2237
  }
2238
+ export function setOverwrites(manifest: Partial<Manifest.Manifest> | null): void;
2239
+ export function clearOverwrites(): void;
2237
2240
  /**
2238
2241
  * Read the studio.json manifest and parse it
2239
2242
  * @param cwd
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseUnknownLongOptions = parseUnknownLongOptions;
4
+ /**
5
+ * Set a nested value in an object by a dot-separated path.
6
+ * Example: setByDotPath(obj, 'dlo.mainFile', 'x') => obj = { dlo: { mainFile: 'x' } }
7
+ */
8
+ function setByDotPath(target, path, value) {
9
+ const parts = path.split('.').filter(Boolean);
10
+ let cur = target;
11
+ for (let i = 0; i < parts.length; i++) {
12
+ const key = parts[i];
13
+ const isLeaf = i === parts.length - 1;
14
+ if (isLeaf) {
15
+ cur[key] = value;
16
+ }
17
+ else {
18
+ if (typeof cur[key] !== 'object' || cur[key] === null || Array.isArray(cur[key])) {
19
+ cur[key] = {};
20
+ }
21
+ cur = cur[key];
22
+ }
23
+ }
24
+ }
25
+ /**
26
+ * Parse unknown long options (starting with `--`) into a key/value object.
27
+ * - Supports `--key=value` and `--key value`
28
+ */
29
+ function parseUnknownLongOptions(command) {
30
+ const argv = command.args;
31
+ const result = {};
32
+ for (let i = 0; i < argv.length; i++) {
33
+ const token = argv[i];
34
+ // Only process long options that start with `--`
35
+ if (!token || !token.startsWith('--')) {
36
+ continue;
37
+ }
38
+ // Split inline assignment: --key=value
39
+ const [flag, inlineVal] = token.split('=', 2);
40
+ // Unknown option: collect it
41
+ const key = flag.slice(2); // remove leading '--'
42
+ let value = true;
43
+ if (inlineVal !== undefined) {
44
+ value = inlineVal;
45
+ }
46
+ else {
47
+ // If next token exists and doesn't look like another flag, use it as the value
48
+ const next = argv[i + 1];
49
+ if (next && !next.startsWith('-')) {
50
+ value = next;
51
+ i++; // consume the value
52
+ }
53
+ }
54
+ // Dot-notation => nested object
55
+ if (key.includes('.')) {
56
+ setByDotPath(result, key, value);
57
+ }
58
+ else {
59
+ result[key] = value;
60
+ }
61
+ }
62
+ return result;
63
+ }
64
+ //# sourceMappingURL=argumentParser.js.map
package/out/globals.js CHANGED
@@ -71,7 +71,7 @@ var Globals;
71
71
  }
72
72
  }
73
73
  // load the projects main.ini and overwrite existing defines
74
- const mainIni = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.dlo.mainINI);
74
+ const mainIni = vscode_uri_1.Utils.joinPath(cwd, manifest.dlo?.iniFile || defaultFiles_1.DefaultFiles.filePaths.dlo.mainINI);
75
75
  if (await fs.stat(mainIni)) {
76
76
  const iniContent = await readIniFile(fs, mainIni);
77
77
  Object.assign(allDefines, iniContent);
package/out/main.js CHANGED
@@ -12,6 +12,7 @@ const globals_1 = require("./globals");
12
12
  const update_notifier_1 = __importDefault(require("update-notifier"));
13
13
  const api_1 = require("./api");
14
14
  const log_1 = require("./log");
15
+ const argumentParser_1 = require("./argumentParser");
15
16
  const program = new commander_1.Command();
16
17
  const notifier = (0, update_notifier_1.default)({ pkg: package_json_1.default });
17
18
  const logger = new log_1.Log.Logger();
@@ -30,14 +31,21 @@ const devPath = () => {
30
31
  };
31
32
  const cwd = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.file(process.cwd()), devPath());
32
33
  program.version(package_json_1.default.version).usage('<command>');
34
+ program.description('This tool is used to manage the project dependencies, build, package and publish the project.\n' +
35
+ 'The manifest options can be overwritten with the --option=value syntax.\n' +
36
+ 'Example: "studio build --dlo.mainFile="./dlo/test.dlo" will overwrite the dlo.mainFile option of the manifest.\n' +
37
+ '\nUse "studio --help" for more information.');
33
38
  /**
34
39
  * Executes a task and ensures that the update available notification is sent after the task completes,
35
40
  * regardless of whether it succeeds or fails.
36
41
  *
42
+ * @param command
37
43
  * @param {Promise<void>} task - A promise representing the task to be executed.
38
44
  * @return {void} This function does not return a value.
39
45
  */
40
- function main(task) {
46
+ function main(command, task) {
47
+ const manifestOptions = (0, argumentParser_1.parseUnknownLongOptions)(command);
48
+ api_1.Manifest.setOverwrites(manifestOptions);
41
49
  // todo add task catch handler like: https://github.com/microsoft/vscode-vsce/blob/5518f2f242983d23f1983f6dd0350474f2011543/src/main.ts#L51
42
50
  task.finally(() => {
43
51
  notifier.notify();
@@ -94,9 +102,10 @@ program
94
102
  .allowExcessArguments(true)
95
103
  .addOption(optionStudioEnv)
96
104
  .addOption(optionStudioToken)
97
- .action((dependencies, opts) => {
105
+ .allowUnknownOption(true)
106
+ .action((dependencies, opts, command) => {
98
107
  const { env, token } = getDefaultOptions(opts);
99
- main((0, api_1.install)(cwd, cliFS_1.cliFS, env, token, dependencies));
108
+ main(command, (0, api_1.install)(cwd, cliFS_1.cliFS, env, token, dependencies));
100
109
  });
101
110
  program
102
111
  .command('build')
@@ -104,9 +113,10 @@ program
104
113
  .allowExcessArguments(true)
105
114
  .addOption(optionStudioEnv)
106
115
  .addOption(optionStudioToken)
107
- .action(opts => {
116
+ .allowUnknownOption(true)
117
+ .action((opts, command) => {
108
118
  const { env, token } = getDefaultOptions(opts);
109
- main((0, api_1.build)(cwd, cliFS_1.cliFS, logger, env, token, opts.part));
119
+ main(command, (0, api_1.build)(cwd, cliFS_1.cliFS, logger, env, token, opts.part));
110
120
  });
111
121
  program
112
122
  .command('publish')
@@ -114,10 +124,11 @@ program
114
124
  .addOption(optionAllowedBackends)
115
125
  .addOption(optionStudioEnv)
116
126
  .addOption(optionStudioToken)
127
+ .allowUnknownOption(true)
117
128
  .option('-i, --packagePath <path>', 'Publish the provided library or app package. Use "*" for autodetection.')
118
- .action(async (opts) => {
129
+ .action(async (opts, command) => {
119
130
  const { env, token } = getDefaultOptions(opts);
120
- main((0, api_1.publish)(cwd, cliFS_1.cliFS, logger, env, token, opts.allowedBackends, opts.phase, opts.packagePath));
131
+ main(command, (0, api_1.publish)(cwd, cliFS_1.cliFS, logger, env, token, opts.allowedBackends, opts.phase, opts.packagePath));
121
132
  });
122
133
  program
123
134
  .command('package')
@@ -126,9 +137,10 @@ program
126
137
  .addOption(optionReleasePhase)
127
138
  .addOption(optionStudioEnv)
128
139
  .addOption(optionStudioToken)
129
- .action(async (opts) => {
140
+ .allowUnknownOption(true)
141
+ .action(async (opts, command) => {
130
142
  const { env, token } = getDefaultOptions(opts);
131
- main((0, api_1.pack)(cwd, cliFS_1.cliFS, logger, env, token, opts.phase));
143
+ main(command, (0, api_1.pack)(cwd, cliFS_1.cliFS, logger, env, token, opts.phase));
132
144
  });
133
145
  module.exports = function (argv) {
134
146
  program.parse(argv);
package/out/manifest.js CHANGED
@@ -10,9 +10,9 @@ const image_dimensions_1 = require("image-dimensions");
10
10
  const file_type_checker_1 = require("file-type-checker");
11
11
  const registryAPI_1 = require("./registryAPI");
12
12
  const preload_1 = __importDefault(require("semver/preload"));
13
- const DeviceProfiles_1 = require("./DeviceProfiles");
14
13
  const apm_1 = require("./package/apm");
15
14
  var isNumeric = helper_1.Helper.isNumeric;
15
+ const deepmerge_ts_1 = require("deepmerge-ts");
16
16
  const PRODUCT_ID_SUPPORTED = '52v007';
17
17
  const SEMVER_SUPPORTED = '53v001';
18
18
  const ADDON_SUPPORTED = '54v001';
@@ -20,13 +20,17 @@ const ADDON_SUPPORTED = '54v001';
20
20
  const manifestCache = {
21
21
  _manifest: null,
22
22
  _stat: null,
23
+ _overwrites: null,
23
24
  get manifest() {
24
25
  // clone the cached object to prevent any reference changes
25
- return structuredClone(this._manifest);
26
+ return (0, deepmerge_ts_1.deepmerge)(structuredClone(this._manifest), manifestCache._overwrites || {});
26
27
  },
27
28
  set manifest(manifest) {
28
29
  this._manifest = manifest;
29
30
  },
31
+ set overwrites(manifest) {
32
+ this._overwrites = manifest;
33
+ },
30
34
  get stat() {
31
35
  return this._stat;
32
36
  },
@@ -73,6 +77,14 @@ var Manifest;
73
77
  PovLocation["embedded"] = "$embedded";
74
78
  PovLocation["pure"] = "$pure";
75
79
  })(PovLocation = Manifest.PovLocation || (Manifest.PovLocation = {}));
80
+ function setOverwrites(manifest) {
81
+ manifestCache.overwrites = manifest;
82
+ }
83
+ Manifest.setOverwrites = setOverwrites;
84
+ function clearOverwrites() {
85
+ manifestCache.overwrites = null;
86
+ }
87
+ Manifest.clearOverwrites = clearOverwrites;
76
88
  /**
77
89
  * Read the studio.json manifest and parse it
78
90
  * @param cwd
@@ -112,8 +124,6 @@ var Manifest;
112
124
  */
113
125
  async function write(cwd, fs, manifest) {
114
126
  manifestCache.clear();
115
- // patch the options if they are not valid for a specific device profile
116
- patchDloCompileOptionsBasedOnDpid(manifest);
117
127
  removeDeprecatedOptions(manifest);
118
128
  return fs.writeFile(vscode_uri_1.Utils.joinPath(cwd, Manifest.fileName), JSON.stringify(manifest, null, '\t'));
119
129
  }
@@ -425,32 +435,6 @@ function validateProjectVersion(manifest) {
425
435
  }
426
436
  }
427
437
  }
428
- /**
429
- * Some devices doesn't support compression. this function does patch the option if it's not supported
430
- * @param manifest
431
- */
432
- function patchDloCompileOptionsBasedOnDpid(manifest) {
433
- if (!manifest.dpid) {
434
- return;
435
- }
436
- const deviceProfile = DeviceProfiles_1.DeviceProfiles[manifest.dpid];
437
- const compileRestrictions = deviceProfile?.dlo?.compileRestrictions || {};
438
- const { compileOptions } = manifest.dlo || {};
439
- if (compileOptions) {
440
- compileOptions.forEach((param, idx) => {
441
- try {
442
- const paramType = param.substring(0, 2);
443
- const paramValue = param.substring(2);
444
- if (Object.hasOwn(compileRestrictions, paramType) && `${paramValue}` !== `${compileRestrictions[paramType]}`) {
445
- compileOptions[idx] = `${paramType}${compileRestrictions[paramType]}`;
446
- }
447
- }
448
- catch (e) {
449
- // todo?
450
- }
451
- });
452
- }
453
- }
454
438
  function removeDeprecatedOptions(manifest) {
455
439
  if (manifest.registry) {
456
440
  delete manifest.registry.allowedBackends;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microtronics/studio-cli",
3
- "version": "0.32.2",
3
+ "version": "0.33.0",
4
4
  "description": "Microtronics Studio CLI Tool",
5
5
  "main": "./out/api.js",
6
6
  "typings": "./dist/studio-cli.d.ts",
@@ -25,12 +25,14 @@
25
25
  "author": "Microtronics",
26
26
  "license": "ISC",
27
27
  "dependencies": {
28
+ "@gera2ld/tarjs": "^0.3.1",
28
29
  "ajv": "^8.17.1",
29
30
  "ajv-formats": "^3.0.1",
30
31
  "ajv-keywords": "^5.1.0",
31
32
  "chalk": "^5.4.1",
32
33
  "commander": "^12.1.0",
33
34
  "cross-fetch": "^4.0.0",
35
+ "deepmerge-ts": "^7.1.5",
34
36
  "dotenv": "^16.4.7",
35
37
  "file-type-checker": "^1.1.2",
36
38
  "glob": "^11.0.1",
@@ -41,7 +43,6 @@
41
43
  "openapi-fetch": "^0.13.0",
42
44
  "pako": "^2.1.0",
43
45
  "semver": "^7.7.2",
44
- "@gera2ld/tarjs": "^0.3.1",
45
46
  "tinytar-fix": "^0.1.1",
46
47
  "update-notifier": "^7.3.1",
47
48
  "vscode-uri": "^3.0.8",