@sdeverywhere/create 0.2.34 → 0.2.35

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 CHANGED
@@ -139,11 +139,11 @@ var sampleComparisonsContent = `# yaml-language-server: $schema=SCHEMA_PATH
139
139
  - input: Another input
140
140
  at: 20
141
141
  `;
142
- async function updateSdeConfig(projDir, mdlPath, genFormat) {
142
+ async function updateSdeConfig(projDir, modelPath, genFormat) {
143
143
  const configPath = (0, import_path.join)(projDir, "sde.config.js");
144
144
  let configText = await (0, import_promises.readFile)(configPath, "utf8");
145
145
  configText = configText.replace(`const genFormat = 'js'`, `const genFormat = '${genFormat}'`);
146
- configText = configText.replaceAll("model/MODEL_NAME.mdl", mdlPath);
146
+ configText = configText.replaceAll("model/MODEL_NAME.mdl", modelPath);
147
147
  await (0, import_promises.writeFile)(configPath, configText);
148
148
  }
149
149
  async function generateYaml(projDir, kind, template) {
@@ -167,14 +167,14 @@ async function generateSampleYamlFiles(projDir) {
167
167
  await generateYaml(projDir, "checks", sampleChecksContent);
168
168
  await generateYaml(projDir, "comparisons", sampleComparisonsContent);
169
169
  }
170
- async function chooseGenConfig(projDir, mdlPath) {
170
+ async function chooseGenConfig(projDir, modelPath) {
171
171
  let mdlVars;
172
172
  try {
173
- mdlVars = await readModelVars(projDir, mdlPath);
173
+ mdlVars = await readModelVars(projDir, modelPath);
174
174
  } catch (e) {
175
175
  console.log(e);
176
176
  (0, import_ora2.default)(
177
- (0, import_colors2.yellow)("The mdl file failed to load. We will continue setting things up, and you can diagnose the issue later.")
177
+ (0, import_colors2.yellow)("The model file failed to load. We will continue setting things up, and you can diagnose the issue later.")
178
178
  ).warn();
179
179
  return;
180
180
  }
@@ -422,16 +422,17 @@ function inputsCsvLine(inputVarName, defaultValue, id) {
422
422
  function escapeCsvField(s) {
423
423
  return s.includes(",") ? `"${s}"` : s;
424
424
  }
425
- async function readModelVars(projDir, mdlPath) {
425
+ async function readModelVars(projDir, modelPath) {
426
426
  const buildDir = (0, import_path.resolve)(projDir, "sde-prep", "build");
427
427
  await (0, import_promises.mkdir)(buildDir, { recursive: true });
428
428
  const spec = {};
429
- const mdlFile = (0, import_path.resolve)(projDir, mdlPath);
430
- const mdlContent = await (0, import_promises.readFile)(mdlFile, "utf8");
431
- const mdlDir = (0, import_path.dirname)(mdlFile);
432
- const mdlName = (0, import_path.parse)(mdlFile).name;
433
- await (0, import_compile.parseAndGenerate)(mdlContent, spec, ["printVarList"], mdlDir, mdlName, buildDir);
434
- const jsonListFile = (0, import_path.join)(buildDir, `${mdlName}.json`);
429
+ const modelFile = (0, import_path.resolve)(projDir, modelPath);
430
+ const modelContent = await (0, import_promises.readFile)(modelFile, "utf8");
431
+ const modelKind = modelContent.includes("<xmile") ? "xmile" : "vensim";
432
+ const modelDir = (0, import_path.dirname)(modelFile);
433
+ const modelName = (0, import_path.parse)(modelFile).name;
434
+ await (0, import_compile.parseAndGenerate)(modelContent, modelKind, spec, ["printVarList"], modelDir, modelName, buildDir);
435
+ const jsonListFile = (0, import_path.join)(buildDir, `${modelName}.json`);
435
436
  const jsonListContent = await (0, import_promises.readFile)(jsonListFile, "utf8");
436
437
  const jsonList = JSON.parse(jsonListContent);
437
438
  const varObjs = jsonList.variables;
@@ -729,13 +730,14 @@ async function chooseGitInit(projDir, args) {
729
730
  }
730
731
  }
731
732
 
732
- // src/step-mdl.ts
733
+ // src/step-model-file.ts
733
734
  var import_promises2 = require("fs/promises");
734
735
  var import_path4 = require("path");
735
736
  var import_colors7 = require("kleur/colors");
736
737
  var import_ora7 = __toESM(require("ora"), 1);
737
738
  var import_prompts7 = __toESM(require("prompts"), 1);
738
- async function chooseMdlFile(projDir) {
739
+ var supportedModelFileExtensions = /* @__PURE__ */ new Set([".mdl", ".xmile", ".stmx", ".itmx"]);
740
+ async function chooseModelFile(projDir) {
739
741
  async function getFiles(dir) {
740
742
  const dirents = await (0, import_promises2.readdir)(dir, { withFileTypes: true });
741
743
  const files = await Promise.all(
@@ -747,28 +749,33 @@ async function chooseMdlFile(projDir) {
747
749
  return files.flat();
748
750
  }
749
751
  const allFiles = await getFiles(projDir);
750
- const mdlFiles = allFiles.filter((f) => f.endsWith(".mdl")).map((f) => (0, import_path4.relative)(projDir, f).replaceAll(import_path4.sep, import_path4.posix.sep));
751
- const mdlChoices = mdlFiles.map((f) => {
752
+ const modelFiles = allFiles.filter((f) => {
753
+ const ext = (0, import_path4.extname)(f).toLowerCase();
754
+ return supportedModelFileExtensions.has(ext);
755
+ }).map((f) => (0, import_path4.relative)(projDir, f).replaceAll(import_path4.sep, import_path4.posix.sep));
756
+ const modelChoices = modelFiles.map((f) => {
752
757
  return {
753
758
  title: f,
754
759
  value: f
755
760
  };
756
761
  });
757
- let mdlFile;
758
- if (mdlFiles.length === 0) {
759
- (0, import_ora7.default)((0, import_colors7.yellow)(`No mdl files were found in "${projDir}". The mdl file from the template will be used instead.`)).warn();
760
- mdlFile = void 0;
761
- } else if (mdlFiles.length === 1) {
762
- mdlFile = mdlFiles[0];
763
- (0, import_ora7.default)().succeed(`Found "${mdlFile}", will configure the project to use that mdl file.`);
762
+ let modelFile;
763
+ if (modelFiles.length === 0) {
764
+ (0, import_ora7.default)(
765
+ (0, import_colors7.yellow)(`No model files were found in "${projDir}". The model file from the template will be used instead.`)
766
+ ).warn();
767
+ modelFile = void 0;
768
+ } else if (modelFiles.length === 1) {
769
+ modelFile = modelFiles[0];
770
+ (0, import_ora7.default)().succeed(`Found "${modelFile}", will configure the project to use that model file.`);
764
771
  } else {
765
772
  const options = await (0, import_prompts7.default)(
766
773
  [
767
774
  {
768
775
  type: "select",
769
- name: "mdlFile",
770
- message: "It looks like there are multiple mdl files. Which one would you like to use?",
771
- choices: mdlChoices
776
+ name: "modelFile",
777
+ message: "It looks like there are multiple model files. Which one would you like to use?",
778
+ choices: modelChoices
772
779
  }
773
780
  ],
774
781
  {
@@ -778,10 +785,10 @@ async function chooseMdlFile(projDir) {
778
785
  }
779
786
  }
780
787
  );
781
- mdlFile = options.mdlFile;
782
- (0, import_ora7.default)((0, import_colors7.green)(`Using "${(0, import_colors7.bold)(mdlFile)}" as the model for the project.`)).succeed();
788
+ modelFile = options.modelFile;
789
+ (0, import_ora7.default)((0, import_colors7.green)(`Using "${(0, import_colors7.bold)(modelFile)}" as the model for the project.`)).succeed();
783
790
  }
784
- return mdlFile;
791
+ return modelFile;
785
792
  }
786
793
 
787
794
  // src/step-template.ts
@@ -851,7 +858,7 @@ async function chooseTemplate(args) {
851
858
  name: templateName
852
859
  };
853
860
  }
854
- async function copyTemplate(template, projDir, pkgManager, configDirExisted, mdlExisted) {
861
+ async function copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted) {
855
862
  const templateSpinner = (0, import_ora8.default)("Copying template files...").start();
856
863
  try {
857
864
  const tmpDir = (0, import_fs4.mkdtempSync)((0, import_path5.join)((0, import_os.tmpdir)(), "sde-create-"));
@@ -865,14 +872,14 @@ async function copyTemplate(template, projDir, pkgManager, configDirExisted, mdl
865
872
  if (configDirExisted) {
866
873
  (0, import_fs4.rmSync)((0, import_path5.join)(tmpDir, "config"), { recursive: true, force: true });
867
874
  }
868
- if (mdlExisted) {
875
+ if (modelExisted) {
869
876
  (0, import_fs4.rmSync)((0, import_path5.join)(tmpDir, "model"), { recursive: true, force: true });
870
877
  }
871
878
  await (0, import_fs_extra.copy)(tmpDir, projDir, {
872
879
  overwrite: false,
873
880
  errorOnExist: false
874
881
  });
875
- if (!mdlExisted) {
882
+ if (!modelExisted) {
876
883
  (0, import_fs4.renameSync)((0, import_path5.join)(projDir, "model", "MODEL_NAME.mdl"), (0, import_path5.join)(projDir, "model", "sample.mdl"));
877
884
  }
878
885
  (0, import_fs4.rmSync)(tmpDir, { recursive: true, force: true });
@@ -916,19 +923,19 @@ ${(0, import_colors9.bold)("Welcome to SDEverywhere!")}`);
916
923
  const configDirExisted = (0, import_fs5.existsSync)((0, import_path6.resolve)(projDir, "config"));
917
924
  const template = await chooseTemplate(args);
918
925
  console.log();
919
- let mdlPath = await chooseMdlFile(projDir);
920
- const mdlExisted = mdlPath !== void 0;
926
+ let modelPath = await chooseModelFile(projDir);
927
+ const modelExisted = modelPath !== void 0;
921
928
  console.log();
922
929
  if (!args.dryRun) {
923
- await copyTemplate(template, projDir, pkgManager, configDirExisted, mdlExisted);
930
+ await copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted);
924
931
  console.log();
925
932
  }
926
- if (mdlPath === void 0) {
927
- mdlPath = `model${import_path6.posix.sep}sample.mdl`;
933
+ if (modelPath === void 0) {
934
+ modelPath = `model${import_path6.posix.sep}sample.mdl`;
928
935
  }
929
936
  const genFormat = await chooseCodeFormat();
930
937
  if (!args.dryRun) {
931
- await updateSdeConfig(projDir, mdlPath, genFormat);
938
+ await updateSdeConfig(projDir, modelPath, genFormat);
932
939
  const modelCheckFilesExist = (0, import_fs5.existsSync)((0, import_path6.resolve)(projDir, "model", "checks")) || (0, import_fs5.existsSync)((0, import_path6.resolve)(projDir, "model", "comparisons"));
933
940
  if (!modelCheckFilesExist) {
934
941
  await generateSampleYamlFiles(projDir);
@@ -943,8 +950,8 @@ ${(0, import_colors9.bold)("Welcome to SDEverywhere!")}`);
943
950
  console.log();
944
951
  } else {
945
952
  const configDirExistsNow = (0, import_fs5.existsSync)((0, import_path6.resolve)(projDir, "config"));
946
- if (configDirExistsNow && mdlExisted && !args.dryRun) {
947
- await chooseGenConfig(projDir, mdlPath);
953
+ if (configDirExistsNow && modelExisted && !args.dryRun) {
954
+ await chooseGenConfig(projDir, modelPath);
948
955
  console.log();
949
956
  }
950
957
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/step-code-format.ts","../src/step-config.ts","../src/step-deps.ts","../src/step-directory.ts","../src/step-emsdk.ts","../src/step-git.ts","../src/step-mdl.ts","../src/step-template.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { posix, relative, resolve as resolvePath } from 'path'\n\nimport { bgCyan, black, bold, cyan, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport detectPackageManager from 'which-pm-runs'\nimport yargs from 'yargs-parser'\n\nimport { chooseCodeFormat } from './step-code-format'\nimport { chooseGenConfig, generateSampleYamlFiles, updateSdeConfig } from './step-config'\nimport { chooseInstallDeps } from './step-deps'\nimport { chooseProjectDir } from './step-directory'\nimport { chooseInstallEmsdk } from './step-emsdk'\nimport { chooseGitInit } from './step-git'\nimport { chooseMdlFile } from './step-mdl'\nimport { chooseTemplate, copyTemplate } from './step-template'\n\nexport async function main(): Promise<void> {\n // Detect the package manager\n const pkgManager = detectPackageManager()?.name || 'npm'\n\n // Parse command line arguments\n const args = yargs(process.argv)\n prompts.override(args)\n\n if (args.dryRun) {\n console.log()\n ora().info(dim(`--dry-run enabled, no files will be written.`))\n }\n\n // Display welcome message\n console.log(`\\n${bold('Welcome to SDEverywhere!')}`)\n console.log(`Let's create a new SDEverywhere project for your model.\\n`)\n\n // Prompt the user to select a project directory\n const projDir = await chooseProjectDir(args)\n console.log()\n\n // See if there is a pre-existing `config` directory\n const configDirExisted = existsSync(resolvePath(projDir, 'config'))\n\n // Prompt the user to select a template\n const template = await chooseTemplate(args)\n console.log()\n\n // Prompt the user to select an mdl file\n let mdlPath = await chooseMdlFile(projDir)\n const mdlExisted = mdlPath !== undefined\n console.log()\n\n if (!args.dryRun) {\n // Copy the template files to the project directory\n await copyTemplate(template, projDir, pkgManager, configDirExisted, mdlExisted)\n console.log()\n }\n\n if (mdlPath === undefined) {\n // There wasn't already an mdl file in the project directory, so we will use\n // the one supplied by the template. The template is expected to have a\n // `model/MODEL_NAME.mdl` file, which gets renamed to `model/sample.mdl`\n // in the `copyTemplate` step. Note that `chooseMdlFile` returns a\n // POSIX-style relative path, so we will also use a relative path here.\n mdlPath = `model${posix.sep}sample.mdl`\n }\n\n // Prompt the user to select a code generation format\n const genFormat = await chooseCodeFormat()\n\n if (!args.dryRun) {\n // Update the `sde.config.js` file to use the chosen mdl file\n await updateSdeConfig(projDir, mdlPath, genFormat)\n\n // Generate sample `checks.yaml` and `comparisons.yaml` files if needed\n const modelCheckFilesExist =\n existsSync(resolvePath(projDir, 'model', 'checks')) || existsSync(resolvePath(projDir, 'model', 'comparisons'))\n if (!modelCheckFilesExist) {\n await generateSampleYamlFiles(projDir)\n }\n }\n console.log()\n\n if (configDirExisted) {\n // There was already a `config` directory, so don't offer to set up CSV files\n ora().succeed(`Found existing \"${bold('config')}\" directory.`)\n ora().info(\n dim(`You can edit the files in the \"${cyan('config')}\" directory later to configure graphs and sliders.`)\n )\n console.log()\n } else {\n // There wasn't already a `config` directory, but there was already an mdl file,\n // so offer to set up CSV files\n const configDirExistsNow = existsSync(resolvePath(projDir, 'config'))\n if (configDirExistsNow && mdlExisted && !args.dryRun) {\n await chooseGenConfig(projDir, mdlPath)\n console.log()\n }\n }\n\n // If the user chose C as the code generation format, prompt the user to\n // install Emscripten SDK\n if (genFormat === 'c') {\n await chooseInstallEmsdk(projDir, args)\n console.log()\n }\n\n // Prompt the user to install dependencies\n await chooseInstallDeps(projDir, args, pkgManager)\n console.log()\n\n // Prompt the user to initialize a git repo\n await chooseGitInit(projDir, args)\n console.log()\n\n ora(green('Setup complete!')).succeed()\n\n console.log(`\\n${bgCyan(black(' Next steps '))}\\n`)\n\n const relProjDir = relative(process.cwd(), projDir)\n const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`\n\n // If the project dir is the current dir, no need to tell users to cd\n if (relProjDir !== '') {\n console.log(`You can now ${bold(cyan('cd'))} into the ${bold(cyan(relProjDir))} project directory.`)\n }\n console.log(`Run ${bold(cyan(devCmd))} to start the local dev server. ${bold(cyan('CTRL-C'))} to close.`)\n console.log('')\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { bold, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\n\nconst promptMessage = `Would you like your project to use WebAssembly?`\n\nconst noDesc = `\\\n* Choose this if you want to get started using SDEverywhere quickly\nand you don't want to install the Emscripten SDK.\n* This will generate a model that uses JavaScript code only, which\ndoesn't require extra build tools, but runs slower than WebAssembly.`\nconst yesDesc = `\\\n* Choose this if you want this script to install the Emscripten SDK\nfor you, or if you already have it installed.\n* This will generate a model that uses WebAssembly, which requires an\nadditional build step, but runs faster than pure JavaScript code.`\n\nconst FORMATS = [\n {\n title: 'No, generate a JavaScript model',\n description: noDesc,\n value: 'js'\n },\n {\n title: 'Yes, generate a WebAssembly model',\n description: yesDesc,\n value: 'c'\n }\n]\n\nexport async function chooseCodeFormat(): Promise<string> {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'format',\n message: promptMessage,\n choices: FORMATS\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n const target = options.format === 'c' ? 'WebAssembly' : 'JavaScript'\n const successMessage = green(\n `Configuring your project to generate ${target}. See \"${bold('sde.config.js')}\" for details.`\n )\n ora(successMessage).succeed()\n\n return options.format\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { mkdir, readFile, writeFile } from 'fs/promises'\nimport { dirname, join as joinPath, parse as parsePath, relative, resolve as resolvePath } from 'path'\n\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\nimport { parseAndGenerate } from '@sdeverywhere/compile'\n\ninterface MdlConstVariable {\n kind: 'const'\n name: string\n value: number\n}\n\ninterface MdlAuxVariable {\n kind: 'aux'\n name: string\n}\n\ninterface MdlLevelVariable {\n kind: 'level'\n name: string\n}\n\ntype MdlVariable = MdlConstVariable | MdlAuxVariable | MdlLevelVariable\n\nconst sampleChecksContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains \"check\" tests that exercise your model under different input\n# scenarios. For more guidance, consult this wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a simple check just to get you started.\n# Replace \"Some output\" with the name of some variable you'd like to test.\n- describe: Some output\n tests:\n - it: should be > 0 for all input scenarios\n scenarios:\n - preset: matrix\n datasets:\n - name: Some output\n predicates:\n - gt: 0\n`\n\nconst sampleComparisonsContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains definitions of custom comparison scenarios, which allow you to see\n# how the behavior of the model compares to that of previous versions. For more guidance,\n# consult the following wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a custom scenario just to get you started.\n# Replace \"Some input\" and \"Another input\" with the names of some variables you'd\n# like to test.\n- scenario:\n title: Custom scenario\n subtitle: gradual ramp-up\n with:\n - input: Some input\n at: 10\n - input: Another input\n at: 20\n`\n\nexport async function updateSdeConfig(projDir: string, mdlPath: string, genFormat: string): Promise<void> {\n // Read the `sde.config.js` file from the template\n const configPath = joinPath(projDir, 'sde.config.js')\n let configText = await readFile(configPath, 'utf8')\n\n // Set the code generation format to the chosen format\n configText = configText.replace(`const genFormat = 'js'`, `const genFormat = '${genFormat}'`)\n\n // Replace instances of `model/MODEL_NAME.mdl` with the path to the chosen mdl file\n configText = configText.replaceAll('model/MODEL_NAME.mdl', mdlPath)\n\n // Write the updated file\n await writeFile(configPath, configText)\n}\n\nasync function generateYaml(projDir: string, kind: 'checks' | 'comparisons', template: string): Promise<void> {\n const yamlDir = joinPath(projDir, 'model', kind)\n const yamlPath = joinPath(yamlDir, `${kind}.yaml`)\n if (!existsSync(yamlPath)) {\n // Get relative path from yaml file parent dir to project dir\n let relProjPath = relative(dirname(yamlPath), projDir)\n if (relProjPath.length === 0) {\n relProjPath = './'\n }\n\n // Create the directory for the yaml file, if needed\n await mkdir(yamlDir, { recursive: true })\n\n // TODO: This path is normally different depending on whether using npm/yarn or\n // pnpm. For npm/yarn, `check-core` is hoisted under top-level `node_modules`,\n // but for pnpm, it is nested under `node_modules/.pnpm`. As an ugly workaround\n // the templates declare `check-core` as a direct dependency even though it is\n // not really needed (a transitive dependency via `plugin-check` would normally\n // suffice). This allows us to use the same path here that works for all\n // three package managers.\n const nodeModulesPart = joinPath(relProjPath, 'node_modules')\n const schemaName = kind === 'checks' ? 'check' : 'comparison'\n const checkCorePart = `@sdeverywhere/check-core/schema/${schemaName}.schema.json`\n const schemaPath = `${nodeModulesPart}/${checkCorePart}`\n const yamlContent = template.replace('SCHEMA_PATH', schemaPath)\n await writeFile(yamlPath, yamlContent)\n }\n}\n\nexport async function generateSampleYamlFiles(projDir: string): Promise<void> {\n // Generate a sample `checks.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'checks', sampleChecksContent)\n\n // Generate a sample `comparisons.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'comparisons', sampleComparisonsContent)\n}\n\nexport async function chooseGenConfig(projDir: string, mdlPath: string): Promise<void> {\n // TODO: For now we eagerly read the mdl file; maybe change this to only load it if\n // the user chooses to generate graph and/or slider config\n let mdlVars: MdlVariable[]\n try {\n // Get the list of variables available in the model\n mdlVars = await readModelVars(projDir, mdlPath)\n } catch (e) {\n console.log(e)\n ora(\n yellow('The mdl file failed to load. We will continue setting things up, and you can diagnose the issue later.')\n ).warn()\n return\n }\n\n // Extract `INITIAL TIME` and `FINAL TIME` values and remove special control variables from the list\n let initialTime: number\n let finalTime: number\n const validVars: MdlVariable[] = []\n for (const v of mdlVars) {\n const varName = v.name.toLowerCase()\n let skip = false\n switch (varName) {\n case 'final time':\n skip = true\n if (v.kind === 'const') {\n finalTime = v.value\n }\n break\n case 'initial time':\n skip = true\n if (v.kind === 'const') {\n initialTime = v.value\n }\n break\n case 'saveper':\n case 'time':\n case 'time step':\n skip = true\n break\n default:\n break\n }\n if (!skip) {\n validVars.push(v)\n }\n }\n\n // Set the values in `model.csv`\n if (initialTime === undefined) {\n initialTime = 0\n }\n if (finalTime === undefined) {\n finalTime = 100\n }\n\n // TODO: Auto-detect dat files that are referenced by the mdl and include them here\n const datFiles: string[] = []\n const datPart = datFiles.join(';')\n\n // Preserve the `model.csv` header but drop other existing content (if any)\n const modelCsvFile = joinPath(projDir, 'config', 'model.csv')\n const origModelCsvContent = await readFile(modelCsvFile, 'utf8')\n const modelCsvHeader = origModelCsvContent.split('\\n')[0]\n\n // Disable bundled listing and customization features by default\n const bundleListing = 'false'\n const customConstants = 'false'\n const customLookups = 'false'\n const customOutputs = 'false'\n\n // Add line and write out updated `model.csv`\n const modelCsvLine = `${initialTime},${finalTime},${datPart},${bundleListing},${customConstants},${customLookups},${customOutputs}`\n const newModelCsvContent = `${modelCsvHeader}\\n${modelCsvLine}\\n`\n await writeFile(modelCsvFile, newModelCsvContent)\n\n // See if the user wants to generate graph config\n await chooseGenGraphConfig(projDir, validVars)\n console.log()\n\n // See if the user wants to generate slider config\n await chooseGenSliderConfig(projDir, validVars)\n}\n\nasync function chooseGenGraphConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genGraph',\n message: `Would you like to configure a graph to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genGraph) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available output variables\n const outputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'aux' || mdlVar.kind === 'level') {\n outputVarNames.push(mdlVar.name)\n }\n }\n outputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = outputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three output variables to display in the graph',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `graphs.csv` header but drop other existing content (if any)\n const graphsCsvFile = joinPath(projDir, 'config', 'graphs.csv')\n const origGraphsCsvContent = await readFile(graphsCsvFile, 'utf8')\n const graphsCsvHeader = origGraphsCsvContent.split('\\n')[0]\n\n // Write the updated `graphs.csv` file\n let newGraphsCsvContent = `${graphsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add line to `graphs.csv`\n const csvLine = graphsCsvLine(varsResponse.vars)\n newGraphsCsvContent += `${csvLine}\\n`\n }\n await writeFile(graphsCsvFile, newGraphsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n ora(\n green(`Added graph to \"${bold('config/graphs.csv')}\". ${dim('You can configure graphs in that file later.')}`)\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction graphsCsvLine(outputVarNames: string[]): string {\n const colors = ['blue', 'red', 'green']\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(131).fill('')\n // id\n a[0] = '1'\n // parent menu\n a[2] = 'Graphs'\n // graph title\n a[3] = 'Graph Title'\n // kind\n a[7] = 'line'\n // Plots start at 26\n let index = 26\n let colorIndex = 0\n for (const outputVarName of outputVarNames) {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(outputVarName)\n // plot N variable\n a[index + 0] = escapedName\n // plot N style\n a[index + 2] = 'line'\n // plot N label\n a[index + 3] = escapedName\n // plot N color\n a[index + 4] = colors[colorIndex]\n index += 7\n colorIndex++\n }\n\n return a.join(',')\n}\n\nasync function chooseGenSliderConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genSliders',\n message: `Would you like to configure a few sliders to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genSliders) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available input variables\n const inputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'const') {\n inputVarNames.push(mdlVar.name)\n }\n }\n inputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = inputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three input variables to control with sliders',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `inputs.csv` header but drop other existing content (if any)\n const inputsCsvFile = joinPath(projDir, 'config', 'inputs.csv')\n const origInputsCsvContent = await readFile(inputsCsvFile, 'utf8')\n const inputsCsvHeader = origInputsCsvContent.split('\\n')[0]\n\n // Write the updated `inputs.csv` file\n let newInputsCsvContent = `${inputsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add lines to `inputs.csv`\n let idNumber = 1\n for (const inputVarName of varsResponse.vars) {\n const inputVar = mdlVars.find(v => v.name === inputVarName)\n if (inputVar && inputVar.kind === 'const') {\n const defaultValue = inputVar.value\n const csvLine = inputsCsvLine(inputVarName, defaultValue, idNumber.toString())\n newInputsCsvContent += `${csvLine}\\n`\n idNumber++\n }\n }\n }\n await writeFile(inputsCsvFile, newInputsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n const slidersText = varsResponse.vars.length > 1 ? 'sliders' : 'sliders'\n ora(\n green(\n `Added ${slidersText} to \"${bold('config/inputs.csv')}\". ${dim('You can configure sliders in that file later.')}`\n )\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction inputsCsvLine(inputVarName: string, defaultValue: number, id: string): string {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(inputVarName)\n\n // TODO: Be smarter about automatically choosing min/max/step values\n const minValue = defaultValue - 1\n const maxValue = defaultValue + 1\n const step = 0.1\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(28).fill('')\n // id\n a[0] = id\n // input type\n a[1] = 'slider'\n // viewid\n a[2] = 'view1'\n // varname\n a[3] = escapedName\n // label\n a[4] = escapedName\n // group name\n a[6] = 'Sliders'\n // slider min\n a[7] = minValue\n // slider max\n a[8] = maxValue\n // slider default\n a[9] = defaultValue\n // slider step\n a[10] = step\n // units\n a[11] = '(units)'\n\n return a.join(',')\n}\n\nfunction escapeCsvField(s: string): string {\n // Surround the value in quotes if it contains a comma\n // TODO: Escape double quotes as well\n return s.includes(',') ? `\"${s}\"` : s\n}\n\nasync function readModelVars(projDir: string, mdlPath: string): Promise<MdlVariable[]> {\n // TODO: This function contains a subset of the logic from `sde-generate.js` in\n // the `cli` package; should revisit\n // let { modelDirname, modelName, modelPathname } = modelPathProps(model)\n\n // Ensure the `build` directory exists (under the `sde-prep` directory)\n const buildDir = resolvePath(projDir, 'sde-prep', 'build')\n await mkdir(buildDir, { recursive: true })\n\n // Use an empty model spec; this will make SDE look at all variables in the mdl\n const spec = {}\n\n // Try parsing the mdl file to generate the list of variables\n // TODO: This depends on some `compile` package APIs that are not yet considered stable.\n // Ideally we'd use an API that does not write files but instead returns an in-memory\n // object in a specified format.\n\n // Read the model file\n const mdlFile = resolvePath(projDir, mdlPath)\n const mdlContent = await readFile(mdlFile, 'utf8')\n\n // Parse the model and generate the variable list\n const mdlDir = dirname(mdlFile)\n const mdlName = parsePath(mdlFile).name\n await parseAndGenerate(mdlContent, spec, ['printVarList'], mdlDir, mdlName, buildDir)\n\n // Read `build/{mdl}.json`\n const jsonListFile = joinPath(buildDir, `${mdlName}.json`)\n const jsonListContent = await readFile(jsonListFile, 'utf8')\n const jsonList = JSON.parse(jsonListContent)\n const varObjs = jsonList.variables\n\n // Create a simplified array of variables\n const mdlVars: MdlVariable[] = []\n for (const varObj of varObjs) {\n // Only include certain variables for now\n // TODO: Include \"data\" vars\n switch (varObj.varType) {\n case 'const':\n mdlVars.push({\n kind: 'const',\n name: varObj.modelLHS,\n value: Number.parseFloat(varObj.modelFormula)\n })\n break\n case 'aux':\n mdlVars.push({\n kind: 'aux',\n name: varObj.modelLHS\n })\n break\n case 'level':\n mdlVars.push({\n kind: 'level',\n name: varObj.modelLHS\n })\n break\n default:\n break\n }\n }\n\n return mdlVars\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execa } from 'execa'\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseInstallDeps(projDir: string, args: Arguments, pkgManager: string): Promise<void> {\n // Prompt the user\n const installResponse = await prompts(\n {\n type: 'confirm',\n name: 'install',\n message: `Would you like to install ${pkgManager} dependencies? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(\n dim('Operation cancelled. Your project folder has been created, but no dependencies have been installed.')\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!installResponse.install) {\n ora().info(dim(`No problem! Remember to install dependencies after setup.`))\n return\n }\n\n // Install dependencies\n const installExec = execa(pkgManager, ['install'], { cwd: projDir })\n const installingPackagesMsg = 'Installing packages...'\n const installSpinner = ora(installingPackagesMsg).start()\n try {\n await new Promise<void>((resolve, reject) => {\n installExec.stdout?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.stderr?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.on('error', error => reject(error))\n installExec.on('close', code => {\n if (code !== 0) {\n reject(`Install failed (code=${code})`)\n } else {\n resolve()\n }\n })\n })\n installSpinner.text = green('Packages installed!')\n installSpinner.succeed()\n } catch {\n installSpinner.text = yellow(\n `There was an error installing packages. Try running ${cyan(\n `${pkgManager} install`\n )} in your project directory later.`\n )\n installSpinner.warn()\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { resolve as resolvePath } from 'path'\n\nimport { bold, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseProjectDir(args: Arguments): Promise<string> {\n /**\n * Return true if the given directory does not exist, or it does not contain important files\n * like `package.json`.\n */\n function isValidDir(dir: string): boolean {\n const packageJson = resolvePath(dir, 'package.json')\n const packagesDir = resolvePath(dir, 'packages')\n return !existsSync(dir) || (!existsSync(packageJson) && !existsSync(packagesDir))\n }\n\n const showValidDirMsg = (dir: string) => {\n ora(green(`Using \"${bold(dir)}\" as the project directory.`)).succeed()\n }\n\n const showInvalidDirMsg = (dir: string) => {\n ora(red(`\"${bold(dir)}\" contains existing 'package.json' and/or 'packages' directory, stopping.`)).fail()\n }\n\n // See if project directory is provided on command line\n let projDir = args['_'][2] as string\n if (projDir) {\n // Directory was provided, see if it is valid\n if (isValidDir(projDir)) {\n // The provided directory is valid, so proceed\n showValidDirMsg(projDir)\n } else {\n // The provided directory is not valid, so show error message and exit\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n } else {\n // Directory was not provided, so prompt the user\n const dirResponse = await prompts(\n {\n type: 'text',\n name: 'directory',\n message: 'Where would you like to create your new project?',\n initial: '<current directory>'\n // validate(value) {\n // if (value === '<current directory>') {\n // value = process.cwd()\n // }\n // if (!isValidDir(value)) {\n // return notValidMsg(value)\n // }\n // return true\n // }\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n projDir = dirResponse.directory\n if (projDir === '<current directory>') {\n projDir = process.cwd()\n }\n if (isValidDir(projDir)) {\n showValidDirMsg(projDir)\n } else {\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n }\n\n return projDir\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, rmSync } from 'fs'\nimport { join as joinPath, resolve as resolvePath } from 'path'\n\nimport { execa } from 'execa'\nimport { findUp } from 'find-up'\nimport { bold, cyan, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\n// TODO: Make this configurable; we're using this older version for now because it is\n// relatively stable and has been used to build En-ROADS and C-ROADS for a long time\nconst version = '2.0.34'\n\nexport async function chooseInstallEmsdk(projDir: string, args: Arguments): Promise<void> {\n // Walk up the directory structure to see if there is an existing `emsdk` directory\n const existingEmsdkDir = await findUp('emsdk', {\n cwd: projDir,\n type: 'directory'\n })\n if (existingEmsdkDir) {\n ora().succeed('Found existing Emscripten SDK installation.')\n ora().info(dim(`Your project will use \"${cyan(existingEmsdkDir)}\".`))\n return\n }\n\n // Prompt the user\n const underParentDir = resolvePath(projDir, '..', 'emsdk')\n const underProjDir = joinPath(projDir, 'emsdk')\n const installResponse = await prompts(\n {\n type: 'select',\n name: 'install',\n message: `Would you like to install the Emscripten SDK that is used to generate WebAssembly?`,\n choices: [\n // ${reset(dim('(recommended)'))\n {\n title: `Install under parent directory (${bold(underParentDir)})`,\n description: 'This is recommended so that it can be shared by multiple projects',\n value: 'parent'\n },\n {\n title: `Install under project directory (${bold(underProjDir)})\"`,\n description: 'This is useful for keeping everything under a single project directory',\n value: 'project'\n },\n {\n title: `Don't install`,\n description: `It's OK, you can install it later`,\n value: 'skip'\n }\n ]\n },\n {\n onCancel: () => {\n ora().info(\n dim(\n 'Operation cancelled. Your project folder has been created, but the Emscripten SDK and other dependencies have not been installed.'\n )\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (installResponse.install === 'skip') {\n ora().info(\n dim(\n `No problem! Be sure to install the Emscripten SDK and configure it in \"${cyan('sde.config.js')}\" after setup.`\n )\n )\n return\n }\n\n const installDir = installResponse.install === 'parent' ? underParentDir : underProjDir\n try {\n // TODO: Use spinner here\n await installEmscripten(installDir)\n } catch (e) {\n ora(red(`Failed to install Emscripten SDK: ${e.message}`)).fail()\n process.exit(0)\n }\n\n ora(green(`Installed the Emscripten SDK in \"${bold(installDir)}\"`)).succeed()\n}\n\n/**\n * Install the Emscripten SDK to the `emsdk` directory under the\n * given directory (if `emsdk` is not already present), then\n * activates the requested version (specified with `version`).\n *\n * The implementation is similar to the existing `setup-emsdk` action\n * (https://github.com/mymindstorm/setup-emsdk) except that one has issues\n * with the cache directory on Windows, so having our own script gives us\n * more control over installation and caching behavior.\n */\nasync function installEmscripten(emsdkDir: string /*, options?: { verbose?: boolean }*/): Promise<void> {\n // Only download if the emsdk directory wasn't restored from a cache\n if (!existsSync(emsdkDir)) {\n console.log(`Downloading Emscripten SDK to ${emsdkDir}`)\n // console.log()\n await execa('git', ['clone', 'https://github.com/emscripten-core/emsdk.git', emsdkDir])\n } else {\n console.log(`Found existing Emscripten SDK directory: ${emsdkDir}`)\n }\n // console.log()\n\n if (process.env.CI) {\n // On GitHub Actions, remove the `.git` directory to keep the cache smaller.\n // When we update to a new version, the cache key will miss and the emsdk\n // repo will be redownloaded.\n console.log('CI detected, removing .git directory...')\n const gitDir = joinPath(emsdkDir, '.git')\n rmSync(gitDir, { recursive: true, force: true })\n } else {\n // For local development, pull to get the latest\n console.log('Local development detected, performing git pull...')\n await execa('git', ['pull'], { cwd: emsdkDir })\n // console.log()\n }\n\n const emsdkCmd = async (...args: string[]) => {\n return execa('python3', ['emsdk.py', ...args], { cwd: emsdkDir })\n }\n\n console.log(`Activating Emscripten SDK ${version}...`)\n await emsdkCmd('install', version)\n await emsdkCmd('activate', version)\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execaCommand } from 'execa'\nimport { cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseGitInit(projDir: string, args: Arguments): Promise<void> {\n // Prompt the user\n const gitResponse = await prompts(\n {\n type: 'confirm',\n name: 'git',\n message: `Would you like to initialize a new git repository? ${reset(dim('(optional)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled. Your project folder has already been created.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!gitResponse.git) {\n ora().info(dim(`No problem! You can come back and run ${cyan(`git init`)} later.`))\n return\n }\n\n // Init git repo\n try {\n await execaCommand('git init', { cwd: projDir })\n ora().succeed(green('Git repository initialized!'))\n } catch {\n ora().warn(\n yellow(\n `There was a problem initializing the Git repository, but no problem, you can run ${cyan(`git init`)} later.`\n )\n )\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { readdir } from 'fs/promises'\nimport { relative, resolve as resolvePath, sep, posix } from 'path'\n\nimport { bold, dim, green, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\nexport async function chooseMdlFile(projDir: string): Promise<string | undefined> {\n // Find all `.mdl` files in the project directory\n // From https://stackoverflow.com/a/45130990\n async function getFiles(dir: string): Promise<string[]> {\n const dirents = await readdir(dir, { withFileTypes: true })\n const files = await Promise.all(\n dirents.map(dirent => {\n const res = resolvePath(dir, dirent.name)\n return dirent.isDirectory() ? getFiles(res) : res\n })\n )\n return files.flat()\n }\n const allFiles = await getFiles(projDir)\n const mdlFiles = allFiles\n // Only include files ending with '.mdl'\n .filter(f => f.endsWith('.mdl'))\n // Convert to a relative path with POSIX path separators (we want\n // paths in the 'sde.config.js' file to use POSIX path style only,\n // since that works on any OS including Windows)\n .map(f => relative(projDir, f).replaceAll(sep, posix.sep))\n const mdlChoices = mdlFiles.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n\n let mdlFile: string\n if (mdlFiles.length === 0) {\n // No mdl files found; return undefined so that the mdl from the template is copied over\n ora(yellow(`No mdl files were found in \"${projDir}\". The mdl file from the template will be used instead.`)).warn()\n mdlFile = undefined\n } else if (mdlFiles.length === 1) {\n // Only one mdl file\n mdlFile = mdlFiles[0]\n ora().succeed(`Found \"${mdlFile}\", will configure the project to use that mdl file.`)\n } else {\n // Multiple mdl files found; allow the user to choose one\n // TODO: Eventually we should allow the user to choose to flatten if there are multiple submodels\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'mdlFile',\n message: 'It looks like there are multiple mdl files. Which one would you like to use?',\n choices: mdlChoices\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n mdlFile = options.mdlFile\n ora(green(`Using \"${bold(mdlFile)}\" as the model for the project.`)).succeed()\n }\n\n return mdlFile\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, mkdtempSync, readdirSync, renameSync, rmSync } from 'fs'\nimport { writeFile } from 'fs/promises'\nimport { copy } from 'fs-extra'\nimport { tmpdir } from 'os'\nimport { join as joinPath } from 'path'\n\nimport { downloadTemplate } from 'giget'\nimport { bold, dim, green, red, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nconst TEMPLATES = [\n {\n title: 'Svelte project (recommended)',\n description: 'Includes recommended structure with config files, Svelte-based app, core library, model-check, etc',\n value: 'svelte'\n },\n {\n title: 'jQuery project',\n description: 'Includes recommended structure with config files, jQuery-based app, core library, model-check, etc',\n value: 'jquery'\n },\n {\n title: 'Minimal project',\n description: 'Includes simple config for model-check',\n value: 'minimal'\n }\n]\n\ninterface Template {\n /** The template URI that can be passed to `giget` to download the template. */\n uri: string\n /** The template name that will be displayed to the user. */\n name: string\n}\n\nexport async function chooseTemplate(args: Arguments): Promise<Template> {\n let templateName: string\n if (args.template) {\n // Allow template name or repository to be provided on command line\n templateName = args.template\n } else {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'template',\n message: 'Which template would you like to use?',\n choices: TEMPLATES\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n templateName = options.template\n }\n\n // Allow branch name or commit hash to be overridden on command line\n const defaultRev = 'main'\n const commit = args.commit || defaultRev\n\n // Construct the template repository URL\n let baseTemplateUri: string\n if (templateName.includes(':')) {\n // Assume the template name is already in the form of a giget template, for example:\n // github:owner/repo\n // gitlab:owner/repo\n baseTemplateUri = templateName\n } else if (templateName.includes('/')) {\n // Assume the template name is a GitHub repository name, for example:\n // owner/repo\n baseTemplateUri = `github:${templateName}`\n } else {\n // Otherwise, assume the template name is one of the available `template-*`\n // projects under `examples` in the SDEverywhere repository, for example:\n // svelte\n // jquery\n // minimal\n baseTemplateUri = `github:climateinteractive/SDEverywhere/examples/template-${templateName}`\n }\n const templateUri = `${baseTemplateUri}#${commit}`\n\n ora(green(`Using \"${bold(templateUri)}\" as the template for the project.`)).succeed()\n\n return {\n uri: templateUri,\n name: templateName\n }\n}\n\nexport async function copyTemplate(\n template: Template,\n projDir: string,\n pkgManager: string,\n configDirExisted: boolean,\n mdlExisted: boolean\n): Promise<void> {\n // Show a spinner while copying the template files\n const templateSpinner = ora('Copying template files...').start()\n\n try {\n // Make giget write to a temporary directory\n const tmpDir = mkdtempSync(joinPath(tmpdir(), 'sde-create-'))\n\n // Use giget to download the template (we will be writing to a temporary directory,\n // so `force` is safe)\n await downloadTemplate(template.uri, {\n force: true,\n dir: tmpDir\n })\n\n // In case giget doesn't return an error when an invalid template is provided, check\n // that the temporary directory is non-empty\n if (!existsSync(tmpDir) || readdirSync(tmpDir).length === 0) {\n throw new Error('Failed to download the requested template: the temporary directory is empty.')\n }\n\n if (configDirExisted) {\n // There is already a `config` directory in the project directory; remove the\n // `config` directory from the template so that we don't write files from the\n // template that conflict with the existing files\n rmSync(joinPath(tmpDir, 'config'), { recursive: true, force: true })\n }\n\n if (mdlExisted) {\n // There is already an mdl file in the project directory; remove the `model`\n // directory (including the mdl file and the model-check yaml files) from the\n // template so that we don't copy them into the project directory\n rmSync(joinPath(tmpDir, 'model'), { recursive: true, force: true })\n }\n\n // Copy files to destination without overwriting\n await copy(tmpDir, projDir, {\n overwrite: false,\n errorOnExist: false\n })\n\n if (!mdlExisted) {\n // There wasn't already an mdl file in the project directory, so we will use\n // the one supplied by the template. Rename it from `MODEL_NAME.mdl` to\n // `sample.mdl`.\n renameSync(joinPath(projDir, 'model', 'MODEL_NAME.mdl'), joinPath(projDir, 'model', 'sample.mdl'))\n }\n\n // Remove the temporary directory\n rmSync(tmpDir, { recursive: true, force: true })\n } catch (e) {\n // The download failed; show an error message\n // TODO: Handle common download issues; for now, just log the error message and exit\n templateSpinner.fail()\n console.error(red(e.message))\n console.error(yellow('\\nThere was a problem copying the template.'))\n console.error(\n yellow(\n 'Please start a new discussion thread and include the command output so that we can help:\\n https://github.com/climateinteractive/SDEverywhere/discussions/categories/q-a\\n'\n )\n )\n process.exit(0)\n }\n\n if (existsSync(joinPath(projDir, 'packages')) && pkgManager === 'pnpm') {\n // When using pnpm and the template has a `packages` folder (i.e., it has a monorepo\n // layout), we need to write a `pnpm-workspace.yaml` file since pnpm doesn't use the\n // \"workspaces\" config from `package.json` (like npm and yarn use)\n const workspaceFile = joinPath(projDir, 'pnpm-workspace.yaml')\n const workspaceContent = `packages:\\n - packages/*\\n`\n await writeFile(workspaceFile, workspaceContent)\n }\n\n templateSpinner.text = green('Template copied!')\n templateSpinner.succeed()\n}\n"],"mappings":"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","names":["import_fs","import_path","import_colors","import_ora","import_prompts","prompts","ora","import_colors","import_ora","import_prompts","joinPath","ora","prompts","resolvePath","parsePath","import_colors","import_ora","import_prompts","prompts","ora","import_fs","import_path","import_colors","import_ora","import_prompts","resolvePath","ora","prompts","import_fs","import_path","import_execa","import_colors","import_ora","import_prompts","ora","resolvePath","joinPath","prompts","import_execa","import_colors","import_ora","import_prompts","prompts","ora","import_promises","import_path","import_colors","import_ora","import_prompts","resolvePath","ora","prompts","import_fs","import_promises","import_path","import_colors","import_ora","import_prompts","prompts","ora","joinPath","detectPackageManager","yargs","prompts","ora","resolvePath"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/step-code-format.ts","../src/step-config.ts","../src/step-deps.ts","../src/step-directory.ts","../src/step-emsdk.ts","../src/step-git.ts","../src/step-model-file.ts","../src/step-template.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { posix, relative, resolve as resolvePath } from 'path'\n\nimport { bgCyan, black, bold, cyan, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport detectPackageManager from 'which-pm-runs'\nimport yargs from 'yargs-parser'\n\nimport { chooseCodeFormat } from './step-code-format'\nimport { chooseGenConfig, generateSampleYamlFiles, updateSdeConfig } from './step-config'\nimport { chooseInstallDeps } from './step-deps'\nimport { chooseProjectDir } from './step-directory'\nimport { chooseInstallEmsdk } from './step-emsdk'\nimport { chooseGitInit } from './step-git'\nimport { chooseModelFile } from './step-model-file'\nimport { chooseTemplate, copyTemplate } from './step-template'\n\nexport async function main(): Promise<void> {\n // Detect the package manager\n const pkgManager = detectPackageManager()?.name || 'npm'\n\n // Parse command line arguments\n const args = yargs(process.argv)\n prompts.override(args)\n\n if (args.dryRun) {\n console.log()\n ora().info(dim(`--dry-run enabled, no files will be written.`))\n }\n\n // Display welcome message\n console.log(`\\n${bold('Welcome to SDEverywhere!')}`)\n console.log(`Let's create a new SDEverywhere project for your model.\\n`)\n\n // Prompt the user to select a project directory\n const projDir = await chooseProjectDir(args)\n console.log()\n\n // See if there is a pre-existing `config` directory\n const configDirExisted = existsSync(resolvePath(projDir, 'config'))\n\n // Prompt the user to select a template\n const template = await chooseTemplate(args)\n console.log()\n\n // Prompt the user to select a model file\n let modelPath = await chooseModelFile(projDir)\n const modelExisted = modelPath !== undefined\n console.log()\n\n if (!args.dryRun) {\n // Copy the template files to the project directory\n await copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted)\n console.log()\n }\n\n if (modelPath === undefined) {\n // There wasn't already a model file in the project directory, so we will use\n // the one supplied by the template. The template is expected to have a\n // `model/MODEL_NAME.mdl` file, which gets renamed to `model/sample.mdl`\n // in the `copyTemplate` step. Note that `chooseModelFile` returns a\n // POSIX-style relative path, so we will also use a relative path here.\n modelPath = `model${posix.sep}sample.mdl`\n }\n\n // Prompt the user to select a code generation format\n const genFormat = await chooseCodeFormat()\n\n if (!args.dryRun) {\n // Update the `sde.config.js` file to use the chosen model file\n await updateSdeConfig(projDir, modelPath, genFormat)\n\n // Generate sample `checks.yaml` and `comparisons.yaml` files if needed\n const modelCheckFilesExist =\n existsSync(resolvePath(projDir, 'model', 'checks')) || existsSync(resolvePath(projDir, 'model', 'comparisons'))\n if (!modelCheckFilesExist) {\n await generateSampleYamlFiles(projDir)\n }\n }\n console.log()\n\n if (configDirExisted) {\n // There was already a `config` directory, so don't offer to set up CSV files\n ora().succeed(`Found existing \"${bold('config')}\" directory.`)\n ora().info(\n dim(`You can edit the files in the \"${cyan('config')}\" directory later to configure graphs and sliders.`)\n )\n console.log()\n } else {\n // There wasn't already a `config` directory, but there was already a model file,\n // so offer to set up CSV files\n const configDirExistsNow = existsSync(resolvePath(projDir, 'config'))\n if (configDirExistsNow && modelExisted && !args.dryRun) {\n await chooseGenConfig(projDir, modelPath)\n console.log()\n }\n }\n\n // If the user chose C as the code generation format, prompt the user to\n // install Emscripten SDK\n if (genFormat === 'c') {\n await chooseInstallEmsdk(projDir, args)\n console.log()\n }\n\n // Prompt the user to install dependencies\n await chooseInstallDeps(projDir, args, pkgManager)\n console.log()\n\n // Prompt the user to initialize a git repo\n await chooseGitInit(projDir, args)\n console.log()\n\n ora(green('Setup complete!')).succeed()\n\n console.log(`\\n${bgCyan(black(' Next steps '))}\\n`)\n\n const relProjDir = relative(process.cwd(), projDir)\n const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`\n\n // If the project dir is the current dir, no need to tell users to cd\n if (relProjDir !== '') {\n console.log(`You can now ${bold(cyan('cd'))} into the ${bold(cyan(relProjDir))} project directory.`)\n }\n console.log(`Run ${bold(cyan(devCmd))} to start the local dev server. ${bold(cyan('CTRL-C'))} to close.`)\n console.log('')\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { bold, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\n\nconst promptMessage = `Would you like your project to use WebAssembly?`\n\nconst noDesc = `\\\n* Choose this if you want to get started using SDEverywhere quickly\nand you don't want to install the Emscripten SDK.\n* This will generate a model that uses JavaScript code only, which\ndoesn't require extra build tools, but runs slower than WebAssembly.`\nconst yesDesc = `\\\n* Choose this if you want this script to install the Emscripten SDK\nfor you, or if you already have it installed.\n* This will generate a model that uses WebAssembly, which requires an\nadditional build step, but runs faster than pure JavaScript code.`\n\nconst FORMATS = [\n {\n title: 'No, generate a JavaScript model',\n description: noDesc,\n value: 'js'\n },\n {\n title: 'Yes, generate a WebAssembly model',\n description: yesDesc,\n value: 'c'\n }\n]\n\nexport async function chooseCodeFormat(): Promise<string> {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'format',\n message: promptMessage,\n choices: FORMATS\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n const target = options.format === 'c' ? 'WebAssembly' : 'JavaScript'\n const successMessage = green(\n `Configuring your project to generate ${target}. See \"${bold('sde.config.js')}\" for details.`\n )\n ora(successMessage).succeed()\n\n return options.format\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { mkdir, readFile, writeFile } from 'fs/promises'\nimport { dirname, join as joinPath, parse as parsePath, relative, resolve as resolvePath } from 'path'\n\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\nimport { parseAndGenerate } from '@sdeverywhere/compile'\n\ninterface MdlConstVariable {\n kind: 'const'\n name: string\n value: number\n}\n\ninterface MdlAuxVariable {\n kind: 'aux'\n name: string\n}\n\ninterface MdlLevelVariable {\n kind: 'level'\n name: string\n}\n\ntype MdlVariable = MdlConstVariable | MdlAuxVariable | MdlLevelVariable\n\nconst sampleChecksContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains \"check\" tests that exercise your model under different input\n# scenarios. For more guidance, consult this wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a simple check just to get you started.\n# Replace \"Some output\" with the name of some variable you'd like to test.\n- describe: Some output\n tests:\n - it: should be > 0 for all input scenarios\n scenarios:\n - preset: matrix\n datasets:\n - name: Some output\n predicates:\n - gt: 0\n`\n\nconst sampleComparisonsContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains definitions of custom comparison scenarios, which allow you to see\n# how the behavior of the model compares to that of previous versions. For more guidance,\n# consult the following wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a custom scenario just to get you started.\n# Replace \"Some input\" and \"Another input\" with the names of some variables you'd\n# like to test.\n- scenario:\n title: Custom scenario\n subtitle: gradual ramp-up\n with:\n - input: Some input\n at: 10\n - input: Another input\n at: 20\n`\n\nexport async function updateSdeConfig(projDir: string, modelPath: string, genFormat: string): Promise<void> {\n // Read the `sde.config.js` file from the template\n const configPath = joinPath(projDir, 'sde.config.js')\n let configText = await readFile(configPath, 'utf8')\n\n // Set the code generation format to the chosen format\n configText = configText.replace(`const genFormat = 'js'`, `const genFormat = '${genFormat}'`)\n\n // Replace instances of `model/MODEL_NAME.mdl` with the path to the chosen model file\n configText = configText.replaceAll('model/MODEL_NAME.mdl', modelPath)\n\n // Write the updated file\n await writeFile(configPath, configText)\n}\n\nasync function generateYaml(projDir: string, kind: 'checks' | 'comparisons', template: string): Promise<void> {\n const yamlDir = joinPath(projDir, 'model', kind)\n const yamlPath = joinPath(yamlDir, `${kind}.yaml`)\n if (!existsSync(yamlPath)) {\n // Get relative path from yaml file parent dir to project dir\n let relProjPath = relative(dirname(yamlPath), projDir)\n if (relProjPath.length === 0) {\n relProjPath = './'\n }\n\n // Create the directory for the yaml file, if needed\n await mkdir(yamlDir, { recursive: true })\n\n // TODO: This path is normally different depending on whether using npm/yarn or\n // pnpm. For npm/yarn, `check-core` is hoisted under top-level `node_modules`,\n // but for pnpm, it is nested under `node_modules/.pnpm`. As an ugly workaround\n // the templates declare `check-core` as a direct dependency even though it is\n // not really needed (a transitive dependency via `plugin-check` would normally\n // suffice). This allows us to use the same path here that works for all\n // three package managers.\n const nodeModulesPart = joinPath(relProjPath, 'node_modules')\n const schemaName = kind === 'checks' ? 'check' : 'comparison'\n const checkCorePart = `@sdeverywhere/check-core/schema/${schemaName}.schema.json`\n const schemaPath = `${nodeModulesPart}/${checkCorePart}`\n const yamlContent = template.replace('SCHEMA_PATH', schemaPath)\n await writeFile(yamlPath, yamlContent)\n }\n}\n\nexport async function generateSampleYamlFiles(projDir: string): Promise<void> {\n // Generate a sample `checks.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'checks', sampleChecksContent)\n\n // Generate a sample `comparisons.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'comparisons', sampleComparisonsContent)\n}\n\nexport async function chooseGenConfig(projDir: string, modelPath: string): Promise<void> {\n // TODO: For now we eagerly read the model file; maybe change this to only load it if\n // the user chooses to generate graph and/or slider config\n let mdlVars: MdlVariable[]\n try {\n // Get the list of variables available in the model\n mdlVars = await readModelVars(projDir, modelPath)\n } catch (e) {\n console.log(e)\n ora(\n yellow('The model file failed to load. We will continue setting things up, and you can diagnose the issue later.')\n ).warn()\n return\n }\n\n // Extract `INITIAL TIME` and `FINAL TIME` values and remove special control variables from the list\n let initialTime: number\n let finalTime: number\n const validVars: MdlVariable[] = []\n for (const v of mdlVars) {\n const varName = v.name.toLowerCase()\n let skip = false\n switch (varName) {\n case 'final time':\n skip = true\n if (v.kind === 'const') {\n finalTime = v.value\n }\n break\n case 'initial time':\n skip = true\n if (v.kind === 'const') {\n initialTime = v.value\n }\n break\n case 'saveper':\n case 'time':\n case 'time step':\n skip = true\n break\n default:\n break\n }\n if (!skip) {\n validVars.push(v)\n }\n }\n\n // Set the values in `model.csv`\n if (initialTime === undefined) {\n initialTime = 0\n }\n if (finalTime === undefined) {\n finalTime = 100\n }\n\n // TODO: Auto-detect dat files that are referenced by the mdl and include them here\n const datFiles: string[] = []\n const datPart = datFiles.join(';')\n\n // Preserve the `model.csv` header but drop other existing content (if any)\n const modelCsvFile = joinPath(projDir, 'config', 'model.csv')\n const origModelCsvContent = await readFile(modelCsvFile, 'utf8')\n const modelCsvHeader = origModelCsvContent.split('\\n')[0]\n\n // Disable bundled listing and customization features by default\n const bundleListing = 'false'\n const customConstants = 'false'\n const customLookups = 'false'\n const customOutputs = 'false'\n\n // Add line and write out updated `model.csv`\n const modelCsvLine = `${initialTime},${finalTime},${datPart},${bundleListing},${customConstants},${customLookups},${customOutputs}`\n const newModelCsvContent = `${modelCsvHeader}\\n${modelCsvLine}\\n`\n await writeFile(modelCsvFile, newModelCsvContent)\n\n // See if the user wants to generate graph config\n await chooseGenGraphConfig(projDir, validVars)\n console.log()\n\n // See if the user wants to generate slider config\n await chooseGenSliderConfig(projDir, validVars)\n}\n\nasync function chooseGenGraphConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genGraph',\n message: `Would you like to configure a graph to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genGraph) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available output variables\n const outputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'aux' || mdlVar.kind === 'level') {\n outputVarNames.push(mdlVar.name)\n }\n }\n outputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = outputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three output variables to display in the graph',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `graphs.csv` header but drop other existing content (if any)\n const graphsCsvFile = joinPath(projDir, 'config', 'graphs.csv')\n const origGraphsCsvContent = await readFile(graphsCsvFile, 'utf8')\n const graphsCsvHeader = origGraphsCsvContent.split('\\n')[0]\n\n // Write the updated `graphs.csv` file\n let newGraphsCsvContent = `${graphsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add line to `graphs.csv`\n const csvLine = graphsCsvLine(varsResponse.vars)\n newGraphsCsvContent += `${csvLine}\\n`\n }\n await writeFile(graphsCsvFile, newGraphsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n ora(\n green(`Added graph to \"${bold('config/graphs.csv')}\". ${dim('You can configure graphs in that file later.')}`)\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction graphsCsvLine(outputVarNames: string[]): string {\n const colors = ['blue', 'red', 'green']\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(131).fill('')\n // id\n a[0] = '1'\n // parent menu\n a[2] = 'Graphs'\n // graph title\n a[3] = 'Graph Title'\n // kind\n a[7] = 'line'\n // Plots start at 26\n let index = 26\n let colorIndex = 0\n for (const outputVarName of outputVarNames) {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(outputVarName)\n // plot N variable\n a[index + 0] = escapedName\n // plot N style\n a[index + 2] = 'line'\n // plot N label\n a[index + 3] = escapedName\n // plot N color\n a[index + 4] = colors[colorIndex]\n index += 7\n colorIndex++\n }\n\n return a.join(',')\n}\n\nasync function chooseGenSliderConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genSliders',\n message: `Would you like to configure a few sliders to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genSliders) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available input variables\n const inputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'const') {\n inputVarNames.push(mdlVar.name)\n }\n }\n inputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = inputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three input variables to control with sliders',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `inputs.csv` header but drop other existing content (if any)\n const inputsCsvFile = joinPath(projDir, 'config', 'inputs.csv')\n const origInputsCsvContent = await readFile(inputsCsvFile, 'utf8')\n const inputsCsvHeader = origInputsCsvContent.split('\\n')[0]\n\n // Write the updated `inputs.csv` file\n let newInputsCsvContent = `${inputsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add lines to `inputs.csv`\n let idNumber = 1\n for (const inputVarName of varsResponse.vars) {\n const inputVar = mdlVars.find(v => v.name === inputVarName)\n if (inputVar && inputVar.kind === 'const') {\n const defaultValue = inputVar.value\n const csvLine = inputsCsvLine(inputVarName, defaultValue, idNumber.toString())\n newInputsCsvContent += `${csvLine}\\n`\n idNumber++\n }\n }\n }\n await writeFile(inputsCsvFile, newInputsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n const slidersText = varsResponse.vars.length > 1 ? 'sliders' : 'sliders'\n ora(\n green(\n `Added ${slidersText} to \"${bold('config/inputs.csv')}\". ${dim('You can configure sliders in that file later.')}`\n )\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction inputsCsvLine(inputVarName: string, defaultValue: number, id: string): string {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(inputVarName)\n\n // TODO: Be smarter about automatically choosing min/max/step values\n const minValue = defaultValue - 1\n const maxValue = defaultValue + 1\n const step = 0.1\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(28).fill('')\n // id\n a[0] = id\n // input type\n a[1] = 'slider'\n // viewid\n a[2] = 'view1'\n // varname\n a[3] = escapedName\n // label\n a[4] = escapedName\n // group name\n a[6] = 'Sliders'\n // slider min\n a[7] = minValue\n // slider max\n a[8] = maxValue\n // slider default\n a[9] = defaultValue\n // slider step\n a[10] = step\n // units\n a[11] = '(units)'\n\n return a.join(',')\n}\n\nfunction escapeCsvField(s: string): string {\n // Surround the value in quotes if it contains a comma\n // TODO: Escape double quotes as well\n return s.includes(',') ? `\"${s}\"` : s\n}\n\nasync function readModelVars(projDir: string, modelPath: string): Promise<MdlVariable[]> {\n // TODO: This function contains a subset of the logic from `sde-generate.js` in\n // the `cli` package; should revisit\n\n // Ensure the `build` directory exists (under the `sde-prep` directory)\n const buildDir = resolvePath(projDir, 'sde-prep', 'build')\n await mkdir(buildDir, { recursive: true })\n\n // Use an empty model spec; this will make SDE look at all variables in the model file\n const spec = {}\n\n // Try parsing the model file to generate the list of variables\n // TODO: This depends on some `compile` package APIs that are not yet considered stable.\n // Ideally we'd use an API that does not write files but instead returns an in-memory\n // object in a specified format.\n\n // Read the model file\n const modelFile = resolvePath(projDir, modelPath)\n const modelContent = await readFile(modelFile, 'utf8')\n\n // Determine the model kind based on the presence of an `<xmile>` tag\n const modelKind = modelContent.includes('<xmile') ? 'xmile' : 'vensim'\n\n // Parse the model and generate the variable list\n const modelDir = dirname(modelFile)\n const modelName = parsePath(modelFile).name\n await parseAndGenerate(modelContent, modelKind, spec, ['printVarList'], modelDir, modelName, buildDir)\n\n // Read `build/{model}.json`\n const jsonListFile = joinPath(buildDir, `${modelName}.json`)\n const jsonListContent = await readFile(jsonListFile, 'utf8')\n const jsonList = JSON.parse(jsonListContent)\n const varObjs = jsonList.variables\n\n // Create a simplified array of variables\n const mdlVars: MdlVariable[] = []\n for (const varObj of varObjs) {\n // Only include certain variables for now\n // TODO: Include \"data\" vars\n switch (varObj.varType) {\n case 'const':\n mdlVars.push({\n kind: 'const',\n name: varObj.modelLHS,\n value: Number.parseFloat(varObj.modelFormula)\n })\n break\n case 'aux':\n mdlVars.push({\n kind: 'aux',\n name: varObj.modelLHS\n })\n break\n case 'level':\n mdlVars.push({\n kind: 'level',\n name: varObj.modelLHS\n })\n break\n default:\n break\n }\n }\n\n return mdlVars\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execa } from 'execa'\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseInstallDeps(projDir: string, args: Arguments, pkgManager: string): Promise<void> {\n // Prompt the user\n const installResponse = await prompts(\n {\n type: 'confirm',\n name: 'install',\n message: `Would you like to install ${pkgManager} dependencies? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(\n dim('Operation cancelled. Your project folder has been created, but no dependencies have been installed.')\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!installResponse.install) {\n ora().info(dim(`No problem! Remember to install dependencies after setup.`))\n return\n }\n\n // Install dependencies\n const installExec = execa(pkgManager, ['install'], { cwd: projDir })\n const installingPackagesMsg = 'Installing packages...'\n const installSpinner = ora(installingPackagesMsg).start()\n try {\n await new Promise<void>((resolve, reject) => {\n installExec.stdout?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.stderr?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.on('error', error => reject(error))\n installExec.on('close', code => {\n if (code !== 0) {\n reject(`Install failed (code=${code})`)\n } else {\n resolve()\n }\n })\n })\n installSpinner.text = green('Packages installed!')\n installSpinner.succeed()\n } catch {\n installSpinner.text = yellow(\n `There was an error installing packages. Try running ${cyan(\n `${pkgManager} install`\n )} in your project directory later.`\n )\n installSpinner.warn()\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { resolve as resolvePath } from 'path'\n\nimport { bold, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseProjectDir(args: Arguments): Promise<string> {\n /**\n * Return true if the given directory does not exist, or it does not contain important files\n * like `package.json`.\n */\n function isValidDir(dir: string): boolean {\n const packageJson = resolvePath(dir, 'package.json')\n const packagesDir = resolvePath(dir, 'packages')\n return !existsSync(dir) || (!existsSync(packageJson) && !existsSync(packagesDir))\n }\n\n const showValidDirMsg = (dir: string) => {\n ora(green(`Using \"${bold(dir)}\" as the project directory.`)).succeed()\n }\n\n const showInvalidDirMsg = (dir: string) => {\n ora(red(`\"${bold(dir)}\" contains existing 'package.json' and/or 'packages' directory, stopping.`)).fail()\n }\n\n // See if project directory is provided on command line\n let projDir = args['_'][2] as string\n if (projDir) {\n // Directory was provided, see if it is valid\n if (isValidDir(projDir)) {\n // The provided directory is valid, so proceed\n showValidDirMsg(projDir)\n } else {\n // The provided directory is not valid, so show error message and exit\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n } else {\n // Directory was not provided, so prompt the user\n const dirResponse = await prompts(\n {\n type: 'text',\n name: 'directory',\n message: 'Where would you like to create your new project?',\n initial: '<current directory>'\n // validate(value) {\n // if (value === '<current directory>') {\n // value = process.cwd()\n // }\n // if (!isValidDir(value)) {\n // return notValidMsg(value)\n // }\n // return true\n // }\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n projDir = dirResponse.directory\n if (projDir === '<current directory>') {\n projDir = process.cwd()\n }\n if (isValidDir(projDir)) {\n showValidDirMsg(projDir)\n } else {\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n }\n\n return projDir\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, rmSync } from 'fs'\nimport { join as joinPath, resolve as resolvePath } from 'path'\n\nimport { execa } from 'execa'\nimport { findUp } from 'find-up'\nimport { bold, cyan, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\n// TODO: Make this configurable; we're using this older version for now because it is\n// relatively stable and has been used to build En-ROADS and C-ROADS for a long time\nconst version = '2.0.34'\n\nexport async function chooseInstallEmsdk(projDir: string, args: Arguments): Promise<void> {\n // Walk up the directory structure to see if there is an existing `emsdk` directory\n const existingEmsdkDir = await findUp('emsdk', {\n cwd: projDir,\n type: 'directory'\n })\n if (existingEmsdkDir) {\n ora().succeed('Found existing Emscripten SDK installation.')\n ora().info(dim(`Your project will use \"${cyan(existingEmsdkDir)}\".`))\n return\n }\n\n // Prompt the user\n const underParentDir = resolvePath(projDir, '..', 'emsdk')\n const underProjDir = joinPath(projDir, 'emsdk')\n const installResponse = await prompts(\n {\n type: 'select',\n name: 'install',\n message: `Would you like to install the Emscripten SDK that is used to generate WebAssembly?`,\n choices: [\n // ${reset(dim('(recommended)'))\n {\n title: `Install under parent directory (${bold(underParentDir)})`,\n description: 'This is recommended so that it can be shared by multiple projects',\n value: 'parent'\n },\n {\n title: `Install under project directory (${bold(underProjDir)})\"`,\n description: 'This is useful for keeping everything under a single project directory',\n value: 'project'\n },\n {\n title: `Don't install`,\n description: `It's OK, you can install it later`,\n value: 'skip'\n }\n ]\n },\n {\n onCancel: () => {\n ora().info(\n dim(\n 'Operation cancelled. Your project folder has been created, but the Emscripten SDK and other dependencies have not been installed.'\n )\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (installResponse.install === 'skip') {\n ora().info(\n dim(\n `No problem! Be sure to install the Emscripten SDK and configure it in \"${cyan('sde.config.js')}\" after setup.`\n )\n )\n return\n }\n\n const installDir = installResponse.install === 'parent' ? underParentDir : underProjDir\n try {\n // TODO: Use spinner here\n await installEmscripten(installDir)\n } catch (e) {\n ora(red(`Failed to install Emscripten SDK: ${e.message}`)).fail()\n process.exit(0)\n }\n\n ora(green(`Installed the Emscripten SDK in \"${bold(installDir)}\"`)).succeed()\n}\n\n/**\n * Install the Emscripten SDK to the `emsdk` directory under the\n * given directory (if `emsdk` is not already present), then\n * activates the requested version (specified with `version`).\n *\n * The implementation is similar to the existing `setup-emsdk` action\n * (https://github.com/mymindstorm/setup-emsdk) except that one has issues\n * with the cache directory on Windows, so having our own script gives us\n * more control over installation and caching behavior.\n */\nasync function installEmscripten(emsdkDir: string /*, options?: { verbose?: boolean }*/): Promise<void> {\n // Only download if the emsdk directory wasn't restored from a cache\n if (!existsSync(emsdkDir)) {\n console.log(`Downloading Emscripten SDK to ${emsdkDir}`)\n // console.log()\n await execa('git', ['clone', 'https://github.com/emscripten-core/emsdk.git', emsdkDir])\n } else {\n console.log(`Found existing Emscripten SDK directory: ${emsdkDir}`)\n }\n // console.log()\n\n if (process.env.CI) {\n // On GitHub Actions, remove the `.git` directory to keep the cache smaller.\n // When we update to a new version, the cache key will miss and the emsdk\n // repo will be redownloaded.\n console.log('CI detected, removing .git directory...')\n const gitDir = joinPath(emsdkDir, '.git')\n rmSync(gitDir, { recursive: true, force: true })\n } else {\n // For local development, pull to get the latest\n console.log('Local development detected, performing git pull...')\n await execa('git', ['pull'], { cwd: emsdkDir })\n // console.log()\n }\n\n const emsdkCmd = async (...args: string[]) => {\n return execa('python3', ['emsdk.py', ...args], { cwd: emsdkDir })\n }\n\n console.log(`Activating Emscripten SDK ${version}...`)\n await emsdkCmd('install', version)\n await emsdkCmd('activate', version)\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execaCommand } from 'execa'\nimport { cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseGitInit(projDir: string, args: Arguments): Promise<void> {\n // Prompt the user\n const gitResponse = await prompts(\n {\n type: 'confirm',\n name: 'git',\n message: `Would you like to initialize a new git repository? ${reset(dim('(optional)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled. Your project folder has already been created.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!gitResponse.git) {\n ora().info(dim(`No problem! You can come back and run ${cyan(`git init`)} later.`))\n return\n }\n\n // Init git repo\n try {\n await execaCommand('git init', { cwd: projDir })\n ora().succeed(green('Git repository initialized!'))\n } catch {\n ora().warn(\n yellow(\n `There was a problem initializing the Git repository, but no problem, you can run ${cyan(`git init`)} later.`\n )\n )\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { readdir } from 'fs/promises'\nimport { relative, resolve as resolvePath, sep, posix, extname } from 'path'\n\nimport { bold, dim, green, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\n// The set of supported model file extensions; this should match the set defined in the cli package\nconst supportedModelFileExtensions = new Set(['.mdl', '.xmile', '.stmx', '.itmx'])\n\nexport async function chooseModelFile(projDir: string): Promise<string | undefined> {\n // Find all supported model files in the project directory\n // From https://stackoverflow.com/a/45130990\n async function getFiles(dir: string): Promise<string[]> {\n const dirents = await readdir(dir, { withFileTypes: true })\n const files = await Promise.all(\n dirents.map(dirent => {\n const res = resolvePath(dir, dirent.name)\n return dirent.isDirectory() ? getFiles(res) : res\n })\n )\n return files.flat()\n }\n const allFiles = await getFiles(projDir)\n const modelFiles = allFiles\n // Only include files that have a supported extension\n .filter(f => {\n const ext = extname(f).toLowerCase()\n return supportedModelFileExtensions.has(ext)\n })\n // Convert to a relative path with POSIX path separators (we want\n // paths in the 'sde.config.js' file to use POSIX path style only,\n // since that works on any OS including Windows)\n .map(f => relative(projDir, f).replaceAll(sep, posix.sep))\n const modelChoices = modelFiles.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n\n let modelFile: string\n if (modelFiles.length === 0) {\n // No model files found; return undefined so that the model from the template is copied over\n ora(\n yellow(`No model files were found in \"${projDir}\". The model file from the template will be used instead.`)\n ).warn()\n modelFile = undefined\n } else if (modelFiles.length === 1) {\n // Only one model file\n modelFile = modelFiles[0]\n ora().succeed(`Found \"${modelFile}\", will configure the project to use that model file.`)\n } else {\n // Multiple model files found; allow the user to choose one\n // TODO: Eventually we should allow the user to choose to flatten if there are multiple submodels\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'modelFile',\n message: 'It looks like there are multiple model files. Which one would you like to use?',\n choices: modelChoices\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n modelFile = options.modelFile\n ora(green(`Using \"${bold(modelFile)}\" as the model for the project.`)).succeed()\n }\n\n return modelFile\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, mkdtempSync, readdirSync, renameSync, rmSync } from 'fs'\nimport { writeFile } from 'fs/promises'\nimport { copy } from 'fs-extra'\nimport { tmpdir } from 'os'\nimport { join as joinPath } from 'path'\n\nimport { downloadTemplate } from 'giget'\nimport { bold, dim, green, red, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nconst TEMPLATES = [\n {\n title: 'Svelte project (recommended)',\n description: 'Includes recommended structure with config files, Svelte-based app, core library, model-check, etc',\n value: 'svelte'\n },\n {\n title: 'jQuery project',\n description: 'Includes recommended structure with config files, jQuery-based app, core library, model-check, etc',\n value: 'jquery'\n },\n {\n title: 'Minimal project',\n description: 'Includes simple config for model-check',\n value: 'minimal'\n }\n]\n\ninterface Template {\n /** The template URI that can be passed to `giget` to download the template. */\n uri: string\n /** The template name that will be displayed to the user. */\n name: string\n}\n\nexport async function chooseTemplate(args: Arguments): Promise<Template> {\n let templateName: string\n if (args.template) {\n // Allow template name or repository to be provided on command line\n templateName = args.template\n } else {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'template',\n message: 'Which template would you like to use?',\n choices: TEMPLATES\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n templateName = options.template\n }\n\n // Allow branch name or commit hash to be overridden on command line\n const defaultRev = 'main'\n const commit = args.commit || defaultRev\n\n // Construct the template repository URL\n let baseTemplateUri: string\n if (templateName.includes(':')) {\n // Assume the template name is already in the form of a giget template, for example:\n // github:owner/repo\n // gitlab:owner/repo\n baseTemplateUri = templateName\n } else if (templateName.includes('/')) {\n // Assume the template name is a GitHub repository name, for example:\n // owner/repo\n baseTemplateUri = `github:${templateName}`\n } else {\n // Otherwise, assume the template name is one of the available `template-*`\n // projects under `examples` in the SDEverywhere repository, for example:\n // svelte\n // jquery\n // minimal\n baseTemplateUri = `github:climateinteractive/SDEverywhere/examples/template-${templateName}`\n }\n const templateUri = `${baseTemplateUri}#${commit}`\n\n ora(green(`Using \"${bold(templateUri)}\" as the template for the project.`)).succeed()\n\n return {\n uri: templateUri,\n name: templateName\n }\n}\n\nexport async function copyTemplate(\n template: Template,\n projDir: string,\n pkgManager: string,\n configDirExisted: boolean,\n modelExisted: boolean\n): Promise<void> {\n // Show a spinner while copying the template files\n const templateSpinner = ora('Copying template files...').start()\n\n try {\n // Make giget write to a temporary directory\n const tmpDir = mkdtempSync(joinPath(tmpdir(), 'sde-create-'))\n\n // Use giget to download the template (we will be writing to a temporary directory,\n // so `force` is safe)\n await downloadTemplate(template.uri, {\n force: true,\n dir: tmpDir\n })\n\n // In case giget doesn't return an error when an invalid template is provided, check\n // that the temporary directory is non-empty\n if (!existsSync(tmpDir) || readdirSync(tmpDir).length === 0) {\n throw new Error('Failed to download the requested template: the temporary directory is empty.')\n }\n\n if (configDirExisted) {\n // There is already a `config` directory in the project directory; remove the\n // `config` directory from the template so that we don't write files from the\n // template that conflict with the existing files\n rmSync(joinPath(tmpDir, 'config'), { recursive: true, force: true })\n }\n\n if (modelExisted) {\n // There is already a model file in the project directory; remove the `model`\n // directory (including the model file and the model-check yaml files) from the\n // template so that we don't copy them into the project directory\n rmSync(joinPath(tmpDir, 'model'), { recursive: true, force: true })\n }\n\n // Copy files to destination without overwriting\n await copy(tmpDir, projDir, {\n overwrite: false,\n errorOnExist: false\n })\n\n if (!modelExisted) {\n // There wasn't already a model file in the project directory, so we will use\n // the one supplied by the template. Rename it from `MODEL_NAME.mdl` to\n // `sample.mdl`.\n // TODO: For now we assume that all templates include a sample model in Vensim\n // format. This will need to be updated if we add templates that include a\n // sample model in a different format.\n renameSync(joinPath(projDir, 'model', 'MODEL_NAME.mdl'), joinPath(projDir, 'model', 'sample.mdl'))\n }\n\n // Remove the temporary directory\n rmSync(tmpDir, { recursive: true, force: true })\n } catch (e) {\n // The download failed; show an error message\n // TODO: Handle common download issues; for now, just log the error message and exit\n templateSpinner.fail()\n console.error(red(e.message))\n console.error(yellow('\\nThere was a problem copying the template.'))\n console.error(\n yellow(\n 'Please start a new discussion thread and include the command output so that we can help:\\n https://github.com/climateinteractive/SDEverywhere/discussions/categories/q-a\\n'\n )\n )\n process.exit(0)\n }\n\n if (existsSync(joinPath(projDir, 'packages')) && pkgManager === 'pnpm') {\n // When using pnpm and the template has a `packages` folder (i.e., it has a monorepo\n // layout), we need to write a `pnpm-workspace.yaml` file since pnpm doesn't use the\n // \"workspaces\" config from `package.json` (like npm and yarn use)\n const workspaceFile = joinPath(projDir, 'pnpm-workspace.yaml')\n const workspaceContent = `packages:\\n - packages/*\\n`\n await writeFile(workspaceFile, workspaceContent)\n }\n\n templateSpinner.text = green('Template copied!')\n templateSpinner.succeed()\n}\n"],"mappings":"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","names":["import_fs","import_path","import_colors","import_ora","import_prompts","prompts","ora","import_colors","import_ora","import_prompts","joinPath","ora","prompts","resolvePath","parsePath","import_colors","import_ora","import_prompts","prompts","ora","import_fs","import_path","import_colors","import_ora","import_prompts","resolvePath","ora","prompts","import_fs","import_path","import_execa","import_colors","import_ora","import_prompts","ora","resolvePath","joinPath","prompts","import_execa","import_colors","import_ora","import_prompts","prompts","ora","import_promises","import_path","import_colors","import_ora","import_prompts","resolvePath","ora","prompts","import_fs","import_promises","import_path","import_colors","import_ora","import_prompts","prompts","ora","joinPath","detectPackageManager","yargs","prompts","ora","resolvePath"]}
package/dist/index.js CHANGED
@@ -106,11 +106,11 @@ var sampleComparisonsContent = `# yaml-language-server: $schema=SCHEMA_PATH
106
106
  - input: Another input
107
107
  at: 20
108
108
  `;
109
- async function updateSdeConfig(projDir, mdlPath, genFormat) {
109
+ async function updateSdeConfig(projDir, modelPath, genFormat) {
110
110
  const configPath = joinPath(projDir, "sde.config.js");
111
111
  let configText = await readFile(configPath, "utf8");
112
112
  configText = configText.replace(`const genFormat = 'js'`, `const genFormat = '${genFormat}'`);
113
- configText = configText.replaceAll("model/MODEL_NAME.mdl", mdlPath);
113
+ configText = configText.replaceAll("model/MODEL_NAME.mdl", modelPath);
114
114
  await writeFile(configPath, configText);
115
115
  }
116
116
  async function generateYaml(projDir, kind, template) {
@@ -134,14 +134,14 @@ async function generateSampleYamlFiles(projDir) {
134
134
  await generateYaml(projDir, "checks", sampleChecksContent);
135
135
  await generateYaml(projDir, "comparisons", sampleComparisonsContent);
136
136
  }
137
- async function chooseGenConfig(projDir, mdlPath) {
137
+ async function chooseGenConfig(projDir, modelPath) {
138
138
  let mdlVars;
139
139
  try {
140
- mdlVars = await readModelVars(projDir, mdlPath);
140
+ mdlVars = await readModelVars(projDir, modelPath);
141
141
  } catch (e) {
142
142
  console.log(e);
143
143
  ora2(
144
- yellow("The mdl file failed to load. We will continue setting things up, and you can diagnose the issue later.")
144
+ yellow("The model file failed to load. We will continue setting things up, and you can diagnose the issue later.")
145
145
  ).warn();
146
146
  return;
147
147
  }
@@ -389,16 +389,17 @@ function inputsCsvLine(inputVarName, defaultValue, id) {
389
389
  function escapeCsvField(s) {
390
390
  return s.includes(",") ? `"${s}"` : s;
391
391
  }
392
- async function readModelVars(projDir, mdlPath) {
392
+ async function readModelVars(projDir, modelPath) {
393
393
  const buildDir = resolvePath(projDir, "sde-prep", "build");
394
394
  await mkdir(buildDir, { recursive: true });
395
395
  const spec = {};
396
- const mdlFile = resolvePath(projDir, mdlPath);
397
- const mdlContent = await readFile(mdlFile, "utf8");
398
- const mdlDir = dirname(mdlFile);
399
- const mdlName = parsePath(mdlFile).name;
400
- await parseAndGenerate(mdlContent, spec, ["printVarList"], mdlDir, mdlName, buildDir);
401
- const jsonListFile = joinPath(buildDir, `${mdlName}.json`);
396
+ const modelFile = resolvePath(projDir, modelPath);
397
+ const modelContent = await readFile(modelFile, "utf8");
398
+ const modelKind = modelContent.includes("<xmile") ? "xmile" : "vensim";
399
+ const modelDir = dirname(modelFile);
400
+ const modelName = parsePath(modelFile).name;
401
+ await parseAndGenerate(modelContent, modelKind, spec, ["printVarList"], modelDir, modelName, buildDir);
402
+ const jsonListFile = joinPath(buildDir, `${modelName}.json`);
402
403
  const jsonListContent = await readFile(jsonListFile, "utf8");
403
404
  const jsonList = JSON.parse(jsonListContent);
404
405
  const varObjs = jsonList.variables;
@@ -696,13 +697,14 @@ async function chooseGitInit(projDir, args) {
696
697
  }
697
698
  }
698
699
 
699
- // src/step-mdl.ts
700
+ // src/step-model-file.ts
700
701
  import { readdir } from "fs/promises";
701
- import { relative as relative2, resolve as resolvePath4, sep, posix } from "path";
702
+ import { relative as relative2, resolve as resolvePath4, sep, posix, extname } from "path";
702
703
  import { bold as bold6, dim as dim7, green as green7, yellow as yellow4 } from "kleur/colors";
703
704
  import ora7 from "ora";
704
705
  import prompts7 from "prompts";
705
- async function chooseMdlFile(projDir) {
706
+ var supportedModelFileExtensions = /* @__PURE__ */ new Set([".mdl", ".xmile", ".stmx", ".itmx"]);
707
+ async function chooseModelFile(projDir) {
706
708
  async function getFiles(dir) {
707
709
  const dirents = await readdir(dir, { withFileTypes: true });
708
710
  const files = await Promise.all(
@@ -714,28 +716,33 @@ async function chooseMdlFile(projDir) {
714
716
  return files.flat();
715
717
  }
716
718
  const allFiles = await getFiles(projDir);
717
- const mdlFiles = allFiles.filter((f) => f.endsWith(".mdl")).map((f) => relative2(projDir, f).replaceAll(sep, posix.sep));
718
- const mdlChoices = mdlFiles.map((f) => {
719
+ const modelFiles = allFiles.filter((f) => {
720
+ const ext = extname(f).toLowerCase();
721
+ return supportedModelFileExtensions.has(ext);
722
+ }).map((f) => relative2(projDir, f).replaceAll(sep, posix.sep));
723
+ const modelChoices = modelFiles.map((f) => {
719
724
  return {
720
725
  title: f,
721
726
  value: f
722
727
  };
723
728
  });
724
- let mdlFile;
725
- if (mdlFiles.length === 0) {
726
- ora7(yellow4(`No mdl files were found in "${projDir}". The mdl file from the template will be used instead.`)).warn();
727
- mdlFile = void 0;
728
- } else if (mdlFiles.length === 1) {
729
- mdlFile = mdlFiles[0];
730
- ora7().succeed(`Found "${mdlFile}", will configure the project to use that mdl file.`);
729
+ let modelFile;
730
+ if (modelFiles.length === 0) {
731
+ ora7(
732
+ yellow4(`No model files were found in "${projDir}". The model file from the template will be used instead.`)
733
+ ).warn();
734
+ modelFile = void 0;
735
+ } else if (modelFiles.length === 1) {
736
+ modelFile = modelFiles[0];
737
+ ora7().succeed(`Found "${modelFile}", will configure the project to use that model file.`);
731
738
  } else {
732
739
  const options = await prompts7(
733
740
  [
734
741
  {
735
742
  type: "select",
736
- name: "mdlFile",
737
- message: "It looks like there are multiple mdl files. Which one would you like to use?",
738
- choices: mdlChoices
743
+ name: "modelFile",
744
+ message: "It looks like there are multiple model files. Which one would you like to use?",
745
+ choices: modelChoices
739
746
  }
740
747
  ],
741
748
  {
@@ -745,10 +752,10 @@ async function chooseMdlFile(projDir) {
745
752
  }
746
753
  }
747
754
  );
748
- mdlFile = options.mdlFile;
749
- ora7(green7(`Using "${bold6(mdlFile)}" as the model for the project.`)).succeed();
755
+ modelFile = options.modelFile;
756
+ ora7(green7(`Using "${bold6(modelFile)}" as the model for the project.`)).succeed();
750
757
  }
751
- return mdlFile;
758
+ return modelFile;
752
759
  }
753
760
 
754
761
  // src/step-template.ts
@@ -818,7 +825,7 @@ async function chooseTemplate(args) {
818
825
  name: templateName
819
826
  };
820
827
  }
821
- async function copyTemplate(template, projDir, pkgManager, configDirExisted, mdlExisted) {
828
+ async function copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted) {
822
829
  const templateSpinner = ora8("Copying template files...").start();
823
830
  try {
824
831
  const tmpDir = mkdtempSync(joinPath3(tmpdir(), "sde-create-"));
@@ -832,14 +839,14 @@ async function copyTemplate(template, projDir, pkgManager, configDirExisted, mdl
832
839
  if (configDirExisted) {
833
840
  rmSync2(joinPath3(tmpDir, "config"), { recursive: true, force: true });
834
841
  }
835
- if (mdlExisted) {
842
+ if (modelExisted) {
836
843
  rmSync2(joinPath3(tmpDir, "model"), { recursive: true, force: true });
837
844
  }
838
845
  await copy(tmpDir, projDir, {
839
846
  overwrite: false,
840
847
  errorOnExist: false
841
848
  });
842
- if (!mdlExisted) {
849
+ if (!modelExisted) {
843
850
  renameSync(joinPath3(projDir, "model", "MODEL_NAME.mdl"), joinPath3(projDir, "model", "sample.mdl"));
844
851
  }
845
852
  rmSync2(tmpDir, { recursive: true, force: true });
@@ -883,19 +890,19 @@ ${bold8("Welcome to SDEverywhere!")}`);
883
890
  const configDirExisted = existsSync5(resolvePath5(projDir, "config"));
884
891
  const template = await chooseTemplate(args);
885
892
  console.log();
886
- let mdlPath = await chooseMdlFile(projDir);
887
- const mdlExisted = mdlPath !== void 0;
893
+ let modelPath = await chooseModelFile(projDir);
894
+ const modelExisted = modelPath !== void 0;
888
895
  console.log();
889
896
  if (!args.dryRun) {
890
- await copyTemplate(template, projDir, pkgManager, configDirExisted, mdlExisted);
897
+ await copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted);
891
898
  console.log();
892
899
  }
893
- if (mdlPath === void 0) {
894
- mdlPath = `model${posix2.sep}sample.mdl`;
900
+ if (modelPath === void 0) {
901
+ modelPath = `model${posix2.sep}sample.mdl`;
895
902
  }
896
903
  const genFormat = await chooseCodeFormat();
897
904
  if (!args.dryRun) {
898
- await updateSdeConfig(projDir, mdlPath, genFormat);
905
+ await updateSdeConfig(projDir, modelPath, genFormat);
899
906
  const modelCheckFilesExist = existsSync5(resolvePath5(projDir, "model", "checks")) || existsSync5(resolvePath5(projDir, "model", "comparisons"));
900
907
  if (!modelCheckFilesExist) {
901
908
  await generateSampleYamlFiles(projDir);
@@ -910,8 +917,8 @@ ${bold8("Welcome to SDEverywhere!")}`);
910
917
  console.log();
911
918
  } else {
912
919
  const configDirExistsNow = existsSync5(resolvePath5(projDir, "config"));
913
- if (configDirExistsNow && mdlExisted && !args.dryRun) {
914
- await chooseGenConfig(projDir, mdlPath);
920
+ if (configDirExistsNow && modelExisted && !args.dryRun) {
921
+ await chooseGenConfig(projDir, modelPath);
915
922
  console.log();
916
923
  }
917
924
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/step-code-format.ts","../src/step-config.ts","../src/step-deps.ts","../src/step-directory.ts","../src/step-emsdk.ts","../src/step-git.ts","../src/step-mdl.ts","../src/step-template.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { posix, relative, resolve as resolvePath } from 'path'\n\nimport { bgCyan, black, bold, cyan, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport detectPackageManager from 'which-pm-runs'\nimport yargs from 'yargs-parser'\n\nimport { chooseCodeFormat } from './step-code-format'\nimport { chooseGenConfig, generateSampleYamlFiles, updateSdeConfig } from './step-config'\nimport { chooseInstallDeps } from './step-deps'\nimport { chooseProjectDir } from './step-directory'\nimport { chooseInstallEmsdk } from './step-emsdk'\nimport { chooseGitInit } from './step-git'\nimport { chooseMdlFile } from './step-mdl'\nimport { chooseTemplate, copyTemplate } from './step-template'\n\nexport async function main(): Promise<void> {\n // Detect the package manager\n const pkgManager = detectPackageManager()?.name || 'npm'\n\n // Parse command line arguments\n const args = yargs(process.argv)\n prompts.override(args)\n\n if (args.dryRun) {\n console.log()\n ora().info(dim(`--dry-run enabled, no files will be written.`))\n }\n\n // Display welcome message\n console.log(`\\n${bold('Welcome to SDEverywhere!')}`)\n console.log(`Let's create a new SDEverywhere project for your model.\\n`)\n\n // Prompt the user to select a project directory\n const projDir = await chooseProjectDir(args)\n console.log()\n\n // See if there is a pre-existing `config` directory\n const configDirExisted = existsSync(resolvePath(projDir, 'config'))\n\n // Prompt the user to select a template\n const template = await chooseTemplate(args)\n console.log()\n\n // Prompt the user to select an mdl file\n let mdlPath = await chooseMdlFile(projDir)\n const mdlExisted = mdlPath !== undefined\n console.log()\n\n if (!args.dryRun) {\n // Copy the template files to the project directory\n await copyTemplate(template, projDir, pkgManager, configDirExisted, mdlExisted)\n console.log()\n }\n\n if (mdlPath === undefined) {\n // There wasn't already an mdl file in the project directory, so we will use\n // the one supplied by the template. The template is expected to have a\n // `model/MODEL_NAME.mdl` file, which gets renamed to `model/sample.mdl`\n // in the `copyTemplate` step. Note that `chooseMdlFile` returns a\n // POSIX-style relative path, so we will also use a relative path here.\n mdlPath = `model${posix.sep}sample.mdl`\n }\n\n // Prompt the user to select a code generation format\n const genFormat = await chooseCodeFormat()\n\n if (!args.dryRun) {\n // Update the `sde.config.js` file to use the chosen mdl file\n await updateSdeConfig(projDir, mdlPath, genFormat)\n\n // Generate sample `checks.yaml` and `comparisons.yaml` files if needed\n const modelCheckFilesExist =\n existsSync(resolvePath(projDir, 'model', 'checks')) || existsSync(resolvePath(projDir, 'model', 'comparisons'))\n if (!modelCheckFilesExist) {\n await generateSampleYamlFiles(projDir)\n }\n }\n console.log()\n\n if (configDirExisted) {\n // There was already a `config` directory, so don't offer to set up CSV files\n ora().succeed(`Found existing \"${bold('config')}\" directory.`)\n ora().info(\n dim(`You can edit the files in the \"${cyan('config')}\" directory later to configure graphs and sliders.`)\n )\n console.log()\n } else {\n // There wasn't already a `config` directory, but there was already an mdl file,\n // so offer to set up CSV files\n const configDirExistsNow = existsSync(resolvePath(projDir, 'config'))\n if (configDirExistsNow && mdlExisted && !args.dryRun) {\n await chooseGenConfig(projDir, mdlPath)\n console.log()\n }\n }\n\n // If the user chose C as the code generation format, prompt the user to\n // install Emscripten SDK\n if (genFormat === 'c') {\n await chooseInstallEmsdk(projDir, args)\n console.log()\n }\n\n // Prompt the user to install dependencies\n await chooseInstallDeps(projDir, args, pkgManager)\n console.log()\n\n // Prompt the user to initialize a git repo\n await chooseGitInit(projDir, args)\n console.log()\n\n ora(green('Setup complete!')).succeed()\n\n console.log(`\\n${bgCyan(black(' Next steps '))}\\n`)\n\n const relProjDir = relative(process.cwd(), projDir)\n const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`\n\n // If the project dir is the current dir, no need to tell users to cd\n if (relProjDir !== '') {\n console.log(`You can now ${bold(cyan('cd'))} into the ${bold(cyan(relProjDir))} project directory.`)\n }\n console.log(`Run ${bold(cyan(devCmd))} to start the local dev server. ${bold(cyan('CTRL-C'))} to close.`)\n console.log('')\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { bold, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\n\nconst promptMessage = `Would you like your project to use WebAssembly?`\n\nconst noDesc = `\\\n* Choose this if you want to get started using SDEverywhere quickly\nand you don't want to install the Emscripten SDK.\n* This will generate a model that uses JavaScript code only, which\ndoesn't require extra build tools, but runs slower than WebAssembly.`\nconst yesDesc = `\\\n* Choose this if you want this script to install the Emscripten SDK\nfor you, or if you already have it installed.\n* This will generate a model that uses WebAssembly, which requires an\nadditional build step, but runs faster than pure JavaScript code.`\n\nconst FORMATS = [\n {\n title: 'No, generate a JavaScript model',\n description: noDesc,\n value: 'js'\n },\n {\n title: 'Yes, generate a WebAssembly model',\n description: yesDesc,\n value: 'c'\n }\n]\n\nexport async function chooseCodeFormat(): Promise<string> {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'format',\n message: promptMessage,\n choices: FORMATS\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n const target = options.format === 'c' ? 'WebAssembly' : 'JavaScript'\n const successMessage = green(\n `Configuring your project to generate ${target}. See \"${bold('sde.config.js')}\" for details.`\n )\n ora(successMessage).succeed()\n\n return options.format\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { mkdir, readFile, writeFile } from 'fs/promises'\nimport { dirname, join as joinPath, parse as parsePath, relative, resolve as resolvePath } from 'path'\n\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\nimport { parseAndGenerate } from '@sdeverywhere/compile'\n\ninterface MdlConstVariable {\n kind: 'const'\n name: string\n value: number\n}\n\ninterface MdlAuxVariable {\n kind: 'aux'\n name: string\n}\n\ninterface MdlLevelVariable {\n kind: 'level'\n name: string\n}\n\ntype MdlVariable = MdlConstVariable | MdlAuxVariable | MdlLevelVariable\n\nconst sampleChecksContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains \"check\" tests that exercise your model under different input\n# scenarios. For more guidance, consult this wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a simple check just to get you started.\n# Replace \"Some output\" with the name of some variable you'd like to test.\n- describe: Some output\n tests:\n - it: should be > 0 for all input scenarios\n scenarios:\n - preset: matrix\n datasets:\n - name: Some output\n predicates:\n - gt: 0\n`\n\nconst sampleComparisonsContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains definitions of custom comparison scenarios, which allow you to see\n# how the behavior of the model compares to that of previous versions. For more guidance,\n# consult the following wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a custom scenario just to get you started.\n# Replace \"Some input\" and \"Another input\" with the names of some variables you'd\n# like to test.\n- scenario:\n title: Custom scenario\n subtitle: gradual ramp-up\n with:\n - input: Some input\n at: 10\n - input: Another input\n at: 20\n`\n\nexport async function updateSdeConfig(projDir: string, mdlPath: string, genFormat: string): Promise<void> {\n // Read the `sde.config.js` file from the template\n const configPath = joinPath(projDir, 'sde.config.js')\n let configText = await readFile(configPath, 'utf8')\n\n // Set the code generation format to the chosen format\n configText = configText.replace(`const genFormat = 'js'`, `const genFormat = '${genFormat}'`)\n\n // Replace instances of `model/MODEL_NAME.mdl` with the path to the chosen mdl file\n configText = configText.replaceAll('model/MODEL_NAME.mdl', mdlPath)\n\n // Write the updated file\n await writeFile(configPath, configText)\n}\n\nasync function generateYaml(projDir: string, kind: 'checks' | 'comparisons', template: string): Promise<void> {\n const yamlDir = joinPath(projDir, 'model', kind)\n const yamlPath = joinPath(yamlDir, `${kind}.yaml`)\n if (!existsSync(yamlPath)) {\n // Get relative path from yaml file parent dir to project dir\n let relProjPath = relative(dirname(yamlPath), projDir)\n if (relProjPath.length === 0) {\n relProjPath = './'\n }\n\n // Create the directory for the yaml file, if needed\n await mkdir(yamlDir, { recursive: true })\n\n // TODO: This path is normally different depending on whether using npm/yarn or\n // pnpm. For npm/yarn, `check-core` is hoisted under top-level `node_modules`,\n // but for pnpm, it is nested under `node_modules/.pnpm`. As an ugly workaround\n // the templates declare `check-core` as a direct dependency even though it is\n // not really needed (a transitive dependency via `plugin-check` would normally\n // suffice). This allows us to use the same path here that works for all\n // three package managers.\n const nodeModulesPart = joinPath(relProjPath, 'node_modules')\n const schemaName = kind === 'checks' ? 'check' : 'comparison'\n const checkCorePart = `@sdeverywhere/check-core/schema/${schemaName}.schema.json`\n const schemaPath = `${nodeModulesPart}/${checkCorePart}`\n const yamlContent = template.replace('SCHEMA_PATH', schemaPath)\n await writeFile(yamlPath, yamlContent)\n }\n}\n\nexport async function generateSampleYamlFiles(projDir: string): Promise<void> {\n // Generate a sample `checks.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'checks', sampleChecksContent)\n\n // Generate a sample `comparisons.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'comparisons', sampleComparisonsContent)\n}\n\nexport async function chooseGenConfig(projDir: string, mdlPath: string): Promise<void> {\n // TODO: For now we eagerly read the mdl file; maybe change this to only load it if\n // the user chooses to generate graph and/or slider config\n let mdlVars: MdlVariable[]\n try {\n // Get the list of variables available in the model\n mdlVars = await readModelVars(projDir, mdlPath)\n } catch (e) {\n console.log(e)\n ora(\n yellow('The mdl file failed to load. We will continue setting things up, and you can diagnose the issue later.')\n ).warn()\n return\n }\n\n // Extract `INITIAL TIME` and `FINAL TIME` values and remove special control variables from the list\n let initialTime: number\n let finalTime: number\n const validVars: MdlVariable[] = []\n for (const v of mdlVars) {\n const varName = v.name.toLowerCase()\n let skip = false\n switch (varName) {\n case 'final time':\n skip = true\n if (v.kind === 'const') {\n finalTime = v.value\n }\n break\n case 'initial time':\n skip = true\n if (v.kind === 'const') {\n initialTime = v.value\n }\n break\n case 'saveper':\n case 'time':\n case 'time step':\n skip = true\n break\n default:\n break\n }\n if (!skip) {\n validVars.push(v)\n }\n }\n\n // Set the values in `model.csv`\n if (initialTime === undefined) {\n initialTime = 0\n }\n if (finalTime === undefined) {\n finalTime = 100\n }\n\n // TODO: Auto-detect dat files that are referenced by the mdl and include them here\n const datFiles: string[] = []\n const datPart = datFiles.join(';')\n\n // Preserve the `model.csv` header but drop other existing content (if any)\n const modelCsvFile = joinPath(projDir, 'config', 'model.csv')\n const origModelCsvContent = await readFile(modelCsvFile, 'utf8')\n const modelCsvHeader = origModelCsvContent.split('\\n')[0]\n\n // Disable bundled listing and customization features by default\n const bundleListing = 'false'\n const customConstants = 'false'\n const customLookups = 'false'\n const customOutputs = 'false'\n\n // Add line and write out updated `model.csv`\n const modelCsvLine = `${initialTime},${finalTime},${datPart},${bundleListing},${customConstants},${customLookups},${customOutputs}`\n const newModelCsvContent = `${modelCsvHeader}\\n${modelCsvLine}\\n`\n await writeFile(modelCsvFile, newModelCsvContent)\n\n // See if the user wants to generate graph config\n await chooseGenGraphConfig(projDir, validVars)\n console.log()\n\n // See if the user wants to generate slider config\n await chooseGenSliderConfig(projDir, validVars)\n}\n\nasync function chooseGenGraphConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genGraph',\n message: `Would you like to configure a graph to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genGraph) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available output variables\n const outputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'aux' || mdlVar.kind === 'level') {\n outputVarNames.push(mdlVar.name)\n }\n }\n outputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = outputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three output variables to display in the graph',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `graphs.csv` header but drop other existing content (if any)\n const graphsCsvFile = joinPath(projDir, 'config', 'graphs.csv')\n const origGraphsCsvContent = await readFile(graphsCsvFile, 'utf8')\n const graphsCsvHeader = origGraphsCsvContent.split('\\n')[0]\n\n // Write the updated `graphs.csv` file\n let newGraphsCsvContent = `${graphsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add line to `graphs.csv`\n const csvLine = graphsCsvLine(varsResponse.vars)\n newGraphsCsvContent += `${csvLine}\\n`\n }\n await writeFile(graphsCsvFile, newGraphsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n ora(\n green(`Added graph to \"${bold('config/graphs.csv')}\". ${dim('You can configure graphs in that file later.')}`)\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction graphsCsvLine(outputVarNames: string[]): string {\n const colors = ['blue', 'red', 'green']\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(131).fill('')\n // id\n a[0] = '1'\n // parent menu\n a[2] = 'Graphs'\n // graph title\n a[3] = 'Graph Title'\n // kind\n a[7] = 'line'\n // Plots start at 26\n let index = 26\n let colorIndex = 0\n for (const outputVarName of outputVarNames) {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(outputVarName)\n // plot N variable\n a[index + 0] = escapedName\n // plot N style\n a[index + 2] = 'line'\n // plot N label\n a[index + 3] = escapedName\n // plot N color\n a[index + 4] = colors[colorIndex]\n index += 7\n colorIndex++\n }\n\n return a.join(',')\n}\n\nasync function chooseGenSliderConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genSliders',\n message: `Would you like to configure a few sliders to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genSliders) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available input variables\n const inputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'const') {\n inputVarNames.push(mdlVar.name)\n }\n }\n inputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = inputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three input variables to control with sliders',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `inputs.csv` header but drop other existing content (if any)\n const inputsCsvFile = joinPath(projDir, 'config', 'inputs.csv')\n const origInputsCsvContent = await readFile(inputsCsvFile, 'utf8')\n const inputsCsvHeader = origInputsCsvContent.split('\\n')[0]\n\n // Write the updated `inputs.csv` file\n let newInputsCsvContent = `${inputsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add lines to `inputs.csv`\n let idNumber = 1\n for (const inputVarName of varsResponse.vars) {\n const inputVar = mdlVars.find(v => v.name === inputVarName)\n if (inputVar && inputVar.kind === 'const') {\n const defaultValue = inputVar.value\n const csvLine = inputsCsvLine(inputVarName, defaultValue, idNumber.toString())\n newInputsCsvContent += `${csvLine}\\n`\n idNumber++\n }\n }\n }\n await writeFile(inputsCsvFile, newInputsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n const slidersText = varsResponse.vars.length > 1 ? 'sliders' : 'sliders'\n ora(\n green(\n `Added ${slidersText} to \"${bold('config/inputs.csv')}\". ${dim('You can configure sliders in that file later.')}`\n )\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction inputsCsvLine(inputVarName: string, defaultValue: number, id: string): string {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(inputVarName)\n\n // TODO: Be smarter about automatically choosing min/max/step values\n const minValue = defaultValue - 1\n const maxValue = defaultValue + 1\n const step = 0.1\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(28).fill('')\n // id\n a[0] = id\n // input type\n a[1] = 'slider'\n // viewid\n a[2] = 'view1'\n // varname\n a[3] = escapedName\n // label\n a[4] = escapedName\n // group name\n a[6] = 'Sliders'\n // slider min\n a[7] = minValue\n // slider max\n a[8] = maxValue\n // slider default\n a[9] = defaultValue\n // slider step\n a[10] = step\n // units\n a[11] = '(units)'\n\n return a.join(',')\n}\n\nfunction escapeCsvField(s: string): string {\n // Surround the value in quotes if it contains a comma\n // TODO: Escape double quotes as well\n return s.includes(',') ? `\"${s}\"` : s\n}\n\nasync function readModelVars(projDir: string, mdlPath: string): Promise<MdlVariable[]> {\n // TODO: This function contains a subset of the logic from `sde-generate.js` in\n // the `cli` package; should revisit\n // let { modelDirname, modelName, modelPathname } = modelPathProps(model)\n\n // Ensure the `build` directory exists (under the `sde-prep` directory)\n const buildDir = resolvePath(projDir, 'sde-prep', 'build')\n await mkdir(buildDir, { recursive: true })\n\n // Use an empty model spec; this will make SDE look at all variables in the mdl\n const spec = {}\n\n // Try parsing the mdl file to generate the list of variables\n // TODO: This depends on some `compile` package APIs that are not yet considered stable.\n // Ideally we'd use an API that does not write files but instead returns an in-memory\n // object in a specified format.\n\n // Read the model file\n const mdlFile = resolvePath(projDir, mdlPath)\n const mdlContent = await readFile(mdlFile, 'utf8')\n\n // Parse the model and generate the variable list\n const mdlDir = dirname(mdlFile)\n const mdlName = parsePath(mdlFile).name\n await parseAndGenerate(mdlContent, spec, ['printVarList'], mdlDir, mdlName, buildDir)\n\n // Read `build/{mdl}.json`\n const jsonListFile = joinPath(buildDir, `${mdlName}.json`)\n const jsonListContent = await readFile(jsonListFile, 'utf8')\n const jsonList = JSON.parse(jsonListContent)\n const varObjs = jsonList.variables\n\n // Create a simplified array of variables\n const mdlVars: MdlVariable[] = []\n for (const varObj of varObjs) {\n // Only include certain variables for now\n // TODO: Include \"data\" vars\n switch (varObj.varType) {\n case 'const':\n mdlVars.push({\n kind: 'const',\n name: varObj.modelLHS,\n value: Number.parseFloat(varObj.modelFormula)\n })\n break\n case 'aux':\n mdlVars.push({\n kind: 'aux',\n name: varObj.modelLHS\n })\n break\n case 'level':\n mdlVars.push({\n kind: 'level',\n name: varObj.modelLHS\n })\n break\n default:\n break\n }\n }\n\n return mdlVars\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execa } from 'execa'\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseInstallDeps(projDir: string, args: Arguments, pkgManager: string): Promise<void> {\n // Prompt the user\n const installResponse = await prompts(\n {\n type: 'confirm',\n name: 'install',\n message: `Would you like to install ${pkgManager} dependencies? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(\n dim('Operation cancelled. Your project folder has been created, but no dependencies have been installed.')\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!installResponse.install) {\n ora().info(dim(`No problem! Remember to install dependencies after setup.`))\n return\n }\n\n // Install dependencies\n const installExec = execa(pkgManager, ['install'], { cwd: projDir })\n const installingPackagesMsg = 'Installing packages...'\n const installSpinner = ora(installingPackagesMsg).start()\n try {\n await new Promise<void>((resolve, reject) => {\n installExec.stdout?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.stderr?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.on('error', error => reject(error))\n installExec.on('close', code => {\n if (code !== 0) {\n reject(`Install failed (code=${code})`)\n } else {\n resolve()\n }\n })\n })\n installSpinner.text = green('Packages installed!')\n installSpinner.succeed()\n } catch {\n installSpinner.text = yellow(\n `There was an error installing packages. Try running ${cyan(\n `${pkgManager} install`\n )} in your project directory later.`\n )\n installSpinner.warn()\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { resolve as resolvePath } from 'path'\n\nimport { bold, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseProjectDir(args: Arguments): Promise<string> {\n /**\n * Return true if the given directory does not exist, or it does not contain important files\n * like `package.json`.\n */\n function isValidDir(dir: string): boolean {\n const packageJson = resolvePath(dir, 'package.json')\n const packagesDir = resolvePath(dir, 'packages')\n return !existsSync(dir) || (!existsSync(packageJson) && !existsSync(packagesDir))\n }\n\n const showValidDirMsg = (dir: string) => {\n ora(green(`Using \"${bold(dir)}\" as the project directory.`)).succeed()\n }\n\n const showInvalidDirMsg = (dir: string) => {\n ora(red(`\"${bold(dir)}\" contains existing 'package.json' and/or 'packages' directory, stopping.`)).fail()\n }\n\n // See if project directory is provided on command line\n let projDir = args['_'][2] as string\n if (projDir) {\n // Directory was provided, see if it is valid\n if (isValidDir(projDir)) {\n // The provided directory is valid, so proceed\n showValidDirMsg(projDir)\n } else {\n // The provided directory is not valid, so show error message and exit\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n } else {\n // Directory was not provided, so prompt the user\n const dirResponse = await prompts(\n {\n type: 'text',\n name: 'directory',\n message: 'Where would you like to create your new project?',\n initial: '<current directory>'\n // validate(value) {\n // if (value === '<current directory>') {\n // value = process.cwd()\n // }\n // if (!isValidDir(value)) {\n // return notValidMsg(value)\n // }\n // return true\n // }\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n projDir = dirResponse.directory\n if (projDir === '<current directory>') {\n projDir = process.cwd()\n }\n if (isValidDir(projDir)) {\n showValidDirMsg(projDir)\n } else {\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n }\n\n return projDir\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, rmSync } from 'fs'\nimport { join as joinPath, resolve as resolvePath } from 'path'\n\nimport { execa } from 'execa'\nimport { findUp } from 'find-up'\nimport { bold, cyan, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\n// TODO: Make this configurable; we're using this older version for now because it is\n// relatively stable and has been used to build En-ROADS and C-ROADS for a long time\nconst version = '2.0.34'\n\nexport async function chooseInstallEmsdk(projDir: string, args: Arguments): Promise<void> {\n // Walk up the directory structure to see if there is an existing `emsdk` directory\n const existingEmsdkDir = await findUp('emsdk', {\n cwd: projDir,\n type: 'directory'\n })\n if (existingEmsdkDir) {\n ora().succeed('Found existing Emscripten SDK installation.')\n ora().info(dim(`Your project will use \"${cyan(existingEmsdkDir)}\".`))\n return\n }\n\n // Prompt the user\n const underParentDir = resolvePath(projDir, '..', 'emsdk')\n const underProjDir = joinPath(projDir, 'emsdk')\n const installResponse = await prompts(\n {\n type: 'select',\n name: 'install',\n message: `Would you like to install the Emscripten SDK that is used to generate WebAssembly?`,\n choices: [\n // ${reset(dim('(recommended)'))\n {\n title: `Install under parent directory (${bold(underParentDir)})`,\n description: 'This is recommended so that it can be shared by multiple projects',\n value: 'parent'\n },\n {\n title: `Install under project directory (${bold(underProjDir)})\"`,\n description: 'This is useful for keeping everything under a single project directory',\n value: 'project'\n },\n {\n title: `Don't install`,\n description: `It's OK, you can install it later`,\n value: 'skip'\n }\n ]\n },\n {\n onCancel: () => {\n ora().info(\n dim(\n 'Operation cancelled. Your project folder has been created, but the Emscripten SDK and other dependencies have not been installed.'\n )\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (installResponse.install === 'skip') {\n ora().info(\n dim(\n `No problem! Be sure to install the Emscripten SDK and configure it in \"${cyan('sde.config.js')}\" after setup.`\n )\n )\n return\n }\n\n const installDir = installResponse.install === 'parent' ? underParentDir : underProjDir\n try {\n // TODO: Use spinner here\n await installEmscripten(installDir)\n } catch (e) {\n ora(red(`Failed to install Emscripten SDK: ${e.message}`)).fail()\n process.exit(0)\n }\n\n ora(green(`Installed the Emscripten SDK in \"${bold(installDir)}\"`)).succeed()\n}\n\n/**\n * Install the Emscripten SDK to the `emsdk` directory under the\n * given directory (if `emsdk` is not already present), then\n * activates the requested version (specified with `version`).\n *\n * The implementation is similar to the existing `setup-emsdk` action\n * (https://github.com/mymindstorm/setup-emsdk) except that one has issues\n * with the cache directory on Windows, so having our own script gives us\n * more control over installation and caching behavior.\n */\nasync function installEmscripten(emsdkDir: string /*, options?: { verbose?: boolean }*/): Promise<void> {\n // Only download if the emsdk directory wasn't restored from a cache\n if (!existsSync(emsdkDir)) {\n console.log(`Downloading Emscripten SDK to ${emsdkDir}`)\n // console.log()\n await execa('git', ['clone', 'https://github.com/emscripten-core/emsdk.git', emsdkDir])\n } else {\n console.log(`Found existing Emscripten SDK directory: ${emsdkDir}`)\n }\n // console.log()\n\n if (process.env.CI) {\n // On GitHub Actions, remove the `.git` directory to keep the cache smaller.\n // When we update to a new version, the cache key will miss and the emsdk\n // repo will be redownloaded.\n console.log('CI detected, removing .git directory...')\n const gitDir = joinPath(emsdkDir, '.git')\n rmSync(gitDir, { recursive: true, force: true })\n } else {\n // For local development, pull to get the latest\n console.log('Local development detected, performing git pull...')\n await execa('git', ['pull'], { cwd: emsdkDir })\n // console.log()\n }\n\n const emsdkCmd = async (...args: string[]) => {\n return execa('python3', ['emsdk.py', ...args], { cwd: emsdkDir })\n }\n\n console.log(`Activating Emscripten SDK ${version}...`)\n await emsdkCmd('install', version)\n await emsdkCmd('activate', version)\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execaCommand } from 'execa'\nimport { cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseGitInit(projDir: string, args: Arguments): Promise<void> {\n // Prompt the user\n const gitResponse = await prompts(\n {\n type: 'confirm',\n name: 'git',\n message: `Would you like to initialize a new git repository? ${reset(dim('(optional)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled. Your project folder has already been created.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!gitResponse.git) {\n ora().info(dim(`No problem! You can come back and run ${cyan(`git init`)} later.`))\n return\n }\n\n // Init git repo\n try {\n await execaCommand('git init', { cwd: projDir })\n ora().succeed(green('Git repository initialized!'))\n } catch {\n ora().warn(\n yellow(\n `There was a problem initializing the Git repository, but no problem, you can run ${cyan(`git init`)} later.`\n )\n )\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { readdir } from 'fs/promises'\nimport { relative, resolve as resolvePath, sep, posix } from 'path'\n\nimport { bold, dim, green, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\nexport async function chooseMdlFile(projDir: string): Promise<string | undefined> {\n // Find all `.mdl` files in the project directory\n // From https://stackoverflow.com/a/45130990\n async function getFiles(dir: string): Promise<string[]> {\n const dirents = await readdir(dir, { withFileTypes: true })\n const files = await Promise.all(\n dirents.map(dirent => {\n const res = resolvePath(dir, dirent.name)\n return dirent.isDirectory() ? getFiles(res) : res\n })\n )\n return files.flat()\n }\n const allFiles = await getFiles(projDir)\n const mdlFiles = allFiles\n // Only include files ending with '.mdl'\n .filter(f => f.endsWith('.mdl'))\n // Convert to a relative path with POSIX path separators (we want\n // paths in the 'sde.config.js' file to use POSIX path style only,\n // since that works on any OS including Windows)\n .map(f => relative(projDir, f).replaceAll(sep, posix.sep))\n const mdlChoices = mdlFiles.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n\n let mdlFile: string\n if (mdlFiles.length === 0) {\n // No mdl files found; return undefined so that the mdl from the template is copied over\n ora(yellow(`No mdl files were found in \"${projDir}\". The mdl file from the template will be used instead.`)).warn()\n mdlFile = undefined\n } else if (mdlFiles.length === 1) {\n // Only one mdl file\n mdlFile = mdlFiles[0]\n ora().succeed(`Found \"${mdlFile}\", will configure the project to use that mdl file.`)\n } else {\n // Multiple mdl files found; allow the user to choose one\n // TODO: Eventually we should allow the user to choose to flatten if there are multiple submodels\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'mdlFile',\n message: 'It looks like there are multiple mdl files. Which one would you like to use?',\n choices: mdlChoices\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n mdlFile = options.mdlFile\n ora(green(`Using \"${bold(mdlFile)}\" as the model for the project.`)).succeed()\n }\n\n return mdlFile\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, mkdtempSync, readdirSync, renameSync, rmSync } from 'fs'\nimport { writeFile } from 'fs/promises'\nimport { copy } from 'fs-extra'\nimport { tmpdir } from 'os'\nimport { join as joinPath } from 'path'\n\nimport { downloadTemplate } from 'giget'\nimport { bold, dim, green, red, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nconst TEMPLATES = [\n {\n title: 'Svelte project (recommended)',\n description: 'Includes recommended structure with config files, Svelte-based app, core library, model-check, etc',\n value: 'svelte'\n },\n {\n title: 'jQuery project',\n description: 'Includes recommended structure with config files, jQuery-based app, core library, model-check, etc',\n value: 'jquery'\n },\n {\n title: 'Minimal project',\n description: 'Includes simple config for model-check',\n value: 'minimal'\n }\n]\n\ninterface Template {\n /** The template URI that can be passed to `giget` to download the template. */\n uri: string\n /** The template name that will be displayed to the user. */\n name: string\n}\n\nexport async function chooseTemplate(args: Arguments): Promise<Template> {\n let templateName: string\n if (args.template) {\n // Allow template name or repository to be provided on command line\n templateName = args.template\n } else {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'template',\n message: 'Which template would you like to use?',\n choices: TEMPLATES\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n templateName = options.template\n }\n\n // Allow branch name or commit hash to be overridden on command line\n const defaultRev = 'main'\n const commit = args.commit || defaultRev\n\n // Construct the template repository URL\n let baseTemplateUri: string\n if (templateName.includes(':')) {\n // Assume the template name is already in the form of a giget template, for example:\n // github:owner/repo\n // gitlab:owner/repo\n baseTemplateUri = templateName\n } else if (templateName.includes('/')) {\n // Assume the template name is a GitHub repository name, for example:\n // owner/repo\n baseTemplateUri = `github:${templateName}`\n } else {\n // Otherwise, assume the template name is one of the available `template-*`\n // projects under `examples` in the SDEverywhere repository, for example:\n // svelte\n // jquery\n // minimal\n baseTemplateUri = `github:climateinteractive/SDEverywhere/examples/template-${templateName}`\n }\n const templateUri = `${baseTemplateUri}#${commit}`\n\n ora(green(`Using \"${bold(templateUri)}\" as the template for the project.`)).succeed()\n\n return {\n uri: templateUri,\n name: templateName\n }\n}\n\nexport async function copyTemplate(\n template: Template,\n projDir: string,\n pkgManager: string,\n configDirExisted: boolean,\n mdlExisted: boolean\n): Promise<void> {\n // Show a spinner while copying the template files\n const templateSpinner = ora('Copying template files...').start()\n\n try {\n // Make giget write to a temporary directory\n const tmpDir = mkdtempSync(joinPath(tmpdir(), 'sde-create-'))\n\n // Use giget to download the template (we will be writing to a temporary directory,\n // so `force` is safe)\n await downloadTemplate(template.uri, {\n force: true,\n dir: tmpDir\n })\n\n // In case giget doesn't return an error when an invalid template is provided, check\n // that the temporary directory is non-empty\n if (!existsSync(tmpDir) || readdirSync(tmpDir).length === 0) {\n throw new Error('Failed to download the requested template: the temporary directory is empty.')\n }\n\n if (configDirExisted) {\n // There is already a `config` directory in the project directory; remove the\n // `config` directory from the template so that we don't write files from the\n // template that conflict with the existing files\n rmSync(joinPath(tmpDir, 'config'), { recursive: true, force: true })\n }\n\n if (mdlExisted) {\n // There is already an mdl file in the project directory; remove the `model`\n // directory (including the mdl file and the model-check yaml files) from the\n // template so that we don't copy them into the project directory\n rmSync(joinPath(tmpDir, 'model'), { recursive: true, force: true })\n }\n\n // Copy files to destination without overwriting\n await copy(tmpDir, projDir, {\n overwrite: false,\n errorOnExist: false\n })\n\n if (!mdlExisted) {\n // There wasn't already an mdl file in the project directory, so we will use\n // the one supplied by the template. Rename it from `MODEL_NAME.mdl` to\n // `sample.mdl`.\n renameSync(joinPath(projDir, 'model', 'MODEL_NAME.mdl'), joinPath(projDir, 'model', 'sample.mdl'))\n }\n\n // Remove the temporary directory\n rmSync(tmpDir, { recursive: true, force: true })\n } catch (e) {\n // The download failed; show an error message\n // TODO: Handle common download issues; for now, just log the error message and exit\n templateSpinner.fail()\n console.error(red(e.message))\n console.error(yellow('\\nThere was a problem copying the template.'))\n console.error(\n yellow(\n 'Please start a new discussion thread and include the command output so that we can help:\\n https://github.com/climateinteractive/SDEverywhere/discussions/categories/q-a\\n'\n )\n )\n process.exit(0)\n }\n\n if (existsSync(joinPath(projDir, 'packages')) && pkgManager === 'pnpm') {\n // When using pnpm and the template has a `packages` folder (i.e., it has a monorepo\n // layout), we need to write a `pnpm-workspace.yaml` file since pnpm doesn't use the\n // \"workspaces\" config from `package.json` (like npm and yarn use)\n const workspaceFile = joinPath(projDir, 'pnpm-workspace.yaml')\n const workspaceContent = `packages:\\n - packages/*\\n`\n await writeFile(workspaceFile, workspaceContent)\n }\n\n templateSpinner.text = green('Template copied!')\n templateSpinner.succeed()\n}\n"],"mappings":"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","names":["existsSync","posix","relative","resolvePath","bold","cyan","dim","green","ora","prompts","bold","dim","green","ora","prompts","bold","cyan","dim","green","reset","yellow","ora","prompts","existsSync","resolvePath","bold","dim","green","ora","prompts","existsSync","joinPath","resolvePath","execa","bold","cyan","dim","green","red","ora","prompts","cyan","dim","green","reset","yellow","ora","prompts","relative","resolvePath","bold","dim","green","yellow","ora","prompts","existsSync","rmSync","writeFile","joinPath","bold","dim","green","red","yellow","ora","prompts","prompts","ora","dim","bold","existsSync","resolvePath","posix","cyan","green","relative"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/step-code-format.ts","../src/step-config.ts","../src/step-deps.ts","../src/step-directory.ts","../src/step-emsdk.ts","../src/step-git.ts","../src/step-model-file.ts","../src/step-template.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { posix, relative, resolve as resolvePath } from 'path'\n\nimport { bgCyan, black, bold, cyan, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport detectPackageManager from 'which-pm-runs'\nimport yargs from 'yargs-parser'\n\nimport { chooseCodeFormat } from './step-code-format'\nimport { chooseGenConfig, generateSampleYamlFiles, updateSdeConfig } from './step-config'\nimport { chooseInstallDeps } from './step-deps'\nimport { chooseProjectDir } from './step-directory'\nimport { chooseInstallEmsdk } from './step-emsdk'\nimport { chooseGitInit } from './step-git'\nimport { chooseModelFile } from './step-model-file'\nimport { chooseTemplate, copyTemplate } from './step-template'\n\nexport async function main(): Promise<void> {\n // Detect the package manager\n const pkgManager = detectPackageManager()?.name || 'npm'\n\n // Parse command line arguments\n const args = yargs(process.argv)\n prompts.override(args)\n\n if (args.dryRun) {\n console.log()\n ora().info(dim(`--dry-run enabled, no files will be written.`))\n }\n\n // Display welcome message\n console.log(`\\n${bold('Welcome to SDEverywhere!')}`)\n console.log(`Let's create a new SDEverywhere project for your model.\\n`)\n\n // Prompt the user to select a project directory\n const projDir = await chooseProjectDir(args)\n console.log()\n\n // See if there is a pre-existing `config` directory\n const configDirExisted = existsSync(resolvePath(projDir, 'config'))\n\n // Prompt the user to select a template\n const template = await chooseTemplate(args)\n console.log()\n\n // Prompt the user to select a model file\n let modelPath = await chooseModelFile(projDir)\n const modelExisted = modelPath !== undefined\n console.log()\n\n if (!args.dryRun) {\n // Copy the template files to the project directory\n await copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted)\n console.log()\n }\n\n if (modelPath === undefined) {\n // There wasn't already a model file in the project directory, so we will use\n // the one supplied by the template. The template is expected to have a\n // `model/MODEL_NAME.mdl` file, which gets renamed to `model/sample.mdl`\n // in the `copyTemplate` step. Note that `chooseModelFile` returns a\n // POSIX-style relative path, so we will also use a relative path here.\n modelPath = `model${posix.sep}sample.mdl`\n }\n\n // Prompt the user to select a code generation format\n const genFormat = await chooseCodeFormat()\n\n if (!args.dryRun) {\n // Update the `sde.config.js` file to use the chosen model file\n await updateSdeConfig(projDir, modelPath, genFormat)\n\n // Generate sample `checks.yaml` and `comparisons.yaml` files if needed\n const modelCheckFilesExist =\n existsSync(resolvePath(projDir, 'model', 'checks')) || existsSync(resolvePath(projDir, 'model', 'comparisons'))\n if (!modelCheckFilesExist) {\n await generateSampleYamlFiles(projDir)\n }\n }\n console.log()\n\n if (configDirExisted) {\n // There was already a `config` directory, so don't offer to set up CSV files\n ora().succeed(`Found existing \"${bold('config')}\" directory.`)\n ora().info(\n dim(`You can edit the files in the \"${cyan('config')}\" directory later to configure graphs and sliders.`)\n )\n console.log()\n } else {\n // There wasn't already a `config` directory, but there was already a model file,\n // so offer to set up CSV files\n const configDirExistsNow = existsSync(resolvePath(projDir, 'config'))\n if (configDirExistsNow && modelExisted && !args.dryRun) {\n await chooseGenConfig(projDir, modelPath)\n console.log()\n }\n }\n\n // If the user chose C as the code generation format, prompt the user to\n // install Emscripten SDK\n if (genFormat === 'c') {\n await chooseInstallEmsdk(projDir, args)\n console.log()\n }\n\n // Prompt the user to install dependencies\n await chooseInstallDeps(projDir, args, pkgManager)\n console.log()\n\n // Prompt the user to initialize a git repo\n await chooseGitInit(projDir, args)\n console.log()\n\n ora(green('Setup complete!')).succeed()\n\n console.log(`\\n${bgCyan(black(' Next steps '))}\\n`)\n\n const relProjDir = relative(process.cwd(), projDir)\n const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`\n\n // If the project dir is the current dir, no need to tell users to cd\n if (relProjDir !== '') {\n console.log(`You can now ${bold(cyan('cd'))} into the ${bold(cyan(relProjDir))} project directory.`)\n }\n console.log(`Run ${bold(cyan(devCmd))} to start the local dev server. ${bold(cyan('CTRL-C'))} to close.`)\n console.log('')\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { bold, dim, green } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\n\nconst promptMessage = `Would you like your project to use WebAssembly?`\n\nconst noDesc = `\\\n* Choose this if you want to get started using SDEverywhere quickly\nand you don't want to install the Emscripten SDK.\n* This will generate a model that uses JavaScript code only, which\ndoesn't require extra build tools, but runs slower than WebAssembly.`\nconst yesDesc = `\\\n* Choose this if you want this script to install the Emscripten SDK\nfor you, or if you already have it installed.\n* This will generate a model that uses WebAssembly, which requires an\nadditional build step, but runs faster than pure JavaScript code.`\n\nconst FORMATS = [\n {\n title: 'No, generate a JavaScript model',\n description: noDesc,\n value: 'js'\n },\n {\n title: 'Yes, generate a WebAssembly model',\n description: yesDesc,\n value: 'c'\n }\n]\n\nexport async function chooseCodeFormat(): Promise<string> {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'format',\n message: promptMessage,\n choices: FORMATS\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n const target = options.format === 'c' ? 'WebAssembly' : 'JavaScript'\n const successMessage = green(\n `Configuring your project to generate ${target}. See \"${bold('sde.config.js')}\" for details.`\n )\n ora(successMessage).succeed()\n\n return options.format\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { mkdir, readFile, writeFile } from 'fs/promises'\nimport { dirname, join as joinPath, parse as parsePath, relative, resolve as resolvePath } from 'path'\n\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\nimport { parseAndGenerate } from '@sdeverywhere/compile'\n\ninterface MdlConstVariable {\n kind: 'const'\n name: string\n value: number\n}\n\ninterface MdlAuxVariable {\n kind: 'aux'\n name: string\n}\n\ninterface MdlLevelVariable {\n kind: 'level'\n name: string\n}\n\ntype MdlVariable = MdlConstVariable | MdlAuxVariable | MdlLevelVariable\n\nconst sampleChecksContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains \"check\" tests that exercise your model under different input\n# scenarios. For more guidance, consult this wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a simple check just to get you started.\n# Replace \"Some output\" with the name of some variable you'd like to test.\n- describe: Some output\n tests:\n - it: should be > 0 for all input scenarios\n scenarios:\n - preset: matrix\n datasets:\n - name: Some output\n predicates:\n - gt: 0\n`\n\nconst sampleComparisonsContent = `\\\n# yaml-language-server: $schema=SCHEMA_PATH\n\n#\n# This file contains definitions of custom comparison scenarios, which allow you to see\n# how the behavior of the model compares to that of previous versions. For more guidance,\n# consult the following wiki page:\n# https://github.com/climateinteractive/SDEverywhere/wiki/Testing-and-Comparing-Your-Model\n#\n\n# NOTE: The following is an example of a custom scenario just to get you started.\n# Replace \"Some input\" and \"Another input\" with the names of some variables you'd\n# like to test.\n- scenario:\n title: Custom scenario\n subtitle: gradual ramp-up\n with:\n - input: Some input\n at: 10\n - input: Another input\n at: 20\n`\n\nexport async function updateSdeConfig(projDir: string, modelPath: string, genFormat: string): Promise<void> {\n // Read the `sde.config.js` file from the template\n const configPath = joinPath(projDir, 'sde.config.js')\n let configText = await readFile(configPath, 'utf8')\n\n // Set the code generation format to the chosen format\n configText = configText.replace(`const genFormat = 'js'`, `const genFormat = '${genFormat}'`)\n\n // Replace instances of `model/MODEL_NAME.mdl` with the path to the chosen model file\n configText = configText.replaceAll('model/MODEL_NAME.mdl', modelPath)\n\n // Write the updated file\n await writeFile(configPath, configText)\n}\n\nasync function generateYaml(projDir: string, kind: 'checks' | 'comparisons', template: string): Promise<void> {\n const yamlDir = joinPath(projDir, 'model', kind)\n const yamlPath = joinPath(yamlDir, `${kind}.yaml`)\n if (!existsSync(yamlPath)) {\n // Get relative path from yaml file parent dir to project dir\n let relProjPath = relative(dirname(yamlPath), projDir)\n if (relProjPath.length === 0) {\n relProjPath = './'\n }\n\n // Create the directory for the yaml file, if needed\n await mkdir(yamlDir, { recursive: true })\n\n // TODO: This path is normally different depending on whether using npm/yarn or\n // pnpm. For npm/yarn, `check-core` is hoisted under top-level `node_modules`,\n // but for pnpm, it is nested under `node_modules/.pnpm`. As an ugly workaround\n // the templates declare `check-core` as a direct dependency even though it is\n // not really needed (a transitive dependency via `plugin-check` would normally\n // suffice). This allows us to use the same path here that works for all\n // three package managers.\n const nodeModulesPart = joinPath(relProjPath, 'node_modules')\n const schemaName = kind === 'checks' ? 'check' : 'comparison'\n const checkCorePart = `@sdeverywhere/check-core/schema/${schemaName}.schema.json`\n const schemaPath = `${nodeModulesPart}/${checkCorePart}`\n const yamlContent = template.replace('SCHEMA_PATH', schemaPath)\n await writeFile(yamlPath, yamlContent)\n }\n}\n\nexport async function generateSampleYamlFiles(projDir: string): Promise<void> {\n // Generate a sample `checks.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'checks', sampleChecksContent)\n\n // Generate a sample `comparisons.yaml` file if one doesn't already exist\n await generateYaml(projDir, 'comparisons', sampleComparisonsContent)\n}\n\nexport async function chooseGenConfig(projDir: string, modelPath: string): Promise<void> {\n // TODO: For now we eagerly read the model file; maybe change this to only load it if\n // the user chooses to generate graph and/or slider config\n let mdlVars: MdlVariable[]\n try {\n // Get the list of variables available in the model\n mdlVars = await readModelVars(projDir, modelPath)\n } catch (e) {\n console.log(e)\n ora(\n yellow('The model file failed to load. We will continue setting things up, and you can diagnose the issue later.')\n ).warn()\n return\n }\n\n // Extract `INITIAL TIME` and `FINAL TIME` values and remove special control variables from the list\n let initialTime: number\n let finalTime: number\n const validVars: MdlVariable[] = []\n for (const v of mdlVars) {\n const varName = v.name.toLowerCase()\n let skip = false\n switch (varName) {\n case 'final time':\n skip = true\n if (v.kind === 'const') {\n finalTime = v.value\n }\n break\n case 'initial time':\n skip = true\n if (v.kind === 'const') {\n initialTime = v.value\n }\n break\n case 'saveper':\n case 'time':\n case 'time step':\n skip = true\n break\n default:\n break\n }\n if (!skip) {\n validVars.push(v)\n }\n }\n\n // Set the values in `model.csv`\n if (initialTime === undefined) {\n initialTime = 0\n }\n if (finalTime === undefined) {\n finalTime = 100\n }\n\n // TODO: Auto-detect dat files that are referenced by the mdl and include them here\n const datFiles: string[] = []\n const datPart = datFiles.join(';')\n\n // Preserve the `model.csv` header but drop other existing content (if any)\n const modelCsvFile = joinPath(projDir, 'config', 'model.csv')\n const origModelCsvContent = await readFile(modelCsvFile, 'utf8')\n const modelCsvHeader = origModelCsvContent.split('\\n')[0]\n\n // Disable bundled listing and customization features by default\n const bundleListing = 'false'\n const customConstants = 'false'\n const customLookups = 'false'\n const customOutputs = 'false'\n\n // Add line and write out updated `model.csv`\n const modelCsvLine = `${initialTime},${finalTime},${datPart},${bundleListing},${customConstants},${customLookups},${customOutputs}`\n const newModelCsvContent = `${modelCsvHeader}\\n${modelCsvLine}\\n`\n await writeFile(modelCsvFile, newModelCsvContent)\n\n // See if the user wants to generate graph config\n await chooseGenGraphConfig(projDir, validVars)\n console.log()\n\n // See if the user wants to generate slider config\n await chooseGenSliderConfig(projDir, validVars)\n}\n\nasync function chooseGenGraphConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genGraph',\n message: `Would you like to configure a graph to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genGraph) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available output variables\n const outputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'aux' || mdlVar.kind === 'level') {\n outputVarNames.push(mdlVar.name)\n }\n }\n outputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = outputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three output variables to display in the graph',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `graphs.csv` header but drop other existing content (if any)\n const graphsCsvFile = joinPath(projDir, 'config', 'graphs.csv')\n const origGraphsCsvContent = await readFile(graphsCsvFile, 'utf8')\n const graphsCsvHeader = origGraphsCsvContent.split('\\n')[0]\n\n // Write the updated `graphs.csv` file\n let newGraphsCsvContent = `${graphsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add line to `graphs.csv`\n const csvLine = graphsCsvLine(varsResponse.vars)\n newGraphsCsvContent += `${csvLine}\\n`\n }\n await writeFile(graphsCsvFile, newGraphsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/graphs.csv')}\" file later.`))\n return\n }\n\n ora(\n green(`Added graph to \"${bold('config/graphs.csv')}\". ${dim('You can configure graphs in that file later.')}`)\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction graphsCsvLine(outputVarNames: string[]): string {\n const colors = ['blue', 'red', 'green']\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(131).fill('')\n // id\n a[0] = '1'\n // parent menu\n a[2] = 'Graphs'\n // graph title\n a[3] = 'Graph Title'\n // kind\n a[7] = 'line'\n // Plots start at 26\n let index = 26\n let colorIndex = 0\n for (const outputVarName of outputVarNames) {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(outputVarName)\n // plot N variable\n a[index + 0] = escapedName\n // plot N style\n a[index + 2] = 'line'\n // plot N label\n a[index + 3] = escapedName\n // plot N color\n a[index + 4] = colors[colorIndex]\n index += 7\n colorIndex++\n }\n\n return a.join(',')\n}\n\nasync function chooseGenSliderConfig(projDir: string, mdlVars: MdlVariable[]): Promise<void> {\n // Prompt the user\n const genResponse = await prompts(\n {\n type: 'confirm',\n name: 'genSliders',\n message: `Would you like to configure a few sliders to get you started? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (!genResponse.genSliders) {\n ora().info(dim(`No problem! You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n // Offer multi-select with available input variables\n const inputVarNames: string[] = []\n for (const mdlVar of mdlVars) {\n if (mdlVar.kind === 'const') {\n inputVarNames.push(mdlVar.name)\n }\n }\n inputVarNames.sort((a, b) => {\n return a.toLowerCase().localeCompare(b.toLowerCase())\n })\n const choices = inputVarNames.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n const varsResponse = await prompts(\n {\n type: 'autocompleteMultiselect',\n name: 'vars',\n message: 'Choose up to three input variables to control with sliders',\n choices,\n max: 3\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n\n // Preserve the `inputs.csv` header but drop other existing content (if any)\n const inputsCsvFile = joinPath(projDir, 'config', 'inputs.csv')\n const origInputsCsvContent = await readFile(inputsCsvFile, 'utf8')\n const inputsCsvHeader = origInputsCsvContent.split('\\n')[0]\n\n // Write the updated `inputs.csv` file\n let newInputsCsvContent = `${inputsCsvHeader}\\n`\n if (varsResponse.vars.length > 0) {\n // Add lines to `inputs.csv`\n let idNumber = 1\n for (const inputVarName of varsResponse.vars) {\n const inputVar = mdlVars.find(v => v.name === inputVarName)\n if (inputVar && inputVar.kind === 'const') {\n const defaultValue = inputVar.value\n const csvLine = inputsCsvLine(inputVarName, defaultValue, idNumber.toString())\n newInputsCsvContent += `${csvLine}\\n`\n idNumber++\n }\n }\n }\n await writeFile(inputsCsvFile, newInputsCsvContent)\n\n if (varsResponse.vars.length === 0) {\n ora().info(dim(`No variables selected. You can edit the \"${cyan('config/inputs.csv')}\" file later.`))\n return\n }\n\n const slidersText = varsResponse.vars.length > 1 ? 'sliders' : 'sliders'\n ora(\n green(\n `Added ${slidersText} to \"${bold('config/inputs.csv')}\". ${dim('You can configure sliders in that file later.')}`\n )\n ).succeed()\n}\n\n// TODO: Ideally the `plugin-config` package would expose an API for generating CSV, but\n// until then, we will generate a comma-separated line of values in hardcoded fashion\nfunction inputsCsvLine(inputVarName: string, defaultValue: number, id: string): string {\n // Surround the name in quotes if it contains a comma\n const escapedName = escapeCsvField(inputVarName)\n\n // TODO: Be smarter about automatically choosing min/max/step values\n const minValue = defaultValue - 1\n const maxValue = defaultValue + 1\n const step = 0.1\n\n // Fill the line with blanks initially, then set the small subset of fields\n const a = Array(28).fill('')\n // id\n a[0] = id\n // input type\n a[1] = 'slider'\n // viewid\n a[2] = 'view1'\n // varname\n a[3] = escapedName\n // label\n a[4] = escapedName\n // group name\n a[6] = 'Sliders'\n // slider min\n a[7] = minValue\n // slider max\n a[8] = maxValue\n // slider default\n a[9] = defaultValue\n // slider step\n a[10] = step\n // units\n a[11] = '(units)'\n\n return a.join(',')\n}\n\nfunction escapeCsvField(s: string): string {\n // Surround the value in quotes if it contains a comma\n // TODO: Escape double quotes as well\n return s.includes(',') ? `\"${s}\"` : s\n}\n\nasync function readModelVars(projDir: string, modelPath: string): Promise<MdlVariable[]> {\n // TODO: This function contains a subset of the logic from `sde-generate.js` in\n // the `cli` package; should revisit\n\n // Ensure the `build` directory exists (under the `sde-prep` directory)\n const buildDir = resolvePath(projDir, 'sde-prep', 'build')\n await mkdir(buildDir, { recursive: true })\n\n // Use an empty model spec; this will make SDE look at all variables in the model file\n const spec = {}\n\n // Try parsing the model file to generate the list of variables\n // TODO: This depends on some `compile` package APIs that are not yet considered stable.\n // Ideally we'd use an API that does not write files but instead returns an in-memory\n // object in a specified format.\n\n // Read the model file\n const modelFile = resolvePath(projDir, modelPath)\n const modelContent = await readFile(modelFile, 'utf8')\n\n // Determine the model kind based on the presence of an `<xmile>` tag\n const modelKind = modelContent.includes('<xmile') ? 'xmile' : 'vensim'\n\n // Parse the model and generate the variable list\n const modelDir = dirname(modelFile)\n const modelName = parsePath(modelFile).name\n await parseAndGenerate(modelContent, modelKind, spec, ['printVarList'], modelDir, modelName, buildDir)\n\n // Read `build/{model}.json`\n const jsonListFile = joinPath(buildDir, `${modelName}.json`)\n const jsonListContent = await readFile(jsonListFile, 'utf8')\n const jsonList = JSON.parse(jsonListContent)\n const varObjs = jsonList.variables\n\n // Create a simplified array of variables\n const mdlVars: MdlVariable[] = []\n for (const varObj of varObjs) {\n // Only include certain variables for now\n // TODO: Include \"data\" vars\n switch (varObj.varType) {\n case 'const':\n mdlVars.push({\n kind: 'const',\n name: varObj.modelLHS,\n value: Number.parseFloat(varObj.modelFormula)\n })\n break\n case 'aux':\n mdlVars.push({\n kind: 'aux',\n name: varObj.modelLHS\n })\n break\n case 'level':\n mdlVars.push({\n kind: 'level',\n name: varObj.modelLHS\n })\n break\n default:\n break\n }\n }\n\n return mdlVars\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execa } from 'execa'\nimport { bold, cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseInstallDeps(projDir: string, args: Arguments, pkgManager: string): Promise<void> {\n // Prompt the user\n const installResponse = await prompts(\n {\n type: 'confirm',\n name: 'install',\n message: `Would you like to install ${pkgManager} dependencies? ${reset(dim('(recommended)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(\n dim('Operation cancelled. Your project folder has been created, but no dependencies have been installed.')\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!installResponse.install) {\n ora().info(dim(`No problem! Remember to install dependencies after setup.`))\n return\n }\n\n // Install dependencies\n const installExec = execa(pkgManager, ['install'], { cwd: projDir })\n const installingPackagesMsg = 'Installing packages...'\n const installSpinner = ora(installingPackagesMsg).start()\n try {\n await new Promise<void>((resolve, reject) => {\n installExec.stdout?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.stderr?.on('data', function (data) {\n installSpinner.text = `${installingPackagesMsg}\\n${bold(`[${pkgManager}]`)} ${data}`\n })\n installExec.on('error', error => reject(error))\n installExec.on('close', code => {\n if (code !== 0) {\n reject(`Install failed (code=${code})`)\n } else {\n resolve()\n }\n })\n })\n installSpinner.text = green('Packages installed!')\n installSpinner.succeed()\n } catch {\n installSpinner.text = yellow(\n `There was an error installing packages. Try running ${cyan(\n `${pkgManager} install`\n )} in your project directory later.`\n )\n installSpinner.warn()\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync } from 'fs'\nimport { resolve as resolvePath } from 'path'\n\nimport { bold, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseProjectDir(args: Arguments): Promise<string> {\n /**\n * Return true if the given directory does not exist, or it does not contain important files\n * like `package.json`.\n */\n function isValidDir(dir: string): boolean {\n const packageJson = resolvePath(dir, 'package.json')\n const packagesDir = resolvePath(dir, 'packages')\n return !existsSync(dir) || (!existsSync(packageJson) && !existsSync(packagesDir))\n }\n\n const showValidDirMsg = (dir: string) => {\n ora(green(`Using \"${bold(dir)}\" as the project directory.`)).succeed()\n }\n\n const showInvalidDirMsg = (dir: string) => {\n ora(red(`\"${bold(dir)}\" contains existing 'package.json' and/or 'packages' directory, stopping.`)).fail()\n }\n\n // See if project directory is provided on command line\n let projDir = args['_'][2] as string\n if (projDir) {\n // Directory was provided, see if it is valid\n if (isValidDir(projDir)) {\n // The provided directory is valid, so proceed\n showValidDirMsg(projDir)\n } else {\n // The provided directory is not valid, so show error message and exit\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n } else {\n // Directory was not provided, so prompt the user\n const dirResponse = await prompts(\n {\n type: 'text',\n name: 'directory',\n message: 'Where would you like to create your new project?',\n initial: '<current directory>'\n // validate(value) {\n // if (value === '<current directory>') {\n // value = process.cwd()\n // }\n // if (!isValidDir(value)) {\n // return notValidMsg(value)\n // }\n // return true\n // }\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n projDir = dirResponse.directory\n if (projDir === '<current directory>') {\n projDir = process.cwd()\n }\n if (isValidDir(projDir)) {\n showValidDirMsg(projDir)\n } else {\n showInvalidDirMsg(projDir)\n process.exit(0)\n }\n }\n\n return projDir\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, rmSync } from 'fs'\nimport { join as joinPath, resolve as resolvePath } from 'path'\n\nimport { execa } from 'execa'\nimport { findUp } from 'find-up'\nimport { bold, cyan, dim, green, red } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\n// TODO: Make this configurable; we're using this older version for now because it is\n// relatively stable and has been used to build En-ROADS and C-ROADS for a long time\nconst version = '2.0.34'\n\nexport async function chooseInstallEmsdk(projDir: string, args: Arguments): Promise<void> {\n // Walk up the directory structure to see if there is an existing `emsdk` directory\n const existingEmsdkDir = await findUp('emsdk', {\n cwd: projDir,\n type: 'directory'\n })\n if (existingEmsdkDir) {\n ora().succeed('Found existing Emscripten SDK installation.')\n ora().info(dim(`Your project will use \"${cyan(existingEmsdkDir)}\".`))\n return\n }\n\n // Prompt the user\n const underParentDir = resolvePath(projDir, '..', 'emsdk')\n const underProjDir = joinPath(projDir, 'emsdk')\n const installResponse = await prompts(\n {\n type: 'select',\n name: 'install',\n message: `Would you like to install the Emscripten SDK that is used to generate WebAssembly?`,\n choices: [\n // ${reset(dim('(recommended)'))\n {\n title: `Install under parent directory (${bold(underParentDir)})`,\n description: 'This is recommended so that it can be shared by multiple projects',\n value: 'parent'\n },\n {\n title: `Install under project directory (${bold(underProjDir)})\"`,\n description: 'This is useful for keeping everything under a single project directory',\n value: 'project'\n },\n {\n title: `Don't install`,\n description: `It's OK, you can install it later`,\n value: 'skip'\n }\n ]\n },\n {\n onCancel: () => {\n ora().info(\n dim(\n 'Operation cancelled. Your project folder has been created, but the Emscripten SDK and other dependencies have not been installed.'\n )\n )\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (installResponse.install === 'skip') {\n ora().info(\n dim(\n `No problem! Be sure to install the Emscripten SDK and configure it in \"${cyan('sde.config.js')}\" after setup.`\n )\n )\n return\n }\n\n const installDir = installResponse.install === 'parent' ? underParentDir : underProjDir\n try {\n // TODO: Use spinner here\n await installEmscripten(installDir)\n } catch (e) {\n ora(red(`Failed to install Emscripten SDK: ${e.message}`)).fail()\n process.exit(0)\n }\n\n ora(green(`Installed the Emscripten SDK in \"${bold(installDir)}\"`)).succeed()\n}\n\n/**\n * Install the Emscripten SDK to the `emsdk` directory under the\n * given directory (if `emsdk` is not already present), then\n * activates the requested version (specified with `version`).\n *\n * The implementation is similar to the existing `setup-emsdk` action\n * (https://github.com/mymindstorm/setup-emsdk) except that one has issues\n * with the cache directory on Windows, so having our own script gives us\n * more control over installation and caching behavior.\n */\nasync function installEmscripten(emsdkDir: string /*, options?: { verbose?: boolean }*/): Promise<void> {\n // Only download if the emsdk directory wasn't restored from a cache\n if (!existsSync(emsdkDir)) {\n console.log(`Downloading Emscripten SDK to ${emsdkDir}`)\n // console.log()\n await execa('git', ['clone', 'https://github.com/emscripten-core/emsdk.git', emsdkDir])\n } else {\n console.log(`Found existing Emscripten SDK directory: ${emsdkDir}`)\n }\n // console.log()\n\n if (process.env.CI) {\n // On GitHub Actions, remove the `.git` directory to keep the cache smaller.\n // When we update to a new version, the cache key will miss and the emsdk\n // repo will be redownloaded.\n console.log('CI detected, removing .git directory...')\n const gitDir = joinPath(emsdkDir, '.git')\n rmSync(gitDir, { recursive: true, force: true })\n } else {\n // For local development, pull to get the latest\n console.log('Local development detected, performing git pull...')\n await execa('git', ['pull'], { cwd: emsdkDir })\n // console.log()\n }\n\n const emsdkCmd = async (...args: string[]) => {\n return execa('python3', ['emsdk.py', ...args], { cwd: emsdkDir })\n }\n\n console.log(`Activating Emscripten SDK ${version}...`)\n await emsdkCmd('install', version)\n await emsdkCmd('activate', version)\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { execaCommand } from 'execa'\nimport { cyan, dim, green, reset, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nexport async function chooseGitInit(projDir: string, args: Arguments): Promise<void> {\n // Prompt the user\n const gitResponse = await prompts(\n {\n type: 'confirm',\n name: 'git',\n message: `Would you like to initialize a new git repository? ${reset(dim('(optional)'))}`,\n initial: true\n },\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled. Your project folder has already been created.'))\n process.exit(0)\n }\n }\n )\n\n // Handle response\n if (args.dryRun) {\n ora().info(dim(`--dry-run enabled, skipping.`))\n return\n } else if (!gitResponse.git) {\n ora().info(dim(`No problem! You can come back and run ${cyan(`git init`)} later.`))\n return\n }\n\n // Init git repo\n try {\n await execaCommand('git init', { cwd: projDir })\n ora().succeed(green('Git repository initialized!'))\n } catch {\n ora().warn(\n yellow(\n `There was a problem initializing the Git repository, but no problem, you can run ${cyan(`git init`)} later.`\n )\n )\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { readdir } from 'fs/promises'\nimport { relative, resolve as resolvePath, sep, posix, extname } from 'path'\n\nimport { bold, dim, green, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport type { Choice } from 'prompts'\nimport prompts from 'prompts'\n\n// The set of supported model file extensions; this should match the set defined in the cli package\nconst supportedModelFileExtensions = new Set(['.mdl', '.xmile', '.stmx', '.itmx'])\n\nexport async function chooseModelFile(projDir: string): Promise<string | undefined> {\n // Find all supported model files in the project directory\n // From https://stackoverflow.com/a/45130990\n async function getFiles(dir: string): Promise<string[]> {\n const dirents = await readdir(dir, { withFileTypes: true })\n const files = await Promise.all(\n dirents.map(dirent => {\n const res = resolvePath(dir, dirent.name)\n return dirent.isDirectory() ? getFiles(res) : res\n })\n )\n return files.flat()\n }\n const allFiles = await getFiles(projDir)\n const modelFiles = allFiles\n // Only include files that have a supported extension\n .filter(f => {\n const ext = extname(f).toLowerCase()\n return supportedModelFileExtensions.has(ext)\n })\n // Convert to a relative path with POSIX path separators (we want\n // paths in the 'sde.config.js' file to use POSIX path style only,\n // since that works on any OS including Windows)\n .map(f => relative(projDir, f).replaceAll(sep, posix.sep))\n const modelChoices = modelFiles.map(f => {\n return {\n title: f,\n value: f\n } as Choice\n })\n\n let modelFile: string\n if (modelFiles.length === 0) {\n // No model files found; return undefined so that the model from the template is copied over\n ora(\n yellow(`No model files were found in \"${projDir}\". The model file from the template will be used instead.`)\n ).warn()\n modelFile = undefined\n } else if (modelFiles.length === 1) {\n // Only one model file\n modelFile = modelFiles[0]\n ora().succeed(`Found \"${modelFile}\", will configure the project to use that model file.`)\n } else {\n // Multiple model files found; allow the user to choose one\n // TODO: Eventually we should allow the user to choose to flatten if there are multiple submodels\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'modelFile',\n message: 'It looks like there are multiple model files. Which one would you like to use?',\n choices: modelChoices\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n modelFile = options.modelFile\n ora(green(`Using \"${bold(modelFile)}\" as the model for the project.`)).succeed()\n }\n\n return modelFile\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { existsSync, mkdtempSync, readdirSync, renameSync, rmSync } from 'fs'\nimport { writeFile } from 'fs/promises'\nimport { copy } from 'fs-extra'\nimport { tmpdir } from 'os'\nimport { join as joinPath } from 'path'\n\nimport { downloadTemplate } from 'giget'\nimport { bold, dim, green, red, yellow } from 'kleur/colors'\nimport ora from 'ora'\nimport prompts from 'prompts'\nimport type { Arguments } from 'yargs-parser'\n\nconst TEMPLATES = [\n {\n title: 'Svelte project (recommended)',\n description: 'Includes recommended structure with config files, Svelte-based app, core library, model-check, etc',\n value: 'svelte'\n },\n {\n title: 'jQuery project',\n description: 'Includes recommended structure with config files, jQuery-based app, core library, model-check, etc',\n value: 'jquery'\n },\n {\n title: 'Minimal project',\n description: 'Includes simple config for model-check',\n value: 'minimal'\n }\n]\n\ninterface Template {\n /** The template URI that can be passed to `giget` to download the template. */\n uri: string\n /** The template name that will be displayed to the user. */\n name: string\n}\n\nexport async function chooseTemplate(args: Arguments): Promise<Template> {\n let templateName: string\n if (args.template) {\n // Allow template name or repository to be provided on command line\n templateName = args.template\n } else {\n // Prompt the user\n const options = await prompts(\n [\n {\n type: 'select',\n name: 'template',\n message: 'Which template would you like to use?',\n choices: TEMPLATES\n }\n ],\n {\n onCancel: () => {\n ora().info(dim('Operation cancelled.'))\n process.exit(0)\n }\n }\n )\n templateName = options.template\n }\n\n // Allow branch name or commit hash to be overridden on command line\n const defaultRev = 'main'\n const commit = args.commit || defaultRev\n\n // Construct the template repository URL\n let baseTemplateUri: string\n if (templateName.includes(':')) {\n // Assume the template name is already in the form of a giget template, for example:\n // github:owner/repo\n // gitlab:owner/repo\n baseTemplateUri = templateName\n } else if (templateName.includes('/')) {\n // Assume the template name is a GitHub repository name, for example:\n // owner/repo\n baseTemplateUri = `github:${templateName}`\n } else {\n // Otherwise, assume the template name is one of the available `template-*`\n // projects under `examples` in the SDEverywhere repository, for example:\n // svelte\n // jquery\n // minimal\n baseTemplateUri = `github:climateinteractive/SDEverywhere/examples/template-${templateName}`\n }\n const templateUri = `${baseTemplateUri}#${commit}`\n\n ora(green(`Using \"${bold(templateUri)}\" as the template for the project.`)).succeed()\n\n return {\n uri: templateUri,\n name: templateName\n }\n}\n\nexport async function copyTemplate(\n template: Template,\n projDir: string,\n pkgManager: string,\n configDirExisted: boolean,\n modelExisted: boolean\n): Promise<void> {\n // Show a spinner while copying the template files\n const templateSpinner = ora('Copying template files...').start()\n\n try {\n // Make giget write to a temporary directory\n const tmpDir = mkdtempSync(joinPath(tmpdir(), 'sde-create-'))\n\n // Use giget to download the template (we will be writing to a temporary directory,\n // so `force` is safe)\n await downloadTemplate(template.uri, {\n force: true,\n dir: tmpDir\n })\n\n // In case giget doesn't return an error when an invalid template is provided, check\n // that the temporary directory is non-empty\n if (!existsSync(tmpDir) || readdirSync(tmpDir).length === 0) {\n throw new Error('Failed to download the requested template: the temporary directory is empty.')\n }\n\n if (configDirExisted) {\n // There is already a `config` directory in the project directory; remove the\n // `config` directory from the template so that we don't write files from the\n // template that conflict with the existing files\n rmSync(joinPath(tmpDir, 'config'), { recursive: true, force: true })\n }\n\n if (modelExisted) {\n // There is already a model file in the project directory; remove the `model`\n // directory (including the model file and the model-check yaml files) from the\n // template so that we don't copy them into the project directory\n rmSync(joinPath(tmpDir, 'model'), { recursive: true, force: true })\n }\n\n // Copy files to destination without overwriting\n await copy(tmpDir, projDir, {\n overwrite: false,\n errorOnExist: false\n })\n\n if (!modelExisted) {\n // There wasn't already a model file in the project directory, so we will use\n // the one supplied by the template. Rename it from `MODEL_NAME.mdl` to\n // `sample.mdl`.\n // TODO: For now we assume that all templates include a sample model in Vensim\n // format. This will need to be updated if we add templates that include a\n // sample model in a different format.\n renameSync(joinPath(projDir, 'model', 'MODEL_NAME.mdl'), joinPath(projDir, 'model', 'sample.mdl'))\n }\n\n // Remove the temporary directory\n rmSync(tmpDir, { recursive: true, force: true })\n } catch (e) {\n // The download failed; show an error message\n // TODO: Handle common download issues; for now, just log the error message and exit\n templateSpinner.fail()\n console.error(red(e.message))\n console.error(yellow('\\nThere was a problem copying the template.'))\n console.error(\n yellow(\n 'Please start a new discussion thread and include the command output so that we can help:\\n https://github.com/climateinteractive/SDEverywhere/discussions/categories/q-a\\n'\n )\n )\n process.exit(0)\n }\n\n if (existsSync(joinPath(projDir, 'packages')) && pkgManager === 'pnpm') {\n // When using pnpm and the template has a `packages` folder (i.e., it has a monorepo\n // layout), we need to write a `pnpm-workspace.yaml` file since pnpm doesn't use the\n // \"workspaces\" config from `package.json` (like npm and yarn use)\n const workspaceFile = joinPath(projDir, 'pnpm-workspace.yaml')\n const workspaceContent = `packages:\\n - packages/*\\n`\n await writeFile(workspaceFile, workspaceContent)\n }\n\n templateSpinner.text = green('Template copied!')\n templateSpinner.succeed()\n}\n"],"mappings":"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","names":["existsSync","posix","relative","resolvePath","bold","cyan","dim","green","ora","prompts","bold","dim","green","ora","prompts","bold","cyan","dim","green","reset","yellow","ora","prompts","existsSync","resolvePath","bold","dim","green","ora","prompts","existsSync","joinPath","resolvePath","execa","bold","cyan","dim","green","red","ora","prompts","cyan","dim","green","reset","yellow","ora","prompts","relative","resolvePath","bold","dim","green","yellow","ora","prompts","existsSync","rmSync","writeFile","joinPath","bold","dim","green","red","yellow","ora","prompts","prompts","ora","dim","bold","existsSync","resolvePath","posix","cyan","green","relative"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdeverywhere/create",
3
- "version": "0.2.34",
3
+ "version": "0.2.35",
4
4
  "description": "Create a new SDEverywhere project with minimal configuration",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,7 +11,7 @@
11
11
  "create-sde": "bin/create-sde.js"
12
12
  },
13
13
  "dependencies": {
14
- "@sdeverywhere/compile": "^0.7.27",
14
+ "@sdeverywhere/compile": "^0.7.28",
15
15
  "execa": "^6.1.0",
16
16
  "find-up": "^6.3.0",
17
17
  "fs-extra": "^10.1.0",