@sdeverywhere/build 0.3.17 → 0.3.18
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/dist/index.d.ts +493 -483
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +884 -959
- package/dist/index.js.map +1 -1
- package/package.json +5 -7
- package/dist/index.cjs +0 -1055
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -603
package/dist/index.cjs
DELETED
|
@@ -1,1055 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
|
|
29
|
-
// src/index.ts
|
|
30
|
-
var index_exports = {};
|
|
31
|
-
__export(index_exports, {
|
|
32
|
-
build: () => build
|
|
33
|
-
});
|
|
34
|
-
module.exports = __toCommonJS(index_exports);
|
|
35
|
-
|
|
36
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.28_typescript@5.2.2_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js
|
|
37
|
-
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
38
|
-
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
39
|
-
|
|
40
|
-
// src/build/build.ts
|
|
41
|
-
var import_path6 = require("path");
|
|
42
|
-
var import_neverthrow3 = require("neverthrow");
|
|
43
|
-
|
|
44
|
-
// src/config/config-loader.ts
|
|
45
|
-
var import_fs = require("fs");
|
|
46
|
-
var import_path = require("path");
|
|
47
|
-
var import_url = require("url");
|
|
48
|
-
var import_neverthrow = require("neverthrow");
|
|
49
|
-
async function loadConfig(mode, config, sdeDir, sdeCmdPath) {
|
|
50
|
-
let userConfig;
|
|
51
|
-
if (typeof config === "object") {
|
|
52
|
-
userConfig = config;
|
|
53
|
-
} else {
|
|
54
|
-
let configPath;
|
|
55
|
-
if (typeof config === "string") {
|
|
56
|
-
configPath = config;
|
|
57
|
-
} else {
|
|
58
|
-
configPath = (0, import_path.join)(process.cwd(), "sde.config.js");
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
if (!(0, import_fs.existsSync)(configPath)) {
|
|
62
|
-
return (0, import_neverthrow.err)(new Error(`Cannot find config file '${configPath}'`));
|
|
63
|
-
}
|
|
64
|
-
const configRelPath = relativeToSourcePath(configPath);
|
|
65
|
-
const configModule = await import(configRelPath);
|
|
66
|
-
userConfig = await configModule.config();
|
|
67
|
-
} catch (e) {
|
|
68
|
-
return (0, import_neverthrow.err)(new Error(`Failed to load config file '${configPath}': ${e.message}`));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
const resolvedConfig = resolveUserConfig(userConfig, mode, sdeDir, sdeCmdPath);
|
|
73
|
-
return (0, import_neverthrow.ok)({
|
|
74
|
-
userConfig,
|
|
75
|
-
resolvedConfig
|
|
76
|
-
});
|
|
77
|
-
} catch (e) {
|
|
78
|
-
return (0, import_neverthrow.err)(e);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function resolveUserConfig(userConfig, mode, sdeDir, sdeCmdPath) {
|
|
82
|
-
function expectDirectory(propName, path) {
|
|
83
|
-
if (!(0, import_fs.existsSync)(path)) {
|
|
84
|
-
throw new Error(`The configured ${propName} (${path}) does not exist`);
|
|
85
|
-
} else if (!(0, import_fs.lstatSync)(path).isDirectory()) {
|
|
86
|
-
throw new Error(`The configured ${propName} (${path}) is not a directory`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
let rootDir;
|
|
90
|
-
if (userConfig.rootDir) {
|
|
91
|
-
rootDir = (0, import_path.resolve)(userConfig.rootDir);
|
|
92
|
-
expectDirectory("rootDir", rootDir);
|
|
93
|
-
} else {
|
|
94
|
-
rootDir = process.cwd();
|
|
95
|
-
}
|
|
96
|
-
let prepDir;
|
|
97
|
-
if (userConfig.prepDir) {
|
|
98
|
-
prepDir = (0, import_path.resolve)(userConfig.prepDir);
|
|
99
|
-
} else {
|
|
100
|
-
prepDir = (0, import_path.resolve)(rootDir, "sde-prep");
|
|
101
|
-
}
|
|
102
|
-
(0, import_fs.mkdirSync)(prepDir, { recursive: true });
|
|
103
|
-
const userModelFiles = userConfig.modelFiles;
|
|
104
|
-
const modelFiles = [];
|
|
105
|
-
for (const userModelFile of userModelFiles) {
|
|
106
|
-
const modelFile = (0, import_path.resolve)(userModelFile);
|
|
107
|
-
if (!(0, import_fs.existsSync)(modelFile)) {
|
|
108
|
-
throw new Error(`The configured model file (${modelFile}) does not exist`);
|
|
109
|
-
}
|
|
110
|
-
modelFiles.push(modelFile);
|
|
111
|
-
}
|
|
112
|
-
let modelInputPaths;
|
|
113
|
-
if (userConfig.modelInputPaths && userConfig.modelInputPaths.length > 0) {
|
|
114
|
-
modelInputPaths = userConfig.modelInputPaths;
|
|
115
|
-
} else {
|
|
116
|
-
modelInputPaths = modelFiles;
|
|
117
|
-
}
|
|
118
|
-
let watchPaths2;
|
|
119
|
-
if (userConfig.watchPaths && userConfig.watchPaths.length > 0) {
|
|
120
|
-
watchPaths2 = userConfig.watchPaths;
|
|
121
|
-
} else {
|
|
122
|
-
watchPaths2 = modelFiles;
|
|
123
|
-
}
|
|
124
|
-
const rawGenFormat = userConfig.genFormat || "js";
|
|
125
|
-
let genFormat;
|
|
126
|
-
switch (rawGenFormat) {
|
|
127
|
-
case "js":
|
|
128
|
-
genFormat = "js";
|
|
129
|
-
break;
|
|
130
|
-
case "c":
|
|
131
|
-
genFormat = "c";
|
|
132
|
-
break;
|
|
133
|
-
default:
|
|
134
|
-
throw new Error(`The configured genFormat value is invalid; must be either 'js' or 'c'`);
|
|
135
|
-
}
|
|
136
|
-
let outListingFile;
|
|
137
|
-
if (userConfig.outListingFile) {
|
|
138
|
-
if ((0, import_path.isAbsolute)(userConfig.outListingFile)) {
|
|
139
|
-
outListingFile = userConfig.outListingFile;
|
|
140
|
-
} else {
|
|
141
|
-
outListingFile = (0, import_path.resolve)(rootDir, userConfig.outListingFile);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return {
|
|
145
|
-
mode,
|
|
146
|
-
rootDir,
|
|
147
|
-
prepDir,
|
|
148
|
-
modelFiles,
|
|
149
|
-
modelInputPaths,
|
|
150
|
-
watchPaths: watchPaths2,
|
|
151
|
-
genFormat,
|
|
152
|
-
outListingFile,
|
|
153
|
-
sdeDir,
|
|
154
|
-
sdeCmdPath
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
function relativeToSourcePath(filePath) {
|
|
158
|
-
const srcDir = (0, import_path.dirname)((0, import_url.fileURLToPath)(importMetaUrl));
|
|
159
|
-
const relPath = (0, import_path.relative)(srcDir, filePath);
|
|
160
|
-
return relPath.replaceAll("\\", "/");
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// src/_shared/log.ts
|
|
164
|
-
var import_fs2 = require("fs");
|
|
165
|
-
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
166
|
-
var activeLevels = /* @__PURE__ */ new Set(["error", "info"]);
|
|
167
|
-
var overlayFile;
|
|
168
|
-
var overlayEnabled = false;
|
|
169
|
-
var overlayHtml = "";
|
|
170
|
-
function setActiveLevels(logLevels) {
|
|
171
|
-
activeLevels.clear();
|
|
172
|
-
for (const level of logLevels) {
|
|
173
|
-
activeLevels.add(level);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
function setOverlayFile(file, enabled) {
|
|
177
|
-
overlayFile = file;
|
|
178
|
-
overlayEnabled = enabled;
|
|
179
|
-
(0, import_fs2.writeFileSync)(overlayFile, "");
|
|
180
|
-
}
|
|
181
|
-
function log(level, msg) {
|
|
182
|
-
if (activeLevels.has(level)) {
|
|
183
|
-
if (level === "error") {
|
|
184
|
-
console.error(import_picocolors.default.red(msg));
|
|
185
|
-
logToOverlay(msg);
|
|
186
|
-
} else {
|
|
187
|
-
console.log(msg);
|
|
188
|
-
logToOverlay(msg);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
function logError(e) {
|
|
193
|
-
const stack = e.stack || "";
|
|
194
|
-
const stackLines = stack.split("\n").filter((s) => s.match(/^\s+at/));
|
|
195
|
-
const trace = stackLines.slice(0, 3).join("\n");
|
|
196
|
-
console.error(import_picocolors.default.red(`
|
|
197
|
-
ERROR: ${e.message}`));
|
|
198
|
-
console.error(import_picocolors.default.dim(import_picocolors.default.red(`${trace}
|
|
199
|
-
`)));
|
|
200
|
-
logToOverlay(`
|
|
201
|
-
ERROR: ${e.message}`, true);
|
|
202
|
-
logToOverlay(`${trace}
|
|
203
|
-
`, true);
|
|
204
|
-
}
|
|
205
|
-
function writeOverlayFiles() {
|
|
206
|
-
(0, import_fs2.writeFileSync)(overlayFile, overlayHtml);
|
|
207
|
-
}
|
|
208
|
-
function clearOverlay() {
|
|
209
|
-
if (!overlayEnabled) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
overlayHtml = "";
|
|
213
|
-
writeOverlayFiles();
|
|
214
|
-
}
|
|
215
|
-
var indent = " ".repeat(4);
|
|
216
|
-
function logToOverlay(msg, error = false) {
|
|
217
|
-
if (!overlayEnabled) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (error) {
|
|
221
|
-
msg = `<span class="overlay-error">${msg}</span>`;
|
|
222
|
-
}
|
|
223
|
-
const msgHtml = msg.replace(/\n/g, "\n<br/>").replace(/\s{2}/g, indent);
|
|
224
|
-
if (overlayHtml) {
|
|
225
|
-
overlayHtml += `<br/>${msgHtml}`;
|
|
226
|
-
} else {
|
|
227
|
-
overlayHtml = `${msgHtml}`;
|
|
228
|
-
}
|
|
229
|
-
writeOverlayFiles();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// src/build/impl/build-once.ts
|
|
233
|
-
var import_fs4 = require("fs");
|
|
234
|
-
var import_promises3 = require("fs/promises");
|
|
235
|
-
var import_path4 = require("path");
|
|
236
|
-
var import_neverthrow2 = require("neverthrow");
|
|
237
|
-
|
|
238
|
-
// src/context/context.ts
|
|
239
|
-
var import_parse = require("@sdeverywhere/parse");
|
|
240
|
-
|
|
241
|
-
// src/context/spawn-child.ts
|
|
242
|
-
var import_cross_spawn = require("cross-spawn");
|
|
243
|
-
function spawnChild(cwd, command, args, abortSignal, opts) {
|
|
244
|
-
return new Promise((resolve, reject) => {
|
|
245
|
-
if (abortSignal?.aborted) {
|
|
246
|
-
reject(new Error("ABORT"));
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
let childProc;
|
|
250
|
-
const localLog = (s, err4 = false) => {
|
|
251
|
-
if (childProc === void 0) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
log(err4 ? "error" : "info", s);
|
|
255
|
-
};
|
|
256
|
-
const abortHandler = () => {
|
|
257
|
-
if (childProc) {
|
|
258
|
-
log("info", "Killing existing build process...");
|
|
259
|
-
childProc.kill("SIGKILL");
|
|
260
|
-
childProc = void 0;
|
|
261
|
-
}
|
|
262
|
-
reject(new Error("ABORT"));
|
|
263
|
-
};
|
|
264
|
-
abortSignal?.addEventListener("abort", abortHandler, { once: true });
|
|
265
|
-
const stdoutMessages = [];
|
|
266
|
-
const stderrMessages = [];
|
|
267
|
-
const logMessage = (msg, err4) => {
|
|
268
|
-
let includeMessage = true;
|
|
269
|
-
if (opts?.ignoredMessageFilter && msg.trim().startsWith(opts.ignoredMessageFilter)) {
|
|
270
|
-
includeMessage = false;
|
|
271
|
-
}
|
|
272
|
-
if (includeMessage) {
|
|
273
|
-
const lines = msg.trim().split("\n");
|
|
274
|
-
for (const line of lines) {
|
|
275
|
-
localLog(` ${line}`, err4);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
childProc = (0, import_cross_spawn.spawn)(command, args, {
|
|
280
|
-
cwd
|
|
281
|
-
});
|
|
282
|
-
childProc.stdout.on("data", (data) => {
|
|
283
|
-
const msg = data.toString();
|
|
284
|
-
if (opts?.captureOutput === true) {
|
|
285
|
-
stdoutMessages.push(msg);
|
|
286
|
-
}
|
|
287
|
-
if (opts?.logOutput !== false) {
|
|
288
|
-
logMessage(msg, false);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
childProc.stderr.on("data", (data) => {
|
|
292
|
-
const msg = data.toString();
|
|
293
|
-
if (opts?.captureOutput === true) {
|
|
294
|
-
stderrMessages.push(msg);
|
|
295
|
-
}
|
|
296
|
-
if (opts?.logOutput !== false) {
|
|
297
|
-
logMessage(msg, true);
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
childProc.on("error", (err4) => {
|
|
301
|
-
localLog(`Process error: ${err4}`, true);
|
|
302
|
-
});
|
|
303
|
-
childProc.on("close", (code, signal) => {
|
|
304
|
-
abortSignal?.removeEventListener("abort", abortHandler);
|
|
305
|
-
childProc = void 0;
|
|
306
|
-
if (signal) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
const processOutput = {
|
|
310
|
-
exitCode: code,
|
|
311
|
-
stdoutMessages,
|
|
312
|
-
stderrMessages
|
|
313
|
-
};
|
|
314
|
-
if (code === 0) {
|
|
315
|
-
resolve(processOutput);
|
|
316
|
-
} else if (!signal) {
|
|
317
|
-
if (opts?.ignoreError === true) {
|
|
318
|
-
resolve(processOutput);
|
|
319
|
-
} else {
|
|
320
|
-
reject(new Error(`Child process failed (code=${code})`));
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// src/context/context.ts
|
|
328
|
-
var BuildContext = class {
|
|
329
|
-
/**
|
|
330
|
-
* @param config The resolved configuration.
|
|
331
|
-
* @hidden
|
|
332
|
-
*/
|
|
333
|
-
constructor(config, stagedFiles, abortSignal) {
|
|
334
|
-
this.config = config;
|
|
335
|
-
this.stagedFiles = stagedFiles;
|
|
336
|
-
this.abortSignal = abortSignal;
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Log a message to the console and/or the in-browser overlay panel.
|
|
340
|
-
*
|
|
341
|
-
* @param level The log level (verbose, info, error).
|
|
342
|
-
* @param msg The message.
|
|
343
|
-
*/
|
|
344
|
-
log(level, msg) {
|
|
345
|
-
log(level, msg);
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Prepare for writing a file to the staged directory.
|
|
349
|
-
*
|
|
350
|
-
* This will add the path to the array of tracked files and will create the
|
|
351
|
-
* staged directory if needed.
|
|
352
|
-
*
|
|
353
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
354
|
-
* the file will be written (this must be a relative path).
|
|
355
|
-
* @param srcFile The name of the file as written to the `staged` directory.
|
|
356
|
-
* @param dstDir The absolute path to the destination directory where the staged
|
|
357
|
-
* file will be copied when the build has completed.
|
|
358
|
-
* @param dstFile The name of the file as written to the destination directory.
|
|
359
|
-
* @return The absolute path to the staged file.
|
|
360
|
-
*/
|
|
361
|
-
prepareStagedFile(srcDir, srcFile, dstDir, dstFile) {
|
|
362
|
-
return this.stagedFiles.prepareStagedFile(srcDir, srcFile, dstDir, dstFile);
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Write a file to the staged directory.
|
|
366
|
-
*
|
|
367
|
-
* This file will be copied (along with other staged files) into the destination
|
|
368
|
-
* directory only after the build process has completed. Copying all staged files
|
|
369
|
-
* at once helps improve the local development experience by making it so that
|
|
370
|
-
* live reloading tools only need to refresh once instead of every time a build
|
|
371
|
-
* file is written.
|
|
372
|
-
*
|
|
373
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
374
|
-
* the file will be written (this must be a relative path).
|
|
375
|
-
* @param dstDir The absolute path to the destination directory where the staged
|
|
376
|
-
* file will be copied when the build has completed.
|
|
377
|
-
* @param filename The name of the file.
|
|
378
|
-
* @param content The file content.
|
|
379
|
-
*/
|
|
380
|
-
writeStagedFile(srcDir, dstDir, filename, content) {
|
|
381
|
-
this.stagedFiles.writeStagedFile(srcDir, dstDir, filename, content);
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Spawn a child process that runs the given command.
|
|
385
|
-
*
|
|
386
|
-
* @param cwd The directory in which the command will be executed.
|
|
387
|
-
* @param command The command to execute.
|
|
388
|
-
* @param args The arguments to pass to the command.
|
|
389
|
-
* @param opts Additional options to configure the process.
|
|
390
|
-
* @returns The output of the process.
|
|
391
|
-
*/
|
|
392
|
-
spawnChild(cwd, command, args, opts) {
|
|
393
|
-
return spawnChild(cwd, command, args, this.abortSignal, opts);
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Format a (subscripted or non-subscripted) model variable name into a canonical
|
|
397
|
-
* identifier (with special characters converted to underscore, and subscript/dimension
|
|
398
|
-
* parts separated by commas).
|
|
399
|
-
*
|
|
400
|
-
* @param name The name of the variable in the source model, e.g., `Variable name[DimA, B2]`.
|
|
401
|
-
* @returns The canonical identifier for the given name, e.g., `_variable_name[_dima,_b2]`.
|
|
402
|
-
*/
|
|
403
|
-
canonicalVarId(name) {
|
|
404
|
-
return (0, import_parse.canonicalVarId)(name);
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
|
|
408
|
-
// src/context/staged-files.ts
|
|
409
|
-
var import_fs3 = require("fs");
|
|
410
|
-
var import_path2 = require("path");
|
|
411
|
-
var StagedFiles = class {
|
|
412
|
-
constructor(prepDir) {
|
|
413
|
-
this.stagedFiles = [];
|
|
414
|
-
this.baseStagedDir = (0, import_path2.join)(prepDir, "staged");
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* Prepare for writing a file to the staged directory.
|
|
418
|
-
*
|
|
419
|
-
* This will add the path to the array of tracked files and will create the
|
|
420
|
-
* staged directory if needed.
|
|
421
|
-
*
|
|
422
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
423
|
-
* the file will be written (this must be a relative path).
|
|
424
|
-
* @param srcFile The name of the file as written to the `staged` directory.
|
|
425
|
-
* @param dstDir The absolute path to the destination directory where the staged
|
|
426
|
-
* file will be copied when the build has completed.
|
|
427
|
-
* @param dstFile The name of the file as written to the destination directory.
|
|
428
|
-
* @return The absolute path to the staged file.
|
|
429
|
-
*/
|
|
430
|
-
prepareStagedFile(srcDir, srcFile, dstDir, dstFile) {
|
|
431
|
-
const stagedFile = {
|
|
432
|
-
srcDir,
|
|
433
|
-
srcFile,
|
|
434
|
-
dstDir,
|
|
435
|
-
dstFile
|
|
436
|
-
};
|
|
437
|
-
if (this.stagedFiles.indexOf(stagedFile) < 0) {
|
|
438
|
-
this.stagedFiles.push(stagedFile);
|
|
439
|
-
}
|
|
440
|
-
const stagedDir = (0, import_path2.join)(this.baseStagedDir, srcDir);
|
|
441
|
-
if (!(0, import_fs3.existsSync)(stagedDir)) {
|
|
442
|
-
(0, import_fs3.mkdirSync)(stagedDir, { recursive: true });
|
|
443
|
-
}
|
|
444
|
-
return (0, import_path2.join)(stagedDir, srcFile);
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Write a file to the staged directory.
|
|
448
|
-
*
|
|
449
|
-
* This file will be copied (along with other staged files) into the destination
|
|
450
|
-
* directory only after the build process has completed. Copying all staged files
|
|
451
|
-
* at once helps improve the local development experience by making it so that
|
|
452
|
-
* live reloading tools only need to refresh once instead of every time a build
|
|
453
|
-
* file is written.
|
|
454
|
-
*
|
|
455
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
456
|
-
* the file will be written (this must be a relative path).
|
|
457
|
-
* @param dstDir The absolute path to the destination directory where the staged
|
|
458
|
-
* file will be copied when the build has completed.
|
|
459
|
-
* @param filename The name of the file.
|
|
460
|
-
* @param content The file content.
|
|
461
|
-
*/
|
|
462
|
-
writeStagedFile(srcDir, dstDir, filename, content) {
|
|
463
|
-
const stagedFilePath = this.prepareStagedFile(srcDir, filename, dstDir, filename);
|
|
464
|
-
(0, import_fs3.writeFileSync)(stagedFilePath, content);
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Return the absolute path to the staged file for the given source directory and file name.
|
|
468
|
-
*
|
|
469
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
470
|
-
* the file would be written initially (this must be a relative path).
|
|
471
|
-
* @param srcFile The name of the file.
|
|
472
|
-
*/
|
|
473
|
-
getStagedFilePath(srcDir, srcFile) {
|
|
474
|
-
return (0, import_path2.join)(this.baseStagedDir, srcDir, srcFile);
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Return true if the staged file exists for the given source directory and file name.
|
|
478
|
-
*
|
|
479
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
480
|
-
* the file would be written initially (this must be a relative path).
|
|
481
|
-
* @param srcFile The name of the file.
|
|
482
|
-
*/
|
|
483
|
-
stagedFileExists(srcDir, srcFile) {
|
|
484
|
-
const fullSrcPath = this.getStagedFilePath(srcDir, srcFile);
|
|
485
|
-
return (0, import_fs3.existsSync)(fullSrcPath);
|
|
486
|
-
}
|
|
487
|
-
/**
|
|
488
|
-
* Return true if the destination file exists for the given source directory and file name.
|
|
489
|
-
*
|
|
490
|
-
* @param srcDir The directory underneath the configured `staged` directory where
|
|
491
|
-
* the file would be written initially (this must be a relative path).
|
|
492
|
-
* @param srcFile The name of the file.
|
|
493
|
-
*/
|
|
494
|
-
destinationFileExists(srcDir, srcFile) {
|
|
495
|
-
const f = this.stagedFiles.find((f2) => f2.srcDir === srcDir && f2.srcFile === srcFile);
|
|
496
|
-
if (f === void 0) {
|
|
497
|
-
return false;
|
|
498
|
-
}
|
|
499
|
-
const fullDstPath = (0, import_path2.join)(f.dstDir, f.dstFile);
|
|
500
|
-
return (0, import_fs3.existsSync)(fullDstPath);
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Copy staged files to their destination; this will only copy the staged
|
|
504
|
-
* files if they are different than the existing destination files. We
|
|
505
|
-
* copy the files in a batch like this so that hot module reload is only
|
|
506
|
-
* triggered once at the end of the whole build process.
|
|
507
|
-
*/
|
|
508
|
-
copyChangedFiles() {
|
|
509
|
-
log("info", "Copying changed files into place...");
|
|
510
|
-
for (const f of this.stagedFiles) {
|
|
511
|
-
this.copyStagedFile(f);
|
|
512
|
-
}
|
|
513
|
-
log("info", "Done copying files");
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Copy a file from the `staged` directory to its destination. If the file already
|
|
517
|
-
* exists in the destination directory and has the same contents as the source file,
|
|
518
|
-
* the file will not be copied and this function will return false.
|
|
519
|
-
*
|
|
520
|
-
* @param f The staged file entry.
|
|
521
|
-
*/
|
|
522
|
-
copyStagedFile(f) {
|
|
523
|
-
if (!(0, import_fs3.existsSync)(f.dstDir)) {
|
|
524
|
-
(0, import_fs3.mkdirSync)(f.dstDir, { recursive: true });
|
|
525
|
-
}
|
|
526
|
-
const fullSrcPath = this.getStagedFilePath(f.srcDir, f.srcFile);
|
|
527
|
-
const fullDstPath = (0, import_path2.join)(f.dstDir, f.dstFile);
|
|
528
|
-
const needsCopy = filesDiffer(fullSrcPath, fullDstPath);
|
|
529
|
-
if (needsCopy) {
|
|
530
|
-
log("verbose", ` Copying ${f.srcFile} to ${fullDstPath}`);
|
|
531
|
-
(0, import_fs3.copyFileSync)(fullSrcPath, fullDstPath);
|
|
532
|
-
}
|
|
533
|
-
return needsCopy;
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
function filesDiffer(aPath, bPath) {
|
|
537
|
-
if ((0, import_fs3.existsSync)(aPath) && (0, import_fs3.existsSync)(bPath)) {
|
|
538
|
-
const aSize = (0, import_fs3.statSync)(aPath).size;
|
|
539
|
-
const bSize = (0, import_fs3.statSync)(bPath).size;
|
|
540
|
-
if (aSize !== bSize) {
|
|
541
|
-
return true;
|
|
542
|
-
} else {
|
|
543
|
-
const aBuf = (0, import_fs3.readFileSync)(aPath);
|
|
544
|
-
const bBuf = (0, import_fs3.readFileSync)(bPath);
|
|
545
|
-
return !aBuf.equals(bBuf);
|
|
546
|
-
}
|
|
547
|
-
} else {
|
|
548
|
-
return true;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// src/build/impl/gen-model.ts
|
|
553
|
-
var import_promises = require("fs/promises");
|
|
554
|
-
var import_path3 = require("path");
|
|
555
|
-
async function generateModel(context, plugins) {
|
|
556
|
-
const config = context.config;
|
|
557
|
-
if (config.modelFiles.length === 0) {
|
|
558
|
-
log("info", "No model input files specified, skipping model generation steps");
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
log("info", "Generating model...");
|
|
562
|
-
const t0 = performance.now();
|
|
563
|
-
const prepDir = config.prepDir;
|
|
564
|
-
const sdeCmdPath = config.sdeCmdPath;
|
|
565
|
-
for (const plugin of plugins) {
|
|
566
|
-
if (plugin.preProcessMdl) {
|
|
567
|
-
await plugin.preProcessMdl(context);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
if (config.modelFiles.length === 1) {
|
|
571
|
-
await preprocessMdl(context, sdeCmdPath, prepDir, config.modelFiles[0]);
|
|
572
|
-
} else {
|
|
573
|
-
await flattenMdls(context, sdeCmdPath, prepDir, config.modelFiles);
|
|
574
|
-
}
|
|
575
|
-
for (const plugin of plugins) {
|
|
576
|
-
if (plugin.postProcessMdl) {
|
|
577
|
-
const mdlPath = (0, import_path3.join)(prepDir, "processed.mdl");
|
|
578
|
-
let mdlContent = await (0, import_promises.readFile)(mdlPath, "utf8");
|
|
579
|
-
mdlContent = await plugin.postProcessMdl(context, mdlContent);
|
|
580
|
-
await (0, import_promises.writeFile)(mdlPath, mdlContent);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
for (const plugin of plugins) {
|
|
584
|
-
if (plugin.preGenerateCode) {
|
|
585
|
-
await plugin.preGenerateCode(context, config.genFormat);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
await generateCode(context, config.sdeDir, sdeCmdPath, prepDir);
|
|
589
|
-
const generatedCodeFile = `processed.${config.genFormat}`;
|
|
590
|
-
const generatedCodePath = (0, import_path3.join)(prepDir, "build", generatedCodeFile);
|
|
591
|
-
for (const plugin of plugins) {
|
|
592
|
-
if (plugin.postGenerateCode) {
|
|
593
|
-
let generatedCodeContent = await (0, import_promises.readFile)(generatedCodePath, "utf8");
|
|
594
|
-
generatedCodeContent = await plugin.postGenerateCode(context, config.genFormat, generatedCodeContent);
|
|
595
|
-
await (0, import_promises.writeFile)(generatedCodePath, generatedCodeContent);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
if (config.genFormat === "js") {
|
|
599
|
-
const outputJsFile = "generated-model.js";
|
|
600
|
-
const stagedOutputJsPath = context.prepareStagedFile("model", outputJsFile, prepDir, outputJsFile);
|
|
601
|
-
await (0, import_promises.copyFile)(generatedCodePath, stagedOutputJsPath);
|
|
602
|
-
}
|
|
603
|
-
if (config.outListingFile) {
|
|
604
|
-
const srcListingJsonPath = (0, import_path3.join)(prepDir, "build", "processed.json");
|
|
605
|
-
const stagedDir = "model";
|
|
606
|
-
const stagedFile = "listing.json";
|
|
607
|
-
const dstDir = (0, import_path3.dirname)(config.outListingFile);
|
|
608
|
-
const dstFile = (0, import_path3.basename)(config.outListingFile);
|
|
609
|
-
const stagedListingJsonPath = context.prepareStagedFile(stagedDir, stagedFile, dstDir, dstFile);
|
|
610
|
-
await (0, import_promises.copyFile)(srcListingJsonPath, stagedListingJsonPath);
|
|
611
|
-
}
|
|
612
|
-
const t1 = performance.now();
|
|
613
|
-
const elapsed = ((t1 - t0) / 1e3).toFixed(1);
|
|
614
|
-
log("info", `Done generating model (${elapsed}s)`);
|
|
615
|
-
}
|
|
616
|
-
async function preprocessMdl(context, sdeCmdPath, prepDir, modelFile) {
|
|
617
|
-
log("verbose", " Preprocessing mdl file");
|
|
618
|
-
await (0, import_promises.copyFile)(modelFile, (0, import_path3.join)(prepDir, "processed.mdl"));
|
|
619
|
-
const command = sdeCmdPath;
|
|
620
|
-
const args = ["generate", "--preprocess", "processed.mdl"];
|
|
621
|
-
const ppOutput = await context.spawnChild(prepDir, command, args, {
|
|
622
|
-
// The default error message from `spawnChild` is not very informative, so the
|
|
623
|
-
// following allows us to throw our own error
|
|
624
|
-
ignoreError: true
|
|
625
|
-
});
|
|
626
|
-
if (ppOutput.exitCode !== 0) {
|
|
627
|
-
throw new Error(`Failed to preprocess mdl file: 'sde generate' command failed (code=${ppOutput.exitCode})`);
|
|
628
|
-
}
|
|
629
|
-
await (0, import_promises.copyFile)((0, import_path3.join)(prepDir, "build", "processed.mdl"), (0, import_path3.join)(prepDir, "processed.mdl"));
|
|
630
|
-
}
|
|
631
|
-
async function flattenMdls(context, sdeCmdPath, prepDir, modelFiles) {
|
|
632
|
-
log("verbose", " Flattening and preprocessing mdl files");
|
|
633
|
-
const command = sdeCmdPath;
|
|
634
|
-
const args = [];
|
|
635
|
-
args.push("flatten");
|
|
636
|
-
args.push("processed.mdl");
|
|
637
|
-
args.push("--inputs");
|
|
638
|
-
for (const path of modelFiles) {
|
|
639
|
-
args.push(path);
|
|
640
|
-
}
|
|
641
|
-
const output = await context.spawnChild(prepDir, command, args, {
|
|
642
|
-
logOutput: false,
|
|
643
|
-
captureOutput: true,
|
|
644
|
-
ignoreError: true
|
|
645
|
-
});
|
|
646
|
-
let flattenErrors = false;
|
|
647
|
-
for (const msg of output.stderrMessages) {
|
|
648
|
-
if (msg.includes("ERROR")) {
|
|
649
|
-
flattenErrors = true;
|
|
650
|
-
break;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
if (flattenErrors) {
|
|
654
|
-
log("error", "There were errors reported when flattening the model:");
|
|
655
|
-
for (const msg of output.stderrMessages) {
|
|
656
|
-
const lines = msg.split("\n");
|
|
657
|
-
for (const line of lines) {
|
|
658
|
-
log("error", ` ${line}`);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
throw new Error(`Failed to flatten mdl files: 'sde flatten' command failed (code=${output.exitCode})`);
|
|
662
|
-
} else if (output.exitCode !== 0) {
|
|
663
|
-
throw new Error(`Failed to flatten mdl files: 'sde flatten' command failed (code=${output.exitCode})`);
|
|
664
|
-
}
|
|
665
|
-
await (0, import_promises.copyFile)((0, import_path3.join)(prepDir, "build", "processed.mdl"), (0, import_path3.join)(prepDir, "processed.mdl"));
|
|
666
|
-
}
|
|
667
|
-
async function generateCode(context, sdeDir, sdeCmdPath, prepDir) {
|
|
668
|
-
const genFormat = context.config.genFormat;
|
|
669
|
-
const genFormatName = genFormat.toUpperCase();
|
|
670
|
-
log("verbose", ` Generating ${genFormatName} code`);
|
|
671
|
-
const dataDir = (0, import_path3.dirname)(context.config.modelFiles[0]);
|
|
672
|
-
const command = sdeCmdPath;
|
|
673
|
-
const outFormat = `--outformat=${genFormat}`;
|
|
674
|
-
const genCmdArgs = ["generate", outFormat, "--list", "--spec", "spec.json", "--datadir", dataDir, "processed"];
|
|
675
|
-
const genCmdOutput = await context.spawnChild(prepDir, command, genCmdArgs, {
|
|
676
|
-
// By default, ignore lines that start with "WARNING: Data for" since these are often harmless
|
|
677
|
-
// TODO: Don't filter by default, but make it configurable
|
|
678
|
-
// ignoredMessageFilter: 'WARNING: Data for'
|
|
679
|
-
// The default error message from `spawnChild` is not very informative, so the
|
|
680
|
-
// following allows us to throw our own error
|
|
681
|
-
ignoreError: true
|
|
682
|
-
});
|
|
683
|
-
if (genCmdOutput.exitCode !== 0) {
|
|
684
|
-
throw new Error(
|
|
685
|
-
`Failed to generate ${genFormatName} code: 'sde generate' command failed (code=${genCmdOutput.exitCode})`
|
|
686
|
-
);
|
|
687
|
-
}
|
|
688
|
-
if (genFormat === "c") {
|
|
689
|
-
const buildDir = (0, import_path3.join)(prepDir, "build");
|
|
690
|
-
const sdeCDir = (0, import_path3.join)(sdeDir, "src", "c");
|
|
691
|
-
const files = await (0, import_promises.readdir)(sdeCDir);
|
|
692
|
-
const copyOps = [];
|
|
693
|
-
for (const file of files) {
|
|
694
|
-
if (file.endsWith(".c") || file.endsWith(".h")) {
|
|
695
|
-
copyOps.push((0, import_promises.copyFile)((0, import_path3.join)(sdeCDir, file), (0, import_path3.join)(buildDir, file)));
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
await Promise.all(copyOps);
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
// src/build/impl/hash-files.ts
|
|
703
|
-
var import_node_crypto = require("crypto");
|
|
704
|
-
var import_node_fs = require("fs");
|
|
705
|
-
var import_node_path = require("path");
|
|
706
|
-
var import_promises2 = require("stream/promises");
|
|
707
|
-
var import_tinyglobby = require("tinyglobby");
|
|
708
|
-
async function computeInputFilesHash(config) {
|
|
709
|
-
const inputFiles = [];
|
|
710
|
-
const specFile = (0, import_node_path.join)(config.prepDir, "spec.json");
|
|
711
|
-
inputFiles.push(specFile);
|
|
712
|
-
if (config.modelInputPaths && config.modelInputPaths.length > 0) {
|
|
713
|
-
for (const globPath of config.modelInputPaths) {
|
|
714
|
-
const paths = await (0, import_tinyglobby.glob)(globPath, {
|
|
715
|
-
cwd: config.rootDir,
|
|
716
|
-
absolute: true,
|
|
717
|
-
onlyFiles: true
|
|
718
|
-
});
|
|
719
|
-
inputFiles.push(...paths);
|
|
720
|
-
}
|
|
721
|
-
} else {
|
|
722
|
-
inputFiles.push(...config.modelFiles);
|
|
723
|
-
}
|
|
724
|
-
let hash = "";
|
|
725
|
-
for (const inputFile of inputFiles) {
|
|
726
|
-
hash += await hashFile(inputFile);
|
|
727
|
-
}
|
|
728
|
-
return hash;
|
|
729
|
-
}
|
|
730
|
-
async function hashFile(file) {
|
|
731
|
-
const hash = (0, import_node_crypto.createHash)("sha1");
|
|
732
|
-
hash.update((0, import_node_path.basename)(file));
|
|
733
|
-
await (0, import_promises2.pipeline)((0, import_node_fs.createReadStream)(file), hash);
|
|
734
|
-
return hash.digest("base64");
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// src/build/impl/build-once.ts
|
|
738
|
-
async function buildOnce(config, userConfig, plugins, options) {
|
|
739
|
-
const stagedFiles = new StagedFiles(config.prepDir);
|
|
740
|
-
const context = new BuildContext(config, stagedFiles, options.abortSignal);
|
|
741
|
-
const modelHashPath = (0, import_path4.join)(config.prepDir, "model-hash.txt");
|
|
742
|
-
let succeeded = true;
|
|
743
|
-
try {
|
|
744
|
-
const userModelSpec = await userConfig.modelSpec(context);
|
|
745
|
-
if (userModelSpec === void 0) {
|
|
746
|
-
return (0, import_neverthrow2.err)(new Error("The model spec must be defined"));
|
|
747
|
-
}
|
|
748
|
-
const modelSpec = resolveModelSpec(userModelSpec);
|
|
749
|
-
for (const plugin of plugins) {
|
|
750
|
-
if (plugin.preGenerate) {
|
|
751
|
-
await plugin.preGenerate(context, modelSpec);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
const specJson = {
|
|
755
|
-
inputVarNames: modelSpec.inputVarNames,
|
|
756
|
-
outputVarNames: modelSpec.outputVarNames,
|
|
757
|
-
datFiles: modelSpec.datFiles,
|
|
758
|
-
bundleListing: modelSpec.bundleListing,
|
|
759
|
-
customConstants: modelSpec.customConstants,
|
|
760
|
-
customLookups: modelSpec.customLookups,
|
|
761
|
-
customOutputs: modelSpec.customOutputs,
|
|
762
|
-
directData: modelSpec.directData,
|
|
763
|
-
dimensionFamilies: modelSpec.dimensionFamilies,
|
|
764
|
-
specialSeparationDims: modelSpec.specialSeparationDims,
|
|
765
|
-
separateAllVarsWithDims: modelSpec.separateAllVarsWithDims
|
|
766
|
-
};
|
|
767
|
-
const specPath = (0, import_path4.join)(config.prepDir, "spec.json");
|
|
768
|
-
await (0, import_promises3.writeFile)(specPath, JSON.stringify(specJson, null, 2));
|
|
769
|
-
let previousModelHash;
|
|
770
|
-
if ((0, import_fs4.existsSync)(modelHashPath)) {
|
|
771
|
-
previousModelHash = (0, import_fs4.readFileSync)(modelHashPath, "utf8");
|
|
772
|
-
} else {
|
|
773
|
-
previousModelHash = "NONE";
|
|
774
|
-
}
|
|
775
|
-
const inputFilesHash = await computeInputFilesHash(config);
|
|
776
|
-
let needModelGen;
|
|
777
|
-
if (options.forceModelGen === true) {
|
|
778
|
-
needModelGen = true;
|
|
779
|
-
} else {
|
|
780
|
-
const hashMismatch = inputFilesHash !== previousModelHash;
|
|
781
|
-
needModelGen = hashMismatch;
|
|
782
|
-
}
|
|
783
|
-
if (needModelGen) {
|
|
784
|
-
await generateModel(context, plugins);
|
|
785
|
-
(0, import_fs4.writeFileSync)(modelHashPath, inputFilesHash);
|
|
786
|
-
} else {
|
|
787
|
-
log("info", "Skipping model code generation; already up-to-date");
|
|
788
|
-
}
|
|
789
|
-
for (const plugin of plugins) {
|
|
790
|
-
if (plugin.postGenerate) {
|
|
791
|
-
const pluginSucceeded = await plugin.postGenerate(context, modelSpec);
|
|
792
|
-
if (!pluginSucceeded) {
|
|
793
|
-
succeeded = false;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
stagedFiles.copyChangedFiles();
|
|
798
|
-
for (const plugin of plugins) {
|
|
799
|
-
if (plugin.postBuild) {
|
|
800
|
-
const pluginSucceeded = await plugin.postBuild(context, modelSpec);
|
|
801
|
-
if (!pluginSucceeded) {
|
|
802
|
-
succeeded = false;
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
if (config.mode === "development") {
|
|
807
|
-
log("info", "Waiting for changes...\n");
|
|
808
|
-
clearOverlay();
|
|
809
|
-
}
|
|
810
|
-
} catch (e) {
|
|
811
|
-
if (e.message !== "ABORT") {
|
|
812
|
-
(0, import_fs4.writeFileSync)(modelHashPath, "");
|
|
813
|
-
return (0, import_neverthrow2.err)(e);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
return (0, import_neverthrow2.ok)(succeeded);
|
|
817
|
-
}
|
|
818
|
-
function resolveModelSpec(userModelSpec) {
|
|
819
|
-
const { options, ...configuredProps } = userModelSpec;
|
|
820
|
-
const modelSpec = { ...options, ...configuredProps };
|
|
821
|
-
let inputVarNames;
|
|
822
|
-
let inputSpecs;
|
|
823
|
-
if (modelSpec.inputs.length > 0) {
|
|
824
|
-
const item = modelSpec.inputs[0];
|
|
825
|
-
if (typeof item === "string") {
|
|
826
|
-
inputVarNames = modelSpec.inputs;
|
|
827
|
-
inputSpecs = inputVarNames.map((varName) => {
|
|
828
|
-
return {
|
|
829
|
-
varName
|
|
830
|
-
};
|
|
831
|
-
});
|
|
832
|
-
} else {
|
|
833
|
-
inputSpecs = modelSpec.inputs;
|
|
834
|
-
inputVarNames = inputSpecs.map((spec) => spec.varName);
|
|
835
|
-
}
|
|
836
|
-
} else {
|
|
837
|
-
inputVarNames = [];
|
|
838
|
-
inputSpecs = [];
|
|
839
|
-
}
|
|
840
|
-
let outputVarNames;
|
|
841
|
-
let outputSpecs;
|
|
842
|
-
if (modelSpec.outputs.length > 0) {
|
|
843
|
-
const item = modelSpec.outputs[0];
|
|
844
|
-
if (typeof item === "string") {
|
|
845
|
-
outputVarNames = modelSpec.outputs;
|
|
846
|
-
outputSpecs = outputVarNames.map((varName) => {
|
|
847
|
-
return {
|
|
848
|
-
varName
|
|
849
|
-
};
|
|
850
|
-
});
|
|
851
|
-
} else {
|
|
852
|
-
outputSpecs = modelSpec.outputs;
|
|
853
|
-
outputVarNames = outputSpecs.map((spec) => spec.varName);
|
|
854
|
-
}
|
|
855
|
-
} else {
|
|
856
|
-
outputVarNames = [];
|
|
857
|
-
outputSpecs = [];
|
|
858
|
-
}
|
|
859
|
-
let customConstants;
|
|
860
|
-
if (modelSpec.customConstants !== void 0) {
|
|
861
|
-
customConstants = modelSpec.customConstants;
|
|
862
|
-
} else {
|
|
863
|
-
customConstants = false;
|
|
864
|
-
}
|
|
865
|
-
let customLookups;
|
|
866
|
-
if (modelSpec.customLookups !== void 0) {
|
|
867
|
-
customLookups = modelSpec.customLookups;
|
|
868
|
-
} else {
|
|
869
|
-
customLookups = false;
|
|
870
|
-
}
|
|
871
|
-
let customOutputs;
|
|
872
|
-
if (modelSpec.customOutputs !== void 0) {
|
|
873
|
-
customOutputs = modelSpec.customOutputs;
|
|
874
|
-
} else {
|
|
875
|
-
customOutputs = false;
|
|
876
|
-
}
|
|
877
|
-
return {
|
|
878
|
-
// Carry through the properties (for example, `directData` and `specialSeparationDims`)
|
|
879
|
-
// that are shared with the compile package and don't need to be resolved here
|
|
880
|
-
...modelSpec,
|
|
881
|
-
inputVarNames,
|
|
882
|
-
inputs: inputSpecs,
|
|
883
|
-
outputVarNames,
|
|
884
|
-
outputs: outputSpecs,
|
|
885
|
-
datFiles: modelSpec.datFiles || [],
|
|
886
|
-
bundleListing: modelSpec.bundleListing === true,
|
|
887
|
-
customConstants,
|
|
888
|
-
customLookups,
|
|
889
|
-
customOutputs
|
|
890
|
-
};
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
// src/build/impl/watch.ts
|
|
894
|
-
var import_path5 = require("path");
|
|
895
|
-
|
|
896
|
-
// src/build/impl/watch-paths.ts
|
|
897
|
-
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
898
|
-
var import_tinyglobby2 = require("tinyglobby");
|
|
899
|
-
function resolveWatchPaths(patterns, cwd) {
|
|
900
|
-
const resolvedPaths = [];
|
|
901
|
-
const regularPaths = [];
|
|
902
|
-
const globPatterns = [];
|
|
903
|
-
for (const pattern of patterns) {
|
|
904
|
-
if ((0, import_tinyglobby2.isDynamicPattern)(pattern)) {
|
|
905
|
-
globPatterns.push(pattern);
|
|
906
|
-
} else {
|
|
907
|
-
regularPaths.push(pattern);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
resolvedPaths.push(...regularPaths);
|
|
911
|
-
if (globPatterns.length > 0) {
|
|
912
|
-
const paths = (0, import_tinyglobby2.globSync)(globPatterns, {
|
|
913
|
-
// Watch paths are resolved relative to the provided cwd
|
|
914
|
-
cwd,
|
|
915
|
-
// Resolve to absolute paths
|
|
916
|
-
absolute: true
|
|
917
|
-
});
|
|
918
|
-
resolvedPaths.push(...paths);
|
|
919
|
-
}
|
|
920
|
-
return resolvedPaths;
|
|
921
|
-
}
|
|
922
|
-
function watchPaths(patterns, cwd, onChange, onReady) {
|
|
923
|
-
const resolvedPathsToWatch = resolveWatchPaths(patterns, cwd);
|
|
924
|
-
const watcher = import_chokidar.default.watch(resolvedPathsToWatch, {
|
|
925
|
-
// Watch paths are resolved relative to the provided cwd
|
|
926
|
-
cwd,
|
|
927
|
-
// Ignore the initial add events when the watcher is created
|
|
928
|
-
ignoreInitial: true,
|
|
929
|
-
// Include a delay, otherwise on macOS we sometimes get multiple
|
|
930
|
-
// change events when the file is saved just once
|
|
931
|
-
awaitWriteFinish: {
|
|
932
|
-
stabilityThreshold: 200
|
|
933
|
-
}
|
|
934
|
-
});
|
|
935
|
-
watcher.on("change", (path) => {
|
|
936
|
-
onChange(path);
|
|
937
|
-
});
|
|
938
|
-
watcher.on("add", (path) => {
|
|
939
|
-
onChange(path);
|
|
940
|
-
});
|
|
941
|
-
watcher.on("unlink", (path) => {
|
|
942
|
-
onChange(path);
|
|
943
|
-
});
|
|
944
|
-
if (onReady) {
|
|
945
|
-
watcher.on("ready", onReady);
|
|
946
|
-
}
|
|
947
|
-
return () => {
|
|
948
|
-
watcher.close();
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
// src/build/impl/watch.ts
|
|
953
|
-
var BuildState = class {
|
|
954
|
-
constructor() {
|
|
955
|
-
this.abortController = new AbortController();
|
|
956
|
-
}
|
|
957
|
-
};
|
|
958
|
-
function watch(config, userConfig, plugins) {
|
|
959
|
-
const delay = 150;
|
|
960
|
-
const changedPaths = /* @__PURE__ */ new Set();
|
|
961
|
-
let currentBuildState;
|
|
962
|
-
function performBuild() {
|
|
963
|
-
clearOverlay();
|
|
964
|
-
for (const path of changedPaths) {
|
|
965
|
-
log("info", `Input file ${(0, import_path5.basename)(path)} has been changed`);
|
|
966
|
-
}
|
|
967
|
-
changedPaths.clear();
|
|
968
|
-
if (currentBuildState) {
|
|
969
|
-
currentBuildState.abortController.abort();
|
|
970
|
-
currentBuildState = void 0;
|
|
971
|
-
}
|
|
972
|
-
currentBuildState = new BuildState();
|
|
973
|
-
const buildOptions = {
|
|
974
|
-
abortSignal: currentBuildState.abortController.signal
|
|
975
|
-
};
|
|
976
|
-
buildOnce(config, userConfig, plugins, buildOptions).then((result) => {
|
|
977
|
-
if (result.isErr()) {
|
|
978
|
-
logError(result.error);
|
|
979
|
-
}
|
|
980
|
-
}).catch((e) => {
|
|
981
|
-
logError(e);
|
|
982
|
-
}).finally(() => {
|
|
983
|
-
currentBuildState = void 0;
|
|
984
|
-
});
|
|
985
|
-
}
|
|
986
|
-
function scheduleBuild(changedPath) {
|
|
987
|
-
const schedule = changedPaths.size === 0;
|
|
988
|
-
changedPaths.add(changedPath);
|
|
989
|
-
if (schedule) {
|
|
990
|
-
setTimeout(() => {
|
|
991
|
-
performBuild();
|
|
992
|
-
}, delay);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
let watchPatterns;
|
|
996
|
-
if (config.watchPaths && config.watchPaths.length > 0) {
|
|
997
|
-
watchPatterns = config.watchPaths;
|
|
998
|
-
} else {
|
|
999
|
-
watchPatterns = config.modelFiles;
|
|
1000
|
-
}
|
|
1001
|
-
watchPaths(watchPatterns, config.rootDir, (path) => {
|
|
1002
|
-
scheduleBuild(path);
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
// src/build/build.ts
|
|
1007
|
-
async function build(mode, options) {
|
|
1008
|
-
const configResult = await loadConfig(mode, options.config, options.sdeDir, options.sdeCmdPath);
|
|
1009
|
-
if (configResult.isErr()) {
|
|
1010
|
-
return (0, import_neverthrow3.err)(configResult.error);
|
|
1011
|
-
}
|
|
1012
|
-
const { userConfig, resolvedConfig } = configResult.value;
|
|
1013
|
-
if (options.logLevels !== void 0) {
|
|
1014
|
-
setActiveLevels(options.logLevels);
|
|
1015
|
-
}
|
|
1016
|
-
const messagesPath = (0, import_path6.join)(resolvedConfig.prepDir, "messages.html");
|
|
1017
|
-
const overlayEnabled2 = mode === "development";
|
|
1018
|
-
setOverlayFile(messagesPath, overlayEnabled2);
|
|
1019
|
-
try {
|
|
1020
|
-
const plugins = userConfig.plugins || [];
|
|
1021
|
-
for (const plugin of plugins) {
|
|
1022
|
-
if (plugin.init) {
|
|
1023
|
-
await plugin.init(resolvedConfig);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
if (mode === "development") {
|
|
1027
|
-
const buildResult = await buildOnce(resolvedConfig, userConfig, plugins, {});
|
|
1028
|
-
if (buildResult.isErr()) {
|
|
1029
|
-
return (0, import_neverthrow3.err)(buildResult.error);
|
|
1030
|
-
}
|
|
1031
|
-
for (const plugin of plugins) {
|
|
1032
|
-
if (plugin.watch) {
|
|
1033
|
-
await plugin.watch(resolvedConfig);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
watch(resolvedConfig, userConfig, plugins);
|
|
1037
|
-
return (0, import_neverthrow3.ok)({});
|
|
1038
|
-
} else {
|
|
1039
|
-
const buildResult = await buildOnce(resolvedConfig, userConfig, plugins, {});
|
|
1040
|
-
if (buildResult.isErr()) {
|
|
1041
|
-
return (0, import_neverthrow3.err)(buildResult.error);
|
|
1042
|
-
}
|
|
1043
|
-
const allPluginsSucceeded = buildResult.value;
|
|
1044
|
-
const exitCode = allPluginsSucceeded ? 0 : 2;
|
|
1045
|
-
return (0, import_neverthrow3.ok)({ exitCode });
|
|
1046
|
-
}
|
|
1047
|
-
} catch (e) {
|
|
1048
|
-
return (0, import_neverthrow3.err)(e);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1052
|
-
0 && (module.exports = {
|
|
1053
|
-
build
|
|
1054
|
-
});
|
|
1055
|
-
//# sourceMappingURL=index.cjs.map
|