pejay-ui 1.3.3 → 1.3.5

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
@@ -1,165 +1,115 @@
1
- # pejay-ui CLI Commands
1
+ # pejay-ui
2
2
 
3
3
  A lightweight CLI tool to initialize, add, and remove React UI components in your projects.
4
4
 
5
- ## Commands
5
+ ## Core Commands
6
6
 
7
7
  ### 1. Initialize Configuration
8
- Initialize the configuration file `pejay-ui.json` in the root of your project.
9
8
  ```bash
10
9
  npx pejay-ui init
11
10
  ```
12
11
 
13
12
  ### 2. Add Component
14
- Download and install a component, automatically setting up its utilities (like `cn`) and resolving component-to-component dependencies.
15
13
  ```bash
16
- npx pejay-ui add <component-name>
14
+ npx pejay-ui add <component-name-or-category> [options]
15
+ ```
16
+
17
+ **Options:**
18
+ - `--all`: Install all components in the specified category.
19
+ - `--select`: Interactively select which components to install from the specified category.
20
+
21
+ **Examples:**
22
+ - Install a single component directly:
23
+ ```bash
24
+ npx pejay-ui add form/input
25
+ ```
26
+ - Install all components in a category (e.g., `form`):
27
+ ```bash
28
+ npx pejay-ui add form --all
29
+ ```
30
+ - Select specific components to install from a category (e.g., `form`):
31
+ ```bash
32
+ npx pejay-ui add form --select
33
+ ```
34
+ *(Note: Running `npx pejay-ui add <category>` without options will default to the interactive selection prompt).*
35
+
36
+ **Automatic Exports (Auto-Indexing):**
37
+ Installing components automatically generates or updates `index.ts` (or `index.js`) files at:
38
+ 1. The category level (e.g., `src/pejay-ui/components/form/index.ts`)
39
+ 2. The global components level (`src/pejay-ui/components/index.ts`)
40
+
41
+ This allows you to easily import multiple components:
42
+ ```typescript
43
+ import { Input, Checkbox, AmountInput } from "@/pejay-ui/components";
17
44
  ```
18
- *Example:* `npx pejay-ui add button` or `npx pejay-ui add form/date-picker`
19
45
 
20
46
  ### 3. Remove Component
21
- Safely delete a component's files, and clean up any unused utilities or package dependencies that were installed with it.
22
47
  ```bash
23
48
  npx pejay-ui remove <component-name>
24
49
  ```
25
- *Example:* `npx pejay-ui remove button`
26
50
 
27
- ---
51
+ ### 4. Check Components Status
52
+ ```bash
53
+ npx pejay-ui status
54
+ ```
28
55
 
29
- ## Available Components
56
+ Lists all available components categorized, showing their local installation status:
57
+ - Installed components are marked with a green `[✔]`.
58
+ - Uninstalled components are marked with `[ ]`.
30
59
 
31
- Below is the list of components you can add. Each has a copyable command block with a working native copy button on GitHub and NPM:
60
+ ---
32
61
 
33
- ### Buttons
62
+ ## Available Components & Scaffolds
34
63
 
35
- * **`button`**: Premium interactive button supporting multiple variants (solid, soft, ghost), loaders, and custom hover tooltips.
36
- ```bash
37
- npx pejay-ui add button
38
- ```
64
+ ### Buttons
65
+ ```bash
66
+ npx pejay-ui add button
67
+ ```
39
68
 
40
69
  ### Form Inputs
