@microtronics/studio-cli 0.29.4 → 0.30.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,25 @@
1
1
 
2
2
 
3
- ## 0.29.4 (2025-04-25)
3
+ ## 0.30.0 (2025-05-05)
4
+
5
+
6
+ ### Features
7
+
8
+ * **studio-cli:** add support for packaging app projects ([280115f](https://bitbucket.org/microtronics-core/vscode-studio/commits/280115fa77afb78754884a4eb83bd0365ff5b319))
9
+ * **studio-cli:** add support for packaging library projects ([1888df1](https://bitbucket.org/microtronics-core/vscode-studio/commits/1888df1b5d8c2f53a9705756d28d42360109e3ba))
4
10
 
5
11
 
6
12
  ### Bug Fixes
7
13
 
14
+ * **studio-cli:** ensure dist/dlo directory is created on compile ([f110636](https://bitbucket.org/microtronics-core/vscode-studio/commits/f110636fc5042a5e25cc2d26fc98df4356d706bb))
15
+ * **studio-cli:** rename method in CustomWasmFS ([c3e1a22](https://bitbucket.org/microtronics-core/vscode-studio/commits/c3e1a227d7e57e91f9ddea45f11412ed59f71614))
16
+ * **studio-cli:** run dlo compiler relative to the cwd ([110b476](https://bitbucket.org/microtronics-core/vscode-studio/commits/110b4767bda8134aca2781c51f6e06bf800c4c67))
17
+
18
+ ## 0.29.4 (2025-04-25)
19
+
20
+
21
+ ### Bug Fixes
22
+
8
23
  * **studio-cli:** always use a clean app version as reference for dde generation ([da0b45b](https://bitbucket.org/microtronics-core/vscode-studio/commits/da0b45b5d9482056b3ead821e5b20e4083f4f06e))
9
24
 
10
25
  ## 0.29.3 (2025-04-25)
@@ -1807,48 +1807,17 @@ declare class DloCompiler {
1807
1807
  private cwd;
1808
1808
  private fs;
1809
1809
  private logger;
1810
- private preCompiler;
1811
1810
  private dloCC;
1812
1811
  private stdout;
1813
1812
  private stderr;
1814
1813
  constructor(cwd: URI, fs: LocalFS, logger: Log.Logger);
1815
1814
  private initDloCC;
1816
- private get MEMFS();
1817
1815
  compile(cwd: URI, fs: LocalFS): Promise<{
1818
1816
  code: number;
1819
1817
  stdout: string[];
1820
1818
  stderr: string[];
1821
1819
  diagnostics: Diagnostics.File[];
1822
1820
  }>;
1823
- private persistGeneratedFiles;
1824
- /**
1825
- * Search for all dlo files and persist it to the MEMFS
1826
- * @param cwd
1827
- * @param fs
1828
- * @param manifest
1829
- * @private
1830
- */
1831
- /**
1832
- * Precompile the given file and pass it to the MEMFS
1833
- * @param cwd
1834
- * @param manifest
1835
- * @param file
1836
- * @param stringBlob
1837
- */
1838
- memFSwriteFile(cwd: URI, manifest: Manifest.Manifest, file: URI, stringBlob: string[]): Promise<Diagnostics.File[]>;
1839
- /**
1840
- * Move a file within the MEMFS
1841
- * @param oldUri
1842
- * @param newUri
1843
- */
1844
- memFSmove(oldUri: URI, newUri: URI): Promise<void>;
1845
- /**
1846
- * Remove a file from the MEMFS
1847
- * @param uri
1848
- */
1849
- memFSunlink(uri: URI): Promise<void>;
1850
- private memFSmkdir;
1851
- private memFSstat;
1852
1821
  /**
1853
1822
  * Get a symbol compiler instance
1854
1823
  */
@@ -2146,6 +2115,12 @@ declare interface LocalFS {
2146
2115
  * @param target The destination location.
2147
2116
  */
2148
2117
  copy: (source: URI, target: URI) => Promise<any>;
2118
+ /**
2119
+ * Create a new directory
2120
+ *
2121
+ * @param path The directory path that should be created.
2122
+ */
2123
+ mkdir: (path: URI) => Promise<any>;
2149
2124
  }
2150
2125
 
2151
2126
  export declare namespace Log {
@@ -2319,6 +2294,19 @@ export declare namespace Manifest {
2319
2294
  export function isApmPartEnabled(cwd: URI, fs: LocalFS, apmPart: APM.Part, manifest?: Manifest.Manifest): Promise<boolean>;
2320
2295
  }
2321
2296
 
2297
+ /**
2298
+ * Packs the given directory into a deployable package using the specified configuration.
2299
+ *
2300
+ * @param {URI} cwd - The current working directory URI where the package is located.
2301
+ * @param {LocalFS} fs - The file system interface to perform file-related operations.
2302
+ * @param {Log.Logger} logger - The logger instance for logging activity during the packaging process.
2303
+ * @param {Globals.ENV} env - The environment variables and settings to use during packaging.
2304
+ * @param {string | null} apiToken - The API token used for authentication, if required.
2305
+ * @param {APM.TagPhase} [optsPhase] - An optional tag phase for the package tagging process.
2306
+ * @return {Promise<Package>} A promise that resolves to the packaged result.
2307
+ */
2308
+ export declare function pack(cwd: URI, fs: LocalFS, logger: Log.Logger, env: Globals.ENV, apiToken: string | null, optsPhase?: APM.TagPhase): Promise<void>;
2309
+
2322
2310
  export declare namespace Package {
2323
2311
  export interface MergedDiagnostics {
2324
2312
  [APM.Part.dde]: Diagnostics.File[];
@@ -2350,6 +2338,7 @@ export declare namespace Package {
2350
2338
  * @param env
2351
2339
  */
2352
2340
  export function release(cwd: URI, fs: LocalFS, logger: Log.Logger, env: Globals.ENV, token: Registry.AuthToken, releasePhase?: APM.TagPhase, allowedBackends?: Registry.ApiNewApplication['allowedBackends']): Promise<void>;
2341
+ export function pack(cwd: URI, fs: LocalFS, logger: Log.Logger, env: Globals.ENV, token: Registry.AuthToken, releasePhase?: APM.TagPhase): Promise<void>;
2353
2342
  /**
2354
2343
  * Publish an application model tag
2355
2344
  * @param cwd
@@ -2395,7 +2384,7 @@ export declare namespace Package {
2395
2384
  export function validatePublishSettings(cwd: URI, fs: LocalFS, token: Registry.AuthToken, env: Globals.ENV): Promise<void>;
2396
2385
  }
2397
2386
 
2398
- declare function parseWarningsAndErrors(stderr: string[], relatedFile?: URI): Diagnostics.File[];
2387
+ declare function parseWarningsAndErrors(cwd: URI, stderr: string[], relatedFile?: URI): Diagnostics.File[];
2399
2388
 
2400
2389
  /**
2401
2390
  * This file was auto-generated by openapi-typescript.
package/out/api.js CHANGED
@@ -4,6 +4,7 @@ exports.Log = exports.ENV = exports.DFILES = exports.Library = exports.APM = exp
4
4
  exports.install = install;
5
5
  exports.build = build;
6
6
  exports.publish = publish;
7
+ exports.pack = pack;
7
8
  const dependencies_1 = require("./dependencies");
8
9
  Object.defineProperty(exports, "Dependencies", { enumerable: true, get: function () { return dependencies_1.Dependencies; } });
9
10
  const manifest_1 = require("./manifest");
@@ -79,6 +80,26 @@ async function install(cwd, fs, env, apiToken, dependencies) {
79
80
  async function build(cwd, fs, logger, env, apiToken = null, selectedParts = true, errorWithDiagnostics) {
80
81
  return package_1.Package.buildAll(cwd, fs, logger, env, apiToken, selectedParts, errorWithDiagnostics);
81
82
  }
83
+ /**
84
+ * Parses and validates the allowed backends configuration.
85
+ *
86
+ * @param {string | undefined} optsAllowedBackends - A string defining allowed backends,
87
+ * either as a semicolon-separated list of backends or the wildcard '*'. It may also be undefined.
88
+ * @return {Promise<Registry.ApiNewApplication['allowedBackends']>} A promise that resolves to
89
+ * an array of allowed backends or null if none are provided.
90
+ * @throws {Error} Throws an error if the validation of the allowed backends fails.
91
+ */
92
+ async function parseAllowedBackends(optsAllowedBackends) {
93
+ let allowedBackends = null;
94
+ if (optsAllowedBackends) {
95
+ allowedBackends = optsAllowedBackends === '*' ? optsAllowedBackends : optsAllowedBackends.split(';');
96
+ const errorMessage = await manifest_1.Manifest.validateRegistryAllowedBackends(allowedBackends);
97
+ if (errorMessage) {
98
+ throw new Error(errorMessage);
99
+ }
100
+ }
101
+ return allowedBackends;
102
+ }
82
103
  /**
83
104
  * Publishes a package to the registry with the specified settings and configurations.
84
105
  *
@@ -93,14 +114,22 @@ async function build(cwd, fs, logger, env, apiToken = null, selectedParts = true
93
114
  */
94
115
  async function publish(cwd, fs, logger, env, apiToken, optsAllowedBackends, optsPhase) {
95
116
  logger.info('Publishing package...');
96
- let allowedBackends = null;
97
- if (optsAllowedBackends) {
98
- allowedBackends = optsAllowedBackends === '*' ? optsAllowedBackends : optsAllowedBackends.split(';');
99
- const errorMessage = await manifest_1.Manifest.validateRegistryAllowedBackends(allowedBackends);
100
- if (errorMessage) {
101
- throw new Error(errorMessage);
102
- }
103
- }
117
+ const allowedBackends = await parseAllowedBackends(optsAllowedBackends);
118
+ await package_1.Package.validatePublishSettings(cwd, fs, apiToken, env);
104
119
  return package_1.Package.release(cwd, fs, logger, env, apiToken, optsPhase, allowedBackends);
105
120
  }
121
+ /**
122
+ * Packs the given directory into a deployable package using the specified configuration.
123
+ *
124
+ * @param {URI} cwd - The current working directory URI where the package is located.
125
+ * @param {LocalFS} fs - The file system interface to perform file-related operations.
126
+ * @param {Log.Logger} logger - The logger instance for logging activity during the packaging process.
127
+ * @param {Globals.ENV} env - The environment variables and settings to use during packaging.
128
+ * @param {string | null} apiToken - The API token used for authentication, if required.
129
+ * @param {APM.TagPhase} [optsPhase] - An optional tag phase for the package tagging process.
130
+ * @return {Promise<Package>} A promise that resolves to the packaged result.
131
+ */
132
+ async function pack(cwd, fs, logger, env, apiToken, optsPhase) {
133
+ return package_1.Package.pack(cwd, fs, logger, env, apiToken, optsPhase);
134
+ }
106
135
  //# sourceMappingURL=api.js.map
package/out/cliFS.js CHANGED
@@ -66,6 +66,9 @@ exports.cliFS = {
66
66
  else {
67
67
  return promises_1.default.copyFile(source.fsPath, target.fsPath);
68
68
  }
69
+ },
70
+ async mkdir(path) {
71
+ await promises_1.default.mkdir(path.fsPath, { recursive: true });
69
72
  }
70
73
  };
71
74
  //# sourceMappingURL=cliFS.js.map
@@ -25,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.CUSTOM_WASM_FS = exports.precompilerDiagnostics = void 0;
27
27
  exports.uriToMemFsPath = uriToMemFsPath;
28
+ exports.relativeMemFsPath = relativeMemFsPath;
28
29
  const nodeFs = __importStar(require("fs"));
29
30
  const vscode_uri_1 = require("vscode-uri");
30
31
  const preCompiler_1 = require("./preCompiler");
@@ -62,6 +63,25 @@ const CUSTOM_WASM_FS = (FS, cwd, manifest) => {
62
63
  ctime: stat.ctime
63
64
  };
64
65
  },
66
+ setattr(node, attr) {
67
+ const path = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(node.mount.opts.root), FS.getPath(node)).fsPath;
68
+ if (!nodeFs.existsSync(path)) {
69
+ throw new FS.ErrnoError(44 /* ENOENT */);
70
+ }
71
+ // Change file size (truncate/grow)
72
+ if (typeof attr.size === 'number') {
73
+ nodeFs.truncateSync(path, attr.size);
74
+ }
75
+ // Change file mode (permissions)
76
+ if (typeof attr.mode === 'number') {
77
+ nodeFs.chmodSync(path, attr.mode);
78
+ }
79
+ // Change access/modification time
80
+ if (attr.atime || attr.mtime) {
81
+ const stat = nodeFs.statSync(path);
82
+ nodeFs.utimesSync(path, attr.atime ?? stat.atime, attr.mtime ?? stat.mtime);
83
+ }
84
+ },
65
85
  lookup(parent, name) {
66
86
  const currPath = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(parent.mount.opts.root), FS.getPath(parent), name);
67
87
  const path = currPath.fsPath;
@@ -81,7 +101,10 @@ const CUSTOM_WASM_FS = (FS, cwd, manifest) => {
81
101
  mknod(parent, name, mode, dev) {
82
102
  const path = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(parent.mount.opts.root), FS.getPath(parent), name).fsPath;
83
103
  nodeFs.writeFileSync(path, '');
84
- return FS.createNode(parent, name, mode, dev);
104
+ const node = FS.createNode(parent, name, mode, dev);
105
+ node.node_ops = parent.node_ops;
106
+ node.stream_ops = parent.stream_ops;
107
+ return node;
85
108
  },
86
109
  unlink(parent, name) {
87
110
  const path = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(parent.mount.opts.root), FS.getPath(parent), name).fsPath;
@@ -90,14 +113,17 @@ const CUSTOM_WASM_FS = (FS, cwd, manifest) => {
90
113
  mkdir(parent, name, mode) {
91
114
  const path = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(parent.mount.opts.root), FS.getPath(parent), name).fsPath;
92
115
  nodeFs.mkdirSync(path, { mode });
93
- return FS.createNode(parent, name, mode | MODE_DIR, 0);
116
+ const node = FS.createNode(parent, name, mode | MODE_DIR, 0);
117
+ node.node_ops = parent.node_ops;
118
+ node.stream_ops = parent.stream_ops;
119
+ return node;
94
120
  },
95
121
  rmdir(parent, name) {
96
122
  const path = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(parent.mount.opts.root), FS.getPath(parent), name).fsPath;
97
123
  nodeFs.rmdirSync(path);
98
124
  },
99
- rename(oldParent, oldName, newParent, newName) {
100
- const oldPath = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(oldParent.mount.opts.root), FS.getPath(oldParent), oldName).fsPath;
125
+ rename(oldParent, newParent, newName) {
126
+ const oldPath = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(oldParent.mount.opts.root), FS.getPath(oldParent)).fsPath;
101
127
  const newPath = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.parse(newParent.mount.opts.root), FS.getPath(newParent), newName).fsPath;
102
128
  nodeFs.renameSync(oldPath, newPath);
103
129
  }
@@ -224,4 +250,9 @@ function precompileRequestedDloFile(cwd, manifest, filePath) {
224
250
  function uriToMemFsPath(path) {
225
251
  return path.fsPath.replace(/\\/g, '/');
226
252
  }
253
+ function relativeMemFsPath(cwd, path) {
254
+ const cwdPath = uriToMemFsPath(cwd);
255
+ const fsPath = uriToMemFsPath(path);
256
+ return fsPath.replace(cwdPath, '');
257
+ }
227
258
  //# sourceMappingURL=CustomWasmFS.js.map
@@ -1,37 +1,12 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.DloCompiler = void 0;
27
4
  exports.parseWarningsAndErrors = parseWarningsAndErrors;
28
5
  exports.generateConfigFile = generateConfigFile;
29
- const preCompiler_1 = require("./preCompiler");
30
6
  const vscode_uri_1 = require("vscode-uri");
31
7
  const manifest_1 = require("../manifest");
32
8
  const defaultFiles_1 = require("../defaultFiles");
33
9
  const dependencies_1 = require("../dependencies");
34
- const iconv = __importStar(require("iconv-lite"));
35
10
  const apm_1 = require("../package/apm");
36
11
  const CustomWasmFS_1 = require("./CustomWasmFS");
37
12
  const DLO_MODULE = require('./dlocc.js');
@@ -39,7 +14,6 @@ class DloCompiler {
39
14
  cwd;
40
15
  fs;
41
16
  logger;
42
- preCompiler = new preCompiler_1.DloPreCompiler();
43
17
  dloCC;
44
18
  stdout = [];
45
19
  stderr = [];
@@ -55,16 +29,18 @@ class DloCompiler {
55
29
  this.dloCC = await DLO_MODULE({
56
30
  noExitRuntime: noExit,
57
31
  print: (data) => {
58
- this.logger.log(data);
32
+ const patched = parseCompilerMessage(this.cwd, data);
33
+ this.logger.log(patched ? patched.message : data);
59
34
  this.stdout.push(data);
60
35
  },
61
36
  printErr: (err) => {
37
+ const patched = parseCompilerMessage(this.cwd, err);
62
38
  // filter for warn messages
63
39
  if (err.includes(': warning')) {
64
- this.logger.warn(err);
40
+ this.logger.warn(patched ? patched.message : err);
65
41
  }
66
42
  else {
67
- this.logger.error(err);
43
+ this.logger.error(patched ? patched.message : err);
68
44
  }
69
45
  this.stderr.push(err);
70
46
  this.stdout.push(err);
@@ -78,9 +54,8 @@ class DloCompiler {
78
54
  FS.filesystems.NODEFS_TS = (0, CustomWasmFS_1.CUSTOM_WASM_FS)(FS, this.cwd, manifest);
79
55
  FS.mkdir(rootDir);
80
56
  FS.mount(FS.filesystems.NODEFS_TS, { root: '/' }, rootDir);
81
- }
82
- get MEMFS() {
83
- return this.dloCC.FS;
57
+ // Set the current working directory to the root directory
58
+ FS.chdir((0, CustomWasmFS_1.uriToMemFsPath)(this.cwd));
84
59
  }
85
60
  async compile(cwd, fs) {
86
61
  const manifest = await manifest_1.Manifest.read(cwd, fs);
@@ -94,18 +69,17 @@ class DloCompiler {
94
69
  };
95
70
  }
96
71
  await this.initDloCC();
72
+ await fs.mkdir(vscode_uri_1.Utils.joinPath(cwd, 'dist/dlo'));
97
73
  const mainFile = vscode_uri_1.Utils.joinPath(cwd, manifest.dlo?.mainFile || defaultFiles_1.DefaultFiles.filePaths.dlo.mainDLO);
98
74
  const options = [];
99
75
  // read config file
100
76
  const configFilePath = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.studio.auto.dlo.cfg);
101
- options.push(`-T${(0, CustomWasmFS_1.uriToMemFsPath)(configFilePath)}`);
77
+ const configFile = (0, CustomWasmFS_1.relativeMemFsPath)(cwd, configFilePath);
78
+ options.push(`-T.${configFile}`);
102
79
  let exitCode = 0;
103
80
  try {
104
- exitCode = await this.dloCC.callMain([(0, CustomWasmFS_1.uriToMemFsPath)(mainFile), ...options]);
105
- // compiler doesn't have any errors
106
- if (exitCode === 0) {
107
- await this.persistGeneratedFiles(cwd, fs, mainFile);
108
- }
81
+ const mainFilePath = `.${(0, CustomWasmFS_1.relativeMemFsPath)(cwd, mainFile)}`;
82
+ exitCode = await this.dloCC.callMain([mainFilePath, ...options]);
109
83
  }
110
84
  catch (e) {
111
85
  this.logger.error(e);
@@ -114,109 +88,9 @@ class DloCompiler {
114
88
  code: exitCode,
115
89
  stdout: this.stdout,
116
90
  stderr: this.stderr,
117
- diagnostics: [...CustomWasmFS_1.precompilerDiagnostics, ...parseWarningsAndErrors(this.stderr, mainFile)]
91
+ diagnostics: [...CustomWasmFS_1.precompilerDiagnostics, ...parseWarningsAndErrors(cwd, this.stderr, mainFile)]
118
92
  };
119
93
  }
120
- async persistGeneratedFiles(cwd, fs, mainFile) {
121
- const baseName = vscode_uri_1.Utils.basename(mainFile).split('.')[0];
122
- const possibleFiles = this.MEMFS.readdir('/');
123
- for (const fileName of possibleFiles) {
124
- if (fileName.startsWith(baseName)) {
125
- const blob = this.MEMFS.readFile(fileName);
126
- const distPath = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.dist.dloPath, fileName);
127
- await fs.writeFile(distPath, blob);
128
- }
129
- }
130
- }
131
- /**
132
- * Search for all dlo files and persist it to the MEMFS
133
- * @param cwd
134
- * @param fs
135
- * @param manifest
136
- * @private
137
- */
138
- /* private async persistDloFiles(cwd: URI, fs: LocalFS, manifest: Manifest.Manifest) {
139
- const files = await fs.findFiles(cwd, '**!/!*.{dlo,inc}');
140
- const precompilerDiagnostics: Diagnostics.File[] = [];
141
- // add dlo.cfg file to the file list
142
- for (const file of files) {
143
- if (await fs.stat(file)) {
144
- const content = await fs.readFile(file);
145
- const stringBlob = convertBlobToStringArray(content);
146
- const diagnostics = await this.memFSwriteFile(cwd, manifest, file, stringBlob);
147
- precompilerDiagnostics.push(...diagnostics);
148
- }
149
- }
150
- return precompilerDiagnostics;
151
- }*/
152
- /**
153
- * Precompile the given file and pass it to the MEMFS
154
- * @param cwd
155
- * @param manifest
156
- * @param file
157
- * @param stringBlob
158
- */
159
- async memFSwriteFile(cwd, manifest, file, stringBlob) {
160
- const precompilerDiagnostics = [];
161
- const preCompiled = this.preCompiler.preCompileDloFile(cwd, manifest, file, stringBlob);
162
- precompilerDiagnostics.push(...preCompiled.diagnostics);
163
- this.memFSmkdir(file);
164
- this.MEMFS.writeFile((0, CustomWasmFS_1.uriToMemFsPath)(file), iconv.encode(preCompiled.data, 'cp1252'));
165
- return precompilerDiagnostics;
166
- }
167
- /**
168
- * Move a file within the MEMFS
169
- * @param oldUri
170
- * @param newUri
171
- */
172
- async memFSmove(oldUri, newUri) {
173
- try {
174
- this.memFSmkdir(newUri);
175
- this.MEMFS.rename((0, CustomWasmFS_1.uriToMemFsPath)(oldUri), (0, CustomWasmFS_1.uriToMemFsPath)(newUri));
176
- }
177
- catch (e) {
178
- this.logger.error('memFSmove', e);
179
- }
180
- }
181
- /**
182
- * Remove a file from the MEMFS
183
- * @param uri
184
- */
185
- async memFSunlink(uri) {
186
- try {
187
- this.MEMFS.unlink((0, CustomWasmFS_1.uriToMemFsPath)(uri));
188
- }
189
- catch (e) {
190
- this.logger.error('memFSunlink', e);
191
- }
192
- }
193
- memFSmkdir(uri) {
194
- const split = (0, CustomWasmFS_1.uriToMemFsPath)(vscode_uri_1.Utils.dirname(uri)).split('/');
195
- let dirname = '';
196
- split.forEach(folder => {
197
- if (!folder) {
198
- return;
199
- }
200
- try {
201
- dirname += `${folder}/`;
202
- if (!this.memFSstat(dirname)) {
203
- this.MEMFS.mkdir(dirname);
204
- }
205
- }
206
- catch (e) {
207
- this.logger.error('memFSmkdir', e);
208
- }
209
- });
210
- }
211
- memFSstat(dirname) {
212
- try {
213
- this.MEMFS.stat(dirname);
214
- return true;
215
- }
216
- catch (e) {
217
- return false;
218
- }
219
- }
220
94
  //Symbol Compiler handling
221
95
  /**
222
96
  * Get a symbol compiler instance
@@ -253,7 +127,7 @@ class DloCompiler {
253
127
  }
254
128
  }
255
129
  exports.DloCompiler = DloCompiler;
256
- function parseWarningsAndErrors(stderr, relatedFile) {
130
+ function parseWarningsAndErrors(cwd, stderr, relatedFile) {
257
131
  const compilerDiagnostics = [];
258
132
  const messages = stderr.filter(line => !!line.trim());
259
133
  for (const message of messages) {
@@ -266,35 +140,44 @@ function parseWarningsAndErrors(stderr, relatedFile) {
266
140
  });
267
141
  continue;
268
142
  }
269
- // regular error/warning - such as:
270
- // C:\Users\aai\rmstudio\apmparts\dlo-pawn\stdlib\rm-dde.inc(392) : error 036: empty statement
271
- // main.p(138) : warning 203: symbol is never used: "log_str"
272
- // main.p(6) : fatal error 100: cannot read from file: "oTests/module_t"
273
- const i0 = message.indexOf(' : ');
274
- const i1 = message.indexOf(': ', i0 + 3);
275
- const fileNameAndLineNumber = message.substring(0, i0).trim();
276
- const levelAndCode = message.substring(i0 + 3, i1).trim();
277
- const msg = message.substring(i1 + 2).trim();
278
- // ignore lines which do not contain err/warn msg (or are empty)
279
- if (!fileNameAndLineNumber || !levelAndCode || !msg) {
143
+ const parsedMessage = parseCompilerMessage(cwd, message);
144
+ if (!parsedMessage) {
280
145
  continue;
281
146
  }
282
- const [fileName, lineNumber] = fileNameAndLineNumber.split(/[()(-)]/);
283
- const decodeLevelAndCode = levelAndCode.split(' ');
284
- const level = decodeLevelAndCode[decodeLevelAndCode.length - 2]; //lvl is always the second last
285
- let posix = fileName.replace(/\\/g, '/');
286
- if (posix.startsWith('/')) {
287
- posix = posix.substring(1);
288
- }
289
147
  compilerDiagnostics.push({
290
- file: vscode_uri_1.URI.parse(`file:///${posix}`),
291
- level,
292
- line: Number(lineNumber) - 1,
293
- message: msg
148
+ file: vscode_uri_1.URI.parse(`file:///${parsedMessage?.posixPath}`),
149
+ level: parsedMessage.level,
150
+ line: Number(parsedMessage.lineNumber) - 1,
151
+ message: parsedMessage.msg
294
152
  });
295
153
  }
296
154
  return compilerDiagnostics;
297
155
  }
156
+ function parseCompilerMessage(cwd, message) {
157
+ // regular error/warning - such as:
158
+ // C:\Users\aai\rmstudio\apmparts\dlo-pawn\stdlib\rm-dde.inc(392) : error 036: empty statement
159
+ // main.p(138) : warning 203: symbol is never used: "log_str"
160
+ // main.p(6) : fatal error 100: cannot read from file: "oTests/module_t"
161
+ const i0 = message.indexOf(' : ');
162
+ const i1 = message.indexOf(': ', i0 + 3);
163
+ const fileNameAndLineNumber = message.substring(0, i0).trim();
164
+ const levelAndCode = message.substring(i0 + 3, i1).trim();
165
+ const msg = message.substring(i1 + 2).trim();
166
+ // ignore lines which do not contain err/warn msg (or are empty)
167
+ if (!fileNameAndLineNumber || !levelAndCode || !msg) {
168
+ return null;
169
+ }
170
+ const [fileName, lineNumber] = fileNameAndLineNumber.split(/[()(-)]/);
171
+ const decodeLevelAndCode = levelAndCode.split(' ');
172
+ const level = decodeLevelAndCode[decodeLevelAndCode.length - 2]; //lvl is always the second last
173
+ const filePath = vscode_uri_1.Utils.joinPath(cwd, fileName);
174
+ let posixPath = filePath.fsPath.replace(/\\/g, '/');
175
+ if (posixPath.startsWith('/')) {
176
+ posixPath = posixPath.substring(1);
177
+ }
178
+ const patchedMessage = message.replace(fileName, posixPath);
179
+ return { level, msg, posixPath, lineNumber, message: patchedMessage };
180
+ }
298
181
  /**
299
182
  * Generates the DLO .cfg file for the dlo compiler
300
183
  * @param cwd
@@ -307,16 +190,17 @@ async function generateConfigFile(cwd, fs, manifest) {
307
190
  '-v2' // verbosity of stdout -> 0=quiet, 1=normal, 2=code/data/stack usage report
308
191
  ];
309
192
  const defaultIncPath = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.studio.auto.dlo.defaultInc);
310
- compileOptions.push(`-p${(0, CustomWasmFS_1.uriToMemFsPath)(defaultIncPath)}`);
193
+ compileOptions.push(`-p.${(0, CustomWasmFS_1.relativeMemFsPath)(cwd, defaultIncPath)}`);
311
194
  const dloLibs = await dependencies_1.Dependencies.getApmPartDependencies(cwd, fs, apm_1.APM.Part.dlo);
312
195
  for (const dloLib of dloLibs) {
313
196
  const dirName = vscode_uri_1.Utils.dirname(dloLib.path);
314
- compileOptions.push(`-i${(0, CustomWasmFS_1.uriToMemFsPath)(dirName)}`);
197
+ compileOptions.push(`-i.${(0, CustomWasmFS_1.relativeMemFsPath)(cwd, dirName)}`);
315
198
  }
316
199
  const dloConfiguration = manifest.dlo;
317
200
  if (dloConfiguration) {
318
201
  compileOptions.push(...dloConfiguration.compileOptions);
319
202
  }
203
+ compileOptions.push(`-o./dist/dlo/main.amx`);
320
204
  return {
321
205
  path: vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.studio.auto.dlo.cfg),
322
206
  data: compileOptions.join('\n')
package/out/main.js CHANGED
@@ -69,6 +69,23 @@ const optionStudioEnv = new commander_1.Option('-e, --env <environment>', 'CLI t
69
69
  * Generic option for the STUDIO_TOKEN
70
70
  */
71
71
  const optionStudioToken = new commander_1.Option('--token <API-token>', 'API Access Token (defaults to STUDIO_TOKEN environment variable)').default(process.env['STUDIO_TOKEN']);
72
+ /**
73
+ * Represents a command-line option for specifying the allowed backends deployment for a version.
74
+ *
75
+ * This variable represents an instance of an `Option` that determines which backends are permitted
76
+ * during the deployment process. The backends can be specified as*/
77
+ const optionAllowedBackends = new commander_1.Option('--allowedBackends <null|*|server.xz;server.yz>', 'specify the allowedBackends deployment for this version.').default(null);
78
+ const releasePhaseArguments = Object.values(apm_1.APM.TagPhase);
79
+ /**
80
+ * Represents a command-line option for specifying a release phase in a software deployment process.
81
+ *
82
+ * The option includes a flag `-ph` or `--phase`, followed by the user-defined release phase value. It offers predefined
83
+ * choices for acceptable release phase arguments, ensuring input validation. If no value is explicitly provided,
84
+ * the default release phase is set to 'release'.
85
+ */
86
+ const optionReleasePhase = new commander_1.Option('-ph --phase <release phase>', 'specify a release phase')
87
+ .choices(releasePhaseArguments)
88
+ .default('release');
72
89
  program
73
90
  .command('install')
74
91
  .aliases(['i'])
@@ -91,19 +108,27 @@ program
91
108
  const { env, token } = getDefaultOptions(opts);
92
109
  main((0, api_1.build)(cwd, cliFS_1.cliFS, logger, env, token, opts.part));
93
110
  });
94
- const releasePhaseArguments = Object.values(apm_1.APM.TagPhase);
95
111
  program
96
112
  .command('publish')
97
- .addOption(new commander_1.Option('-ph --phase <release phase>', 'specify a release phase')
98
- .choices(releasePhaseArguments)
99
- .default('release'))
100
- .addOption(new commander_1.Option('--allowedBackends <null|*|server.xz;server.yz>', 'specify the allowedBackends deployment for this version.').default(null))
113
+ .addOption(optionReleasePhase)
114
+ .addOption(optionAllowedBackends)
101
115
  .addOption(optionStudioEnv)
102
116
  .addOption(optionStudioToken)
103
117
  .action(async (opts) => {
104
118
  const { env, token } = getDefaultOptions(opts);
105
119
  main((0, api_1.publish)(cwd, cliFS_1.cliFS, logger, env, token, opts.allowedBackends, opts.phase));
106
120
  });
121
+ program
122
+ .command('package')
123
+ .alias('pack')
124
+ .description('Package the project')
125
+ .addOption(optionReleasePhase)
126
+ .addOption(optionStudioEnv)
127
+ .addOption(optionStudioToken)
128
+ .action(async (opts) => {
129
+ const { env, token } = getDefaultOptions(opts);
130
+ main((0, api_1.pack)(cwd, cliFS_1.cliFS, logger, env, token, opts.phase));
131
+ });
107
132
  module.exports = function (argv) {
108
133
  program.parse(argv);
109
134
  };
@@ -14,6 +14,8 @@ const registryAPI_1 = require("../registryAPI");
14
14
  const manifest_1 = require("../manifest");
15
15
  const library_1 = require("./library");
16
16
  const dfiles_1 = require("../dfiles/dfiles");
17
+ const pako = require('pako');
18
+ const tarball = require('tarballjs');
17
19
  var Package;
18
20
  (function (Package) {
19
21
  class BuildError extends Error {
@@ -114,6 +116,29 @@ var Package;
114
116
  }
115
117
  }
116
118
  Package.release = release;
119
+ async function pack(cwd, fs, logger, env, token, releasePhase) {
120
+ const manifest = await manifest_1.Manifest.read(cwd, fs);
121
+ const archiveName = `${manifest.name}-${manifest.version}.tar.gz`;
122
+ let archive = null;
123
+ if (manifest_1.Manifest.isLibrary(manifest)) {
124
+ logger.info('Library project detected. Packing library...');
125
+ archive = await createLibraryPackage(cwd, fs, logger, token, env);
126
+ }
127
+ else {
128
+ logger.info('App project detected. Packing app...');
129
+ const apmTag = await createAPMPackage(cwd, fs, logger, token, releasePhase, env);
130
+ archive = await createArchiveFromApmPackage(apmTag);
131
+ }
132
+ const archivePath = vscode_uri_1.Utils.joinPath(cwd, archiveName);
133
+ if (archive !== null) {
134
+ await fs.writeFile(archivePath, archive);
135
+ logger.done(`Packaged: ${archivePath.fsPath}`);
136
+ }
137
+ else {
138
+ logger.error(`Could not create archive: ${archivePath.fsPath}`);
139
+ }
140
+ }
141
+ Package.pack = pack;
117
142
  /**
118
143
  * Publish an application model tag
119
144
  * @param cwd
@@ -125,19 +150,13 @@ var Package;
125
150
  * @param env
126
151
  */
127
152
  async function releaseAPM(cwd, fs, logger, token, releasePhase, allowedBackends = null, env) {
128
- if (!Object.values(apm_1.APM.TagPhase).includes(releasePhase)) {
129
- throw new Error(`ReleasePhase: ${releasePhase} is not a valid release phase`);
130
- }
131
- await manifest_1.Manifest.validateBasicManifest(cwd, fs, null);
132
153
  const application = await apm_1.APM.validateAccess(cwd, fs, token, false, env);
133
154
  if (!application) {
134
- return;
155
+ throw new Error('Could not validate access to application');
135
156
  }
136
- // build the complete project
137
- await buildAll(cwd, fs, logger, env, token);
157
+ const tagContent = await createAPMPackage(cwd, fs, logger, token, releasePhase, env);
138
158
  // update the store apm with the actual name/description/...
139
159
  await apm_1.APM.updateProfile(cwd, fs, token, env);
140
- const tagContent = await apm_1.APM.createTag(cwd, fs, releasePhase);
141
160
  const newTag = await apm_1.APM.publishTag(cwd, fs, token, tagContent, env);
142
161
  if (allowedBackends !== null) {
143
162
  const manifest = await manifest_1.Manifest.read(cwd, fs);
@@ -160,11 +179,7 @@ var Package;
160
179
  */
161
180
  async function releaseLibrary(cwd, fs, logger, token, env) {
162
181
  const manifest = await manifest_1.Manifest.read(cwd, fs);
163
- await manifest_1.Manifest.validateBasicManifest(cwd, fs, manifest);
164
- await validatePublishSettings(cwd, fs, token, env);
165
- // build the complete project
166
- await buildAll(cwd, fs, logger, env, token);
167
- const archive = await library_1.Library.createArchive(cwd, fs);
182
+ const archive = await createLibraryPackage(cwd, fs, logger, token, env);
168
183
  await library_1.Library.publishPackage(cwd, fs, token, archive, env);
169
184
  logger.done(`Library "${manifest.publisher}/${manifest.name}" with version "${manifest.version}" published!`);
170
185
  }
@@ -357,4 +372,36 @@ function logDiagnostics(logger, diagnostics) {
357
372
  }
358
373
  });
359
374
  }
375
+ async function createLibraryPackage(cwd, fs, logger, token, env) {
376
+ const manifest = await manifest_1.Manifest.read(cwd, fs);
377
+ await manifest_1.Manifest.validateBasicManifest(cwd, fs, manifest);
378
+ // build the complete project
379
+ await Package.buildAll(cwd, fs, logger, env, token);
380
+ return await library_1.Library.createArchive(cwd, fs);
381
+ }
382
+ async function createAPMPackage(cwd, fs, logger, token, releasePhase, env) {
383
+ if (!Object.values(apm_1.APM.TagPhase).includes(releasePhase)) {
384
+ throw new Error(`ReleasePhase: ${releasePhase} is not a valid release phase`);
385
+ }
386
+ await manifest_1.Manifest.validateBasicManifest(cwd, fs, null);
387
+ // build the complete project
388
+ await Package.buildAll(cwd, fs, logger, env, token);
389
+ return await apm_1.APM.createTag(cwd, fs, releasePhase);
390
+ }
391
+ async function createArchiveFromApmPackage(data) {
392
+ const tar = new tarball.TarWriter();
393
+ // @ts-ignore .entries is valid on FormData
394
+ for (const [name, value] of data.entries()) {
395
+ if (name === 'tag') {
396
+ const fileNode = value;
397
+ tar.addTextFile(name, fileNode);
398
+ }
399
+ else {
400
+ const fileNode = value;
401
+ tar.addFileArrayBuffer(name, await fileNode.arrayBuffer());
402
+ }
403
+ }
404
+ const tarBuffer = await tar.write();
405
+ return pako.gzip(tarBuffer);
406
+ }
360
407
  //# sourceMappingURL=package.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microtronics/studio-cli",
3
- "version": "0.29.4",
3
+ "version": "0.30.0",
4
4
  "description": "Microtronics Studio CLI Tool",
5
5
  "main": "./out/api.js",
6
6
  "typings": "./dist/studio-cli.d.ts",
@@ -63,9 +63,11 @@
63
63
  "chai": "^4.3.8",
64
64
  "chai-as-promised": "^7.1.2",
65
65
  "cross-env": "^7.0.3",
66
+ "extract-zip": "^2.0.1",
66
67
  "mocha": "^10.8.2",
67
68
  "mocha-junit-reporter": "^2.2.1",
68
69
  "openapi-typescript": "^7.6.0",
70
+ "tar": "^7.4.3",
69
71
  "ts-node": "^10.9.2",
70
72
  "typescript": "^5.6.3"
71
73
  },