@microtronics/studio-cli 0.40.0 → 0.42.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 +20 -1
- package/dist/studio-cli.d.ts +6 -0
- package/out/api.js +7 -11
- package/out/dde/fileGenerators/api.js +43 -4
- package/out/dde/fileGenerators/xml.js +2 -1
- package/out/manifest.js +33 -0
- package/out/package/apm.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.42.0 (2026-01-13)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
|
|
7
|
+
* add isIotApp helper function to check IoT app project type ([98ce8a1](https://bitbucket.org/microtronics-core/vscode-studio/commits/98ce8a1358bdd4d2ba1635cd4ef1a3f6e8ec0004))
|
|
8
|
+
* add POST endpoint for addon timeseries data insertion ([ace6880](https://bitbucket.org/microtronics-core/vscode-studio/commits/ace6880f801faefc303a8020c7acf87b06db5709))
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* restrict write access rejection to IoT apps only ([13aa98f](https://bitbucket.org/microtronics-core/vscode-studio/commits/13aa98f261632b576681a894ecb375b7ab5a4b99))
|
|
13
|
+
|
|
14
|
+
## 0.41.0 (2026-01-12)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* add validation for maxInstancesPerSite manifest property ([065dc98](https://bitbucket.org/microtronics-core/vscode-studio/commits/065dc9809e8dccb75b74c5b52a58ce4ec15b5860))
|
|
19
|
+
* use manifest maxInstancesPerSite for addon package header ([0350d2a](https://bitbucket.org/microtronics-core/vscode-studio/commits/0350d2af8ee3aae0ddbb00d7af5cd0b1c2c4cdd5))
|
|
20
|
+
* validate manifest before building package ([e70fc0e](https://bitbucket.org/microtronics-core/vscode-studio/commits/e70fc0ef9c89849ce2c19ec0a9bb575a764a3b07))
|
|
21
|
+
|
|
22
|
+
## 0.40.0 (2025-11-11)
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
7
26
|
* add lowercase property mapping for timeseries containers ([24f575e](https://bitbucket.org/microtronics-core/vscode-studio/commits/24f575efa418417c5fd612e55bd17f5fb80972cf))
|
|
8
27
|
|
|
9
28
|
## 0.39.0 (2025-11-10)
|
package/dist/studio-cli.d.ts
CHANGED
|
@@ -2183,6 +2183,7 @@ export declare namespace Manifest {
|
|
|
2183
2183
|
description: string;
|
|
2184
2184
|
type: ProjectTypes;
|
|
2185
2185
|
legacyProject?: boolean;
|
|
2186
|
+
maxInstancesPerSite?: number;
|
|
2186
2187
|
icon?: string;
|
|
2187
2188
|
dpid?: DeviceProfiles;
|
|
2188
2189
|
engines?: {
|
|
@@ -2273,6 +2274,11 @@ export declare namespace Manifest {
|
|
|
2273
2274
|
* @param manifest
|
|
2274
2275
|
*/
|
|
2275
2276
|
export function isApp(manifest: Manifest.Manifest): boolean;
|
|
2277
|
+
/**
|
|
2278
|
+
* Check if the current project is an iot app project
|
|
2279
|
+
* @param manifest
|
|
2280
|
+
*/
|
|
2281
|
+
export function isIotApp(manifest: Manifest.Manifest): boolean;
|
|
2276
2282
|
/**
|
|
2277
2283
|
* Check if the current project is an analytics project
|
|
2278
2284
|
* @param manifest
|
package/out/api.js
CHANGED
|
@@ -50,19 +50,14 @@ Object.defineProperty(exports, "Log", { enumerable: true, get: function () { ret
|
|
|
50
50
|
* @return {Promise<void>} A promise that resolves when the installation process completes successfully or logs an error if it fails.
|
|
51
51
|
*/
|
|
52
52
|
async function install(cwd, fs, env, apiToken, dependencies) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
await dependencies_1.Dependencies.installDependency(cwd, fs, env, apiToken, libraryId, version || null);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
return await dependencies_1.Dependencies.installDependencies(cwd, fs, env, apiToken);
|
|
53
|
+
if (dependencies.length > 0) {
|
|
54
|
+
for (const dependency of dependencies) {
|
|
55
|
+
const [libraryId, version] = dependency.split('@');
|
|
56
|
+
await dependencies_1.Dependencies.installDependency(cwd, fs, env, apiToken, libraryId, version || null);
|
|
62
57
|
}
|
|
63
58
|
}
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
else {
|
|
60
|
+
return await dependencies_1.Dependencies.installDependencies(cwd, fs, env, apiToken);
|
|
66
61
|
}
|
|
67
62
|
}
|
|
68
63
|
/**
|
|
@@ -78,6 +73,7 @@ async function install(cwd, fs, env, apiToken, dependencies) {
|
|
|
78
73
|
* @return {Promise<Object>} A promise resolved with an object containing diagnostics information for the specified project parts: `dde`, `dlo`, and `dfiles`.
|
|
79
74
|
*/
|
|
80
75
|
async function build(cwd, fs, logger, env, apiToken = null, selectedParts = true, errorWithDiagnostics) {
|
|
76
|
+
await manifest_1.Manifest.validateBasicManifest(cwd, fs, null);
|
|
81
77
|
return package_1.Package.buildAll(cwd, fs, logger, env, apiToken, selectedParts, errorWithDiagnostics);
|
|
82
78
|
}
|
|
83
79
|
/**
|
|
@@ -495,7 +495,7 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
|
|
|
495
495
|
apiPathOptions = [
|
|
496
496
|
{
|
|
497
497
|
path: `/api/1/sites/{siteUid}/addons/{addonUid}/${containerType}/${containerDefinition.title}`,
|
|
498
|
-
params: [addonIdRef],
|
|
498
|
+
params: [contextIdRef, addonIdRef],
|
|
499
499
|
tags: [containerRouteTagName]
|
|
500
500
|
}
|
|
501
501
|
];
|
|
@@ -511,7 +511,8 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
|
|
|
511
511
|
apiPathOptions.push(appCenterPathOptions);
|
|
512
512
|
const apiPathMethods = {
|
|
513
513
|
get: undefined,
|
|
514
|
-
put: undefined
|
|
514
|
+
put: undefined,
|
|
515
|
+
post: undefined
|
|
515
516
|
};
|
|
516
517
|
const getMethod = {
|
|
517
518
|
tags: [],
|
|
@@ -610,6 +611,41 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
|
|
|
610
611
|
...defaultResponseCodes
|
|
611
612
|
}
|
|
612
613
|
};
|
|
614
|
+
if (isAddonProject) {
|
|
615
|
+
apiPathMethods.post = {
|
|
616
|
+
tags: [],
|
|
617
|
+
summary: `Insert data into the "${tagNameFromContainerTitle(containerDefinition.title)}" container`,
|
|
618
|
+
parameters: [
|
|
619
|
+
{
|
|
620
|
+
name: 'allow_future_date',
|
|
621
|
+
in: 'query',
|
|
622
|
+
description: 'Allow inserting records with a stamp value in the future',
|
|
623
|
+
schema: {
|
|
624
|
+
type: 'boolean'
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
],
|
|
628
|
+
requestBody: {
|
|
629
|
+
content: {
|
|
630
|
+
'application/json': {
|
|
631
|
+
schema: {
|
|
632
|
+
$ref: `#/components/schemas/${containerDefinition.title}`
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
responses: {
|
|
638
|
+
201: {
|
|
639
|
+
...successfulOperationResponse
|
|
640
|
+
},
|
|
641
|
+
400: {
|
|
642
|
+
description: 'Bad request',
|
|
643
|
+
...defaultErrorResponse
|
|
644
|
+
},
|
|
645
|
+
...defaultResponseCodes
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
}
|
|
613
649
|
// only site and addons support timeseries
|
|
614
650
|
const pathOptions = apiPathOptions[0];
|
|
615
651
|
const methods = structuredClone(apiPathMethods);
|
|
@@ -634,7 +670,9 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
|
|
|
634
670
|
};
|
|
635
671
|
youngestMethod.get.summary = `Get the youngest record of "${containerDefinition.title}" container`;
|
|
636
672
|
youngestMethod.get.responses['200'] = histdataSingleResponse;
|
|
637
|
-
|
|
673
|
+
const parameterIdx = isAddonProject ? 2 : 1;
|
|
674
|
+
youngestMethod.get.parameters[parameterIdx].schema.$ref =
|
|
675
|
+
`#/components/schemas/${containerDefinition.title}RequestSingle`;
|
|
638
676
|
apiDescription.paths[youngestPath] = youngestMethod;
|
|
639
677
|
const oldestPath = `${pathOptions.path}/oldest`;
|
|
640
678
|
const oldestMethod = {
|
|
@@ -642,7 +680,8 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
|
|
|
642
680
|
};
|
|
643
681
|
oldestMethod.get.summary = `Get the oldest record of "${containerDefinition.title}" container`;
|
|
644
682
|
oldestMethod.get.responses['200'] = histdataSingleResponse;
|
|
645
|
-
oldestMethod.get.parameters[
|
|
683
|
+
oldestMethod.get.parameters[parameterIdx].schema.$ref =
|
|
684
|
+
`#/components/schemas/${containerDefinition.title}RequestSingle`;
|
|
646
685
|
apiDescription.paths[oldestPath] = oldestMethod;
|
|
647
686
|
}
|
|
648
687
|
}
|
|
@@ -68,7 +68,8 @@ function generateXMLFromMap(manifest, ddeMap) {
|
|
|
68
68
|
xmlAttr('download', '0');
|
|
69
69
|
}
|
|
70
70
|
// set edit=99 on upward containers to reject write access via API
|
|
71
|
-
|
|
71
|
+
// only for IoT apps and libraries. For addons or analytics this is not needed.
|
|
72
|
+
if ((manifest_1.Manifest.isIotApp(manifest) || manifest_1.Manifest.isLibrary(manifest)) &&
|
|
72
73
|
[TransferDirection.up, TransferDirection.upPlus].includes(containerDefinition.transferDirection)) {
|
|
73
74
|
xmlAttr('edit', '99');
|
|
74
75
|
}
|
package/out/manifest.js
CHANGED
|
@@ -161,6 +161,17 @@ var Manifest;
|
|
|
161
161
|
return manifest.type === ProjectTypes.app;
|
|
162
162
|
}
|
|
163
163
|
Manifest.isApp = isApp;
|
|
164
|
+
/**
|
|
165
|
+
* Check if the current project is an iot app project
|
|
166
|
+
* @param manifest
|
|
167
|
+
*/
|
|
168
|
+
function isIotApp(manifest) {
|
|
169
|
+
if (manifest.type === undefined) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return manifest.type === ProjectTypes.app;
|
|
173
|
+
}
|
|
174
|
+
Manifest.isIotApp = isIotApp;
|
|
164
175
|
/**
|
|
165
176
|
* Check if the current project is an analytics project
|
|
166
177
|
* @param manifest
|
|
@@ -183,6 +194,7 @@ var Manifest;
|
|
|
183
194
|
validateProjectVersion(manifest);
|
|
184
195
|
validatePOVSettings(manifest);
|
|
185
196
|
validateBLOSettings(manifest);
|
|
197
|
+
validateMaxInstancesPerSite(manifest);
|
|
186
198
|
}
|
|
187
199
|
Manifest.validateBasicManifest = validateBasicManifest;
|
|
188
200
|
function validateLibraryName(libraryName) {
|
|
@@ -433,6 +445,27 @@ function validateAddonOrAnalyticsSupported(manifest) {
|
|
|
433
445
|
throw new Error(`For project type "${manifest.type}", "dpid" is not supported!"`);
|
|
434
446
|
}
|
|
435
447
|
}
|
|
448
|
+
function validateMaxInstancesPerSite(manifest) {
|
|
449
|
+
const { maxInstancesPerSite } = manifest;
|
|
450
|
+
// If maxInstancesPerSite is not defined, check if it's required
|
|
451
|
+
if (maxInstancesPerSite === undefined) {
|
|
452
|
+
if (Manifest.isAddon(manifest)) {
|
|
453
|
+
throw new Error('Property "maxInstancesPerSite" is required for addon projects!');
|
|
454
|
+
}
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
// If maxInstancesPerSite is defined, validate it's only allowed for addon projects
|
|
458
|
+
if (!Manifest.isAddon(manifest)) {
|
|
459
|
+
throw new Error(`Property "maxInstancesPerSite" is only allowed for addon projects!`);
|
|
460
|
+
}
|
|
461
|
+
// Validate the value
|
|
462
|
+
if (!Number.isInteger(maxInstancesPerSite)) {
|
|
463
|
+
throw new Error('Property "maxInstancesPerSite" must be an integer!');
|
|
464
|
+
}
|
|
465
|
+
if (maxInstancesPerSite < 1 || maxInstancesPerSite > 100) {
|
|
466
|
+
throw new Error('Property "maxInstancesPerSite" must be between 1 and 100!');
|
|
467
|
+
}
|
|
468
|
+
}
|
|
436
469
|
/**
|
|
437
470
|
* Check based on the current env if the given version string is correct
|
|
438
471
|
* @param manifest
|
package/out/package/apm.js
CHANGED
|
@@ -54,7 +54,7 @@ var APM;
|
|
|
54
54
|
tagHeader.required_hwfw = undefined;
|
|
55
55
|
tagHeader.required_productcode = undefined;
|
|
56
56
|
tagHeader.addon_max_sources = 1;
|
|
57
|
-
tagHeader.addon_max_per_site =
|
|
57
|
+
tagHeader.addon_max_per_site = manifest.maxInstancesPerSite;
|
|
58
58
|
}
|
|
59
59
|
return tagHeader;
|
|
60
60
|
}
|