41
-
42
- * **`form/input`**: Standard text input field with validation, labels, and error messaging.
43
- ```bash
44
- npx pejay-ui add form/input
45
- ```
46
- * **`form/amount-input`**: Numeric input configured for currency entry with symbol prefixes and formatting.
47
- ```bash
48
- npx pejay-ui add form/amount-input
49
- ```
50
- * **`form/checkbox`**: Styled single checkbox input.
51
- ```bash
52
- npx pejay-ui add form/checkbox
53
- ```
54
- * **`form/checkbox-group`**: Group of checkboxes managing single or multiple selection states with item indices.
55
- ```bash
56
- npx pejay-ui add form/checkbox-group
57
- ```
58
- * **`form/email-input`**: Dedicated input for email addresses with prefix icon.
59
- ```bash
60
- npx pejay-ui add form/email-input
61
- ```
62
- * **`form/file-input`**: Premium dropzone-style file upload component supporting drag-and-drop and progress/preview states.
63
- ```bash
64
- npx pejay-ui add form/file-input
65
- ```
66
- * **`form/number-input`**: Input field for numerical values with increment/decrement steppers.
67
- ```bash
68
- npx pejay-ui add form/number-input
69
- ```
70
- * **`form/password-input`**: Secure text input with eye icon toggle to show/hide the password.
71
- ```bash
72
- npx pejay-ui add form/password-input
73
- ```
74
- * **`form/phone-input`**: Formatted input field for telephone numbers.
75
- ```bash
76
- npx pejay-ui add form/phone-input
77
- ```
78
- * **`form/radio`**: Styled radio selection dot.
79
- ```bash
80
- npx pejay-ui add form/radio
81
- ```
82
- * **`form/radio-group`**: Group of mutually exclusive radio options.
83
- ```bash
84
- npx pejay-ui add form/radio-group
85
- ```
86
- * **`form/range-slider`**: Slider controls for choosing values from a numeric range.
87
- ```bash
88
- npx pejay-ui add form/range-slider
89
- ```
90
- * **`form/switch`**: Styled toggle switch representing boolean options.
91
- ```bash
92
- npx pejay-ui add form/switch
93
- ```
94
- * **`form/textarea`**: Multiline text area input with character counter/limit indicators.
95
- ```bash
96
- npx pejay-ui add form/textarea
97
- ```
98
- * **`form/url-input`**: Styled input field specifically formatted for web addresses/links.
99
- ```bash
100
- npx pejay-ui add form/url-input
101
- ```
70
+ ```bash
71
+ npx pejay-ui add form/input
72
+ npx pejay-ui add form/amount-input
73
+ npx pejay-ui add form/checkbox
74
+ npx pejay-ui add form/checkbox-group
75
+ npx pejay-ui add form/email-input
76
+ npx pejay-ui add form/file-input
77
+ npx pejay-ui add form/number-input
78
+ npx pejay-ui add form/password-input
79
+ npx pejay-ui add form/phone-input
80
+ npx pejay-ui add form/radio
81
+ npx pejay-ui add form/radio-group
82
+ npx pejay-ui add form/range-slider
83
+ npx pejay-ui add form/switch
84
+ npx pejay-ui add form/textarea
85
+ npx pejay-ui add form/url-input
86
+ ```
102
87
 
103
88
  ### Date & Time Pickers
104
-
105
- * **`form/date-picker`**: Calendar-based date selector popover with inline month/year dropdowns.
106
- ```bash
107
- npx pejay-ui add form/date-picker
108
- ```
109
- * **`form/date-range-picker`**: Date range selector to pick start and end dates with highlight ranges.
110
- ```bash
111
- npx pejay-ui add form/date-range-picker
112
- ```
113
- * **`form/time-picker`**: Dropdown component for picking specific hours, minutes, and AM/PM.
114
- ```bash
115
- npx pejay-ui add form/time-picker
116
- ```
117
- * **`form/time-range-picker`**: Popover time selector for configuring custom duration intervals.
118
- ```bash
119
- npx pejay-ui add form/time-range-picker
120
- ```
89
+ ```bash
90
+ npx pejay-ui add form/date-picker
91
+ npx pejay-ui add form/date-range-picker
92
+ npx pejay-ui add form/time-picker
93
+ npx pejay-ui add form/time-range-picker
94
+ ```
121
95
 
122
96
  ### Dropdowns & Selects
123
-
124
- * **`dropdown/select-input`**: Elegant single-select searchable dropdown input.
125
- ```bash
126
- npx pejay-ui add dropdown/select-input
127
- ```
128
- * **`dropdown/multiselect-input`**: Searchable multiselect dropdown which renders selected options as dismissible tag pills.
129
- ```bash
130
- npx pejay-ui add dropdown/multiselect-input
131
- ```
97
+ ```bash
98
+ npx pejay-ui add dropdown/select-input
99
+ npx pejay-ui add dropdown/multiselect-input
100
+ ```
132
101
 
133
102
  ### Layouts
