@microtronics/studio-cli 0.43.0 → 0.45.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,16 +1,25 @@
1
1
  # Changelog
2
2
 
3
- ## 0.43.0 (2026-01-19)
3
+ ## 0.45.0 (2026-02-04)
4
4
 
5
5
  ### Features
6
6
 
7
- * add debug option to enable mdnCom logging ([34dfd29](https://bitbucket.org/microtronics-core/vscode-studio/commits/34dfd29cf2f5e6776e31463a85f0484a6907b13b))
8
- * add support for uploading any amx file to an usb device ([e89f108](https://bitbucket.org/microtronics-core/vscode-studio/commits/e89f1087e22e6c0cc88c8b68bbbcc4f1d813dc4f))
9
- * add USB device detection and listing functionality ([906e3e1](https://bitbucket.org/microtronics-core/vscode-studio/commits/906e3e12bca647f5ceba8b4196f00d507be163d9))
10
- * add USB device listing command ([fb16e1a](https://bitbucket.org/microtronics-core/vscode-studio/commits/fb16e1ab0c9a52e38467b664e4b2b6adb135a249)), closes [#close](https://bitbucket.org/microtronics-core/vscode-studio/issues/close)
11
-
12
- ### Bug Fixes
13
-
7
+ * add development deployment workflow with USB and myDatanet integration ([0503666](https://bitbucket.org/microtronics-core/vscode-studio/commits/05036666d0a80f419b76ed4140037e11281d0621))
8
+ * add VSCode extension support to MyDatanetClient ([67866fc](https://bitbucket.org/microtronics-core/vscode-studio/commits/67866fc2ab069a108df4594124fcb38b13ca1b68))
9
+
10
+ ## 0.44.0 (2026-01-19)
11
+
12
+ ## 0.43.0 (2026-01-19)
13
+
14
+ ### Features
15
+
16
+ * add debug option to enable mdnCom logging ([34dfd29](https://bitbucket.org/microtronics-core/vscode-studio/commits/34dfd29cf2f5e6776e31463a85f0484a6907b13b))
17
+ * add support for uploading any amx file to an usb device ([e89f108](https://bitbucket.org/microtronics-core/vscode-studio/commits/e89f1087e22e6c0cc88c8b68bbbcc4f1d813dc4f))
18
+ * add USB device detection and listing functionality ([906e3e1](https://bitbucket.org/microtronics-core/vscode-studio/commits/906e3e12bca647f5ceba8b4196f00d507be163d9))
19
+ * add USB device listing command ([fb16e1a](https://bitbucket.org/microtronics-core/vscode-studio/commits/fb16e1ab0c9a52e38467b664e4b2b6adb135a249)), closes [#close](https://bitbucket.org/microtronics-core/vscode-studio/issues/close)
20
+
21
+ ### Bug Fixes
22
+
14
23
  * ensure proper exit code on successful USB upload ([cc1ae63](https://bitbucket.org/microtronics-core/vscode-studio/commits/cc1ae632669e785017c2afaa689c3750ba22d7fb))
15
24
 
16
25
  ## 0.42.0 (2026-01-13)
package/README.md CHANGED
@@ -21,9 +21,181 @@ For a reference on all the available `studio-cli` commands, run `studio-cli --he
21
21
 
22
22
  ## Requirements
23
23
 
24
- [Node.js](https://nodejs.org/en/) at least `20.x.x`.
24
+ [Node.js](https://nodejs.org/en/) version `22` or higher.
25
25
 
26
26
 
27
+ ## Commands
28
+
29
+ ### install (alias: i)
30
+ Install all dependencies in your project.
31
+
32
+ ```console
33
+ $ studio-cli install [dependency...]
34
+ ```
35
+
36
+ **Options:**
37
+ - `-e, --env <environment>` - CLI target environment (defaults to STUDIO_ENV environment variable)
38
+ - `--token <API-token>` - API Access Token (defaults to STUDIO_TOKEN environment variable)
39
+
40
+ **Examples:**
41
+ ```console
42
+ $ studio-cli install
43
+ $ studio-cli i
44
+ $ studio-cli install dependency-name
45
+ ```
46
+
47
+ ### build
48
+ Build the project.
49
+
50
+ ```console
51
+ $ studio-cli build [options]
52
+ ```
53
+
54
+ **Options:**
55
+ - `-p, --part <APM part>` - APM part that should be built
56
+ - Available parts: `dde`, `dlo`, `pov`, `blo`, `dfiles`
57
+ - `-e, --env <environment>` - CLI target environment
58
+ - Available environments: `lucky`, `wynni`, `production` (default)
59
+ - `--token <API-token>` - API Access Token
60
+
61
+ **Manifest Overrides:**
62
+ You can overwrite manifest options using the `--option=value` syntax.
63
+
64
+ **Examples:**
65
+ ```console
66
+ $ studio-cli build
67
+ $ studio-cli build --part dlo
68
+ $ studio-cli build --env wynni
69
+ $ studio-cli build --dlo.mainFile="./dlo/test.dlo"
70
+ ```
71
+
72
+ ### publish
73
+ Publish the project to the registry.
74
+
75
+ ```console
76
+ $ studio-cli publish [options]
77
+ ```
78
+
79
+ **Options:**
80
+ - `-ph, --phase <release phase>` - Specify a release phase (default: `release`)
81
+ - Available phases: `alpha`, `beta`, `rc`, `release`, `stage`, `passive`, `withdrawn`
82
+ - `--allowedBackends <null|*|server.xz;server.yz>` - Specify the allowedBackends deployment for this version
83
+ - `null` - No restrictions (default)
84
+ - `*` - All backends allowed
85
+ - `server.xz;server.yz` - Specific backend servers (semicolon-separated)
86
+ - `-e, --env <environment>` - CLI target environment
87
+ - Available environments: `lucky`, `wynni`, `production` (default)
88
+ - `--token <API-token>` - API Access Token
89
+ - `-i, --packagePath <path>` - Publish the provided library or app package. Use "*" for autodetection
90
+
91
+ **Examples:**
92
+ ```console
93
+ $ studio-cli publish
94
+ $ studio-cli publish --phase beta
95
+ $ studio-cli publish --allowedBackends "*"
96
+ $ studio-cli publish --packagePath ./my-package.tar.gz --env wynni
97
+ ```
98
+
99
+ ### package (alias: pack)
100
+ Package the project.
101
+
102
+ ```console
103
+ $ studio-cli package [options]
104
+ ```
105
+
106
+ **Options:**
107
+ - `-ph, --phase <release phase>` - Specify a release phase (default: `release`)
108
+ - Available phases: `alpha`, `beta`, `rc`, `release`, `stage`, `passive`, `withdrawn`
109
+ - `-e, --env <environment>` - CLI target environment
110
+ - Available environments: `lucky`, `wynni`, `production` (default)
111
+ - `--token <API-token>` - API Access Token
112
+
113
+ **Examples:**
114
+ ```console
115
+ $ studio-cli package
116
+ $ studio-cli pack --phase alpha
117
+ $ studio-cli pack --env wynni
118
+ ```
119
+
120
+ ### run
121
+ Build, upload to USB device, and create development site on myDatanet. This command is designed for development and integration testing purposes.
122
+
123
+ ```console
124
+ $ studio-cli run -s <serial> --server <url> [options]
125
+ ```
126
+
127
+ **Options:**
128
+ - `-s, --serial <serial>` - Device serial number (16 characters hex) **[required]**
129
+ - `--server <url>` - myDatanet instance URL (https:// prefix optional). Defaults to `MYDATANET_HOST` environment variable
130
+ - `--customer <customerId>` - myDatanet customer UID or ID. Defaults to `MYDATANET_CUSTOMER` environment variable
131
+ - `--mdn-token <token>` - myDatanet API token. Defaults to `MYDATANET_TOKEN` environment variable
132
+ - `-p, --part <APM part>` - APM part that should be built
133
+ - Available parts: `dde`, `dlo`, `pov`, `blo`, `dfiles`
134
+ - `-e, --env <environment>` - CLI target environment
135
+ - Available environments: `lucky`, `wynni`, `production` (default)
136
+ - `--token <API-token>` - Studio API Access Token
137
+ - `--debug` - Enable debug logging
138
+
139
+ **Exit Codes:**
140
+ - `0` - Success
141
+ - `1` - Build failed
142
+ - `2` - USB device not found
143
+ - `3` - USB upload failed
144
+ - `4` - myDatanet authentication failed
145
+ - `5` - Development tag upload failed
146
+ - `6` - Site creation failed
147
+
148
+ **Output:**
149
+ On success, the command outputs:
150
+ - Site UID of the newly created/reused development site
151
+ - APM ID of the development tag
152
+
153
+ **Examples:**
154
+ ```console
155
+ # Basic usage with environment variables
156
+ $ export MYDATANET_TOKEN=your_token
157
+ $ export MYDATANET_HOST=myserver.mydatanet.net
158
+ $ export MYDATANET_CUSTOMER=your_customer_id
159
+ $ studio-cli run -s 1234567890ABCDEF
160
+
161
+ # Explicit options
162
+ $ studio-cli run -s 1234567890ABCDEF --server myserver.mydatanet.net --customer CUST123 --mdn-token your_token
163
+
164
+ # With build part selection
165
+ $ studio-cli run -s 1234567890ABCDEF --server myserver.mydatanet.net --part dlo --debug
166
+
167
+ # With manifest overrides
168
+ $ studio-cli run -s 1234567890ABCDEF --server myserver.mydatanet.net --dlo.mainFile="./dlo/test.dlo"
169
+ ```
170
+
171
+ ### usb
172
+ USB device management commands.
173
+
174
+ #### usb list
175
+ List available USB devices.
176
+
177
+ ```console
178
+ $ studio-cli usb list
179
+ ```
180
+
181
+ #### usb upload
182
+ Upload an AMX binary to a USB device.
183
+
184
+ ```console
185
+ $ studio-cli usb upload -s <serial> -f <path> [--debug]
186
+ ```
187
+
188
+ **Options:**
189
+ - `-s, --serial <serial>` - Device serial number (16 characters hex) **[required]**
190
+ - `-f, --file <path>` - Path to the AMX file (relative to current directory) **[required]**
191
+ - `--debug` - Enable debug logging
192
+
193
+ **Example:**
194
+ ```console
195
+ $ studio-cli usb upload -s 1234567890ABCDEF -f ./app.amx
196
+ $ studio-cli usb upload -s 1234567890ABCDEF -f ./app.amx --debug
197
+ ```
198
+
27
199
  ## Development
28
200
 
29
201
  Execute commands from the root dir
@@ -135,6 +135,11 @@ export declare function build(cwd: URI, fs: LocalFS, logger: Log.Logger, env: Gl
135
135
  [APM.Part.dfiles]: Diagnostics.File[];
136
136
  }>;
137
137
 
138
+ /**
139
+ * Build development installation info from manifest and options
140
+ */
141
+ export declare function buildDevelopmentInstallInfo(cwd: URI, fs: LocalFS, serialNumber: string, userName: string, customerUid: string | null): Promise<DevelopmentInstallInfo>;
142
+
138
143
  declare interface components {
139
144
  schemas: {
140
145
  /** @default 25 */
@@ -1708,6 +1713,23 @@ export declare namespace Dependencies {
1708
1713
  export function getApmPartDependencies(cwd: URI, fs: LocalFS, apmPart: APM.Part.dlo | APM.Part.dfiles): Promise<APMPartLibrary[]>;
1709
1714
  }
1710
1715
 
1716
+ /**
1717
+ * Development installation information
1718
+ */
1719
+ export declare interface DevelopmentInstallInfo {
1720
+ apmId: string;
1721
+ applicationId: string | null;
1722
+ name: string;
1723
+ version: number;
1724
+ serialNumber?: string;
1725
+ siteUid: string | null;
1726
+ siteName?: string;
1727
+ customerUid: string | null;
1728
+ customerName?: string;
1729
+ /** Whether a registration code is needed (used by VSCode extension) */
1730
+ registrationCodeNeeded?: boolean;
1731
+ }
1732
+
1711
1733
  export declare const DeviceProfiles: any;
1712
1734
 
1713
1735
  export declare namespace DFILES {
@@ -1947,6 +1969,11 @@ declare enum FileType {
1947
1969
  SymbolicLink = 64
1948
1970
  }
1949
1971
 
1972
+ /**
1973
+ * Generate a development APM ID based on a reference string
1974
+ */
1975
+ export declare function generateDevApmId(developmentReference: string): string;
1976
+
1950
1977
  export declare namespace Globals {
1951
1978
  /**
1952
1979
  * Supported ENV for the studio environment
@@ -2035,6 +2062,16 @@ export declare namespace Helper {
2035
2062
  export function defer(token: string, timeout: number, callback: any): void;
2036
2063
  }
2037
2064
 
2065
+ /**
2066
+ * HTTP methods supported by the myDatanet API
2067
+ */
2068
+ export declare enum HttpMethod {
2069
+ Get = "GET",
2070
+ Post = "POST",
2071
+ Put = "PUT",
2072
+ Delete = "DELETE"
2073
+ }
2074
+
2038
2075
  /**
2039
2076
  * Installs the specified dependencies or all dependencies if none are provided.
2040
2077
  *
@@ -2311,6 +2348,134 @@ export declare namespace Manifest {
2311
2348
  export function isApmPartEnabled(cwd: URI, fs: LocalFS, apmPart: APM.Part, manifest?: Manifest.Manifest): Promise<boolean>;
2312
2349
  }
2313
2350
 
2351
+ /**
2352
+ * MyDatanet API client for CLI and extension operations
2353
+ */
2354
+ export declare class MyDatanetClient {
2355
+ private domain;
2356
+ private auth;
2357
+ private logger?;
2358
+ private userInfo;
2359
+ /**
2360
+ * Create a new MyDatanetClient
2361
+ * @param serverUrl - Server URL (https:// prefix is optional)
2362
+ * @param apiTokenOrLogger - API token string OR Logger instance for backward compatibility
2363
+ * @param loggerOrUndefined - Logger instance (only when apiTokenOrLogger is a string)
2364
+ */
2365
+ constructor(serverUrl: string, apiTokenOrLogger: string | Log.Logger, loggerOrUndefined?: Log.Logger);
2366
+ /**
2367
+ * Create a new MyDatanetClient with options
2368
+ * @param options - Client configuration options
2369
+ */
2370
+ constructor(options: MyDatanetClientOptions);
2371
+ /**
2372
+ * Set or update the authentication header
2373
+ */
2374
+ setAuth(authHeader: string): void;
2375
+ /**
2376
+ * Get the current domain
2377
+ */
2378
+ getDomain(): string;
2379
+ /**
2380
+ * Normalize server URL to ensure https:// prefix
2381
+ */
2382
+ private normalizeServerUrl;
2383
+ /**
2384
+ * Remove protocol from domain for display purposes
2385
+ */
2386
+ private trimDomain;
2387
+ /**
2388
+ * Make an authenticated JSON request to the myDatanet API
2389
+ */
2390
+ fetchJSON<T>(method: HttpMethod, path: string, body?: any): Promise<T>;
2391
+ /**
2392
+ * Authenticate and get user information
2393
+ */
2394
+ authenticate(): Promise<MyDatanetUserInfo>;
2395
+ /**
2396
+ * Get the current user info (must call authenticate first)
2397
+ */
2398
+ getUserInfo(): MyDatanetUserInfo | null;
2399
+ /**
2400
+ * Upload a development APM tag to the app-center
2401
+ */
2402
+ uploadDevTag(apmId: string, apmBuffer: FormData): Promise<string>;
2403
+ /**
2404
+ * Get customer information by UID or name
2405
+ */
2406
+ getCustomer(customerIdOrUid: string): Promise<MyDatanetCustomer>;
2407
+ /**
2408
+ * Get all customers accessible by the current user
2409
+ */
2410
+ getCustomers(): Promise<MyDatanetCustomer[]>;
2411
+ /**
2412
+ * Get device site information
2413
+ */
2414
+ getDeviceSite(serialNumber: string): Promise<{
2415
+ app: {
2416
+ phase: string;
2417
+ apmid: string;
2418
+ appl_id: string;
2419
+ };
2420
+ _uid: string;
2421
+ name: string;
2422
+ customer_uid: string;
2423
+ } | null>;
2424
+ /**
2425
+ * Get device information
2426
+ */
2427
+ getDevice(serialNumber: string): Promise<{
2428
+ customer_uid: string;
2429
+ } | null>;
2430
+ /**
2431
+ * Get or create a site by name within a customer
2432
+ */
2433
+ getSite(customerUid: string, siteName: string): Promise<{
2434
+ _uid: string;
2435
+ name: string;
2436
+ } | null>;
2437
+ /**
2438
+ * Create a development site
2439
+ */
2440
+ createDevelopmentSite(customerUid: string, installInfo: DevelopmentInstallInfo, registrationCode?: string): Promise<string>;
2441
+ /**
2442
+ * Update site name
2443
+ */
2444
+ updateSiteName(siteUid: string, name: string): Promise<void>;
2445
+ }
2446
+
2447
+ /**
2448
+ * Options for creating a MyDatanetClient
2449
+ */
2450
+ export declare interface MyDatanetClientOptions {
2451
+ /** Server URL (https:// prefix is optional) */
2452
+ serverUrl: string;
2453
+ /** API token for Bearer authentication */
2454
+ apiToken?: string;
2455
+ /** Pre-formatted authentication header (e.g., "Basic 1-xxx" or "Bearer xxx") */
2456
+ authHeader?: string;
2457
+ /** Logger instance (optional) */
2458
+ logger?: Log.Logger;
2459
+ }
2460
+
2461
+ /**
2462
+ * Customer information from myDatanet
2463
+ */
2464
+ export declare interface MyDatanetCustomer {
2465
+ _uid: string;
2466
+ name: string;
2467
+ }
2468
+
2469
+ /**
2470
+ * User information returned from myDatanet /api/1/me endpoint
2471
+ */
2472
+ export declare interface MyDatanetUserInfo {
2473
+ name: string;
2474
+ email: string;
2475
+ group?: number;
2476
+ customers?: MyDatanetCustomer[];
2477
+ }
2478
+
2314
2479
  /**
2315
2480
  * Packs the given directory into a deployable package using the specified configuration.
2316
2481
  *
package/out/api.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Log = exports.ENV = exports.DFILES = exports.Library = exports.APM = exports.Package = exports.DLO = exports.Globals = exports.DeviceProfiles = exports.DefaultFiles = exports.Diagnostics = exports.Helper = exports.DDE = exports.DDE_Core = exports.Registry = exports.Manifest = exports.Dependencies = void 0;
3
+ exports.buildDevelopmentInstallInfo = exports.generateDevApmId = exports.HttpMethod = exports.MyDatanetClient = exports.Log = exports.ENV = exports.DFILES = exports.Library = exports.APM = exports.Package = exports.DLO = exports.Globals = exports.DeviceProfiles = exports.DefaultFiles = exports.Diagnostics = exports.Helper = exports.DDE = exports.DDE_Core = exports.Registry = exports.Manifest = exports.Dependencies = void 0;
4
4
  exports.install = install;
5
5
  exports.build = build;
6
6
  exports.publish = publish;
@@ -134,4 +134,10 @@ async function publish(cwd, fs, logger, env, apiToken, optsAllowedBackends, opts
134
134
  async function pack(cwd, fs, logger, env, apiToken, optsPhase) {
135
135
  return package_1.Package.pack(cwd, fs, logger, env, apiToken, optsPhase);
136
136
  }
137
+ // Re-export myDatanet client types and helpers for external use
138
+ var myDatanetClient_1 = require("./myDatanetClient");
139
+ Object.defineProperty(exports, "MyDatanetClient", { enumerable: true, get: function () { return myDatanetClient_1.MyDatanetClient; } });
140
+ Object.defineProperty(exports, "HttpMethod", { enumerable: true, get: function () { return myDatanetClient_1.HttpMethod; } });
141
+ Object.defineProperty(exports, "generateDevApmId", { enumerable: true, get: function () { return myDatanetClient_1.generateDevApmId; } });
142
+ Object.defineProperty(exports, "buildDevelopmentInstallInfo", { enumerable: true, get: function () { return myDatanetClient_1.buildDevelopmentInstallInfo; } });
137
143
  //# sourceMappingURL=api.js.map
package/out/main.js CHANGED
@@ -14,6 +14,7 @@ const api_1 = require("./api");
14
14
  const log_1 = require("./log");
15
15
  const argumentParser_1 = require("./argumentParser");
16
16
  const usb_1 = require("./usb");
17
+ const run_1 = require("./run");
17
18
  const program = new commander_1.Command();
18
19
  const notifier = (0, update_notifier_1.default)({ pkg: package_json_1.default });
19
20
  const logger = new log_1.Log.Logger();
@@ -98,6 +99,30 @@ const releasePhaseArguments = Object.values(apm_1.APM.TagPhase);
98
99
  const optionReleasePhase = new commander_1.Option('-ph --phase <release phase>', 'specify a release phase')
99
100
  .choices(releasePhaseArguments)
100
101
  .default('release');
102
+ /**
103
+ * Option for specifying the APM part to build
104
+ */
105
+ const optionApmPart = new commander_1.Option('-p --part <APM part>', 'APM part that should be built').choices(Object.values(apm_1.APM.Part));
106
+ /**
107
+ * Option for device serial number (16 characters hex)
108
+ */
109
+ const optionDeviceSerial = new commander_1.Option('-s, --serial <serial>', 'Device serial number (16 characters hex)');
110
+ /**
111
+ * Option for enabling debug logging
112
+ */
113
+ const optionDebug = new commander_1.Option('--debug', 'Enable debug logging').default(false);
114
+ /**
115
+ * Option for myDatanet instance URL
116
+ */
117
+ const optionMdnServer = new commander_1.Option('--server <url>', 'myDatanet instance URL (https:// prefix optional)').default(process.env['MYDATANET_HOST']);
118
+ /**
119
+ * Option for myDatanet customer UID or ID
120
+ */
121
+ const optionMdnCustomer = new commander_1.Option('--customer <customerId>', 'myDatanet customer UID or ID').default(process.env['MYDATANET_CUSTOMER']);
122
+ /**
123
+ * Option for myDatanet API token
124
+ */
125
+ const optionMdnToken = new commander_1.Option('--mdn-token <token>', 'myDatanet API token').default(process.env['MYDATANET_TOKEN']);
101
126
  program
102
127
  .command('install')
103
128
  .aliases(['i'])
@@ -113,7 +138,7 @@ program
113
138
  });
114
139
  program
115
140
  .command('build')
116
- .addOption(new commander_1.Option('-p --part <APM part>', 'APM part that should be build').choices(Object.values(apm_1.APM.Part)))
141
+ .addOption(optionApmPart)
117
142
  .allowExcessArguments(true)
118
143
  .addOption(optionStudioEnv)
119
144
  .addOption(optionStudioToken)
@@ -146,6 +171,53 @@ program
146
171
  const { env, token } = getDefaultOptions(opts);
147
172
  main(command, (0, api_1.pack)(cwd, cliFS_1.cliFS, logger, env, token, opts.phase));
148
173
  });
174
+ // Run command - Build, upload to device, and create development site
175
+ program
176
+ .command('run')
177
+ .description('Build, upload to USB device, and create development site on myDatanet')
178
+ .addOption(optionDeviceSerial.makeOptionMandatory(true))
179
+ .addOption(optionMdnServer)
180
+ .addOption(optionMdnCustomer)
181
+ .addOption(optionMdnToken)
182
+ .addOption(optionApmPart)
183
+ .addOption(optionStudioEnv)
184
+ .addOption(optionStudioToken)
185
+ .addOption(optionDebug)
186
+ .allowUnknownOption(true)
187
+ .action(async (opts, command) => {
188
+ const { env, token } = getDefaultOptions(opts);
189
+ const mdnToken = opts.mdnToken;
190
+ const server = opts.server;
191
+ // Validate required options
192
+ if (!mdnToken) {
193
+ logger.error('MYDATANET_TOKEN is required. Set via --mdn-token or MYDATANET_TOKEN environment variable');
194
+ notifier.notify();
195
+ process.exit(run_1.RunExitCode.AuthenticationFailed);
196
+ }
197
+ if (!server) {
198
+ logger.error('Server URL is required. Set via --server or MYDATANET_HOST environment variable');
199
+ notifier.notify();
200
+ process.exit(run_1.RunExitCode.AuthenticationFailed);
201
+ }
202
+ const manifestOptions = (0, argumentParser_1.parseUnknownLongOptions)(command);
203
+ api_1.Manifest.setOverwrites(manifestOptions);
204
+ const result = await (0, run_1.run)(cwd, cliFS_1.cliFS, logger, env, token, {
205
+ serial: opts.serial,
206
+ server: server,
207
+ customer: opts.customer,
208
+ mdnToken: mdnToken,
209
+ debug: opts.debug,
210
+ part: opts.part ? [opts.part] : undefined
211
+ });
212
+ notifier.notify();
213
+ if (result.success) {
214
+ process.exit(run_1.RunExitCode.Success);
215
+ }
216
+ else {
217
+ logger.error(result.message);
218
+ process.exit(result.errorCode || 1);
219
+ }
220
+ });
149
221
  // USB commands
150
222
  const usbCommand = program.command('usb').description('USB device management commands');
151
223
  usbCommand
@@ -158,9 +230,9 @@ usbCommand
158
230
  usbCommand
159
231
  .command('upload')
160
232
  .description('Upload an AMX binary to a USB device')
161
- .requiredOption('-s, --serial <serial>', 'Device serial number (16 characters hex)')
233
+ .addOption(optionDeviceSerial.makeOptionMandatory(true))
162
234
  .requiredOption('-f, --file <path>', 'Path to the AMX file (relative to current directory)')
163
- .requiredOption('--debug', 'Enable debug logging', false)
235
+ .addOption(optionDebug)
164
236
  .action(async (opts) => {
165
237
  const fileUri = vscode_uri_1.Utils.joinPath(cwd, opts.file);
166
238
  const result = await (0, usb_1.uploadToDevice)(opts.serial, fileUri, cliFS_1.cliFS, logger, opts.debug);
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MyDatanetClient = exports.RunExitCode = exports.HttpMethod = void 0;
4
+ exports.generateDevApmId = generateDevApmId;
5
+ exports.buildDevelopmentInstallInfo = buildDevelopmentInstallInfo;
6
+ const manifest_1 = require("./manifest");
7
+ const apm_1 = require("./package/apm");
8
+ const uuid_1 = require("uuid");
9
+ // Used to generate reproducible apmids
10
+ const UUID_NAMESPACE = 'b4baec47-0ba4-4e37-b237-8f9cde42b8dd';
11
+ /**
12
+ * HTTP methods supported by the myDatanet API
13
+ */
14
+ var HttpMethod;
15
+ (function (HttpMethod) {
16
+ HttpMethod["Get"] = "GET";
17
+ HttpMethod["Post"] = "POST";
18
+ HttpMethod["Put"] = "PUT";
19
+ HttpMethod["Delete"] = "DELETE";
20
+ })(HttpMethod || (exports.HttpMethod = HttpMethod = {}));
21
+ /**
22
+ * Exit codes for the run command
23
+ */
24
+ var RunExitCode;
25
+ (function (RunExitCode) {
26
+ RunExitCode[RunExitCode["Success"] = 0] = "Success";
27
+ RunExitCode[RunExitCode["BuildFailed"] = 1] = "BuildFailed";
28
+ RunExitCode[RunExitCode["DeviceNotFound"] = 2] = "DeviceNotFound";
29
+ RunExitCode[RunExitCode["UsbUploadFailed"] = 3] = "UsbUploadFailed";
30
+ RunExitCode[RunExitCode["AuthenticationFailed"] = 4] = "AuthenticationFailed";
31
+ RunExitCode[RunExitCode["DevTagUploadFailed"] = 5] = "DevTagUploadFailed";
32
+ RunExitCode[RunExitCode["SiteCreationFailed"] = 6] = "SiteCreationFailed";
33
+ })(RunExitCode || (exports.RunExitCode = RunExitCode = {}));
34
+ /**
35
+ * MyDatanet API client for CLI and extension operations
36
+ */
37
+ class MyDatanetClient {
38
+ domain;
39
+ auth;
40
+ logger;
41
+ userInfo = null;
42
+ constructor(serverUrlOrOptions, apiTokenOrLogger, loggerOrUndefined) {
43
+ if (typeof serverUrlOrOptions === 'object') {
44
+ // New options-based constructor
45
+ const { serverUrl, apiToken, authHeader, logger } = serverUrlOrOptions;
46
+ this.domain = this.normalizeServerUrl(serverUrl);
47
+ this.auth = authHeader || (apiToken ? `Bearer ${apiToken}` : '');
48
+ this.logger = logger;
49
+ }
50
+ else {
51
+ // Legacy constructor for backward compatibility
52
+ this.domain = this.normalizeServerUrl(serverUrlOrOptions);
53
+ if (typeof apiTokenOrLogger === 'string') {
54
+ this.auth = `Bearer ${apiTokenOrLogger}`;
55
+ this.logger = loggerOrUndefined;
56
+ }
57
+ else {
58
+ this.auth = '';
59
+ this.logger = apiTokenOrLogger;
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Set or update the authentication header
65
+ */
66
+ setAuth(authHeader) {
67
+ this.auth = authHeader;
68
+ }
69
+ /**
70
+ * Get the current domain
71
+ */
72
+ getDomain() {
73
+ return this.domain;
74
+ }
75
+ /**
76
+ * Normalize server URL to ensure https:// prefix
77
+ */
78
+ normalizeServerUrl(url) {
79
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
80
+ return `https://${url}`;
81
+ }
82
+ return url;
83
+ }
84
+ /**
85
+ * Remove protocol from domain for display purposes
86
+ */
87
+ trimDomain(domain) {
88
+ return domain.replace(/(^\w+:|^)\/\//, '');
89
+ }
90
+ /**
91
+ * Make an authenticated JSON request to the myDatanet API
92
+ */
93
+ async fetchJSON(method, path, body) {
94
+ const url = `${this.domain}${path}`;
95
+ const headers = {
96
+ Authorization: this.auth
97
+ };
98
+ const options = {
99
+ method,
100
+ headers
101
+ };
102
+ if (body) {
103
+ if (body instanceof FormData) {
104
+ options.body = body;
105
+ }
106
+ else {
107
+ headers['Content-Type'] = 'application/json';
108
+ options.body = JSON.stringify(body);
109
+ }
110
+ }
111
+ const response = await fetch(url, options);
112
+ if (!response.ok) {
113
+ const errorText = await response.text().catch(() => 'Unknown error');
114
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
115
+ }
116
+ return response.json();
117
+ }
118
+ /**
119
+ * Authenticate and get user information
120
+ */
121
+ async authenticate() {
122
+ this.logger?.info(`Authenticating with ${this.trimDomain(this.domain)}...`);
123
+ try {
124
+ const { user, customers } = await this.fetchJSON(HttpMethod.Get, '/api/1/me');
125
+ this.userInfo = {
126
+ name: user.name,
127
+ email: user.email,
128
+ group: user.group,
129
+ customers: customers
130
+ };
131
+ this.logger?.info(`Authenticated as ${this.userInfo.name}`);
132
+ return this.userInfo;
133
+ }
134
+ catch (error) {
135
+ throw new Error(`Authentication failed: ${error instanceof Error ? error.message : String(error)}`);
136
+ }
137
+ }
138
+ /**
139
+ * Get the current user info (must call authenticate first)
140
+ */
141
+ getUserInfo() {
142
+ return this.userInfo;
143
+ }
144
+ /**
145
+ * Upload a development APM tag to the app-center
146
+ */
147
+ async uploadDevTag(apmId, apmBuffer) {
148
+ this.logger?.info(`Uploading development tag ${apmId}...`);
149
+ const { applid } = await this.fetchJSON(HttpMethod.Post, `/api/1/app-center/__dev/${apmId}`, apmBuffer);
150
+ this.logger?.info(`Development tag uploaded, application ID: ${applid}`);
151
+ return applid;
152
+ }
153
+ /**
154
+ * Get customer information by UID or name
155
+ */
156
+ async getCustomer(customerIdOrUid) {
157
+ const { _uid, name } = await this.fetchJSON(HttpMethod.Get, `/api/1/customers/${customerIdOrUid}`);
158
+ return { _uid, name };
159
+ }
160
+ /**
161
+ * Get all customers accessible by the current user
162
+ */
163
+ async getCustomers() {
164
+ return this.fetchJSON(HttpMethod.Get, '/api/1/customers');
165
+ }
166
+ /**
167
+ * Get device site information
168
+ */
169
+ async getDeviceSite(serialNumber) {
170
+ try {
171
+ return await this.fetchJSON(HttpMethod.Get, `/api/1/devices/${serialNumber}/site`);
172
+ }
173
+ catch {
174
+ return null;
175
+ }
176
+ }
177
+ /**
178
+ * Get device information
179
+ */
180
+ async getDevice(serialNumber) {
181
+ try {
182
+ return await this.fetchJSON(HttpMethod.Get, `/api/1/devices/${serialNumber}`);
183
+ }
184
+ catch {
185
+ return null;
186
+ }
187
+ }
188
+ /**
189
+ * Get or create a site by name within a customer
190
+ */
191
+ async getSite(customerUid, siteName) {
192
+ try {
193
+ return await this.fetchJSON(HttpMethod.Get, `/api/1/customers/${customerUid}/sites/${siteName}`);
194
+ }
195
+ catch {
196
+ return null;
197
+ }
198
+ }
199
+ /**
200
+ * Create a development site
201
+ */
202
+ async createDevelopmentSite(customerUid, installInfo, registrationCode) {
203
+ this.logger?.info(`Creating development site "${installInfo.name}"...`);
204
+ // Check if device is already attached to a site
205
+ if (installInfo.serialNumber) {
206
+ const existingSite = await this.getSite(customerUid, installInfo.name.toLowerCase());
207
+ if (existingSite) {
208
+ // Try to attach device to existing site
209
+ try {
210
+ await this.fetchJSON(HttpMethod.Post, `/api/1/customers/${customerUid}/sites/${existingSite._uid}/cn-attach-device`, {
211
+ device_id: installInfo.serialNumber,
212
+ allow_overwrite: true,
213
+ detach_from_old_site: true,
214
+ acquire: true,
215
+ create: true
216
+ });
217
+ this.logger?.info(`Device attached to existing site ${existingSite._uid}`);
218
+ return existingSite._uid;
219
+ }
220
+ catch (error) {
221
+ // 304 means device is already attached - that's OK
222
+ if (error.message && !error.message.includes('304')) {
223
+ this.logger?.warn(`Could not attach device to existing site: ${error.message}`);
224
+ }
225
+ else {
226
+ return existingSite._uid;
227
+ }
228
+ }
229
+ }
230
+ }
231
+ // Create new site
232
+ const { _uid } = await this.fetchJSON(HttpMethod.Post, `/api/1/customers/${customerUid}/sites`, {
233
+ name: installInfo.name,
234
+ create: true,
235
+ force: true,
236
+ note: 'This is a Studio development site',
237
+ applid: installInfo.applicationId,
238
+ device_id: installInfo.serialNumber,
239
+ reg_code: registrationCode,
240
+ servicetariff: '0000000000000000',
241
+ servicetariff_indiv_cost: 0
242
+ });
243
+ this.logger?.info(`Development site created: ${_uid}`);
244
+ return _uid;
245
+ }
246
+ /**
247
+ * Update site name
248
+ */
249
+ async updateSiteName(siteUid, name) {
250
+ try {
251
+ await this.fetchJSON(HttpMethod.Put, `/api/1/sites/${siteUid}`, { name });
252
+ }
253
+ catch {
254
+ // Ignore update failures
255
+ }
256
+ }
257
+ }
258
+ exports.MyDatanetClient = MyDatanetClient;
259
+ /**
260
+ * Generate a development APM ID based on a reference string
261
+ */
262
+ function generateDevApmId(developmentReference) {
263
+ return (0, uuid_1.v5)(developmentReference, UUID_NAMESPACE);
264
+ }
265
+ /**
266
+ * Build development installation info from manifest and options
267
+ */
268
+ async function buildDevelopmentInstallInfo(cwd, fs, serialNumber, userName, customerUid) {
269
+ const manifest = await manifest_1.Manifest.read(cwd, fs);
270
+ const currentUserId = userName.replaceAll(' ', '_').replace(/[^a-zA-Z0-9-]+/g, '');
271
+ const appName = manifest.name.replaceAll(' ', '_').replace(/[^a-zA-Z0-9-]+/g, '');
272
+ const hasDlo = await manifest_1.Manifest.isApmPartEnabled(cwd, fs, apm_1.APM.Part.dlo, manifest);
273
+ const useDeviceSerial = hasDlo && serialNumber;
274
+ const siteName = useDeviceSerial ? serialNumber.toUpperCase() : `${appName}_${currentUserId}`;
275
+ const developmentReference = useDeviceSerial ? serialNumber : siteName;
276
+ return {
277
+ apmId: generateDevApmId(developmentReference),
278
+ applicationId: null,
279
+ name: `Development_${siteName}`,
280
+ version: 1,
281
+ serialNumber: hasDlo ? serialNumber : undefined,
282
+ siteUid: null,
283
+ customerUid: customerUid
284
+ };
285
+ }
286
+ //# sourceMappingURL=myDatanetClient.js.map
package/out/run.js ADDED
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RunExitCode = void 0;
4
+ exports.run = run;
5
+ const vscode_uri_1 = require("vscode-uri");
6
+ const apm_1 = require("./package/apm");
7
+ const defaultFiles_1 = require("./defaultFiles");
8
+ const package_1 = require("./package/package");
9
+ const manifest_1 = require("./manifest");
10
+ const myDatanetClient_1 = require("./myDatanetClient");
11
+ Object.defineProperty(exports, "RunExitCode", { enumerable: true, get: function () { return myDatanetClient_1.RunExitCode; } });
12
+ const usb_1 = require("./usb");
13
+ /**
14
+ * Helper to extract error message from unknown error
15
+ */
16
+ function getErrorMessage(error) {
17
+ return error instanceof Error ? error.message : String(error);
18
+ }
19
+ /**
20
+ * Helper to create a failure result
21
+ */
22
+ function failureResult(errorCode, message) {
23
+ return { success: false, errorCode, message };
24
+ }
25
+ /**
26
+ * Step 1: Build the project
27
+ */
28
+ async function buildProject(ctx) {
29
+ const { cwd, fs, logger, env, apiToken, options } = ctx;
30
+ logger.info('[1/5] Building project...');
31
+ try {
32
+ const partsToBuild = options.part ? options.part : true;
33
+ await manifest_1.Manifest.validateBasicManifest(cwd, fs, null);
34
+ await package_1.Package.buildAll(cwd, fs, logger, env, apiToken, partsToBuild, true);
35
+ logger.done('Build completed successfully');
36
+ return null;
37
+ }
38
+ catch (error) {
39
+ return failureResult(myDatanetClient_1.RunExitCode.BuildFailed, `Build failed: ${getErrorMessage(error)}`);
40
+ }
41
+ }
42
+ /**
43
+ * Step 2: Find and validate USB device
44
+ */
45
+ async function findDevice(ctx) {
46
+ const { logger, options } = ctx;
47
+ const { serial } = options;
48
+ logger.info(`[2/5] Searching for USB device with serial: ${serial}...`);
49
+ const device = await (0, usb_1.findDeviceBySerialNumber)(serial);
50
+ if (!device) {
51
+ return failureResult(myDatanetClient_1.RunExitCode.DeviceNotFound, `USB device not found with serial number: ${serial}`);
52
+ }
53
+ logger.done(`Device found: ${device.productName}`);
54
+ return device;
55
+ }
56
+ /**
57
+ * Step 3: Upload binary to USB device
58
+ */
59
+ async function uploadToUsbDevice(ctx) {
60
+ const { cwd, fs, logger, options } = ctx;
61
+ const { serial, debug } = options;
62
+ logger.info('[3/5] Uploading binary to USB device...');
63
+ const amxPath = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.dist.mainAmxPath);
64
+ const uploadResult = await (0, usb_1.uploadToDevice)(serial, amxPath, fs, logger, debug);
65
+ if (!uploadResult.success) {
66
+ return failureResult(myDatanetClient_1.RunExitCode.UsbUploadFailed, `USB upload failed: ${uploadResult.message}`);
67
+ }
68
+ logger.done('USB upload completed');
69
+ return null;
70
+ }
71
+ /**
72
+ * Step 4a: Authenticate with myDatanet
73
+ */
74
+ async function authenticateWithMyDatanet(mdnClient, logger) {
75
+ logger.info('[4/5] Connecting to myDatanet server...');
76
+ try {
77
+ return await mdnClient.authenticate();
78
+ }
79
+ catch (error) {
80
+ return failureResult(myDatanetClient_1.RunExitCode.AuthenticationFailed, `myDatanet authentication failed: ${getErrorMessage(error)}`);
81
+ }
82
+ }
83
+ /**
84
+ * Step 4b: Resolve customer UID
85
+ */
86
+ async function resolveCustomer(mdnClient, customer, logger) {
87
+ if (customer) {
88
+ try {
89
+ const customerInfo = await mdnClient.getCustomer(customer);
90
+ logger.info(`Using customer: ${customerInfo.name} (${customerInfo._uid})`);
91
+ return customerInfo._uid;
92
+ }
93
+ catch {
94
+ return failureResult(myDatanetClient_1.RunExitCode.SiteCreationFailed, `Customer "${customer}" not found`);
95
+ }
96
+ }
97
+ // Try to get customer from available customers
98
+ const customers = await mdnClient.getCustomers();
99
+ if (customers.length === 0) {
100
+ return failureResult(myDatanetClient_1.RunExitCode.SiteCreationFailed, 'No customers available. Please specify --customer or set MYDATANET_CUSTOMER');
101
+ }
102
+ if (customers.length === 1) {
103
+ logger.info(`Using customer: ${customers[0].name} (${customers[0]._uid})`);
104
+ return customers[0]._uid;
105
+ }
106
+ const customerNames = customers.map(c => c.name).join(', ');
107
+ return failureResult(myDatanetClient_1.RunExitCode.SiteCreationFailed, `Multiple customers available. Please specify --customer or set MYDATANET_CUSTOMER. Available: ${customerNames}`);
108
+ }
109
+ /**
110
+ * Step 4c: Update install info with existing site data if available
111
+ */
112
+ async function updateInstallInfoFromExistingSite(mdnClient, serial, installInfo, logger) {
113
+ const existingSite = await mdnClient.getDeviceSite(serial);
114
+ if (!existingSite) {
115
+ return;
116
+ }
117
+ if (existingSite.app.phase === 'dev') {
118
+ installInfo.apmId = existingSite.app.apmid;
119
+ installInfo.applicationId = existingSite.app.appl_id;
120
+ }
121
+ installInfo.siteUid = existingSite._uid;
122
+ installInfo.siteName = existingSite.name;
123
+ installInfo.customerUid = existingSite.customer_uid;
124
+ logger.info(`Found existing site: ${existingSite.name}`);
125
+ }
126
+ /**
127
+ * Step 4d: Create and upload development APM tag
128
+ */
129
+ async function uploadDevTag(ctx, mdnClient, installInfo) {
130
+ const { cwd, fs, logger } = ctx;
131
+ logger.info('Creating development APM tag...');
132
+ try {
133
+ const apmBuffer = await apm_1.APM.createDevTag(cwd, fs);
134
+ const applicationId = await mdnClient.uploadDevTag(installInfo.apmId, apmBuffer);
135
+ installInfo.applicationId = applicationId;
136
+ logger.done('Development tag uploaded');
137
+ return null;
138
+ }
139
+ catch (error) {
140
+ return failureResult(myDatanetClient_1.RunExitCode.DevTagUploadFailed, `Development tag upload failed: ${getErrorMessage(error)}`);
141
+ }
142
+ }
143
+ /**
144
+ * Step 5: Create or update development site
145
+ */
146
+ async function createOrUpdateSite(mdnClient, customerUid, installInfo, logger) {
147
+ logger.info('[5/5] Creating development site...');
148
+ try {
149
+ if (installInfo.siteUid) {
150
+ // Update site name if different
151
+ if (installInfo.siteName !== installInfo.name) {
152
+ await mdnClient.updateSiteName(installInfo.siteUid, installInfo.name);
153
+ }
154
+ logger.info(`Reusing existing site: ${installInfo.siteUid}`);
155
+ return installInfo.siteUid;
156
+ }
157
+ return await mdnClient.createDevelopmentSite(customerUid, installInfo);
158
+ }
159
+ catch (error) {
160
+ return failureResult(myDatanetClient_1.RunExitCode.SiteCreationFailed, `Site creation failed: ${getErrorMessage(error)}`);
161
+ }
162
+ }
163
+ /**
164
+ * Log the deployment summary
165
+ */
166
+ function logDeploymentSummary(logger, siteUid, apmId) {
167
+ logger.done('Development deployment completed successfully!');
168
+ logger.info('');
169
+ logger.info('=== Deployment Summary ===');
170
+ logger.info(`Site UID: ${siteUid}`);
171
+ logger.info(`APM ID: ${apmId}`);
172
+ logger.info('==========================');
173
+ }
174
+ /**
175
+ * Check if result is a failure
176
+ */
177
+ function isFailure(result) {
178
+ return typeof result === 'object' && result !== null && 'errorCode' in result;
179
+ }
180
+ /**
181
+ * Builds, uploads to USB device, and creates a development site on myDatanet.
182
+ *
183
+ * This function orchestrates the complete development deployment workflow:
184
+ * 1. Builds the project
185
+ * 2. Uploads the binary to the USB device
186
+ * 3. Authenticates with myDatanet
187
+ * 4. Creates and uploads a development APM tag
188
+ * 5. Creates or reuses a development site
189
+ *
190
+ * @param {URI} cwd - The current working directory of the project.
191
+ * @param {LocalFS} fs - The file system interface for file operations.
192
+ * @param {Log.Logger} logger - Logger instance for logging progress.
193
+ * @param {Globals.ENV} env - The environment configuration.
194
+ * @param {string | null} apiToken - The Studio API token for registry operations.
195
+ * @param {RunOptions} options - Options for the run command.
196
+ * @return {Promise<RunResult>} A promise that resolves to the result of the run command.
197
+ */
198
+ async function run(cwd, fs, logger, env, apiToken, options) {
199
+ const ctx = { cwd, fs, logger, env, apiToken, options };
200
+ const { serial, server, customer, mdnToken } = options;
201
+ logger.info('Starting development deployment...');
202
+ // Step 1: Build the project
203
+ const buildResult = await buildProject(ctx);
204
+ if (buildResult) {
205
+ return buildResult;
206
+ }
207
+ // Step 2: Find and validate USB device
208
+ const deviceResult = await findDevice(ctx);
209
+ if (isFailure(deviceResult)) {
210
+ return deviceResult;
211
+ }
212
+ // Step 3: Upload binary to USB device
213
+ const uploadResult = await uploadToUsbDevice(ctx);
214
+ if (uploadResult) {
215
+ return uploadResult;
216
+ }
217
+ // Step 4: myDatanet operations
218
+ const mdnClient = new myDatanetClient_1.MyDatanetClient(server, mdnToken, logger);
219
+ // 4a: Authenticate
220
+ const authResult = await authenticateWithMyDatanet(mdnClient, logger);
221
+ if (isFailure(authResult)) {
222
+ return authResult;
223
+ }
224
+ const userInfo = authResult;
225
+ // 4b: Resolve customer
226
+ const customerResult = await resolveCustomer(mdnClient, customer, logger);
227
+ if (isFailure(customerResult)) {
228
+ return customerResult;
229
+ }
230
+ const customerUid = customerResult;
231
+ // Build development install info
232
+ const installInfo = await (0, myDatanetClient_1.buildDevelopmentInstallInfo)(cwd, fs, serial, userInfo.name, customerUid);
233
+ // 4c: Check for existing site
234
+ await updateInstallInfoFromExistingSite(mdnClient, serial, installInfo, logger);
235
+ // 4d: Upload dev tag
236
+ const devTagResult = await uploadDevTag(ctx, mdnClient, installInfo);
237
+ if (devTagResult) {
238
+ return devTagResult;
239
+ }
240
+ // Step 5: Create or update development site
241
+ const siteResult = await createOrUpdateSite(mdnClient, customerUid, installInfo, logger);
242
+ if (isFailure(siteResult)) {
243
+ return siteResult;
244
+ }
245
+ const siteUid = siteResult;
246
+ logDeploymentSummary(logger, siteUid, installInfo.apmId);
247
+ return {
248
+ success: true,
249
+ siteUid,
250
+ apmId: installInfo.apmId,
251
+ message: 'Development deployment completed successfully'
252
+ };
253
+ }
254
+ //# sourceMappingURL=run.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microtronics/studio-cli",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "description": "Microtronics Studio CLI Tool",
5
5
  "main": "./out/api.js",
6
6
  "typings": "./dist/studio-cli.d.ts",