@microtronics/studio-cli 0.47.0 → 0.49.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/out/run.js DELETED
@@ -1,254 +0,0 @@
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/out/usb.js DELETED
@@ -1,189 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.listUsbDevices = listUsbDevices;
4
- exports.printUsbDevices = printUsbDevices;
5
- exports.findDeviceBySerialNumber = findDeviceBySerialNumber;
6
- exports.uploadToDevice = uploadToDevice;
7
- const usb_1 = require("usb");
8
- const uto_master_1 = require("uto-master");
9
- const utoStack_1 = require("uto-master/dist/src/utilities/utoStack");
10
- // Microtronics vendor ID
11
- const MICROTRONICS_VENDOR_ID = 0x2544;
12
- /**
13
- * Custom WebUSB instance configured to allow Microtronics devices
14
- */
15
- const customWebUSB = new usb_1.WebUSB({
16
- // Bypass checking for authorized devices
17
- allowedDevices: [
18
- {
19
- vendorId: MICROTRONICS_VENDOR_ID
20
- }
21
- ]
22
- });
23
- /**
24
- * Lists all available USB devices filtered by Microtronics vendor ID
25
- * @returns Promise resolving to an array of USB device information
26
- */
27
- async function listUsbDevices() {
28
- const devices = await customWebUSB.getDevices();
29
- return devices.map((device) => ({
30
- productName: device.productName,
31
- serialNumber: device.serialNumber || device.productName?.split(' ').pop(),
32
- vendorId: device.vendorId,
33
- productId: device.productId
34
- }));
35
- }
36
- /**
37
- * Prints USB device product names using the provided logger
38
- * @param logger - The logger instance to use for output
39
- */
40
- async function printUsbDevices(logger) {
41
- const devices = await listUsbDevices();
42
- if (devices.length === 0) {
43
- logger.info('No USB devices found.');
44
- return;
45
- }
46
- logger.info('Available USB devices:');
47
- devices.forEach((device, index) => {
48
- const name = device.productName ||
49
- `Unknown Device (VID: 0x${device.vendorId.toString(16)}, PID: 0x${device.productId.toString(16)})`;
50
- const serial = device.serialNumber ? ` [${device.serialNumber}]` : '';
51
- logger.log(` ${index + 1}. ${name}${serial}`);
52
- });
53
- }
54
- /**
55
- * Find a USB device by its serial number
56
- * @param serialNumber - The 16-character hex serial number of the device
57
- * @returns The USB device or null if not found
58
- */
59
- async function findDeviceBySerialNumber(serialNumber) {
60
- const devices = await customWebUSB.getDevices();
61
- for (const device of devices) {
62
- // Check direct serial number or serial from product name
63
- const deviceSerial = device.serialNumber || device.productName?.split(' ').pop();
64
- if (deviceSerial?.toLowerCase() === serialNumber.toLowerCase()) {
65
- return device;
66
- }
67
- }
68
- return null;
69
- }
70
- /**
71
- * Upload an AMX binary file to a USB device
72
- * @param serialNumber - The serial number of the target device
73
- * @param fileUri - The URI to the AMX file
74
- * @param fs - The filesystem interface for file operations
75
- * @param logger - The logger instance for output
76
- * @param debugLog - Enable debug logging
77
- * @returns Promise resolving to an UploadResult
78
- */
79
- async function uploadToDevice(serialNumber, fileUri, fs, logger, debugLog = false) {
80
- // Check if file exists
81
- const fileStat = await fs.stat(fileUri);
82
- if (!fileStat) {
83
- return {
84
- success: false,
85
- message: `File not found: ${fileUri.fsPath}`
86
- };
87
- }
88
- // Find the device by serial number
89
- logger.info(`Searching for device with serial number: ${serialNumber}`);
90
- const device = await findDeviceBySerialNumber(serialNumber);
91
- if (!device) {
92
- return {
93
- success: false,
94
- message: `Device not found with serial number: ${serialNumber}`
95
- };
96
- }
97
- logger.info(`Device found: ${device.productName}`);
98
- // Read the file contents
99
- const fileData = (await fs.readFile(fileUri));
100
- // Initialize UTO Master
101
- const utoMaster = new uto_master_1.UtoMaster();
102
- let deviceConnected = false;
103
- try {
104
- await utoMaster.init();
105
- // Set up UTO transmit callback
106
- utoMaster.utoTx(async (data) => {
107
- if (device.opened) {
108
- await device.transferOut(uto_master_1.USB_CONFIGURATION.utoEndpoint, data);
109
- }
110
- });
111
- if (debugLog) {
112
- utoMaster.on('mdnCom', (message) => {
113
- logger.log('mdnCom', message);
114
- });
115
- utoMaster.on('mdnComError', (message) => {
116
- logger.log('mdnComError', message);
117
- });
118
- }
119
- // Set up progress reporting
120
- let lastProgress = -1;
121
- utoMaster.on('installing', (data) => {
122
- if (!data) {
123
- return;
124
- }
125
- // /*const progress = Math.round(data.progress);
126
- if (data !== lastProgress) {
127
- lastProgress = data;
128
- logger.info(`Upload progress: ${data}%`);
129
- }
130
- });
131
- // Open device and claim interfaces
132
- await device.open();
133
- await device.selectConfiguration(uto_master_1.USB_CONFIGURATION.configurationNumber);
134
- await device.claimInterface(uto_master_1.USB_CONFIGURATION.utoInterface);
135
- deviceConnected = true;
136
- logger.info('Device connected, starting upload...');
137
- // Start UTO polling for receiving data
138
- startUtoPolling(device, utoMaster, () => deviceConnected);
139
- await utoMaster.requestDeviceInfo();
140
- // Upload the file
141
- await utoMaster.sendFile(utoStack_1.UtoFileType.pawn, new Uint8Array(fileData.buffer, fileData.byteOffset, fileData.length));
142
- logger.done('Upload completed successfully!');
143
- return {
144
- success: true,
145
- message: 'File uploaded successfully'
146
- };
147
- }
148
- catch (error) {
149
- const errorMessage = error instanceof Error ? error.message : String(error);
150
- return {
151
- success: false,
152
- message: `Upload failed: ${errorMessage}`
153
- };
154
- }
155
- finally {
156
- // Clean up - close device
157
- deviceConnected = false;
158
- if (device.opened) {
159
- try {
160
- await device.close().catch();
161
- }
162
- catch {
163
- // Ignore close errors
164
- }
165
- }
166
- }
167
- }
168
- /**
169
- * Start polling for UTO data from the device
170
- * @param device - The USB device
171
- * @param utoMaster - The UTO Master instance
172
- * @param isConnected - Function that returns connection status
173
- */
174
- async function startUtoPolling(device, utoMaster, isConnected) {
175
- while (isConnected()) {
176
- try {
177
- const result = await device.transferIn(uto_master_1.USB_CONFIGURATION.utoEndpoint, uto_master_1.USB_CONFIGURATION.utoSize);
178
- if (result.status === 'ok' && result.data) {
179
- const uint8Data = new Uint8Array(result.data.buffer);
180
- await utoMaster.utoRx(uint8Data);
181
- }
182
- }
183
- catch {
184
- // Connection lost or polling stopped
185
- break;
186
- }
187
- }
188
- }
189
- //# sourceMappingURL=usb.js.map