134
-
135
- * **`layouts/lv1`**: A responsive, collapsible sidebar-based application layout.
136
- ```bash
137
- npx pejay-ui add layouts/lv1
138
- ```
103
+ ```bash
104
+ npx pejay-ui add layouts/lv1
105
+ ```
139
106
 
140
107
  ### Scaffolds & Templates
141
-
142
- * **`tanstack-query-client`**: Bare-bone TanStack Query client and context provider setup, copied directly into your project's `src/tanstack-query/`.
143
- ```bash
144
- npx pejay-ui add tanstack-query-client
145
- ```
146
- * **`react-router-client`**: Bare-bone React Router client layout, routing structure, and route guard setup, copied into `src/react-router/`.
147
- ```bash
148
- npx pejay-ui add react-router-client
149
- ```
150
- * **`tanstack-router-client`**: TanStack Router setup with layouts, route guards, and file-based route stubs, copied into `src/tanstack-router/`.
151
- ```bash
152
- npx pejay-ui add tanstack-router-client
153
- ```
154
- * **`axios-client`**: Axios instance with interceptors, request helpers, and a sample API module, copied into `src/axios/`.
155
- ```bash
156
- npx pejay-ui add axios-client
157
- ```
158
- * **`redux-store-client`**: Redux Toolkit store setup with `redux-persist`, reducers, slices, and selectors, copied into `src/redux-store/`.
159
- ```bash
160
- npx pejay-ui add redux-store-client
161
- ```
162
- * **`rtk-query-client`**: RTK Query base API with `fetchBaseQuery`, tag management, middleware, and a sample endpoint, copied into `src/rtk-query/`.
163
- ```bash
164
- npx pejay-ui add rtk-query-client
165
- ```
108
+ ```bash
109
+ npx pejay-ui add tanstack-query-client
110
+ npx pejay-ui add react-router-client
111
+ npx pejay-ui add tanstack-router-client
112
+ npx pejay-ui add axios-client
113
+ npx pejay-ui add redux-store-client
114
+ npx pejay-ui add rtk-query-client
115
+ ```
package/bin/cli.js CHANGED
@@ -74,7 +74,9 @@ program
74
74
  program
75
75
  .command("add <component>")
76
76
  .description("Add a component to your project")
