airyhooks 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -53
  3. package/dist/commands/add.js +70 -22
  4. package/dist/commands/add.js.map +1 -1
  5. package/dist/commands/entry.js +27 -0
  6. package/dist/commands/entry.js.map +1 -0
  7. package/dist/commands/init.js +31 -8
  8. package/dist/commands/init.js.map +1 -1
  9. package/dist/commands/list.js +1 -1
  10. package/dist/commands/list.js.map +1 -1
  11. package/dist/index.js +9 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/utils/config.js +7 -3
  14. package/dist/utils/config.js.map +1 -1
  15. package/dist/utils/get-file-extension.js +12 -0
  16. package/dist/utils/get-file-extension.js.map +1 -0
  17. package/dist/utils/get-hook-filename.js +12 -0
  18. package/dist/utils/get-hook-filename.js.map +1 -0
  19. package/dist/utils/get-hook-template.js +9 -1071
  20. package/dist/utils/get-hook-template.js.map +1 -1
  21. package/dist/utils/hook-templates.js +3386 -0
  22. package/dist/utils/hook-templates.js.map +1 -0
  23. package/dist/utils/registry.js +40 -0
  24. package/dist/utils/registry.js.map +1 -1
  25. package/package.json +9 -4
  26. package/dist/commands/add.d.ts +0 -2
  27. package/dist/commands/add.d.ts.map +0 -1
  28. package/dist/commands/init.d.ts +0 -2
  29. package/dist/commands/init.d.ts.map +0 -1
  30. package/dist/commands/list.d.ts +0 -2
  31. package/dist/commands/list.d.ts.map +0 -1
  32. package/dist/index.d.ts +0 -3
  33. package/dist/index.d.ts.map +0 -1
  34. package/dist/utils/config.d.ts +0 -6
  35. package/dist/utils/config.d.ts.map +0 -1
  36. package/dist/utils/get-hook-template.d.ts +0 -2
  37. package/dist/utils/get-hook-template.d.ts.map +0 -1
  38. package/dist/utils/registry.d.ts +0 -7
  39. package/dist/utils/registry.d.ts.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Leif Arriens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,21 +1,15 @@
1
1
  # airyhooks
2
2
 
