@reliverse/rempts 1.7.41 → 1.7.43

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright (c) Nazar Kornienko (blefnk), Reliverse
3
+ Copyright (c) Nazar Kornienko (blefnk), Bleverse, Reliverse
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1210,6 +1210,219 @@ mycli --tags desktop
1210
1210
 
1211
1211
  The validation happens after type casting, so for example with numbers, the input will first be converted to a number and then checked against the allowed list.
1212
1212
 
1213
+ ## Typed Commands System
1214
+
1215
+ The typed commands system provides TypeScript intellisense and type safety for rempts launcher usage while maintaining dynamic code execution.
1216
+
1217
+ - 🎯 **TypeScript Intellisense**: Full autocomplete for command names and arguments
1218
+ - 🔒 **Type Safety**: Compile-time checking for argument types and required fields
1219
+ - ⚡ **Dynamic Execution**: Commands are still loaded and executed dynamically
1220
+ - 📝 **Automatic Sync**: Utility script to keep types in sync with actual command definitions
1221
+
1222
+ ### Usage
1223
+
1224
+ #### Basic Usage
1225
+
1226
+ ```typescript
1227
+ import { callCmd } from "~/app/cmds";
1228
+
1229
+ // Simple command with typed arguments
1230
+ await callCmd("pub", { dev: true });
1231
+
1232
+ // Command with multiple arguments
1233
+ await callCmd("check", {
1234
+ directory: "src",
1235
+ checks: "missing-deps,file-extensions",
1236
+ strict: true,
1237
+ json: false
1238
+ });
1239
+
1240
+ // Command with no arguments
1241
+ await callCmd("update");
1242
+
1243
+ // Generators with typed arguments
1244
+ await callCmd("rempts", {
1245
+ init: "new-cmd another-cmd",
1246
+ overwrite: true,
1247
+ outFile: "src/app/cmds.ts"
1248
+ });
1249
+ ```
1250
+
1251
+ #### Advanced Usage
1252
+
1253
+ ```typescript
1254
+ import { getTypedCmd } from "~/app/cmds";
1255
+
1256
+ // Get command instance for more control
1257
+ const { command, run } = await getTypedCmd("magic");
1258
+
1259
+ console.log(`Running: ${command.meta.name}`);
1260
+ console.log(`Description: ${command.meta.description}`);
1261
+
1262
+ await run({
1263
+ targets: ["dist-npm", "dist-jsr"],
1264
+ concurrency: 4,
1265
+ stopOnError: true
1266
+ });
1267
+ ```
1268
+
1269
+ #### TypeScript Benefits
1270
+
1271
+ ##### 1. Command Name Autocomplete
1272
+
1273
+ When you type `callCmd("`, TypeScript will show all available commands.
1274
+
1275
+ ##### 2. Argument Intellisense
1276
+
1277
+ When you type the arguments object, you get full autocomplete for:
1278
+
1279
+ - Argument names
1280
+ - Argument types
1281
+ - Required vs optional fields
1282
+
1283
+ ##### 3. Type Validation
1284
+
1285
+ ```typescript
1286
+ // ✅ Correct usage
1287
+ await callCmd("create", {
1288
+ mode: "files", // Only "template" | "files" allowed
1289
+ multiple: true // boolean
1290
+ });
1291
+
1292
+ // ❌ TypeScript errors
1293
+ await callCmd("create", {
1294
+ mode: "invalid", // Error: not assignable to type
1295
+ multiple: "yes" // Error: string not assignable to boolean
1296
+ });
1297
+ ```
1298
+
1299
+ ##### 4. Required Field Checking
1300
+
1301
+ ```typescript
1302
+ // ✅ Required field provided
1303
+ await callCmd("magic", {
1304
+ targets: ["dist-npm"] // Required field
1305
+ });
1306
+
1307
+ // ❌ TypeScript error: missing required field 'targets'
1308
+ await callCmd("magic", {
1309
+ concurrency: 4
1310
+ });
1311
+ ```
1312
+
1313
+ ### Maintaining the System
1314
+
1315
+ #### Adding New Commands
1316
+
1317
+ 1. Create your command in `src/app/<command-name>/cmd.ts` using `defineCommand` and `defineArgs`
1318
+ 2. Run the generator: `dler rempts --overwrite`
1319
+ 3. The `CommandArgsMap` interface in `src/app/cmds.ts` will be automatically updated
1320
+
1321
+ #### Manual Updates
1322
+
1323
+ The `CommandArgsMap` interface is auto-generated. If you need custom types, you can add manual type assertions (it is more recommended to edit your command file instead and regenerate the types):
1324
+
1325
+ ```typescript
1326
+ interface CommandArgsMap {
1327
+ myCommand: {
1328
+ // Use union types for specific values
1329
+ mode: "development" | "production";
1330
+
1331
+ // Use template literal types for patterns
1332
+ version: `${number}.${number}.${number}`;
1333
+
1334
+ // Use branded types for validation
1335
+ port: number & { __brand: "Port" };
1336
+ };
1337
+ }
1338
+ ```
1339
+
1340
+ ### Migration from Old System
1341
+
1342
+ #### Before (Old System, still supported)
1343
+
1344
+ ```typescript
1345
+ import { runCmd } from "@reliverse/rempts";
1346
+ import { getPubCmd } from "./app/cmds";
1347
+
1348
+ // No type safety, string-based arguments
1349
+ await runCmd(await getPubCmd(), [`--dev=${isDev}`]);
1350
+ ```
1351
+
1352
+ ### After (New System)
1353
+
1354
+ ```typescript
1355
+ import { callCmd } from "./app/cmds";
1356
+
1357
+ // Full type safety and intellisense
1358
+ await callCmd("pub", { dev: isDev });
1359
+ ```
1360
+
1361
+ ### Implementation Details
1362
+
1363
+ The system works by:
1364
+
1365
+ 1. **Command Loading**: Commands are still loaded dynamically using `loadCommand()`
1366
+ 2. **Argument Conversion**: Typed arguments are converted to string array format that `runCmd` expects
1367
+ 3. **Type Mapping**: `CommandArgsMap` interface maps command names to their argument types
1368
+ 4. **Generic Types**: `callCmd<T extends keyof CommandArgsMap>` provides type safety
1369
+
1370
+ ### Generator Usage
1371
+
1372
+ The typed command system also supports calling generators with full intellisense:
1373
+
1374
+ #### Creating New Commands
1375
+
1376
+ ```typescript
1377
+ // Create new commands with typed arguments
1378
+ await callCmd("rempts", {
1379
+ init: "auth login logout", // Commands to create
1380
+ overwrite: true, // Overwrite existing
1381
+ outFile: "src/app/cmds.ts" // Export file path
1382
+ });
1383
+
1384
+ // Create commands in custom location
1385
+ await callCmd("rempts", {
1386
+ init: "api-handler",
1387
+ customCmdsRoot: "src/modules/api",
1388
+ outFile: "src/modules/api/exports.ts",
1389
+ overwrite: true
1390
+ });
1391
+ ```
1392
+
1393
+ #### Regenerating Exports
1394
+
1395
+ ```typescript
1396
+ // Regenerate exports file only
1397
+ await callCmd("rempts", {
1398
+ overwrite: true,
1399
+ outFile: "src/app/cmds.ts"
1400
+ });
1401
+
1402
+ // Generate exports for specific directories
1403
+ await callCmd("rempts", {
1404
+ cmdDirs: ["build", "pub", "magic"],
1405
+ outFile: "src/app/core-cmds.ts",
1406
+ overwrite: true
1407
+ });
1408
+ ```
1409
+
1410
+ #### Batch Operations
1411
+
1412
+ ```typescript
1413
+ // Create multiple commands programmatically
1414
+ const modules = ["auth", "db", "api", "deploy"];
1415
+
1416
+ for (const module of modules) {
1417
+ await callCmd("rempts", {
1418
+ init: `${module}-create ${module}-update ${module}-delete`,
1419
+ customCmdsRoot: `src/modules/${module}`,
1420
+ outFile: `src/modules/${module}/cmds.ts`,
1421
+ overwrite: true
1422
+ });
1423
+ }
1424
+ ```
1425
+
1213
1426
  ## Contributing
