create-stencil-components 1.0.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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +55 -0
  4. package/dist/index.mjs +396 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/dist/templates/base/.editorconfig +15 -0
  7. package/dist/templates/base/.eslintignore +4 -0
  8. package/dist/templates/base/.gemini/settings.json +13 -0
  9. package/dist/templates/base/.husky/commit-msg +1 -0
  10. package/dist/templates/base/.husky/install.mjs +6 -0
  11. package/dist/templates/base/.husky/pre-commit +2 -0
  12. package/dist/templates/base/.mcp.json +12 -0
  13. package/dist/templates/base/.nvmrc +1 -0
  14. package/dist/templates/base/.prettierignore +2 -0
  15. package/dist/templates/base/.stylelintignore +0 -0
  16. package/dist/templates/base/AGENTS.md +118 -0
  17. package/dist/templates/base/CLAUDE.md +16 -0
  18. package/dist/templates/base/README.md +83 -0
  19. package/dist/templates/base/commitlint.config.mjs +1 -0
  20. package/dist/templates/base/docs/CODE_OF_CONDUCT.md +122 -0
  21. package/dist/templates/base/docs/CONTRIBUTING.md +103 -0
  22. package/dist/templates/base/docs/LICENSE.md +21 -0
  23. package/dist/templates/base/docs/RELEASE.md +95 -0
  24. package/dist/templates/base/docs/STYLE_GUIDE.md +128 -0
  25. package/dist/templates/base/eslint.config.mjs +37 -0
  26. package/dist/templates/base/gitignore +32 -0
  27. package/dist/templates/base/nx.json +36 -0
  28. package/dist/templates/base/package.json +43 -0
  29. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/CHANGELOG.md +0 -0
  30. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/README.md +74 -0
  31. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/project.json +144 -0
  32. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/components/my-component/my-component.scss +3 -0
  33. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/components/my-component/my-component.tsx +32 -0
  34. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/components/my-component/readme.md +19 -0
  35. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/components/my-component/test/my-component.e2e.ts +32 -0
  36. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/components/my-component/test/my-component.spec.ts +36 -0
  37. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/components.d.ts +61 -0
  38. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/index.html +14 -0
  39. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/index.ts +12 -0
  40. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/main.scss +0 -0
  41. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/utils/utils.spec.ts +19 -0
  42. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/src/utils/utils.ts +3 -0
  43. package/dist/templates/base/packages/components-{{PROJECT_NAME_KEBAB}}-core/tsconfig.json +12 -0
  44. package/dist/templates/base/prettier.config.mjs +19 -0
  45. package/dist/templates/base/stylelint.config.mjs +25 -0
  46. package/dist/templates/base/tsconfig.base.json +23 -0
  47. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/CHANGELOG.md +0 -0
  48. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/README.md +108 -0
  49. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/ng-package.json +6 -0
  50. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/package.json +27 -0
  51. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/project.json +93 -0
  52. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/src/components-{{PROJECT_NAME_KEBAB}}.module.ts +20 -0
  53. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/src/directives/.gitkeep +0 -0
  54. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/src/index.ts +3 -0
  55. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/standalone/ng-package.json +6 -0
  56. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/standalone/src/directives/.gitkeep +0 -0
  57. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/standalone/src/index.ts +1 -0
  58. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-angular/tsconfig.json +41 -0
  59. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-core/package.json +85 -0
  60. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-core/stencil.config.ts +90 -0
  61. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/CHANGELOG.md +0 -0
  62. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/README.md +97 -0
  63. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/package.json +48 -0
  64. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/project.json +92 -0
  65. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/src/components/index.ts +1 -0
  66. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/src/index.ts +1 -0
  67. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-react/tsconfig.json +36 -0
  68. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/CHANGELOG.md +0 -0
  69. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/README.md +78 -0
  70. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/package.json +43 -0
  71. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/project.json +92 -0
  72. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/src/components/index.ts +1 -0
  73. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/src/index.ts +1 -0
  74. package/dist/templates/variants/all/packages/components-{{PROJECT_NAME_KEBAB}}-vue/tsconfig.json +39 -0
  75. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/CHANGELOG.md +0 -0
  76. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/README.md +108 -0
  77. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/ng-package.json +6 -0
  78. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/package.json +27 -0
  79. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/project.json +93 -0
  80. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/src/components-{{PROJECT_NAME_KEBAB}}.module.ts +20 -0
  81. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/src/directives/.gitkeep +0 -0
  82. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/src/index.ts +3 -0
  83. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/standalone/ng-package.json +6 -0
  84. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/standalone/src/directives/.gitkeep +0 -0
  85. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/standalone/src/index.ts +1 -0
  86. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-angular/tsconfig.json +41 -0
  87. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-core/package.json +83 -0
  88. package/dist/templates/variants/angular/packages/components-{{PROJECT_NAME_KEBAB}}-core/stencil.config.ts +72 -0
  89. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-core/package.json +83 -0
  90. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-core/stencil.config.ts +67 -0
  91. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/CHANGELOG.md +0 -0
  92. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/README.md +97 -0
  93. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/package.json +48 -0
  94. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/project.json +92 -0
  95. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/src/components/index.ts +1 -0
  96. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/src/index.ts +1 -0
  97. package/dist/templates/variants/react/packages/components-{{PROJECT_NAME_KEBAB}}-react/tsconfig.json +36 -0
  98. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-core/package.json +83 -0
  99. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-core/stencil.config.ts +67 -0
  100. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/CHANGELOG.md +0 -0
  101. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/README.md +78 -0
  102. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/package.json +43 -0
  103. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/project.json +92 -0
  104. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/src/components/index.ts +1 -0
  105. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/src/index.ts +1 -0
  106. package/dist/templates/variants/vue/packages/components-{{PROJECT_NAME_KEBAB}}-vue/tsconfig.json +39 -0
  107. package/dist/templates/variants/web-components/packages/components-{{PROJECT_NAME_KEBAB}}-core/package.json +82 -0
  108. package/dist/templates/variants/web-components/packages/components-{{PROJECT_NAME_KEBAB}}-core/stencil.config.ts +58 -0
  109. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2025
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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2025
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 ADDED
@@ -0,0 +1,55 @@
1
+ # create-stencil-components
2
+
3
+ > Create a stencil component library project using Nx, TypeScript, and SASS.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Features](#features)
8
+ - [Prerequisites](#prerequisites)
9
+ - [Usage](#usage)
10
+ - [Contributing](#contributing)
11
+ - [License](#license)
12
+
13
+ ## Features
14
+
15
+ - **Scaffolding**: Quickly generate a Stencil component library structure.
16
+ - **Framework Support**: Generate framework wrappers for Angular, React, and Vue.
17
+ - **Nx Integration**: Built on top of Nx for efficient monorepo management.
18
+
19
+ ## Prerequisites
20
+
21
+ - Node.js (Latest LTS recommended)
22
+
23
+ ## Usage
24
+
25
+ You can run generator directly while following the prompts afterwards:
26
+
27
+ ```bash
28
+ npm create stencil-components@latest
29
+ ```
30
+
31
+ You can directly specify the project name:
32
+
33
+ ```bash
34
+ npm create stencil-components@latest [project-name]
35
+ ```
36
+
37
+ Use the help option to see what additional command line options are available:
38
+
39
+ ```bash
40
+ npm create stencil-components@latest -- --help
41
+ ```
42
+
43
+ ## Contributing
44
+
45
+ Contributions are always welcome! Please see the contribution guidelines for more details.
46
+
47
+ 1. Fork the project
48
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
49
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
50
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
51
+ 5. Open a Pull Request
52
+
53
+ ## License
54
+
55
+ Distributed under the MIT License. See [LICENSE](/LICENSE.md) for more information.
package/dist/index.mjs ADDED
@@ -0,0 +1,396 @@
1
+ #!/usr/bin/env node
2
+ import * as prompts from "@clack/prompts";
3
+ import { Command } from "commander";
4
+ import pc from "picocolors";
5
+ import fs from "fs-extra";
6
+ import { execSync } from "node:child_process";
7
+ import path from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { adjectives, colors, names, uniqueNamesGenerator } from "unique-names-generator";
10
+
11
+ //#region src/utils.ts
12
+ /**
13
+ * Converts a string to PascalCase.
14
+ * @param str - The string to convert.
15
+ * @returns The PascalCase string.
16
+ */
17
+ function toPascalCase(str) {
18
+ return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (_, c) => c.toUpperCase());
19
+ }
20
+ /**
21
+ * Converts a string to camelCase.
22
+ * @param str - The string to convert.
23
+ * @returns The camelCase string.
24
+ */
25
+ function toCamelCase(str) {
26
+ const pascal = toPascalCase(str);
27
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
28
+ }
29
+ /**
30
+ * Converts a string to snake_case.
31
+ * @param str - The string to convert.
32
+ * @returns The snake_case string.
33
+ */
34
+ function toSnakeCase(str) {
35
+ return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`).replace(/[-\s]+/g, "_").replace(/^_/, "");
36
+ }
37
+ /**
38
+ * Converts a string to kebab-case.
39
+ * @param str - The string to convert.
40
+ * @returns The kebab-case string.
41
+ */
42
+ function toKebabCase(str) {
43
+ return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`).replace(/[_\s]+/g, "-").replace(/^-/, "");
44
+ }
45
+
46
+ //#endregion
47
+ //#region src/generator.ts
48
+ const __filename = fileURLToPath(import.meta.url);
49
+ const __dirname = path.dirname(__filename);
50
+ /**
51
+ * Generates a new project based on the provided configuration.
52
+ * @param config - The project configuration object.
53
+ * @returns A promise that resolves when the project generation is complete.
54
+ */
55
+ async function generateProject(config) {
56
+ const { projectName, template, packageManager = "npm", git, install } = config;
57
+ const targetDir = path.join(process.cwd(), projectName);
58
+ if (await fs.pathExists(targetDir)) throw new Error(`Project directory ${projectName} already exists`);
59
+ await prompts.tasks([
60
+ {
61
+ title: "Creating project directory",
62
+ task: async () => {
63
+ await fs.ensureDir(targetDir);
64
+ await copyAndProcessTemplate(template, targetDir, config);
65
+ return `Created project in ${targetDir}`;
66
+ }
67
+ },
68
+ {
69
+ title: "Initializing git repository",
70
+ task: async () => {
71
+ if (git) {
72
+ await initGit(targetDir);
73
+ return `Initialized git repository`;
74
+ }
75
+ return `Skipped initializing git repository`;
76
+ },
77
+ enabled: false
78
+ },
79
+ {
80
+ title: "Installing dependencies",
81
+ task: async () => {
82
+ if (install) {
83
+ await installDependencies(targetDir, packageManager);
84
+ return `Installed dependencies`;
85
+ }
86
+ return `Skipped installing dependencies`;
87
+ },
88
+ enabled: false
89
+ }
90
+ ]);
91
+ }
92
+ /**
93
+ * Copies the template files to the target directory and processes them.
94
+ * @param template - The name of the template to use.
95
+ * @param targetDir - The directory where the project will be created.
96
+ * @param config - The project configuration.
97
+ * @returns A promise that resolves when the template is copied and processed.
98
+ */
99
+ async function copyAndProcessTemplate(template, targetDir, config) {
100
+ const templatesRoot = path.join(__dirname, "templates");
101
+ const baseDir = path.join(templatesRoot, "base");
102
+ const templateDir = path.join(templatesRoot, "variants", template);
103
+ if (!await fs.pathExists(templateDir)) throw new Error(`Template ${template} not found`);
104
+ const variables = {
105
+ PROJECT_NAME: config.projectName,
106
+ PROJECT_NAME_CAMEL: toCamelCase(config.projectName),
107
+ PROJECT_NAME_KEBAB: toKebabCase(config.projectName),
108
+ PROJECT_NAME_PASCAL: toPascalCase(config.projectName),
109
+ PROJECT_NAME_SNAKE: toSnakeCase(config.projectName),
110
+ ORGANIZATION_NAME: config.organizationName,
111
+ LICENSE: config.license
112
+ };
113
+ if (await fs.pathExists(baseDir)) {
114
+ await fs.copy(baseDir, targetDir);
115
+ await fs.move(path.join(targetDir, "gitignore"), path.join(targetDir, ".gitignore"));
116
+ }
117
+ await fs.copy(templateDir, targetDir, { overwrite: true });
118
+ await renameFolders(targetDir, variables);
119
+ await renameFiles(targetDir, variables);
120
+ await processTemplateFiles(targetDir, variables);
121
+ }
122
+ /**
123
+ * Renames folders within a directory by replacing template variables in their names.
124
+ * @param dir - The directory to process.
125
+ * @param variables - The template variables to replace.
126
+ * @returns A promise that resolves when folder renaming is complete.
127
+ */
128
+ async function renameFolders(dir, variables) {
129
+ const entries = await fs.readdir(dir, { withFileTypes: true });
130
+ for (const entry of entries) {
131
+ const oldPath = path.join(dir, entry.name);
132
+ if (entry.isDirectory()) {
133
+ await renameFolders(oldPath, variables);
134
+ const newName = replaceTemplateVariables(entry.name, variables);
135
+ if (newName !== entry.name) {
136
+ const newPath = path.join(dir, newName);
137
+ await fs.move(oldPath, newPath);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ /**
143
+ * Renames files within a directory by replacing template variables in their names.
144
+ * @param dir - The directory to process.
145
+ * @param variables - The template variables to replace.
146
+ * @returns A promise that resolves when file renaming is complete.
147
+ */
148
+ async function renameFiles(dir, variables) {
149
+ const entries = await fs.readdir(dir, { withFileTypes: true });
150
+ for (const entry of entries) {
151
+ const oldPath = path.join(dir, entry.name);
152
+ if (entry.isDirectory()) await renameFiles(oldPath, variables);
153
+ else if (entry.isFile()) {
154
+ const newName = replaceTemplateVariables(entry.name, variables);
155
+ if (newName !== entry.name) {
156
+ const newPath = path.join(dir, newName);
157
+ await fs.move(oldPath, newPath);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ /**
163
+ * Processes all files in a directory to replace template variables in their content.
164
+ * @param dir - The directory to process.
165
+ * @param variables - The template variables to replace.
166
+ * @returns A promise that resolves when file processing is complete.
167
+ */
168
+ async function processTemplateFiles(dir, variables) {
169
+ const files = await fs.readdir(dir, { withFileTypes: true });
170
+ for (const file of files) {
171
+ const filePath = path.join(dir, file.name);
172
+ if (file.isDirectory()) await processTemplateFiles(filePath, variables);
173
+ else if (file.isFile()) await processFile(filePath, variables);
174
+ }
175
+ }
176
+ /**
177
+ * Processes a single file to replace template variables in its content.
178
+ * @param filePath - The path to the file to process.
179
+ * @param variables - The template variables to replace.
180
+ * @returns A promise that resolves when the file is processed.
181
+ */
182
+ async function processFile(filePath, variables) {
183
+ const ext = path.extname(filePath);
184
+ if ([
185
+ ".js",
186
+ ".ts",
187
+ ".jsx",
188
+ ".tsx",
189
+ ".json",
190
+ ".md",
191
+ ".html",
192
+ ".css",
193
+ ".scss",
194
+ ".yaml",
195
+ ".yml",
196
+ ".txt",
197
+ ".env",
198
+ ".gitignore",
199
+ ".npmrc",
200
+ ".editorconfig"
201
+ ].includes(ext) || !ext) try {
202
+ let content = await fs.readFile(filePath, "utf8");
203
+ content = replaceTemplateVariables(content, variables);
204
+ await fs.writeFile(filePath, content, "utf8");
205
+ } catch (error) {
206
+ prompts.log.message(pc.gray(` Exception process file: ${error}`));
207
+ prompts.log.message(pc.gray(` Skipping binary file: ${path.basename(filePath)}`));
208
+ }
209
+ }
210
+ /**
211
+ * Replaces template variables in a string content.
212
+ * @param content - The content string.
213
+ * @param variables - The template variables to replace.
214
+ * @returns The content with variables replaced.
215
+ */
216
+ function replaceTemplateVariables(content, variables) {
217
+ let result = content;
218
+ for (const [key, value] of Object.entries(variables)) {
219
+ const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g");
220
+ result = result.replace(regex, value);
221
+ }
222
+ return result;
223
+ }
224
+ /**
225
+ * Initializes a git repository in the target directory.
226
+ * @param targetDir - The directory to initialize git in.
227
+ * @returns A promise that resolves when git initialization is complete.
228
+ */
229
+ async function initGit(targetDir) {
230
+ try {
231
+ execSync("git init", {
232
+ cwd: targetDir,
233
+ stdio: "ignore"
234
+ });
235
+ } catch (error) {
236
+ prompts.log.warn(pc.yellow(`Failed to initialize git repository: ${error}`));
237
+ }
238
+ }
239
+ /**
240
+ * Installs project dependencies using the specified package manager.
241
+ * @param targetDir - The project directory.
242
+ * @param packageManager - The package manager to use (e.g., 'npm', 'yarn', 'pnpm').
243
+ * @returns A promise that resolves when dependencies are installed.
244
+ */
245
+ async function installDependencies(targetDir, packageManager) {
246
+ try {
247
+ execSync(`${packageManager} install`, {
248
+ cwd: targetDir,
249
+ stdio: "inherit"
250
+ });
251
+ } catch (error) {
252
+ prompts.log.warn(pc.yellow(`Failed to install dependencies: ${error}`));
253
+ prompts.log.info(pc.gray(` Run "${packageManager} install" manually`));
254
+ }
255
+ }
256
+
257
+ //#endregion
258
+ //#region src/prompts.ts
259
+ /**
260
+ * Prompts the user for project configuration details.
261
+ * @param projectName - The name of the project, if provided as an argument.
262
+ * @param options - Command-line options that pre-fill or configure the prompts.
263
+ * @returns A promise that resolves to the complete project configuration.
264
+ */
265
+ async function getProjectQuestions(projectName, options) {
266
+ const answers = await prompts.group({
267
+ projectName: async () => {
268
+ return prompts.text({
269
+ message: "Project name:",
270
+ initialValue: projectName || uniqueNamesGenerator({
271
+ dictionaries: [adjectives, colors],
272
+ separator: "-",
273
+ style: "lowerCase",
274
+ length: 2
275
+ }),
276
+ validate: (value) => {
277
+ if (!value || value.trim() === "") return "Project name is required";
278
+ if (!/^[a-z0-9-_]+$/.test(value)) return "Invalid project name (can only contain lowercase letters, numbers, hyphens, and underscores)";
279
+ }
280
+ });
281
+ },
282
+ organizationName: async () => {
283
+ return prompts.text({
284
+ message: "Organization name (used in the scope name field of the package.json):",
285
+ initialValue: options?.organizationName || uniqueNamesGenerator({
286
+ dictionaries: [names],
287
+ style: "lowerCase",
288
+ length: 1
289
+ }),
290
+ validate: (value) => {
291
+ if (!value || value.trim() === "") return "Organization name is required";
292
+ if (!/^[a-z]+$/.test(value)) return "Organization name can only contain lowercase letters";
293
+ }
294
+ });
295
+ },
296
+ template: async () => {
297
+ return prompts.select({
298
+ message: "Select a framework:",
299
+ options: [
300
+ {
301
+ label: "angular",
302
+ value: "angular",
303
+ hint: "Angular framework"
304
+ },
305
+ {
306
+ label: "react",
307
+ value: "react",
308
+ hint: "React framework"
309
+ },
310
+ {
311
+ label: "vue",
312
+ value: "vue",
313
+ hint: "Vue framework"
314
+ },
315
+ {
316
+ label: "web-components",
317
+ value: "web-components",
318
+ hint: "Web components only"
319
+ },
320
+ {
321
+ label: "all",
322
+ value: "all",
323
+ hint: "Includes all frameworks"
324
+ }
325
+ ],
326
+ initialValue: options.template || "all",
327
+ maxItems: 5
328
+ });
329
+ },
330
+ packageManager: () => Promise.resolve("npm"),
331
+ git: () => Promise.resolve(false),
332
+ install: () => Promise.resolve(false)
333
+ }, { onCancel: () => {
334
+ prompts.cancel("Operation cancelled");
335
+ process.exit(1);
336
+ } });
337
+ return {
338
+ projectName: answers.projectName,
339
+ organizationName: answers.organizationName,
340
+ template: answers.template,
341
+ packageManager: answers.packageManager,
342
+ git: answers.git,
343
+ install: answers.install
344
+ };
345
+ }
346
+
347
+ //#endregion
348
+ //#region src/cli.ts
349
+ /**
350
+ * The main entry point for the CLI.
351
+ * Sets up the command-line interface, parses arguments, prompts the user for configuration,
352
+ * and triggers the project generation process.
353
+ * @returns A promise that resolves when the CLI execution is complete.
354
+ */
355
+ async function cli() {
356
+ const program = new Command();
357
+ program.name("create-stencil-components").description("Create a stencil component library project using Nx, TypeScript, and SASS.").argument("[project-name]", "Name of the project").option("-o, --organization-name <name>", "Name of the organization (used in the name field of the package.json)").option("-t, --template <type>", "Template type (angular, react, vue, web-components, all)").parse();
358
+ const options = program.opts();
359
+ const [projectName] = program.args;
360
+ prompts.intro(pc.cyan("Welcome to create-stencil-components!"));
361
+ try {
362
+ const config = await getProjectQuestions(projectName, options);
363
+ await generateProject(config);
364
+ prompts.outro(pc.green("Your project is ready!"));
365
+ printNextSteps(config);
366
+ } catch (error) {
367
+ if (error instanceof Error) prompts.log.error(pc.red(`Error: ${error.message}`));
368
+ process.exit(1);
369
+ }
370
+ }
371
+ /**
372
+ * Prints the next steps for the user after the project has been successfully generated.
373
+ * @param config - The configuration object containing project details like name and package manager.
374
+ */
375
+ function printNextSteps(config) {
376
+ const { projectName, packageManager = "npm" } = config;
377
+ console.log(pc.cyan("Next steps:"));
378
+ console.log(` ${pc.gray("$")} cd ${projectName}`);
379
+ if (config.install === false) {
380
+ console.log(` ${pc.gray("$")} ${packageManager} install`);
381
+ console.log(` ${pc.gray("$")} npx nx run-many -t build`);
382
+ } else console.log(` ${pc.gray("$")} npx nx run-many -t build`);
383
+ }
384
+
385
+ //#endregion
386
+ //#region bin/index.ts
387
+ try {
388
+ await cli();
389
+ } catch (error) {
390
+ if (error instanceof Error) console.error(`Exception while doing something: ${error.message}`);
391
+ process.exit(1);
392
+ }
393
+
394
+ //#endregion
395
+ export { };
396
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["variables: TemplateVariables","config: ProjectConfig","error: unknown","error: unknown"],"sources":["../src/utils.ts","../src/generator.ts","../src/prompts.ts","../src/cli.ts","../bin/index.ts"],"sourcesContent":["import fs from 'fs-extra';\r\nimport path from 'node:path';\r\n\r\n/**\r\n * Checks if a directory is empty.\r\n * @param dirPath - The path to the directory to check.\r\n * @returns A promise that resolves to true if the directory is empty, false otherwise.\r\n */\r\nexport async function isDirectoryEmpty(dirPath: string): Promise<boolean> {\r\n try {\r\n const files = await fs.readdir(dirPath);\r\n return files.length === 0;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Validates if a project name consists only of alphanumeric characters, hyphens, and underscores.\r\n * @param name - The project name to validate.\r\n * @returns True if the name is valid, false otherwise.\r\n */\r\nexport function validateProjectName(name: string): boolean {\r\n return /^[a-z0-9-_]+$/i.test(name);\r\n}\r\n\r\n/**\r\n * Checks if a file or directory exists at the given path.\r\n * @param filePath - The path to check.\r\n * @returns A promise that resolves to true if the file exists, false otherwise.\r\n */\r\nexport async function fileExists(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.access(filePath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Gets the absolute path to a specific template directory.\r\n * @param template - The name of the template.\r\n * @returns The absolute path to the template directory.\r\n */\r\nexport function getTemplateDir(template: string): string {\r\n return path.join(process.cwd(), 'templates', template);\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n * @param str - The string to convert.\r\n * @returns The PascalCase string.\r\n */\r\nexport function toPascalCase(str: string): string {\r\n return str\r\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\r\n .replace(/^(.)/, (_, c) => c.toUpperCase());\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n * @param str - The string to convert.\r\n * @returns The camelCase string.\r\n */\r\nexport function toCamelCase(str: string): string {\r\n const pascal = toPascalCase(str);\r\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n * @param str - The string to convert.\r\n * @returns The snake_case string.\r\n */\r\nexport function toSnakeCase(str: string): string {\r\n return str\r\n .replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\r\n .replace(/[-\\s]+/g, '_')\r\n .replace(/^_/, '');\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n * @param str - The string to convert.\r\n * @returns The kebab-case string.\r\n */\r\nexport function toKebabCase(str: string): string {\r\n return str\r\n .replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)\r\n .replace(/[_\\s]+/g, '-')\r\n .replace(/^-/, '');\r\n}","import * as prompts from '@clack/prompts';\r\nimport fs from 'fs-extra';\r\nimport { execSync } from 'node:child_process';\r\nimport path from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport pc from 'picocolors';\r\nimport type { ProjectConfig, TemplateVariables } from './types.js';\r\nimport { toCamelCase, toKebabCase, toPascalCase, toSnakeCase } from './utils.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/**\r\n * Generates a new project based on the provided configuration.\r\n * @param config - The project configuration object.\r\n * @returns A promise that resolves when the project generation is complete.\r\n */\r\nexport async function generateProject(config: ProjectConfig): Promise<void> {\r\n const { projectName, template, packageManager = 'npm', git, install } = config;\r\n const targetDir = path.join(process.cwd(), projectName);\r\n\r\n // Check if directory already exists\r\n if (await fs.pathExists(targetDir)) {\r\n throw new Error(`Project directory ${projectName} already exists`);\r\n }\r\n\r\n await prompts.tasks([\r\n {\r\n title: 'Creating project directory',\r\n task: async () => {\r\n await fs.ensureDir(targetDir);\r\n await copyAndProcessTemplate(template, targetDir, config);\r\n return `Created project in ${targetDir}`;\r\n }\r\n },\r\n {\r\n title: 'Initializing git repository',\r\n task: async () => {\r\n if (git) {\r\n await initGit(targetDir);\r\n return `Initialized git repository`;\r\n }\r\n return `Skipped initializing git repository`;\r\n },\r\n enabled: false\r\n },\r\n {\r\n title: 'Installing dependencies',\r\n task: async () => {\r\n if (install) {\r\n await installDependencies(targetDir, packageManager);\r\n return `Installed dependencies`;\r\n }\r\n return `Skipped installing dependencies`;\r\n },\r\n enabled: false\r\n }\r\n ]);\r\n}\r\n\r\n/**\r\n * Copies the template files to the target directory and processes them.\r\n * @param template - The name of the template to use.\r\n * @param targetDir - The directory where the project will be created.\r\n * @param config - The project configuration.\r\n * @returns A promise that resolves when the template is copied and processed.\r\n */\r\nasync function copyAndProcessTemplate(\r\n template: string, \r\n targetDir: string,\r\n config: ProjectConfig\r\n): Promise<void> {\r\n const templatesRoot = path.join(__dirname, 'templates');\r\n const baseDir = path.join(templatesRoot, 'base');\r\n const templateDir = path.join(templatesRoot, 'variants', template);\r\n \r\n if (!await fs.pathExists(templateDir)) {\r\n throw new Error(`Template ${template} not found`);\r\n }\r\n\r\n // Prepare template variables\r\n const variables: TemplateVariables = {\r\n PROJECT_NAME: config.projectName,\r\n PROJECT_NAME_CAMEL: toCamelCase(config.projectName),\r\n PROJECT_NAME_KEBAB: toKebabCase(config.projectName),\r\n PROJECT_NAME_PASCAL: toPascalCase(config.projectName),\r\n PROJECT_NAME_SNAKE: toSnakeCase(config.projectName),\r\n ORGANIZATION_NAME: config.organizationName,\r\n LICENSE: config.license\r\n };\r\n\r\n // Step 1: Copy base template if it exists\r\n if (await fs.pathExists(baseDir)) {\r\n await fs.copy(baseDir, targetDir);\r\n // Rename gitignore if it exists\r\n await fs.move(\r\n path.join(targetDir, 'gitignore'), \r\n path.join(targetDir, '.gitignore')\r\n );\r\n }\r\n\r\n // Step 2: Copy template-specific files (overwrites base files if needed)\r\n await fs.copy(templateDir, targetDir, { overwrite: true });\r\n\r\n // Step 3: Rename folders with variables\r\n await renameFolders(targetDir, variables);\r\n \r\n // Step 4: Rename files with variables\r\n await renameFiles(targetDir, variables);\r\n \r\n // Step 5: Process all file contents\r\n await processTemplateFiles(targetDir, variables);\r\n}\r\n\r\n/**\r\n * Renames folders within a directory by replacing template variables in their names.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when folder renaming is complete.\r\n */\r\nasync function renameFolders(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n // Sort directories first, then process recursively\r\n for (const entry of entries) {\r\n const oldPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // First process subdirectories recursively\r\n await renameFolders(oldPath, variables);\r\n \r\n // Then rename this directory if needed\r\n const newName = replaceTemplateVariables(entry.name, variables);\r\n if (newName !== entry.name) {\r\n const newPath = path.join(dir, newName);\r\n await fs.move(oldPath, newPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Renames files within a directory by replacing template variables in their names.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when file renaming is complete.\r\n */\r\nasync function renameFiles(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const oldPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Recursively process subdirectories\r\n await renameFiles(oldPath, variables);\r\n } else if (entry.isFile()) {\r\n // Rename file if it contains variables\r\n const newName = replaceTemplateVariables(entry.name, variables);\r\n if (newName !== entry.name) {\r\n const newPath = path.join(dir, newName);\r\n await fs.move(oldPath, newPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Processes all files in a directory to replace template variables in their content.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when file processing is complete.\r\n */\r\nasync function processTemplateFiles(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const files = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const file of files) {\r\n const filePath = path.join(dir, file.name);\r\n\r\n if (file.isDirectory()) {\r\n // Recursively process subdirectories\r\n await processTemplateFiles(filePath, variables);\r\n } else if (file.isFile()) {\r\n // Process file based on extension\r\n await processFile(filePath, variables);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Processes a single file to replace template variables in its content.\r\n * @param filePath - The path to the file to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when the file is processed.\r\n */\r\nasync function processFile(\r\n filePath: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const ext = path.extname(filePath);\r\n \r\n // Only process text files (not binaries like images)\r\n const textExtensions = [\r\n '.js', '.ts', '.jsx', '.tsx', '.json', '.md', '.html', \r\n '.css', '.scss', '.yaml', '.yml', '.txt', '.env', \r\n '.gitignore', '.npmrc', '.editorconfig'\r\n ];\r\n\r\n if (textExtensions.includes(ext) || !ext) {\r\n try {\r\n let content = await fs.readFile(filePath, 'utf8');\r\n \r\n // Replace template variables\r\n content = replaceTemplateVariables(content, variables);\r\n \r\n await fs.writeFile(filePath, content, 'utf8');\r\n } catch (error) {\r\n // Skip binary files that can't be read as text\r\n prompts.log.message(pc.gray(` Exception process file: ${error}`));\r\n prompts.log.message(pc.gray(` Skipping binary file: ${path.basename(filePath)}`));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Replaces template variables in a string content.\r\n * @param content - The content string.\r\n * @param variables - The template variables to replace.\r\n * @returns The content with variables replaced.\r\n */\r\nfunction replaceTemplateVariables(\r\n content: string, \r\n variables: TemplateVariables\r\n): string {\r\n let result = content;\r\n\r\n // Replace {{VARIABLE_NAME}} tokens\r\n for (const [key, value] of Object.entries(variables)) {\r\n const regex = new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g');\r\n result = result.replace(regex, value);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Initializes a git repository in the target directory.\r\n * @param targetDir - The directory to initialize git in.\r\n * @returns A promise that resolves when git initialization is complete.\r\n */\r\nasync function initGit(targetDir: string): Promise<void> {\r\n try {\r\n execSync('git init', { cwd: targetDir, stdio: 'ignore' });\r\n } catch (error) {\r\n prompts.log.warn(pc.yellow(`Failed to initialize git repository: ${error}`));\r\n }\r\n}\r\n\r\n/**\r\n * Installs project dependencies using the specified package manager.\r\n * @param targetDir - The project directory.\r\n * @param packageManager - The package manager to use (e.g., 'npm', 'yarn', 'pnpm').\r\n * @returns A promise that resolves when dependencies are installed.\r\n */\r\nasync function installDependencies(targetDir: string, packageManager: string): Promise<void> { \r\n try {\r\n execSync(`${packageManager} install`, { \r\n cwd: targetDir, \r\n stdio: 'inherit' \r\n });\r\n } catch (error) {\r\n prompts.log.warn(pc.yellow(`Failed to install dependencies: ${error}`));\r\n prompts.log.info(pc.gray(` Run \"${packageManager} install\" manually`));\r\n }\r\n}","import * as prompts from '@clack/prompts';\r\nimport type { CLIOptions, PackageManager, ProjectConfig, TemplateType } from './types.js';\r\n\r\nimport { adjectives, colors, names, uniqueNamesGenerator } from 'unique-names-generator';\r\n\r\n/**\r\n * Prompts the user for project configuration details.\r\n * @param projectName - The name of the project, if provided as an argument.\r\n * @param options - Command-line options that pre-fill or configure the prompts.\r\n * @returns A promise that resolves to the complete project configuration.\r\n */\r\nexport async function getProjectQuestions(\r\n projectName: string | undefined,\r\n options: CLIOptions\r\n): Promise<ProjectConfig> {\r\n const answers = await prompts.group({\r\n projectName: async () => {\r\n return prompts.text({\r\n message: 'Project name:',\r\n initialValue: projectName || uniqueNamesGenerator({\r\n dictionaries: [adjectives, colors],\r\n separator: '-',\r\n style: 'lowerCase',\r\n length: 2,\r\n }),\r\n validate: (value: string) => {\r\n if (!value || value.trim() === '') {\r\n return 'Project name is required';\r\n }\r\n if (!/^[a-z0-9-_]+$/.test(value)) {\r\n return 'Invalid project name (can only contain lowercase letters, numbers, hyphens, and underscores)';\r\n }\r\n return undefined;\r\n }\r\n });\r\n },\r\n organizationName: async () => {\r\n return prompts.text({\r\n message: 'Organization name (used in the scope name field of the package.json):',\r\n initialValue: options?.organizationName || uniqueNamesGenerator({\r\n dictionaries: [names],\r\n style: 'lowerCase',\r\n length: 1\r\n }),\r\n validate: (value: string) => {\r\n if (!value || value.trim() === '') {\r\n return 'Organization name is required';\r\n }\r\n if (!/^[a-z]+$/.test(value)) {\r\n return 'Organization name can only contain lowercase letters';\r\n }\r\n return undefined;\r\n }\r\n });\r\n },\r\n template: async () => {\r\n return prompts.select({\r\n message: 'Select a framework:',\r\n options: [\r\n { label: 'angular', value: 'angular', hint: 'Angular framework' },\r\n { label: 'react', value: 'react', hint: 'React framework' },\r\n { label: 'vue', value: 'vue', hint: 'Vue framework' },\r\n { label: 'web-components', value: 'web-components', hint: 'Web components only' },\r\n { label: 'all', value: 'all', hint: 'Includes all frameworks' }\r\n ],\r\n initialValue: options.template || 'all',\r\n maxItems: 5\r\n });\r\n },\r\n packageManager: () => Promise.resolve('npm' as PackageManager),\r\n git: () => Promise.resolve(false),\r\n install: () => Promise.resolve(false)\r\n }, {\r\n onCancel: () => {\r\n prompts.cancel('Operation cancelled');\r\n process.exit(1);\r\n }\r\n });\r\n\r\n return {\r\n projectName: answers.projectName,\r\n organizationName: answers.organizationName,\r\n template: answers.template as TemplateType,\r\n packageManager: answers.packageManager,\r\n git: answers.git,\r\n install: answers.install\r\n };\r\n}\r\n\r\nexport default getProjectQuestions;","import * as prompts from '@clack/prompts';\r\nimport { Command } from 'commander';\r\nimport pc from 'picocolors';\r\nimport { generateProject } from './generator.js';\r\nimport { getProjectQuestions } from './prompts.js';\r\nimport type { CLIOptions, ProjectConfig } from './types.js';\r\n\r\n/**\r\n * The main entry point for the CLI.\r\n * Sets up the command-line interface, parses arguments, prompts the user for configuration,\r\n * and triggers the project generation process.\r\n * @returns A promise that resolves when the CLI execution is complete.\r\n */\r\nexport async function cli(): Promise<void> {\r\n const program = new Command();\r\n \r\n program\r\n .name('create-stencil-components')\r\n .description('Create a stencil component library project using Nx, TypeScript, and SASS.')\r\n .argument('[project-name]', 'Name of the project')\r\n .option('-o, --organization-name <name>', 'Name of the organization (used in the name field of the package.json)')\r\n .option('-t, --template <type>', 'Template type (angular, react, vue, web-components, all)')\r\n //.option('-p, --package-manager <pm>', 'Package manager (npm, yarn, pnpm)')\r\n //.option('--no-git', 'Skip git initialization')\r\n //.option('--no-install', 'Skip dependency installation')\r\n .parse();\r\n\r\n const options = program.opts<CLIOptions>();\r\n const [projectName] = program.args;\r\n\r\n prompts.intro(pc.cyan('Welcome to create-stencil-components!'));\r\n\r\n try {\r\n // Get user input through prompts\r\n const config: ProjectConfig = await getProjectQuestions(projectName, options);\r\n \r\n // Generate the project\r\n await generateProject(config);\r\n prompts.outro(pc.green('Your project is ready!'));\r\n printNextSteps(config);\r\n } catch (error: unknown) {\r\n if (error instanceof Error) {\r\n prompts.log.error(pc.red(`Error: ${error.message}`));\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\n/**\r\n * Prints the next steps for the user after the project has been successfully generated.\r\n * @param config - The configuration object containing project details like name and package manager.\r\n */\r\nfunction printNextSteps(config: ProjectConfig): void {\r\n const { projectName, packageManager = 'npm' } = config;\r\n \r\n console.log(pc.cyan('Next steps:'));\r\n console.log(` ${pc.gray('$')} cd ${projectName}`);\r\n \r\n if (config.install === false) {\r\n console.log(` ${pc.gray('$')} ${packageManager} install`);\r\n console.log(` ${pc.gray('$')} npx nx run-many -t build`);\r\n } else {\r\n console.log(` ${pc.gray('$')} npx nx run-many -t build`);\r\n }\r\n}","#!/usr/bin/env node\r\n\r\nimport { cli } from '../src/cli.js';\r\n\r\ntry {\r\n await cli();\r\n} catch (error: unknown) {\r\n if (error instanceof Error) {\r\n console.error(`Exception while doing something: ${error.message}`);\r\n }\r\n process.exit(1);\r\n}"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ # http://editorconfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ charset = utf-8
7
+ indent_style = space
8
+ indent_size = 2
9
+ end_of_line = lf
10
+ insert_final_newline = true
11
+ trim_trailing_whitespace = true
12
+
13
+ [*.md]
14
+ insert_final_newline = false
15
+ trim_trailing_whitespace = false
@@ -0,0 +1,4 @@
1
+ src/components.d.ts
2
+ **/test/**/*.spec.ts
3
+ **/test/**/*.spec.tsx
4
+ **/test/**/*.e2e.ts
@@ -0,0 +1,13 @@
1
+ {
2
+ "mcpServers": {
3
+ "nx-mcp": {
4
+ "type": "stdio",
5
+ "command": "npx",
6
+ "args": [
7
+ "nx",
8
+ "mcp"
9
+ ]
10
+ }
11
+ },
12
+ "contextFileName": "AGENTS.md"
13
+ }
@@ -0,0 +1 @@
1
+ npx --no -- commitlint --edit
@@ -0,0 +1,6 @@
1
+ // Skip Husky install in production and CI
2
+ if (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {
3
+ process.exit(0)
4
+ }
5
+ const husky = (await import('husky')).default
6
+ console.log(husky())
@@ -0,0 +1,2 @@
1
+ #npm test
2
+ exit 0
@@ -0,0 +1,12 @@
1
+ {
2
+ "mcpServers": {
3
+ "nx-mcp": {
4
+ "type": "stdio",
5
+ "command": "npx",
6
+ "args": [
7
+ "nx",
8
+ "mcp"
9
+ ]
10
+ }
11
+ }
12
+ }
@@ -0,0 +1 @@
1
+ 25.2.1
@@ -0,0 +1,2 @@
1
+ dist
2
+ src/components/d.ts
File without changes