3
- Add production-ready React hooks directly to your project—no package installation required.
3
+ ![airyhooks logo](https://raw.githubusercontent.com/leifarriens/airyhooks/HEAD/media/logo_embed.png)
4
4
 
5
- airyhooks is a CLI tool that lets you add battle-tested, TypeScript-first React hooks directly to your codebase. Instead of installing a package, you copy exactly what you need. This gives you complete control: modify hooks for your use case, avoid dependency bloat, and eliminate version conflicts.
5
+ Add production-ready zero-dependency React hooks without package installation directly to your project.
6
+
7
+ `airyhooks` is a CLI tool that lets you add tested, TypeScript-first React hooks directly to your codebase. Instead of installing a package, you copy exactly what you need. This gives you complete control: modify hooks for your use case, avoid dependency bloat, and eliminate version conflicts.
6
8
 
7
9
  ```bash
8
- pnpm dlx airyhooks@latest add useDebounce
10
+ pnpm dlx airyhooks
9
11
  ```
10
12
 
11
- ## Why airyhooks?
12
-
13
- - **Zero Dependencies**: Hooks only depend on React—nothing else
14
- - **Full Ownership**: Code lives in your repo; customize freely
15
- - **TypeScript Native**: Complete type safety with generics
16
- - **Battle-Tested**: 50+ tests, 94%+ coverage
17
- - **One Command**: Add hooks instantly with the CLI
18
-
19
13
  ## 🚀 Quick Start
20
14
 
21
15
  ### 1. Initialize
@@ -23,17 +17,26 @@ pnpm dlx airyhooks@latest add useDebounce
23
17
  Create the configuration file and set your hooks directory:
24
18
 
25
19
  ```bash
26
- pnpm dlx airyhooks@latest init
20
+ pnpm dlx airyhooks init
27
21
  ```
28
22
 
29
23
  This creates `airyhooks.json` in your project root and prompts you for the hooks directory path (default: `./hooks`).
30
24
 
31
- ### 2. Add a Hook
25
+ > [!NOTE]
26
+ > You can use `airyhooks` without initialization. It will use the [default configuration](#-configuration).
32
27
 
33
- Add any hook to your project:
28
+ ### 2. Start Adding Hooks
29
+
30
+ Pick from all available hooks and add them to your project:
34
31
 
35
32
  ```bash
36
- pnpm dlx airyhooks@latest add useDebounce
33
+ pnpm dlx airyhooks
34
+ ```
35
+
36
+ Or add a specific hook directly:
37
+
38
+ ```bash
39
+ pnpm dlx airyhooks add useDebounce
37
40
  ```
38
41
 
39
42
  This creates the following structure:
@@ -65,6 +68,38 @@ export function SearchComponent() {
65
68
  }
66
69
  ```
67
70
 
71
+ ## 📚 Available Hooks
72
+
73
+ | Hook | Description |
74
+ | ------------------------- | ------------------------------------------------------- |
75
+ | `useClickAway` | Detect clicks outside of an element |
76
+ | `useCopyToClipboard` | Copy text to clipboard with status feedback |
77
+ | `useCounter` | Manage numeric state with increment/decrement/reset/set |
78
+ | `useDebounce` | Debounce a value with a specified delay |
79
+ | `useDebouncedCallback` | Debounce a callback function with cancel support |
80
+ | `useDocumentTitle` | Dynamically update the document title |
81
+ | `useEventListener` | Attach event listeners with automatic cleanup |
82
+ | `useFetch` | Fetch data with loading, error, and refetch support |
83
+ | `useHover` | Track mouse hover state on elements |
84
+ | `useIntersectionObserver` | Track element visibility in viewport |
85
+ | `useInterval` | Call a callback at specified intervals |
86
+ | `useIsClient` | Check if code is running on client (SSR-safe) |
87
+ | `useKeyPress` | Detect specific keyboard key presses |
88
+ | `useLocalStorage` | Sync state with localStorage |
89
+ | `useLockBodyScroll` | Prevent body scrolling (useful for modals) |
90
+ | `useMeasure` | Measure element dimensions with ResizeObserver |
91
+ | `useMedia` | React to CSS media query changes |
92
+ | `useMount` | Call a callback on component mount |
93
+ | `usePrevious` | Track previous state or props value |
94
+ | `useScroll` | Track scroll position of element or window |
95
+ | `useSessionStorage` | Sync state with sessionStorage |
96
+ | `useThrottle` | Throttle a value to update at most once per interval |
97
+ | `useThrottledCallback` | Throttle a callback with leading/trailing options |
98
+ | `useTimeout` | Call a callback after a timeout |
99
+ | `useToggle` | Toggle a boolean value with convenient handlers |
100
+ | `useUnmount` | Call a callback on component unmount |
101
+ | `useWindowSize` | Track window dimensions |
102
+
68
103
  ## 📖 Commands
69
104
 
70
105
  ### `airyhooks init`
@@ -72,9 +107,19 @@ export function SearchComponent() {
72
107
  Initialize airyhooks in your project. Creates `airyhooks.json` configuration file and prompts for your hooks directory path.
73
108
 
74
109
  ```bash
75
- pnpm dlx airyhooks@latest init
110
+ pnpm dlx airyhooks init
111
+ # or
112
+ npx airyhooks init
113
+ ```
114
+
115
+ ### `airyhooks`
116
+
117
+ Run the interactive hook picker to browse and add hooks to your project.
118
+
119
+ ```bash
120
+ pnpm dlx airyhooks
76
121
  # or
77
- npx airyhooks@latest init
122
+ npx airyhooks
78
123
  ```
79
124
 
80
125
  ### `airyhooks add <hook-name>`
@@ -82,39 +127,27 @@ npx airyhooks@latest init
82
127
  Add a specific hook to your project. Creates the hook directory with TypeScript files.
83
128
 
84
129
  ```bash
85
- pnpm dlx airyhooks@latest add useDebounce
130
+ pnpm dlx airyhooks add useDebounce
86
131
  ```
87
132
 
88
- ### `airyhooks list`
133
+ #### Options
89
134
 
90
- List all available hooks with descriptions.
135
+ - `--raw` - Output only the raw hook template to console (no files created)
136
+
137
+ > [!TIP]
138
+ > Use `--raw` to pipe the hook directly to a file or integrate with other tools:
91
139
 
92
140
  ```bash
93
- pnpm dlx airyhooks@latest list
141
+ pnpm dlx airyhooks add useDebounce --raw > useDebounce.ts
94
142
  ```
95
143
 
96
- ## 📚 Available Hooks
144
+ ### `airyhooks list`
145
+
146
+ List all available hooks with descriptions.
97
147
 
98
- | Hook | Description |
99
- | ------------------- | ------------------------------------------------------- |
100
- | `useDebounce` | Debounce a value with a specified delay |
101
- | `useThrottle` | Throttle a value to update at most once per interval |
102
- | `useLocalStorage` | Sync state with localStorage |
103
- | `useSessionStorage` | Sync state with sessionStorage |
104
- | `usePrevious` | Track previous state or props value |
105
- | `useToggle` | Toggle a boolean value with convenient handlers |
106
- | `useBoolean` | Boolean state with setTrue, setFalse, and toggle |
107
- | `useMount` | Call a callback on component mount |
108
- | `useUnmount` | Call a callback on component unmount |
109
- | `useInterval` | Call a callback at specified intervals |
110
- | `useTimeout` | Call a callback after a timeout |
111
- | `useClickAway` | Detect clicks outside of an element |
112
- | `useWindowSize` | Track window dimensions |
113
- | `useCounter` | Manage numeric state with increment/decrement/reset/set |
114
- | `useHover` | Track mouse hover state on elements |
115
- | `useKeyPress` | Detect specific keyboard key presses |
116
- | `useMedia` | React to CSS media query changes |
117
- | `useScroll` | Track scroll position of element or window |
148
+ ```bash
149
+ pnpm dlx airyhooks list
150
+ ```
118
151
 
119
152
  ## 💡 Usage Example
120
153
 
@@ -147,11 +180,103 @@ The `airyhooks.json` file stores your configuration:
147
180
 
148
181
  ```json
149
182
  {
150
- "hooksPath": "./hooks"
183
+ "casing": "camelCase",
184
+ "hooksPath": "src/hooks",
185
+ "importExtension": "none",
186
+ "includeTests": false,
187
+ "structure": "nested"
151
188
  }
152
189
  ```
153
190
 
154
- You can manually edit this file to change the hooks directory path.
191
+ ### Options
192
+
193
+ | Option | Type | Default | Description |
194
+ | ----------------- | ------------------------------- | ------------- | ----------------------------------------------------------------- |
195
+ | `hooksPath` | `string` | `"src/hooks"` | Directory path where hooks are added |
196
+ | `casing` | `"camelCase"` \| `"kebab-case"` | `"camelCase"` | Naming convention for hook directories and files |
197
+ | `structure` | `"flat"` \| `"nested"` | `"flat"` | Directory structure for hooks |
198
+ | `importExtension` | `"none"` \| `"js"` \| `"ts"` | `"none"` | File extension used in barrel export imports |
199
+ | `includeTests` | `boolean` | `false` | Include test files next to hook implementations when adding hooks |
200
+
201
+ #### `hooksPath`
202
+
203
+ The directory where hooks will be created. Can be any valid path relative to your project root.
204
+
205
+ ```json
206
+ { "hooksPath": "src/lib/hooks" }
207
+ ```
208
+
209
+ #### `casing`
210
+
211
+ Controls the naming convention for hook directories and files:
212
+
213
+ - `"camelCase"` — Keeps the original hook name (e.g., `useDebounce/useDebounce.ts`)
214
+ - `"kebab-case"` — Converts to kebab-case (e.g., `use-debounce/use-debounce.ts`)
215
+
216
+ ```
217
+ # camelCase (default)
218
+ hooks/useDebounce/
219
+ ├── useDebounce.ts
220
+ └── index.ts
221
+
222
+ # kebab-case
223
+ hooks/use-debounce/
224
+ ├── use-debounce.ts
225
+ └── index.ts
226
+ ```
227
+
228
+ > [!TIP]
229
+ > You can override casing per-command with the `--kebab` flag: `airyhooks add useDebounce --kebab`
230
+
231
+ #### `structure`
232
+
233
+ Controls the directory structure for added hooks:
234
+
235
+ - `"flat"` — All hooks are added directly under the `hooksPath` directory.
236
+ - `"nested"` — Each hook gets its own subdirectory under `hooksPath`.
237
+
238
+ ```
239
+ # flat (default)
240
+ hooks/
241
+ ├── useDebounce.ts
242
+ └── useToggle.ts
243
+
244
+ # nested
245
+ hooks/
246
+ ├── useDebounce/
247
+ │ ├── useDebounce.ts
248
+ │ └── index.ts
249
+ └── useToggle/
250
+ ├── useToggle.ts
251
+ └── index.ts
252
+ ```
253
+
254
+ #### `importExtension`
255
+
256
+ Controls the file extension in the generated `index.ts` barrel export. Only relevant when using the `structure: nested`.
257
+
258
+ Choose based on your TypeScript configuration:
259
+
260
+ | Value | Output | When to use |
261
+ | -------- | ------------------------------------------------ | --------------------------------------------------- |
262
+ | `"none"` | `export { useDebounce } from "./useDebounce"` | `moduleResolution: "bundler"` (Vite, webpack, etc.) |
263
+ | `"js"` | `export { useDebounce } from "./useDebounce.js"` | `moduleResolution: "nodenext"` or `"node16"` |
264
+ | `"ts"` | `export { useDebounce } from "./useDebounce.ts"` | `allowImportingTsExtensions: true` in tsconfig |
265
+
266
+ #### `includeTests`
267
+
268
+ When `true`, airyhooks will also copy the test file for the hook next to the generated hook implementation. The behavior follows the configured `structure`:
269
+
270
+ - With `"nested"`, the test file is written inside the hook's subdirectory (e.g. `useDebounce/useDebounce.test.ts`).
271
+ - With `"flat"`, the test file is written directly under the `hooksPath` next to the hook file (e.g. `useDebounce.test.ts`).
272
+
273
+ You can enable this by setting it in `airyhooks.json`:
274
+
275
+ ```json
276
+ { "includeTests": true }
277
+ ```
278
+
279
+ You can also override this per-command with the CLI flag: `airyhooks add <hook-name> --include-tests`.
155
280
 
156
281
  ## 📦 Package Managers
157
282
 
@@ -159,22 +284,18 @@ airyhooks works with all major package managers:
159
284
 
160
285
  ```bash
161
286
  # pnpm
162
- pnpm dlx airyhooks@latest add useDebounce
287
+ pnpm dlx airyhooks add useDebounce
163
288
 
164
289
  # npm
165
- npx airyhooks@latest add useDebounce
290
+ npx airyhooks add useDebounce
166
291
 
167
292
  # yarn
168
- yarn dlx airyhooks@latest add useDebounce
293
+ yarn dlx airyhooks add useDebounce
169
294
 
170
295
  # bun
171
- bunx airyhooks@latest add useDebounce
296
+ bunx airyhooks add useDebounce
172
297
  ```
173
298
 
174
- ## 📄 License
175
-
176
- MIT
177
-
178
299
  ---
179
300
 
180
- **Ready to use?** Run `pnpm dlx airyhooks@latest init` to get started!
301
+ **Ready to use?** Run `pnpm dlx airyhooks init` to get started!
@@ -2,37 +2,63 @@ import fs from "fs-extra";
2
2
  import path from "node:path";
3
3
  import pc from "picocolors";
4
4
  import { getConfig } from "../utils/config.js";
5
- import { getHookTemplate } from "../utils/get-hook-template.js";
5
+ import { getFileExtension } from "../utils/get-file-extension.js";
6
+ import { getHookFileBaseName } from "../utils/get-hook-filename.js";
7
+ import { getHookTemplate, getHookTestTemplate, } from "../utils/get-hook-template.js";
6
8
  import { registry } from "../utils/registry.js";
7
- export async function add(hookName) {
9
+ export async function add(hookName, options = {}) {
10
+ const { force, kebab, raw } = options;
8
11
  const hook = registry.find((h) => h.name.toLowerCase() === hookName.toLowerCase());
9
12
  if (!hook) {
10
13
  console.log(pc.red(`✗ Hook "${hookName}" not found.`));
11
14
  console.log(pc.dim("Run `airyhooks list` to see available hooks."));
12
15
  process.exit(1);
13
16
  }
14
- const config = await getConfig();
17
+ const config = await getConfig({
18
+ ...(kebab ? { casing: "kebab-case" } : {}),
19
+ ...(options.includeTests ? { includeTests: true } : {}),
20
+ });
15
21
  const hooksDir = path.join(process.cwd(), config.hooksPath);
16
- const hookDir = path.join(hooksDir, hook.name);
17
- // Ensure hook subdirectory exists
18
- await fs.ensureDir(hookDir);
19
- // Check if hook already exists
20
- const hookFilePath = path.join(hookDir, `${hook.name}.ts`);
21
- if (await fs.pathExists(hookFilePath)) {
22
- console.log(pc.yellow(`⚠ ${hook.name} already exists. Skipping.`));
23
- return;
24
- }
25
- // Write hook implementation
22
+ const casedHookName = getHookFileBaseName(hook.name, config.casing);
23
+ const hookTargetDir = path.join(hooksDir, config.structure === "nested" ? casedHookName : "");
26
24
  const template = getHookTemplate(hook.name);
27
- await fs.writeFile(hookFilePath, template);
28
- // Write barrel export
29
- const barrelFilePath = path.join(hookDir, "index.ts");
30
- const barrelContent = `export { ${hook.name} } from "./${hook.name}.js";\n`;
31
- await fs.writeFile(barrelFilePath, barrelContent);
32
- console.log(pc.green(`✓ Added ${hook.name}`));
33
- console.log(pc.dim(` → ${path.relative(process.cwd(), hookDir)}/`));
34
- console.log(pc.dim(` ├── ${hook.name}.ts`));
35
- console.log(pc.dim(` └── index.ts`));
25
+ const testTemplate = getHookTestTemplate(hook.name);
26
+ if (!raw) {
27
+ // Ensure hook subdirectory exists
28
+ await fs.ensureDir(hookTargetDir);
29
+ const hookFilePath = path.join(hookTargetDir, `${casedHookName}.ts`);
30
+ const hookTestFilePath = path.join(hookTargetDir, `${casedHookName}.test.ts`);
31
+ // Check if hook already exists
32
+ if (!force && (await fs.pathExists(hookFilePath))) {
33
+ console.log(pc.yellow(`⚠ ${casedHookName} already exists. Skipping.`));
34
+ console.log(pc.dim("Use --force to overwrite existing hooks."));
35
+ return;
36
+ }
37
+ const barrelFilePath = path.join(hookTargetDir, "index.ts");
38
+ const hookImportExtension = getFileExtension(config.importExtension);
39
+ // Write hook implementation
40
+ await fs.writeFile(hookFilePath, template);
41
+ // Write hook test
42
+ if (config.includeTests) {
43
+ const hookImplementationImportPath = `./${hookName}.js`;
44
+ const modifiedTestTemplate = testTemplate.replace(hookImplementationImportPath, `./${hook.name}${hookImportExtension}`);
45
+ await fs.writeFile(hookTestFilePath, modifiedTestTemplate);
46
+ }
47
+ if (config.structure === "nested") {
48
+ // Write barrel file for nested structure
49
+ const barrelContent = `export { ${hook.name} } from "./${casedHookName}${hookImportExtension}";\n`;
50
+ await fs.writeFile(barrelFilePath, barrelContent);
51
+ }
52
+ logOutput({
53
+ casedHookName,
54
+ hookFunctionName: hook.name,
55
+ hookTargetDir,
56
+ ...config,
57
+ });
58
+ }
59
+ else {
60
+ console.log(pc.cyan(template));
61
+ }
36
62
  if (hook.dependencies && hook.dependencies.length > 0) {
37
63
  console.log(pc.dim(`\n Required dependencies:`));
38
64
  hook.dependencies.forEach((dep) => {
@@ -40,4 +66,26 @@ export async function add(hookName) {
40
66
  });
41
67
  }
42
68
  }
69
+ /**
70
+ * Log output to the console after adding a hook.
71
+ */
72
+ function logOutput({ casedHookName, hookFunctionName, hookTargetDir, includeTests, structure, }) {
73
+ const relativeHookDir = path.relative(process.cwd(), hookTargetDir);
74
+ console.log(pc.green(`✓ Added ${hookFunctionName}`));
75
+ if (structure === "nested") {
76
+ console.log(pc.dim(` → ${relativeHookDir}/`));
77
+ if (includeTests) {
78
+ console.log(pc.dim(` ├── ${casedHookName}.test.ts`));
79
+ }
80
+ console.log(pc.dim(` ├── ${casedHookName}.ts`));
81
+ console.log(pc.dim(` └── index.ts`));
82
+ }
83
+ else {
84
+ console.log(pc.dim(` → ${relativeHookDir}/`));
85
+ if (includeTests) {
86
+ console.log(pc.dim(` ├── ${casedHookName}.test.ts`));
87
+ }
88
+ console.log(pc.dim(` └── ${casedHookName}.ts`));
89
+ }
90
+ }
43
91
  //# sourceMappingURL=add.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import prompts from "prompts";
2
+ import { registry } from "../utils/registry.js";
3
+ import { add } from "./add.js";
4
+ export async function entry() {
5
+ const response = await prompts({
6
+ choices: registry.map((hook) => ({
7
+ description: hook.description,
8
+ title: hook.name,
9
+ value: hook.name,
10
+ })),
11
+ limit: 10,
12
+ message: "Select a hook to add:",
13
+ name: "hookName",
14
+ async suggest(input, choices) {
15
+ return Promise.resolve(choices
16
+ .filter((choice) => choice.title.toLowerCase().includes(input.toLowerCase()))
17
+ .sort((a, b) => a.title.localeCompare(b.title)));
18
+ },
19
+ type: "autocomplete",
20
+ });
21
+ const hookName = response.hookName;
22
+ if (!hookName) {
23
+ return;
24
+ }
25
+ await add(hookName);
26
+ }
27
+ //# sourceMappingURL=entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/commands/entry.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,KAAK,EAAE,IAAI,CAAC,IAAI;SACjB,CAAC,CAAC;QACH,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,uBAAuB;QAChC,IAAI,EAAE,UAAU;QAChB,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,OAAO;YAClC,OAAO,OAAO,CAAC,OAAO,CACpB,OAAO;iBACJ,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACjB,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CACzD;iBACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAClD,CAAC;QACJ,CAAC;QACD,IAAI,EAAE,cAAc;KACrB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAA8B,CAAC;IAEzD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IAED,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;AACtB,CAAC"}
@@ -2,7 +2,7 @@ import fs from "fs-extra";
2
2
  import path from "node:path";
3
3
  import pc from "picocolors";
4
4
  import prompts from "prompts";
5
- import { DEFAULT_CONFIG } from "../utils/config.js";
5
+ import { DEFAULT_CONFIG, } from "../utils/config.js";
6
6
  export async function init() {
7
7
  const configPath = path.join(process.cwd(), "airyhooks.json");
8
8
  if (await fs.pathExists(configPath)) {
@@ -17,18 +17,41 @@ export async function init() {
17
17
  return;
18
18
  }
19
19
  }
20
- const response = await prompts({
21
- initial: DEFAULT_CONFIG.hooksPath,
22
- message: "Where would you like to store your hooks?",
23
- name: "hooksPath",
24
- type: "text",
25
- });
20
+ const response = await prompts([
21
+ {
22
+ initial: DEFAULT_CONFIG.hooksPath,
23
+ message: "Where would you like to store your hooks?",
24
+ name: "hooksPath",
25
+ type: "text",
26
+ },
27
+ {
28
+ choices: [
29
+ {
30
+ description: "Use camelCase for hook file and directory names",
31
+ title: "useDebounce",
32
+ value: "camelCase",
33
+ },
34
+ {
35
+ description: "Use kebab-case for hook file and directory names",
36
+ title: "use-debounce",
37
+ value: "kebab-case",
38
+ },
39
+ ],
40
+ initial: 0,
41
+ message: "What naming convention would you like to use for your hook files and directories?",
42
+ name: "casing",
43
+ type: "select",
44
+ },
45
+ ]);
26
46
  const hooksPath = response.hooksPath;
27
- if (!hooksPath) {
47
+ const casing = response.casing;
48
+ if (!hooksPath || !casing) {
28
49
  console.log(pc.yellow("Initialization cancelled."));
29
50
  return;
30
51
  }
31
52
  const config = {
53
+ ...DEFAULT_CONFIG,
54
+ casing,
32
55
  hooksPath,
33
56
  };
34
57
  await fs.writeJson(configPath, config, { spaces: 2 });
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAwB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAE9D,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC7B,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,2CAA2C;YACpD,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B,OAAO,EAAE,cAAc,CAAC,SAAS;QACjC,OAAO,EAAE,2CAA2C;QACpD,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,MAAM;KACb,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,SAA+B,CAAC;IAE3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAoB;QAC9B,SAAS;KACV,CAAC;IAEF,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,SAAS,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAGL,cAAc,GACf,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAE9D,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC7B,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,2CAA2C;YACpD,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC7B;YACE,OAAO,EAAE,cAAc,CAAC,SAAS;YACjC,OAAO,EAAE,2CAA2C;YACpD,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,MAAM;SACb;QACD;YACE,OAAO,EAAE;gBACP;oBACE,WAAW,EAAE,iDAAiD;oBAC9D,KAAK,EAAE,aAAa;oBACpB,KAAK,EAAE,WAAW;iBACnB;gBACD;oBACE,WAAW,EAAE,kDAAkD;oBAC/D,KAAK,EAAE,cAAc;oBACrB,KAAK,EAAE,YAAY;iBACpB;aACF;YACD,OAAO,EAAE,CAAC;YACV,OAAO,EACL,mFAAmF;YACrF,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;SACf;KACF,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,SAA+B,CAAC;IAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAA4B,CAAC;IAErD,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAoB;QAC9B,GAAG,cAAc;QACjB,MAAM;QACN,SAAS;KACV,CAAC;IAEF,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,SAAS,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC"}
@@ -2,7 +2,7 @@ import pc from "picocolors";
2
2
  import { registry } from "../utils/registry.js";
3
3
  export function list() {
4
4
  console.log(pc.bold("\nAvailable hooks:\n"));
5
- for (const hook of registry) {
5
+ for (const hook of registry.sort((a, b) => a.name.localeCompare(b.name))) {
6
6
  console.log(` ${pc.cyan(hook.name)}`);
7
7
  console.log(pc.dim(` ${hook.description}\n`));
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAE7C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAE7C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;AAC5D,CAAC"}
package/dist/index.js CHANGED
@@ -1,13 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import packageJson from "../package.json" with { type: "json" };
3
4
  import { add } from "./commands/add.js";
5
+ import { entry } from "./commands/entry.js";
4
6
  import { init } from "./commands/init.js";
5
7
  import { list } from "./commands/list.js";
6
8
  const program = new Command();
7
9
  program
8
10
  .name("airyhooks")
9
11
  .description("Add React hooks to your project")
10
- .version("0.1.0");
12
+ .action(entry)
13
+ .alias("search")
14
+ .version(packageJson.version, "-v, --version");
11
15
  program
12
16
  .command("init")
13
17
  .description("Initialize airyhooks configuration")
@@ -16,6 +20,10 @@ program
16
20
  .command("add")
17
21
  .description("Add a hook to your project")
18
22
  .argument("<hook>", "Name of the hook to add (e.g., useDebounce)")
23
+ .option("-r --raw", "Output only the raw hook template to console", false)
24
+ .option("-f --force", "Force overwrite if the hook file already exists", false)
25
+ .option("-k --kebab", "Use kebab-case for the hook file and directory names. Overrides the default casing in config.", false)
26
+ .option("--include-tests", "Include test files when adding hooks. Overrides the default setting in config.", false)
19
27
  .action(add);
20
28
  program.command("list").description("List all available hooks").action(list);
21
29
  program.parse();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,IAAI,CAAC,CAAC;AAEhB,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,4BAA4B,CAAC;KACzC,QAAQ,CAAC,QAAQ,EAAE,6CAA6C,CAAC;KACjE,MAAM,CAAC,GAAG,CAAC,CAAC;AAEf,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAE7E,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAChE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,KAAK,CAAC;KACb,KAAK,CAAC,QAAQ,CAAC;KACf,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AAEjD,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,IAAI,CAAC,CAAC;AAEhB,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,4BAA4B,CAAC;KACzC,QAAQ,CAAC,QAAQ,EAAE,6CAA6C,CAAC;KACjE,MAAM,CAAC,UAAU,EAAE,8CAA8C,EAAE,KAAK,CAAC;KACzE,MAAM,CACL,YAAY,EACZ,iDAAiD,EACjD,KAAK,CACN;KACA,MAAM,CACL,YAAY,EACZ,+FAA+F,EAC/F,KAAK,CACN;KACA,MAAM,CACL,iBAAiB,EACjB,gFAAgF,EAChF,KAAK,CACN;KACA,MAAM,CAAC,GAAG,CAAC,CAAC;AAEf,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAE7E,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1,14 +1,18 @@
1
1
  import fs from "fs-extra";
2
2
  import path from "node:path";
3
3
  export const DEFAULT_CONFIG = {
4
+ casing: "camelCase",
4
5
  hooksPath: "src/hooks",
6
+ importExtension: "none",
7
+ includeTests: false,
8
+ structure: "nested",
5
9
  };
6
- export async function getConfig() {
10
+ export async function getConfig(overrides) {
7
11
  const configPath = path.join(process.cwd(), "airyhooks.json");
8
12
  if (await fs.pathExists(configPath)) {
9
13
  const userConfig = (await fs.readJson(configPath));
10
- return { ...DEFAULT_CONFIG, ...userConfig };
14
+ return { ...DEFAULT_CONFIG, ...userConfig, ...overrides };
11
15
  }
12
- return DEFAULT_CONFIG;
16
+ return { ...DEFAULT_CONFIG, ...overrides };
13
17
  }
14
18
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAM7B,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,SAAS,EAAE,WAAW;CACvB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAE9D,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CACnC,UAAU,CACX,CAA6B,CAAC;QAC/B,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,UAAU,EAAE,CAAC;IAC9C,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAuB7B,MAAM,CAAC,MAAM,cAAc,GAA8B;IACvD,MAAM,EAAE,WAAW;IACnB,SAAS,EAAE,WAAW;IACtB,eAAe,EAAE,MAAM;IACvB,YAAY,EAAE,KAAK;IACnB,SAAS,EAAE,QAAQ;CACpB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAAoC;IAEpC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAE9D,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CACnC,UAAU,CACX,CAA6B,CAAC;QAE/B,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,UAAU,EAAE,GAAG,SAAS,EAAE,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,SAAS,EAAE,CAAC;AAC7C,CAAC"}