@sdeverywhere/create 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,752 @@
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(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/index.ts
23
+ var src_exports = {};
24
+ __export(src_exports, {
25
+ main: () => main
26
+ });
27
+ module.exports = __toCommonJS(src_exports);
28
+ var import_path6 = require("path");
29
+ var import_colors8 = require("kleur/colors");
30
+ var import_ora8 = __toESM(require("ora"), 1);
31
+ var import_prompts8 = __toESM(require("prompts"), 1);
32
+ var import_which_pm_runs = __toESM(require("which-pm-runs"), 1);
33
+ var import_yargs_parser = __toESM(require("yargs-parser"), 1);
34
+
35
+ // src/step-config.ts
36
+ var import_fs = require("fs");
37
+ var import_promises = require("fs/promises");
38
+ var import_path = require("path");
39
+ var import_colors = require("kleur/colors");
40
+ var import_ora = __toESM(require("ora"), 1);
41
+ var import_prompts = __toESM(require("prompts"), 1);
42
+ var import_yaml = __toESM(require("yaml"), 1);
43
+ var import_compile = require("@sdeverywhere/compile");
44
+ var sampleCheckContent = `# yaml-language-server: $schema=SCHEMA_PATH
45
+
46
+ # NOTE: This is just a simple check to get you started. Replace "Some output" with
47
+ # the name of some variable you'd like to test. Additional tests can be developed
48
+ # in the "playground" (beta) inside the model-check report.
49
+ - describe: Some output
50
+ tests:
51
+ - it: should be > 0 for all input scenarios
52
+ scenarios:
53
+ - preset: matrix
54
+ datasets:
55
+ - name: Some output
56
+ predicates:
57
+ - gt: 0
58
+ `;
59
+ async function updateSdeConfig(projDir, mdlPath) {
60
+ const configPath = (0, import_path.join)(projDir, "sde.config.js");
61
+ let configText = await (0, import_promises.readFile)(configPath, "utf8");
62
+ configText = configText.replaceAll("MODEL_NAME.mdl", mdlPath);
63
+ await (0, import_promises.writeFile)(configPath, configText);
64
+ }
65
+ async function generateCheckYaml(projDir, mdlPath) {
66
+ const checkYamlFile = mdlPath.replace(".mdl", ".check.yaml");
67
+ const checkYamlPath = (0, import_path.join)(projDir, checkYamlFile);
68
+ if (!(0, import_fs.existsSync)(checkYamlPath)) {
69
+ let relProjPath = (0, import_path.relative)((0, import_path.dirname)(checkYamlPath), projDir);
70
+ if (relProjPath.length === 0) {
71
+ relProjPath = "./";
72
+ }
73
+ const nodeModulesPart = (0, import_path.join)(relProjPath, "node_modules");
74
+ const checkCorePart = "@sdeverywhere/check-core/schema/check.schema.json";
75
+ const schemaPath = `${nodeModulesPart}/${checkCorePart}`;
76
+ const checkContent = sampleCheckContent.replace("SCHEMA_PATH", schemaPath);
77
+ await (0, import_promises.writeFile)(checkYamlPath, checkContent);
78
+ }
79
+ }
80
+ async function chooseGenConfig(projDir, mdlPath) {
81
+ let mdlVars;
82
+ try {
83
+ mdlVars = await readModelVars(projDir, mdlPath);
84
+ } catch (e) {
85
+ console.log(e);
86
+ (0, import_ora.default)((0, import_colors.yellow)("The mdl file failed to load. We will continue setting things up, and you can diagnose the issue later.")).warn();
87
+ return;
88
+ }
89
+ let initialTime;
90
+ let finalTime;
91
+ const validVars = [];
92
+ for (const v of mdlVars) {
93
+ const varName = v.name.toLowerCase();
94
+ let skip = false;
95
+ switch (varName) {
96
+ case "final time":
97
+ skip = true;
98
+ if (v.kind === "const") {
99
+ finalTime = v.value;
100
+ }
101
+ break;
102
+ case "initial time":
103
+ skip = true;
104
+ if (v.kind === "const") {
105
+ initialTime = v.value;
106
+ }
107
+ break;
108
+ case "saveper":
109
+ case "time":
110
+ case "time step":
111
+ skip = true;
112
+ break;
113
+ default:
114
+ break;
115
+ }
116
+ if (!skip) {
117
+ validVars.push(v);
118
+ }
119
+ }
120
+ if (initialTime === void 0) {
121
+ initialTime = 0;
122
+ }
123
+ if (finalTime === void 0) {
124
+ finalTime = 100;
125
+ }
126
+ const datFiles = [];
127
+ const datPart = datFiles.join(";");
128
+ const modelCsvFile = (0, import_path.join)(projDir, "config", "model.csv");
129
+ const origModelCsvContent = await (0, import_promises.readFile)(modelCsvFile, "utf8");
130
+ const modelCsvHeader = origModelCsvContent.split("\n")[0];
131
+ const modelCsvLine = `${initialTime},${finalTime},${initialTime},${finalTime},${datPart}`;
132
+ const newModelCsvContent = `${modelCsvHeader}
133
+ ${modelCsvLine}
134
+ `;
135
+ await (0, import_promises.writeFile)(modelCsvFile, newModelCsvContent);
136
+ await chooseGenGraphConfig(projDir, validVars);
137
+ console.log();
138
+ await chooseGenSliderConfig(projDir, validVars);
139
+ }
140
+ async function chooseGenGraphConfig(projDir, mdlVars) {
141
+ const genResponse = await (0, import_prompts.default)({
142
+ type: "confirm",
143
+ name: "genGraph",
144
+ message: `Would you like to configure a graph to get you started? ${(0, import_colors.reset)((0, import_colors.dim)("(recommended)"))}`,
145
+ initial: true
146
+ }, {
147
+ onCancel: () => {
148
+ (0, import_ora.default)().info((0, import_colors.dim)("Operation cancelled."));
149
+ process.exit(0);
150
+ }
151
+ });
152
+ if (!genResponse.genGraph) {
153
+ (0, import_ora.default)().info((0, import_colors.dim)(`No problem! You can edit the "${(0, import_colors.cyan)("config/graphs.csv")}" file later.`));
154
+ return;
155
+ }
156
+ const outputVarNames = [];
157
+ for (const mdlVar of mdlVars) {
158
+ if (mdlVar.kind === "aux" || mdlVar.kind === "level") {
159
+ outputVarNames.push(mdlVar.name);
160
+ }
161
+ }
162
+ outputVarNames.sort((a, b) => {
163
+ return a.toLowerCase().localeCompare(b.toLowerCase());
164
+ });
165
+ const choices = outputVarNames.map((f) => {
166
+ return {
167
+ title: f,
168
+ value: f
169
+ };
170
+ });
171
+ const varsResponse = await (0, import_prompts.default)({
172
+ type: "autocompleteMultiselect",
173
+ name: "vars",
174
+ message: "Choose up to three output variables to display in the graph",
175
+ choices,
176
+ max: 3
177
+ }, {
178
+ onCancel: () => {
179
+ (0, import_ora.default)().info((0, import_colors.dim)("Operation cancelled."));
180
+ process.exit(0);
181
+ }
182
+ });
183
+ if (varsResponse.vars.length === 0) {
184
+ (0, import_ora.default)().info((0, import_colors.dim)(`No variables selected. You can edit the "${(0, import_colors.cyan)("config/graphs.csv")}" file later.`));
185
+ return;
186
+ }
187
+ const graphsCsvFile = (0, import_path.join)(projDir, "config", "graphs.csv");
188
+ const csvLine = graphsCsvLine(varsResponse.vars);
189
+ let graphsCsvContent = await (0, import_promises.readFile)(graphsCsvFile, "utf8");
190
+ graphsCsvContent += `${csvLine}
191
+ `;
192
+ await (0, import_promises.writeFile)(graphsCsvFile, graphsCsvContent);
193
+ (0, import_ora.default)((0, import_colors.green)(`Added graph to "${(0, import_colors.bold)("config/graphs.csv")}". ${(0, import_colors.dim)("You can configure graphs in that file later.")}`)).succeed();
194
+ }
195
+ function graphsCsvLine(outputVarNames) {
196
+ const colors = ["blue", "red", "green"];
197
+ const a = Array(131).fill("");
198
+ a[0] = "1";
199
+ a[2] = "Graphs";
200
+ a[3] = "Graph Title";
201
+ a[7] = "line";
202
+ let index = 26;
203
+ let colorIndex = 0;
204
+ for (const outputVarName of outputVarNames) {
205
+ const escapedName = escapeCsvField(outputVarName);
206
+ a[index + 0] = escapedName;
207
+ a[index + 2] = "line";
208
+ a[index + 3] = escapedName;
209
+ a[index + 4] = colors[colorIndex];
210
+ index += 7;
211
+ colorIndex++;
212
+ }
213
+ return a.join(",");
214
+ }
215
+ async function chooseGenSliderConfig(projDir, mdlVars) {
216
+ const genResponse = await (0, import_prompts.default)({
217
+ type: "confirm",
218
+ name: "genSliders",
219
+ message: `Would you like to configure a few sliders to get you started? ${(0, import_colors.reset)((0, import_colors.dim)("(recommended)"))}`,
220
+ initial: true
221
+ }, {
222
+ onCancel: () => {
223
+ (0, import_ora.default)().info((0, import_colors.dim)("Operation cancelled."));
224
+ process.exit(0);
225
+ }
226
+ });
227
+ if (!genResponse.genSliders) {
228
+ (0, import_ora.default)().info((0, import_colors.dim)(`No problem! You can edit the "${(0, import_colors.cyan)("config/inputs.csv")}" file later.`));
229
+ return;
230
+ }
231
+ const inputVarNames = [];
232
+ for (const mdlVar of mdlVars) {
233
+ if (mdlVar.kind === "const") {
234
+ inputVarNames.push(mdlVar.name);
235
+ }
236
+ }
237
+ inputVarNames.sort((a, b) => {
238
+ return a.toLowerCase().localeCompare(b.toLowerCase());
239
+ });
240
+ const choices = inputVarNames.map((f) => {
241
+ return {
242
+ title: f,
243
+ value: f
244
+ };
245
+ });
246
+ const varsResponse = await (0, import_prompts.default)({
247
+ type: "autocompleteMultiselect",
248
+ name: "vars",
249
+ message: "Choose up to three input variables to control with sliders",
250
+ choices,
251
+ max: 3
252
+ }, {
253
+ onCancel: () => {
254
+ (0, import_ora.default)().info((0, import_colors.dim)("Operation cancelled."));
255
+ process.exit(0);
256
+ }
257
+ });
258
+ if (varsResponse.vars.length === 0) {
259
+ (0, import_ora.default)().info((0, import_colors.dim)(`No variables selected. You can edit the "${(0, import_colors.cyan)("config/inputs.csv")}" file later.`));
260
+ return;
261
+ }
262
+ const inputsCsvFile = (0, import_path.join)(projDir, "config", "inputs.csv");
263
+ let inputsCsvContent = await (0, import_promises.readFile)(inputsCsvFile, "utf8");
264
+ let idNumber = 1;
265
+ for (const inputVarName of varsResponse.vars) {
266
+ const inputVar = mdlVars.find((v) => v.name === inputVarName);
267
+ if (inputVar && inputVar.kind === "const") {
268
+ const defaultValue = inputVar.value;
269
+ const csvLine = inputsCsvLine(inputVarName, defaultValue, idNumber.toString());
270
+ inputsCsvContent += `${csvLine}
271
+ `;
272
+ idNumber++;
273
+ }
274
+ }
275
+ await (0, import_promises.writeFile)(inputsCsvFile, inputsCsvContent);
276
+ const slidersText = varsResponse.vars.length > 1 ? "sliders" : "sliders";
277
+ (0, import_ora.default)((0, import_colors.green)(`Added ${slidersText} to "${(0, import_colors.bold)("config/inputs.csv")}". ${(0, import_colors.dim)("You can configure sliders in that file later.")}`)).succeed();
278
+ }
279
+ function inputsCsvLine(inputVarName, defaultValue, id) {
280
+ const escapedName = escapeCsvField(inputVarName);
281
+ const minValue = defaultValue - 1;
282
+ const maxValue = defaultValue + 1;
283
+ const step = 0.1;
284
+ const a = Array(28).fill("");
285
+ a[0] = id;
286
+ a[1] = "slider";
287
+ a[2] = "view1";
288
+ a[3] = escapedName;
289
+ a[4] = escapedName;
290
+ a[6] = "Sliders";
291
+ a[7] = minValue;
292
+ a[8] = maxValue;
293
+ a[9] = defaultValue;
294
+ a[10] = step;
295
+ a[11] = "(units)";
296
+ return a.join(",");
297
+ }
298
+ function escapeCsvField(s) {
299
+ return s.includes(",") ? `"${s}"` : s;
300
+ }
301
+ async function readModelVars(projDir, mdlPath) {
302
+ const buildDir = (0, import_path.resolve)(projDir, "sde-prep", "build");
303
+ await (0, import_promises.mkdir)(buildDir, { recursive: true });
304
+ const spec = {};
305
+ const mdlFile = (0, import_path.resolve)(projDir, mdlPath);
306
+ const preprocessed = (0, import_compile.preprocessModel)(mdlFile, spec, "genc", false);
307
+ const mdlDir = (0, import_path.dirname)(mdlFile);
308
+ const mdlName = (0, import_path.parse)(mdlFile).name;
309
+ await (0, import_compile.parseAndGenerate)(preprocessed, spec, "printVarList", mdlDir, mdlName, buildDir);
310
+ const varsYamlFile = (0, import_path.join)(buildDir, `${mdlName}_vars.yaml`);
311
+ const varsYamlContent = await (0, import_promises.readFile)(varsYamlFile, "utf8");
312
+ const varObjs = import_yaml.default.parse(varsYamlContent);
313
+ const mdlVars = [];
314
+ for (const varObj of varObjs) {
315
+ switch (varObj.varType) {
316
+ case "const":
317
+ mdlVars.push({
318
+ kind: "const",
319
+ name: varObj.modelLHS,
320
+ value: Number.parseFloat(varObj.modelFormula)
321
+ });
322
+ break;
323
+ case "aux":
324
+ mdlVars.push({
325
+ kind: "aux",
326
+ name: varObj.modelLHS
327
+ });
328
+ break;
329
+ case "level":
330
+ mdlVars.push({
331
+ kind: "level",
332
+ name: varObj.modelLHS
333
+ });
334
+ break;
335
+ default:
336
+ break;
337
+ }
338
+ }
339
+ return mdlVars;
340
+ }
341
+
342
+ // src/step-deps.ts
343
+ var import_execa = require("execa");
344
+ var import_colors2 = require("kleur/colors");
345
+ var import_ora2 = __toESM(require("ora"), 1);
346
+ var import_prompts2 = __toESM(require("prompts"), 1);
347
+ async function chooseInstallDeps(projDir, args, pkgManager) {
348
+ const installResponse = await (0, import_prompts2.default)({
349
+ type: "confirm",
350
+ name: "install",
351
+ message: `Would you like to install ${pkgManager} dependencies? ${(0, import_colors2.reset)((0, import_colors2.dim)("(recommended)"))}`,
352
+ initial: true
353
+ }, {
354
+ onCancel: () => {
355
+ (0, import_ora2.default)().info((0, import_colors2.dim)("Operation cancelled. Your project folder has been created, but no dependencies have been installed."));
356
+ process.exit(0);
357
+ }
358
+ });
359
+ if (args.dryRun) {
360
+ (0, import_ora2.default)().info((0, import_colors2.dim)(`--dry-run enabled, skipping.`));
361
+ return;
362
+ } else if (!installResponse.install) {
363
+ (0, import_ora2.default)().info((0, import_colors2.dim)(`No problem! Remember to install dependencies after setup.`));
364
+ return;
365
+ }
366
+ const installExec = (0, import_execa.execa)(pkgManager, ["install"], { cwd: projDir });
367
+ const installingPackagesMsg = "Installing packages...";
368
+ const installSpinner = (0, import_ora2.default)(installingPackagesMsg).start();
369
+ try {
370
+ await new Promise((resolve, reject) => {
371
+ var _a, _b;
372
+ (_a = installExec.stdout) == null ? void 0 : _a.on("data", function(data) {
373
+ installSpinner.text = `${installingPackagesMsg}
374
+ ${(0, import_colors2.bold)(`[${pkgManager}]`)} ${data}`;
375
+ });
376
+ (_b = installExec.stderr) == null ? void 0 : _b.on("data", function(data) {
377
+ installSpinner.text = `${installingPackagesMsg}
378
+ ${(0, import_colors2.bold)(`[${pkgManager}]`)} ${data}`;
379
+ });
380
+ installExec.on("error", (error) => reject(error));
381
+ installExec.on("exit", (code) => reject(`Install failed (code=${code})`));
382
+ installExec.on("close", () => resolve());
383
+ });
384
+ installSpinner.text = (0, import_colors2.green)("Packages installed!");
385
+ installSpinner.succeed();
386
+ } catch (e) {
387
+ installSpinner.text = (0, import_colors2.yellow)(`There was an error installing packages. Try running ${(0, import_colors2.cyan)(`${pkgManager} install`)} in your project directory later.`);
388
+ installSpinner.warn();
389
+ }
390
+ }
391
+
392
+ // src/step-directory.ts
393
+ var import_fs2 = require("fs");
394
+ var import_path2 = require("path");
395
+ var import_colors3 = require("kleur/colors");
396
+ var import_ora3 = __toESM(require("ora"), 1);
397
+ var import_prompts3 = __toESM(require("prompts"), 1);
398
+ async function chooseProjectDir(args) {
399
+ function isValidDir(dir) {
400
+ const packageJson = (0, import_path2.resolve)(dir, "package.json");
401
+ const packagesDir = (0, import_path2.resolve)(dir, "packages");
402
+ return !(0, import_fs2.existsSync)(dir) || !(0, import_fs2.existsSync)(packageJson) && !(0, import_fs2.existsSync)(packagesDir);
403
+ }
404
+ const showValidDirMsg = (dir) => {
405
+ (0, import_ora3.default)((0, import_colors3.green)(`Using "${(0, import_colors3.bold)(dir)}" as the project directory.`)).succeed();
406
+ };
407
+ const showInvalidDirMsg = (dir) => {
408
+ (0, import_ora3.default)((0, import_colors3.red)(`"${(0, import_colors3.bold)(dir)}" contains existing 'package.json' and/or 'packages' directory, stopping.`)).fail();
409
+ };
410
+ let projDir = args["_"][2];
411
+ if (projDir) {
412
+ if (isValidDir(projDir)) {
413
+ showValidDirMsg(projDir);
414
+ } else {
415
+ showInvalidDirMsg(projDir);
416
+ process.exit(0);
417
+ }
418
+ } else {
419
+ const dirResponse = await (0, import_prompts3.default)({
420
+ type: "text",
421
+ name: "directory",
422
+ message: "Where would you like to create your new project?",
423
+ initial: "<current directory>"
424
+ }, {
425
+ onCancel: () => {
426
+ (0, import_ora3.default)().info((0, import_colors3.dim)("Operation cancelled."));
427
+ process.exit(0);
428
+ }
429
+ });
430
+ projDir = dirResponse.directory;
431
+ if (projDir === "<current directory>") {
432
+ projDir = process.cwd();
433
+ }
434
+ if (isValidDir(projDir)) {
435
+ showValidDirMsg(projDir);
436
+ } else {
437
+ showInvalidDirMsg(projDir);
438
+ process.exit(0);
439
+ }
440
+ }
441
+ return projDir;
442
+ }
443
+
444
+ // src/step-emsdk.ts
445
+ var import_fs3 = require("fs");
446
+ var import_path3 = require("path");
447
+ var import_execa2 = require("execa");
448
+ var import_colors4 = require("kleur/colors");
449
+ var import_ora4 = __toESM(require("ora"), 1);
450
+ var import_prompts4 = __toESM(require("prompts"), 1);
451
+ var version = "2.0.34";
452
+ async function chooseInstallEmsdk(projDir, args) {
453
+ const underParentDir = (0, import_path3.resolve)(projDir, "..", "emsdk");
454
+ const underProjDir = (0, import_path3.join)(projDir, "emsdk");
455
+ const installResponse = await (0, import_prompts4.default)({
456
+ type: "select",
457
+ name: "install",
458
+ message: `Would you like to install the Emscripten SDK?`,
459
+ choices: [
460
+ {
461
+ title: `Install under parent directory (${(0, import_colors4.bold)(underParentDir)})`,
462
+ description: "This is recommended so that it can be shared by multiple projects",
463
+ value: "parent"
464
+ },
465
+ {
466
+ title: `Install under project directory (${(0, import_colors4.bold)(underProjDir)})"`,
467
+ description: "This is useful for keeping everything under a single project directory",
468
+ value: "project"
469
+ },
470
+ {
471
+ title: `Don't install`,
472
+ description: `It's OK, you can install it later`,
473
+ value: "skip"
474
+ }
475
+ ]
476
+ }, {
477
+ onCancel: () => {
478
+ (0, import_ora4.default)().info((0, import_colors4.dim)("Operation cancelled. Your project folder has been created, but the Emscripten SDK and other dependencies have not been installed."));
479
+ process.exit(0);
480
+ }
481
+ });
482
+ if (args.dryRun) {
483
+ (0, import_ora4.default)().info((0, import_colors4.dim)(`--dry-run enabled, skipping.`));
484
+ return;
485
+ } else if (installResponse.install === "skip") {
486
+ (0, import_ora4.default)().info((0, import_colors4.dim)(`No problem! Be sure to install the Emscripten SDK and configure it in "${(0, import_colors4.cyan)("sde.config.js")}" after setup.`));
487
+ return;
488
+ }
489
+ const installDir = installResponse.install === "parent" ? underParentDir : underProjDir;
490
+ try {
491
+ await installEmscripten(installDir);
492
+ } catch (e) {
493
+ (0, import_ora4.default)((0, import_colors4.red)(`Failed to install Emscripten SDK: ${e.message}`)).fail();
494
+ process.exit(0);
495
+ }
496
+ (0, import_ora4.default)((0, import_colors4.green)(`Installed the Emscripten SDK in "${(0, import_colors4.bold)(installDir)}"`)).succeed();
497
+ }
498
+ async function installEmscripten(emsdkDir) {
499
+ if (!(0, import_fs3.existsSync)(emsdkDir)) {
500
+ console.log(`Downloading Emscripten SDK to ${emsdkDir}`);
501
+ await (0, import_execa2.execa)("git", ["clone", "https://github.com/emscripten-core/emsdk.git", emsdkDir]);
502
+ } else {
503
+ console.log(`Found existing Emscripten SDK directory: ${emsdkDir}`);
504
+ }
505
+ if (process.env.CI) {
506
+ console.log("CI detected, removing .git directory...");
507
+ const gitDir = (0, import_path3.join)(emsdkDir, ".git");
508
+ (0, import_fs3.rmSync)(gitDir, { recursive: true, force: true });
509
+ } else {
510
+ console.log("Local development detected, performing git pull...");
511
+ await (0, import_execa2.execa)("git", ["pull"], { cwd: emsdkDir });
512
+ }
513
+ const emsdkCmd = async (...args) => {
514
+ return (0, import_execa2.execa)("python3", ["emsdk.py", ...args], { cwd: emsdkDir });
515
+ };
516
+ console.log(`Activating Emscripten SDK ${version}...`);
517
+ await emsdkCmd("install", version);
518
+ await emsdkCmd("activate", version);
519
+ }
520
+
521
+ // src/step-git.ts
522
+ var import_execa3 = require("execa");
523
+ var import_colors5 = require("kleur/colors");
524
+ var import_ora5 = __toESM(require("ora"), 1);
525
+ var import_prompts5 = __toESM(require("prompts"), 1);
526
+ async function chooseGitInit(projDir, args) {
527
+ const gitResponse = await (0, import_prompts5.default)({
528
+ type: "confirm",
529
+ name: "git",
530
+ message: `Would you like to initialize a new git repository? ${(0, import_colors5.reset)((0, import_colors5.dim)("(optional)"))}`,
531
+ initial: true
532
+ }, {
533
+ onCancel: () => {
534
+ (0, import_ora5.default)().info((0, import_colors5.dim)("Operation cancelled. Your project folder has already been created."));
535
+ process.exit(0);
536
+ }
537
+ });
538
+ if (args.dryRun) {
539
+ (0, import_ora5.default)().info((0, import_colors5.dim)(`--dry-run enabled, skipping.`));
540
+ return;
541
+ } else if (!gitResponse.git) {
542
+ (0, import_ora5.default)().info((0, import_colors5.dim)(`No problem! You can come back and run ${(0, import_colors5.cyan)(`git init`)} later.`));
543
+ return;
544
+ }
545
+ await (0, import_execa3.execaCommand)("git init", { cwd: projDir });
546
+ (0, import_ora5.default)().succeed((0, import_colors5.green)("Git repository initialized!"));
547
+ }
548
+
549
+ // src/step-mdl.ts
550
+ var import_promises2 = require("fs/promises");
551
+ var import_path4 = require("path");
552
+ var import_colors6 = require("kleur/colors");
553
+ var import_ora6 = __toESM(require("ora"), 1);
554
+ var import_prompts6 = __toESM(require("prompts"), 1);
555
+ var sampleMdlContent = `{UTF-8}
556
+
557
+ X = TIME
558
+ ~~|
559
+
560
+ Y = 0
561
+ ~ [-10,10,0.1]
562
+ ~
563
+ |
564
+
565
+ Z = X + Y
566
+ ~~|
567
+
568
+ INITIAL TIME = 2000 ~~|
569
+ FINAL TIME = 2100 ~~|
570
+ TIME STEP = 1 ~~|
571
+ SAVEPER = TIME STEP ~~|
572
+ `;
573
+ async function chooseMdlFile(projDir) {
574
+ async function getFiles(dir) {
575
+ const dirents = await (0, import_promises2.readdir)(dir, { withFileTypes: true });
576
+ const files = await Promise.all(dirents.map((dirent) => {
577
+ const res = (0, import_path4.resolve)(dir, dirent.name);
578
+ return dirent.isDirectory() ? getFiles(res) : res;
579
+ }));
580
+ return files.flat();
581
+ }
582
+ const allFiles = await getFiles(projDir);
583
+ const mdlFiles = allFiles.filter((f) => f.endsWith(".mdl")).map((f) => (0, import_path4.relative)(projDir, f));
584
+ const mdlChoices = mdlFiles.map((f) => {
585
+ return {
586
+ title: f,
587
+ value: f
588
+ };
589
+ });
590
+ let mdlFile;
591
+ if (mdlFiles.length === 0) {
592
+ const sampleMdlFile = (0, import_path4.join)(projDir, "sample.mdl");
593
+ await (0, import_promises2.writeFile)(sampleMdlFile, sampleMdlContent);
594
+ (0, import_ora6.default)((0, import_colors6.yellow)(`No mdl files were found in "${projDir}". A "${(0, import_colors6.cyan)("sample.mdl")}" file has been added to the project to get you started.`)).warn();
595
+ mdlFile = "sample.mdl";
596
+ } else if (mdlFiles.length === 1) {
597
+ (0, import_ora6.default)().succeed(`Found "${mdlFiles[0]}", will configure the project to use that mdl file.`);
598
+ mdlFile = mdlFiles[0];
599
+ } else {
600
+ const options = await (0, import_prompts6.default)([
601
+ {
602
+ type: "select",
603
+ name: "mdlFile",
604
+ message: "It looks like there are multiple mdl files. Which one would you like to use?",
605
+ choices: mdlChoices
606
+ }
607
+ ], {
608
+ onCancel: () => {
609
+ (0, import_ora6.default)().info((0, import_colors6.dim)("Operation cancelled."));
610
+ process.exit(0);
611
+ }
612
+ });
613
+ mdlFile = options.mdlFile;
614
+ }
615
+ (0, import_ora6.default)((0, import_colors6.green)(`Using "${(0, import_colors6.bold)(mdlFile)}" as the model for the project.`)).succeed();
616
+ return mdlFile;
617
+ }
618
+
619
+ // src/step-template.ts
620
+ var import_fs4 = require("fs");
621
+ var import_promises3 = require("fs/promises");
622
+ var import_fs_extra = require("fs-extra");
623
+ var import_os = require("os");
624
+ var import_path5 = require("path");
625
+ var import_degit = __toESM(require("degit"), 1);
626
+ var import_colors7 = require("kleur/colors");
627
+ var import_ora7 = __toESM(require("ora"), 1);
628
+ var import_prompts7 = __toESM(require("prompts"), 1);
629
+ var TEMPLATES = [
630
+ {
631
+ title: "Default project",
632
+ description: "Includes recommended structure with config files, app, core library, model-check, etc",
633
+ value: "template-default"
634
+ },
635
+ {
636
+ title: "Minimal project",
637
+ description: "Includes simple config for model-check",
638
+ value: "template-minimal"
639
+ }
640
+ ];
641
+ async function chooseTemplate(projDir, args, pkgManager) {
642
+ const options = await (0, import_prompts7.default)([
643
+ {
644
+ type: "select",
645
+ name: "template",
646
+ message: "Which template would you like to use?",
647
+ choices: TEMPLATES
648
+ }
649
+ ], {
650
+ onCancel: () => {
651
+ (0, import_ora7.default)().info((0, import_colors7.dim)("Operation cancelled."));
652
+ process.exit(0);
653
+ }
654
+ });
655
+ if (args.dryRun) {
656
+ (0, import_ora7.default)().info((0, import_colors7.dim)(`--dry-run enabled, skipping.`));
657
+ return;
658
+ }
659
+ const defaultRev = "main";
660
+ const commit = args.commit || defaultRev;
661
+ const templateTarget = `climateinteractive/SDEverywhere/examples/${options.template}`;
662
+ const hash = `#${commit}`;
663
+ const templateSpinner = (0, import_ora7.default)("Copying project files...").start();
664
+ await runDegit(templateTarget, hash, projDir, args, templateSpinner);
665
+ templateSpinner.text = (0, import_colors7.green)("Template copied!");
666
+ templateSpinner.succeed();
667
+ if (options.template === "template-default" && pkgManager === "pnpm") {
668
+ const workspaceFile = (0, import_path5.join)(projDir, "pnpm-workspace.yaml");
669
+ const workspaceContent = `packages:
670
+ - packages/*
671
+ `;
672
+ await (0, import_promises3.writeFile)(workspaceFile, workspaceContent);
673
+ }
674
+ return options.template;
675
+ }
676
+ async function runDegit(templateTarget, hash, dstDir, args, spinner) {
677
+ const verbose = args.verbose;
678
+ const emitter = (0, import_degit.default)(`${templateTarget}${hash}`, {
679
+ cache: false,
680
+ force: true,
681
+ verbose
682
+ });
683
+ try {
684
+ if (verbose) {
685
+ emitter.on("info", (info) => {
686
+ console.log(info.message);
687
+ });
688
+ }
689
+ const tmpDir = (0, import_fs4.mkdtempSync)((0, import_path5.join)((0, import_os.tmpdir)(), "sde-create-"));
690
+ await emitter.clone(tmpDir);
691
+ if (!(0, import_fs4.existsSync)(tmpDir) || (0, import_fs4.readdirSync)(tmpDir).length === 0) {
692
+ throw new Error("The requested template failed to download");
693
+ }
694
+ await (0, import_fs_extra.copy)(tmpDir, dstDir, {
695
+ overwrite: false,
696
+ errorOnExist: false
697
+ });
698
+ (0, import_fs4.rmSync)(tmpDir, { recursive: true, force: true });
699
+ } catch (e) {
700
+ spinner.fail();
701
+ console.error((0, import_colors7.red)(e.message));
702
+ console.error((0, import_colors7.yellow)("There was a problem copying the template."));
703
+ console.error((0, import_colors7.yellow)("Please file a new issue with the command output here: https://github.com/climateinteractive/sdeverywhere/issues"));
704
+ process.exit(0);
705
+ }
706
+ }
707
+
708
+ // src/index.ts
709
+ async function main() {
710
+ var _a;
711
+ const pkgManager = ((_a = (0, import_which_pm_runs.default)()) == null ? void 0 : _a.name) || "npm";
712
+ const args = (0, import_yargs_parser.default)(process.argv);
713
+ import_prompts8.default.override(args);
714
+ console.log(`
715
+ ${(0, import_colors8.bold)("Welcome to SDEverywhere!")}`);
716
+ console.log(`Let's create a new SDEverywhere project for your model.
717
+ `);
718
+ const projDir = await chooseProjectDir(args);
719
+ console.log();
720
+ const templateName = await chooseTemplate(projDir, args, pkgManager);
721
+ console.log();
722
+ const mdlPath = await chooseMdlFile(projDir);
723
+ await updateSdeConfig(projDir, mdlPath);
724
+ await generateCheckYaml(projDir, mdlPath);
725
+ console.log();
726
+ if (templateName === "template-default" && !args.dryRun) {
727
+ await chooseGenConfig(projDir, mdlPath);
728
+ console.log();
729
+ }
730
+ await chooseInstallEmsdk(projDir, args);
731
+ console.log();
732
+ await chooseInstallDeps(projDir, args, pkgManager);
733
+ console.log();
734
+ await chooseGitInit(projDir, args);
735
+ console.log();
736
+ (0, import_ora8.default)((0, import_colors8.green)("Setup complete!")).succeed();
737
+ console.log(`
738
+ ${(0, import_colors8.bgCyan)((0, import_colors8.black)(" Next steps "))}
739
+ `);
740
+ const relProjDir = (0, import_path6.relative)(process.cwd(), projDir);
741
+ const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
742
+ if (relProjDir !== "") {
743
+ console.log(`You can now ${(0, import_colors8.bold)((0, import_colors8.cyan)("cd"))} into the ${(0, import_colors8.bold)((0, import_colors8.cyan)(relProjDir))} project directory.`);
744
+ }
745
+ console.log(`Run ${(0, import_colors8.bold)((0, import_colors8.cyan)(devCmd))} to start the local dev server. ${(0, import_colors8.bold)((0, import_colors8.cyan)("CTRL-C"))} to close.`);
746
+ console.log("");
747
+ }
748
+ // Annotate the CommonJS export names for ESM import in node:
749
+ 0 && (module.exports = {
750
+ main
751
+ });
752
+ //# sourceMappingURL=index.cjs.map