1214
1427
 
1215
1428
  Bug report? Prompt idea? Want to build the best DX possible?
@@ -1,4 +1,4 @@
1
- import { colorize, re } from "@reliverse/relico";
1
+ import { re } from "@reliverse/relico";
2
2
  import { stdin as input, stdout as output } from "node:process";
3
3
  import readline from "node:readline/promises";
4
4
  import { bar, msg } from "../msg-fmt/messages.js";
@@ -148,7 +148,7 @@ export async function confirmPrompt(options) {
148
148
  deleteLastLine();
149
149
  msg({
150
150
  type: "M_NULL",
151
- title: `${colorize(re.reset(formattedBar), borderColor)} ${re.reset(effectiveDefault ? "y" : "n")}`
151
+ title: `${formattedBar} ${effectiveDefault ? "y" : "n"}`
152
152
  });
153
153
  result = effectiveDefault;
154
154
  } else if (answer === "y" || answer === "yes") {
@@ -1,4 +1,5 @@
1
1
  import type { InputPromptOptions } from "../../types.js";
2
- export declare const input: any;
3
- export declare const text: any;
4
- export declare const password: (options: Omit<InputPromptOptions, "mode">) => any;
2
+ import { inputPrompt } from "./input-mod.js";
3
+ export declare const input: typeof inputPrompt;
4
+ export declare const text: typeof inputPrompt;
5
+ export declare const password: (options: Omit<InputPromptOptions, "mode">) => Promise<string>;
@@ -0,0 +1,16 @@
1
+ import type { Command } from "./launcher-types";
2
+ /**
3
+ * Static implementation functions for the typed command system.
4
+ * These functions are imported by the generated cmds.ts file.
5
+ */
6
+ export declare function argsToStringArray(args: Record<string, unknown>): string[];
7
+ export declare function createCallCmd<TCommandArgsMap>(): Promise<(<T extends keyof TCommandArgsMap>(cmdName: T, args?: TCommandArgsMap[T]) => Promise<void>)>;
8
+ export declare function createGetTypedCmd<TCommandArgsMap>(): Promise<(<T extends keyof TCommandArgsMap>(cmdName: T) => Promise<{
9
+ command: Command;
10
+ run: (args?: TCommandArgsMap[T]) => Promise<void>;
11
+ }>)>;
12
+ export declare function callCmdImpl<TCommandArgsMap>(cmdName: keyof TCommandArgsMap, args?: TCommandArgsMap[keyof TCommandArgsMap]): Promise<void>;
13
+ export declare function getTypedCmdImpl<TCommandArgsMap>(cmdName: keyof TCommandArgsMap): Promise<{
14
+ command: Command;
15
+ run: (args?: TCommandArgsMap[keyof TCommandArgsMap]) => Promise<void>;
16
+ }>;
@@ -0,0 +1,60 @@
1
+ import { loadCommand } from "./command-runner.js";
2
+ import { runCmd } from "./launcher-mod.js";
3
+ export function argsToStringArray(args) {
4
+ const result = [];
5
+ for (const [key, value] of Object.entries(args)) {
6
+ if (value === void 0 || value === null) continue;
7
+ if (typeof value === "boolean") {
8
+ result.push(`--${key}=${value}`);
9
+ } else if (Array.isArray(value)) {
10
+ result.push(`--${key}=${value.join(",")}`);
11
+ } else {
12
+ result.push(`--${key}=${String(value)}`);
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ export async function createCallCmd() {
18
+ return async function callCmd(cmdName, args) {
19
+ try {
20
+ const command = await loadCommand(cmdName);
21
+ const stringArgs = args ? argsToStringArray(args) : [];
22
+ await runCmd(command, stringArgs);
23
+ } catch (error) {
24
+ console.error(`Error running command '${String(cmdName)}':`, error);
25
+ throw error;
26
+ }
27
+ };
28
+ }
29
+ export async function createGetTypedCmd() {
30
+ return async function getTypedCmd(cmdName) {
31
+ const command = await loadCommand(cmdName);
32
+ return {
33
+ command,
34
+ run: async (args) => {
35
+ const stringArgs = args ? argsToStringArray(args) : [];
36
+ await runCmd(command, stringArgs);
37
+ }
38
+ };
39
+ };
40
+ }
41
+ export async function callCmdImpl(cmdName, args) {
42
+ try {
43
+ const command = await loadCommand(cmdName);
44
+ const stringArgs = args ? argsToStringArray(args) : [];
45
+ await runCmd(command, stringArgs);
46
+ } catch (error) {
47
+ console.error(`Error running command '${String(cmdName)}':`, error);
48
+ throw error;
49
+ }
50
+ }
51
+ export async function getTypedCmdImpl(cmdName) {
52
+ const command = await loadCommand(cmdName);
53
+ return {
54
+ command,
55
+ run: async (args) => {
56
+ const stringArgs = args ? argsToStringArray(args) : [];
57
+ await runCmd(command, stringArgs);
58
+ }
59
+ };
60
+ }
package/bin/mod.d.ts CHANGED
@@ -13,13 +13,14 @@ export { input, text, password } from "./libs/input/input-alias.js";
13
13
  export { inputPrompt } from "./libs/input/input-mod.js";
14
14
  export { startPrompt, intro } from "./libs/intro/intro-alias.js";
15
15
  export { introPrompt } from "./libs/intro/intro-mod.js";
16
+ export { loadCommand } from "./libs/launcher/command-runner.js";
17
+ export { argsToStringArray, createCallCmd, createGetTypedCmd, callCmdImpl, getTypedCmdImpl, } from "./libs/launcher/command-typed.js";
16
18
  export { runMain } from "./libs/launcher/launcher-alias.js";
17
- export { defineCommand, showUsage, createCli, defineArgs, runCmd, runCmdWithSubcommands, } from "./libs/launcher/launcher-mod.js";
19
+ export { defineCommand, showUsage, createCli, defineArgs, runCmdWithSubcommands, runCmd, } from "./libs/launcher/launcher-mod.js";
18
20
  export type { EmptyArgs, BaseArgProps, BaseArgDefinition, PositionalArgDefinition, BooleanArgDefinition, StringArgDefinition, NumberArgDefinition, ArrayArgDefinition, ArgDefinition, ArgDefinitions, CommandMeta, CommandSpec, CommandsMap, CommandContext, CommandRun, CommandHook, DefineCommandOptions, Command, InferArgTypes, FileBasedOptions, } from "./libs/launcher/launcher-types.js";
19
- export { loadCommand } from "./libs/launcher/run-command.js";
20
21
  export { addCompletions } from "./libs/launcher/trpc-orpc-support/completions.js";
21
22
  export { CliValidationError, FailedToExitError, } from "./libs/launcher/trpc-orpc-support/errors.js";
22
- export { TrpcCommand, parseRouter, createRpcCli, z, trpcServer, zod, } from "./libs/launcher/trpc-orpc-support/index.js";
23
+ export { TrpcCommand, parseRouter, createRpcCli, z, } from "./libs/launcher/trpc-orpc-support/index.js";
23
24
  export { flattenedProperties, incompatiblePropertyPairs, getDescription, getSchemaTypes, getEnumChoices, } from "./libs/launcher/trpc-orpc-support/json-schema.js";
24
25
  export type { CommandJSON } from "./libs/launcher/trpc-orpc-support/json.js";
25
26
  export { commandToJSON } from "./libs/launcher/trpc-orpc-support/json.js";
package/bin/mod.js CHANGED
@@ -24,16 +24,23 @@ export { input, text, password } from "./libs/input/input-alias.js";
24
24
  export { inputPrompt } from "./libs/input/input-mod.js";
25
25
  export { startPrompt, intro } from "./libs/intro/intro-alias.js";
26
26
  export { introPrompt } from "./libs/intro/intro-mod.js";
27
+ export { loadCommand } from "./libs/launcher/command-runner.js";
28
+ export {
29
+ argsToStringArray,
30
+ createCallCmd,
31
+ createGetTypedCmd,
32
+ callCmdImpl,
33
+ getTypedCmdImpl
34
+ } from "./libs/launcher/command-typed.js";
27
35
  export { runMain } from "./libs/launcher/launcher-alias.js";
28
36
  export {
29
37
  defineCommand,
30
38
  showUsage,
31
39
  createCli,
32
40
  defineArgs,
33
- runCmd,
34
- runCmdWithSubcommands
41
+ runCmdWithSubcommands,
42
+ runCmd
35
43
  } from "./libs/launcher/launcher-mod.js";
36
- export { loadCommand } from "./libs/launcher/run-command.js";
37
44
  export { addCompletions } from "./libs/launcher/trpc-orpc-support/completions.js";
38
45
  export {
39
46
  CliValidationError,
@@ -43,9 +50,7 @@ export {
43
50
  TrpcCommand,
44
51
  parseRouter,
45
52
  createRpcCli,
46
- z,
47
- trpcServer,
48
- zod
53
+ z
49
54
  } from "./libs/launcher/trpc-orpc-support/index.js";
50
55
  export {
51
56
  flattenedProperties,
package/package.json CHANGED
@@ -3,10 +3,10 @@
3
3
  "@clack/prompts": "^0.11.0",
4
4
  "@figliolia/chalk-animation": "^1.0.4",
5
5
  "@inquirer/prompts": "^7.7.1",
6
- "@orpc/server": "^1.7.4",
6
+ "@orpc/server": "^1.7.5",
7
7
  "@reliverse/pathkit": "^1.3.4",
8
8
  "@reliverse/reliarg": "^1.0.3",
9
- "@reliverse/relico": "^1.1.2",
9
+ "@reliverse/relico": "^1.2.0",
10
10
  "@reliverse/relifso": "^1.4.5",
11
11
  "@reliverse/relinka": "^1.5.3",
12
12
  "@reliverse/runtime": "^1.0.3",
@@ -17,11 +17,11 @@
17
17
  "cli-spinners": "^3.2.0",
18
18
  "commander": "^14.0.0",
19
19
  "detect-package-manager": "^3.0.2",
20
- "effect": "^3.17.1",
20
+ "effect": "^3.17.2",
21
21
  "enquirer": "^2.4.1",
22
22
  "figlet": "^1.8.2",
23
23
  "gradient-string": "^3.0.0",
24
- "jiti": "^2.5.0",
24
+ "jiti": "^2.5.1",
25
25
  "json-schema": "^0.4.0",
26
26
  "log-update": "^6.1.0",
27
27
  "node-emoji": "^2.2.0",
@@ -36,7 +36,7 @@
36
36
  "tsx": "^4.20.3",
37
37
  "valibot": "^1.1.0",
38
38
  "wrap-ansi": "^9.0.0",
39
- "zod": "^4.0.7",
39
+ "zod": "^4.0.10",
40
40
  "zod-to-json-schema": "^3.24.6"
41
41
  },
42
42
  "description": "@reliverse/rempts is a modern, type-safe toolkit for building delightful cli experiences. it's fast, flexible, and made for developer happiness. file-based commands keep things simple.",
@@ -44,7 +44,7 @@
44
44
  "license": "MIT",
45
45
  "name": "@reliverse/rempts",
46
46
  "type": "module",
47
- "version": "1.7.41",
47
+ "version": "1.7.43",
48
48
  "author": "reliverse",
49
49
  "bugs": {
50
50
  "email": "blefnk@gmail.com",