@sdeverywhere/build 0.3.3 → 0.3.5
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 +188 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +183 -22
- package/dist/index.d.ts +183 -22
- package/dist/index.js +192 -74
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -121,6 +121,26 @@ function resolveUserConfig(userConfig, mode, sdeDir, sdeCmdPath) {
|
|
|
121
121
|
} else {
|
|
122
122
|
watchPaths = modelFiles;
|
|
123
123
|
}
|
|
124
|
+
const rawGenFormat = userConfig.genFormat || "js";
|
|
125
|
+
let genFormat;
|
|
126
|
+
switch (rawGenFormat) {
|
|
127
|
+
case "js":
|
|
128
|
+
genFormat = "js";
|
|
129
|
+
break;
|
|
130
|
+
case "c":
|
|
131
|
+
genFormat = "c";
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`The configured genFormat value is invalid; must be either 'js' or 'c'`);
|
|
135
|
+
}
|
|
136
|
+
let outListingFile;
|
|
137
|
+
if (userConfig.outListingFile) {
|
|
138
|
+
if ((0, import_path.isAbsolute)(userConfig.outListingFile)) {
|
|
139
|
+
outListingFile = userConfig.outListingFile;
|
|
140
|
+
} else {
|
|
141
|
+
outListingFile = (0, import_path.resolve)(rootDir, userConfig.outListingFile);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
124
144
|
return {
|
|
125
145
|
mode,
|
|
126
146
|
rootDir,
|
|
@@ -128,6 +148,8 @@ function resolveUserConfig(userConfig, mode, sdeDir, sdeCmdPath) {
|
|
|
128
148
|
modelFiles,
|
|
129
149
|
modelInputPaths,
|
|
130
150
|
watchPaths,
|
|
151
|
+
genFormat,
|
|
152
|
+
outListingFile,
|
|
131
153
|
sdeDir,
|
|
132
154
|
sdeCmdPath
|
|
133
155
|
};
|
|
@@ -545,18 +567,33 @@ async function generateModel(context, plugins) {
|
|
|
545
567
|
}
|
|
546
568
|
}
|
|
547
569
|
for (const plugin of plugins) {
|
|
548
|
-
if (plugin.
|
|
549
|
-
await plugin.
|
|
570
|
+
if (plugin.preGenerateCode) {
|
|
571
|
+
await plugin.preGenerateCode(context, config.genFormat);
|
|
550
572
|
}
|
|
551
573
|
}
|
|
552
|
-
await
|
|
574
|
+
await generateCode(context, config.sdeDir, sdeCmdPath, prepDir);
|
|
575
|
+
const generatedCodeFile = `processed.${config.genFormat}`;
|
|
576
|
+
const generatedCodePath = (0, import_path3.join)(prepDir, "build", generatedCodeFile);
|
|
553
577
|
for (const plugin of plugins) {
|
|
554
|
-
if (plugin.
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
578
|
+
if (plugin.postGenerateCode) {
|
|
579
|
+
let generatedCodeContent = await (0, import_promises.readFile)(generatedCodePath, "utf8");
|
|
580
|
+
generatedCodeContent = await plugin.postGenerateCode(context, config.genFormat, generatedCodeContent);
|
|
581
|
+
await (0, import_promises.writeFile)(generatedCodePath, generatedCodeContent);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (config.genFormat === "js") {
|
|
585
|
+
const outputJsFile = "generated-model.js";
|
|
586
|
+
const stagedOutputJsPath = context.prepareStagedFile("model", outputJsFile, prepDir, outputJsFile);
|
|
587
|
+
await (0, import_promises.copyFile)(generatedCodePath, stagedOutputJsPath);
|
|
588
|
+
}
|
|
589
|
+
if (config.outListingFile) {
|
|
590
|
+
const srcListingJsonPath = (0, import_path3.join)(prepDir, "build", "processed.json");
|
|
591
|
+
const stagedDir = "model";
|
|
592
|
+
const stagedFile = "listing.json";
|
|
593
|
+
const dstDir = (0, import_path3.dirname)(config.outListingFile);
|
|
594
|
+
const dstFile = (0, import_path3.basename)(config.outListingFile);
|
|
595
|
+
const stagedListingJsonPath = context.prepareStagedFile(stagedDir, stagedFile, dstDir, dstFile);
|
|
596
|
+
await (0, import_promises.copyFile)(srcListingJsonPath, stagedListingJsonPath);
|
|
560
597
|
}
|
|
561
598
|
const t1 = performance.now();
|
|
562
599
|
const elapsed = ((t1 - t0) / 1e3).toFixed(1);
|
|
@@ -567,7 +604,14 @@ async function preprocessMdl(context, sdeCmdPath, prepDir, modelFile) {
|
|
|
567
604
|
await (0, import_promises.copyFile)(modelFile, (0, import_path3.join)(prepDir, "processed.mdl"));
|
|
568
605
|
const command = sdeCmdPath;
|
|
569
606
|
const args = ["generate", "--preprocess", "processed.mdl"];
|
|
570
|
-
await context.spawnChild(prepDir, command, args
|
|
607
|
+
const ppOutput = await context.spawnChild(prepDir, command, args, {
|
|
608
|
+
// The default error message from `spawnChild` is not very informative, so the
|
|
609
|
+
// following allows us to throw our own error
|
|
610
|
+
ignoreError: true
|
|
611
|
+
});
|
|
612
|
+
if (ppOutput.exitCode !== 0) {
|
|
613
|
+
throw new Error(`Failed to preprocess mdl file: 'sde generate' command failed (code=${ppOutput.exitCode})`);
|
|
614
|
+
}
|
|
571
615
|
await (0, import_promises.copyFile)((0, import_path3.join)(prepDir, "build", "processed.mdl"), (0, import_path3.join)(prepDir, "processed.mdl"));
|
|
572
616
|
}
|
|
573
617
|
async function flattenMdls(context, sdeCmdPath, prepDir, modelFiles) {
|
|
@@ -600,31 +644,44 @@ async function flattenMdls(context, sdeCmdPath, prepDir, modelFiles) {
|
|
|
600
644
|
log("error", ` ${line}`);
|
|
601
645
|
}
|
|
602
646
|
}
|
|
603
|
-
throw new Error(`
|
|
647
|
+
throw new Error(`Failed to flatten mdl files: 'sde flatten' command failed (code=${output.exitCode})`);
|
|
604
648
|
} else if (output.exitCode !== 0) {
|
|
605
|
-
throw new Error(`
|
|
649
|
+
throw new Error(`Failed to flatten mdl files: 'sde flatten' command failed (code=${output.exitCode})`);
|
|
606
650
|
}
|
|
607
651
|
await (0, import_promises.copyFile)((0, import_path3.join)(prepDir, "build", "processed.mdl"), (0, import_path3.join)(prepDir, "processed.mdl"));
|
|
608
652
|
}
|
|
609
|
-
async function
|
|
610
|
-
|
|
653
|
+
async function generateCode(context, sdeDir, sdeCmdPath, prepDir) {
|
|
654
|
+
const genFormat = context.config.genFormat;
|
|
655
|
+
const genFormatName = genFormat.toUpperCase();
|
|
656
|
+
log("verbose", ` Generating ${genFormatName} code`);
|
|
611
657
|
const command = sdeCmdPath;
|
|
612
|
-
const
|
|
613
|
-
|
|
658
|
+
const outFormat = `--outformat=${genFormat}`;
|
|
659
|
+
const genCmdArgs = ["generate", outFormat, "--list", "--spec", "spec.json", "processed"];
|
|
660
|
+
const genCmdOutput = await context.spawnChild(prepDir, command, genCmdArgs, {
|
|
614
661
|
// By default, ignore lines that start with "WARNING: Data for" since these are often harmless
|
|
615
662
|
// TODO: Don't filter by default, but make it configurable
|
|
616
663
|
// ignoredMessageFilter: 'WARNING: Data for'
|
|
664
|
+
// The default error message from `spawnChild` is not very informative, so the
|
|
665
|
+
// following allows us to throw our own error
|
|
666
|
+
ignoreError: true
|
|
617
667
|
});
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
668
|
+
if (genCmdOutput.exitCode !== 0) {
|
|
669
|
+
throw new Error(
|
|
670
|
+
`Failed to generate ${genFormatName} code: 'sde generate' command failed (code=${genCmdOutput.exitCode})`
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
if (genFormat === "c") {
|
|
674
|
+
const buildDir = (0, import_path3.join)(prepDir, "build");
|
|
675
|
+
const sdeCDir = (0, import_path3.join)(sdeDir, "src", "c");
|
|
676
|
+
const files = await (0, import_promises.readdir)(sdeCDir);
|
|
677
|
+
const copyOps = [];
|
|
678
|
+
for (const file of files) {
|
|
679
|
+
if (file.endsWith(".c") || file.endsWith(".h")) {
|
|
680
|
+
copyOps.push((0, import_promises.copyFile)((0, import_path3.join)(sdeCDir, file), (0, import_path3.join)(buildDir, file)));
|
|
681
|
+
}
|
|
625
682
|
}
|
|
683
|
+
await Promise.all(copyOps);
|
|
626
684
|
}
|
|
627
|
-
await Promise.all(copyOps);
|
|
628
685
|
}
|
|
629
686
|
|
|
630
687
|
// src/build/impl/hash-files.ts
|
|
@@ -659,45 +716,44 @@ async function computeInputFilesHash(config) {
|
|
|
659
716
|
async function buildOnce(config, userConfig, plugins, options) {
|
|
660
717
|
const stagedFiles = new StagedFiles(config.prepDir);
|
|
661
718
|
const context = new BuildContext(config, stagedFiles, options.abortSignal);
|
|
662
|
-
|
|
719
|
+
const modelHashPath = (0, import_path5.join)(config.prepDir, "model-hash.txt");
|
|
720
|
+
let succeeded = true;
|
|
663
721
|
try {
|
|
664
|
-
|
|
665
|
-
if (
|
|
722
|
+
const userModelSpec = await userConfig.modelSpec(context);
|
|
723
|
+
if (userModelSpec === void 0) {
|
|
666
724
|
return (0, import_neverthrow2.err)(new Error("The model spec must be defined"));
|
|
667
725
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
726
|
+
const modelSpec = resolveModelSpec(userModelSpec);
|
|
727
|
+
for (const plugin of plugins) {
|
|
728
|
+
if (plugin.preGenerate) {
|
|
729
|
+
await plugin.preGenerate(context, modelSpec);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
const specJson = {
|
|
733
|
+
inputVarNames: modelSpec.inputVarNames,
|
|
734
|
+
outputVarNames: modelSpec.outputVarNames,
|
|
735
|
+
externalDatfiles: modelSpec.datFiles,
|
|
736
|
+
bundleListing: modelSpec.bundleListing,
|
|
737
|
+
customLookups: modelSpec.customLookups,
|
|
738
|
+
customOutputs: modelSpec.customOutputs,
|
|
739
|
+
...modelSpec.options
|
|
740
|
+
};
|
|
741
|
+
const specPath = (0, import_path5.join)(config.prepDir, "spec.json");
|
|
742
|
+
await (0, import_promises2.writeFile)(specPath, JSON.stringify(specJson, null, 2));
|
|
743
|
+
let previousModelHash;
|
|
744
|
+
if ((0, import_fs4.existsSync)(modelHashPath)) {
|
|
745
|
+
previousModelHash = (0, import_fs4.readFileSync)(modelHashPath, "utf8");
|
|
746
|
+
} else {
|
|
747
|
+
previousModelHash = "NONE";
|
|
748
|
+
}
|
|
749
|
+
const inputFilesHash = await computeInputFilesHash(config);
|
|
750
|
+
let needModelGen;
|
|
751
|
+
if (options.forceModelGen === true) {
|
|
752
|
+
needModelGen = true;
|
|
753
|
+
} else {
|
|
754
|
+
const hashMismatch = inputFilesHash !== previousModelHash;
|
|
755
|
+
needModelGen = hashMismatch;
|
|
674
756
|
}
|
|
675
|
-
}
|
|
676
|
-
const specJson = {
|
|
677
|
-
inputVarNames: modelSpec.inputs.map((input) => input.varName),
|
|
678
|
-
outputVarNames: modelSpec.outputs.map((output) => output.varName),
|
|
679
|
-
externalDatfiles: modelSpec.datFiles,
|
|
680
|
-
...modelSpec.options
|
|
681
|
-
};
|
|
682
|
-
const specPath = (0, import_path5.join)(config.prepDir, "spec.json");
|
|
683
|
-
await (0, import_promises2.writeFile)(specPath, JSON.stringify(specJson, null, 2));
|
|
684
|
-
const modelHashPath = (0, import_path5.join)(config.prepDir, "model-hash.txt");
|
|
685
|
-
let previousModelHash;
|
|
686
|
-
if ((0, import_fs4.existsSync)(modelHashPath)) {
|
|
687
|
-
previousModelHash = (0, import_fs4.readFileSync)(modelHashPath, "utf8");
|
|
688
|
-
} else {
|
|
689
|
-
previousModelHash = "NONE";
|
|
690
|
-
}
|
|
691
|
-
const inputFilesHash = await computeInputFilesHash(config);
|
|
692
|
-
let needModelGen;
|
|
693
|
-
if (options.forceModelGen === true) {
|
|
694
|
-
needModelGen = true;
|
|
695
|
-
} else {
|
|
696
|
-
const hashMismatch = inputFilesHash !== previousModelHash;
|
|
697
|
-
needModelGen = hashMismatch;
|
|
698
|
-
}
|
|
699
|
-
let succeeded = true;
|
|
700
|
-
try {
|
|
701
757
|
if (needModelGen) {
|
|
702
758
|
await generateModel(context, plugins);
|
|
703
759
|
(0, import_fs4.writeFileSync)(modelHashPath, inputFilesHash);
|
|
@@ -733,6 +789,69 @@ async function buildOnce(config, userConfig, plugins, options) {
|
|
|
733
789
|
}
|
|
734
790
|
return (0, import_neverthrow2.ok)(succeeded);
|
|
735
791
|
}
|
|
792
|
+
function resolveModelSpec(modelSpec) {
|
|
793
|
+
let inputVarNames;
|
|
794
|
+
let inputSpecs;
|
|
795
|
+
if (modelSpec.inputs.length > 0) {
|
|
796
|
+
const item = modelSpec.inputs[0];
|
|
797
|
+
if (typeof item === "string") {
|
|
798
|
+
inputVarNames = modelSpec.inputs;
|
|
799
|
+
inputSpecs = inputVarNames.map((varName) => {
|
|
800
|
+
return {
|
|
801
|
+
varName
|
|
802
|
+
};
|
|
803
|
+
});
|
|
804
|
+
} else {
|
|
805
|
+
inputSpecs = modelSpec.inputs;
|
|
806
|
+
inputVarNames = inputSpecs.map((spec) => spec.varName);
|
|
807
|
+
}
|
|
808
|
+
} else {
|
|
809
|
+
inputVarNames = [];
|
|
810
|
+
inputSpecs = [];
|
|
811
|
+
}
|
|
812
|
+
let outputVarNames;
|
|
813
|
+
let outputSpecs;
|
|
814
|
+
if (modelSpec.outputs.length > 0) {
|
|
815
|
+
const item = modelSpec.outputs[0];
|
|
816
|
+
if (typeof item === "string") {
|
|
817
|
+
outputVarNames = modelSpec.outputs;
|
|
818
|
+
outputSpecs = outputVarNames.map((varName) => {
|
|
819
|
+
return {
|
|
820
|
+
varName
|
|
821
|
+
};
|
|
822
|
+
});
|
|
823
|
+
} else {
|
|
824
|
+
outputSpecs = modelSpec.outputs;
|
|
825
|
+
outputVarNames = outputSpecs.map((spec) => spec.varName);
|
|
826
|
+
}
|
|
827
|
+
} else {
|
|
828
|
+
outputVarNames = [];
|
|
829
|
+
outputSpecs = [];
|
|
830
|
+
}
|
|
831
|
+
let customLookups;
|
|
832
|
+
if (modelSpec.customLookups !== void 0) {
|
|
833
|
+
customLookups = modelSpec.customLookups;
|
|
834
|
+
} else {
|
|
835
|
+
customLookups = false;
|
|
836
|
+
}
|
|
837
|
+
let customOutputs;
|
|
838
|
+
if (modelSpec.customOutputs !== void 0) {
|
|
839
|
+
customOutputs = modelSpec.customOutputs;
|
|
840
|
+
} else {
|
|
841
|
+
customOutputs = false;
|
|
842
|
+
}
|
|
843
|
+
return {
|
|
844
|
+
inputVarNames,
|
|
845
|
+
inputs: inputSpecs,
|
|
846
|
+
outputVarNames,
|
|
847
|
+
outputs: outputSpecs,
|
|
848
|
+
datFiles: modelSpec.datFiles || [],
|
|
849
|
+
bundleListing: modelSpec.bundleListing === true,
|
|
850
|
+
customLookups,
|
|
851
|
+
customOutputs,
|
|
852
|
+
options: modelSpec.options
|
|
853
|
+
};
|
|
854
|
+
}
|
|
736
855
|
|
|
737
856
|
// src/build/impl/watch.ts
|
|
738
857
|
var import_path6 = require("path");
|
|
@@ -812,28 +931,27 @@ async function build(mode, options) {
|
|
|
812
931
|
const messagesPath = (0, import_path7.join)(resolvedConfig.prepDir, "messages.html");
|
|
813
932
|
const overlayEnabled2 = mode === "development";
|
|
814
933
|
setOverlayFile(messagesPath, overlayEnabled2);
|
|
815
|
-
const plugins = userConfig.plugins || [];
|
|
816
|
-
for (const plugin of plugins) {
|
|
817
|
-
if (plugin.init) {
|
|
818
|
-
await plugin.init(resolvedConfig);
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
934
|
try {
|
|
822
|
-
const
|
|
935
|
+
const plugins = userConfig.plugins || [];
|
|
936
|
+
for (const plugin of plugins) {
|
|
937
|
+
if (plugin.init) {
|
|
938
|
+
await plugin.init(resolvedConfig);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
823
941
|
if (mode === "development") {
|
|
824
|
-
const buildResult = await buildOnce(resolvedConfig, userConfig,
|
|
942
|
+
const buildResult = await buildOnce(resolvedConfig, userConfig, plugins, {});
|
|
825
943
|
if (buildResult.isErr()) {
|
|
826
944
|
return (0, import_neverthrow3.err)(buildResult.error);
|
|
827
945
|
}
|
|
828
|
-
for (const plugin of
|
|
946
|
+
for (const plugin of plugins) {
|
|
829
947
|
if (plugin.watch) {
|
|
830
948
|
await plugin.watch(resolvedConfig);
|
|
831
949
|
}
|
|
832
950
|
}
|
|
833
|
-
watch(resolvedConfig, userConfig,
|
|
951
|
+
watch(resolvedConfig, userConfig, plugins);
|
|
834
952
|
return (0, import_neverthrow3.ok)({});
|
|
835
953
|
} else {
|
|
836
|
-
const buildResult = await buildOnce(resolvedConfig, userConfig,
|
|
954
|
+
const buildResult = await buildOnce(resolvedConfig, userConfig, plugins, {});
|
|
837
955
|
if (buildResult.isErr()) {
|
|
838
956
|
return (0, import_neverthrow3.err)(buildResult.error);
|
|
839
957
|
}
|