jsrepo 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +144 -87
- package/package.json +2 -1
- package/src/commands/build.ts +5 -1
- package/src/utils/build.ts +18 -3
- package/src/utils/language-support.ts +70 -12
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import color7 from "chalk";
|
|
|
12
12
|
import { Command, program as program2 } from "commander";
|
|
13
13
|
import { resolveCommand as resolveCommand2 } from "package-manager-detector/commands";
|
|
14
14
|
import { detect } from "package-manager-detector/detect";
|
|
15
|
-
import * as
|
|
15
|
+
import * as v5 from "valibot";
|
|
16
16
|
|
|
17
17
|
// src/utils/ascii.ts
|
|
18
18
|
import color from "chalk";
|
|
@@ -680,19 +680,20 @@ var mapToArray = (map, fn) => {
|
|
|
680
680
|
|
|
681
681
|
// src/utils/git-providers.ts
|
|
682
682
|
import { Octokit } from "octokit";
|
|
683
|
-
import * as
|
|
683
|
+
import * as v3 from "valibot";
|
|
684
684
|
|
|
685
685
|
// src/utils/build.ts
|
|
686
686
|
import fs3 from "node:fs";
|
|
687
687
|
import path3 from "node:path";
|
|
688
688
|
import color3 from "chalk";
|
|
689
689
|
import { program } from "commander";
|
|
690
|
-
import * as
|
|
690
|
+
import * as v2 from "valibot";
|
|
691
691
|
|
|
692
692
|
// src/utils/language-support.ts
|
|
693
693
|
import fs2 from "node:fs";
|
|
694
694
|
import { builtinModules } from "node:module";
|
|
695
695
|
import path2 from "node:path";
|
|
696
|
+
import * as v from "@vue/compiler-sfc";
|
|
696
697
|
import color2 from "chalk";
|
|
697
698
|
import { walk } from "estree-walker";
|
|
698
699
|
import * as sv from "svelte/compiler";
|
|
@@ -726,7 +727,7 @@ var parsePackageName = (input) => {
|
|
|
726
727
|
// src/utils/language-support.ts
|
|
727
728
|
var typescript = {
|
|
728
729
|
matches: (fileName) => fileName.endsWith(".ts") || fileName.endsWith(".js") || fileName.endsWith(".tsx") || fileName.endsWith(".jsx"),
|
|
729
|
-
resolveDependencies: (filePath, category, isSubDir) => {
|
|
730
|
+
resolveDependencies: ({ filePath, category, isSubDir, excludeDeps }) => {
|
|
730
731
|
const project = new Project();
|
|
731
732
|
const blockFile = project.addSourceFileAtPath(filePath);
|
|
732
733
|
const imports = blockFile.getImportDeclarations();
|
|
@@ -740,7 +741,11 @@ var typescript = {
|
|
|
740
741
|
if (localDep) localDeps.add(localDep);
|
|
741
742
|
}
|
|
742
743
|
const deps = imports.filter((declaration) => !declaration.getModuleSpecifierValue().startsWith(".")).map((declaration) => declaration.getModuleSpecifierValue());
|
|
743
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(
|
|
744
|
+
const { devDependencies, dependencies } = resolveRemoteDeps(
|
|
745
|
+
Array.from(deps),
|
|
746
|
+
filePath,
|
|
747
|
+
excludeDeps
|
|
748
|
+
);
|
|
744
749
|
return Ok({
|
|
745
750
|
local: Array.from(localDeps),
|
|
746
751
|
dependencies,
|
|
@@ -753,7 +758,7 @@ ${content}
|
|
|
753
758
|
};
|
|
754
759
|
var svelte = {
|
|
755
760
|
matches: (fileName) => fileName.endsWith(".svelte"),
|
|
756
|
-
resolveDependencies: (filePath, category, isSubDir) => {
|
|
761
|
+
resolveDependencies: ({ filePath, category, isSubDir, excludeDeps }) => {
|
|
757
762
|
const sourceCode = fs2.readFileSync(filePath).toString();
|
|
758
763
|
const root = sv.parse(sourceCode, { modern: true });
|
|
759
764
|
if (!root.instance) return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
@@ -777,7 +782,44 @@ var svelte = {
|
|
|
777
782
|
}
|
|
778
783
|
}
|
|
779
784
|
});
|
|
780
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath
|
|
785
|
+
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath, [
|
|
786
|
+
"svelte",
|
|
787
|
+
...excludeDeps
|
|
788
|
+
]);
|
|
789
|
+
return Ok({
|
|
790
|
+
dependencies,
|
|
791
|
+
devDependencies,
|
|
792
|
+
local: Array.from(localDeps)
|
|
793
|
+
});
|
|
794
|
+
},
|
|
795
|
+
comment: (content) => `<!--
|
|
796
|
+
${content}
|
|
797
|
+
-->`
|
|
798
|
+
};
|
|
799
|
+
var vue = {
|
|
800
|
+
matches: (fileName) => fileName.endsWith(".vue"),
|
|
801
|
+
resolveDependencies: ({ filePath, category, isSubDir, excludeDeps }) => {
|
|
802
|
+
const sourceCode = fs2.readFileSync(filePath).toString();
|
|
803
|
+
const parsed = v.parse(sourceCode);
|
|
804
|
+
if (!parsed.descriptor.script?.content && !parsed.descriptor.scriptSetup?.content)
|
|
805
|
+
return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
806
|
+
const localDeps = /* @__PURE__ */ new Set();
|
|
807
|
+
const deps = /* @__PURE__ */ new Set();
|
|
808
|
+
const compiled = v.compileScript(parsed.descriptor, { id: "shut-it" });
|
|
809
|
+
if (!compiled.imports) return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
810
|
+
const imports = Object.values(compiled.imports);
|
|
811
|
+
for (const imp of imports) {
|
|
812
|
+
if (imp.source.startsWith(".")) {
|
|
813
|
+
const localDep = resolveLocalImport(imp.source, category, isSubDir);
|
|
814
|
+
if (localDep) localDeps.add(localDep);
|
|
815
|
+
} else {
|
|
816
|
+
deps.add(imp.source);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath, [
|
|
820
|
+
"vue",
|
|
821
|
+
...excludeDeps
|
|
822
|
+
]);
|
|
781
823
|
return Ok({
|
|
782
824
|
dependencies,
|
|
783
825
|
devDependencies,
|
|
@@ -797,10 +839,11 @@ var resolveLocalImport = (mod, category, isSubDir) => {
|
|
|
797
839
|
return `${category}/${path2.parse(path2.basename(mod)).name}`;
|
|
798
840
|
}
|
|
799
841
|
const segments = mod.replaceAll("../", "").split("/");
|
|
800
|
-
if (segments.length
|
|
842
|
+
if (segments.length < 2) return void 0;
|
|
801
843
|
return `${segments[0]}/${segments[1]}`;
|
|
802
844
|
};
|
|
803
|
-
var resolveRemoteDeps = (deps, filePath) => {
|
|
845
|
+
var resolveRemoteDeps = (deps, filePath, doNotInstall = []) => {
|
|
846
|
+
const exemptDeps = new Set(doNotInstall);
|
|
804
847
|
const filteredDeps = deps.filter(
|
|
805
848
|
(dep) => !builtinModules.includes(dep) && !dep.startsWith("node:")
|
|
806
849
|
);
|
|
@@ -824,6 +867,7 @@ var resolveRemoteDeps = (deps, filePath) => {
|
|
|
824
867
|
);
|
|
825
868
|
continue;
|
|
826
869
|
}
|
|
870
|
+
if (exemptDeps.has(depInfo.name)) continue;
|
|
827
871
|
let version2 = void 0;
|
|
828
872
|
if (packageDependencies !== void 0) {
|
|
829
873
|
version2 = packageDependencies[depInfo.name];
|
|
@@ -847,28 +891,28 @@ var resolveRemoteDeps = (deps, filePath) => {
|
|
|
847
891
|
devDependencies: Array.from(devDependencies)
|
|
848
892
|
};
|
|
849
893
|
};
|
|
850
|
-
var languages = [typescript, svelte];
|
|
894
|
+
var languages = [typescript, svelte, vue];
|
|
851
895
|
|
|
852
896
|
// src/utils/build.ts
|
|
853
|
-
var blockSchema =
|
|
854
|
-
name:
|
|
855
|
-
category:
|
|
856
|
-
localDependencies:
|
|
857
|
-
dependencies:
|
|
858
|
-
devDependencies:
|
|
859
|
-
tests:
|
|
897
|
+
var blockSchema = v2.object({
|
|
898
|
+
name: v2.string(),
|
|
899
|
+
category: v2.string(),
|
|
900
|
+
localDependencies: v2.array(v2.string()),
|
|
901
|
+
dependencies: v2.array(v2.string()),
|
|
902
|
+
devDependencies: v2.array(v2.string()),
|
|
903
|
+
tests: v2.boolean(),
|
|
860
904
|
/** Where to find the block relative to root */
|
|
861
|
-
directory:
|
|
862
|
-
subdirectory:
|
|
863
|
-
files:
|
|
905
|
+
directory: v2.string(),
|
|
906
|
+
subdirectory: v2.boolean(),
|
|
907
|
+
files: v2.array(v2.string())
|
|
864
908
|
});
|
|
865
|
-
var categorySchema =
|
|
866
|
-
name:
|
|
867
|
-
blocks:
|
|
909
|
+
var categorySchema = v2.object({
|
|
910
|
+
name: v2.string(),
|
|
911
|
+
blocks: v2.array(blockSchema)
|
|
868
912
|
});
|
|
869
913
|
var TEST_SUFFIXES = [".test.ts", "_test.ts", ".test.js", "_test.js"];
|
|
870
914
|
var isTestFile = (file) => TEST_SUFFIXES.find((suffix) => file.endsWith(suffix)) !== void 0;
|
|
871
|
-
var buildBlocksDirectory = (blocksPath, cwd) => {
|
|
915
|
+
var buildBlocksDirectory = (blocksPath, { cwd, excludeDeps }) => {
|
|
872
916
|
let paths;
|
|
873
917
|
try {
|
|
874
918
|
paths = fs3.readdirSync(blocksPath);
|
|
@@ -902,7 +946,12 @@ var buildBlocksDirectory = (blocksPath, cwd) => {
|
|
|
902
946
|
const testsPath = files.find(
|
|
903
947
|
(f) => TEST_SUFFIXES.find((suffix) => f === `${name2}${suffix}`)
|
|
904
948
|
);
|
|
905
|
-
const { dependencies, devDependencies, local } = lang.resolveDependencies(
|
|
949
|
+
const { dependencies, devDependencies, local } = lang.resolveDependencies({
|
|
950
|
+
filePath: blockDir,
|
|
951
|
+
category: categoryName,
|
|
952
|
+
isSubDir: false,
|
|
953
|
+
excludeDeps
|
|
954
|
+
}).match(
|
|
906
955
|
(val) => val,
|
|
907
956
|
(err) => {
|
|
908
957
|
program.error(color3.red(err));
|
|
@@ -941,7 +990,12 @@ var buildBlocksDirectory = (blocksPath, cwd) => {
|
|
|
941
990
|
);
|
|
942
991
|
continue;
|
|
943
992
|
}
|
|
944
|
-
const { local, dependencies, devDependencies } = lang.resolveDependencies(
|
|
993
|
+
const { local, dependencies, devDependencies } = lang.resolveDependencies({
|
|
994
|
+
filePath: path3.join(blockDir, f),
|
|
995
|
+
category: categoryName,
|
|
996
|
+
isSubDir: true,
|
|
997
|
+
excludeDeps
|
|
998
|
+
}).match(
|
|
945
999
|
(val) => val,
|
|
946
1000
|
(err) => {
|
|
947
1001
|
program.error(color3.red(err));
|
|
@@ -1049,7 +1103,7 @@ var getManifest = async (url) => {
|
|
|
1049
1103
|
if (!response.ok) {
|
|
1050
1104
|
return errorMessage(`${response.status} ${response.text}`);
|
|
1051
1105
|
}
|
|
1052
|
-
const categories =
|
|
1106
|
+
const categories = v3.parse(v3.array(categorySchema), await response.json());
|
|
1053
1107
|
return Ok(categories);
|
|
1054
1108
|
} catch (err) {
|
|
1055
1109
|
return errorMessage(`${err}`);
|
|
@@ -1147,20 +1201,20 @@ var getInstalled = (blocks, config, cwd) => {
|
|
|
1147
1201
|
// src/utils/config.ts
|
|
1148
1202
|
import fs5 from "node:fs";
|
|
1149
1203
|
import path5 from "node:path";
|
|
1150
|
-
import * as
|
|
1204
|
+
import * as v4 from "valibot";
|
|
1151
1205
|
var CONFIG_NAME = "jsrepo.json";
|
|
1152
|
-
var schema =
|
|
1153
|
-
$schema:
|
|
1154
|
-
repos:
|
|
1155
|
-
includeTests:
|
|
1156
|
-
path:
|
|
1157
|
-
watermark:
|
|
1206
|
+
var schema = v4.object({
|
|
1207
|
+
$schema: v4.string(),
|
|
1208
|
+
repos: v4.optional(v4.array(v4.string()), []),
|
|
1209
|
+
includeTests: v4.boolean(),
|
|
1210
|
+
path: v4.pipe(v4.string(), v4.minLength(1)),
|
|
1211
|
+
watermark: v4.optional(v4.boolean(), true)
|
|
1158
1212
|
});
|
|
1159
1213
|
var getConfig = (cwd) => {
|
|
1160
1214
|
if (!fs5.existsSync(path5.join(cwd, CONFIG_NAME))) {
|
|
1161
1215
|
return Err("Could not find your configuration file! Please run `init`.");
|
|
1162
1216
|
}
|
|
1163
|
-
const config =
|
|
1217
|
+
const config = v4.safeParse(
|
|
1164
1218
|
schema,
|
|
1165
1219
|
JSON.parse(fs5.readFileSync(path5.join(cwd, CONFIG_NAME)).toString())
|
|
1166
1220
|
);
|
|
@@ -1281,18 +1335,18 @@ var nextSteps = (steps) => {
|
|
|
1281
1335
|
var _intro = (version2) => intro(`${color6.bgHex("#f7df1e").black(" jsrepo ")}${color6.gray(` v${version2} `)}`);
|
|
1282
1336
|
|
|
1283
1337
|
// src/commands/add.ts
|
|
1284
|
-
var schema2 =
|
|
1285
|
-
repo:
|
|
1286
|
-
allow:
|
|
1287
|
-
yes:
|
|
1288
|
-
verbose:
|
|
1289
|
-
cwd:
|
|
1338
|
+
var schema2 = v5.object({
|
|
1339
|
+
repo: v5.optional(v5.string()),
|
|
1340
|
+
allow: v5.boolean(),
|
|
1341
|
+
yes: v5.boolean(),
|
|
1342
|
+
verbose: v5.boolean(),
|
|
1343
|
+
cwd: v5.string()
|
|
1290
1344
|
});
|
|
1291
1345
|
var add = new Command("add").argument(
|
|
1292
1346
|
"[blocks...]",
|
|
1293
1347
|
"Names of the blocks you want to add to your project. ex: (utils/math, github/ieedan/std/utils/math)"
|
|
1294
1348
|
).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("-y, --yes", "Skip confirmation prompt.", false).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (blockNames, opts) => {
|
|
1295
|
-
const options =
|
|
1349
|
+
const options = v5.parse(schema2, opts);
|
|
1296
1350
|
_intro(context.package.version);
|
|
1297
1351
|
await _add(blockNames, options);
|
|
1298
1352
|
outro(color7.green("All done!"));
|
|
@@ -1572,15 +1626,16 @@ import path7 from "node:path";
|
|
|
1572
1626
|
import { outro as outro2, spinner as spinner3 } from "@clack/prompts";
|
|
1573
1627
|
import color8 from "chalk";
|
|
1574
1628
|
import { Command as Command2 } from "commander";
|
|
1575
|
-
import * as
|
|
1576
|
-
var schema3 =
|
|
1577
|
-
dirs:
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1629
|
+
import * as v6 from "valibot";
|
|
1630
|
+
var schema3 = v6.object({
|
|
1631
|
+
dirs: v6.array(v6.string()),
|
|
1632
|
+
excludeDeps: v6.array(v6.string()),
|
|
1633
|
+
output: v6.boolean(),
|
|
1634
|
+
verbose: v6.boolean(),
|
|
1635
|
+
cwd: v6.string()
|
|
1581
1636
|
});
|
|
1582
|
-
var build = new Command2("build").description(`Builds the provided --dirs in the project root into a \`${OUTPUT_FILE}\` file.`).option("--dirs [dirs...]", "The directories containing the blocks.", ["./blocks"]).option("--no-output", `Do not output a \`${OUTPUT_FILE}\` file.`).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
1583
|
-
const options =
|
|
1637
|
+
var build = new Command2("build").description(`Builds the provided --dirs in the project root into a \`${OUTPUT_FILE}\` file.`).option("--dirs [dirs...]", "The directories containing the blocks.", ["./blocks"]).option("--exclude-deps [deps...]", "Dependencies that should not be added.", []).option("--no-output", `Do not output a \`${OUTPUT_FILE}\` file.`).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
1638
|
+
const options = v6.parse(schema3, opts);
|
|
1584
1639
|
_intro(context.package.version);
|
|
1585
1640
|
await _build(options);
|
|
1586
1641
|
outro2(color8.green("All done!"));
|
|
@@ -1593,7 +1648,9 @@ var _build = async (options) => {
|
|
|
1593
1648
|
const dirPath = path7.join(options.cwd, dir);
|
|
1594
1649
|
loading.start(`Building ${color8.cyan(dirPath)}`);
|
|
1595
1650
|
if (options.output && fs7.existsSync(outFile)) fs7.rmSync(outFile);
|
|
1596
|
-
categories.push(
|
|
1651
|
+
categories.push(
|
|
1652
|
+
...buildBlocksDirectory(dirPath, { cwd: options.cwd, excludeDeps: options.excludeDeps })
|
|
1653
|
+
);
|
|
1597
1654
|
loading.stop(`Built ${color8.cyan(dirPath)}`);
|
|
1598
1655
|
}
|
|
1599
1656
|
const categoriesMap = /* @__PURE__ */ new Map();
|
|
@@ -1620,7 +1677,7 @@ import { cancel as cancel2, confirm as confirm2, isCancel as isCancel2, outro as
|
|
|
1620
1677
|
import color10 from "chalk";
|
|
1621
1678
|
import { Command as Command3, program as program3 } from "commander";
|
|
1622
1679
|
import { diffLines } from "diff";
|
|
1623
|
-
import * as
|
|
1680
|
+
import * as v7 from "valibot";
|
|
1624
1681
|
|
|
1625
1682
|
// src/utils/diff.ts
|
|
1626
1683
|
import color9 from "chalk";
|
|
@@ -1814,12 +1871,12 @@ var formatDiff = ({
|
|
|
1814
1871
|
};
|
|
1815
1872
|
|
|
1816
1873
|
// src/commands/diff.ts
|
|
1817
|
-
var schema4 =
|
|
1818
|
-
expand:
|
|
1819
|
-
maxUnchanged:
|
|
1820
|
-
repo:
|
|
1821
|
-
allow:
|
|
1822
|
-
cwd:
|
|
1874
|
+
var schema4 = v7.object({
|
|
1875
|
+
expand: v7.boolean(),
|
|
1876
|
+
maxUnchanged: v7.number(),
|
|
1877
|
+
repo: v7.optional(v7.string()),
|
|
1878
|
+
allow: v7.boolean(),
|
|
1879
|
+
cwd: v7.string()
|
|
1823
1880
|
});
|
|
1824
1881
|
var diff = new Command3("diff").description("Compares local blocks to the blocks in the provided repository.").option("-E, --expand", "Expands the diff so you see everything.", false).option(
|
|
1825
1882
|
"--max-unchanged <number>",
|
|
@@ -1828,7 +1885,7 @@ var diff = new Command3("diff").description("Compares local blocks to the blocks
|
|
|
1828
1885
|
// this is such a dumb api thing
|
|
1829
1886
|
3
|
|
1830
1887
|
).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
1831
|
-
const options =
|
|
1888
|
+
const options = v7.parse(schema4, opts);
|
|
1832
1889
|
_intro(context.package.version);
|
|
1833
1890
|
await _diff(options);
|
|
1834
1891
|
outro3(color10.green("All done!"));
|
|
@@ -1949,19 +2006,19 @@ import path9 from "node:path";
|
|
|
1949
2006
|
import { cancel as cancel3, confirm as confirm3, isCancel as isCancel3, outro as outro4, spinner as spinner5, text } from "@clack/prompts";
|
|
1950
2007
|
import color11 from "chalk";
|
|
1951
2008
|
import { Command as Command4 } from "commander";
|
|
1952
|
-
import * as
|
|
1953
|
-
var schema5 =
|
|
1954
|
-
path:
|
|
1955
|
-
repos:
|
|
1956
|
-
watermark:
|
|
1957
|
-
tests:
|
|
1958
|
-
cwd:
|
|
2009
|
+
import * as v8 from "valibot";
|
|
2010
|
+
var schema5 = v8.object({
|
|
2011
|
+
path: v8.optional(v8.string()),
|
|
2012
|
+
repos: v8.optional(v8.array(v8.string())),
|
|
2013
|
+
watermark: v8.boolean(),
|
|
2014
|
+
tests: v8.optional(v8.boolean()),
|
|
2015
|
+
cwd: v8.string()
|
|
1959
2016
|
});
|
|
1960
2017
|
var init = new Command4("init").description("Initializes your project with a configuration file.").option("--path <path>", "Path to install the blocks.").option("--repos [repos...]", "Repository to install the blocks from.").option(
|
|
1961
2018
|
"--no-watermark",
|
|
1962
2019
|
"Will not add a watermark to each file upon adding it to your project."
|
|
1963
2020
|
).option("--tests", "Will include tests with the blocks.").option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
1964
|
-
const options =
|
|
2021
|
+
const options = v8.parse(schema5, opts);
|
|
1965
2022
|
_intro(context.package.version);
|
|
1966
2023
|
await _init(options);
|
|
1967
2024
|
outro4(color11.green("All done!"));
|
|
@@ -2039,16 +2096,16 @@ import { execa as execa2 } from "execa";
|
|
|
2039
2096
|
import { resolveCommand as resolveCommand3 } from "package-manager-detector/commands";
|
|
2040
2097
|
import { detect as detect2 } from "package-manager-detector/detect";
|
|
2041
2098
|
import { Project as Project2 } from "ts-morph";
|
|
2042
|
-
import * as
|
|
2043
|
-
var schema6 =
|
|
2044
|
-
repo:
|
|
2045
|
-
allow:
|
|
2046
|
-
debug:
|
|
2047
|
-
verbose:
|
|
2048
|
-
cwd:
|
|
2099
|
+
import * as v9 from "valibot";
|
|
2100
|
+
var schema6 = v9.object({
|
|
2101
|
+
repo: v9.optional(v9.string()),
|
|
2102
|
+
allow: v9.boolean(),
|
|
2103
|
+
debug: v9.boolean(),
|
|
2104
|
+
verbose: v9.boolean(),
|
|
2105
|
+
cwd: v9.string()
|
|
2049
2106
|
});
|
|
2050
2107
|
var test = new Command5("test").description("Tests local blocks against most recent remote tests.").addArgument(new Argument("[blocks...]", "The blocks you want to test.").default([])).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("--debug", "Leaves the temp test file around for debugging upon failure.", false).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (blockNames, opts) => {
|
|
2051
|
-
const options =
|
|
2108
|
+
const options = v9.parse(schema6, opts);
|
|
2052
2109
|
_intro(context.package.version);
|
|
2053
2110
|
await _test(blockNames, options);
|
|
2054
2111
|
outro5(color12.green("All done!"));
|
|
@@ -2098,7 +2155,7 @@ var _test = async (blockNames, options) => {
|
|
|
2098
2155
|
)
|
|
2099
2156
|
);
|
|
2100
2157
|
}
|
|
2101
|
-
const categories =
|
|
2158
|
+
const categories = v9.parse(v9.array(categorySchema), await response.json());
|
|
2102
2159
|
for (const category of categories) {
|
|
2103
2160
|
for (const block of category.blocks) {
|
|
2104
2161
|
blocksMap.set(
|
|
@@ -2294,16 +2351,16 @@ import { Command as Command6, program as program5 } from "commander";
|
|
|
2294
2351
|
import { diffLines as diffLines2 } from "diff";
|
|
2295
2352
|
import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
|
|
2296
2353
|
import { detect as detect3 } from "package-manager-detector/detect";
|
|
2297
|
-
import * as
|
|
2298
|
-
var schema7 =
|
|
2299
|
-
all:
|
|
2300
|
-
expand:
|
|
2301
|
-
maxUnchanged:
|
|
2302
|
-
repo:
|
|
2303
|
-
allow:
|
|
2304
|
-
yes:
|
|
2305
|
-
verbose:
|
|
2306
|
-
cwd:
|
|
2354
|
+
import * as v10 from "valibot";
|
|
2355
|
+
var schema7 = v10.object({
|
|
2356
|
+
all: v10.boolean(),
|
|
2357
|
+
expand: v10.boolean(),
|
|
2358
|
+
maxUnchanged: v10.number(),
|
|
2359
|
+
repo: v10.optional(v10.string()),
|
|
2360
|
+
allow: v10.boolean(),
|
|
2361
|
+
yes: v10.boolean(),
|
|
2362
|
+
verbose: v10.boolean(),
|
|
2363
|
+
cwd: v10.string()
|
|
2307
2364
|
});
|
|
2308
2365
|
var update = new Command6("update").argument("[blocks...]", "Names of the blocks you want to update. ex: (utils/math)").option("--all", "Update all installed components.", false).option("-E, --expand", "Expands the diff so you see everything.", false).option(
|
|
2309
2366
|
"--max-unchanged <number>",
|
|
@@ -2312,7 +2369,7 @@ var update = new Command6("update").argument("[blocks...]", "Names of the blocks
|
|
|
2312
2369
|
// this is such a dumb api thing
|
|
2313
2370
|
3
|
|
2314
2371
|
).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("-y, --yes", "Skip confirmation prompt.", false).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (blockNames, opts) => {
|
|
2315
|
-
const options =
|
|
2372
|
+
const options = v10.parse(schema7, opts);
|
|
2316
2373
|
_intro(context.package.version);
|
|
2317
2374
|
await _update(blockNames, options);
|
|
2318
2375
|
outro6(color13.green("All done!"));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsrepo",
|
|
3
3
|
"description": "A CLI to add shared code from remote repositories.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/ieedan/jsrepo"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@clack/prompts": "^0.8.1",
|
|
42
|
+
"@vue/compiler-sfc": "^3.5.13",
|
|
42
43
|
"ansi-regex": "^6.1.0",
|
|
43
44
|
"chalk": "^5.3.0",
|
|
44
45
|
"commander": "^12.1.0",
|
package/src/commands/build.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { intro } from '../utils/prompts';
|
|
|
11
11
|
|
|
12
12
|
const schema = v.object({
|
|
13
13
|
dirs: v.array(v.string()),
|
|
14
|
+
excludeDeps: v.array(v.string()),
|
|
14
15
|
output: v.boolean(),
|
|
15
16
|
verbose: v.boolean(),
|
|
16
17
|
cwd: v.string(),
|
|
@@ -21,6 +22,7 @@ type Options = v.InferInput<typeof schema>;
|
|
|
21
22
|
const build = new Command('build')
|
|
22
23
|
.description(`Builds the provided --dirs in the project root into a \`${OUTPUT_FILE}\` file.`)
|
|
23
24
|
.option('--dirs [dirs...]', 'The directories containing the blocks.', ['./blocks'])
|
|
25
|
+
.option('--exclude-deps [deps...]', 'Dependencies that should not be added.', [])
|
|
24
26
|
.option('--no-output', `Do not output a \`${OUTPUT_FILE}\` file.`)
|
|
25
27
|
.option('--verbose', 'Include debug logs.', false)
|
|
26
28
|
.option('--cwd <path>', 'The current working directory.', process.cwd())
|
|
@@ -48,7 +50,9 @@ const _build = async (options: Options) => {
|
|
|
48
50
|
|
|
49
51
|
if (options.output && fs.existsSync(outFile)) fs.rmSync(outFile);
|
|
50
52
|
|
|
51
|
-
categories.push(
|
|
53
|
+
categories.push(
|
|
54
|
+
...buildBlocksDirectory(dirPath, { cwd: options.cwd, excludeDeps: options.excludeDeps })
|
|
55
|
+
);
|
|
52
56
|
|
|
53
57
|
loading.stop(`Built ${color.cyan(dirPath)}`);
|
|
54
58
|
}
|
package/src/utils/build.ts
CHANGED
|
@@ -33,12 +33,17 @@ const TEST_SUFFIXES = ['.test.ts', '_test.ts', '.test.js', '_test.js'] as const;
|
|
|
33
33
|
const isTestFile = (file: string): boolean =>
|
|
34
34
|
TEST_SUFFIXES.find((suffix) => file.endsWith(suffix)) !== undefined;
|
|
35
35
|
|
|
36
|
+
type Options = {
|
|
37
|
+
cwd: string;
|
|
38
|
+
excludeDeps: string[];
|
|
39
|
+
};
|
|
40
|
+
|
|
36
41
|
/** Using the provided path to the blocks folder builds the blocks into categories and also resolves dependencies
|
|
37
42
|
*
|
|
38
43
|
* @param blocksPath
|
|
39
44
|
* @returns
|
|
40
45
|
*/
|
|
41
|
-
const buildBlocksDirectory = (blocksPath: string, cwd:
|
|
46
|
+
const buildBlocksDirectory = (blocksPath: string, { cwd, excludeDeps }: Options): Category[] => {
|
|
42
47
|
let paths: string[];
|
|
43
48
|
|
|
44
49
|
try {
|
|
@@ -88,7 +93,12 @@ const buildBlocksDirectory = (blocksPath: string, cwd: string): Category[] => {
|
|
|
88
93
|
);
|
|
89
94
|
|
|
90
95
|
const { dependencies, devDependencies, local } = lang
|
|
91
|
-
.resolveDependencies(
|
|
96
|
+
.resolveDependencies({
|
|
97
|
+
filePath: blockDir,
|
|
98
|
+
category: categoryName,
|
|
99
|
+
isSubDir: false,
|
|
100
|
+
excludeDeps,
|
|
101
|
+
})
|
|
92
102
|
.match(
|
|
93
103
|
(val) => val,
|
|
94
104
|
(err) => {
|
|
@@ -140,7 +150,12 @@ const buildBlocksDirectory = (blocksPath: string, cwd: string): Category[] => {
|
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
const { local, dependencies, devDependencies } = lang
|
|
143
|
-
.resolveDependencies(
|
|
153
|
+
.resolveDependencies({
|
|
154
|
+
filePath: path.join(blockDir, f),
|
|
155
|
+
category: categoryName,
|
|
156
|
+
isSubDir: true,
|
|
157
|
+
excludeDeps,
|
|
158
|
+
})
|
|
144
159
|
.match(
|
|
145
160
|
(val) => val,
|
|
146
161
|
(err) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { builtinModules } from 'node:module';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import * as v from '@vue/compiler-sfc';
|
|
4
5
|
import color from 'chalk';
|
|
5
6
|
import { walk } from 'estree-walker';
|
|
6
7
|
import * as sv from 'svelte/compiler';
|
|
@@ -17,15 +18,18 @@ export type ResolvedDependencies = {
|
|
|
17
18
|
dependencies: string[];
|
|
18
19
|
};
|
|
19
20
|
|
|
21
|
+
export type ResolveDependencyOptions = {
|
|
22
|
+
filePath: string;
|
|
23
|
+
category: string;
|
|
24
|
+
isSubDir: boolean;
|
|
25
|
+
excludeDeps: string[];
|
|
26
|
+
};
|
|
27
|
+
|
|
20
28
|
export type Lang = {
|
|
21
29
|
/** Matches the supported file types */
|
|
22
30
|
matches: (fileName: string) => boolean;
|
|
23
31
|
/** Reads the file and gets any dependencies from its imports */
|
|
24
|
-
resolveDependencies: (
|
|
25
|
-
filePath: string,
|
|
26
|
-
category: string,
|
|
27
|
-
isSubDir: boolean
|
|
28
|
-
) => Result<ResolvedDependencies, string>;
|
|
32
|
+
resolveDependencies: (opts: ResolveDependencyOptions) => Result<ResolvedDependencies, string>;
|
|
29
33
|
/** Returns a multiline comment containing the content */
|
|
30
34
|
comment: (content: string) => string;
|
|
31
35
|
};
|
|
@@ -36,7 +40,7 @@ const typescript: Lang = {
|
|
|
36
40
|
fileName.endsWith('.js') ||
|
|
37
41
|
fileName.endsWith('.tsx') ||
|
|
38
42
|
fileName.endsWith('.jsx'),
|
|
39
|
-
resolveDependencies: (filePath, category, isSubDir) => {
|
|
43
|
+
resolveDependencies: ({ filePath, category, isSubDir, excludeDeps }) => {
|
|
40
44
|
const project = new Project();
|
|
41
45
|
|
|
42
46
|
const blockFile = project.addSourceFileAtPath(filePath);
|
|
@@ -61,7 +65,11 @@ const typescript: Lang = {
|
|
|
61
65
|
.filter((declaration) => !declaration.getModuleSpecifierValue().startsWith('.'))
|
|
62
66
|
.map((declaration) => declaration.getModuleSpecifierValue());
|
|
63
67
|
|
|
64
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(
|
|
68
|
+
const { devDependencies, dependencies } = resolveRemoteDeps(
|
|
69
|
+
Array.from(deps),
|
|
70
|
+
filePath,
|
|
71
|
+
excludeDeps
|
|
72
|
+
);
|
|
65
73
|
|
|
66
74
|
return Ok({
|
|
67
75
|
local: Array.from(localDeps),
|
|
@@ -74,7 +82,7 @@ const typescript: Lang = {
|
|
|
74
82
|
|
|
75
83
|
const svelte: Lang = {
|
|
76
84
|
matches: (fileName) => fileName.endsWith('.svelte'),
|
|
77
|
-
resolveDependencies: (filePath, category, isSubDir) => {
|
|
85
|
+
resolveDependencies: ({ filePath, category, isSubDir, excludeDeps }) => {
|
|
78
86
|
const sourceCode = fs.readFileSync(filePath).toString();
|
|
79
87
|
|
|
80
88
|
const root = sv.parse(sourceCode, { modern: true });
|
|
@@ -106,7 +114,53 @@ const svelte: Lang = {
|
|
|
106
114
|
},
|
|
107
115
|
});
|
|
108
116
|
|
|
109
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath
|
|
117
|
+
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath, [
|
|
118
|
+
'svelte',
|
|
119
|
+
...excludeDeps,
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
return Ok({
|
|
123
|
+
dependencies,
|
|
124
|
+
devDependencies,
|
|
125
|
+
local: Array.from(localDeps),
|
|
126
|
+
} satisfies ResolvedDependencies);
|
|
127
|
+
},
|
|
128
|
+
comment: (content) => `<!--\n${content}\n-->`,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const vue: Lang = {
|
|
132
|
+
matches: (fileName) => fileName.endsWith('.vue'),
|
|
133
|
+
resolveDependencies: ({ filePath, category, isSubDir, excludeDeps }) => {
|
|
134
|
+
const sourceCode = fs.readFileSync(filePath).toString();
|
|
135
|
+
|
|
136
|
+
const parsed = v.parse(sourceCode);
|
|
137
|
+
|
|
138
|
+
if (!parsed.descriptor.script?.content && !parsed.descriptor.scriptSetup?.content)
|
|
139
|
+
return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
140
|
+
|
|
141
|
+
const localDeps = new Set<string>();
|
|
142
|
+
const deps = new Set<string>();
|
|
143
|
+
|
|
144
|
+
const compiled = v.compileScript(parsed.descriptor, { id: 'shut-it' }); // you need this id to remove a warning
|
|
145
|
+
|
|
146
|
+
if (!compiled.imports) return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
147
|
+
|
|
148
|
+
const imports = Object.values(compiled.imports);
|
|
149
|
+
|
|
150
|
+
for (const imp of imports) {
|
|
151
|
+
if (imp.source.startsWith('.')) {
|
|
152
|
+
const localDep = resolveLocalImport(imp.source, category, isSubDir);
|
|
153
|
+
|
|
154
|
+
if (localDep) localDeps.add(localDep);
|
|
155
|
+
} else {
|
|
156
|
+
deps.add(imp.source);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath, [
|
|
161
|
+
'vue',
|
|
162
|
+
...excludeDeps,
|
|
163
|
+
]);
|
|
110
164
|
|
|
111
165
|
return Ok({
|
|
112
166
|
dependencies,
|
|
@@ -136,7 +190,7 @@ const resolveLocalImport = (
|
|
|
136
190
|
const segments = mod.replaceAll('../', '').split('/');
|
|
137
191
|
|
|
138
192
|
// invalid path
|
|
139
|
-
if (segments.length
|
|
193
|
+
if (segments.length < 2) return undefined;
|
|
140
194
|
|
|
141
195
|
return `${segments[0]}/${segments[1]}`;
|
|
142
196
|
};
|
|
@@ -148,7 +202,9 @@ const resolveLocalImport = (
|
|
|
148
202
|
* @param filePath
|
|
149
203
|
* @returns
|
|
150
204
|
*/
|
|
151
|
-
const resolveRemoteDeps = (deps: string[], filePath: string) => {
|
|
205
|
+
const resolveRemoteDeps = (deps: string[], filePath: string, doNotInstall: string[] = []) => {
|
|
206
|
+
const exemptDeps = new Set(doNotInstall);
|
|
207
|
+
|
|
152
208
|
const filteredDeps = deps.filter(
|
|
153
209
|
(dep) => !builtinModules.includes(dep) && !dep.startsWith('node:')
|
|
154
210
|
);
|
|
@@ -181,6 +237,8 @@ const resolveRemoteDeps = (deps: string[], filePath: string) => {
|
|
|
181
237
|
continue;
|
|
182
238
|
}
|
|
183
239
|
|
|
240
|
+
if (exemptDeps.has(depInfo.name)) continue;
|
|
241
|
+
|
|
184
242
|
let version: string | undefined = undefined;
|
|
185
243
|
if (packageDependencies !== undefined) {
|
|
186
244
|
version = packageDependencies[depInfo.name];
|
|
@@ -211,6 +269,6 @@ const resolveRemoteDeps = (deps: string[], filePath: string) => {
|
|
|
211
269
|
};
|
|
212
270
|
};
|
|
213
271
|
|
|
214
|
-
const languages: Lang[] = [typescript, svelte];
|
|
272
|
+
const languages: Lang[] = [typescript, svelte, vue];
|
|
215
273
|
|
|
216
274
|
export { typescript, languages };
|