77
- .action(async (component) => {
77
+ .option("--all", "Add all components in the category")
78
+ .option("--select", "Select specific components from the category to add")
79
+ .action(async (component, options) => {
78
80
  try {
79
81
  const cwd = process.cwd();
80
82
  const configPath = path.join(cwd, "pejay-ui.json");
@@ -95,6 +97,46 @@ program
95
97
  const registry = await fs.readJSON(registryPath);
96
98
  const isTsProject = await fs.pathExists(path.join(cwd, "tsconfig.json"));
97
99
 
100
+ // Determine which components to install
101
+ let selectedComponents = [];
102
+
103
+ // Check if it's a category
104
+ const categoryComponents = Object.keys(registry).filter(
105
+ (key) => registry[key].category === component
106
+ );
107
+
108
+ if (categoryComponents.length > 0) {
109
+ if (options.all) {
110
+ selectedComponents = categoryComponents;
111
+ } else {
112
+ // Dynamic prompt using inquirer checkbox for --select or when no flag is specified for category
113
+ const answers = await prompt([
114
+ {
115
+ type: "checkbox",
116
+ name: "components",
117
+ message: `Select components from category "${component}" to add:`,
118
+ choices: categoryComponents.map((key) => ({
119
+ name: `${registry[key].name} (${key})`,
120
+ value: key,
121
+ })),
122
+ },
123
+ ]);
124
+ selectedComponents = answers.components;
125
+ if (selectedComponents.length === 0) {
126
+ console.log("No components selected. Exiting.");
127
+ process.exit(0);
128
+ }
129
+ }
130
+ } else {
131
+ // Not a category, treat as a single component key
132
+ if (!registry[component]) {
133
+ console.error(`Error: Component or Category '${component}' not found in registry.`);
134
+ console.log(`Available categories/components: ${Array.from(new Set(Object.values(registry).map(c => c.category).filter(Boolean))).join(", ")} or ${Object.keys(registry).join(", ")}`);
135
+ process.exit(1);
136
+ }
137
+ selectedComponents = [component];
138
+ }
139
+
98
140
  // Track all components to install (including dependencies) in topological/order of dependencies
99
141
  const installQueue = [];
100
142
  const visited = new Set();
@@ -106,7 +148,6 @@ program
106
148
  const compData = registry[compName];
107
149
  if (!compData) {
108
150
  console.error(`Error: Component '${compName}' not found in registry.`);
109
- console.log(`Available components: ${Object.keys(registry).join(", ")}`);
110
151
  process.exit(1);
111
152
  }
112
153
 
@@ -120,13 +161,15 @@ program
120
161
  installQueue.push(compName);
121
162
  };
122
163
 
123
- resolveDependencies(component);
164
+ for (const comp of selectedComponents) {
165
+ resolveDependencies(comp);
166
+ }
124
167
 
125
168
  console.log("\n🚀 Starting installation...\n");
126
169
 
127
170
  for (const compToInstall of installQueue) {
128
- // Skip if already marked as installed in config (unless it is the main component requested)
129
- if (config.installed?.[compToInstall] && compToInstall !== component) {
171
+ // Skip if already marked as installed in config (unless it is one of the explicitly requested components)
172
+ if (config.installed?.[compToInstall] && !selectedComponents.includes(compToInstall)) {
130
173
  console.log(`Component '${compToInstall}' is already installed. Skipping dependency installation.`);
131
174
  continue;
132
175
  }
@@ -293,6 +336,56 @@ program
293
336
  }
294
337
  }
295
338
 
339
+ // 3.5 Automatically generate/update category-level and global index.ts/index.js files
340
+ if (componentData.category && !["scaffold", "scaffolds", "script", "scripts"].includes(componentData.category.toLowerCase())) {
341
+ const indexExt = isTsProject ? "ts" : "js";
342
+ const filesInDir = await fs.readdir(targetDir);
343
+ const exportableFiles = [];
344
+
345
+ for (const file of filesInDir) {
346
+ const filePath = path.join(targetDir, file);
347
+ const stat = await fs.stat(filePath);
348
+ if (stat.isFile()) {
349
+ const ext = path.extname(file);
350
+ const name = path.basename(file, ext);
351
+ if ((ext === ".tsx" || ext === ".ts" || ext === ".jsx" || ext === ".js") && name !== "index") {
352
+ exportableFiles.push(name);
353
+ }
354
+ }
355
+ }
356
+
357
+ if (exportableFiles.length > 0) {
358
+ exportableFiles.sort();
359
+ const indexFilePath = path.join(targetDir, `index.${indexExt}`);
360
+ const exportLines = exportableFiles.map(name => `export * from "./${name}";`);
361
+ await fs.writeFile(indexFilePath, exportLines.join("\n") + "\n", "utf-8");
362
+ console.log(`✅ Updated index.${indexExt} in ${path.relative(cwd, targetDir)}`);
363
+
364
+ // Also update the global components index file
365
+ const componentsDir = path.dirname(targetDir); // src/pejay-ui/components
366
+ if (await fs.pathExists(componentsDir)) {
367
+ const categories = await fs.readdir(componentsDir);
368
+ const validCategories = [];
369
+ for (const cat of categories) {
370
+ const catDir = path.join(componentsDir, cat);
371
+ const catStat = await fs.stat(catDir);
372
+ if (catStat.isDirectory()) {
373
+ if (await fs.pathExists(path.join(catDir, `index.ts`)) || await fs.pathExists(path.join(catDir, `index.js`))) {
374
+ validCategories.push(cat);
375
+ }
376
+ }
377
+ }
378
+ if (validCategories.length > 0) {
379
+ validCategories.sort();
380
+ const globalIndexFile = path.join(componentsDir, `index.${indexExt}`);
381
+ const globalExportLines = validCategories.map(cat => `export * from "./${cat}";`);
382
+ await fs.writeFile(globalIndexFile, globalExportLines.join("\n") + "\n", "utf-8");
383
+ console.log(`✅ Updated global index.${indexExt} in ${path.relative(cwd, componentsDir)}`);
384
+ }
385
+ }
386
+ }
387
+ }
388
+
296
389
  // 4. Update State tracking in config
297
390
  config.installed = config.installed || {};
298
391
  config.installed[compToInstall] = {
@@ -358,6 +451,73 @@ program
358
451
  }
359
452
  }
360
453
 
454
+ // 1.5 Update index files
455
+ if (componentData.category && !["scaffold", "scaffolds", "script", "scripts"].includes(componentData.category.toLowerCase())) {
456
+ const isTsProject = await fs.pathExists(path.join(cwd, "tsconfig.json"));
457
+ const targetDir = path.join(cwd, config.baseDir, "components", componentData.category);
458
+ const indexExt = isTsProject ? "ts" : "js";
459
+
460
+ if (await fs.pathExists(targetDir)) {
461
+ const filesInDir = await fs.readdir(targetDir);
462
+ const exportableFiles = [];
463
+
464
+ for (const file of filesInDir) {
465
+ const filePath = path.join(targetDir, file);
466
+ const stat = await fs.stat(filePath);
467
+ if (stat.isFile()) {
468
+ const ext = path.extname(file);
469
+ const name = path.basename(file, ext);
470
+ if ((ext === ".tsx" || ext === ".ts" || ext === ".jsx" || ext === ".js") && name !== "index") {
471
+ exportableFiles.push(name);
472
+ }
473
+ }
474
+ }
475
+
476
+ const indexFilePath = path.join(targetDir, `index.${indexExt}`);
477
+ if (exportableFiles.length > 0) {
478
+ exportableFiles.sort();
479
+ const exportLines = exportableFiles.map(name => `export * from "./${name}";`);
480
+ await fs.writeFile(indexFilePath, exportLines.join("\n") + "\n", "utf-8");
481
+ console.log(`✅ Updated index.${indexExt} in ${path.relative(cwd, targetDir)}`);
482
+ } else {
483
+ // No files left, delete the category index file
484
+ if (await fs.pathExists(indexFilePath)) {
485
+ await fs.remove(indexFilePath);
486
+ console.log(`🗑️ Removed empty index.${indexExt} in ${path.relative(cwd, targetDir)}`);
487
+ }
488
+ }
489
+
490
+ // Also update the global components index file
491
+ const componentsDir = path.dirname(targetDir);
492
+ if (await fs.pathExists(componentsDir)) {
493
+ const categories = await fs.readdir(componentsDir);
494
+ const validCategories = [];
495
+ for (const cat of categories) {
496
+ const catDir = path.join(componentsDir, cat);
497
+ const catStat = await fs.stat(catDir);
498
+ if (catStat.isDirectory()) {
499
+ if (await fs.pathExists(path.join(catDir, `index.ts`)) || await fs.pathExists(path.join(catDir, `index.js`))) {
500
+ validCategories.push(cat);
501
+ }
502
+ }
503
+ }
504
+ const globalIndexFile = path.join(componentsDir, `index.${indexExt}`);
505
+ if (validCategories.length > 0) {
506
+ validCategories.sort();
507
+ const globalExportLines = validCategories.map(cat => `export * from "./${cat}";`);
508
+ await fs.writeFile(globalIndexFile, globalExportLines.join("\n") + "\n", "utf-8");
509
+ console.log(`✅ Updated global index.${indexExt} in ${path.relative(cwd, componentsDir)}`);
510
+ } else {
511
+ // No categories left with index files, remove the global index
512
+ if (await fs.pathExists(globalIndexFile)) {
513
+ await fs.remove(globalIndexFile);
514
+ console.log(`🗑️ Removed empty global index.${indexExt} in ${path.relative(cwd, componentsDir)}`);
515
+ }
516
+ }
517
+ }
518
+ }
519
+ }
520
+
361
521
  // 2. Build Utility Usage Map
362
522
  const utilityUsage = {};
363
523
  for (const [compName, compInfo] of Object.entries(config.installed)) {
@@ -452,4 +612,86 @@ program
452
612
  }
453
613
  });
454
614
 
615
+ /* =============================
616
+ STATUS COMMAND
617
+ ============================= */
618
+ program
619
+ .command("status")
620
+ .description("List all available components and check their installation status")
621
+ .action(async () => {
622
+ try {
623
+ const cwd = process.cwd();
624
+ const configPath = path.join(cwd, "pejay-ui.json");
625
+
626
+ let config = { installed: {} };
627
+ let hasConfig = true;
628
+
629
+ if (!await fs.pathExists(configPath)) {
630
+ hasConfig = false;
631
+ } else {
632
+ try {
633
+ config = await fs.readJSON(configPath);
634
+ } catch (e) {
635
+ hasConfig = false;
636
+ }
637
+ }
638
+
639
+ const registryPath = path.join(packageRoot, "registry.json");
640
+ if (!await fs.pathExists(registryPath)) {
641
+ console.error("Error: Registry configuration not found.");
642
+ process.exit(1);
643
+ }
644
+
645
+ const registry = await fs.readJSON(registryPath);
646
+
647
+ // Terminal styling colors
648
+ const GREEN = "\x1b[32m";
649
+ const CYAN = "\x1b[36m";
650
+ const DIM = "\x1b[2m";
651
+ const RESET = "\x1b[0m";
652
+ const YELLOW = "\x1b[33m";
653
+
654
+ console.log(`\n🔍 ${CYAN}pejay-ui Components Status:${RESET}\n`);
655
+
656
+ if (!hasConfig) {
657
+ console.log(`${YELLOW}Note: pejay-ui.json not found. Initialize first via 'npx pejay-ui init'.${RESET}`);
658
+ console.log(`${YELLOW}Showing all components as uninstalled.${RESET}\n`);
659
+ }
660
+
661
+ // Group registry items by category
662
+ const categories = {};
663
+ for (const [key, compData] of Object.entries(registry)) {
664
+ const category = compData.category || "other";
665
+ if (!categories[category]) {
666
+ categories[category] = [];
667
+ }
668
+ categories[category].push({
669
+ key,
670
+ name: compData.name,
671
+ installed: !!config.installed?.[key]
672
+ });
673
+ }
674
+
675
+ // Print categories and components sorted alphabetically
676
+ const sortedCategoryNames = Object.keys(categories).sort();
677
+ for (const cat of sortedCategoryNames) {
678
+ console.log(`${CYAN}Category: ${cat}${RESET}`);
679
+ const comps = categories[cat];
680
+ comps.sort((a, b) => a.name.localeCompare(b.name));
681
+
682
+ for (const comp of comps) {
683
+ if (comp.installed) {
684
+ console.log(` ${GREEN}[✔] ${comp.name}${RESET} ${DIM}(${comp.key})${RESET}`);
685
+ } else {
686
+ console.log(` [ ] ${comp.name} ${DIM}(${comp.key})${RESET}`);
687
+ }
688
+ }
689
+ console.log(); // blank line between categories
690
+ }
691
+
692
+ } catch (err) {
693
+ console.error("\n❌ Status display failed\n", err);
694
+ }
695
+ });
696
+
455
697
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pejay-ui",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "type": "module",
5
5
  "description": "react ui components",
6
6
  "bin": {
package/registry.json CHANGED
@@ -46,7 +46,7 @@
46
46
  "lucide-react",
47
47
  "@floating-ui/react"
48
48
  ],
49
- "dependencies": ["select-dropdown/select-input"]
49
+ "dependencies": ["dropdown/select-input"]
50
50
  },
51
51
  "form/date-range-picker": {
52
52
  "name": "DateRangePicker",
@@ -59,7 +59,7 @@
59
59
  "lucide-react",
60
60
  "@floating-ui/react"
61
61
  ],
62
- "dependencies": ["select-dropdown/select-input"]
62
+ "dependencies": ["dropdown/select-input"]
63
63
  },
64
64
  "form/email-input": {
65
65
  "name": "EmailInput",
@@ -143,7 +143,7 @@
143
143
  "lucide-react",
144
144
  "@floating-ui/react"
145
145
  ],
146
- "dependencies": ["select-dropdown/select-input"]
146
+ "dependencies": ["dropdown/select-input"]
147
147
  },
148
148
  "form/time-range-picker": {
149
149
  "name": "TimeRangePicker",
@@ -156,7 +156,7 @@
156
156
  "lucide-react",
157
157
  "@floating-ui/react"
158
158
  ],
159
- "dependencies": ["select-dropdown/select-input"]
159
+ "dependencies": ["dropdown/select-input"]
160
160
  },
161
161
  "form/url-input": {
162
162
  "name": "UrlInput",