@sdeverywhere/create 0.2.34 → 0.2.36
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 +47 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +48 -41
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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,
|
|
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",
|
|
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,
|
|
170
|
+
async function chooseGenConfig(projDir, modelPath) {
|
|
171
171
|
let mdlVars;
|
|
172
172
|
try {
|
|
173
|
-
mdlVars = await readModelVars(projDir,
|
|
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
|
|
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,
|
|
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
|
|
430
|
-
const
|
|
431
|
-
const
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
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-
|
|
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
|
-
|
|
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
|
|
751
|
-
|
|
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
|
|
758
|
-
if (
|
|
759
|
-
(0, import_ora7.default)(
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
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: "
|
|
770
|
-
message: "It looks like there are multiple
|
|
771
|
-
choices:
|
|
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
|
-
|
|
782
|
-
(0, import_ora7.default)((0, import_colors7.green)(`Using "${(0, import_colors7.bold)(
|
|
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
|
|
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,
|
|
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 (
|
|
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 (!
|
|
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
|
|
920
|
-
const
|
|
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,
|
|
930
|
+
await copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted);
|
|
924
931
|
console.log();
|
|
925
932
|
}
|
|
926
|
-
if (
|
|
927
|
-
|
|
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,
|
|
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 &&
|
|
947
|
-
await chooseGenConfig(projDir,
|
|
953
|
+
if (configDirExistsNow && modelExisted && !args.dryRun) {
|
|
954
|
+
await chooseGenConfig(projDir, modelPath);
|
|
948
955
|
console.log();
|
|
949
956
|
}
|
|
950
957
|
}
|
package/dist/index.cjs.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":["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,
|
|
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",
|
|
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,
|
|
137
|
+
async function chooseGenConfig(projDir, modelPath) {
|
|
138
138
|
let mdlVars;
|
|
139
139
|
try {
|
|
140
|
-
mdlVars = await readModelVars(projDir,
|
|
140
|
+
mdlVars = await readModelVars(projDir, modelPath);
|
|
141
141
|
} catch (e) {
|
|
142
142
|
console.log(e);
|
|
143
143
|
ora2(
|
|
144
|
-
yellow("The
|
|
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,
|
|
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
|
|
397
|
-
const
|
|
398
|
-
const
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
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-
|
|
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
|
-
|
|
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
|
|
718
|
-
|
|
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
|
|
725
|
-
if (
|
|
726
|
-
ora7(
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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: "
|
|
737
|
-
message: "It looks like there are multiple
|
|
738
|
-
choices:
|
|
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
|
-
|
|
749
|
-
ora7(green7(`Using "${bold6(
|
|
755
|
+
modelFile = options.modelFile;
|
|
756
|
+
ora7(green7(`Using "${bold6(modelFile)}" as the model for the project.`)).succeed();
|
|
750
757
|
}
|
|
751
|
-
return
|
|
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,
|
|
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 (
|
|
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 (!
|
|
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
|
|
887
|
-
const
|
|
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,
|
|
897
|
+
await copyTemplate(template, projDir, pkgManager, configDirExisted, modelExisted);
|
|
891
898
|
console.log();
|
|
892
899
|
}
|
|
893
|
-
if (
|
|
894
|
-
|
|
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,
|
|
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 &&
|
|
914
|
-
await chooseGenConfig(projDir,
|
|
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":";AAEA,SAAS,cAAAA,mBAAkB;AAC3B,SAAS,SAAAC,QAAO,YAAAC,WAAU,WAAWC,oBAAmB;AAExD,SAAS,QAAQ,OAAO,QAAAC,OAAM,QAAAC,OAAM,OAAAC,MAAK,SAAAC,cAAa;AACtD,OAAOC,UAAS;AAChB,OAAOC,cAAa;AACpB,OAAO,0BAA0B;AACjC,OAAO,WAAW;;;ACPlB,SAAS,MAAM,KAAK,aAAa;AACjC,OAAO,SAAS;AAChB,OAAO,aAAa;AAEpB,IAAM,gBAAgB;AAEtB,IAAM,SAAS;AAAA;AAAA;AAAA;AAKf,IAAM,UAAU;AAAA;AAAA;AAAA;AAMhB,IAAM,UAAU;AAAA,EACd;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,mBAAoC;AAExD,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,YAAI,EAAE,KAAK,IAAI,sBAAsB,CAAC;AACtC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,WAAW,MAAM,gBAAgB;AACxD,QAAM,iBAAiB;AAAA,IACrB,wCAAwC,MAAM,UAAU,KAAK,eAAe,CAAC;AAAA,EAC/E;AACA,MAAI,cAAc,EAAE,QAAQ;AAE5B,SAAO,QAAQ;AACjB;;;ACxDA,SAAS,kBAAkB;AAC3B,SAAS,OAAO,UAAU,iBAAiB;AAC3C,SAAS,SAAS,QAAQ,UAAU,SAAS,WAAW,UAAU,WAAW,mBAAmB;AAEhG,SAAS,QAAAC,OAAM,MAAM,OAAAC,MAAK,SAAAC,QAAO,OAAO,cAAc;AACtD,OAAOC,UAAS;AAEhB,OAAOC,cAAa;AAEpB,SAAS,wBAAwB;AAoBjC,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsB5B,IAAM,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBjC,eAAsB,gBAAgB,SAAiB,SAAiB,WAAkC;AAExG,QAAM,aAAa,SAAS,SAAS,eAAe;AACpD,MAAI,aAAa,MAAM,SAAS,YAAY,MAAM;AAGlD,eAAa,WAAW,QAAQ,0BAA0B,sBAAsB,SAAS,GAAG;AAG5F,eAAa,WAAW,WAAW,wBAAwB,OAAO;AAGlE,QAAM,UAAU,YAAY,UAAU;AACxC;AAEA,eAAe,aAAa,SAAiB,MAAgC,UAAiC;AAC5G,QAAM,UAAU,SAAS,SAAS,SAAS,IAAI;AAC/C,QAAM,WAAW,SAAS,SAAS,GAAG,IAAI,OAAO;AACjD,MAAI,CAAC,WAAW,QAAQ,GAAG;AAEzB,QAAI,cAAc,SAAS,QAAQ,QAAQ,GAAG,OAAO;AACrD,QAAI,YAAY,WAAW,GAAG;AAC5B,oBAAc;AAAA,IAChB;AAGA,UAAM,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AASxC,UAAM,kBAAkB,SAAS,aAAa,cAAc;AAC5D,UAAM,aAAa,SAAS,WAAW,UAAU;AACjD,UAAM,gBAAgB,mCAAmC,UAAU;AACnE,UAAM,aAAa,GAAG,eAAe,IAAI,aAAa;AACtD,UAAM,cAAc,SAAS,QAAQ,eAAe,UAAU;AAC9D,UAAM,UAAU,UAAU,WAAW;AAAA,EACvC;AACF;AAEA,eAAsB,wBAAwB,SAAgC;AAE5E,QAAM,aAAa,SAAS,UAAU,mBAAmB;AAGzD,QAAM,aAAa,SAAS,eAAe,wBAAwB;AACrE;AAEA,eAAsB,gBAAgB,SAAiB,SAAgC;AAGrF,MAAI;AACJ,MAAI;AAEF,cAAU,MAAM,cAAc,SAAS,OAAO;AAAA,EAChD,SAAS,GAAG;AACV,YAAQ,IAAI,CAAC;AACb,IAAAD;AAAA,MACE,OAAO,wGAAwG;AAAA,IACjH,EAAE,KAAK;AACP;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACJ,QAAM,YAA2B,CAAC;AAClC,aAAW,KAAK,SAAS;AACvB,UAAM,UAAU,EAAE,KAAK,YAAY;AACnC,QAAI,OAAO;AACX,YAAQ,SAAS;AAAA,MACf,KAAK;AACH,eAAO;AACP,YAAI,EAAE,SAAS,SAAS;AACtB,sBAAY,EAAE;AAAA,QAChB;AACA;AAAA,MACF,KAAK;AACH,eAAO;AACP,YAAI,EAAE,SAAS,SAAS;AACtB,wBAAc,EAAE;AAAA,QAClB;AACA;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AACP;AAAA,MACF;AACE;AAAA,IACJ;AACA,QAAI,CAAC,MAAM;AACT,gBAAU,KAAK,CAAC;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,gBAAgB,QAAW;AAC7B,kBAAc;AAAA,EAChB;AACA,MAAI,cAAc,QAAW;AAC3B,gBAAY;AAAA,EACd;AAGA,QAAM,WAAqB,CAAC;AAC5B,QAAM,UAAU,SAAS,KAAK,GAAG;AAGjC,QAAM,eAAe,SAAS,SAAS,UAAU,WAAW;AAC5D,QAAM,sBAAsB,MAAM,SAAS,cAAc,MAAM;AAC/D,QAAM,iBAAiB,oBAAoB,MAAM,IAAI,EAAE,CAAC;AAGxD,QAAM,gBAAgB;AACtB,QAAM,kBAAkB;AACxB,QAAM,gBAAgB;AACtB,QAAM,gBAAgB;AAGtB,QAAM,eAAe,GAAG,WAAW,IAAI,SAAS,IAAI,OAAO,IAAI,aAAa,IAAI,eAAe,IAAI,aAAa,IAAI,aAAa;AACjI,QAAM,qBAAqB,GAAG,cAAc;AAAA,EAAK,YAAY;AAAA;AAC7D,QAAM,UAAU,cAAc,kBAAkB;AAGhD,QAAM,qBAAqB,SAAS,SAAS;AAC7C,UAAQ,IAAI;AAGZ,QAAM,sBAAsB,SAAS,SAAS;AAChD;AAEA,eAAe,qBAAqB,SAAiB,SAAuC;AAE1F,QAAM,cAAc,MAAMC;AAAA,IACxB;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,2DAA2D,MAAMH,KAAI,eAAe,CAAC,CAAC;AAAA,MAC/F,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAE,KAAI,EAAE,KAAKF,KAAI,sBAAsB,CAAC;AACtC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,YAAY,UAAU;AACzB,IAAAE,KAAI,EAAE,KAAKF,KAAI,iCAAiC,KAAK,mBAAmB,CAAC,eAAe,CAAC;AACzF;AAAA,EACF;AAGA,QAAM,iBAA2B,CAAC;AAClC,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS,SAAS,OAAO,SAAS,SAAS;AACpD,qBAAe,KAAK,OAAO,IAAI;AAAA,IACjC;AAAA,EACF;AACA,iBAAe,KAAK,CAAC,GAAG,MAAM;AAC5B,WAAO,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,CAAC;AAAA,EACtD,CAAC;AACD,QAAM,UAAU,eAAe,IAAI,OAAK;AACtC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,eAAe,MAAMG;AAAA,IACzB;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAD,KAAI,EAAE,KAAKF,KAAI,sBAAsB,CAAC;AACtC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,gBAAgB,SAAS,SAAS,UAAU,YAAY;AAC9D,QAAM,uBAAuB,MAAM,SAAS,eAAe,MAAM;AACjE,QAAM,kBAAkB,qBAAqB,MAAM,IAAI,EAAE,CAAC;AAG1D,MAAI,sBAAsB,GAAG,eAAe;AAAA;AAC5C,MAAI,aAAa,KAAK,SAAS,GAAG;AAEhC,UAAM,UAAU,cAAc,aAAa,IAAI;AAC/C,2BAAuB,GAAG,OAAO;AAAA;AAAA,EACnC;AACA,QAAM,UAAU,eAAe,mBAAmB;AAElD,MAAI,aAAa,KAAK,WAAW,GAAG;AAClC,IAAAE,KAAI,EAAE,KAAKF,KAAI,4CAA4C,KAAK,mBAAmB,CAAC,eAAe,CAAC;AACpG;AAAA,EACF;AAEA,EAAAE;AAAA,IACED,OAAM,mBAAmBF,MAAK,mBAAmB,CAAC,MAAMC,KAAI,8CAA8C,CAAC,EAAE;AAAA,EAC/G,EAAE,QAAQ;AACZ;AAIA,SAAS,cAAc,gBAAkC;AACvD,QAAM,SAAS,CAAC,QAAQ,OAAO,OAAO;AAGtC,QAAM,IAAI,MAAM,GAAG,EAAE,KAAK,EAAE;AAE5B,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,MAAI,QAAQ;AACZ,MAAI,aAAa;AACjB,aAAW,iBAAiB,gBAAgB;AAE1C,UAAM,cAAc,eAAe,aAAa;AAEhD,MAAE,QAAQ,CAAC,IAAI;AAEf,MAAE,QAAQ,CAAC,IAAI;AAEf,MAAE,QAAQ,CAAC,IAAI;AAEf,MAAE,QAAQ,CAAC,IAAI,OAAO,UAAU;AAChC,aAAS;AACT;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,GAAG;AACnB;AAEA,eAAe,sBAAsB,SAAiB,SAAuC;AAE3F,QAAM,cAAc,MAAMG;AAAA,IACxB;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,iEAAiE,MAAMH,KAAI,eAAe,CAAC,CAAC;AAAA,MACrG,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAE,KAAI,EAAE,KAAKF,KAAI,sBAAsB,CAAC;AACtC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,YAAY,YAAY;AAC3B,IAAAE,KAAI,EAAE,KAAKF,KAAI,iCAAiC,KAAK,mBAAmB,CAAC,eAAe,CAAC;AACzF;AAAA,EACF;AAGA,QAAM,gBAA0B,CAAC;AACjC,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS,SAAS;AAC3B,oBAAc,KAAK,OAAO,IAAI;AAAA,IAChC;AAAA,EACF;AACA,gBAAc,KAAK,CAAC,GAAG,MAAM;AAC3B,WAAO,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,CAAC;AAAA,EACtD,CAAC;AACD,QAAM,UAAU,cAAc,IAAI,OAAK;AACrC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,eAAe,MAAMG;AAAA,IACzB;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAD,KAAI,EAAE,KAAKF,KAAI,sBAAsB,CAAC;AACtC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,gBAAgB,SAAS,SAAS,UAAU,YAAY;AAC9D,QAAM,uBAAuB,MAAM,SAAS,eAAe,MAAM;AACjE,QAAM,kBAAkB,qBAAqB,MAAM,IAAI,EAAE,CAAC;AAG1D,MAAI,sBAAsB,GAAG,eAAe;AAAA;AAC5C,MAAI,aAAa,KAAK,SAAS,GAAG;AAEhC,QAAI,WAAW;AACf,eAAW,gBAAgB,aAAa,MAAM;AAC5C,YAAM,WAAW,QAAQ,KAAK,OAAK,EAAE,SAAS,YAAY;AAC1D,UAAI,YAAY,SAAS,SAAS,SAAS;AACzC,cAAM,eAAe,SAAS;AAC9B,cAAM,UAAU,cAAc,cAAc,cAAc,SAAS,SAAS,CAAC;AAC7E,+BAAuB,GAAG,OAAO;AAAA;AACjC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,UAAU,eAAe,mBAAmB;AAElD,MAAI,aAAa,KAAK,WAAW,GAAG;AAClC,IAAAE,KAAI,EAAE,KAAKF,KAAI,4CAA4C,KAAK,mBAAmB,CAAC,eAAe,CAAC;AACpG;AAAA,EACF;AAEA,QAAM,cAAc,aAAa,KAAK,SAAS,IAAI,YAAY;AAC/D,EAAAE;AAAA,IACED;AAAA,MACE,SAAS,WAAW,QAAQF,MAAK,mBAAmB,CAAC,MAAMC,KAAI,+CAA+C,CAAC;AAAA,IACjH;AAAA,EACF,EAAE,QAAQ;AACZ;AAIA,SAAS,cAAc,cAAsB,cAAsB,IAAoB;AAErF,QAAM,cAAc,eAAe,YAAY;AAG/C,QAAM,WAAW,eAAe;AAChC,QAAM,WAAW,eAAe;AAChC,QAAM,OAAO;AAGb,QAAM,IAAI,MAAM,EAAE,EAAE,KAAK,EAAE;AAE3B,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,CAAC,IAAI;AAEP,IAAE,EAAE,IAAI;AAER,IAAE,EAAE,IAAI;AAER,SAAO,EAAE,KAAK,GAAG;AACnB;AAEA,SAAS,eAAe,GAAmB;AAGzC,SAAO,EAAE,SAAS,GAAG,IAAI,IAAI,CAAC,MAAM;AACtC;AAEA,eAAe,cAAc,SAAiB,SAAyC;AAMrF,QAAM,WAAW,YAAY,SAAS,YAAY,OAAO;AACzD,QAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAGzC,QAAM,OAAO,CAAC;AAQd,QAAM,UAAU,YAAY,SAAS,OAAO;AAC5C,QAAM,aAAa,MAAM,SAAS,SAAS,MAAM;AAGjD,QAAM,SAAS,QAAQ,OAAO;AAC9B,QAAM,UAAU,UAAU,OAAO,EAAE;AACnC,QAAM,iBAAiB,YAAY,MAAM,CAAC,cAAc,GAAG,QAAQ,SAAS,QAAQ;AAGpF,QAAM,eAAe,SAAS,UAAU,GAAG,OAAO,OAAO;AACzD,QAAM,kBAAkB,MAAM,SAAS,cAAc,MAAM;AAC3D,QAAM,WAAW,KAAK,MAAM,eAAe;AAC3C,QAAM,UAAU,SAAS;AAGzB,QAAM,UAAyB,CAAC;AAChC,aAAW,UAAU,SAAS;AAG5B,YAAQ,OAAO,SAAS;AAAA,MACtB,KAAK;AACH,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,UACb,OAAO,OAAO,WAAW,OAAO,YAAY;AAAA,QAC9C,CAAC;AACD;AAAA,MACF,KAAK;AACH,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,QACf,CAAC;AACD;AAAA,MACF,KAAK;AACH,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,QACf,CAAC;AACD;AAAA,MACF;AACE;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AACT;;;AC3gBA,SAAS,aAAa;AACtB,SAAS,QAAAI,OAAM,QAAAC,OAAM,OAAAC,MAAK,SAAAC,QAAO,SAAAC,QAAO,UAAAC,eAAc;AACtD,OAAOC,UAAS;AAChB,OAAOC,cAAa;AAGpB,eAAsB,kBAAkB,SAAiB,MAAiB,YAAmC;AAE3G,QAAM,kBAAkB,MAAMA;AAAA,IAC5B;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,6BAA6B,UAAU,kBAAkBH,OAAMF,KAAI,eAAe,CAAC,CAAC;AAAA,MAC7F,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAI,KAAI,EAAE;AAAA,UACJJ,KAAI,qGAAqG;AAAA,QAC3G;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,QAAQ;AACf,IAAAI,KAAI,EAAE,KAAKJ,KAAI,8BAA8B,CAAC;AAC9C;AAAA,EACF,WAAW,CAAC,gBAAgB,SAAS;AACnC,IAAAI,KAAI,EAAE,KAAKJ,KAAI,2DAA2D,CAAC;AAC3E;AAAA,EACF;AAGA,QAAM,cAAc,MAAM,YAAY,CAAC,SAAS,GAAG,EAAE,KAAK,QAAQ,CAAC;AACnE,QAAM,wBAAwB;AAC9B,QAAM,iBAAiBI,KAAI,qBAAqB,EAAE,MAAM;AACxD,MAAI;AACF,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,kBAAY,QAAQ,GAAG,QAAQ,SAAU,MAAM;AAC7C,uBAAe,OAAO,GAAG,qBAAqB;AAAA,EAAKN,MAAK,IAAI,UAAU,GAAG,CAAC,IAAI,IAAI;AAAA,MACpF,CAAC;AACD,kBAAY,QAAQ,GAAG,QAAQ,SAAU,MAAM;AAC7C,uBAAe,OAAO,GAAG,qBAAqB;AAAA,EAAKA,MAAK,IAAI,UAAU,GAAG,CAAC,IAAI,IAAI;AAAA,MACpF,CAAC;AACD,kBAAY,GAAG,SAAS,WAAS,OAAO,KAAK,CAAC;AAC9C,kBAAY,GAAG,SAAS,UAAQ;AAC9B,YAAI,SAAS,GAAG;AACd,iBAAO,wBAAwB,IAAI,GAAG;AAAA,QACxC,OAAO;AACL,kBAAQ;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,mBAAe,OAAOG,OAAM,qBAAqB;AACjD,mBAAe,QAAQ;AAAA,EACzB,QAAQ;AACN,mBAAe,OAAOE;AAAA,MACpB,uDAAuDJ;AAAA,QACrD,GAAG,UAAU;AAAA,MACf,CAAC;AAAA,IACH;AACA,mBAAe,KAAK;AAAA,EACtB;AACF;;;ACjEA,SAAS,cAAAO,mBAAkB;AAC3B,SAAS,WAAWC,oBAAmB;AAEvC,SAAS,QAAAC,OAAM,OAAAC,MAAK,SAAAC,QAAO,WAAW;AACtC,OAAOC,UAAS;AAChB,OAAOC,cAAa;AAGpB,eAAsB,iBAAiB,MAAkC;AAKvE,WAAS,WAAW,KAAsB;AACxC,UAAM,cAAcL,aAAY,KAAK,cAAc;AACnD,UAAM,cAAcA,aAAY,KAAK,UAAU;AAC/C,WAAO,CAACD,YAAW,GAAG,KAAM,CAACA,YAAW,WAAW,KAAK,CAACA,YAAW,WAAW;AAAA,EACjF;AAEA,QAAM,kBAAkB,CAAC,QAAgB;AACvC,IAAAK,KAAID,OAAM,UAAUF,MAAK,GAAG,CAAC,6BAA6B,CAAC,EAAE,QAAQ;AAAA,EACvE;AAEA,QAAM,oBAAoB,CAAC,QAAgB;AACzC,IAAAG,KAAI,IAAI,IAAIH,MAAK,GAAG,CAAC,2EAA2E,CAAC,EAAE,KAAK;AAAA,EAC1G;AAGA,MAAI,UAAU,KAAK,GAAG,EAAE,CAAC;AACzB,MAAI,SAAS;AAEX,QAAI,WAAW,OAAO,GAAG;AAEvB,sBAAgB,OAAO;AAAA,IACzB,OAAO;AAEL,wBAAkB,OAAO;AACzB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,OAAO;AAEL,UAAM,cAAc,MAAMI;AAAA,MACxB;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUX;AAAA,MACA;AAAA,QACE,UAAU,MAAM;AACd,UAAAD,KAAI,EAAE,KAAKF,KAAI,sBAAsB,CAAC;AACtC,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AACA,cAAU,YAAY;AACtB,QAAI,YAAY,uBAAuB;AACrC,gBAAU,QAAQ,IAAI;AAAA,IACxB;AACA,QAAI,WAAW,OAAO,GAAG;AACvB,sBAAgB,OAAO;AAAA,IACzB,OAAO;AACL,wBAAkB,OAAO;AACzB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;;;AC7EA,SAAS,cAAAI,aAAY,cAAc;AACnC,SAAS,QAAQC,WAAU,WAAWC,oBAAmB;AAEzD,SAAS,SAAAC,cAAa;AACtB,SAAS,cAAc;AACvB,SAAS,QAAAC,OAAM,QAAAC,OAAM,OAAAC,MAAK,SAAAC,QAAO,OAAAC,YAAW;AAC5C,OAAOC,UAAS;AAChB,OAAOC,cAAa;AAKpB,IAAM,UAAU;AAEhB,eAAsB,mBAAmB,SAAiB,MAAgC;AAExF,QAAM,mBAAmB,MAAM,OAAO,SAAS;AAAA,IAC7C,KAAK;AAAA,IACL,MAAM;AAAA,EACR,CAAC;AACD,MAAI,kBAAkB;AACpB,IAAAD,KAAI,EAAE,QAAQ,6CAA6C;AAC3D,IAAAA,KAAI,EAAE,KAAKH,KAAI,0BAA0BD,MAAK,gBAAgB,CAAC,IAAI,CAAC;AACpE;AAAA,EACF;AAGA,QAAM,iBAAiBH,aAAY,SAAS,MAAM,OAAO;AACzD,QAAM,eAAeD,UAAS,SAAS,OAAO;AAC9C,QAAM,kBAAkB,MAAMS;AAAA,IAC5B;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA;AAAA,QAEP;AAAA,UACE,OAAO,mCAAmCN,MAAK,cAAc,CAAC;AAAA,UAC9D,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,OAAO,oCAAoCA,MAAK,YAAY,CAAC;AAAA,UAC7D,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAK,KAAI,EAAE;AAAA,UACJH;AAAA,YACE;AAAA,UACF;AAAA,QACF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,QAAQ;AACf,IAAAG,KAAI,EAAE,KAAKH,KAAI,8BAA8B,CAAC;AAC9C;AAAA,EACF,WAAW,gBAAgB,YAAY,QAAQ;AAC7C,IAAAG,KAAI,EAAE;AAAA,MACJH;AAAA,QACE,0EAA0ED,MAAK,eAAe,CAAC;AAAA,MACjG;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,aAAa,gBAAgB,YAAY,WAAW,iBAAiB;AAC3E,MAAI;AAEF,UAAM,kBAAkB,UAAU;AAAA,EACpC,SAAS,GAAG;AACV,IAAAI,KAAID,KAAI,qCAAqC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK;AAChE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,EAAAC,KAAIF,OAAM,oCAAoCH,MAAK,UAAU,CAAC,GAAG,CAAC,EAAE,QAAQ;AAC9E;AAYA,eAAe,kBAAkB,UAAuE;AAEtG,MAAI,CAACJ,YAAW,QAAQ,GAAG;AACzB,YAAQ,IAAI,iCAAiC,QAAQ,EAAE;AAEvD,UAAMG,OAAM,OAAO,CAAC,SAAS,gDAAgD,QAAQ,CAAC;AAAA,EACxF,OAAO;AACL,YAAQ,IAAI,4CAA4C,QAAQ,EAAE;AAAA,EACpE;AAGA,MAAI,QAAQ,IAAI,IAAI;AAIlB,YAAQ,IAAI,yCAAyC;AACrD,UAAM,SAASF,UAAS,UAAU,MAAM;AACxC,WAAO,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACjD,OAAO;AAEL,YAAQ,IAAI,oDAAoD;AAChE,UAAME,OAAM,OAAO,CAAC,MAAM,GAAG,EAAE,KAAK,SAAS,CAAC;AAAA,EAEhD;AAEA,QAAM,WAAW,UAAU,SAAmB;AAC5C,WAAOA,OAAM,WAAW,CAAC,YAAY,GAAG,IAAI,GAAG,EAAE,KAAK,SAAS,CAAC;AAAA,EAClE;AAEA,UAAQ,IAAI,6BAA6B,OAAO,KAAK;AACrD,QAAM,SAAS,WAAW,OAAO;AACjC,QAAM,SAAS,YAAY,OAAO;AACpC;;;ACpIA,SAAS,oBAAoB;AAC7B,SAAS,QAAAQ,OAAM,OAAAC,MAAK,SAAAC,QAAO,SAAAC,QAAO,UAAAC,eAAc;AAChD,OAAOC,UAAS;AAChB,OAAOC,cAAa;AAGpB,eAAsB,cAAc,SAAiB,MAAgC;AAEnF,QAAM,cAAc,MAAMA;AAAA,IACxB;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,sDAAsDH,OAAMF,KAAI,YAAY,CAAC,CAAC;AAAA,MACvF,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAAI,KAAI,EAAE,KAAKJ,KAAI,oEAAoE,CAAC;AACpF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,QAAQ;AACf,IAAAI,KAAI,EAAE,KAAKJ,KAAI,8BAA8B,CAAC;AAC9C;AAAA,EACF,WAAW,CAAC,YAAY,KAAK;AAC3B,IAAAI,KAAI,EAAE,KAAKJ,KAAI,yCAAyCD,MAAK,UAAU,CAAC,SAAS,CAAC;AAClF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,aAAa,YAAY,EAAE,KAAK,QAAQ,CAAC;AAC/C,IAAAK,KAAI,EAAE,QAAQH,OAAM,6BAA6B,CAAC;AAAA,EACpD,QAAQ;AACN,IAAAG,KAAI,EAAE;AAAA,MACJD;AAAA,QACE,oFAAoFJ,MAAK,UAAU,CAAC;AAAA,MACtG;AAAA,IACF;AAAA,EACF;AACF;;;AC3CA,SAAS,eAAe;AACxB,SAAS,YAAAO,WAAU,WAAWC,cAAa,KAAK,aAAa;AAE7D,SAAS,QAAAC,OAAM,OAAAC,MAAK,SAAAC,QAAO,UAAAC,eAAc;AACzC,OAAOC,UAAS;AAEhB,OAAOC,cAAa;AAEpB,eAAsB,cAAc,SAA8C;AAGhF,iBAAe,SAAS,KAAgC;AACtD,UAAM,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC;AAC1D,UAAM,QAAQ,MAAM,QAAQ;AAAA,MAC1B,QAAQ,IAAI,YAAU;AACpB,cAAM,MAAMN,aAAY,KAAK,OAAO,IAAI;AACxC,eAAO,OAAO,YAAY,IAAI,SAAS,GAAG,IAAI;AAAA,MAChD,CAAC;AAAA,IACH;AACA,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,QAAM,WAAW,MAAM,SAAS,OAAO;AACvC,QAAM,WAAW,SAEd,OAAO,OAAK,EAAE,SAAS,MAAM,CAAC,EAI9B,IAAI,OAAKD,UAAS,SAAS,CAAC,EAAE,WAAW,KAAK,MAAM,GAAG,CAAC;AAC3D,QAAM,aAAa,SAAS,IAAI,OAAK;AACnC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,MAAI;AACJ,MAAI,SAAS,WAAW,GAAG;AAEzB,IAAAM,KAAID,QAAO,+BAA+B,OAAO,yDAAyD,CAAC,EAAE,KAAK;AAClH,cAAU;AAAA,EACZ,WAAW,SAAS,WAAW,GAAG;AAEhC,cAAU,SAAS,CAAC;AACpB,IAAAC,KAAI,EAAE,QAAQ,UAAU,OAAO,qDAAqD;AAAA,EACtF,OAAO;AAGL,UAAM,UAAU,MAAMC;AAAA,MACpB;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU,MAAM;AACd,UAAAD,KAAI,EAAE,KAAKH,KAAI,sBAAsB,CAAC;AACtC,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AACA,cAAU,QAAQ;AAClB,IAAAG,KAAIF,OAAM,UAAUF,MAAK,OAAO,CAAC,iCAAiC,CAAC,EAAE,QAAQ;AAAA,EAC/E;AAEA,SAAO;AACT;;;ACrEA,SAAS,cAAAM,aAAY,aAAa,aAAa,YAAY,UAAAC,eAAc;AACzE,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,QAAQC,iBAAgB;AAEjC,SAAS,wBAAwB;AACjC,SAAS,QAAAC,OAAM,OAAAC,MAAK,SAAAC,QAAO,OAAAC,MAAK,UAAAC,eAAc;AAC9C,OAAOC,UAAS;AAChB,OAAOC,cAAa;AAGpB,IAAM,YAAY;AAAA,EAChB;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AACF;AASA,eAAsB,eAAe,MAAoC;AACvE,MAAI;AACJ,MAAI,KAAK,UAAU;AAEjB,mBAAe,KAAK;AAAA,EACtB,OAAO;AAEL,UAAM,UAAU,MAAMA;AAAA,MACpB;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU,MAAM;AACd,UAAAD,KAAI,EAAE,KAAKJ,KAAI,sBAAsB,CAAC;AACtC,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AACA,mBAAe,QAAQ;AAAA,EACzB;AAGA,QAAM,aAAa;AACnB,QAAM,SAAS,KAAK,UAAU;AAG9B,MAAI;AACJ,MAAI,aAAa,SAAS,GAAG,GAAG;AAI9B,sBAAkB;AAAA,EACpB,WAAW,aAAa,SAAS,GAAG,GAAG;AAGrC,sBAAkB,UAAU,YAAY;AAAA,EAC1C,OAAO;AAML,sBAAkB,4DAA4D,YAAY;AAAA,EAC5F;AACA,QAAM,cAAc,GAAG,eAAe,IAAI,MAAM;AAEhD,EAAAI,KAAIH,OAAM,UAAUF,MAAK,WAAW,CAAC,oCAAoC,CAAC,EAAE,QAAQ;AAEpF,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAEA,eAAsB,aACpB,UACA,SACA,YACA,kBACA,YACe;AAEf,QAAM,kBAAkBK,KAAI,2BAA2B,EAAE,MAAM;AAE/D,MAAI;AAEF,UAAM,SAAS,YAAYN,UAAS,OAAO,GAAG,aAAa,CAAC;AAI5D,UAAM,iBAAiB,SAAS,KAAK;AAAA,MACnC,OAAO;AAAA,MACP,KAAK;AAAA,IACP,CAAC;AAID,QAAI,CAACH,YAAW,MAAM,KAAK,YAAY,MAAM,EAAE,WAAW,GAAG;AAC3D,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAChG;AAEA,QAAI,kBAAkB;AAIpB,MAAAC,QAAOE,UAAS,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACrE;AAEA,QAAI,YAAY;AAId,MAAAF,QAAOE,UAAS,QAAQ,OAAO,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACpE;AAGA,UAAM,KAAK,QAAQ,SAAS;AAAA,MAC1B,WAAW;AAAA,MACX,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,YAAY;AAIf,iBAAWA,UAAS,SAAS,SAAS,gBAAgB,GAAGA,UAAS,SAAS,SAAS,YAAY,CAAC;AAAA,IACnG;AAGA,IAAAF,QAAO,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACjD,SAAS,GAAG;AAGV,oBAAgB,KAAK;AACrB,YAAQ,MAAMM,KAAI,EAAE,OAAO,CAAC;AAC5B,YAAQ,MAAMC,QAAO,6CAA6C,CAAC;AACnE,YAAQ;AAAA,MACNA;AAAA,QACE;AAAA,MACF;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAIR,YAAWG,UAAS,SAAS,UAAU,CAAC,KAAK,eAAe,QAAQ;AAItE,UAAM,gBAAgBA,UAAS,SAAS,qBAAqB;AAC7D,UAAM,mBAAmB;AAAA;AAAA;AACzB,UAAMD,WAAU,eAAe,gBAAgB;AAAA,EACjD;AAEA,kBAAgB,OAAOI,OAAM,kBAAkB;AAC/C,kBAAgB,QAAQ;AAC1B;;;AR/JA,eAAsB,OAAsB;AAE1C,QAAM,aAAa,qBAAqB,GAAG,QAAQ;AAGnD,QAAM,OAAO,MAAM,QAAQ,IAAI;AAC/B,EAAAK,SAAQ,SAAS,IAAI;AAErB,MAAI,KAAK,QAAQ;AACf,YAAQ,IAAI;AACZ,IAAAC,KAAI,EAAE,KAAKC,KAAI,8CAA8C,CAAC;AAAA,EAChE;AAGA,UAAQ,IAAI;AAAA,EAAKC,MAAK,0BAA0B,CAAC,EAAE;AACnD,UAAQ,IAAI;AAAA,CAA2D;AAGvE,QAAM,UAAU,MAAM,iBAAiB,IAAI;AAC3C,UAAQ,IAAI;AAGZ,QAAM,mBAAmBC,YAAWC,aAAY,SAAS,QAAQ,CAAC;AAGlE,QAAM,WAAW,MAAM,eAAe,IAAI;AAC1C,UAAQ,IAAI;AAGZ,MAAI,UAAU,MAAM,cAAc,OAAO;AACzC,QAAM,aAAa,YAAY;AAC/B,UAAQ,IAAI;AAEZ,MAAI,CAAC,KAAK,QAAQ;AAEhB,UAAM,aAAa,UAAU,SAAS,YAAY,kBAAkB,UAAU;AAC9E,YAAQ,IAAI;AAAA,EACd;AAEA,MAAI,YAAY,QAAW;AAMzB,cAAU,QAAQC,OAAM,GAAG;AAAA,EAC7B;AAGA,QAAM,YAAY,MAAM,iBAAiB;AAEzC,MAAI,CAAC,KAAK,QAAQ;AAEhB,UAAM,gBAAgB,SAAS,SAAS,SAAS;AAGjD,UAAM,uBACJF,YAAWC,aAAY,SAAS,SAAS,QAAQ,CAAC,KAAKD,YAAWC,aAAY,SAAS,SAAS,aAAa,CAAC;AAChH,QAAI,CAAC,sBAAsB;AACzB,YAAM,wBAAwB,OAAO;AAAA,IACvC;AAAA,EACF;AACA,UAAQ,IAAI;AAEZ,MAAI,kBAAkB;AAEpB,IAAAJ,KAAI,EAAE,QAAQ,mBAAmBE,MAAK,QAAQ,CAAC,cAAc;AAC7D,IAAAF,KAAI,EAAE;AAAA,MACJC,KAAI,kCAAkCK,MAAK,QAAQ,CAAC,oDAAoD;AAAA,IAC1G;AACA,YAAQ,IAAI;AAAA,EACd,OAAO;AAGL,UAAM,qBAAqBH,YAAWC,aAAY,SAAS,QAAQ,CAAC;AACpE,QAAI,sBAAsB,cAAc,CAAC,KAAK,QAAQ;AACpD,YAAM,gBAAgB,SAAS,OAAO;AACtC,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AAIA,MAAI,cAAc,KAAK;AACrB,UAAM,mBAAmB,SAAS,IAAI;AACtC,YAAQ,IAAI;AAAA,EACd;AAGA,QAAM,kBAAkB,SAAS,MAAM,UAAU;AACjD,UAAQ,IAAI;AAGZ,QAAM,cAAc,SAAS,IAAI;AACjC,UAAQ,IAAI;AAEZ,EAAAJ,KAAIO,OAAM,iBAAiB,CAAC,EAAE,QAAQ;AAEtC,UAAQ,IAAI;AAAA,EAAK,OAAO,MAAM,cAAc,CAAC,CAAC;AAAA,CAAI;AAElD,QAAM,aAAaC,UAAS,QAAQ,IAAI,GAAG,OAAO;AAClD,QAAM,SAAS,eAAe,QAAQ,gBAAgB,GAAG,UAAU;AAGnE,MAAI,eAAe,IAAI;AACrB,YAAQ,IAAI,eAAeN,MAAKI,MAAK,IAAI,CAAC,CAAC,aAAaJ,MAAKI,MAAK,UAAU,CAAC,CAAC,qBAAqB;AAAA,EACrG;AACA,UAAQ,IAAI,OAAOJ,MAAKI,MAAK,MAAM,CAAC,CAAC,mCAAmCJ,MAAKI,MAAK,QAAQ,CAAC,CAAC,YAAY;AACxG,UAAQ,IAAI,EAAE;AAChB;","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.
|
|
3
|
+
"version": "0.2.36",
|
|
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.
|
|
14
|
+
"@sdeverywhere/compile": "^0.7.29",
|
|
15
15
|
"execa": "^6.1.0",
|
|
16
16
|
"find-up": "^6.3.0",
|
|
17
17
|
"fs-extra": "^10.1.0",
|