@tutorialkit-rb/cli 1.5.2-rb.0.1.0 → 1.5.2-rb.0.1.1
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.js +161 -176
- package/package.json +1 -1
- package/template/.gitignore +1 -0
- package/template/bin/build-wasm +10 -0
- package/template/package.json +4 -4
- package/template/src/components/FileManager.tsx +62 -13
package/dist/index.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import
|
|
4
|
+
import chalk9 from "chalk";
|
|
5
5
|
import yargs2 from "yargs-parser";
|
|
6
6
|
|
|
7
7
|
// src/commands/create/index.ts
|
|
8
8
|
import fs7 from "node:fs";
|
|
9
|
-
import
|
|
9
|
+
import path8 from "node:path";
|
|
10
10
|
import * as prompts7 from "@clack/prompts";
|
|
11
|
-
import
|
|
12
|
-
import { execa } from "execa";
|
|
11
|
+
import chalk7 from "chalk";
|
|
13
12
|
import "yargs-parser";
|
|
14
13
|
|
|
15
14
|
// package.json
|
|
16
15
|
var package_default = {
|
|
17
16
|
name: "@tutorialkit-rb/cli",
|
|
18
|
-
version: "1.5.2-rb.0.1.
|
|
17
|
+
version: "1.5.2-rb.0.1.1",
|
|
19
18
|
description: "Interactive tutorials powered by WebContainer API",
|
|
20
19
|
author: "StackBlitz Inc.",
|
|
21
20
|
type: "module",
|
|
@@ -439,9 +438,9 @@ function replaceArgs(newTutorialKitArgs, ast) {
|
|
|
439
438
|
const integrationImport = "@tutorialkit-rb/astro";
|
|
440
439
|
let integrationId;
|
|
441
440
|
visit(ast, {
|
|
442
|
-
ImportDeclaration(
|
|
443
|
-
if (
|
|
444
|
-
const defaultImport =
|
|
441
|
+
ImportDeclaration(path10) {
|
|
442
|
+
if (path10.node.source.value === integrationImport) {
|
|
443
|
+
const defaultImport = path10.node.specifiers.find((specifier) => specifier.type === "ImportDefaultSpecifier");
|
|
445
444
|
if (defaultImport) {
|
|
446
445
|
integrationId = defaultImport.local;
|
|
447
446
|
}
|
|
@@ -452,11 +451,11 @@ function replaceArgs(newTutorialKitArgs, ast) {
|
|
|
452
451
|
throw new Error(`Could not find import to '${integrationImport}'`);
|
|
453
452
|
}
|
|
454
453
|
visit(ast, {
|
|
455
|
-
ExportDefaultDeclaration(
|
|
456
|
-
if (!t.isCallExpression(
|
|
454
|
+
ExportDefaultDeclaration(path10) {
|
|
455
|
+
if (!t.isCallExpression(path10.node.declaration)) {
|
|
457
456
|
return;
|
|
458
457
|
}
|
|
459
|
-
const configObject =
|
|
458
|
+
const configObject = path10.node.declaration.arguments[0];
|
|
460
459
|
if (!t.isObjectExpression(configObject)) {
|
|
461
460
|
throw new Error("TutorialKit is not part of the exported config");
|
|
462
461
|
}
|
|
@@ -585,11 +584,101 @@ function validateEditorOrigin(value) {
|
|
|
585
584
|
}
|
|
586
585
|
}
|
|
587
586
|
|
|
588
|
-
// src/commands/create/
|
|
589
|
-
import fs3 from "node:fs";
|
|
587
|
+
// src/commands/create/gemfile-editing.ts
|
|
590
588
|
import path3 from "node:path";
|
|
591
589
|
import * as prompts2 from "@clack/prompts";
|
|
592
590
|
import chalk3 from "chalk";
|
|
591
|
+
import { execa } from "execa";
|
|
592
|
+
|
|
593
|
+
// src/commands/create/options.ts
|
|
594
|
+
import path2 from "node:path";
|
|
595
|
+
import { fileURLToPath } from "node:url";
|
|
596
|
+
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
597
|
+
var templatePath = path2.resolve(__dirname, "../template");
|
|
598
|
+
var DEFAULT_VALUES = {
|
|
599
|
+
git: !process.env.CI,
|
|
600
|
+
install: true,
|
|
601
|
+
start: true,
|
|
602
|
+
dryRun: false,
|
|
603
|
+
force: false,
|
|
604
|
+
packageManager: "npm",
|
|
605
|
+
provider: "skip"
|
|
606
|
+
};
|
|
607
|
+
function readFlag(flags, flag) {
|
|
608
|
+
let value = flags[flag];
|
|
609
|
+
if (flags.defaults) {
|
|
610
|
+
value ??= DEFAULT_VALUES[flag];
|
|
611
|
+
}
|
|
612
|
+
return value;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// src/commands/create/gemfile-editing.ts
|
|
616
|
+
async function promptGemfileEditing(dest, flags) {
|
|
617
|
+
if (flags.defaults || flags.dryRun) {
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
prompts2.log.message(chalk3.bold.underline("Ruby Gems Configuration"));
|
|
621
|
+
prompts2.log.info(`Your Ruby application's gems are configured in ${chalk3.blue("ruby-wasm/Gemfile")}`);
|
|
622
|
+
const answer = await prompts2.confirm({
|
|
623
|
+
message: "Would you like to edit the Gemfile to add additional gems?",
|
|
624
|
+
initialValue: true
|
|
625
|
+
});
|
|
626
|
+
assertNotCanceled(answer);
|
|
627
|
+
if (answer) {
|
|
628
|
+
const gemfilePath = path3.resolve(dest, "ruby-wasm/Gemfile");
|
|
629
|
+
const editor = process.env.EDITOR;
|
|
630
|
+
if (editor) {
|
|
631
|
+
prompts2.log.message("");
|
|
632
|
+
prompts2.log.info(`Opening ${chalk3.blue("ruby-wasm/Gemfile")} in your editor...`);
|
|
633
|
+
try {
|
|
634
|
+
await execa(editor, [gemfilePath], { stdio: "inherit" });
|
|
635
|
+
prompts2.log.success("Great! Your Gemfile has been configured.");
|
|
636
|
+
return true;
|
|
637
|
+
} catch (error) {
|
|
638
|
+
prompts2.log.warn(`Failed to open editor: ${error.message}`);
|
|
639
|
+
prompts2.log.info("Falling back to manual editing instructions...");
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
prompts2.log.message("");
|
|
643
|
+
prompts2.log.step(`1. Open ${chalk3.blue(gemfilePath)} in your editor`);
|
|
644
|
+
prompts2.log.step(`2. Add any additional gems you need for your tutorial`);
|
|
645
|
+
prompts2.log.step(`3. Save the file and return here`);
|
|
646
|
+
prompts2.log.message("");
|
|
647
|
+
const ready = await prompts2.confirm({
|
|
648
|
+
message: "Have you finished editing the Gemfile?",
|
|
649
|
+
initialValue: true
|
|
650
|
+
});
|
|
651
|
+
assertNotCanceled(ready);
|
|
652
|
+
if (ready) {
|
|
653
|
+
prompts2.log.success("Great! Your Gemfile has been configured.");
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
function printRubyNextSteps(dest) {
|
|
660
|
+
let i = 0;
|
|
661
|
+
prompts2.log.message(chalk3.bold.underline("Next Steps"));
|
|
662
|
+
const steps = [
|
|
663
|
+
[`cd ${dest}`, "Navigate to project"],
|
|
664
|
+
["npm run build:wasm", "Build Ruby WebAssembly with your gems"],
|
|
665
|
+
["npm run dev", "Start development server"],
|
|
666
|
+
[, `Head over to ${chalk3.underline("http://localhost:4321")}`]
|
|
667
|
+
];
|
|
668
|
+
for (const [command, text2] of steps) {
|
|
669
|
+
i++;
|
|
670
|
+
prompts2.log.step(`${i}. ${command ? `${chalk3.blue(command)} - ` : ""}${text2}`);
|
|
671
|
+
}
|
|
672
|
+
prompts2.log.message("");
|
|
673
|
+
prompts2.log.info("\u{1F4A1} The WASM build step may take several minutes the first time.");
|
|
674
|
+
prompts2.log.info("\u{1F4A1} Subsequent builds will be faster thanks to caching.");
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// src/commands/create/generate-hosting-config.ts
|
|
678
|
+
import fs3 from "node:fs";
|
|
679
|
+
import path4 from "node:path";
|
|
680
|
+
import * as prompts3 from "@clack/prompts";
|
|
681
|
+
import chalk4 from "chalk";
|
|
593
682
|
|
|
594
683
|
// src/commands/create/hosting-config/_headers.txt?raw
|
|
595
684
|
var headers_default = "/*\n Cross-Origin-Embedder-Policy: require-corp\n Cross-Origin-Opener-Policy: same-origin\n";
|
|
@@ -616,33 +705,11 @@ var vercel_default = {
|
|
|
616
705
|
]
|
|
617
706
|
};
|
|
618
707
|
|
|
619
|
-
// src/commands/create/options.ts
|
|
620
|
-
import path2 from "node:path";
|
|
621
|
-
import { fileURLToPath } from "node:url";
|
|
622
|
-
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
623
|
-
var templatePath = path2.resolve(__dirname, "../template");
|
|
624
|
-
var DEFAULT_VALUES = {
|
|
625
|
-
git: !process.env.CI,
|
|
626
|
-
install: true,
|
|
627
|
-
start: true,
|
|
628
|
-
dryRun: false,
|
|
629
|
-
force: false,
|
|
630
|
-
packageManager: "npm",
|
|
631
|
-
provider: "skip"
|
|
632
|
-
};
|
|
633
|
-
function readFlag(flags, flag) {
|
|
634
|
-
let value = flags[flag];
|
|
635
|
-
if (flags.defaults) {
|
|
636
|
-
value ??= DEFAULT_VALUES[flag];
|
|
637
|
-
}
|
|
638
|
-
return value;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
708
|
// src/commands/create/generate-hosting-config.ts
|
|
642
709
|
async function generateHostingConfig(dest, flags) {
|
|
643
710
|
let provider = readFlag(flags, "provider");
|
|
644
711
|
if (provider === void 0) {
|
|
645
|
-
provider = await
|
|
712
|
+
provider = await prompts3.select({
|
|
646
713
|
message: "Select hosting providers for automatic configuration:",
|
|
647
714
|
options: [
|
|
648
715
|
{ value: "Vercel", label: "Vercel" },
|
|
@@ -657,13 +724,13 @@ async function generateHostingConfig(dest, flags) {
|
|
|
657
724
|
provider = "skip";
|
|
658
725
|
}
|
|
659
726
|
if (!provider || provider === "skip") {
|
|
660
|
-
|
|
661
|
-
`${
|
|
727
|
+
prompts3.log.message(
|
|
728
|
+
`${chalk4.blue("hosting provider config [skip]")} You can configure hosting provider settings manually later.`
|
|
662
729
|
);
|
|
663
730
|
return provider;
|
|
664
731
|
}
|
|
665
|
-
|
|
666
|
-
const resolvedDest =
|
|
732
|
+
prompts3.log.info(`${chalk4.blue("Hosting Configuration")} Setting up configuration for ${provider}`);
|
|
733
|
+
const resolvedDest = path4.resolve(dest);
|
|
667
734
|
if (!fs3.existsSync(resolvedDest)) {
|
|
668
735
|
fs3.mkdirSync(resolvedDest, { recursive: true });
|
|
669
736
|
}
|
|
@@ -692,7 +759,7 @@ async function generateHostingConfig(dest, flags) {
|
|
|
692
759
|
dryRun: flags.dryRun,
|
|
693
760
|
dryRunMessage: `${warnLabel("DRY RUN")} Skipped hosting provider config creation`,
|
|
694
761
|
task: async () => {
|
|
695
|
-
const filepath =
|
|
762
|
+
const filepath = path4.join(resolvedDest, filename);
|
|
696
763
|
fs3.writeFileSync(filepath, config);
|
|
697
764
|
return `Added ${filepath}`;
|
|
698
765
|
}
|
|
@@ -703,9 +770,9 @@ async function generateHostingConfig(dest, flags) {
|
|
|
703
770
|
|
|
704
771
|
// src/commands/create/git.ts
|
|
705
772
|
import fs4 from "node:fs";
|
|
706
|
-
import
|
|
707
|
-
import * as
|
|
708
|
-
import
|
|
773
|
+
import path5 from "node:path";
|
|
774
|
+
import * as prompts4 from "@clack/prompts";
|
|
775
|
+
import chalk5 from "chalk";
|
|
709
776
|
|
|
710
777
|
// src/utils/shell.ts
|
|
711
778
|
import { spawn } from "node:child_process";
|
|
@@ -751,7 +818,7 @@ async function runShellCommand(command, flags, opts = {}) {
|
|
|
751
818
|
async function initGitRepo(cwd, flags) {
|
|
752
819
|
let shouldInitGitRepo = readFlag(flags, "git");
|
|
753
820
|
if (shouldInitGitRepo === void 0) {
|
|
754
|
-
const answer = await
|
|
821
|
+
const answer = await prompts4.confirm({
|
|
755
822
|
message: "Initialize a new git repository?",
|
|
756
823
|
initialValue: DEFAULT_VALUES.git
|
|
757
824
|
});
|
|
@@ -769,12 +836,12 @@ async function initGitRepo(cwd, flags) {
|
|
|
769
836
|
}
|
|
770
837
|
});
|
|
771
838
|
} else {
|
|
772
|
-
|
|
839
|
+
prompts4.log.message(`${chalk5.blue("git [skip]")} You can always run ${chalk5.yellow("git init")} manually.`);
|
|
773
840
|
}
|
|
774
841
|
}
|
|
775
842
|
async function _initGitRepo(cwd) {
|
|
776
|
-
if (fs4.existsSync(
|
|
777
|
-
return `${
|
|
843
|
+
if (fs4.existsSync(path5.join(cwd, ".git"))) {
|
|
844
|
+
return `${chalk5.cyan("Nice!")} Git has already been initialized`;
|
|
778
845
|
}
|
|
779
846
|
try {
|
|
780
847
|
await runShellCommand("git", ["init"], { cwd, stdio: "ignore" });
|
|
@@ -793,42 +860,11 @@ async function _initGitRepo(cwd) {
|
|
|
793
860
|
}
|
|
794
861
|
}
|
|
795
862
|
|
|
796
|
-
// src/commands/create/install-start.ts
|
|
797
|
-
import * as prompts4 from "@clack/prompts";
|
|
798
|
-
async function installAndStart(flags) {
|
|
799
|
-
const installDeps = readFlag(flags, "install");
|
|
800
|
-
const startProject2 = readFlag(flags, "start");
|
|
801
|
-
if (installDeps === false) {
|
|
802
|
-
return { install: false, start: false };
|
|
803
|
-
}
|
|
804
|
-
if (startProject2) {
|
|
805
|
-
return { install: true, start: true };
|
|
806
|
-
}
|
|
807
|
-
if (installDeps) {
|
|
808
|
-
if (startProject2 === false) {
|
|
809
|
-
return { install: true, start: false };
|
|
810
|
-
} else {
|
|
811
|
-
const answer2 = await prompts4.confirm({
|
|
812
|
-
message: "Start project?",
|
|
813
|
-
initialValue: DEFAULT_VALUES.install
|
|
814
|
-
});
|
|
815
|
-
assertNotCanceled(answer2);
|
|
816
|
-
return { install: true, start: answer2 };
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
const answer = await prompts4.confirm({
|
|
820
|
-
message: "Install dependencies and start project?",
|
|
821
|
-
initialValue: DEFAULT_VALUES.install
|
|
822
|
-
});
|
|
823
|
-
assertNotCanceled(answer);
|
|
824
|
-
return { install: answer, start: answer };
|
|
825
|
-
}
|
|
826
|
-
|
|
827
863
|
// src/commands/create/package-manager.ts
|
|
828
864
|
import fs5 from "node:fs";
|
|
829
|
-
import
|
|
865
|
+
import path6 from "node:path";
|
|
830
866
|
import * as prompts5 from "@clack/prompts";
|
|
831
|
-
import
|
|
867
|
+
import chalk6 from "chalk";
|
|
832
868
|
import { lookpath } from "lookpath";
|
|
833
869
|
var LOCK_FILES = /* @__PURE__ */ new Map([
|
|
834
870
|
["npm", "package-lock.json"],
|
|
@@ -839,7 +875,7 @@ async function selectPackageManager(cwd, flags) {
|
|
|
839
875
|
const packageManager = await resolvePackageManager(flags);
|
|
840
876
|
for (const [pkgManager, lockFile] of LOCK_FILES) {
|
|
841
877
|
if (pkgManager !== packageManager) {
|
|
842
|
-
fs5.rmSync(
|
|
878
|
+
fs5.rmSync(path6.join(cwd, lockFile), { force: true });
|
|
843
879
|
}
|
|
844
880
|
}
|
|
845
881
|
return packageManager;
|
|
@@ -850,7 +886,7 @@ async function resolvePackageManager(flags) {
|
|
|
850
886
|
return flags.packageManager;
|
|
851
887
|
}
|
|
852
888
|
prompts5.log.warn(
|
|
853
|
-
`The specified package manager '${
|
|
889
|
+
`The specified package manager '${chalk6.yellow(flags.packageManager)}' doesn't seem to be installed!`
|
|
854
890
|
);
|
|
855
891
|
}
|
|
856
892
|
if (flags.defaults) {
|
|
@@ -893,7 +929,7 @@ async function getInstalledPackageManagers() {
|
|
|
893
929
|
// src/commands/create/template.ts
|
|
894
930
|
import fs6 from "node:fs";
|
|
895
931
|
import fsPromises from "node:fs/promises";
|
|
896
|
-
import
|
|
932
|
+
import path7 from "node:path";
|
|
897
933
|
import * as prompts6 from "@clack/prompts";
|
|
898
934
|
import ignore from "ignore";
|
|
899
935
|
async function copyTemplate(dest, flags) {
|
|
@@ -911,9 +947,9 @@ async function copyTemplate(dest, flags) {
|
|
|
911
947
|
toCopy.push(file);
|
|
912
948
|
}
|
|
913
949
|
for (const fileName of toCopy) {
|
|
914
|
-
const sourceFilePath =
|
|
950
|
+
const sourceFilePath = path7.join(templatePath, fileName);
|
|
915
951
|
const destFileName = fileName === ".npmignore" ? ".gitignore" : fileName;
|
|
916
|
-
const destFilePath =
|
|
952
|
+
const destFilePath = path7.join(dest, destFileName);
|
|
917
953
|
const stats = await fsPromises.stat(sourceFilePath);
|
|
918
954
|
if (stats.isDirectory()) {
|
|
919
955
|
await fsPromises.cp(sourceFilePath, destFilePath, { recursive: true });
|
|
@@ -924,9 +960,9 @@ async function copyTemplate(dest, flags) {
|
|
|
924
960
|
}
|
|
925
961
|
function readIgnoreFile() {
|
|
926
962
|
try {
|
|
927
|
-
return fs6.readFileSync(
|
|
963
|
+
return fs6.readFileSync(path7.resolve(templatePath, ".npmignore"), "utf8");
|
|
928
964
|
} catch {
|
|
929
|
-
return fs6.readFileSync(
|
|
965
|
+
return fs6.readFileSync(path7.resolve(templatePath, ".gitignore"), "utf8");
|
|
930
966
|
}
|
|
931
967
|
}
|
|
932
968
|
|
|
@@ -940,25 +976,23 @@ async function createTutorial(flags) {
|
|
|
940
976
|
tables: {
|
|
941
977
|
Options: [
|
|
942
978
|
["--dir, -d", "The folder in which the tutorial gets created"],
|
|
943
|
-
["--
|
|
944
|
-
["--start, --no-start", `Start project (default ${chalk6.yellow(DEFAULT_VALUES.start)})`],
|
|
945
|
-
["--git, --no-git", `Initialize a local git repository (default ${chalk6.yellow(DEFAULT_VALUES.git)})`],
|
|
979
|
+
["--git, --no-git", `Initialize a local git repository (default ${chalk7.yellow(DEFAULT_VALUES.git)})`],
|
|
946
980
|
[
|
|
947
981
|
"--provider <name>, --no-provider",
|
|
948
|
-
`Select a hosting provider (default ${
|
|
982
|
+
`Select a hosting provider (default ${chalk7.yellow(DEFAULT_VALUES.provider)})`
|
|
949
983
|
],
|
|
950
|
-
["--dry-run", `Walk through steps without executing (default ${
|
|
984
|
+
["--dry-run", `Walk through steps without executing (default ${chalk7.yellow(DEFAULT_VALUES.dryRun)})`],
|
|
951
985
|
[
|
|
952
986
|
"--package-manager <name>, -p <name>",
|
|
953
|
-
`The package used to install dependencies (default ${
|
|
987
|
+
`The package used to install dependencies (default ${chalk7.yellow(DEFAULT_VALUES.packageManager)})`
|
|
954
988
|
],
|
|
955
989
|
[
|
|
956
990
|
"--enterprise <origin>, -e <origin>",
|
|
957
|
-
`The origin of your StackBlitz Enterprise instance (if not provided authentication is not turned on and your project will use ${
|
|
991
|
+
`The origin of your StackBlitz Enterprise instance (if not provided authentication is not turned on and your project will use ${chalk7.yellow("https://stackblitz.com")})`
|
|
958
992
|
],
|
|
959
993
|
[
|
|
960
994
|
"--force",
|
|
961
|
-
`Overwrite existing files in the target directory without prompting (default ${
|
|
995
|
+
`Overwrite existing files in the target directory without prompting (default ${chalk7.yellow(DEFAULT_VALUES.force)})`
|
|
962
996
|
],
|
|
963
997
|
["--defaults", "Skip all prompts and initialize the tutorial using the defaults"]
|
|
964
998
|
]
|
|
@@ -967,12 +1001,6 @@ async function createTutorial(flags) {
|
|
|
967
1001
|
return 0;
|
|
968
1002
|
}
|
|
969
1003
|
applyAliases(flags);
|
|
970
|
-
try {
|
|
971
|
-
verifyFlags(flags);
|
|
972
|
-
} catch (error) {
|
|
973
|
-
console.error(`${errorLabel()} ${error.message}`);
|
|
974
|
-
process.exit(1);
|
|
975
|
-
}
|
|
976
1004
|
try {
|
|
977
1005
|
return _createTutorial(flags);
|
|
978
1006
|
} catch (error) {
|
|
@@ -1006,10 +1034,10 @@ async function _createTutorial(flags) {
|
|
|
1006
1034
|
tutorialName = answer;
|
|
1007
1035
|
}
|
|
1008
1036
|
}
|
|
1009
|
-
prompts7.log.info(`We'll call your tutorial ${
|
|
1037
|
+
prompts7.log.info(`We'll call your tutorial ${chalk7.blue(tutorialName)}`);
|
|
1010
1038
|
const dest = await getTutorialDirectory(tutorialName, flags);
|
|
1011
|
-
const resolvedDest =
|
|
1012
|
-
prompts7.log.info(`Scaffolding tutorial in ${
|
|
1039
|
+
const resolvedDest = path8.resolve(process.cwd(), dest);
|
|
1040
|
+
prompts7.log.info(`Scaffolding tutorial in ${chalk7.blue(resolvedDest)}`);
|
|
1013
1041
|
if (fs7.existsSync(resolvedDest) && !flags.force) {
|
|
1014
1042
|
if (flags.defaults) {
|
|
1015
1043
|
console.error(`
|
|
@@ -1044,32 +1072,11 @@ ${errorLabel()} Failed to create tutorial. Directory already exists.`);
|
|
|
1044
1072
|
updateReadme(resolvedDest, selectedPackageManager, flags);
|
|
1045
1073
|
await setupEnterpriseConfig(resolvedDest, flags);
|
|
1046
1074
|
await initGitRepo(resolvedDest, flags);
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
message = "Please wait while we install the dependencies...";
|
|
1053
|
-
printNextSteps(dest, selectedPackageManager, true);
|
|
1054
|
-
}
|
|
1055
|
-
prompts7.outro(message);
|
|
1056
|
-
await startProject(resolvedDest, selectedPackageManager, flags, start);
|
|
1057
|
-
} else {
|
|
1058
|
-
printNextSteps(dest, selectedPackageManager, false);
|
|
1059
|
-
prompts7.outro(`You're all set!`);
|
|
1060
|
-
console.log("Until next time \u{1F44B}");
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
async function startProject(cwd, packageManager, flags, startProject2) {
|
|
1064
|
-
if (flags.dryRun) {
|
|
1065
|
-
const message = startProject2 ? "Skipped dependency installation and project start" : "Skipped dependency installation";
|
|
1066
|
-
console.warn(`${warnLabel("DRY RUN")} ${message}`);
|
|
1067
|
-
} else {
|
|
1068
|
-
await execa(packageManager, ["install"], { cwd, stdio: "inherit" });
|
|
1069
|
-
if (startProject2) {
|
|
1070
|
-
await execa(packageManager, ["run", "dev"], { cwd, stdio: "inherit" });
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1075
|
+
prompts7.log.success(chalk7.green("Tutorial successfully created!"));
|
|
1076
|
+
await promptGemfileEditing(dest, flags);
|
|
1077
|
+
printRubyNextSteps(dest);
|
|
1078
|
+
prompts7.outro(`You're all set!`);
|
|
1079
|
+
console.log("Until next time \u{1F44B}");
|
|
1073
1080
|
}
|
|
1074
1081
|
async function getTutorialDirectory(tutorialName, flags) {
|
|
1075
1082
|
const dir = flags.dir;
|
|
@@ -1084,7 +1091,7 @@ async function getTutorialDirectory(tutorialName, flags) {
|
|
|
1084
1091
|
initialValue: `./${tutorialName}`,
|
|
1085
1092
|
placeholder: "./",
|
|
1086
1093
|
validate(value) {
|
|
1087
|
-
if (!
|
|
1094
|
+
if (!path8.isAbsolute(value) && !value.startsWith("./")) {
|
|
1088
1095
|
return "Please provide an absolute or relative path!";
|
|
1089
1096
|
}
|
|
1090
1097
|
return void 0;
|
|
@@ -1093,28 +1100,11 @@ async function getTutorialDirectory(tutorialName, flags) {
|
|
|
1093
1100
|
assertNotCanceled(promptResult);
|
|
1094
1101
|
return promptResult;
|
|
1095
1102
|
}
|
|
1096
|
-
function printNextSteps(dest, packageManager, dependenciesInstalled) {
|
|
1097
|
-
let i = 0;
|
|
1098
|
-
prompts7.log.message(chalk6.bold.underline("Next Steps"));
|
|
1099
|
-
const steps = [
|
|
1100
|
-
[`cd ${dest}`, "Navigate to project"],
|
|
1101
|
-
[`${packageManager} install`, "Install dependencies", !dependenciesInstalled],
|
|
1102
|
-
[`${packageManager} run dev`, "Start development server"],
|
|
1103
|
-
[, `Head over to ${chalk6.underline("http://localhost:4321")}`]
|
|
1104
|
-
];
|
|
1105
|
-
for (const [command, text2, render] of steps) {
|
|
1106
|
-
if (render === false) {
|
|
1107
|
-
continue;
|
|
1108
|
-
}
|
|
1109
|
-
i++;
|
|
1110
|
-
prompts7.log.step(`${i}. ${command ? `${chalk6.blue(command)} - ` : ""}${text2}`);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
1103
|
function updatePackageJson(dest, projectName, flags, provider) {
|
|
1114
1104
|
if (flags.dryRun) {
|
|
1115
1105
|
return;
|
|
1116
1106
|
}
|
|
1117
|
-
const pkgPath =
|
|
1107
|
+
const pkgPath = path8.resolve(dest, "package.json");
|
|
1118
1108
|
const pkgJson = JSON.parse(fs7.readFileSync(pkgPath, "utf8"));
|
|
1119
1109
|
pkgJson.name = projectName;
|
|
1120
1110
|
updateWorkspaceVersions(pkgJson.dependencies, TUTORIALKIT_VERSION);
|
|
@@ -1125,7 +1115,7 @@ function updatePackageJson(dest, projectName, flags, provider) {
|
|
|
1125
1115
|
}
|
|
1126
1116
|
fs7.writeFileSync(pkgPath, JSON.stringify(pkgJson, null, 2));
|
|
1127
1117
|
try {
|
|
1128
|
-
const pkgLockPath =
|
|
1118
|
+
const pkgLockPath = path8.resolve(dest, "package-lock.json");
|
|
1129
1119
|
const pkgLockJson = JSON.parse(fs7.readFileSync(pkgLockPath, "utf8"));
|
|
1130
1120
|
const defaultPackage = pkgLockJson.packages[""];
|
|
1131
1121
|
pkgLockJson.name = projectName;
|
|
@@ -1140,7 +1130,7 @@ function updateReadme(dest, packageManager, flags) {
|
|
|
1140
1130
|
if (flags.dryRun) {
|
|
1141
1131
|
return;
|
|
1142
1132
|
}
|
|
1143
|
-
const readmePath =
|
|
1133
|
+
const readmePath = path8.resolve(dest, "README.md");
|
|
1144
1134
|
let readme = fs7.readFileSync(readmePath, "utf8");
|
|
1145
1135
|
readme = readme.replaceAll("<% pkgManager %>", packageManager ?? DEFAULT_VALUES.packageManager);
|
|
1146
1136
|
fs7.writeFileSync(readmePath, readme);
|
|
@@ -1160,17 +1150,12 @@ function applyAliases(flags) {
|
|
|
1160
1150
|
flags.enterprise = flags.e;
|
|
1161
1151
|
}
|
|
1162
1152
|
}
|
|
1163
|
-
function verifyFlags(flags) {
|
|
1164
|
-
if (flags.install === false && flags.start) {
|
|
1165
|
-
throw new Error("Cannot start project without installing dependencies.");
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
1153
|
|
|
1169
1154
|
// src/commands/eject/index.ts
|
|
1170
1155
|
import fs8 from "node:fs";
|
|
1171
|
-
import
|
|
1156
|
+
import path9 from "node:path";
|
|
1172
1157
|
import * as prompts8 from "@clack/prompts";
|
|
1173
|
-
import
|
|
1158
|
+
import chalk8 from "chalk";
|
|
1174
1159
|
import detectIndent from "detect-indent";
|
|
1175
1160
|
import { execa as execa2 } from "execa";
|
|
1176
1161
|
import whichpm from "which-pm";
|
|
@@ -1201,7 +1186,7 @@ function ejectRoutes(flags) {
|
|
|
1201
1186
|
Options: [
|
|
1202
1187
|
[
|
|
1203
1188
|
"--force",
|
|
1204
|
-
`Overwrite existing files in the target directory without prompting (default ${
|
|
1189
|
+
`Overwrite existing files in the target directory without prompting (default ${chalk8.yellow(DEFAULT_VALUES2.force)})`
|
|
1205
1190
|
],
|
|
1206
1191
|
["--defaults", "Skip all the prompts and eject the routes using the defaults"]
|
|
1207
1192
|
]
|
|
@@ -1225,7 +1210,7 @@ async function _eject(flags) {
|
|
|
1225
1210
|
if (folderPath === void 0) {
|
|
1226
1211
|
folderPath = process.cwd();
|
|
1227
1212
|
} else {
|
|
1228
|
-
folderPath =
|
|
1213
|
+
folderPath = path9.resolve(process.cwd(), folderPath);
|
|
1229
1214
|
}
|
|
1230
1215
|
const { astroConfigPath, srcPath, pkgJsonPath, astroIntegrationPath, srcDestPath } = validateDestination(
|
|
1231
1216
|
folderPath,
|
|
@@ -1239,7 +1224,7 @@ async function _eject(flags) {
|
|
|
1239
1224
|
const indent = detectIndent(pkgJsonContent).indent || " ";
|
|
1240
1225
|
const pkgJson = JSON.parse(pkgJsonContent);
|
|
1241
1226
|
const astroIntegrationPkgJson = JSON.parse(
|
|
1242
|
-
fs8.readFileSync(
|
|
1227
|
+
fs8.readFileSync(path9.join(astroIntegrationPath, "package.json"), "utf-8")
|
|
1243
1228
|
);
|
|
1244
1229
|
const newDependencies = [];
|
|
1245
1230
|
for (const dep of REQUIRED_DEPENDENCIES) {
|
|
@@ -1260,9 +1245,9 @@ async function _eject(flags) {
|
|
|
1260
1245
|
`New dependencies added: ${newDependencies.join(", ")}. Install the new dependencies before proceeding.`
|
|
1261
1246
|
);
|
|
1262
1247
|
if (!flags.defaults) {
|
|
1263
|
-
const packageManager = (await whichpm(
|
|
1248
|
+
const packageManager = (await whichpm(path9.dirname(pkgJsonPath))).name;
|
|
1264
1249
|
const answer = await prompts8.confirm({
|
|
1265
|
-
message: `Do you want to install those dependencies now using ${
|
|
1250
|
+
message: `Do you want to install those dependencies now using ${chalk8.blue(packageManager)}?`
|
|
1266
1251
|
});
|
|
1267
1252
|
if (answer === true) {
|
|
1268
1253
|
await execa2(packageManager, ["install"], { cwd: folderPath, stdio: "inherit" });
|
|
@@ -1273,17 +1258,17 @@ async function _eject(flags) {
|
|
|
1273
1258
|
}
|
|
1274
1259
|
function validateDestination(folder, force) {
|
|
1275
1260
|
assertExists(folder);
|
|
1276
|
-
const pkgJsonPath = assertExists(
|
|
1277
|
-
const astroConfigPath = assertExists(
|
|
1278
|
-
const srcDestPath = assertExists(
|
|
1279
|
-
const astroIntegrationPath = assertExists(
|
|
1280
|
-
const srcPath =
|
|
1261
|
+
const pkgJsonPath = assertExists(path9.join(folder, "package.json"));
|
|
1262
|
+
const astroConfigPath = assertExists(path9.join(folder, "astro.config.ts"));
|
|
1263
|
+
const srcDestPath = assertExists(path9.join(folder, "src"));
|
|
1264
|
+
const astroIntegrationPath = assertExists(path9.resolve(folder, "node_modules", "@tutorialkit-rb", "astro"));
|
|
1265
|
+
const srcPath = path9.join(astroIntegrationPath, "dist", "default");
|
|
1281
1266
|
if (!force) {
|
|
1282
1267
|
walk(srcPath, (relativePath) => {
|
|
1283
|
-
const destination =
|
|
1268
|
+
const destination = path9.join(srcDestPath, relativePath);
|
|
1284
1269
|
if (fs8.existsSync(destination)) {
|
|
1285
1270
|
throw new Error(
|
|
1286
|
-
`Eject aborted because '${destination}' would be overwritten by this command. Use ${
|
|
1271
|
+
`Eject aborted because '${destination}' would be overwritten by this command. Use ${chalk8.yellow("--force")} to ignore this error.`
|
|
1287
1272
|
);
|
|
1288
1273
|
}
|
|
1289
1274
|
});
|
|
@@ -1305,9 +1290,9 @@ function assertExists(filePath) {
|
|
|
1305
1290
|
function walk(root, visit2) {
|
|
1306
1291
|
function traverse2(folder, pathPrefix) {
|
|
1307
1292
|
for (const filename of fs8.readdirSync(folder)) {
|
|
1308
|
-
const filePath =
|
|
1293
|
+
const filePath = path9.join(folder, filename);
|
|
1309
1294
|
const stat = fs8.statSync(filePath);
|
|
1310
|
-
const relativeFilePath =
|
|
1295
|
+
const relativeFilePath = path9.join(pathPrefix, filename);
|
|
1311
1296
|
if (stat.isDirectory()) {
|
|
1312
1297
|
traverse2(filePath, relativeFilePath);
|
|
1313
1298
|
} else {
|
|
@@ -1336,13 +1321,13 @@ async function cli() {
|
|
|
1336
1321
|
async function runCommand(cmd, flags) {
|
|
1337
1322
|
switch (cmd) {
|
|
1338
1323
|
case "version": {
|
|
1339
|
-
console.log(`${primaryLabel(package_default.name)} ${
|
|
1324
|
+
console.log(`${primaryLabel(package_default.name)} ${chalk9.green(`v${package_default.version}`)}`);
|
|
1340
1325
|
return;
|
|
1341
1326
|
}
|
|
1342
1327
|
case "help": {
|
|
1343
1328
|
printHelp({
|
|
1344
1329
|
commandName: package_default.name,
|
|
1345
|
-
prolog: `${primaryLabel(package_default.name)} ${
|
|
1330
|
+
prolog: `${primaryLabel(package_default.name)} ${chalk9.green(`v${package_default.version}`)} Create tutorial apps powered by WebContainer API`,
|
|
1346
1331
|
usage: ["[command] [...options]", "[ -h | --help | -v | --version ]"],
|
|
1347
1332
|
tables: {
|
|
1348
1333
|
Commands: [
|
|
@@ -1364,7 +1349,7 @@ async function runCommand(cmd, flags) {
|
|
|
1364
1349
|
return ejectRoutes(flags);
|
|
1365
1350
|
}
|
|
1366
1351
|
default: {
|
|
1367
|
-
console.error(`${errorLabel()} Unknown command ${
|
|
1352
|
+
console.error(`${errorLabel()} Unknown command ${chalk9.red(cmd)}`);
|
|
1368
1353
|
return 1;
|
|
1369
1354
|
}
|
|
1370
1355
|
}
|
package/package.json
CHANGED
package/template/.gitignore
CHANGED
package/template/bin/build-wasm
CHANGED
|
@@ -24,7 +24,17 @@ echo "Building WASM module..."
|
|
|
24
24
|
echo "WASM build completed successfully!"
|
|
25
25
|
echo "ruby.wasm is now available at ruby-wasm/dist/ruby.wasm"
|
|
26
26
|
|
|
27
|
+
# Generate hash of Gemfile.lock for cache versioning
|
|
28
|
+
echo "Generating Gemfile.lock hash..."
|
|
29
|
+
GEMFILE_HASH=$(sha256sum Gemfile.lock | cut -c1-16)
|
|
30
|
+
echo "Gemfile.lock hash: $GEMFILE_HASH"
|
|
31
|
+
|
|
27
32
|
# Copy the built ruby.wasm to the public directory
|
|
28
33
|
echo "Copying ruby.wasm to public directory..."
|
|
29
34
|
cp dist/ruby.wasm ../public/
|
|
30
35
|
echo "ruby.wasm copied to public directory."
|
|
36
|
+
|
|
37
|
+
# Create ruby.wasm.hash with the hash
|
|
38
|
+
echo "Creating ruby.wasm.hash..."
|
|
39
|
+
echo "$GEMFILE_HASH" > ../public/ruby.wasm.hash
|
|
40
|
+
echo "ruby.wasm.hash created with hash: $GEMFILE_HASH"
|
package/template/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"@codemirror/lang-yaml": "^6.1.2",
|
|
16
16
|
"@codemirror/legacy-modes": "^6.5.1",
|
|
17
17
|
"@nanostores/react": "0.7.2",
|
|
18
|
-
"@tutorialkit-rb/react": "1.5.2-rb.0.1.
|
|
18
|
+
"@tutorialkit-rb/react": "1.5.2-rb.0.1.1",
|
|
19
19
|
"nanostores": "^0.10.3",
|
|
20
20
|
"react": "^18.3.1",
|
|
21
21
|
"react-dom": "^18.3.1"
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@astrojs/check": "^0.7.0",
|
|
25
25
|
"@astrojs/react": "^3.6.0",
|
|
26
|
-
"@tutorialkit-rb/astro": "1.5.2-rb.0.1.
|
|
27
|
-
"@tutorialkit-rb/theme": "1.5.2-rb.0.1.
|
|
28
|
-
"@tutorialkit-rb/types": "1.5.2-rb.0.1.
|
|
26
|
+
"@tutorialkit-rb/astro": "1.5.2-rb.0.1.1",
|
|
27
|
+
"@tutorialkit-rb/theme": "1.5.2-rb.0.1.1",
|
|
28
|
+
"@tutorialkit-rb/types": "1.5.2-rb.0.1.1",
|
|
29
29
|
"@types/mdast": "^4.0.4",
|
|
30
30
|
"@types/node": "^20.14.6",
|
|
31
31
|
"@types/react": "^18.3.3",
|
|
@@ -5,7 +5,7 @@ import { webcontainer } from 'tutorialkit:core';
|
|
|
5
5
|
import tutorialStore from 'tutorialkit:store';
|
|
6
6
|
|
|
7
7
|
const VERSIONED_WASM_URL = `/ruby.wasm`;
|
|
8
|
-
const
|
|
8
|
+
const GEMFILE_HASH_URL = `/ruby.wasm.hash`;
|
|
9
9
|
const WC_WASM_LOG_PATH = `/ruby.wasm.log.txt`;
|
|
10
10
|
const WC_WASM_PATH = `/ruby.wasm`;
|
|
11
11
|
|
|
@@ -15,6 +15,31 @@ export function FileManager() {
|
|
|
15
15
|
const processedFiles = useRef(new Set<string>());
|
|
16
16
|
const wasmCached = useRef(false);
|
|
17
17
|
|
|
18
|
+
async function fetchGemfileHash(): Promise<string> {
|
|
19
|
+
try {
|
|
20
|
+
console.log(`Fetching Gemfile hash from ${GEMFILE_HASH_URL}...`);
|
|
21
|
+
|
|
22
|
+
const response = await fetch(GEMFILE_HASH_URL);
|
|
23
|
+
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
console.warn(`Failed to fetch ruby.wasm.hash: ${response.status}`);
|
|
26
|
+
return 'default';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const hash = (await response.text()).trim();
|
|
30
|
+
console.log(`Fetched Gemfile hash: ${hash}`);
|
|
31
|
+
|
|
32
|
+
return hash;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn('Failed to fetch Gemfile hash, using default version:', error);
|
|
35
|
+
return 'default';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getVersionedCacheFileName(gemfileLockHash: string): string {
|
|
40
|
+
return `ruby-${gemfileLockHash}.wasm`;
|
|
41
|
+
}
|
|
42
|
+
|
|
18
43
|
async function chmodx(wc: WebContainer, path: string) {
|
|
19
44
|
const process = await wc.spawn('chmod', ['+x', path]);
|
|
20
45
|
|
|
@@ -27,12 +52,12 @@ export function FileManager() {
|
|
|
27
52
|
}
|
|
28
53
|
}
|
|
29
54
|
|
|
30
|
-
async function fetchCachedWasmFile(): Promise<Uint8Array | null> {
|
|
55
|
+
async function fetchCachedWasmFile(cacheFileName: string): Promise<Uint8Array | null> {
|
|
31
56
|
try {
|
|
32
57
|
const opfsRoot = await navigator.storage.getDirectory();
|
|
33
|
-
const fileHandle = await opfsRoot.getFileHandle(
|
|
58
|
+
const fileHandle = await opfsRoot.getFileHandle(cacheFileName);
|
|
34
59
|
const file = await fileHandle.getFile();
|
|
35
|
-
console.log(`Found cached Ruby WASM: ${
|
|
60
|
+
console.log(`Found cached Ruby WASM: ${cacheFileName}`);
|
|
36
61
|
|
|
37
62
|
return new Uint8Array(await file.arrayBuffer());
|
|
38
63
|
} catch {
|
|
@@ -40,20 +65,38 @@ export function FileManager() {
|
|
|
40
65
|
}
|
|
41
66
|
}
|
|
42
67
|
|
|
43
|
-
async function persistWasmFile(wasmData: Uint8Array): Promise<void> {
|
|
68
|
+
async function persistWasmFile(wasmData: Uint8Array, cacheFileName: string): Promise<void> {
|
|
44
69
|
try {
|
|
45
70
|
const opfsRoot = await navigator.storage.getDirectory();
|
|
46
|
-
const fileHandle = await opfsRoot.getFileHandle(
|
|
71
|
+
const fileHandle = await opfsRoot.getFileHandle(cacheFileName, { create: true });
|
|
47
72
|
const writable = await fileHandle.createWritable();
|
|
48
73
|
await writable.write(wasmData);
|
|
49
74
|
await writable.close();
|
|
50
|
-
console.log(`Ruby WASM file ${
|
|
75
|
+
console.log(`Ruby WASM file ${cacheFileName} cached`);
|
|
51
76
|
} catch (error) {
|
|
52
77
|
console.error('Failed to persist Ruby WASM:', error);
|
|
53
78
|
}
|
|
54
79
|
}
|
|
55
80
|
|
|
56
|
-
async function
|
|
81
|
+
async function cleanupOldCacheFiles(currentCacheFileName: string): Promise<void> {
|
|
82
|
+
try {
|
|
83
|
+
const opfsRoot = await navigator.storage.getDirectory();
|
|
84
|
+
|
|
85
|
+
for await (const [name] of opfsRoot.entries()) {
|
|
86
|
+
if (
|
|
87
|
+
((name.startsWith('ruby-') && name.endsWith('.wasm')) || name === 'ruby.wasm') &&
|
|
88
|
+
name !== currentCacheFileName
|
|
89
|
+
) {
|
|
90
|
+
console.log(`Removing old cached Ruby WASM: ${name}`);
|
|
91
|
+
await opfsRoot.removeEntry(name);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.warn('Failed to cleanup old cache files:', error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function cacheWasmFile(wc: WebContainer, cacheFileName: string): Promise<void> {
|
|
57
100
|
console.log(`Dowloading WASM file ${VERSIONED_WASM_URL}...`);
|
|
58
101
|
|
|
59
102
|
try {
|
|
@@ -61,10 +104,11 @@ export function FileManager() {
|
|
|
61
104
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: downloaded');
|
|
62
105
|
|
|
63
106
|
const wasmData = new Uint8Array(await wasm.arrayBuffer());
|
|
64
|
-
await persistWasmFile(wasmData);
|
|
107
|
+
await persistWasmFile(wasmData, cacheFileName);
|
|
108
|
+
await cleanupOldCacheFiles(cacheFileName);
|
|
65
109
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: cached');
|
|
66
110
|
await wc.fs.writeFile(WC_WASM_PATH, wasmData);
|
|
67
|
-
} catch
|
|
111
|
+
} catch {
|
|
68
112
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: error');
|
|
69
113
|
}
|
|
70
114
|
}
|
|
@@ -93,18 +137,23 @@ export function FileManager() {
|
|
|
93
137
|
if (!wasmCached.current) {
|
|
94
138
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: init');
|
|
95
139
|
|
|
96
|
-
const
|
|
140
|
+
const gemfileLockHash = await fetchGemfileHash();
|
|
141
|
+
const cacheFileName = getVersionedCacheFileName(gemfileLockHash);
|
|
142
|
+
console.log(`Using cache file: ${cacheFileName} (hash: ${gemfileLockHash})`);
|
|
143
|
+
|
|
144
|
+
const cachedWasm = await fetchCachedWasmFile(cacheFileName);
|
|
97
145
|
|
|
98
146
|
if (cachedWasm) {
|
|
99
147
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: load from cache');
|
|
100
148
|
await wc.fs.writeFile(WC_WASM_PATH, cachedWasm);
|
|
101
149
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: done');
|
|
102
|
-
console.log(`Ruby WASM ${
|
|
150
|
+
console.log(`Ruby WASM ${cacheFileName} loaded from cache`);
|
|
103
151
|
wasmCached.current = true;
|
|
104
152
|
} else {
|
|
105
153
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: download');
|
|
106
|
-
await cacheWasmFile(wc);
|
|
154
|
+
await cacheWasmFile(wc, cacheFileName);
|
|
107
155
|
await wc.fs.writeFile(WC_WASM_LOG_PATH, 'status: done');
|
|
156
|
+
wasmCached.current = true;
|
|
108
157
|
}
|
|
109
158
|
}
|
|
110
159
|
})();
|