@microtronics/studio-cli 0.17.0 → 0.19.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,4 +1,31 @@
1
-
1
+ # Changelog
2
+
3
+ ## 0.19.0 (2025-02-19)
4
+
5
+ * test(studio-cli): tag header should not have property type ([5082db8](https://bitbucket.org/microtronics-core/vscode-studio/commits/5082db8))
6
+ * test(studio-cli): test if type addon can only used from specific version onwards ([213bc7c](https://bitbucket.org/microtronics-core/vscode-studio/commits/213bc7c))
7
+ * test(studio-cli): validate apm tag header creation ([e74acc8](https://bitbucket.org/microtronics-core/vscode-studio/commits/e74acc8))
8
+ * test(studio-cli): validate openapi generation for addons ([08176bc](https://bitbucket.org/microtronics-core/vscode-studio/commits/08176bc))
9
+ * feat(studio-cli): added function to validate if app id is an uuid ([60bda6f](https://bitbucket.org/microtronics-core/vscode-studio/commits/60bda6f))
10
+ * feat(studio-cli): allow creating an apm tag for addons ([a7d32c4](https://bitbucket.org/microtronics-core/vscode-studio/commits/a7d32c4))
11
+ * feat(studio-cli): generate api routes for addons ([a075407](https://bitbucket.org/microtronics-core/vscode-studio/commits/a075407))
12
+ * feat(studio-cli): improved manifest validation if type is addon ([c3ae0c9](https://bitbucket.org/microtronics-core/vscode-studio/commits/c3ae0c9))
13
+ * feat(studio-cli): only allow project type addon for a specific backend version ([46f0f28](https://bitbucket.org/microtronics-core/vscode-studio/commits/46f0f28))
14
+ * feat(studio-cli): support for new app type `apm` ([8041db3](https://bitbucket.org/microtronics-core/vscode-studio/commits/8041db3))
15
+ * chore(studio-cli): add run file for local addon development ([465a1f0](https://bitbucket.org/microtronics-core/vscode-studio/commits/465a1f0))
16
+ * chore(studio-cli): disable dlo per default if project type is addon ([a7f98af](https://bitbucket.org/microtronics-core/vscode-studio/commits/a7f98af))
17
+ * chore(studio-cli): dissallow setting hw/fw & productId if project type is addon ([74c90c3](https://bitbucket.org/microtronics-core/vscode-studio/commits/74c90c3))
18
+ * chore(studio-cli): improve type to allow `Manifest.ProjectTypes` ([fe6535f](https://bitbucket.org/microtronics-core/vscode-studio/commits/fe6535f))
19
+ * chore(studio-cli): validate for device profile id if dlo is enabled ([908fc9a](https://bitbucket.org/microtronics-core/vscode-studio/commits/908fc9a))
20
+ * revert(studio-cli): remove type property from tagheader object ([65f90ad](https://bitbucket.org/microtronics-core/vscode-studio/commits/65f90ad))
21
+ * refactor(studio-cli): added function to create the `baseTagHeader` ([ac9f83f](https://bitbucket.org/microtronics-core/vscode-studio/commits/ac9f83f))
22
+
23
+ ## 0.18.0 (2025-02-13)
24
+
25
+
26
+ ### Features
27
+
28
+ * **studio-cli:** support for new qualification stages ([7511873](https://bitbucket.org/microtronics-core/vscode-studio/commits/7511873eab82fa4e1fb4be3c1b998b1a3576f5f9))
2
29
 
3
30
  ## 0.17.0 (2025-02-13)
4
31
 
@@ -5,6 +5,9 @@ import { URI } from 'vscode-uri';
5
5
 
6
6
  export declare namespace APM {
7
7
  export enum TagPhase {
8
+ alpha = "alpha",
9
+ beta = "beta",
10
+ rc = "rc",
8
11
  release = "release",
9
12
  stage = "stage",
10
13
  passive = "passive",
@@ -20,37 +23,14 @@ export declare namespace APM {
20
23
  blo = "blo",
21
24
  dfiles = "dfiles"
22
25
  }
23
- export interface TagHeader extends ApplicationTagInformation {
24
- author: string;
25
- version: string;
26
- blo_level?: Manifest.BloAccessLevel;
27
- required_be?: string;
28
- required_hwfw?: string;
29
- required_productcode?: string;
26
+ export interface TagHeader extends BaseTagHeader {
27
+ phase: TagPhase;
28
+ version: string | number;
30
29
  }
31
- export interface DevTagHeader {
32
- name: string;
33
- abstract: string;
34
- author: string;
35
- pip_id: string;
36
- pov_location: Manifest.PovLocation;
37
- pov_details_lowlevel: boolean;
38
- blo_level: Manifest.BloAccessLevel;
30
+ export interface DevTagHeader extends BaseTagHeader {
39
31
  blo_autostart: boolean;
40
- /**
41
- * ONE specific
42
- * the version 0 for ONE
43
- */
44
- version?: number;
45
- /**
46
- * ONE specific
47
- * owner_id is the organizationID
48
- */
49
- owner_id?: string;
50
- required_be?: string;
51
- required_hwfw?: string;
52
- required_productcode?: string;
53
32
  }
33
+ export function createBaseTagHeader(manifest: Manifest.Manifest): BaseTagHeader;
54
34
  /**
55
35
  * Create new release tag
56
36
  * @param cwd
@@ -114,7 +94,26 @@ export declare namespace APM {
114
94
  }>;
115
95
  }
116
96
 
117
- declare type ApplicationTagInformation = components['schemas']['ApplicationTagInformation'];
97
+ declare interface BaseTagHeader {
98
+ name: string;
99
+ abstract: string;
100
+ author: string;
101
+ blo_level?: Manifest.BloAccessLevel;
102
+ required_be?: string;
103
+ required_hwfw?: string;
104
+ required_productcode?: string;
105
+ pov_location: Manifest.PovLocation;
106
+ pov_details_lowlevel: boolean;
107
+ pip_id: '';
108
+ /**
109
+ * exists only when app type is addon
110
+ */
111
+ addon_max_per_site?: number;
112
+ /**
113
+ * exists only when app type is addon
114
+ */
115
+ addon_max_sources?: number;
116
+ }
118
117
 
119
118
  declare interface components {
120
119
  schemas: {
@@ -170,6 +169,7 @@ declare interface components {
170
169
  NewApplication: {
171
170
  /** @description The project name */
172
171
  name: string;
172
+ type?: components["schemas"]["ApplicationType"];
173
173
  /** @description Short description what this library does */
174
174
  description: string;
175
175
  targetSystem: components["schemas"]["TargetSystem"];
@@ -177,7 +177,11 @@ declare interface components {
177
177
  organizationId?: string;
178
178
  /** @description Defines which servers are allowed to see this application. If null, the application wont be shared with anyone */
179
179
  allowedBackends?: ("*" | string[]) | null;
180
+ /** @description Sites with the given APM ID are allowed to be defined as addon parent. This property is only available if the project type is 'addon' */
181
+ allowedApplications?: ("*" | string[]) | null;
180
182
  };
183
+ /** @enum {string} */
184
+ ApplicationType: "app" | "addon";
181
185
  ApplicationInformationBase: {
182
186
  version: components["parameters"]["ApplicationVersion"];
183
187
  publisherId: components["parameters"]["PublisherId"];
@@ -231,7 +235,7 @@ declare interface components {
231
235
  * @description The released phase
232
236
  * @enum {string}
233
237
  */
234
- ReleasePhases: "passive" | "stage" | "release" | "withdrawn";
238
+ ReleasePhases: "passive" | "alpha" | "beta" | "stage" | "rc" | "release" | "withdrawn";
235
239
  NewPublisher: {
236
240
  /** @description Unique id of the publisher. Can not be changed afterwards. Can only contain 'A' through 'Z', 'a' through 'z', '0' through '9' and '-'. The publisher ID must start with an alphabetic or numeric character. */
237
241
  id: string;
@@ -2042,13 +2046,21 @@ export declare namespace Manifest {
2042
2046
  * The source filename where the information is stored in
2043
2047
  */
2044
2048
  const fileName = "studio.json";
2045
- export type DeviceProfiles = 'm22x' | 'm23x' | 'nrf91' | 'm2blegw' | 'm2easyv3' | 'm2easyiot';
2049
+ export enum DeviceProfiles {
2050
+ m22x = "m22x",
2051
+ m23x = "m23x",
2052
+ nrf91 = "nrf91",
2053
+ m2blegw = "m2blegw",
2054
+ m2easyv3 = "m2easyv3",
2055
+ m2easyiot = "m2easyiot"
2056
+ }
2046
2057
  /**
2047
2058
  * Type of the iot app project
2048
2059
  */
2049
2060
  export enum ProjectTypes {
2050
2061
  app = "app",
2051
- library = "library"
2062
+ library = "library",
2063
+ addon = "addon"
2052
2064
  }
2053
2065
  export interface Manifest {
2054
2066
  version: string;
@@ -2115,7 +2127,7 @@ export declare namespace Manifest {
2115
2127
  */
2116
2128
  export function read(cwd: URI, fs: LocalFS): Promise<Manifest>;
2117
2129
  /**
2118
- * Reads the studio.json as an uint8array
2130
+ * Reads the studio.json as an Uint8Array
2119
2131
  * @param cwd
2120
2132
  * @param fs
2121
2133
  */
@@ -2131,6 +2143,16 @@ export declare namespace Manifest {
2131
2143
  * Check if the current project is a library project
2132
2144
  */
2133
2145
  export function isLibrary(manifest: Manifest.Manifest): boolean;
2146
+ /**
2147
+ * Check if the current project is an addon project
2148
+ * @param manifest
2149
+ */
2150
+ export function isAddon(manifest: Manifest.Manifest): boolean;
2151
+ /**
2152
+ * Check if the current project is an app project
2153
+ * @param manifest
2154
+ */
2155
+ export function isApp(manifest: Manifest.Manifest): boolean;
2134
2156
  /**
2135
2157
  * Validates if the properties within
2136
2158
  * @param cwd
@@ -2145,6 +2167,7 @@ export declare namespace Manifest {
2145
2167
  export function validatePublisherId(publisher: string): "No publisher set yet" | "Publisher can only contain 'A' through 'Z', 'a' through 'z', '0' through '9' and '-'. The Publisher start with an alphabetic or numeric character." | null;
2146
2168
  export function validatePublisherOnline(token: Registry.AuthToken, publisher: string): Promise<string | null>;
2147
2169
  export function validateRegistryAllowedBackends(allowedBackends: undefined | null | string | string[]): Promise<string | null>;
2170
+ export function validateRegistryAllowedApplications(allowedApplications: undefined | null | string | string[]): Promise<string | null>;
2148
2171
  export function validateApplicationIcon(cwd: URI, fs: LocalFS, manifest: Manifest.Manifest): Promise<void>;
2149
2172
  export function validateEngineSettings(manifest: Manifest.Manifest): void;
2150
2173
  /**
@@ -4286,7 +4309,9 @@ export declare namespace Registry {
4286
4309
  export function fetchCustomContent(token: AuthToken, contentURL: string, json?: boolean, env?: Globals.ENV): Promise<ArrayBuffer | any>;
4287
4310
  export type Publisher = components['schemas']['Publisher'];
4288
4311
  export function getPublisher(token: AuthToken, publisherId: string): Promise<Publisher | null>;
4289
- export type ApiNewApplication = components['schemas']['NewApplication'];
4312
+ export type ApiNewApplication = components['schemas']['NewApplication'] & {
4313
+ type?: string | Manifest.ProjectTypes;
4314
+ };
4290
4315
  export function createNewApplication(token: AuthToken, publisherId: string, newApplication: ApiNewApplication, env?: Globals.ENV): Promise<string | null | undefined>;
4291
4316
  export type ApplicationDetailInformation = components['schemas']['ApplicationDetailInformation'];
4292
4317
  export function getExistingApplication(token: AuthToken, publisherId: string, applicationId: string, env?: Globals.ENV): Promise<ApplicationDetailInformation>;
@@ -30,7 +30,9 @@ const coreDefinitions_1 = require("../coreDefinitions");
30
30
  var ContainerType = coreDefinitions_1.DDE_Core.ContainerType;
31
31
  var TransferDirection = coreDefinitions_1.DDE_Core.TransferDirection;
32
32
  var fieldTypeDefinitions = coreDefinitions_1.DDE_Core.fieldTypeDefinitions;
33
+ const manifest_1 = require("../../manifest");
33
34
  const contextIdRef = { $ref: '#/components/parameters/contextId' };
35
+ const addonIdRef = { $ref: '#/components/parameters/addonId' };
34
36
  const histdataResponseRef = { $ref: '#/components/schemas/histdataResponse' };
35
37
  const histdataRequestRef = { $ref: '#/components/schemas/histdataRequest' };
36
38
  const rapidM2MStampRef = { $ref: '#/components/schemas/rapidM2MStamp' };
@@ -179,6 +181,19 @@ function generateAPIFromMap(ddeMap, manifest, context = null) {
179
181
  else {
180
182
  Object.assign(apiDescription.components, structuredClone(defaultAppComponents));
181
183
  }
184
+ const isAddon = manifest_1.Manifest.isAddon(manifest);
185
+ if (isAddon) {
186
+ // add addonUid parameter if this is an addon project
187
+ apiDescription.components.parameters['addonId'] = {
188
+ name: 'addonUid',
189
+ in: 'path',
190
+ description: 'The addon uid',
191
+ schema: {
192
+ type: 'string'
193
+ },
194
+ required: true
195
+ };
196
+ }
182
197
  for (const containerDefinition of Object.values(ddeMap.containers)) {
183
198
  if ((context &&
184
199
  (!containerDefinition.libraries.includes(context) || containerDefinition.containerType === ContainerType.hx)) ||
@@ -188,10 +203,12 @@ function generateAPIFromMap(ddeMap, manifest, context = null) {
188
203
  }
189
204
  generateTagDescriptionFromContainer(apiDescription, containerDefinition);
190
205
  generateSchemasFromContainer(apiDescription, containerDefinition, context);
191
- generatePathInformationFromContainer(apiDescription, containerDefinition);
206
+ generatePathInformationFromContainer(apiDescription, containerDefinition, isAddon);
192
207
  // legacy routes
193
- generateLegacySchemasFromContainer(apiDescription, containerDefinition, context);
194
- generateLegacyPathInformationFromContainer(apiDescription, containerDefinition);
208
+ if (!isAddon) {
209
+ generateLegacySchemasFromContainer(apiDescription, containerDefinition, context);
210
+ generateLegacyPathInformationFromContainer(apiDescription, containerDefinition);
211
+ }
195
212
  }
196
213
  return (0, yaml_1.stringify)(apiDescription);
197
214
  }
@@ -434,10 +451,15 @@ function generateLegacyPathInformationFromContainer(apiDescription, containerDef
434
451
  }
435
452
  apiDescription.paths[apiPath] = apiPathMethods;
436
453
  }
437
- function generatePathInformationFromContainer(apiDescription, containerDefinition) {
454
+ function generatePathInformationFromContainer(apiDescription, containerDefinition, isAddonProject = false) {
438
455
  const isTimeseriesContainer = containerDefinition.containerType === ContainerType.hx;
439
456
  const containerType = isTimeseriesContainer ? 'timeseries' : 'containers';
440
- const apiPath = `/api/1/sites/{siteUid}/${containerType}/${containerDefinition.title}`;
457
+ const pathParameters = [contextIdRef];
458
+ let apiPath = `/api/1/sites/{siteUid}/${containerType}/${containerDefinition.title}`;
459
+ if (isAddonProject) {
460
+ apiPath = `/api/1/sites/{siteUid}/addons/{addonUid}/${containerType}/${containerDefinition.title}`;
461
+ pathParameters.push(addonIdRef);
462
+ }
441
463
  const apiPathMethods = {
442
464
  get: undefined,
443
465
  put: undefined
@@ -445,7 +467,7 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
445
467
  const getMethod = {
446
468
  tags: [tagNameFromContainerTitle(containerDefinition.title)],
447
469
  summary: `Retrieve the data of the "${tagNameFromContainerTitle(containerDefinition.title)}" container`,
448
- parameters: [contextIdRef],
470
+ parameters: [...pathParameters],
449
471
  responses: {
450
472
  '200': {
451
473
  ...successfulOperationResponse,
@@ -478,7 +500,7 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
478
500
  apiPathMethods.put = {
479
501
  tags: [tagNameFromContainerTitle(containerDefinition.title)],
480
502
  summary: `Modify the data of the "${tagNameFromContainerTitle(containerDefinition.title)}" container`,
481
- parameters: [contextIdRef],
503
+ parameters: [...pathParameters],
482
504
  requestBody: {
483
505
  content: {
484
506
  'application/json': {
@@ -506,7 +528,7 @@ function generatePathInformationFromContainer(apiDescription, containerDefinitio
506
528
  tags: [tagNameFromContainerTitle(containerDefinition.title)],
507
529
  summary: `Get the historical data of "${containerDefinition.title}"`,
508
530
  parameters: [
509
- contextIdRef,
531
+ ...pathParameters,
510
532
  {
511
533
  name: 'json',
512
534
  in: 'query',
package/out/main.js CHANGED
@@ -22,6 +22,9 @@ const devPath = () => {
22
22
  else if (process.env.NODE_ENV === 'local-dev-lib') {
23
23
  return './dev/lib';
24
24
  }
25
+ else if (process.env.NODE_ENV === 'local-dev-addon') {
26
+ return './dev/addon';
27
+ }
25
28
  return '';
26
29
  };
27
30
  const cwd = vscode_uri_1.Utils.joinPath(vscode_uri_1.URI.file(process.cwd()), devPath());
package/out/manifest.js CHANGED
@@ -12,8 +12,11 @@ const registryAPI_1 = require("./registryAPI");
12
12
  const globals_1 = require("./globals");
13
13
  const preload_1 = __importDefault(require("semver/preload"));
14
14
  const DeviceProfiles_1 = require("./DeviceProfiles");
15
- var isNumeric = helper_1.Helper.isNumeric;
16
15
  const apm_1 = require("./package/apm");
16
+ var isNumeric = helper_1.Helper.isNumeric;
17
+ const PRODUCT_ID_SUPPORTED = '52v007';
18
+ // todo fill with actual version
19
+ const ADDON_SUPPORTED = '52v099';
17
20
  // Cache to reduce the disk read requests
18
21
  const manifestCache = {
19
22
  _manifest: null,
@@ -43,6 +46,15 @@ var Manifest;
43
46
  * The source filename where the information is stored in
44
47
  */
45
48
  Manifest.fileName = 'studio.json';
49
+ let DeviceProfiles;
50
+ (function (DeviceProfiles) {
51
+ DeviceProfiles["m22x"] = "m22x";
52
+ DeviceProfiles["m23x"] = "m23x";
53
+ DeviceProfiles["nrf91"] = "nrf91";
54
+ DeviceProfiles["m2blegw"] = "m2blegw";
55
+ DeviceProfiles["m2easyv3"] = "m2easyv3";
56
+ DeviceProfiles["m2easyiot"] = "m2easyiot";
57
+ })(DeviceProfiles = Manifest.DeviceProfiles || (Manifest.DeviceProfiles = {}));
46
58
  /**
47
59
  * Type of the iot app project
48
60
  */
@@ -50,6 +62,7 @@ var Manifest;
50
62
  (function (ProjectTypes) {
51
63
  ProjectTypes["app"] = "app";
52
64
  ProjectTypes["library"] = "library";
65
+ ProjectTypes["addon"] = "addon";
53
66
  })(ProjectTypes = Manifest.ProjectTypes || (Manifest.ProjectTypes = {}));
54
67
  let BloAccessLevel;
55
68
  (function (BloAccessLevel) {
@@ -84,7 +97,7 @@ var Manifest;
84
97
  }
85
98
  Manifest.read = read;
86
99
  /**
87
- * Reads the studio.json as an uint8array
100
+ * Reads the studio.json as an Uint8Array
88
101
  * @param cwd
89
102
  * @param fs
90
103
  */
@@ -118,6 +131,22 @@ var Manifest;
118
131
  }
119
132
  }
120
133
  Manifest.isLibrary = isLibrary;
134
+ /**
135
+ * Check if the current project is an addon project
136
+ * @param manifest
137
+ */
138
+ function isAddon(manifest) {
139
+ return manifest.type === ProjectTypes.addon;
140
+ }
141
+ Manifest.isAddon = isAddon;
142
+ /**
143
+ * Check if the current project is an app project
144
+ * @param manifest
145
+ */
146
+ function isApp(manifest) {
147
+ return manifest.type === ProjectTypes.app;
148
+ }
149
+ Manifest.isApp = isApp;
121
150
  /**
122
151
  * Validates if the properties within
123
152
  * @param cwd
@@ -228,6 +257,30 @@ var Manifest;
228
257
  return null;
229
258
  }
230
259
  Manifest.validateRegistryAllowedBackends = validateRegistryAllowedBackends;
260
+ const REGEX_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
261
+ async function validateRegistryAllowedApplications(allowedApplications) {
262
+ if (allowedApplications === undefined) {
263
+ return 'Allowed applications not specified yet';
264
+ }
265
+ if (allowedApplications === null) {
266
+ return null;
267
+ }
268
+ if (Array.isArray(allowedApplications) || allowedApplications?.includes(';')) {
269
+ const validationArray = allowedApplications?.includes(';')
270
+ ? allowedApplications.split(';')
271
+ : allowedApplications;
272
+ for (const uid of validationArray) {
273
+ if (!uid.match(REGEX_UUID)) {
274
+ return `Application id "${uid}" is invalid`;
275
+ }
276
+ }
277
+ }
278
+ else if (!allowedApplications?.match(REGEX_UUID) && allowedApplications !== '*') {
279
+ return `Invalid value for "allowedApplications"`;
280
+ }
281
+ return null;
282
+ }
283
+ Manifest.validateRegistryAllowedApplications = validateRegistryAllowedApplications;
231
284
  async function validateApplicationIcon(cwd, fs, manifest) {
232
285
  const iconPath = manifest.icon;
233
286
  if (!iconPath) {
@@ -262,6 +315,7 @@ var Manifest;
262
315
  throw new Error('Setting "engines.backend" is invalid');
263
316
  }
264
317
  validateHwFwOrProductId(manifest);
318
+ validateAddonSupported(manifest);
265
319
  }
266
320
  Manifest.validateEngineSettings = validateEngineSettings;
267
321
  /**
@@ -275,9 +329,10 @@ var Manifest;
275
329
  if (!manifest) {
276
330
  manifest = await Manifest.read(cwd, fs);
277
331
  }
332
+ const isAddon = Manifest.isAddon(manifest);
278
333
  switch (apmPart) {
279
334
  case apm_1.APM.Part.dlo:
280
- return !!manifest?.dlo?.mainFile;
335
+ return !!manifest?.dlo?.mainFile && !isAddon;
281
336
  case apm_1.APM.Part.blo:
282
337
  return !!(manifest.blo?.buildCommand && manifest.blo?.workingPath);
283
338
  case apm_1.APM.Part.pov:
@@ -324,13 +379,28 @@ function validateBLOSettings(manifest) {
324
379
  }
325
380
  function validateHwFwOrProductId(manifest) {
326
381
  const { backend, productId, hwfw } = manifest.engines;
327
- if (backend && backend >= '52v007') {
382
+ if (Manifest.isAddon(manifest) && (productId || hwfw)) {
383
+ throw new Error('For project type "addon", "engines.hwfw" or "engines.productId" is not allowed!"');
384
+ }
385
+ if (backend && backend >= PRODUCT_ID_SUPPORTED) {
328
386
  if (hwfw && productId) {
329
387
  throw new Error('Only "engines.hwfw" or "engines.productId" is allowed!"');
330
388
  }
331
389
  }
332
390
  else if (productId) {
333
- throw new Error('"engines.productId" requires "engines.backend" to be ">=52v007"');
391
+ throw new Error(`"engines.productId" requires "engines.backend" to be "${PRODUCT_ID_SUPPORTED}"`);
392
+ }
393
+ }
394
+ function validateAddonSupported(manifest) {
395
+ if (!Manifest.isAddon(manifest)) {
396
+ return;
397
+ }
398
+ const { backend } = manifest.engines;
399
+ if (!backend || backend < ADDON_SUPPORTED) {
400
+ throw new Error(`Project type "addon" requires "engines.backend" to be ">=${ADDON_SUPPORTED}"`);
401
+ }
402
+ if (Manifest.isAddon(manifest) && manifest.dlo) {
403
+ throw new Error('For project type "addon", "dlo" is not allowed!"');
334
404
  }
335
405
  }
336
406
  /**
@@ -12,9 +12,9 @@ var APM;
12
12
  (function (APM) {
13
13
  let TagPhase;
14
14
  (function (TagPhase) {
15
- /*alpha='alpha',
16
- beta='beta',
17
- rc='rc',*/
15
+ TagPhase["alpha"] = "alpha";
16
+ TagPhase["beta"] = "beta";
17
+ TagPhase["rc"] = "rc";
18
18
  TagPhase["release"] = "release";
19
19
  TagPhase["stage"] = "stage";
20
20
  TagPhase["passive"] = "passive";
@@ -31,30 +31,47 @@ var APM;
31
31
  Part["blo"] = "blo";
32
32
  Part["dfiles"] = "dfiles";
33
33
  })(Part = APM.Part || (APM.Part = {}));
34
- /**
35
- * Create new release tag
36
- * @param cwd
37
- * @param fs
38
- * @param phase
39
- */
40
- async function createTag(cwd, fs, phase) {
41
- const manifest = await manifest_1.Manifest.read(cwd, fs);
42
- const { version, description, name, pov, engines, blo, publisher } = manifest;
34
+ function createBaseTagHeader(manifest) {
35
+ const { description, name, pov, engines, blo, publisher, type } = manifest;
36
+ const projectType = type || manifest_1.Manifest.ProjectTypes.app;
43
37
  const tagHeader = {
44
38
  name: name,
45
39
  abstract: description,
46
- phase: phase,
47
40
  author: publisher || '',
48
41
  pov_location: manifest_1.Manifest.PovLocation.embedded,
49
- version: version,
42
+ pov_details_lowlevel: false,
50
43
  required_be: engines?.backend,
51
44
  required_hwfw: engines?.hwfw?.join(';'),
52
45
  required_productcode: engines?.productId?.join(';'),
53
- blo_level: blo?.accessLevel || manifest_1.Manifest.BloAccessLevel.restricted
46
+ blo_level: blo?.accessLevel || manifest_1.Manifest.BloAccessLevel.restricted,
47
+ pip_id: ''
54
48
  };
55
49
  if (pov && pov.details) {
56
50
  tagHeader.pov_location = manifest_1.Manifest.PovLocation.pure;
57
51
  }
52
+ if (projectType === 'addon') {
53
+ tagHeader.required_hwfw = undefined;
54
+ tagHeader.required_productcode = undefined;
55
+ tagHeader.addon_max_sources = 1;
56
+ tagHeader.addon_max_per_site = 1;
57
+ }
58
+ return tagHeader;
59
+ }
60
+ APM.createBaseTagHeader = createBaseTagHeader;
61
+ /**
62
+ * Create new release tag
63
+ * @param cwd
64
+ * @param fs
65
+ * @param phase
66
+ */
67
+ async function createTag(cwd, fs, phase) {
68
+ const manifest = await manifest_1.Manifest.read(cwd, fs);
69
+ const baseTagHeader = createBaseTagHeader(manifest);
70
+ const tagHeader = {
71
+ version: manifest.version,
72
+ ...baseTagHeader,
73
+ phase: phase
74
+ };
58
75
  return await createBuffer(cwd, fs, manifest, tagHeader);
59
76
  }
60
77
  APM.createTag = createTag;
@@ -65,23 +82,11 @@ var APM;
65
82
  */
66
83
  async function createDevTag(cwd, fs) {
67
84
  const manifest = await manifest_1.Manifest.read(cwd, fs);
68
- const { publisher, name, engines, blo } = manifest;
85
+ const baseTag = createBaseTagHeader(manifest);
69
86
  const apmTagHeader = {
70
- name: name,
71
- author: publisher || '',
72
- abstract: '',
73
- blo_level: blo?.accessLevel || manifest_1.Manifest.BloAccessLevel.restricted,
74
- pip_id: '',
75
- pov_details_lowlevel: false,
76
- pov_location: manifest_1.Manifest.PovLocation.embedded,
77
- required_be: engines?.backend,
78
- required_hwfw: engines?.hwfw?.join(';'),
79
- required_productcode: engines?.productId?.join(';'),
87
+ ...baseTag,
80
88
  blo_autostart: false
81
89
  };
82
- if (manifest.pov?.details) {
83
- apmTagHeader.pov_location = manifest_1.Manifest.PovLocation.pure;
84
- }
85
90
  return createBuffer(cwd, fs, manifest, apmTagHeader);
86
91
  }
87
92
  APM.createDevTag = createDevTag;
@@ -178,11 +183,17 @@ var APM;
178
183
  const backendTarget = 'myDatanet';
179
184
  const { publisher, name, description } = manifest;
180
185
  const newApplication = {
186
+ // @ts-ignore
187
+ type: manifest.type || manifest_1.Manifest.ProjectTypes.app,
181
188
  name: name,
182
189
  targetSystem: backendTarget,
183
190
  description: description || '',
184
191
  allowedBackends: null
185
192
  };
193
+ // initialize allowedApplications for addon
194
+ if (manifest_1.Manifest.isAddon(manifest)) {
195
+ newApplication.allowedApplications = null;
196
+ }
186
197
  // create new application
187
198
  const projectId = await registryAPI_1.Registry.createNewApplication(token, publisher, newApplication, env);
188
199
  if (!projectId) {
@@ -171,6 +171,12 @@ var Package;
171
171
  if (!manifest_1.Manifest.isLibrary(manifest)) {
172
172
  await manifest_1.Manifest.validateApplicationIcon(cwd, fs, manifest);
173
173
  manifest_1.Manifest.validateEngineSettings(manifest);
174
+ // validate for dpid
175
+ if (manifest_1.Manifest.isApp(manifest) &&
176
+ (await manifest_1.Manifest.isApmPartEnabled(cwd, fs, apm_1.APM.Part.dlo, manifest)) &&
177
+ (!manifest.dpid || !Object.values(manifest_1.Manifest.DeviceProfiles).includes(manifest.dpid))) {
178
+ throw new Error(`dpid: The device profile is needed to compile a dlo`);
179
+ }
174
180
  }
175
181
  }
176
182
  Package.validatePublishSettings = validatePublishSettings;
package/package.json CHANGED
@@ -1,77 +1,77 @@
1
- {
2
- "name": "@microtronics/studio-cli",
3
- "version": "0.17.0",
4
- "description": "Microtronics Studio CLI Tool",
5
- "main": "./out/api.js",
6
- "typings": "./dist/studio-cli.d.ts",
7
- "bin": {
8
- "studio-cli": "studio-cli"
9
- },
10
- "publishConfig": {
11
- "access": "public"
12
- },
13
- "scripts": {
14
- "release": "release-it --ci",
15
- "compile": "npm run build:registryApiTypings && tsc",
16
- "api": "api-extractor run --local --verbose",
17
- "build": "npm run compile && npm run api",
18
- "watch:build": "npm run compile -- --watch",
19
- "test": "cross-env STUDIO_ENV=lucky mocha",
20
- "test-ci": "cross-env STUDIO_ENV=lucky mocha --reporter mocha-junit-reporter",
21
- "watch:test": "npm run test -- --watch",
22
- "prepublishOnly": "npm run build",
23
- "build:registryApiTypings": "npx openapi-typescript https://api.registry.stage.microtronics.com/v1/openapi.yaml -o ./src/typings/registry.ts"
24
- },
25
- "author": "Microtronics",
26
- "license": "ISC",
27
- "dependencies": {
28
- "ajv": "^8.17.1",
29
- "ajv-formats": "^3.0.1",
30
- "ajv-keywords": "^5.1.0",
31
- "commander": "^12.1.0",
32
- "cross-fetch": "^4.0.0",
33
- "dotenv": "^16.4.7",
34
- "file-type-checker": "^1.1.2",
35
- "glob": "^11.0.1",
36
- "iconv-lite": "^0.6.3",
37
- "image-dimensions": "^2.3.0",
38
- "ini": "^5.0.0",
39
- "minimatch": "^10.0.1",
40
- "openapi-fetch": "^0.13.0",
41
- "pako": "^2.1.0",
42
- "semver": "^7.6.3",
43
- "tarballjs": "github:ankitrohatgi/tarballjs",
44
- "tinytar-fix": "^0.1.1",
45
- "vscode-uri": "^3.0.8",
46
- "yaml": "^2.6.1"
47
- },
48
- "engines": {
49
- "node": ">= 22"
50
- },
51
- "devDependencies": {
52
- "@microsoft/api-extractor": "^7.47.11",
53
- "@types/chai": "^4.3.6",
54
- "@types/chai-as-promised": "^7.1.5",
55
- "@types/ini": "^4.1.1",
56
- "@types/mocha": "^10.0.9",
57
- "@types/node": "^22.9.1",
58
- "@types/semver": "^7.5.6",
59
- "@types/vscode": "^1.86.2",
60
- "chai": "^4.3.8",
61
- "chai-as-promised": "^7.1.2",
62
- "cross-env": "^7.0.3",
63
- "mocha": "^10.8.2",
64
- "mocha-junit-reporter": "^2.2.1",
65
- "openapi-typescript": "^7.6.0",
66
- "ts-node": "^10.9.2",
67
- "typescript": "^5.6.3"
68
- },
69
- "mocha": {
70
- "require": [
71
- "ts-node/register"
72
- ],
73
- "watch-files": "src/**",
74
- "spec": "./test/**/*.spec.ts",
75
- "recursive": true
76
- }
77
- }
1
+ {
2
+ "name": "@microtronics/studio-cli",
3
+ "version": "0.19.0",
4
+ "description": "Microtronics Studio CLI Tool",
5
+ "main": "./out/api.js",
6
+ "typings": "./dist/studio-cli.d.ts",
7
+ "bin": {
8
+ "studio-cli": "studio-cli"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "release": "release-it --ci",
15
+ "compile": "npm run build:registryApiTypings && tsc",
16
+ "api": "api-extractor run --local --verbose",
17
+ "build": "npm run compile && npm run api",
18
+ "watch:build": "npm run compile -- --watch",
19
+ "test": "cross-env STUDIO_ENV=lucky mocha",
20
+ "test-ci": "cross-env STUDIO_ENV=lucky mocha --reporter mocha-junit-reporter",
21
+ "watch:test": "npm run test -- --watch",
22
+ "prepublishOnly": "npm run build",
23
+ "build:registryApiTypings": "npx openapi-typescript https://api.registry.stage.microtronics.com/v1/openapi.yaml -o ./src/typings/registry.ts"
24
+ },
25
+ "author": "Microtronics",
26
+ "license": "ISC",
27
+ "dependencies": {
28
+ "ajv": "^8.17.1",
29
+ "ajv-formats": "^3.0.1",
30
+ "ajv-keywords": "^5.1.0",
31
+ "commander": "^12.1.0",
32
+ "cross-fetch": "^4.0.0",
33
+ "dotenv": "^16.4.7",
34
+ "file-type-checker": "^1.1.2",
35
+ "glob": "^11.0.1",
36
+ "iconv-lite": "^0.6.3",
37
+ "image-dimensions": "^2.3.0",
38
+ "ini": "^5.0.0",
39
+ "minimatch": "^10.0.1",
40
+ "openapi-fetch": "^0.13.0",
41
+ "pako": "^2.1.0",
42
+ "semver": "^7.6.3",
43
+ "tarballjs": "github:ankitrohatgi/tarballjs",
44
+ "tinytar-fix": "^0.1.1",
45
+ "vscode-uri": "^3.0.8",
46
+ "yaml": "^2.6.1"
47
+ },
48
+ "engines": {
49
+ "node": ">= 22"
50
+ },
51
+ "devDependencies": {
52
+ "@microsoft/api-extractor": "^7.47.11",
53
+ "@types/chai": "^4.3.6",
54
+ "@types/chai-as-promised": "^7.1.5",
55
+ "@types/ini": "^4.1.1",
56
+ "@types/mocha": "^10.0.9",
57
+ "@types/node": "^22.9.1",
58
+ "@types/semver": "^7.5.6",
59
+ "@types/vscode": "^1.86.2",
60
+ "chai": "^4.3.8",
61
+ "chai-as-promised": "^7.1.2",
62
+ "cross-env": "^7.0.3",
63
+ "mocha": "^10.8.2",
64
+ "mocha-junit-reporter": "^2.2.1",
65
+ "openapi-typescript": "^7.6.0",
66
+ "ts-node": "^10.9.2",
67
+ "typescript": "^5.6.3"
68
+ },
69
+ "mocha": {
70
+ "require": [
71
+ "ts-node/register"
72
+ ],
73
+ "watch-files": "src/**",
74
+ "spec": "./test/**/*.spec.ts",
75
+ "recursive": true
76
+ }
77
+ }
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // used for local development only
3
+ process.env.NODE_ENV = 'local-dev-addon';
4
+ require('./out/main')(process.argv);