@microtronics/studio-cli 0.36.0 → 0.38.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,9 +1,26 @@
1
1
  # Changelog
2
2
 
3
- ## 0.36.0 (2025-09-25)
3
+ ## 0.38.0 (2025-10-23)
4
4
 
5
- ### Bug Fixes
5
+ ### Features
6
6
 
7
+ * **cli:** dde generation filter out used containers in precompiler ([15a6c3e](https://bitbucket.org/microtronics-core/vscode-studio/commits/15a6c3eebb8245a3673311de64fa493dfc8c2094))
8
+
9
+ ## 0.37.0 (2025-10-22)
10
+
11
+ ### Features
12
+
13
+ * **cli:** add write permission for timeseries for type addon ([d8b8f05](https://bitbucket.org/microtronics-core/vscode-studio/commits/d8b8f059873f2c4503aef8b1a39d96707f843884))
14
+ * **cli:** enhance regex for relation validation ([7d995c4](https://bitbucket.org/microtronics-core/vscode-studio/commits/7d995c47bc6c24abdb2af6717f4df50f727a1b7a))
15
+ * **cli:** enhance support for cross-library relations ([3d9a6f7](https://bitbucket.org/microtronics-core/vscode-studio/commits/3d9a6f789758bfccf01963e7386573a54fe11f71))
16
+ * **cli:** improve container title extraction logic ([2a0618a](https://bitbucket.org/microtronics-core/vscode-studio/commits/2a0618aae01ed30c3c854430b0bd5ff4454b6288))
17
+ * **cli:** update `isApp` logic to handle undefined type ([fc9c12d](https://bitbucket.org/microtronics-core/vscode-studio/commits/fc9c12ddebdffe4ca9fbed10359ce9b8265f3e57))
18
+ * **core:** extend regex patterns for relation validation ([5ffe3b4](https://bitbucket.org/microtronics-core/vscode-studio/commits/5ffe3b4cad70a842111a937e5c8bd9306571f688))
19
+
20
+ ## 0.36.0 (2025-09-25)
21
+
22
+ ### Bug Fixes
23
+
7
24
  * **cli:** enhance DDE function mangling logic for libraries ([4d2272d](https://bitbucket.org/microtronics-core/vscode-studio/commits/4d2272d627530dbbfb342899549c7c76a99c6c56))
8
25
 
9
26
  ## 0.35.0 (2025-09-12)
@@ -1,4 +1,6 @@
1
+ import { Document as Document_2 } from 'yaml';
1
2
  import { LineCounter } from 'yaml';
3
+ import { ParsedNode } from 'yaml';
2
4
  import { Range as Range_2 } from 'yaml';
3
5
  import { SemVer } from 'semver';
4
6
  import { URI } from 'vscode-uri';
@@ -1174,7 +1176,7 @@ export declare namespace DDE {
1174
1176
  * Generate the needed xml for the myDatanet application
1175
1177
  * @param ddeJSON
1176
1178
  */
1177
- export function generateMyDatanetXML(ddeJSON: DDEJson): string;
1179
+ export function generateMyDatanetXML(manifest: Manifest.Manifest, ddeJSON: DDEJson): string;
1178
1180
  /**
1179
1181
  * Generate the xml dde notation and write it to the correct dist directory
1180
1182
  * @param cwd
@@ -4727,6 +4729,7 @@ declare namespace YamlPreCompiler {
4727
4729
  private readonly usedContainerNames;
4728
4730
  private fileDiagnostics;
4729
4731
  private readonly libraryDDE;
4732
+ private libraryYaml;
4730
4733
  constructor(manifest: Manifest.Manifest, libraryFiles: DDE_Core.LibraryFile[], ddeHistory: DDE.HistoryJson | null);
4731
4734
  /**
4732
4735
  * Parse the given library files and return the diagnostics
@@ -4747,8 +4750,9 @@ declare namespace YamlPreCompiler {
4747
4750
  * @return An object containing the parsed DDE JSON and an array of diagnostic messages related to the file.
4748
4751
  */
4749
4752
  parseYamlFile(filePath: URI, yaml: string, libraryName?: string): {
4750
- parsedDDE: DDEJson;
4753
+ parsedDDE: DDE_Core.DDEJson;
4751
4754
  diagnostics: Diagnostics.File[];
4755
+ parsedYaml: null | Document_2.Parsed<ParsedNode, true>;
4752
4756
  };
4753
4757
  private yamlDocToDdeJson;
4754
4758
  private getRealContainerInformation;
@@ -173,8 +173,8 @@ var DDE_Core;
173
173
  ContainerName.config9
174
174
  ];
175
175
  DDE_Core.SERVER_CONTAINER = [ContainerName.configA, ContainerName.configB, ContainerName.configC];
176
- // relation checkings.
177
- DDE_Core.regexRelation = /^@[a-zA-Z0-9_].[a-zA-Z0-9[\]{}._+-]+(?<!\.)$/;
176
+ // check if the given string is a relation to an app container or library container
177
+ DDE_Core.regexRelation = /^(@[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*(\[[^\]]+\])?(\.[a-zA-Z_][a-zA-Z0-9_]*)*|lib:[a-zA-Z0-9_-]+@[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*(\[[^\]]+\])?(\.[a-zA-Z_][a-zA-Z0-9_]*)*)$/;
178
178
  const STRING_TYPES = ['astring', 'nstring', 'cstring', 'wstring', 'ustring'];
179
179
  const NUMBER_TYPES = [
180
180
  'int8',
@@ -225,7 +225,7 @@ var DDE_Core;
225
225
  if (DDE_Core.regexRelation.exec(`${currentAttributeValue}`)) {
226
226
  const isSetPoint = attribute === 'chartSetPoint';
227
227
  const [root, ...containerFields] = currentAttributeValue.split('.');
228
- const containerTitle = root.substring(1);
228
+ const [, /*libraryRelation*/ containerTitle] = root.split('@'); //remove the @
229
229
  const realContainer = Object.values(ddeMap.containers).find(container => container.title === containerTitle);
230
230
  const containerField = containerFields.join('.');
231
231
  const delimeter = isSetPoint ? ';' : '%';
package/out/dde/dde.js CHANGED
@@ -148,8 +148,8 @@ var DDE;
148
148
  * Generate the needed xml for the myDatanet application
149
149
  * @param ddeJSON
150
150
  */
151
- function generateMyDatanetXML(ddeJSON) {
152
- return (0, xml_1.generateXMLFromMap)(ddeJSON);
151
+ function generateMyDatanetXML(manifest, ddeJSON) {
152
+ return (0, xml_1.generateXMLFromMap)(manifest, ddeJSON);
153
153
  }
154
154
  DDE.generateMyDatanetXML = generateMyDatanetXML;
155
155
  /**
@@ -159,7 +159,8 @@ var DDE;
159
159
  * @param ddeJSON
160
160
  */
161
161
  async function exportMyDatanetXML(cwd, fs, logger, ddeJSON) {
162
- const xml = (0, xml_1.generateXMLFromMap)(ddeJSON);
162
+ const manifest = await manifest_1.Manifest.read(cwd, fs);
163
+ const xml = (0, xml_1.generateXMLFromMap)(manifest, ddeJSON);
163
164
  const distFile = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.dist.ddeXmlPath);
164
165
  await fs.writeFile(distFile, xml);
165
166
  logger.log('Generated', defaultFiles_1.DefaultFiles.filePaths.dist.ddeXmlPath);
@@ -805,14 +805,14 @@
805
805
  "relationLinkPattern": {
806
806
  "anyOf": [
807
807
  {
808
- "pattern": "^@([a-zA-Z0-9_]).[a-zA-Z0-9\\[\\]{}._+]+(?<!\\.)$"
808
+ "pattern": "^(@[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*(\\[[^\\]]+\\])?(\\.[a-zA-Z_][a-zA-Z0-9_]*)*|lib:[a-zA-Z0-9_-]+@[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*(\\[[^\\]]+\\])?(\\.[a-zA-Z_][a-zA-Z0-9_]*)*)$"
809
809
  }
810
810
  ]
811
811
  },
812
812
  "setPointRelationPattern": {
813
813
  "anyOf": [
814
814
  {
815
- "pattern": "^@([a-zA-Z0-9_]).[a-zA-Z0-9\\[\\]{}._]+(?<!\\.)$"
815
+ "pattern": "^(@[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*(\\[[^\\]]+\\])?(\\.[a-zA-Z_][a-zA-Z0-9_]*)*|lib:[a-zA-Z0-9_-]+@[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*(\\[[^\\]]+\\])?(\\.[a-zA-Z_][a-zA-Z0-9_]*)*)$"
816
816
  },
817
817
  {
818
818
  "const": "\"@setting.\"",
@@ -8,8 +8,9 @@ var parseXMLBitmask = coreDefinitions_1.DDE_Core.parseXMLBitmask;
8
8
  var parseXMLDefaultValue = coreDefinitions_1.DDE_Core.parseXMLDefaultValue;
9
9
  var fieldTypeDefinitions = coreDefinitions_1.DDE_Core.fieldTypeDefinitions;
10
10
  const helper_1 = require("../../helper");
11
+ const manifest_1 = require("../../manifest");
11
12
  // eslint-disable-next-line sonarjs/cognitive-complexity
12
- function generateXMLFromMap(ddeMap) {
13
+ function generateXMLFromMap(manifest, ddeMap) {
13
14
  const indent = '';
14
15
  const xml_ = [];
15
16
  function xml(s, condition = true) {
@@ -67,8 +68,8 @@ function generateXMLFromMap(ddeMap) {
67
68
  xmlAttr('download', '0');
68
69
  }
69
70
  // set edit=99 on upward containers to reject write access via API
70
- if ([TransferDirection.up, TransferDirection.upPlus].includes(containerDefinition.transferDirection)) {
71
- // containerAttributes['edit'] = '99';
71
+ if ((manifest_1.Manifest.isApp(manifest) || manifest_1.Manifest.isLibrary(manifest)) &&
72
+ [TransferDirection.up, TransferDirection.upPlus].includes(containerDefinition.transferDirection)) {
72
73
  xmlAttr('edit', '99');
73
74
  }
74
75
  //insert fields:
@@ -29,6 +29,7 @@ var YamlPreCompiler;
29
29
  usedContainerNames = {};
30
30
  fileDiagnostics = [];
31
31
  libraryDDE = [];
32
+ libraryYaml = {};
32
33
  constructor(manifest, libraryFiles, ddeHistory) {
33
34
  this.manifest = manifest;
34
35
  this.libraryFiles = libraryFiles;
@@ -41,9 +42,10 @@ var YamlPreCompiler;
41
42
  this.libraryDDE.length = 0;
42
43
  const libDiagnostics = [];
43
44
  this.libraryFiles.forEach(file => {
44
- const { parsedDDE, diagnostics } = this.parseYamlFile(file.path, file.yaml, file.libraryName);
45
+ const { parsedDDE, diagnostics, parsedYaml } = this.parseYamlFile(file.path, file.yaml, file.libraryName);
45
46
  libDiagnostics.push(...diagnostics);
46
47
  this.libraryDDE.push(parsedDDE);
48
+ this.libraryYaml[file.libraryName] = parsedYaml;
47
49
  });
48
50
  return libDiagnostics;
49
51
  }
@@ -84,7 +86,8 @@ var YamlPreCompiler;
84
86
  containers: {},
85
87
  setPointList: {}
86
88
  },
87
- diagnostics: []
89
+ diagnostics: [],
90
+ parsedYaml: null
88
91
  };
89
92
  }
90
93
  const docContent = yamlDoc.contents || new yaml_1.YAMLMap();
@@ -96,7 +99,8 @@ var YamlPreCompiler;
96
99
  // mapAsMap is used to keep order of fields:
97
100
  return {
98
101
  parsedDDE: this.yamlDocToDdeJson(yamlDoc.toJS({ mapAsMap: true }), libraryName),
99
- diagnostics: [...this.fileDiagnostics]
102
+ diagnostics: [...this.fileDiagnostics],
103
+ parsedYaml: yamlDoc
100
104
  };
101
105
  }
102
106
  // eslint-disable-next-line sonarjs/cognitive-complexity
@@ -286,6 +290,13 @@ var YamlPreCompiler;
286
290
  [DDEContainerName.relations, DDEContainerName.storage].includes(ddeContainerName)) {
287
291
  containerList = SERVER_CONTAINER;
288
292
  }
293
+ const previousContainerList = this.previousVersion?.containers;
294
+ // filter out all containers that are already used
295
+ if (previousContainerList) {
296
+ containerList = containerList.filter(containerName => {
297
+ return !Object.hasOwn(previousContainerList, containerName);
298
+ });
299
+ }
289
300
  return containerList.find(containerName => {
290
301
  return !Object.hasOwn(this.usedContainerNames, containerName);
291
302
  });
@@ -594,8 +605,10 @@ var YamlPreCompiler;
594
605
  validateContainerRelation(itemType, itemValue, yamlDoc, sourceUri, lineCounter) {
595
606
  //validate if the relation exist
596
607
  const [root, fieldRef, arrayField] = itemValue.value.split('.', 3);
597
- const containerName = root.substring(1); //remove the @
598
- const containerExist = yamlDoc.contents?.get(containerName);
608
+ const [libraryRelation, containerName] = root.split('@');
609
+ const libraryName = libraryRelation ? libraryRelation.split(':')[1] : null;
610
+ const yamlContentToSearch = libraryName && this.libraryYaml[libraryName] ? this.libraryYaml[libraryName] : yamlDoc;
611
+ const containerExist = yamlContentToSearch.contents?.get(containerName);
599
612
  const referencedField = fieldRef.split('[')[0];
600
613
  let relatedField = null;
601
614
  if (containerExist) {
@@ -631,6 +644,14 @@ var YamlPreCompiler;
631
644
  });
632
645
  }
633
646
  }
647
+ else if (libraryName && !this.libraryYaml[libraryName]) {
648
+ this.fileDiagnostics.push({
649
+ file: sourceUri,
650
+ level: 'error',
651
+ message: `Related library "${libraryName}" does not exist.`,
652
+ ...yamlRangeToLineInformation(lineCounter, itemValue.range)
653
+ });
654
+ }
634
655
  else {
635
656
  this.fileDiagnostics.push({
636
657
  file: sourceUri,
package/out/manifest.js CHANGED
@@ -155,6 +155,9 @@ var Manifest;
155
155
  * @param manifest
156
156
  */
157
157
  function isApp(manifest) {
158
+ if (manifest.type === undefined && !isLibrary(manifest)) {
159
+ return true;
160
+ }
158
161
  return manifest.type === ProjectTypes.app;
159
162
  }
160
163
  Manifest.isApp = isApp;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microtronics/studio-cli",
3
- "version": "0.36.0",
3
+ "version": "0.38.0",
4
4
  "description": "Microtronics Studio CLI Tool",
5
5
  "main": "./out/api.js",
6
6
  "typings": "./dist/studio-cli.d.ts",