@reliverse/dler 1.7.78 → 1.7.79

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/README.md CHANGED
@@ -114,6 +114,47 @@ if you run just `dler` — it will display a list of commands which you can laun
114
114
 
115
115
  [build](#1-build) — [pub](#2-pub) — [agg](#3-agg) — [check](#4-check) — [conv](#5-conv) — [fs](#6-fs) — [init](#7-init) — [inject](#8-inject) — [libs](#9-libs) — [merge](#10-merge) — [migrate](#11-migrate) — [rempts](#12-rempts) — [x](#13-x) — [spell](#14-magic) — [split](#15-split) — [pack](#16-pack)
116
116
 
117
+ ### 0. `core`
118
+
119
+ #### `install`
120
+
121
+ ```bash
122
+ # Install all dependencies
123
+ dler install
124
+
125
+ # Install with workspace filtering
126
+ dler install --filter "pkg-*" --filter "!pkg-c"
127
+ dler install --filter "./packages/pkg-*"
128
+
129
+ # Install specific package in filtered workspaces
130
+ dler install lodash --filter "pkg-*"
131
+ ```
132
+
133
+ #### `remove`
134
+
135
+ ```bash
136
+ # Remove package from all workspaces
137
+ dler remove lodash
138
+
139
+ # Remove from specific workspaces
140
+ dler remove lodash --filter "pkg-*" --filter "!pkg-c"
141
+ ```
142
+
143
+ #### `update`
144
+
145
+ when dler detects that you are in a monorepo, it will uses linked dependencies (`--linker`).
146
+
147
+ ```bash
148
+ # Update all dependencies
149
+ dler update
150
+
151
+ # Update with workspace filtering
152
+ dler update --filter "pkg-*" --filter "!pkg-c"
153
+
154
+ # Update specific packages in filtered workspaces
155
+ dler update lodash --filter "pkg-*"
156
+ ```
157
+
117
158
  ### 1. `build`
118
159
 
119
160
  since dler is fully modular, build command is separated for its own build-in plugin as well.
@@ -904,11 +945,156 @@ bun dler update
904
945
 
905
946
  - recursive lookup for deps in multiple package.json files (e.g. monorepo; or case when you have `C:/foo/bar1/package.json` and `C:/foo/bar2/package.json` and using `dler update` in `C:/foo`).
906
947
 
907
- ## related
948
+ ## workspaces and catalogs
908
949
 
909
- special thanks to the project that inspired `@reliverse/dler`:
950
+ dler has full workspaces and catalogs support for the package management commands. Catalog logic is similar to Bun across all package management commands.
910
951
 
911
- - [unjs/unbuild](https://github.com/unjs/unbuild#readme)
952
+ ### **Catalog Features:**
953
+
954
+ #### **1. Install Dependencies as Catalogs**
955
+
956
+ ```bash
957
+ # Add to default catalog
958
+ dler install react react-dom --as-catalog default
959
+
960
+ # Add to named catalog
961
+ dler install jest testing-library --as-catalog testing
962
+ dler install webpack babel --as-catalog build --catalog-name build
963
+
964
+ # With workspace filtering
965
+ dler install lodash --as-catalog default --filter "pkg-*"
966
+ ```
967
+
968
+ #### **2. Remove Dependencies from Catalogs**
969
+
970
+ ```bash
971
+ # Remove from default catalog
972
+ dler remove react react-dom --from-catalog default
973
+
974
+ # Remove from named catalog
975
+ dler remove jest --from-catalog testing
976
+ dler remove webpack --from-catalog build --catalog-name build
977
+ ```
978
+
979
+ #### **3. List Catalogs**
980
+
981
+ ```bash
982
+ # List all catalogs and their dependencies
983
+ dler catalog list
984
+ dler catalog ls
985
+ ```
986
+
987
+ #### **4. Update Catalogs**
988
+
989
+ ```bash
990
+ # Update all catalog dependencies to latest versions
991
+ dler update --update-catalogs
992
+ ```
993
+
994
+ ### **Technical Implementation:**
995
+
996
+ #### **Smart Version Management**
997
+
998
+ - Dler automatically fetches latest versions from npm registry
999
+ - Uses `^` and `~` prefixes for semver compatibility
1000
+ - Handles scoped packages correctly
1001
+
1002
+ ### **Catalog Structure Support:**
1003
+
1004
+ #### **Default Catalog**
1005
+
1006
+ ```json
1007
+ {
1008
+ "workspaces": {
1009
+ "packages": ["packages/*"],
1010
+ "catalog": {
1011
+ "react": "^19.0.0",
1012
+ "react-dom": "^19.0.0"
1013
+ }
1014
+ }
1015
+ }
1016
+ ```
1017
+
1018
+ #### **Named Catalogs**
1019
+
1020
+ ```json
1021
+ {
1022
+ "workspaces": {
1023
+ "packages": ["packages/*"],
1024
+ "catalogs": {
1025
+ "testing": {
1026
+ "jest": "^30.0.0",
1027
+ "testing-library": "^14.0.0"
1028
+ },
1029
+ "build": {
1030
+ "webpack": "^5.88.2",
1031
+ "babel": "^7.22.10"
1032
+ }
1033
+ }
1034
+ }
1035
+ }
1036
+ ```
1037
+
1038
+ ### **Usage Examples:**
1039
+
1040
+ #### **Setting up a React Monorepo with Catalogs:**
1041
+
1042
+ ```bash
1043
+ # 1. Add core React dependencies to default catalog
1044
+ dler install react react-dom react-router-dom --as-catalog default
1045
+
1046
+ # 2. Add build tools to named catalog
1047
+ dler install webpack babel --as-catalog build
1048
+
1049
+ # 3. Add testing tools to named catalog
1050
+ dler install jest react-testing-library --as-catalog testing
1051
+
1052
+ # 4. List all catalogs
1053
+ dler catalog list
1054
+
1055
+ # 5. Update all catalogs to latest versions
1056
+ dler update --update-catalogs
1057
+ ```
1058
+
1059
+ #### **Workspace Package Usage:**
1060
+
1061
+ ```json
1062
+ // packages/app/package.json
1063
+ {
1064
+ "dependencies": {
1065
+ "react": "catalog:",
1066
+ "react-dom": "catalog:",
1067
+ "react-router-dom": "catalog:"
1068
+ },
1069
+ "devDependencies": {
1070
+ "webpack": "catalog:build",
1071
+ "jest": "catalog:testing"
1072
+ }
1073
+ }
1074
+ ```
1075
+
1076
+ #### **Advanced Operations:**
1077
+
1078
+ ```bash
1079
+ # Add dependencies to specific workspaces as catalogs
1080
+ dler install lodash --as-catalog default --filter "pkg-*" --filter "!pkg-c"
1081
+
1082
+ # Remove dependencies from catalogs in filtered workspaces
1083
+ dler remove typescript --from-catalog default --filter "pkg-*"
1084
+
1085
+ # Update catalogs and then install
1086
+ dler update --update-catalogs
1087
+ dler install
1088
+ ```
1089
+
1090
+ ### **Benefits:**
1091
+
1092
+ 1. **Consistency**: Ensures all packages use the same version of critical dependencies
1093
+ 2. **Maintenance**: Update a dependency version in one place instead of across multiple package.json files
1094
+ 3. **Clarity**: Makes it obvious which dependencies are standardized across your monorepo
1095
+ 4. **Simplicity**: No need for complex version resolution strategies or external tools
1096
+ 5. **Workspace Integration**: Seamlessly works with workspace filtering
1097
+ 6. **Cross-Package Manager**: Works with Bun (full support) and provides helpful messages for others
912
1098
 
913
1099
  ## contributors
914
1100
 
@@ -1011,6 +1197,12 @@ special thanks to the project that inspired `@reliverse/dler`:
1011
1197
  - [ ] -c, --config=<val> Specify path to Bun config file. Default $cwd/bunfig.toml
1012
1198
  - [ ] -h, --help Display this menu and exit
1013
1199
 
1200
+ ## related
1201
+
1202
+ special thanks to the project that inspired `@reliverse/dler`:
1203
+
1204
+ - [unjs/unbuild](https://github.com/unjs/unbuild#readme)
1205
+
1014
1206
  ## support
1015
1207
 
1016
1208
  - if dler saves you time and effort, please consider supporting its development: [github sponsors](https://github.com/sponsors/blefnk);
@@ -0,0 +1,13 @@
1
+ declare const _default: import("@reliverse/rempts").Command<{
2
+ action: {
3
+ type: "string";
4
+ description: string;
5
+ required: false;
6
+ default: string;
7
+ };
8
+ cwd: {
9
+ type: "string";
10
+ description: string;
11
+ };
12
+ }>;
13
+ export default _default;
@@ -0,0 +1,48 @@
1
+ import { relinka } from "@reliverse/relinka";
2
+ import { defineArgs, defineCommand } from "@reliverse/rempts";
3
+ import { listCatalogs, isCatalogSupported } from "../../libs/sdk/sdk-impl/utils/pm/pm-catalog.js";
4
+ import { detectPackageManager } from "../../libs/sdk/sdk-impl/utils/pm/pm-detect.js";
5
+ export default defineCommand({
6
+ meta: {
7
+ name: "catalog",
8
+ version: "1.0.0",
9
+ description: "Manage dependency catalogs for monorepos. Usage example: `dler catalog list`"
10
+ },
11
+ args: defineArgs({
12
+ action: {
13
+ type: "string",
14
+ description: "Action to perform: list, ls",
15
+ required: false,
16
+ default: "list"
17
+ },
18
+ cwd: {
19
+ type: "string",
20
+ description: "Current working directory"
21
+ }
22
+ }),
23
+ async run({ args }) {
24
+ const { action, cwd } = args;
25
+ const packageManager = await detectPackageManager(cwd || process.cwd());
26
+ if (!packageManager) {
27
+ relinka("error", "Could not detect package manager");
28
+ return process.exit(1);
29
+ }
30
+ if (!isCatalogSupported(packageManager)) {
31
+ relinka(
32
+ "error",
33
+ `Catalogs are not supported by ${packageManager.name}. Only Bun supports catalogs.`
34
+ );
35
+ return process.exit(1);
36
+ }
37
+ switch (action) {
38
+ case "list":
39
+ case "ls":
40
+ await listCatalogs(cwd || process.cwd());
41
+ break;
42
+ default:
43
+ relinka("error", `Unknown action: ${action}`);
44
+ relinka("log", "Available actions: list, ls");
45
+ return process.exit(1);
46
+ }
47
+ }
48
+ });
@@ -46,5 +46,17 @@ declare const _default: import("@reliverse/rempts").Command<{
46
46
  description: string;
47
47
  default: false;
48
48
  };
49
+ filter: {
50
+ type: "array";
51
+ description: string;
52
+ };
53
+ "as-catalog": {
54
+ type: "string";
55
+ description: string;
56
+ };
57
+ "catalog-name": {
58
+ type: "string";
59
+ description: string;
60
+ };
49
61
  }>;
50
62
  export default _default;
@@ -5,6 +5,8 @@ import {
5
5
  dedupeDependencies,
6
6
  installDependencies
7
7
  } from "../../libs/sdk/sdk-impl/utils/pm/pm-api.js";
8
+ import { addToCatalog, isCatalogSupported } from "../../libs/sdk/sdk-impl/utils/pm/pm-catalog.js";
9
+ import { detectPackageManager } from "../../libs/sdk/sdk-impl/utils/pm/pm-detect.js";
8
10
  export default defineCommand({
9
11
  meta: {
10
12
  name: "install",
@@ -52,11 +54,56 @@ export default defineCommand({
52
54
  type: "boolean",
53
55
  description: "Run linter checks after updating dependencies",
54
56
  default: false
57
+ },
58
+ filter: {
59
+ type: "array",
60
+ description: "Filter workspaces to operate on (e.g., 'pkg-*', '!pkg-c', './packages/pkg-*')"
61
+ },
62
+ "as-catalog": {
63
+ type: "string",
64
+ description: "Install dependencies as catalog entries (e.g., 'default', 'testing', 'build')"
65
+ },
66
+ "catalog-name": {
67
+ type: "string",
68
+ description: "Name of the catalog to add dependencies to (used with --as-catalog)"
55
69
  }
56
70
  }),
57
71
  async run({ args }) {
58
72
  console.log("DEBUG: install command starting with args:", args);
59
- const { action, name, linter, ...options } = args;
73
+ const {
74
+ action,
75
+ name,
76
+ linter,
77
+ filter,
78
+ "as-catalog": asCatalog,
79
+ "catalog-name": catalogName,
80
+ ...options
81
+ } = args;
82
+ if (filter && filter.length > 0) {
83
+ const packageManager = await detectPackageManager(process.cwd());
84
+ if (packageManager) {
85
+ options.filter = filter;
86
+ }
87
+ }
88
+ if (asCatalog && name) {
89
+ const packageManager = await detectPackageManager(process.cwd());
90
+ if (!packageManager) {
91
+ relinka("error", "Could not detect package manager");
92
+ return process.exit(1);
93
+ }
94
+ if (!isCatalogSupported(packageManager)) {
95
+ relinka(
96
+ "error",
97
+ `Catalogs are not supported by ${packageManager.name}. Only Bun supports catalogs.`
98
+ );
99
+ return process.exit(1);
100
+ }
101
+ const dependencies = Array.isArray(name) ? name : [name];
102
+ const catalogType = asCatalog === "default" ? "catalog" : "catalogs";
103
+ const actualCatalogName = asCatalog === "default" ? void 0 : catalogName || asCatalog;
104
+ await addToCatalog(dependencies, catalogType, actualCatalogName, options.cwd);
105
+ return;
106
+ }
60
107
  switch (action) {
61
108
  case "install":
62
109
  case "i":
@@ -39,6 +39,18 @@ declare const _default: import("@reliverse/rempts").Command<{
39
39
  description: string;
40
40
  default: false;
41
41
  };
42
+ filter: {
43
+ type: "array";
44
+ description: string;
45
+ };
46
+ "from-catalog": {
47
+ type: "string";
48
+ description: string;
49
+ };
50
+ "catalog-name": {
51
+ type: "string";
52
+ description: string;
53
+ };
42
54
  standalone: {
43
55
  type: "boolean";
44
56
  description: string;
@@ -6,6 +6,8 @@ import { execa } from "execa";
6
6
  import { lookpath } from "lookpath";
7
7
  import { homedir, platform } from "node:os";
8
8
  import { removeDependency } from "../../libs/sdk/sdk-impl/utils/pm/pm-api.js";
9
+ import { removeFromCatalog, isCatalogSupported } from "../../libs/sdk/sdk-impl/utils/pm/pm-catalog.js";
10
+ import { detectPackageManager } from "../../libs/sdk/sdk-impl/utils/pm/pm-detect.js";
9
11
  export default defineCommand({
10
12
  meta: {
11
13
  name: "remove",
@@ -46,6 +48,18 @@ export default defineCommand({
46
48
  description: "Run linter checks after removing dependencies",
47
49
  default: false
48
50
  },
51
+ filter: {
52
+ type: "array",
53
+ description: "Filter workspaces to operate on (e.g., 'pkg-*', '!pkg-c', './packages/pkg-*')"
54
+ },
55
+ "from-catalog": {
56
+ type: "string",
57
+ description: "Remove dependencies from catalog (e.g., 'default', 'testing', 'build')"
58
+ },
59
+ "catalog-name": {
60
+ type: "string",
61
+ description: "Name of the catalog to remove dependencies from (used with --from-catalog)"
62
+ },
49
63
  standalone: {
50
64
  type: "boolean",
51
65
  description: "Remove standalone dler installation",
@@ -53,7 +67,41 @@ export default defineCommand({
53
67
  }
54
68
  }),
55
69
  async run({ args }) {
56
- const { action, name, linter, standalone, ...options } = args;
70
+ const {
71
+ action,
72
+ name,
73
+ linter,
74
+ standalone,
75
+ filter,
76
+ "from-catalog": fromCatalog,
77
+ "catalog-name": catalogName,
78
+ ...options
79
+ } = args;
80
+ if (filter && filter.length > 0) {
81
+ const packageManager = await detectPackageManager(process.cwd());
82
+ if (packageManager) {
83
+ options.filter = filter;
84
+ }
85
+ }
86
+ if (fromCatalog && name) {
87
+ const packageManager = await detectPackageManager(process.cwd());
88
+ if (!packageManager) {
89
+ relinka("error", "Could not detect package manager");
90
+ return process.exit(1);
91
+ }
92
+ if (!isCatalogSupported(packageManager)) {
93
+ relinka(
94
+ "error",
95
+ `Catalogs are not supported by ${packageManager.name}. Only Bun supports catalogs.`
96
+ );
97
+ return process.exit(1);
98
+ }
99
+ const dependencies = Array.isArray(name) ? name : [name];
100
+ const catalogType = fromCatalog === "default" ? "catalog" : "catalogs";
101
+ const actualCatalogName = fromCatalog === "default" ? void 0 : catalogName || fromCatalog;
102
+ await removeFromCatalog(dependencies, catalogType, actualCatalogName, options.cwd);
103
+ return;
104
+ }
57
105
  if (standalone) {
58
106
  await removeStandaloneDler();
59
107
  return;
@@ -70,5 +70,14 @@ declare const _default: import("@reliverse/rempts").Command<{
70
70
  description: string;
71
71
  default: false;
72
72
  };
73
+ filter: {
74
+ type: "array";
75
+ description: string;
76
+ };
77
+ "update-catalogs": {
78
+ type: "boolean";
79
+ description: string;
80
+ default: false;
81
+ };
73
82
  }>;
74
83
  export default _default;
@@ -8,6 +8,8 @@ import pMap from "p-map";
8
8
  import { readPackageJSON } from "pkg-types";
9
9
  import semver from "semver";
10
10
  import { getConfigBunfig } from "../../libs/sdk/sdk-impl/config/load.js";
11
+ import { updateCatalogs, isCatalogSupported } from "../../libs/sdk/sdk-impl/utils/pm/pm-catalog.js";
12
+ import { detectPackageManager } from "../../libs/sdk/sdk-impl/utils/pm/pm-detect.js";
11
13
  import { latestVersion } from "../../libs/sdk/sdk-impl/utils/pm/pm-meta.js";
12
14
  function isNpmAlias(versionSpec) {
13
15
  return versionSpec.startsWith("npm:");
@@ -93,6 +95,69 @@ async function getGlobalPackages(packageManager) {
93
95
  return {};
94
96
  }
95
97
  }
98
+ async function runInstallCommand(packageManager, linker) {
99
+ try {
100
+ switch (packageManager.name) {
101
+ case "bun": {
102
+ const linkerArg = linker ? `--linker ${linker}` : "";
103
+ await $`bun install ${linkerArg}`;
104
+ break;
105
+ }
106
+ case "npm":
107
+ await $`npm install`;
108
+ break;
109
+ case "yarn":
110
+ await $`yarn install`;
111
+ break;
112
+ case "pnpm":
113
+ await $`pnpm install`;
114
+ break;
115
+ case "deno":
116
+ await $`deno cache --reload import_map.json`;
117
+ break;
118
+ default:
119
+ throw new Error(`Unsupported package manager: ${packageManager.name}`);
120
+ }
121
+ } catch (error) {
122
+ relinka("warn", `Failed to run install command for ${packageManager.name}: ${error}`);
123
+ throw error;
124
+ }
125
+ }
126
+ async function runInstallCommandWithFilter(packageManager, linker, filterArgs = []) {
127
+ try {
128
+ switch (packageManager.name) {
129
+ case "bun": {
130
+ const linkerArg = linker ? `--linker ${linker}` : "";
131
+ const filterStr = filterArgs.join(" ");
132
+ await $`bun install ${linkerArg} ${filterStr}`;
133
+ break;
134
+ }
135
+ case "npm": {
136
+ const npmFilterStr = filterArgs.join(" ");
137
+ await $`npm install ${npmFilterStr}`;
138
+ break;
139
+ }
140
+ case "yarn": {
141
+ const yarnFilterStr = filterArgs.join(" ");
142
+ await $`yarn install ${yarnFilterStr}`;
143
+ break;
144
+ }
145
+ case "pnpm": {
146
+ const pnpmFilterStr = filterArgs.join(" ");
147
+ await $`pnpm install ${pnpmFilterStr}`;
148
+ break;
149
+ }
150
+ case "deno":
151
+ await $`deno cache --reload import_map.json`;
152
+ break;
153
+ default:
154
+ throw new Error(`Unsupported package manager: ${packageManager.name}`);
155
+ }
156
+ } catch (error) {
157
+ relinka("warn", `Failed to run install command for ${packageManager.name}: ${error}`);
158
+ throw error;
159
+ }
160
+ }
96
161
  async function updateGlobalPackage(packageManager, packageName) {
97
162
  try {
98
163
  if (packageManager === "npm") {
@@ -343,6 +408,15 @@ export default defineCommand({
343
408
  type: "boolean",
344
409
  description: "Interactively select which dependencies to update",
345
410
  default: false
411
+ },
412
+ filter: {
413
+ type: "array",
414
+ description: "Filter workspaces to operate on (e.g., 'pkg-*', '!pkg-c', './packages/pkg-*')"
415
+ },
416
+ "update-catalogs": {
417
+ type: "boolean",
418
+ description: "Update catalog dependencies to latest versions",
419
+ default: false
346
420
  }
347
421
  }),
348
422
  async run({ args }) {
@@ -350,24 +424,44 @@ export default defineCommand({
350
424
  if (args.global) {
351
425
  return await handleGlobalUpdates(args);
352
426
  }
427
+ if (args["update-catalogs"]) {
428
+ const packageManager = await detectPackageManager(process.cwd());
429
+ if (!packageManager) {
430
+ relinka("error", "Could not detect package manager");
431
+ return process.exit(1);
432
+ }
433
+ if (!isCatalogSupported(packageManager)) {
434
+ relinka(
435
+ "error",
436
+ `Catalogs are not supported by ${packageManager.name}. Only Bun supports catalogs.`
437
+ );
438
+ return process.exit(1);
439
+ }
440
+ await updateCatalogs(process.cwd());
441
+ return;
442
+ }
353
443
  const packageJsonPath = path.resolve(process.cwd(), "package.json");
354
444
  if (!await fs.pathExists(packageJsonPath)) {
355
445
  relinka("error", "No package.json found in current directory");
356
446
  return process.exit(1);
357
447
  }
358
448
  let effectiveLinker = args.linker;
449
+ let linkerSource = "CLI default";
359
450
  if (typeof Bun !== "undefined") {
360
451
  const bunfigConfig = await getConfigBunfig();
361
452
  if (bunfigConfig?.install?.linker) {
362
453
  const bunfigLinker = bunfigConfig.install.linker;
363
454
  if ((bunfigLinker === "isolated" || bunfigLinker === "hoisted") && args.linker === "hoisted") {
364
455
  effectiveLinker = bunfigLinker;
456
+ linkerSource = bunfigLinker === "hoisted" ? "bunfig.toml (same as default)" : "bunfig.toml";
365
457
  }
366
458
  }
367
459
  }
368
460
  if (args.linker !== "hoisted") {
369
461
  effectiveLinker = args.linker;
462
+ linkerSource = "CLI argument (explicit override)";
370
463
  }
464
+ relinka("verbose", `Using linker strategy: ${effectiveLinker} (from ${linkerSource})`);
371
465
  const packageJson = await readPackageJSON();
372
466
  const dependencies = packageJson.dependencies || {};
373
467
  const devDependencies = packageJson.devDependencies || {};
@@ -643,13 +737,39 @@ export default defineCommand({
643
737
  "utf8"
644
738
  );
645
739
  relinka("success", `Updated ${toUpdate.length} dependencies in package.json`);
646
- if (typeof Bun !== "undefined" && !args["no-install"]) {
647
- await $`bun install --linker ${effectiveLinker}`;
648
- if (packageJson.scripts?.check && args["with-check-script"]) {
649
- await $`bun check`;
740
+ if (!args["no-install"]) {
741
+ const packageManager = await detectPackageManager(process.cwd());
742
+ if (packageManager) {
743
+ try {
744
+ if (args.filter && args.filter.length > 0) {
745
+ const filterArgs = args.filter.flatMap((filter) => ["--filter", filter]);
746
+ await runInstallCommandWithFilter(packageManager, effectiveLinker, filterArgs);
747
+ } else {
748
+ await runInstallCommand(packageManager, effectiveLinker);
749
+ }
750
+ if (packageManager.name === "bun" && packageJson.scripts?.check && args["with-check-script"]) {
751
+ await $`bun check`;
752
+ }
753
+ } catch (error) {
754
+ relinka(
755
+ "warn",
756
+ `Install failed: ${error instanceof Error ? error.message : String(error)}`
757
+ );
758
+ relinka(
759
+ "info",
760
+ `Run '${packageManager.command} install' manually to apply the changes`
761
+ );
762
+ }
763
+ } else {
764
+ relinka("warn", "Could not detect package manager. Please run install manually.");
650
765
  }
651
766
  } else {
652
- relinka("info", "Run your package manager's install command to apply the changes");
767
+ const packageManager = await detectPackageManager(process.cwd());
768
+ const installCommand = packageManager ? `${packageManager.command} install` : "your package manager's install command";
769
+ relinka(
770
+ "info",
771
+ `Skipped install step due to --no-install flag. Run '${installCommand}' to apply the changes.`
772
+ );
653
773
  }
654
774
  } catch (error) {
655
775
  relinka(
@@ -1,5 +1,5 @@
1
1
  import { endPrompt, startPrompt } from "@reliverse/rempts";
2
- const version = "1.7.78";
2
+ const version = "1.7.79";
3
3
  export async function showStartPrompt(isDev) {
4
4
  await startPrompt({
5
5
  titleColor: "inverse",
@@ -7,8 +7,9 @@ import type { OperationOptions } from "./pm-types";
7
7
  * @param options.silent - Whether to run the command in silent mode.
8
8
  * @param options.packageManager - The package manager info to use (auto-detected).
9
9
  * @param options.frozenLockFile - Whether to install dependencies with frozen lock file.
10
+ * @param options.filter - Filter workspaces to operate on (e.g., 'pkg-*', '!pkg-c').
10
11
  */
11
- export declare function installDependencies(options?: Pick<OperationOptions, "cwd" | "silent" | "packageManager"> & {
12
+ export declare function installDependencies(options?: Pick<OperationOptions, "cwd" | "silent" | "packageManager" | "filter"> & {
12
13
  frozenLockFile?: boolean;
13
14
  }): Promise<void>;
14
15
  /**
@@ -48,6 +49,7 @@ export declare function addDevDependency(name: string | string[], options?: Omit
48
49
  * @param options.dev - Whether to remove dev dependency.
49
50
  * @param options.workspace - The name of the workspace to use.
50
51
  * @param options.global - Whether to run the command in global mode.
52
+ * @param options.filter - Filter workspaces to operate on (e.g., 'pkg-*', '!pkg-c').
51
53
  */
52
54
  export declare function removeDependency(name: string | string[], options?: OperationOptions): Promise<void>;
53
55
  /**
@@ -17,7 +17,9 @@ export async function installDependencies(options = {}) {
17
17
  deno: ["install", "--frozen"]
18
18
  };
19
19
  const commandArgs = options.frozenLockFile ? pmToFrozenLockfileInstallCommand[resolvedOptions.packageManager.name] : ["install"];
20
- await executeCommand(resolvedOptions.packageManager.command, commandArgs, {
20
+ const workspaceArgs = getWorkspaceArgs(resolvedOptions);
21
+ const finalArgs = [...commandArgs, ...workspaceArgs];
22
+ await executeCommand(resolvedOptions.packageManager.command, finalArgs, {
21
23
  cwd: resolvedOptions.cwd,
22
24
  silent: resolvedOptions.silent
23
25
  });
@@ -0,0 +1,36 @@
1
+ import type { PackageManager } from "./pm-types";
2
+ /**
3
+ * Interface for catalog structure
4
+ */
5
+ export interface CatalogStructure {
6
+ catalog?: Record<string, string>;
7
+ catalogs?: Record<string, Record<string, string>>;
8
+ }
9
+ /**
10
+ * Get catalog structure from package.json
11
+ */
12
+ export declare function getCatalogStructure(cwd?: string): Promise<CatalogStructure>;
13
+ /**
14
+ * Add dependencies to catalog
15
+ */
16
+ export declare function addToCatalog(dependencies: string[], catalogType: "catalog" | "catalogs", catalogName?: string, cwd?: string): Promise<void>;
17
+ /**
18
+ * Check if catalog is supported by package manager
19
+ */
20
+ export declare function isCatalogSupported(packageManager: PackageManager): boolean;
21
+ /**
22
+ * Get catalog reference format for a dependency
23
+ */
24
+ export declare function getCatalogReference(dependency: string, catalogType: "catalog" | "catalogs", catalogName?: string): string;
25
+ /**
26
+ * List all catalogs and their dependencies
27
+ */
28
+ export declare function listCatalogs(cwd?: string): Promise<void>;
29
+ /**
30
+ * Update catalog dependencies to latest versions
31
+ */
32
+ export declare function updateCatalogs(cwd?: string): Promise<void>;
33
+ /**
34
+ * Remove dependencies from catalog
35
+ */
36
+ export declare function removeFromCatalog(dependencies: string[], catalogType: "catalog" | "catalogs", catalogName?: string, cwd?: string): Promise<void>;
@@ -0,0 +1,237 @@
1
+ import path from "@reliverse/pathkit";
2
+ import fs from "@reliverse/relifso";
3
+ import { relinka } from "@reliverse/relinka";
4
+ import { readPackageJSON } from "pkg-types";
5
+ export async function getCatalogStructure(cwd = process.cwd()) {
6
+ try {
7
+ const packageJson = await readPackageJSON(cwd);
8
+ const workspaces = packageJson.workspaces || {};
9
+ return {
10
+ catalog: workspaces.catalog || packageJson.catalog || {},
11
+ catalogs: workspaces.catalogs || packageJson.catalogs || {}
12
+ };
13
+ } catch (error) {
14
+ relinka("warn", `Failed to read catalog structure: ${error}`);
15
+ return { catalog: {}, catalogs: {} };
16
+ }
17
+ }
18
+ export async function addToCatalog(dependencies, catalogType, catalogName, cwd = process.cwd()) {
19
+ try {
20
+ const packageJsonPath = path.resolve(cwd, "package.json");
21
+ const packageJson = await readPackageJSON(cwd);
22
+ const latestVersions = {};
23
+ for (const dep of dependencies) {
24
+ try {
25
+ const packageName = dep.split("@")[0] || dep;
26
+ const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
27
+ if (response.ok) {
28
+ const data = await response.json();
29
+ latestVersions[packageName] = `^${data.version}`;
30
+ } else {
31
+ latestVersions[packageName] = "latest";
32
+ }
33
+ } catch (error) {
34
+ relinka("warn", `Failed to get latest version for ${dep}: ${error}`);
35
+ latestVersions[dep] = "latest";
36
+ }
37
+ }
38
+ const updatedPackageJson = { ...packageJson };
39
+ if (catalogType === "catalog") {
40
+ if (!updatedPackageJson.workspaces) {
41
+ updatedPackageJson.workspaces = {};
42
+ }
43
+ if (!updatedPackageJson.workspaces.catalog) {
44
+ updatedPackageJson.workspaces.catalog = {};
45
+ }
46
+ Object.assign(updatedPackageJson.workspaces.catalog, latestVersions);
47
+ if (updatedPackageJson.catalog) {
48
+ Object.assign(updatedPackageJson.catalog, latestVersions);
49
+ }
50
+ } else if (catalogType === "catalogs" && catalogName) {
51
+ if (!updatedPackageJson.workspaces) {
52
+ updatedPackageJson.workspaces = {};
53
+ }
54
+ if (!updatedPackageJson.workspaces.catalogs) {
55
+ updatedPackageJson.workspaces.catalogs = {};
56
+ }
57
+ if (!updatedPackageJson.workspaces.catalogs[catalogName]) {
58
+ updatedPackageJson.workspaces.catalogs[catalogName] = {};
59
+ }
60
+ Object.assign(updatedPackageJson.workspaces.catalogs[catalogName], latestVersions);
61
+ if (updatedPackageJson.catalogs) {
62
+ if (!updatedPackageJson.catalogs[catalogName]) {
63
+ updatedPackageJson.catalogs[catalogName] = {};
64
+ }
65
+ Object.assign(updatedPackageJson.catalogs[catalogName], latestVersions);
66
+ }
67
+ }
68
+ await fs.writeFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2) + "\n", "utf8");
69
+ relinka(
70
+ "success",
71
+ `Added ${dependencies.length} dependencies to ${catalogType}${catalogName ? ` (${catalogName})` : ""}`
72
+ );
73
+ } catch (error) {
74
+ relinka("error", `Failed to add dependencies to catalog: ${error}`);
75
+ throw error;
76
+ }
77
+ }
78
+ export function isCatalogSupported(packageManager) {
79
+ return packageManager.name === "bun";
80
+ }
81
+ export function getCatalogReference(dependency, catalogType, catalogName) {
82
+ if (catalogType === "catalog") {
83
+ return "catalog:";
84
+ } else if (catalogType === "catalogs" && catalogName) {
85
+ return `catalog:${catalogName}`;
86
+ }
87
+ return dependency;
88
+ }
89
+ export async function listCatalogs(cwd = process.cwd()) {
90
+ try {
91
+ const { catalog, catalogs } = await getCatalogStructure(cwd);
92
+ if ((!catalog || Object.keys(catalog).length === 0) && (!catalogs || Object.keys(catalogs).length === 0)) {
93
+ relinka("info", "No catalogs found in package.json");
94
+ return;
95
+ }
96
+ if (catalog && Object.keys(catalog).length > 0) {
97
+ relinka("info", "Default catalog:");
98
+ for (const [dep, version] of Object.entries(catalog)) {
99
+ relinka("log", ` ${dep}: ${version}`);
100
+ }
101
+ }
102
+ if (catalogs && Object.keys(catalogs).length > 0) {
103
+ for (const [catalogName, dependencies] of Object.entries(catalogs)) {
104
+ relinka("info", `
105
+ Catalog '${catalogName}':`);
106
+ for (const [dep, version] of Object.entries(dependencies)) {
107
+ relinka("log", ` ${dep}: ${version}`);
108
+ }
109
+ }
110
+ }
111
+ } catch (error) {
112
+ relinka("error", `Failed to list catalogs: ${error}`);
113
+ }
114
+ }
115
+ export async function updateCatalogs(cwd = process.cwd()) {
116
+ try {
117
+ const { catalog, catalogs } = await getCatalogStructure(cwd);
118
+ const packageJsonPath = path.resolve(cwd, "package.json");
119
+ const packageJson = await readPackageJSON(cwd);
120
+ const updatedPackageJson = { ...packageJson };
121
+ let updatedCount = 0;
122
+ if (catalog && Object.keys(catalog).length > 0) {
123
+ const updatedCatalog = {};
124
+ for (const [dep, currentVersion] of Object.entries(catalog)) {
125
+ try {
126
+ const response = await fetch(`https://registry.npmjs.org/${dep}/latest`);
127
+ if (response.ok) {
128
+ const data = await response.json();
129
+ const latestVersion = `^${data.version}`;
130
+ if (latestVersion !== currentVersion) {
131
+ updatedCatalog[dep] = latestVersion;
132
+ updatedCount++;
133
+ relinka("log", ` ${dep}: ${currentVersion} \u2192 ${latestVersion}`);
134
+ } else {
135
+ updatedCatalog[dep] = currentVersion;
136
+ }
137
+ } else {
138
+ updatedCatalog[dep] = currentVersion;
139
+ }
140
+ } catch (error) {
141
+ relinka("warn", `Failed to update ${dep}: ${error}`);
142
+ updatedCatalog[dep] = currentVersion;
143
+ }
144
+ }
145
+ if (!updatedPackageJson.workspaces) {
146
+ updatedPackageJson.workspaces = {};
147
+ }
148
+ updatedPackageJson.workspaces.catalog = updatedCatalog;
149
+ if (updatedPackageJson.catalog) {
150
+ updatedPackageJson.catalog = updatedCatalog;
151
+ }
152
+ }
153
+ if (catalogs && Object.keys(catalogs).length > 0) {
154
+ if (!updatedPackageJson.workspaces) {
155
+ updatedPackageJson.workspaces = {};
156
+ }
157
+ if (!updatedPackageJson.workspaces.catalogs) {
158
+ updatedPackageJson.workspaces.catalogs = {};
159
+ }
160
+ for (const [catalogName, dependencies] of Object.entries(catalogs)) {
161
+ const updatedNamedCatalog = {};
162
+ for (const [dep, currentVersion] of Object.entries(dependencies)) {
163
+ try {
164
+ const response = await fetch(`https://registry.npmjs.org/${dep}/latest`);
165
+ if (response.ok) {
166
+ const data = await response.json();
167
+ const latestVersion = `^${data.version}`;
168
+ if (latestVersion !== currentVersion) {
169
+ updatedNamedCatalog[dep] = latestVersion;
170
+ updatedCount++;
171
+ relinka("log", ` ${catalogName}:${dep}: ${currentVersion} \u2192 ${latestVersion}`);
172
+ } else {
173
+ updatedNamedCatalog[dep] = currentVersion;
174
+ }
175
+ } else {
176
+ updatedNamedCatalog[dep] = currentVersion;
177
+ }
178
+ } catch (error) {
179
+ relinka("warn", `Failed to update ${catalogName}:${dep}: ${error}`);
180
+ updatedNamedCatalog[dep] = currentVersion;
181
+ }
182
+ }
183
+ updatedPackageJson.workspaces.catalogs[catalogName] = updatedNamedCatalog;
184
+ if (updatedPackageJson.catalogs) {
185
+ updatedPackageJson.catalogs[catalogName] = updatedNamedCatalog;
186
+ }
187
+ }
188
+ }
189
+ await fs.writeFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2) + "\n", "utf8");
190
+ if (updatedCount > 0) {
191
+ relinka("success", `Updated ${updatedCount} catalog dependencies`);
192
+ } else {
193
+ relinka("success", "All catalog dependencies are up to date");
194
+ }
195
+ } catch (error) {
196
+ relinka("error", `Failed to update catalogs: ${error}`);
197
+ throw error;
198
+ }
199
+ }
200
+ export async function removeFromCatalog(dependencies, catalogType, catalogName, cwd = process.cwd()) {
201
+ try {
202
+ const packageJsonPath = path.resolve(cwd, "package.json");
203
+ const packageJson = await readPackageJSON(cwd);
204
+ const updatedPackageJson = { ...packageJson };
205
+ if (catalogType === "catalog") {
206
+ if (updatedPackageJson.workspaces?.catalog) {
207
+ for (const dep of dependencies) {
208
+ delete updatedPackageJson.workspaces.catalog[dep];
209
+ }
210
+ }
211
+ if (updatedPackageJson.catalog) {
212
+ for (const dep of dependencies) {
213
+ delete updatedPackageJson.catalog[dep];
214
+ }
215
+ }
216
+ } else if (catalogType === "catalogs" && catalogName) {
217
+ if (updatedPackageJson.workspaces?.catalogs?.[catalogName]) {
218
+ for (const dep of dependencies) {
219
+ delete updatedPackageJson.workspaces.catalogs[catalogName][dep];
220
+ }
221
+ }
222
+ if (updatedPackageJson.catalogs?.[catalogName]) {
223
+ for (const dep of dependencies) {
224
+ delete updatedPackageJson.catalogs[catalogName][dep];
225
+ }
226
+ }
227
+ }
228
+ await fs.writeFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2) + "\n", "utf8");
229
+ relinka(
230
+ "success",
231
+ `Removed ${dependencies.length} dependencies from ${catalogType}${catalogName ? ` (${catalogName})` : ""}`
232
+ );
233
+ } catch (error) {
234
+ relinka("error", `Failed to remove dependencies from catalog: ${error}`);
235
+ throw error;
236
+ }
237
+ }
@@ -16,6 +16,9 @@ export interface OperationOptions {
16
16
  dev?: boolean;
17
17
  workspace?: boolean | string;
18
18
  global?: boolean;
19
+ filter?: string[];
20
+ asCatalog?: string;
21
+ catalogName?: string;
19
22
  }
20
23
  export interface DetectPackageManagerOptions {
21
24
  /**
@@ -4,7 +4,7 @@ type NonPartial<T> = {
4
4
  [P in keyof T]-?: T[P];
5
5
  };
6
6
  export declare const NO_PACKAGE_MANAGER_DETECTED_ERROR_MSG = "No package manager auto-detected.";
7
- export declare function resolveOperationOptions(options?: OperationOptions): Promise<NonPartial<Pick<OperationOptions, "cwd" | "silent" | "dev" | "global">> & Pick<OperationOptions, "workspace"> & {
7
+ export declare function resolveOperationOptions(options?: OperationOptions): Promise<NonPartial<Pick<OperationOptions, "cwd" | "silent" | "dev" | "global">> & Pick<OperationOptions, "workspace" | "filter" | "asCatalog" | "catalogName"> & {
8
8
  packageManager: PackageManager;
9
9
  }>;
10
10
  export declare function getWorkspaceArgs(options: Awaited<ReturnType<typeof resolveOperationOptions>>): string[];
@@ -71,10 +71,20 @@ export async function resolveOperationOptions(options = {}) {
71
71
  packageManager,
72
72
  dev: options.dev ?? false,
73
73
  workspace: options.workspace,
74
+ filter: options.filter,
75
+ asCatalog: options.asCatalog,
76
+ catalogName: options.catalogName,
74
77
  global: options.global ?? false
75
78
  };
76
79
  }
77
80
  export function getWorkspaceArgs(options) {
81
+ const args = [];
82
+ if (options.filter && options.filter.length > 0) {
83
+ for (const filter of options.filter) {
84
+ args.push("--filter", filter);
85
+ }
86
+ return args;
87
+ }
78
88
  if (!options.workspace) {
79
89
  return [];
80
90
  }
package/package.json CHANGED
@@ -37,7 +37,7 @@
37
37
  "pretty-ms": "^9.2.0",
38
38
  "registry-auth-token": "^5.1.0",
39
39
  "registry-url": "^7.2.0",
40
- "rollup": "^4.46.0",
40
+ "rollup": "^4.46.1",
41
41
  "rollup-plugin-dts": "^6.2.1",
42
42
  "scule": "^1.3.0",
43
43
  "semver": "^7.7.2",
@@ -52,7 +52,7 @@
52
52
  "license": "MIT",
53
53
  "name": "@reliverse/dler",
54
54
  "type": "module",
55
- "version": "1.7.78",
55
+ "version": "1.7.79",
56
56
  "keywords": [
57
57
  "reliverse",
58
58
  "cli",