@microtronics/studio-cli 0.18.0 → 0.19.1

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,5 +1,29 @@
1
1
 
2
2
 
3
+ ## 0.19.1 (2025-02-20)
4
+
5
+ # Changelog
6
+
7
+ ## 0.19.0 (2025-02-19)
8
+
9
+ * test(studio-cli): tag header should not have property type ([5082db8](https://bitbucket.org/microtronics-core/vscode-studio/commits/5082db8))
10
+ * test(studio-cli): test if type addon can only used from specific version onwards ([213bc7c](https://bitbucket.org/microtronics-core/vscode-studio/commits/213bc7c))
11
+ * test(studio-cli): validate apm tag header creation ([e74acc8](https://bitbucket.org/microtronics-core/vscode-studio/commits/e74acc8))
12
+ * test(studio-cli): validate openapi generation for addons ([08176bc](https://bitbucket.org/microtronics-core/vscode-studio/commits/08176bc))
13
+ * feat(studio-cli): added function to validate if app id is an uuid ([60bda6f](https://bitbucket.org/microtronics-core/vscode-studio/commits/60bda6f))
14
+ * feat(studio-cli): allow creating an apm tag for addons ([a7d32c4](https://bitbucket.org/microtronics-core/vscode-studio/commits/a7d32c4))
15
+ * feat(studio-cli): generate api routes for addons ([a075407](https://bitbucket.org/microtronics-core/vscode-studio/commits/a075407))
16
+ * feat(studio-cli): improved manifest validation if type is addon ([c3ae0c9](https://bitbucket.org/microtronics-core/vscode-studio/commits/c3ae0c9))
17
+ * feat(studio-cli): only allow project type addon for a specific backend version ([46f0f28](https://bitbucket.org/microtronics-core/vscode-studio/commits/46f0f28))
18
+ * feat(studio-cli): support for new app type `apm` ([8041db3](https://bitbucket.org/microtronics-core/vscode-studio/commits/8041db3))
19
+ * chore(studio-cli): add run file for local addon development ([465a1f0](https://bitbucket.org/microtronics-core/vscode-studio/commits/465a1f0))
20
+ * chore(studio-cli): disable dlo per default if project type is addon ([a7f98af](https://bitbucket.org/microtronics-core/vscode-studio/commits/a7f98af))
21
+ * chore(studio-cli): dissallow setting hw/fw & productId if project type is addon ([74c90c3](https://bitbucket.org/microtronics-core/vscode-studio/commits/74c90c3))
22
+ * chore(studio-cli): improve type to allow `Manifest.ProjectTypes` ([fe6535f](https://bitbucket.org/microtronics-core/vscode-studio/commits/fe6535f))
23
+ * chore(studio-cli): validate for device profile id if dlo is enabled ([908fc9a](https://bitbucket.org/microtronics-core/vscode-studio/commits/908fc9a))
24
+ * revert(studio-cli): remove type property from tagheader object ([65f90ad](https://bitbucket.org/microtronics-core/vscode-studio/commits/65f90ad))
25
+ * refactor(studio-cli): added function to create the `baseTagHeader` ([ac9f83f](https://bitbucket.org/microtronics-core/vscode-studio/commits/ac9f83f))
26
+
3
27
  ## 0.18.0 (2025-02-13)
4
28
 
5
29
 
@@ -23,37 +23,14 @@ export declare namespace APM {
23
23
  blo = "blo",
24
24
  dfiles = "dfiles"
25
25
  }
26
- export interface TagHeader extends ApplicationTagInformation {
27
- author: string;
28
- version: string;
29
- blo_level?: Manifest.BloAccessLevel;
30
- required_be?: string;
31
- required_hwfw?: string;
32
- required_productcode?: string;
26
+ export interface TagHeader extends BaseTagHeader {
27
+ phase: TagPhase;
28
+ version: string | number;
33
29
  }
34
- export interface DevTagHeader {
35
- name: string;
36
- abstract: string;
37
- author: string;
38
- pip_id: string;
39
- pov_location: Manifest.PovLocation;
40
- pov_details_lowlevel: boolean;
41
- blo_level: Manifest.BloAccessLevel;
30
+ export interface DevTagHeader extends BaseTagHeader {
42
31
  blo_autostart: boolean;
43
- /**
44
- * ONE specific
45
- * the version 0 for ONE
46
- */
47
- version?: number;
48
- /**
49
- * ONE specific
50
- * owner_id is the organizationID
51
- */
52
- owner_id?: string;
53
- required_be?: string;
54
- required_hwfw?: string;
55
- required_productcode?: string;
56
32
  }
33
+ export function createBaseTagHeader(manifest: Manifest.Manifest): BaseTagHeader;
57
34
  /**
58
35
  * Create new release tag
59
36
  * @param cwd
@@ -117,7 +94,26 @@ export declare namespace APM {
117
94
  }>;
118
95
  }
119
96
 
120
- 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
+ }
121
117
 
122
118
  declare interface components {
123
119
  schemas: {
@@ -173,6 +169,7 @@ declare interface components {
173
169
  NewApplication: {
174
170
  /** @description The project name */
175
171
  name: string;
172
+ type?: components["schemas"]["ApplicationType"];
176
173
  /** @description Short description what this library does */
177
174
  description: string;
178
175
  targetSystem: components["schemas"]["TargetSystem"];
@@ -180,7 +177,11 @@ declare interface components {
180
177
  organizationId?: string;
181
178
  /** @description Defines which servers are allowed to see this application. If null, the application wont be shared with anyone */
182
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;
183
182
  };
183
+ /** @enum {string} */
184
+ ApplicationType: "app" | "addon";
184
185
  ApplicationInformationBase: {
185
186
  version: components["parameters"]["ApplicationVersion"];
186
187
  publisherId: components["parameters"]["PublisherId"];
@@ -2045,13 +2046,21 @@ export declare namespace Manifest {
2045
2046
  * The source filename where the information is stored in
2046
2047
  */
2047
2048
  const fileName = "studio.json";
2048
- 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
+ }
2049
2057
  /**
2050
2058
  * Type of the iot app project
2051
2059
  */
2052
2060
  export enum ProjectTypes {
2053
2061
  app = "app",
2054
- library = "library"
2062
+ library = "library",
2063
+ addon = "addon"
2055
2064
  }
2056
2065
  export interface Manifest {
2057
2066
  version: string;
@@ -2061,7 +2070,7 @@ export declare namespace Manifest {
2061
2070
  type: ProjectTypes;
2062
2071
  legacyProject?: boolean;
2063
2072
  icon?: string;
2064
- dpid: DeviceProfiles;
2073
+ dpid?: DeviceProfiles;
2065
2074
  engines?: {
2066
2075
  backend?: string;
2067
2076
  hwfw?: string[];
@@ -2118,7 +2127,7 @@ export declare namespace Manifest {
2118
2127
  */
2119
2128
  export function read(cwd: URI, fs: LocalFS): Promise<Manifest>;
2120
2129
  /**
2121
- * Reads the studio.json as an uint8array
2130
+ * Reads the studio.json as an Uint8Array
2122
2131
  * @param cwd
2123
2132
  * @param fs
2124
2133
  */
@@ -2134,6 +2143,16 @@ export declare namespace Manifest {
2134
2143
  * Check if the current project is a library project
2135
2144
  */
2136
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;
2137
2156
  /**
2138
2157
  * Validates if the properties within
2139
2158
  * @param cwd
@@ -2148,6 +2167,7 @@ export declare namespace Manifest {
2148
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;
2149
2168
  export function validatePublisherOnline(token: Registry.AuthToken, publisher: string): Promise<string | null>;
2150
2169
  export function validateRegistryAllowedBackends(allowedBackends: undefined | null | string | string[]): Promise<string | null>;
2170
+ export function validateRegistryAllowedApplications(allowedApplications: undefined | null | string | string[]): Promise<string | null>;
2151
2171
  export function validateApplicationIcon(cwd: URI, fs: LocalFS, manifest: Manifest.Manifest): Promise<void>;
2152
2172
  export function validateEngineSettings(manifest: Manifest.Manifest): void;
2153
2173
  /**
@@ -4289,7 +4309,9 @@ export declare namespace Registry {
4289
4309
  export function fetchCustomContent(token: AuthToken, contentURL: string, json?: boolean, env?: Globals.ENV): Promise<ArrayBuffer | any>;
4290
4310
  export type Publisher = components['schemas']['Publisher'];
4291
4311
  export function getPublisher(token: AuthToken, publisherId: string): Promise<Publisher | null>;
4292
- export type ApiNewApplication = components['schemas']['NewApplication'];
4312
+ export type ApiNewApplication = components['schemas']['NewApplication'] & {
4313
+ type?: string | Manifest.ProjectTypes;
4314
+ };
4293
4315
  export function createNewApplication(token: AuthToken, publisherId: string, newApplication: ApiNewApplication, env?: Globals.ENV): Promise<string | null | undefined>;
4294
4316
  export type ApplicationDetailInformation = components['schemas']['ApplicationDetailInformation'];
4295
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',
@@ -101,6 +101,9 @@ function generateAutoIncFromMap(ddeMap, globalDefines, manifest) {
101
101
  pwn(`#define ${name} ${quotes}${value}${quotes}`);
102
102
  }
103
103
  const { dpid, registry } = manifest;
104
+ if (!dpid) {
105
+ throw new Error('Setting "dpid" is required to generate dlo files');
106
+ }
104
107
  const { auto_inc } = DeviceProfiles_1.DeviceProfiles[dpid];
105
108
  addDefinition(`APM_DPID`, `${dpid}`);
106
109
  addDefinition(`APM_DPID_${dpid}`, `1`);
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,31 @@ 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.dlo) {
403
+ throw new Error('For project type "addon", "dlo" is not supported!"');
404
+ }
405
+ if (manifest.dpid) {
406
+ throw new Error('For project type "addon", "dpid" is not supported!"');
334
407
  }
335
408
  }
336
409
  /**
@@ -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;
@@ -204,8 +210,10 @@ async function buildDDE(cwd, fs) {
204
210
  await dde_1.DDE.exportHistoryJson(cwd, fs, result.ddeJSON);
205
211
  }
206
212
  await dde_1.DDE.exportOpenApi(cwd, fs, result.ddeJSON);
207
- await dde_1.DDE.exportAutoDloFiles(cwd, fs, result.ddeJSON);
208
- await dlo_1.DLO.exportDloConfig(cwd, fs);
213
+ if (await manifest_1.Manifest.isApmPartEnabled(cwd, fs, apm_1.APM.Part.dlo, manifest)) {
214
+ await dde_1.DDE.exportAutoDloFiles(cwd, fs, result.ddeJSON);
215
+ await dlo_1.DLO.exportDloConfig(cwd, fs);
216
+ }
209
217
  }
210
218
  else {
211
219
  throw new Error('Project has errors!');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microtronics/studio-cli",
3
- "version": "0.18.0",
3
+ "version": "0.19.1",
4
4
  "description": "Microtronics Studio CLI Tool",
5
5
  "main": "./out/api.js",
6
6
  "typings": "./dist/studio-cli.d.ts",
@@ -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);