jsrepo 1.3.1 → 1.4.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 +163 -107
- package/package.json +3 -1
- package/src/commands/add.ts +1 -1
- package/src/commands/build.ts +6 -2
- package/src/commands/diff.ts +6 -10
- package/src/commands/init.ts +1 -1
- package/src/commands/test.ts +1 -1
- package/src/commands/update.ts +6 -8
- package/src/index.ts +1 -1
- package/src/utils/blocks.ts +1 -1
- package/src/utils/build.ts +19 -4
- package/src/utils/config.ts +1 -1
- package/src/utils/language-support.ts +71 -13
- package/src/utils/package.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import fs12 from "node:fs";
|
|
3
|
-
import path12 from "node:path";
|
|
4
3
|
import { fileURLToPath } from "node:url";
|
|
5
4
|
import { program as program6 } from "commander";
|
|
5
|
+
import path12 from "pathe";
|
|
6
6
|
|
|
7
7
|
// src/commands/add.ts
|
|
8
8
|
import fs6 from "node:fs";
|
|
9
|
-
import path6 from "node:path";
|
|
10
9
|
import { cancel, confirm, isCancel, multiselect, outro, spinner as spinner2 } from "@clack/prompts";
|
|
11
10
|
import color7 from "chalk";
|
|
12
11
|
import { Command, program as program2 } from "commander";
|
|
13
12
|
import { resolveCommand as resolveCommand2 } from "package-manager-detector/commands";
|
|
14
13
|
import { detect } from "package-manager-detector/detect";
|
|
15
|
-
import
|
|
14
|
+
import path6 from "pathe";
|
|
15
|
+
import * as v5 from "valibot";
|
|
16
16
|
|
|
17
17
|
// src/utils/ascii.ts
|
|
18
18
|
import color from "chalk";
|
|
@@ -28,8 +28,8 @@ var INFO = color.bgBlueBright.white("INFO");
|
|
|
28
28
|
|
|
29
29
|
// src/utils/blocks.ts
|
|
30
30
|
import fs4 from "node:fs";
|
|
31
|
-
import path4 from "node:path";
|
|
32
31
|
import color4 from "chalk";
|
|
32
|
+
import path4 from "pathe";
|
|
33
33
|
|
|
34
34
|
// src/utils/blocks/types/result.ts
|
|
35
35
|
var Result = class {
|
|
@@ -680,28 +680,29 @@ 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
|
-
import path3 from "node:path";
|
|
688
687
|
import color3 from "chalk";
|
|
689
688
|
import { program } from "commander";
|
|
690
|
-
import
|
|
689
|
+
import path3 from "pathe";
|
|
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
|
-
import
|
|
695
|
+
import * as v from "@vue/compiler-sfc";
|
|
696
696
|
import color2 from "chalk";
|
|
697
697
|
import { walk } from "estree-walker";
|
|
698
|
+
import path2 from "pathe";
|
|
698
699
|
import * as sv from "svelte/compiler";
|
|
699
700
|
import { Project } from "ts-morph";
|
|
700
701
|
import validatePackageName from "validate-npm-package-name";
|
|
701
702
|
|
|
702
703
|
// src/utils/package.ts
|
|
703
704
|
import fs from "node:fs";
|
|
704
|
-
import path from "
|
|
705
|
+
import path from "pathe";
|
|
705
706
|
var findNearestPackageJson = (startDir, until) => {
|
|
706
707
|
const packagePath = path.join(startDir, "package.json");
|
|
707
708
|
if (fs.existsSync(packagePath)) return packagePath;
|
|
@@ -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}`);
|
|
@@ -1146,21 +1200,21 @@ var getInstalled = (blocks, config, cwd) => {
|
|
|
1146
1200
|
|
|
1147
1201
|
// src/utils/config.ts
|
|
1148
1202
|
import fs5 from "node:fs";
|
|
1149
|
-
import path5 from "
|
|
1150
|
-
import * as
|
|
1203
|
+
import path5 from "pathe";
|
|
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!"));
|
|
@@ -1568,19 +1622,20 @@ ${content}`;
|
|
|
1568
1622
|
|
|
1569
1623
|
// src/commands/build.ts
|
|
1570
1624
|
import fs7 from "node:fs";
|
|
1571
|
-
import path7 from "node:path";
|
|
1572
1625
|
import { outro as outro2, spinner as spinner3 } from "@clack/prompts";
|
|
1573
1626
|
import color8 from "chalk";
|
|
1574
1627
|
import { Command as Command2 } from "commander";
|
|
1575
|
-
import
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1628
|
+
import path7 from "pathe";
|
|
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();
|
|
@@ -1615,12 +1672,12 @@ var _build = async (options) => {
|
|
|
1615
1672
|
|
|
1616
1673
|
// src/commands/diff.ts
|
|
1617
1674
|
import fs8 from "node:fs";
|
|
1618
|
-
import path8 from "node:path";
|
|
1619
1675
|
import { cancel as cancel2, confirm as confirm2, isCancel as isCancel2, outro as outro3, spinner as spinner4 } from "@clack/prompts";
|
|
1620
1676
|
import color10 from "chalk";
|
|
1621
1677
|
import { Command as Command3, program as program3 } from "commander";
|
|
1622
1678
|
import { diffLines } from "diff";
|
|
1623
|
-
import
|
|
1679
|
+
import path8 from "pathe";
|
|
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!"));
|
|
@@ -1909,11 +1966,10 @@ ${remoteContent}`;
|
|
|
1909
1966
|
const from = path8.join(
|
|
1910
1967
|
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}`,
|
|
1911
1968
|
sourcePath
|
|
1912
|
-
)
|
|
1913
|
-
const to = prettyLocalPath.replaceAll("\\", "/");
|
|
1969
|
+
);
|
|
1914
1970
|
const formattedDiff = formatDiff({
|
|
1915
1971
|
from,
|
|
1916
|
-
to,
|
|
1972
|
+
to: prettyLocalPath,
|
|
1917
1973
|
changes,
|
|
1918
1974
|
expand: options.expand,
|
|
1919
1975
|
maxUnchanged: options.maxUnchanged,
|
|
@@ -1922,11 +1978,11 @@ ${remoteContent}`;
|
|
|
1922
1978
|
colorCharsAdded: color10.bgGreenBright,
|
|
1923
1979
|
colorCharsRemoved: color10.bgRedBright,
|
|
1924
1980
|
prefix: () => `${VERTICAL_LINE} `,
|
|
1925
|
-
onUnchanged: ({ from: from2, to
|
|
1981
|
+
onUnchanged: ({ from: from2, to, prefix }) => `${prefix?.() ?? ""}${color10.cyan(from2)} \u2192 ${color10.gray(to)} ${color10.gray("(unchanged)")}
|
|
1926
1982
|
`,
|
|
1927
|
-
intro: ({ from: from2, to
|
|
1983
|
+
intro: ({ from: from2, to, changes: changes2, prefix }) => {
|
|
1928
1984
|
const totalChanges = changes2.filter((a) => a.added).length;
|
|
1929
|
-
return `${prefix?.() ?? ""}${color10.cyan(from2)} \u2192 ${color10.gray(
|
|
1985
|
+
return `${prefix?.() ?? ""}${color10.cyan(from2)} \u2192 ${color10.gray(to)} (${totalChanges} change${totalChanges === 1 ? "" : "s"})
|
|
1930
1986
|
${prefix?.() ?? ""}
|
|
1931
1987
|
`;
|
|
1932
1988
|
}
|
|
@@ -1945,23 +2001,23 @@ ${prefix?.() ?? ""}
|
|
|
1945
2001
|
|
|
1946
2002
|
// src/commands/init.ts
|
|
1947
2003
|
import fs9 from "node:fs";
|
|
1948
|
-
import path9 from "node:path";
|
|
1949
2004
|
import { cancel as cancel3, confirm as confirm3, isCancel as isCancel3, outro as outro4, spinner as spinner5, text } from "@clack/prompts";
|
|
1950
2005
|
import color11 from "chalk";
|
|
1951
2006
|
import { Command as Command4 } from "commander";
|
|
1952
|
-
import
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
2007
|
+
import path9 from "pathe";
|
|
2008
|
+
import * as v8 from "valibot";
|
|
2009
|
+
var schema5 = v8.object({
|
|
2010
|
+
path: v8.optional(v8.string()),
|
|
2011
|
+
repos: v8.optional(v8.array(v8.string())),
|
|
2012
|
+
watermark: v8.boolean(),
|
|
2013
|
+
tests: v8.optional(v8.boolean()),
|
|
2014
|
+
cwd: v8.string()
|
|
1959
2015
|
});
|
|
1960
2016
|
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
2017
|
"--no-watermark",
|
|
1962
2018
|
"Will not add a watermark to each file upon adding it to your project."
|
|
1963
2019
|
).option("--tests", "Will include tests with the blocks.").option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
1964
|
-
const options =
|
|
2020
|
+
const options = v8.parse(schema5, opts);
|
|
1965
2021
|
_intro(context.package.version);
|
|
1966
2022
|
await _init(options);
|
|
1967
2023
|
outro4(color11.green("All done!"));
|
|
@@ -2031,24 +2087,24 @@ var _init = async (options) => {
|
|
|
2031
2087
|
|
|
2032
2088
|
// src/commands/test.ts
|
|
2033
2089
|
import fs10 from "node:fs";
|
|
2034
|
-
import path10 from "node:path";
|
|
2035
2090
|
import { cancel as cancel4, confirm as confirm4, isCancel as isCancel4, outro as outro5, spinner as spinner6 } from "@clack/prompts";
|
|
2036
2091
|
import color12 from "chalk";
|
|
2037
2092
|
import { Argument, Command as Command5, program as program4 } from "commander";
|
|
2038
2093
|
import { execa as execa2 } from "execa";
|
|
2039
2094
|
import { resolveCommand as resolveCommand3 } from "package-manager-detector/commands";
|
|
2040
2095
|
import { detect as detect2 } from "package-manager-detector/detect";
|
|
2096
|
+
import path10 from "pathe";
|
|
2041
2097
|
import { Project as Project2 } from "ts-morph";
|
|
2042
|
-
import * as
|
|
2043
|
-
var schema6 =
|
|
2044
|
-
repo:
|
|
2045
|
-
allow:
|
|
2046
|
-
debug:
|
|
2047
|
-
verbose:
|
|
2048
|
-
cwd:
|
|
2098
|
+
import * as v9 from "valibot";
|
|
2099
|
+
var schema6 = v9.object({
|
|
2100
|
+
repo: v9.optional(v9.string()),
|
|
2101
|
+
allow: v9.boolean(),
|
|
2102
|
+
debug: v9.boolean(),
|
|
2103
|
+
verbose: v9.boolean(),
|
|
2104
|
+
cwd: v9.string()
|
|
2049
2105
|
});
|
|
2050
2106
|
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 =
|
|
2107
|
+
const options = v9.parse(schema6, opts);
|
|
2052
2108
|
_intro(context.package.version);
|
|
2053
2109
|
await _test(blockNames, options);
|
|
2054
2110
|
outro5(color12.green("All done!"));
|
|
@@ -2098,7 +2154,7 @@ var _test = async (blockNames, options) => {
|
|
|
2098
2154
|
)
|
|
2099
2155
|
);
|
|
2100
2156
|
}
|
|
2101
|
-
const categories =
|
|
2157
|
+
const categories = v9.parse(v9.array(categorySchema), await response.json());
|
|
2102
2158
|
for (const category of categories) {
|
|
2103
2159
|
for (const block of category.blocks) {
|
|
2104
2160
|
blocksMap.set(
|
|
@@ -2287,23 +2343,23 @@ var _test = async (blockNames, options) => {
|
|
|
2287
2343
|
|
|
2288
2344
|
// src/commands/update.ts
|
|
2289
2345
|
import fs11 from "node:fs";
|
|
2290
|
-
import path11 from "node:path";
|
|
2291
2346
|
import { cancel as cancel5, confirm as confirm5, isCancel as isCancel5, multiselect as multiselect2, outro as outro6, spinner as spinner7 } from "@clack/prompts";
|
|
2292
2347
|
import color13 from "chalk";
|
|
2293
2348
|
import { Command as Command6, program as program5 } from "commander";
|
|
2294
2349
|
import { diffLines as diffLines2 } from "diff";
|
|
2295
2350
|
import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
|
|
2296
2351
|
import { detect as detect3 } from "package-manager-detector/detect";
|
|
2297
|
-
import
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2352
|
+
import path11 from "pathe";
|
|
2353
|
+
import * as v10 from "valibot";
|
|
2354
|
+
var schema7 = v10.object({
|
|
2355
|
+
all: v10.boolean(),
|
|
2356
|
+
expand: v10.boolean(),
|
|
2357
|
+
maxUnchanged: v10.number(),
|
|
2358
|
+
repo: v10.optional(v10.string()),
|
|
2359
|
+
allow: v10.boolean(),
|
|
2360
|
+
yes: v10.boolean(),
|
|
2361
|
+
verbose: v10.boolean(),
|
|
2362
|
+
cwd: v10.string()
|
|
2307
2363
|
});
|
|
2308
2364
|
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
2365
|
"--max-unchanged <number>",
|
|
@@ -2312,7 +2368,7 @@ var update = new Command6("update").argument("[blocks...]", "Names of the blocks
|
|
|
2312
2368
|
// this is such a dumb api thing
|
|
2313
2369
|
3
|
|
2314
2370
|
).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 =
|
|
2371
|
+
const options = v10.parse(schema7, opts);
|
|
2316
2372
|
_intro(context.package.version);
|
|
2317
2373
|
await _update(blockNames, options);
|
|
2318
2374
|
outro6(color13.green("All done!"));
|
|
@@ -2450,8 +2506,8 @@ ${remoteContent}`;
|
|
|
2450
2506
|
const from = path11.join(
|
|
2451
2507
|
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}`,
|
|
2452
2508
|
file.fileName
|
|
2453
|
-
)
|
|
2454
|
-
const to = path11.relative(options.cwd, file.destPath)
|
|
2509
|
+
);
|
|
2510
|
+
const to = path11.relative(options.cwd, file.destPath);
|
|
2455
2511
|
const formattedDiff = formatDiff({
|
|
2456
2512
|
from,
|
|
2457
2513
|
to,
|
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.1",
|
|
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",
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
"execa": "^9.5.1",
|
|
48
49
|
"octokit": "^4.0.2",
|
|
49
50
|
"package-manager-detector": "^0.2.4",
|
|
51
|
+
"pathe": "^1.1.2",
|
|
50
52
|
"svelte": "^5.2.3",
|
|
51
53
|
"ts-morph": "^24.0.0",
|
|
52
54
|
"valibot": "^0.42.1",
|
package/src/commands/add.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { cancel, confirm, isCancel, multiselect, outro, spinner } from '@clack/prompts';
|
|
4
3
|
import color from 'chalk';
|
|
5
4
|
import { Command, program } from 'commander';
|
|
6
5
|
import { resolveCommand } from 'package-manager-detector/commands';
|
|
7
6
|
import { detect } from 'package-manager-detector/detect';
|
|
7
|
+
import path from 'pathe';
|
|
8
8
|
import * as v from 'valibot';
|
|
9
9
|
import { context } from '..';
|
|
10
10
|
import * as ascii from '../utils/ascii';
|
package/src/commands/build.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { outro, spinner } from '@clack/prompts';
|
|
4
3
|
import color from 'chalk';
|
|
5
4
|
import { Command } from 'commander';
|
|
5
|
+
import path from 'pathe';
|
|
6
6
|
import * as v from 'valibot';
|
|
7
7
|
import { context } from '..';
|
|
8
8
|
import { type Category, buildBlocksDirectory } from '../utils/build';
|
|
@@ -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/commands/diff.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { cancel, confirm, isCancel, outro, spinner } from '@clack/prompts';
|
|
4
3
|
import color from 'chalk';
|
|
5
4
|
import { Command, program } from 'commander';
|
|
6
5
|
import { diffLines } from 'diff';
|
|
6
|
+
import path from 'pathe';
|
|
7
7
|
import * as v from 'valibot';
|
|
8
8
|
import { context } from '..';
|
|
9
9
|
import * as ascii from '../utils/ascii';
|
|
@@ -156,18 +156,14 @@ const _diff = async (options: Options) => {
|
|
|
156
156
|
|
|
157
157
|
const changes = diffLines(fileContent, remoteContent);
|
|
158
158
|
|
|
159
|
-
const from = path
|
|
160
|
-
.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
)
|
|
164
|
-
.replaceAll('\\', '/');
|
|
165
|
-
|
|
166
|
-
const to = prettyLocalPath.replaceAll('\\', '/');
|
|
159
|
+
const from = path.join(
|
|
160
|
+
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}`,
|
|
161
|
+
sourcePath
|
|
162
|
+
);
|
|
167
163
|
|
|
168
164
|
const formattedDiff = formatDiff({
|
|
169
165
|
from,
|
|
170
|
-
to,
|
|
166
|
+
to: prettyLocalPath,
|
|
171
167
|
changes,
|
|
172
168
|
expand: options.expand,
|
|
173
169
|
maxUnchanged: options.maxUnchanged,
|
package/src/commands/init.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { cancel, confirm, isCancel, outro, spinner, text } from '@clack/prompts';
|
|
4
3
|
import color from 'chalk';
|
|
5
4
|
import { Command } from 'commander';
|
|
5
|
+
import path from 'pathe';
|
|
6
6
|
import * as v from 'valibot';
|
|
7
7
|
import { context } from '..';
|
|
8
8
|
import { CONFIG_NAME, type Config, getConfig } from '../utils/config';
|
package/src/commands/test.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { cancel, confirm, isCancel, outro, spinner } from '@clack/prompts';
|
|
4
3
|
import color from 'chalk';
|
|
5
4
|
import { Argument, Command, program } from 'commander';
|
|
6
5
|
import { execa } from 'execa';
|
|
7
6
|
import { resolveCommand } from 'package-manager-detector/commands';
|
|
8
7
|
import { detect } from 'package-manager-detector/detect';
|
|
8
|
+
import path from 'pathe';
|
|
9
9
|
import { Project } from 'ts-morph';
|
|
10
10
|
import * as v from 'valibot';
|
|
11
11
|
import { context } from '..';
|
package/src/commands/update.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { cancel, confirm, isCancel, multiselect, outro, spinner } from '@clack/prompts';
|
|
4
3
|
import color from 'chalk';
|
|
5
4
|
import { Command, program } from 'commander';
|
|
6
5
|
import { diffLines } from 'diff';
|
|
7
6
|
import { resolveCommand } from 'package-manager-detector/commands';
|
|
8
7
|
import { detect } from 'package-manager-detector/detect';
|
|
8
|
+
import path from 'pathe';
|
|
9
9
|
import * as v from 'valibot';
|
|
10
10
|
import { context } from '..';
|
|
11
11
|
import * as ascii from '../utils/ascii';
|
|
@@ -239,14 +239,12 @@ const _update = async (blockNames: string[], options: Options) => {
|
|
|
239
239
|
|
|
240
240
|
const changes = diffLines(localContent, remoteContent);
|
|
241
241
|
|
|
242
|
-
const from = path
|
|
243
|
-
.
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
)
|
|
247
|
-
.replaceAll('\\', '/');
|
|
242
|
+
const from = path.join(
|
|
243
|
+
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}`,
|
|
244
|
+
file.fileName
|
|
245
|
+
);
|
|
248
246
|
|
|
249
|
-
const to = path.relative(options.cwd, file.destPath)
|
|
247
|
+
const to = path.relative(options.cwd, file.destPath);
|
|
250
248
|
|
|
251
249
|
const formattedDiff = formatDiff({
|
|
252
250
|
from,
|
package/src/index.ts
CHANGED
package/src/utils/blocks.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import color from 'chalk';
|
|
3
|
+
import path from 'pathe';
|
|
4
4
|
import { Err, Ok, type Result } from './blocks/types/result';
|
|
5
5
|
import { mapToArray } from './blocks/utils/map-to-array';
|
|
6
6
|
import type { Block } from './build';
|
package/src/utils/build.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import color from 'chalk';
|
|
4
3
|
import { program } from 'commander';
|
|
4
|
+
import path from 'pathe';
|
|
5
5
|
import * as v from 'valibot';
|
|
6
6
|
import * as ascii from './ascii';
|
|
7
7
|
import { languages } from './language-support';
|
|
@@ -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) => {
|
package/src/utils/config.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { builtinModules } from 'node:module';
|
|
3
|
-
import
|
|
3
|
+
import * as v from '@vue/compiler-sfc';
|
|
4
4
|
import color from 'chalk';
|
|
5
5
|
import { walk } from 'estree-walker';
|
|
6
|
+
import path from 'pathe';
|
|
6
7
|
import * as sv from 'svelte/compiler';
|
|
7
8
|
import { Project } from 'ts-morph';
|
|
8
9
|
import validatePackageName from 'validate-npm-package-name';
|
|
@@ -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 };
|
package/src/utils/package.ts
CHANGED