@microtronics/studio-cli 0.61.0 → 0.62.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/out/manifest.js DELETED
@@ -1,492 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Manifest = void 0;
7
- const vscode_uri_1 = require("vscode-uri");
8
- const helper_1 = require("./helper");
9
- const image_dimensions_1 = require("image-dimensions");
10
- const file_type_checker_1 = require("file-type-checker");
11
- const registryAPI_1 = require("./registryAPI");
12
- const preload_1 = __importDefault(require("semver/preload"));
13
- const apm_1 = require("./package/apm");
14
- var isNumeric = helper_1.Helper.isNumeric;
15
- const deepmerge_ts_1 = require("deepmerge-ts");
16
- const PRODUCT_ID_SUPPORTED = '52v007';
17
- const SEMVER_SUPPORTED = '53v001';
18
- const ADDON_SUPPORTED = '54v001';
19
- const ANALYTICS_SUPPORTED = '56v001';
20
- // Cache to reduce the disk read requests
21
- const manifestCache = {
22
- _manifest: null,
23
- _stat: null,
24
- _overwrites: null,
25
- get manifest() {
26
- // clone the cached object to prevent any reference changes
27
- return (0, deepmerge_ts_1.deepmerge)(structuredClone(this._manifest), manifestCache._overwrites || {});
28
- },
29
- set manifest(manifest) {
30
- this._manifest = manifest;
31
- },
32
- set overwrites(manifest) {
33
- this._overwrites = manifest;
34
- },
35
- get stat() {
36
- return this._stat;
37
- },
38
- set stat(stat) {
39
- this._stat = stat;
40
- },
41
- clear() {
42
- this._stat = null;
43
- this._manifest = null;
44
- }
45
- };
46
- var Manifest;
47
- (function (Manifest) {
48
- var convertBlobToString = helper_1.Helper.convertBlobToString;
49
- /**
50
- * The source filename where the information is stored in
51
- */
52
- Manifest.fileName = 'studio.json';
53
- let DeviceProfiles;
54
- (function (DeviceProfiles) {
55
- DeviceProfiles["m22x"] = "m22x";
56
- DeviceProfiles["m23x"] = "m23x";
57
- DeviceProfiles["nrf91"] = "nrf91";
58
- DeviceProfiles["m2blegw"] = "m2blegw";
59
- DeviceProfiles["m2easyv3"] = "m2easyv3";
60
- DeviceProfiles["m2easyiot"] = "m2easyiot";
61
- })(DeviceProfiles = Manifest.DeviceProfiles || (Manifest.DeviceProfiles = {}));
62
- /**
63
- * Type of the iot app project
64
- */
65
- let ProjectTypes;
66
- (function (ProjectTypes) {
67
- ProjectTypes["app"] = "app";
68
- ProjectTypes["library"] = "library";
69
- ProjectTypes["addon"] = "addon";
70
- ProjectTypes["analytics"] = "analytics";
71
- })(ProjectTypes = Manifest.ProjectTypes || (Manifest.ProjectTypes = {}));
72
- let BloAccessLevel;
73
- (function (BloAccessLevel) {
74
- BloAccessLevel["restricted"] = "restricted";
75
- BloAccessLevel["global"] = "global";
76
- })(BloAccessLevel = Manifest.BloAccessLevel || (Manifest.BloAccessLevel = {}));
77
- let PovLocation;
78
- (function (PovLocation) {
79
- PovLocation["embedded"] = "$embedded";
80
- PovLocation["pure"] = "$pure";
81
- })(PovLocation = Manifest.PovLocation || (Manifest.PovLocation = {}));
82
- function setOverwrites(manifest) {
83
- manifestCache.overwrites = manifest;
84
- }
85
- Manifest.setOverwrites = setOverwrites;
86
- function clearOverwrites() {
87
- manifestCache.overwrites = null;
88
- }
89
- Manifest.clearOverwrites = clearOverwrites;
90
- /**
91
- * Read the studio.json manifest and parse it
92
- * @param cwd
93
- * @param fs
94
- */
95
- async function read(cwd, fs) {
96
- const manifestUri = vscode_uri_1.Utils.joinPath(cwd, Manifest.fileName);
97
- const manifestStat = await fs.stat(manifestUri);
98
- // if the manifest was modified, reload the cache
99
- if (manifestCache.manifest === null ||
100
- manifestUri?.fsPath !== manifestCache.stat?.path.fsPath ||
101
- manifestStat?.ctime !== manifestCache.stat?.ctime ||
102
- manifestStat?.mtime !== manifestCache.stat?.mtime ||
103
- manifestStat?.size !== manifestCache.stat?.size) {
104
- const localManifest = await fs.readFile(manifestUri);
105
- const manifestString = convertBlobToString(localManifest);
106
- manifestCache.manifest = JSON.parse(manifestString);
107
- manifestCache.stat = { ...manifestStat, path: manifestUri };
108
- }
109
- return manifestCache.manifest;
110
- }
111
- Manifest.read = read;
112
- /**
113
- * Reads the studio.json as an Uint8Array
114
- * @param cwd
115
- * @param fs
116
- */
117
- async function readAsBlob(cwd, fs) {
118
- return await fs.readFile(vscode_uri_1.Utils.joinPath(cwd, Manifest.fileName));
119
- }
120
- Manifest.readAsBlob = readAsBlob;
121
- /**
122
- * Write the manifest to the workspace
123
- * @param cwd
124
- * @param fs
125
- * @param manifest
126
- */
127
- async function write(cwd, fs, manifest) {
128
- manifestCache.clear();
129
- removeDeprecatedOptions(manifest);
130
- return fs.writeFile(vscode_uri_1.Utils.joinPath(cwd, Manifest.fileName), JSON.stringify(manifest, null, '\t'));
131
- }
132
- Manifest.write = write;
133
- /**
134
- * Check if the current project is a library project
135
- */
136
- function isLibrary(manifest) {
137
- if (manifest.library !== undefined) {
138
- return manifest.library;
139
- }
140
- else {
141
- return manifest.type === ProjectTypes.library;
142
- }
143
- }
144
- Manifest.isLibrary = isLibrary;
145
- /**
146
- * Check if the current project is an addon project
147
- * @param manifest
148
- */
149
- function isAddon(manifest) {
150
- return manifest.type === ProjectTypes.addon;
151
- }
152
- Manifest.isAddon = isAddon;
153
- /**
154
- * Check if the current project is an app project
155
- * @param manifest
156
- */
157
- function isApp(manifest) {
158
- if (manifest.type === undefined && !isLibrary(manifest)) {
159
- return true;
160
- }
161
- return manifest.type === ProjectTypes.app;
162
- }
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;
175
- /**
176
- * Check if the current project is an analytics project
177
- * @param manifest
178
- */
179
- function isAnalytics(manifest) {
180
- return manifest.type === ProjectTypes.analytics;
181
- }
182
- Manifest.isAnalytics = isAnalytics;
183
- /**
184
- * Validates if the properties within
185
- * @param cwd
186
- * @param fs
187
- * @param manifest
188
- * @param env
189
- */
190
- async function validateBasicManifest(cwd, fs, manifest) {
191
- if (!manifest) {
192
- manifest = await read(cwd, fs);
193
- }
194
- validateProjectVersion(manifest);
195
- validatePOVSettings(manifest);
196
- validateBLOSettings(manifest);
197
- validateMaxInstancesPerSite(manifest);
198
- }
199
- Manifest.validateBasicManifest = validateBasicManifest;
200
- function validateLibraryName(libraryName) {
201
- const errorMessage = `Library name can only contain 'a' through 'z', '0' through '9', '_' and '-'. The Library name must start with an alphabetic or numeric character.`;
202
- const valid = libraryName.match(/^[a-z0-9-_]+$/);
203
- if (valid) {
204
- const invalidChars = ['-', '_'];
205
- if (invalidChars.includes(libraryName[0]) || invalidChars.includes(libraryName[libraryName.length - 1])) {
206
- return errorMessage;
207
- }
208
- }
209
- else {
210
- return errorMessage;
211
- }
212
- if (libraryName.length < 3 || libraryName.length > 20) {
213
- return `The library name is beyond permissible length of 20 characters.`;
214
- }
215
- return null;
216
- }
217
- Manifest.validateLibraryName = validateLibraryName;
218
- function validateProjectName(name, isLibrary) {
219
- if (isLibrary) {
220
- return validateLibraryName(name);
221
- }
222
- else {
223
- const errorMessage = `Project name can only contain 'A' through 'Z', 'a' through 'z', '0' through '9', ' ', '_' and '-'. The Project name must start with an alphabetic or numeric character.`;
224
- // ...validate...
225
- const validChars = name.match(/^([a-zA-Z0-9 _-]+)$/);
226
- if (!validChars) {
227
- return errorMessage;
228
- }
229
- if (name.length < 3 || name.length > 40) {
230
- return `The project name is beyond permissible length of 40 characters.`;
231
- }
232
- const invalidChars = ['-', '_', ' '];
233
- if (invalidChars.includes(name[0]) || invalidChars.includes(name[name.length - 1])) {
234
- return errorMessage;
235
- }
236
- return null;
237
- }
238
- }
239
- Manifest.validateProjectName = validateProjectName;
240
- function validateDescription(description) {
241
- if (description.length < 5) {
242
- return `The description must have at least 5 characters.`;
243
- }
244
- else {
245
- return null;
246
- }
247
- }
248
- Manifest.validateDescription = validateDescription;
249
- function validatePublisherId(publisher) {
250
- if (!publisher) {
251
- return `No publisher set yet`;
252
- }
253
- const errorMessage = `Publisher can only contain 'A' through 'Z', 'a' through 'z', '0' through '9' and '-'. The Publisher start with an alphabetic or numeric character.`;
254
- const valid = publisher.match(/^[a-zA-Z0-9-]+$/);
255
- if (valid) {
256
- const invalidChars = ['_'];
257
- if (invalidChars.includes(publisher[0]) || invalidChars.includes(publisher[publisher.length - 1])) {
258
- return errorMessage;
259
- }
260
- }
261
- else {
262
- return errorMessage;
263
- }
264
- return null;
265
- }
266
- Manifest.validatePublisherId = validatePublisherId;
267
- async function validatePublisherOnline(token, publisher, env) {
268
- const exists = await registryAPI_1.Registry.getPublisher(token, publisher, env);
269
- if (!exists) {
270
- return `Publisher '${publisher}' does not exist.`;
271
- }
272
- return null;
273
- }
274
- Manifest.validatePublisherOnline = validatePublisherOnline;
275
- const REGEX_SERVER_DOMAIN = /^(((?!-))(xn--)?[a-z0-9\-_]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30})\.[a-z]{2,}$/;
276
- async function validateRegistryAllowedBackends(allowedBackends) {
277
- if (allowedBackends === undefined) {
278
- return 'Allowed backends not specified yet';
279
- }
280
- if (allowedBackends === null) {
281
- return null;
282
- }
283
- if (Array.isArray(allowedBackends) || allowedBackends?.includes(';')) {
284
- const validationArray = allowedBackends?.includes(';') ? allowedBackends.split(';') : allowedBackends;
285
- for (const domain of validationArray) {
286
- if (!domain.match(REGEX_SERVER_DOMAIN)) {
287
- return `Domain "${domain}" is invalid`;
288
- }
289
- }
290
- }
291
- else if (!allowedBackends?.match(REGEX_SERVER_DOMAIN) && allowedBackends !== '*') {
292
- return `Invalid value for "allowedBackends"`;
293
- }
294
- return null;
295
- }
296
- Manifest.validateRegistryAllowedBackends = validateRegistryAllowedBackends;
297
- 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;
298
- async function validateRegistryAllowedApplications(allowedApplications) {
299
- if (allowedApplications === undefined) {
300
- return 'Allowed applications not specified yet';
301
- }
302
- if (allowedApplications === null) {
303
- return null;
304
- }
305
- if (Array.isArray(allowedApplications) || allowedApplications?.includes(';')) {
306
- const validationArray = allowedApplications?.includes(';')
307
- ? allowedApplications.split(';')
308
- : allowedApplications;
309
- for (const uid of validationArray) {
310
- if (!uid.match(REGEX_UUID)) {
311
- return `Application id "${uid}" is invalid`;
312
- }
313
- }
314
- }
315
- else if (!allowedApplications?.match(REGEX_UUID) && allowedApplications !== '*') {
316
- return `Invalid value for "allowedApplications"`;
317
- }
318
- return null;
319
- }
320
- Manifest.validateRegistryAllowedApplications = validateRegistryAllowedApplications;
321
- async function validateApplicationIcon(cwd, fs, manifest) {
322
- const iconPath = manifest.icon;
323
- if (!iconPath) {
324
- throw new Error('App icon is required for publishing an application!');
325
- }
326
- const iconUri = vscode_uri_1.Utils.joinPath(cwd, iconPath);
327
- const iconExist = await fs.stat(iconUri);
328
- if (!iconExist) {
329
- throw new Error(`Could not load icon "${iconPath}"`);
330
- }
331
- const iconData = await fs.readFile(iconUri);
332
- const dimensions = (0, image_dimensions_1.imageDimensionsFromData)(iconData);
333
- if (!dimensions) {
334
- throw new Error(`App icon could not be validated!`);
335
- }
336
- if (dimensions?.width !== dimensions?.height) {
337
- throw new Error(`App icon has to be a square!`);
338
- }
339
- if (dimensions.width > 512 || dimensions.width < 75) {
340
- throw new Error(`App icon size should be between 75px and 512px!`);
341
- }
342
- if (!(0, file_type_checker_1.isPNG)(iconData)) {
343
- throw new Error(`App icon has to be of type PNG!`);
344
- }
345
- }
346
- Manifest.validateApplicationIcon = validateApplicationIcon;
347
- function validateEngineSettings(manifest) {
348
- const { engines } = manifest;
349
- // validate vor server versions >=52v006
350
- if (engines?.backend &&
351
- !engines.backend.match(/(^[5-9][2-9]|[6-9]\d+|\d{3,})v(0(0[0-9]|[1-9]\d)|[1-9]\d{2}|[1-9]\d{3,})$/)) {
352
- throw new Error('Setting "engines.backend" is invalid');
353
- }
354
- validateHwFwOrProductId(manifest);
355
- validateAddonOrAnalyticsSupported(manifest);
356
- }
357
- Manifest.validateEngineSettings = validateEngineSettings;
358
- /**
359
- * Validate if the given apm part is used
360
- * @param cwd
361
- * @param fs
362
- * @param apmPart
363
- * @param manifest
364
- */
365
- async function isApmPartEnabled(cwd, fs, apmPart, manifest) {
366
- if (!manifest) {
367
- manifest = await Manifest.read(cwd, fs);
368
- }
369
- const isAddon = Manifest.isAddon(manifest);
370
- const isAnalytics = Manifest.isAnalytics(manifest);
371
- switch (apmPart) {
372
- case apm_1.APM.Part.dlo:
373
- return !!manifest?.dlo?.mainFile && !isAddon && !isAnalytics;
374
- case apm_1.APM.Part.blo:
375
- return !!(manifest.blo?.buildCommand && manifest.blo?.workingPath);
376
- case apm_1.APM.Part.pov:
377
- return !!(manifest.pov?.details?.buildCommand && manifest.pov.details.workingPath);
378
- // dde and dfiles are always enabled
379
- case apm_1.APM.Part.dde:
380
- case apm_1.APM.Part.dfiles:
381
- return true;
382
- default:
383
- return false;
384
- }
385
- }
386
- Manifest.isApmPartEnabled = isApmPartEnabled;
387
- })(Manifest || (exports.Manifest = Manifest = {}));
388
- function validatePOVSettings(manifest) {
389
- const { pov } = manifest;
390
- if (!pov) {
391
- return;
392
- }
393
- if (pov.details) {
394
- if (!Object.hasOwn(pov.details, 'buildCommand')) {
395
- throw new Error('Setting "pov.details.buildCommand" missing!');
396
- }
397
- if (!Object.hasOwn(pov.details, 'workingPath')) {
398
- throw new Error('Setting "pov.details.workingPath" missing!');
399
- }
400
- }
401
- }
402
- function validateBLOSettings(manifest) {
403
- const { blo } = manifest;
404
- if (!blo) {
405
- return;
406
- }
407
- if (!Object.hasOwn(blo, 'buildCommand')) {
408
- throw new Error('Setting "blo.buildCommand" missing!');
409
- }
410
- if (!Object.hasOwn(blo, 'workingPath')) {
411
- throw new Error('Setting "blo.workingPath" missing!');
412
- }
413
- if (blo.accessLevel &&
414
- ![Manifest.BloAccessLevel.restricted, Manifest.BloAccessLevel.global].includes(blo.accessLevel)) {
415
- throw new Error(`Only "${Manifest.BloAccessLevel.restricted}" or "${Manifest.BloAccessLevel.global}" are allowed as value for "blo.accessLevel"!`);
416
- }
417
- }
418
- function validateHwFwOrProductId(manifest) {
419
- const { backend, productId, hwfw } = manifest.engines;
420
- if (Manifest.isAddon(manifest) && (productId || hwfw)) {
421
- throw new Error('For project type "addon", "engines.hwfw" or "engines.productId" is not allowed!"');
422
- }
423
- if (backend && backend >= PRODUCT_ID_SUPPORTED) {
424
- if (hwfw && productId) {
425
- throw new Error('Only "engines.hwfw" or "engines.productId" is allowed!"');
426
- }
427
- }
428
- else if (productId) {
429
- throw new Error(`"engines.productId" requires "engines.backend" to be "${PRODUCT_ID_SUPPORTED}"`);
430
- }
431
- }
432
- function validateAddonOrAnalyticsSupported(manifest) {
433
- if (!Manifest.isAddon(manifest) && !Manifest.isAnalytics(manifest)) {
434
- return;
435
- }
436
- const { backend } = manifest.engines;
437
- const requiredBackend = Manifest.isAddon(manifest) ? ADDON_SUPPORTED : ANALYTICS_SUPPORTED;
438
- if (!backend || backend < requiredBackend) {
439
- throw new Error(`Project type "${manifest.type}" requires "engines.backend" to be ">=${requiredBackend}"`);
440
- }
441
- if (manifest.dlo) {
442
- throw new Error(`For project type "${manifest.type}", "dlo" is not supported!"`);
443
- }
444
- if (manifest.dpid) {
445
- throw new Error(`For project type "${manifest.type}", "dpid" is not supported!"`);
446
- }
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
- }
469
- /**
470
- * Check based on the current env if the given version string is correct
471
- * @param manifest
472
- */
473
- function validateProjectVersion(manifest) {
474
- const serverVersion = manifest.engines?.backend || '00v000';
475
- if (serverVersion >= SEMVER_SUPPORTED || Manifest.isLibrary(manifest)) {
476
- if (!preload_1.default.valid(manifest.version)) {
477
- throw new Error(`From "engines.backend" version >= ${SEMVER_SUPPORTED} onwards "version" has to be a semantic version string!"`);
478
- }
479
- }
480
- else {
481
- if (!isNumeric(manifest.version)) {
482
- throw new Error('"version" has to be a number!');
483
- }
484
- }
485
- }
486
- function removeDeprecatedOptions(manifest) {
487
- if (manifest.registry) {
488
- delete manifest.registry.allowedBackends;
489
- delete manifest.registry.target;
490
- }
491
- }
492
- //# sourceMappingURL=manifest.js.map