@microtronics/studio-cli 0.51.0 → 0.52.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 +22 -4
- package/dist/main.js +115 -63
- package/dist/studio-cli.d.ts +351 -61
- package/out/dde/dde.js +207 -20
- package/out/dde/dynamic-dde.schema.json +331 -105
- package/out/dde/fileGenerators/dlo.js +1 -1
- package/out/defaultFiles.js +5 -2
- package/out/globals.js +286 -24
- package/out/package/package.js +10 -0
- package/package.json +1 -1
|
@@ -139,7 +139,7 @@ function generateAutoIncFromMap(ddeMap, globalDefines, manifest) {
|
|
|
139
139
|
/**
|
|
140
140
|
* generate global dlo defines if there are any
|
|
141
141
|
*/
|
|
142
|
-
pwn_section('GLOBAL DEFINES
|
|
142
|
+
pwn_section('GLOBAL DEFINES');
|
|
143
143
|
for (const [define, value] of Object.entries(globalDefines)) {
|
|
144
144
|
const valueIsDefine = Object.hasOwn(globalDefines, value);
|
|
145
145
|
addDefinition(define, `${value}`, valueIsDefine);
|
package/out/defaultFiles.js
CHANGED
|
@@ -72,7 +72,8 @@ var DefaultFiles;
|
|
|
72
72
|
dfilesPath: `${deployDirectoryName}dfiles`,
|
|
73
73
|
dfilesProperties: `${deployDirectoryName}dfiles/properties.json`,
|
|
74
74
|
bloPath: `${deployDirectoryName}blo`,
|
|
75
|
-
reportTemplate: `${deployDirectoryName}/${DefaultFiles.fileNames.reportTemplate}
|
|
75
|
+
reportTemplate: `${deployDirectoryName}/${DefaultFiles.fileNames.reportTemplate}`,
|
|
76
|
+
definesTs: `${deployDirectoryName}defines.ts`
|
|
76
77
|
},
|
|
77
78
|
dlo: {
|
|
78
79
|
path: dloDirectoryName,
|
|
@@ -86,7 +87,9 @@ var DefaultFiles;
|
|
|
86
87
|
dfiles: {
|
|
87
88
|
path: dfilesDirectoryName,
|
|
88
89
|
mainDFILES: `${dfilesDirectoryName}/main.dfiles`
|
|
89
|
-
}
|
|
90
|
+
},
|
|
91
|
+
appIni: 'app.ini',
|
|
92
|
+
defaultsIni: 'defaults.ini'
|
|
90
93
|
};
|
|
91
94
|
/**
|
|
92
95
|
* Changelog.md
|
package/out/globals.js
CHANGED
|
@@ -44,49 +44,311 @@ var Globals;
|
|
|
44
44
|
ENV["production"] = "production";
|
|
45
45
|
})(ENV = Globals.ENV || (Globals.ENV = {}));
|
|
46
46
|
/**
|
|
47
|
-
* Read all ini files from the project directory
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* Read all ini files from the project directory and its dependencies.
|
|
48
|
+
*
|
|
49
|
+
* Merge order (lowest → highest priority):
|
|
50
|
+
* Library dlo/<name>.ini & defaults.ini (from each installed dependency)
|
|
51
|
+
* Project dlo/<name>.ini (library projects only)
|
|
52
|
+
* Project dlo/main.ini (or manifest dlo.iniFile override)
|
|
53
|
+
* Project defaults.ini (library) or app.ini (app/addon/analytics)
|
|
54
|
+
*
|
|
55
|
+
* @param cwd - project root URI
|
|
56
|
+
* @param fs - filesystem abstraction
|
|
57
|
+
* @param logger
|
|
50
58
|
*/
|
|
51
|
-
async function read(cwd, fs) {
|
|
59
|
+
async function read(cwd, fs, logger) {
|
|
52
60
|
const manifest = await manifest_1.Manifest.read(cwd, fs);
|
|
53
61
|
const allDependencies = await dependencies_1.Dependencies.getAll(manifest);
|
|
54
62
|
const allDefines = {};
|
|
63
|
+
const sections = {};
|
|
64
|
+
const definesWithSource = {};
|
|
65
|
+
// Library dlo/<name>.ini and default.ini files
|
|
55
66
|
for (const dependencyId in allDependencies) {
|
|
56
67
|
const depPath = dependencies_1.Dependencies.dependencyToPath(cwd, dependencyId);
|
|
57
68
|
const name = dependencies_1.Dependencies.dependencyIdToName(dependencyId);
|
|
58
69
|
const libIniPath = vscode_uri_1.Utils.joinPath(depPath, DLO_PATH, `${name}.ini`);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
70
|
+
await mergeIniFile(fs, libIniPath, allDefines, sections, definesWithSource);
|
|
71
|
+
// defaults.ini files
|
|
72
|
+
const libDefaultsPath = vscode_uri_1.Utils.joinPath(depPath, defaultFiles_1.DefaultFiles.filePaths.defaultsIni);
|
|
73
|
+
await mergeIniFile(fs, libDefaultsPath, allDefines, sections, definesWithSource);
|
|
64
74
|
}
|
|
65
|
-
//
|
|
75
|
+
// Load the library project's specific ini file (deprecated location)
|
|
66
76
|
if (manifest_1.Manifest.isLibrary(manifest)) {
|
|
67
77
|
const libIni = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.dlo.path, `${manifest.name}.ini`);
|
|
68
|
-
if (await fs.stat(libIni)) {
|
|
69
|
-
|
|
70
|
-
Object.assign(allDefines, iniContent);
|
|
78
|
+
if (logger && (await fs.stat(libIni))) {
|
|
79
|
+
logger.warn(`dlo/${manifest.name}.ini is deprecated. Please migrate your defines to defaults.ini in the project root.`);
|
|
71
80
|
}
|
|
81
|
+
await mergeIniFile(fs, libIni, allDefines, sections, definesWithSource);
|
|
82
|
+
}
|
|
83
|
+
// Load the project's main.ini and overwrite existing defines (deprecated location)
|
|
84
|
+
const mainIniRelPath = manifest.dlo?.iniFile || defaultFiles_1.DefaultFiles.filePaths.dlo.mainINI;
|
|
85
|
+
const mainIni = vscode_uri_1.Utils.joinPath(cwd, mainIniRelPath);
|
|
86
|
+
if (logger && (await fs.stat(mainIni))) {
|
|
87
|
+
logger.warn(`${mainIniRelPath} is deprecated. Please migrate your defines to app.ini in the project root.`);
|
|
88
|
+
}
|
|
89
|
+
await mergeIniFile(fs, mainIni, allDefines, sections, definesWithSource);
|
|
90
|
+
// Project root: defaults.ini (library) or app.ini (app/addon/analytics)
|
|
91
|
+
if (manifest_1.Manifest.isLibrary(manifest)) {
|
|
92
|
+
const defaultsIni = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.defaultsIni);
|
|
93
|
+
await mergeIniFile(fs, defaultsIni, allDefines, sections, definesWithSource);
|
|
72
94
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const iniContent = await readIniFile(fs, mainIni);
|
|
77
|
-
Object.assign(allDefines, iniContent);
|
|
95
|
+
else {
|
|
96
|
+
const appIni = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.appIni);
|
|
97
|
+
await mergeIniFile(fs, appIni, allDefines, sections, definesWithSource);
|
|
78
98
|
}
|
|
79
|
-
return allDefines;
|
|
99
|
+
return { flat: allDefines, sections, definesWithSource };
|
|
80
100
|
}
|
|
81
101
|
Globals.read = read;
|
|
102
|
+
/**
|
|
103
|
+
* Generate a dist/defines.ts file from the resolved config.
|
|
104
|
+
* The generated file creates/extends globalThis.STUDIO_DEFINES.
|
|
105
|
+
*
|
|
106
|
+
* @param cwd - project root URI
|
|
107
|
+
* @param fs - filesystem abstraction
|
|
108
|
+
* @param resolvedConfig - the resolved config from Globals.read()
|
|
109
|
+
*/
|
|
110
|
+
async function exportDefinesTs(cwd, fs, resolvedConfig) {
|
|
111
|
+
const entries = Object.entries(resolvedConfig.flat);
|
|
112
|
+
// Build the StudioDefines interface members
|
|
113
|
+
const interfaceLines = [];
|
|
114
|
+
for (const [key, value] of entries) {
|
|
115
|
+
const entry = resolvedConfig.definesWithSource[key];
|
|
116
|
+
if (entry?.comment) {
|
|
117
|
+
const jsDoc = formatJsDoc(entry.comment);
|
|
118
|
+
for (const docLine of jsDoc.split('\n')) {
|
|
119
|
+
interfaceLines.push(`\t\t${docLine}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const tsType = isNumericValue(value) ? 'number' : 'string';
|
|
123
|
+
interfaceLines.push(`\t\t${key}: ${tsType};`);
|
|
124
|
+
}
|
|
125
|
+
const lines = [
|
|
126
|
+
'// Auto-generated by @microtronics/studio-cli \u2014 DO NOT EDIT',
|
|
127
|
+
'declare global {',
|
|
128
|
+
'\tinterface StudioDefines {',
|
|
129
|
+
...interfaceLines,
|
|
130
|
+
'\t}',
|
|
131
|
+
'\tvar STUDIO_DEFINES: StudioDefines;',
|
|
132
|
+
'}',
|
|
133
|
+
'',
|
|
134
|
+
'globalThis.STUDIO_DEFINES ??= {} as StudioDefines;',
|
|
135
|
+
''
|
|
136
|
+
];
|
|
137
|
+
for (const [key, value] of entries) {
|
|
138
|
+
const entry = resolvedConfig.definesWithSource[key];
|
|
139
|
+
if (entry?.comment) {
|
|
140
|
+
lines.push(formatJsDoc(entry.comment));
|
|
141
|
+
}
|
|
142
|
+
if (isNumericValue(value)) {
|
|
143
|
+
lines.push(`globalThis.STUDIO_DEFINES['${key}'] = ${Number(value)};`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const escapedValue = value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
147
|
+
lines.push(`globalThis.STUDIO_DEFINES['${key}'] = '${escapedValue}';`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
lines.push('');
|
|
151
|
+
lines.push('export {};');
|
|
152
|
+
lines.push('');
|
|
153
|
+
const definesPath = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.dist.definesTs);
|
|
154
|
+
await fs.writeFile(definesPath, lines.join('\n'));
|
|
155
|
+
}
|
|
156
|
+
Globals.exportDefinesTs = exportDefinesTs;
|
|
157
|
+
/**
|
|
158
|
+
* Replace {{KEY}} template tokens in a string with their resolved values.
|
|
159
|
+
*
|
|
160
|
+
* @param content - the content string with {{KEY}} tokens
|
|
161
|
+
* @param defines - the flat defines map
|
|
162
|
+
* @returns the substituted string and list of unresolved keys
|
|
163
|
+
*/
|
|
164
|
+
function replaceDefineTemplates(content, defines) {
|
|
165
|
+
const unresolvedKeys = [];
|
|
166
|
+
const result = content.replace(/\{\{([^}]+)\}\}/g, (_match, key) => {
|
|
167
|
+
const trimmedKey = key.trim();
|
|
168
|
+
if (Object.hasOwn(defines, trimmedKey)) {
|
|
169
|
+
return defines[trimmedKey];
|
|
170
|
+
}
|
|
171
|
+
unresolvedKeys.push(trimmedKey);
|
|
172
|
+
return _match;
|
|
173
|
+
});
|
|
174
|
+
return { result, unresolvedKeys };
|
|
175
|
+
}
|
|
176
|
+
Globals.replaceDefineTemplates = replaceDefineTemplates;
|
|
82
177
|
})(Globals || (exports.Globals = Globals = {}));
|
|
83
178
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
|
|
179
|
+
* Classify a trimmed ini-file line into one of the known kinds.
|
|
180
|
+
* Moves boolean-operator branching out of the main loop to reduce cognitive complexity.
|
|
181
|
+
*/
|
|
182
|
+
function classifyIniLine(trimmed) {
|
|
183
|
+
if (trimmed === '') {
|
|
184
|
+
return { kind: 'empty' };
|
|
185
|
+
}
|
|
186
|
+
if (trimmed.startsWith('#') || trimmed.startsWith(';')) {
|
|
187
|
+
return { kind: 'comment', text: trimmed.replace(/^[#;]\s?/, '') };
|
|
188
|
+
}
|
|
189
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
190
|
+
return { kind: 'section', name: trimmed.slice(1, -1) };
|
|
191
|
+
}
|
|
192
|
+
const eqIndex = trimmed.indexOf('=');
|
|
193
|
+
if (eqIndex > 0) {
|
|
194
|
+
return { kind: 'keyValue', key: trimmed.slice(0, eqIndex).trim() };
|
|
195
|
+
}
|
|
196
|
+
return { kind: 'other' };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Extract comment-to-key associations from raw ini text.
|
|
200
|
+
* Comments are lines starting with `#` or `;`. Consecutive comment lines
|
|
201
|
+
* are joined with `\n`. An empty line between a comment block and a key
|
|
202
|
+
* breaks the association. Section headers (`[Name]`) do NOT break a pending
|
|
203
|
+
* comment — the comment carries over to the first key inside the section.
|
|
204
|
+
*
|
|
205
|
+
* Returns a map of flattened key → comment text (with `#`/`;` prefix stripped).
|
|
87
206
|
*/
|
|
88
|
-
|
|
207
|
+
function extractComments(rawText) {
|
|
208
|
+
const result = {};
|
|
209
|
+
const lines = rawText.split(/\r?\n/);
|
|
210
|
+
let pendingCommentLines = [];
|
|
211
|
+
let currentSection = null;
|
|
212
|
+
for (const line of lines) {
|
|
213
|
+
const classified = classifyIniLine(line.trim());
|
|
214
|
+
if (classified.kind === 'empty' || classified.kind === 'other') {
|
|
215
|
+
pendingCommentLines = [];
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (classified.kind === 'comment') {
|
|
219
|
+
pendingCommentLines.push(classified.text);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (classified.kind === 'section') {
|
|
223
|
+
currentSection = classified.name;
|
|
224
|
+
// Don't reset pendingCommentLines — comment carries to first key
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
// keyValue
|
|
228
|
+
const flatKey = currentSection ? `${currentSection}_${classified.key}` : classified.key;
|
|
229
|
+
if (pendingCommentLines.length > 0) {
|
|
230
|
+
result[flatKey] = pendingCommentLines.join('\n');
|
|
231
|
+
}
|
|
232
|
+
pendingCommentLines = [];
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Format a comment string as a JSDoc block.
|
|
238
|
+
* Single-line: \/** comment*\/
|
|
239
|
+
* Multi-line: \/**\n * line1\n * line2\n *\/
|
|
240
|
+
*/
|
|
241
|
+
function formatJsDoc(comment) {
|
|
242
|
+
const commentLines = comment.split('\n');
|
|
243
|
+
if (commentLines.length === 1) {
|
|
244
|
+
return `/** ${commentLines[0]} */`;
|
|
245
|
+
}
|
|
246
|
+
const body = commentLines.map(l => ` * ${l}`).join('\n');
|
|
247
|
+
return `/**\n${body}\n */`;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check whether a string value represents a valid number.
|
|
251
|
+
* Empty strings are NOT considered numeric.
|
|
252
|
+
*/
|
|
253
|
+
function isNumericValue(value) {
|
|
254
|
+
return value !== '' && !isNaN(Number(value));
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Create a DefineEntry, attaching a comment from the comment map if available.
|
|
258
|
+
*/
|
|
259
|
+
function createDefineEntry(stringValue, fileUri, lines, key, sectionName, commentMap) {
|
|
260
|
+
const flatKey = sectionName ? `${sectionName}_${key}` : key;
|
|
261
|
+
const entry = {
|
|
262
|
+
value: stringValue,
|
|
263
|
+
sourceUri: fileUri,
|
|
264
|
+
sourceLine: findLineNumber(lines, key, sectionName)
|
|
265
|
+
};
|
|
266
|
+
if (commentMap[flatKey]) {
|
|
267
|
+
entry.comment = commentMap[flatKey];
|
|
268
|
+
}
|
|
269
|
+
return entry;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Merge all keys from a parsed ini section into the accumulators.
|
|
273
|
+
*/
|
|
274
|
+
function mergeSectionEntries(sectionName, sectionData, allDefines, sections, definesWithSource, fileUri, lines, commentMap) {
|
|
275
|
+
if (!sections[sectionName]) {
|
|
276
|
+
sections[sectionName] = {};
|
|
277
|
+
}
|
|
278
|
+
for (const [key, sectionValue] of Object.entries(sectionData)) {
|
|
279
|
+
const flatKey = `${sectionName}_${key}`;
|
|
280
|
+
const stringValue = `${sectionValue}`;
|
|
281
|
+
allDefines[flatKey] = stringValue;
|
|
282
|
+
sections[sectionName][key] = stringValue;
|
|
283
|
+
definesWithSource[flatKey] = createDefineEntry(stringValue, fileUri, lines, key, sectionName, commentMap);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Read and merge a single ini file into the accumulated defines, sections, and source tracking.
|
|
288
|
+
* Supports sections: keys under [SectionName] are flattened as SectionName_keyname.
|
|
289
|
+
*
|
|
290
|
+
* @param fs - filesystem abstraction
|
|
291
|
+
* @param filePath - URI to the ini file
|
|
292
|
+
* @param allDefines - accumulated flat defines (mutated)
|
|
293
|
+
* @param sections - accumulated sectioned config (mutated)
|
|
294
|
+
* @param definesWithSource - accumulated source tracking (mutated)
|
|
295
|
+
*/
|
|
296
|
+
async function mergeIniFile(fs, filePath, allDefines, sections, definesWithSource) {
|
|
297
|
+
// early return if the file doesn't exist
|
|
298
|
+
if (!(await fs.stat(filePath))) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
89
301
|
const iniContent = await fs.readFile(filePath);
|
|
90
|
-
|
|
302
|
+
const rawText = convertBlobToString(iniContent);
|
|
303
|
+
const parsed = ini.parse(rawText);
|
|
304
|
+
const fileUri = filePath.toString();
|
|
305
|
+
const lines = rawText.split(/\r?\n/);
|
|
306
|
+
const commentMap = extractComments(rawText);
|
|
307
|
+
for (const [sectionOrKey, value] of Object.entries(parsed)) {
|
|
308
|
+
if (typeof value === 'object' && value !== null) {
|
|
309
|
+
mergeSectionEntries(sectionOrKey, value, allDefines, sections, definesWithSource, fileUri, lines, commentMap);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
const stringValue = `${value}`;
|
|
313
|
+
allDefines[sectionOrKey] = stringValue;
|
|
314
|
+
definesWithSource[sectionOrKey] = createDefineEntry(stringValue, fileUri, lines, sectionOrKey, null, commentMap);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Find the line number (0-based) of a key within an ini file's text lines.
|
|
320
|
+
* If a sectionName is provided, only searches within that section.
|
|
321
|
+
*
|
|
322
|
+
* @param lines - the file split by newlines
|
|
323
|
+
* @param key - the ini key to find
|
|
324
|
+
* @param sectionName - the section to search within, or null for top-level
|
|
325
|
+
* @returns 0-based line number, or 0 if not found
|
|
326
|
+
*/
|
|
327
|
+
function findLineNumber(lines, key, sectionName) {
|
|
328
|
+
let inTargetSection = sectionName === null;
|
|
329
|
+
const sectionHeader = sectionName ? `[${sectionName}]` : null;
|
|
330
|
+
const keyPattern = new RegExp(`^\\s*${escapeRegex(key)}\\s*=`);
|
|
331
|
+
for (let i = 0; i < lines.length; i++) {
|
|
332
|
+
const trimmed = lines[i].trim();
|
|
333
|
+
if (sectionHeader && trimmed === sectionHeader) {
|
|
334
|
+
inTargetSection = true;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (inTargetSection && trimmed.startsWith('[') && trimmed.endsWith(']') && sectionName !== null) {
|
|
338
|
+
// Entered a different section
|
|
339
|
+
inTargetSection = false;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
if (inTargetSection && keyPattern.test(lines[i])) {
|
|
343
|
+
return i;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return 0;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Escape a string for use in a RegExp
|
|
350
|
+
*/
|
|
351
|
+
function escapeRegex(str) {
|
|
352
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
91
353
|
}
|
|
92
354
|
//# sourceMappingURL=globals.js.map
|
package/out/package/package.js
CHANGED
|
@@ -13,6 +13,7 @@ const compiler_1 = require("../dlo/compiler");
|
|
|
13
13
|
const scriptRunner_1 = require("../scriptRunner");
|
|
14
14
|
const registryAPI_1 = require("../registryAPI");
|
|
15
15
|
const manifest_1 = require("../manifest");
|
|
16
|
+
const globals_1 = require("../globals");
|
|
16
17
|
const library_1 = require("./library");
|
|
17
18
|
const dfiles_1 = require("../dfiles/dfiles");
|
|
18
19
|
const tarjs_1 = require("@gera2ld/tarjs");
|
|
@@ -42,6 +43,15 @@ var Package;
|
|
|
42
43
|
async function buildAll(cwd, fs, logger, env, apiToken, selectedParts = true, errorWithDiagnostics) {
|
|
43
44
|
selectedParts = normalizeSelectedParts(logger, selectedParts);
|
|
44
45
|
await preBuild(cwd, fs, logger, env, apiToken, selectedParts);
|
|
46
|
+
// Generate dist/defines.ts before POV/BLO builds
|
|
47
|
+
try {
|
|
48
|
+
const resolvedConfig = await globals_1.Globals.read(cwd, fs, logger);
|
|
49
|
+
await globals_1.Globals.exportDefinesTs(cwd, fs, resolvedConfig);
|
|
50
|
+
logger.log('Generated', defaultFiles_1.DefaultFiles.filePaths.dist.definesTs);
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
logger.warn('Could not generate defines.ts:', e);
|
|
54
|
+
}
|
|
45
55
|
const mergedDiagnostics = {
|
|
46
56
|
[apm_1.APM.Part.dde]: [],
|
|
47
57
|
[apm_1.APM.Part.dlo]: [],
|