stack-dev 0.1.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 (204) hide show
  1. package/.idea/modules.xml +8 -0
  2. package/.idea/prettier.xml +7 -0
  3. package/.idea/stack-dev.iml +12 -0
  4. package/.idea/vcs.xml +6 -0
  5. package/apps/cli/eslint.config.mjs +3 -0
  6. package/apps/cli/node_modules/.bin/acorn +21 -0
  7. package/apps/cli/node_modules/.bin/esbuild +21 -0
  8. package/apps/cli/node_modules/.bin/eslint +21 -0
  9. package/apps/cli/node_modules/.bin/glob +21 -0
  10. package/apps/cli/node_modules/.bin/json5 +21 -0
  11. package/apps/cli/node_modules/.bin/prettier +21 -0
  12. package/apps/cli/node_modules/.bin/stack-prettier +21 -0
  13. package/apps/cli/node_modules/.bin/tsc +21 -0
  14. package/apps/cli/node_modules/.bin/tsserver +21 -0
  15. package/apps/cli/node_modules/.bin/tsup +21 -0
  16. package/apps/cli/node_modules/.bin/tsup-node +21 -0
  17. package/apps/cli/node_modules/.bin/yaml +21 -0
  18. package/apps/cli/package.json +35 -0
  19. package/apps/cli/prettier.config.mjs +3 -0
  20. package/apps/cli/src/file-generator/file-generator-imp.ts +20 -0
  21. package/apps/cli/src/file-generator/file-generator.ts +5 -0
  22. package/apps/cli/src/file-generator/index.ts +3 -0
  23. package/apps/cli/src/file-generator/package-json-generator.ts +23 -0
  24. package/apps/cli/src/index.ts +185 -0
  25. package/apps/cli/src/link-packages.ts +65 -0
  26. package/apps/cli/src/package-json/dependency.ts +28 -0
  27. package/apps/cli/src/package-json/index.ts +3 -0
  28. package/apps/cli/src/package-json/package-json.ts +269 -0
  29. package/apps/cli/src/packages/create-config-package.ts +29 -0
  30. package/apps/cli/src/packages/index.ts +4 -0
  31. package/apps/cli/src/packages/library-package/create-library-package.ts +85 -0
  32. package/apps/cli/src/packages/library-package/files/add-file-generator.ts +8 -0
  33. package/apps/cli/src/packages/library-package/files/add-spec-file-generator.ts +17 -0
  34. package/apps/cli/src/packages/library-package/files/eslint-config-file-generator.ts +11 -0
  35. package/apps/cli/src/packages/library-package/files/index-file-generator.ts +9 -0
  36. package/apps/cli/src/packages/library-package/files/prettier-config-file-generator.ts +11 -0
  37. package/apps/cli/src/packages/library-package/files/tsconfig-file-generator.ts +15 -0
  38. package/apps/cli/src/packages/library-package/files/tsup-config-file-generator.ts +23 -0
  39. package/apps/cli/src/packages/library-package/files/vitest-config-file-generator.ts +19 -0
  40. package/apps/cli/src/packages/library-package/index.ts +1 -0
  41. package/apps/cli/src/packages/react-package/create-react-package.ts +25 -0
  42. package/apps/cli/src/packages/react-package/create-tailwind-react-package.ts +30 -0
  43. package/apps/cli/src/packages/react-package/create-unstyled-react-package.ts +3 -0
  44. package/apps/cli/src/packages/react-package/css-react-package/create-css-react-package.ts +103 -0
  45. package/apps/cli/src/packages/react-package/css-react-package/files/button-css-module-file-generator.ts +16 -0
  46. package/apps/cli/src/packages/react-package/css-react-package/files/button-file-generator.ts +14 -0
  47. package/apps/cli/src/packages/react-package/css-react-package/files/button-spec-file-generator.ts +33 -0
  48. package/apps/cli/src/packages/react-package/css-react-package/files/eslint-config-file-generator.ts +18 -0
  49. package/apps/cli/src/packages/react-package/css-react-package/files/index-file-generator.ts +9 -0
  50. package/apps/cli/src/packages/react-package/css-react-package/files/prettier-config-file-generator.ts +11 -0
  51. package/apps/cli/src/packages/react-package/css-react-package/files/tsconfig-file-generator.ts +15 -0
  52. package/apps/cli/src/packages/react-package/css-react-package/files/tsup-config-file-generator.ts +24 -0
  53. package/apps/cli/src/packages/react-package/css-react-package/files/vitest-config-file-generator.ts +23 -0
  54. package/apps/cli/src/packages/react-package/index.ts +1 -0
  55. package/apps/cli/src/packages/react-package/styled-components-react-package/create-styled-components-react-package.ts +112 -0
  56. package/apps/cli/src/packages/react-package/styled-components-react-package/files/button-file-generator.ts +30 -0
  57. package/apps/cli/src/packages/react-package/styled-components-react-package/files/button-spec-file-generator.ts +33 -0
  58. package/apps/cli/src/packages/react-package/styled-components-react-package/files/eslint-config-file-generator.ts +18 -0
  59. package/apps/cli/src/packages/react-package/styled-components-react-package/files/index-file-generator.ts +9 -0
  60. package/apps/cli/src/packages/react-package/styled-components-react-package/files/prettier-config-file-generator.ts +11 -0
  61. package/apps/cli/src/packages/react-package/styled-components-react-package/files/tsconfig-file-generator.ts +15 -0
  62. package/apps/cli/src/packages/react-package/styled-components-react-package/files/tsup-config-file-generator.ts +21 -0
  63. package/apps/cli/src/packages/react-package/styled-components-react-package/files/vitest-config-file-generator.ts +23 -0
  64. package/apps/cli/src/packages/vite-react-app/create-vite-react-app.ts +79 -0
  65. package/apps/cli/src/packages/vite-react-app/files/app-file-generator.ts +28 -0
  66. package/apps/cli/src/packages/vite-react-app/files/eslint-config-file-generator.ts +11 -0
  67. package/apps/cli/src/packages/vite-react-app/files/index-html-file-generator.ts +20 -0
  68. package/apps/cli/src/packages/vite-react-app/files/main-file-generator.ts +14 -0
  69. package/apps/cli/src/packages/vite-react-app/files/prettier-config-file-generator.ts +11 -0
  70. package/apps/cli/src/packages/vite-react-app/files/tsconfig-file-generator.ts +15 -0
  71. package/apps/cli/src/packages/vite-react-app/files/vite-config-file-generator.ts +17 -0
  72. package/apps/cli/src/packages/vite-react-app/files/vitest-config-file-generator.ts +19 -0
  73. package/apps/cli/src/tsconfig/compiler-options.ts +83 -0
  74. package/apps/cli/src/tsconfig/index.ts +4 -0
  75. package/apps/cli/src/tsconfig/reference.ts +21 -0
  76. package/apps/cli/src/tsconfig/tsconfig.ts +137 -0
  77. package/apps/cli/src/unlink-packages.ts +47 -0
  78. package/apps/cli/src/utils/package-generator.ts +41 -0
  79. package/apps/cli/src/utils/package-type.ts +44 -0
  80. package/apps/cli/src/utils/package.ts +126 -0
  81. package/apps/cli/src/utils/style-type.ts +41 -0
  82. package/apps/cli/src/utils/utils.ts +28 -0
  83. package/apps/cli/src/utils/workspace.ts +78 -0
  84. package/apps/cli/src/workspace/create-workspace.ts +39 -0
  85. package/apps/cli/src/workspace/index.ts +1 -0
  86. package/apps/cli/src/workspace/root-package.ts +195 -0
  87. package/apps/cli/src/workspace/typescript-config.ts +84 -0
  88. package/apps/cli/tsconfig.json +14 -0
  89. package/apps/cli/tsup.config.ts +16 -0
  90. package/apps/demo/eslint.config.mjs +3 -0
  91. package/apps/demo/index.html +12 -0
  92. package/apps/demo/node_modules/.bin/browserslist +21 -0
  93. package/apps/demo/node_modules/.bin/eslint +21 -0
  94. package/apps/demo/node_modules/.bin/prettier +21 -0
  95. package/apps/demo/node_modules/.bin/tsc +21 -0
  96. package/apps/demo/node_modules/.bin/tsserver +21 -0
  97. package/apps/demo/node_modules/.bin/vite +21 -0
  98. package/apps/demo/node_modules/.vite/deps/_metadata.json +52 -0
  99. package/apps/demo/node_modules/.vite/deps/chunk-IGB2AZES.js +1930 -0
  100. package/apps/demo/node_modules/.vite/deps/chunk-IGB2AZES.js.map +7 -0
  101. package/apps/demo/node_modules/.vite/deps/chunk-NEPDRNXC.js +21626 -0
  102. package/apps/demo/node_modules/.vite/deps/chunk-NEPDRNXC.js.map +7 -0
  103. package/apps/demo/node_modules/.vite/deps/package.json +3 -0
  104. package/apps/demo/node_modules/.vite/deps/react-dom.js +6 -0
  105. package/apps/demo/node_modules/.vite/deps/react-dom.js.map +7 -0
  106. package/apps/demo/node_modules/.vite/deps/react-dom_client.js +38 -0
  107. package/apps/demo/node_modules/.vite/deps/react-dom_client.js.map +7 -0
  108. package/apps/demo/node_modules/.vite/deps/react.js +5 -0
  109. package/apps/demo/node_modules/.vite/deps/react.js.map +7 -0
  110. package/apps/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +911 -0
  111. package/apps/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
  112. package/apps/demo/node_modules/.vite/deps/react_jsx-runtime.js +923 -0
  113. package/apps/demo/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
  114. package/apps/demo/node_modules/.vite/deps/styled-components.js +1366 -0
  115. package/apps/demo/node_modules/.vite/deps/styled-components.js.map +7 -0
  116. package/apps/demo/package.json +32 -0
  117. package/apps/demo/prettier.config.mjs +3 -0
  118. package/apps/demo/src/App.tsx +50 -0
  119. package/apps/demo/src/main.tsx +9 -0
  120. package/apps/demo/tsconfig.json +17 -0
  121. package/apps/demo/vite.config.ts +9 -0
  122. package/apps/demo/vitest.config.ts +11 -0
  123. package/configs/eslint-config/base.mjs +15 -0
  124. package/configs/eslint-config/node_modules/.bin/acorn +21 -0
  125. package/configs/eslint-config/node_modules/.bin/eslint +21 -0
  126. package/configs/eslint-config/node_modules/.bin/tsc +21 -0
  127. package/configs/eslint-config/node_modules/.bin/tsserver +21 -0
  128. package/configs/eslint-config/package.json +12 -0
  129. package/configs/eslint-config/react.mjs +17 -0
  130. package/configs/prettier-config/base.mjs +11 -0
  131. package/configs/prettier-config/node_modules/.bin/prettier +21 -0
  132. package/configs/prettier-config/node_modules/.bin/tsc +21 -0
  133. package/configs/prettier-config/node_modules/.bin/tsserver +21 -0
  134. package/configs/prettier-config/package.json +9 -0
  135. package/configs/typescript-config/global.d.ts +12 -0
  136. package/configs/typescript-config/node_modules/.bin/tsc +21 -0
  137. package/configs/typescript-config/node_modules/.bin/tsserver +21 -0
  138. package/configs/typescript-config/package.json +7 -0
  139. package/configs/typescript-config/tsconfig.base.json +19 -0
  140. package/configs/typescript-config/tsconfig.node.json +6 -0
  141. package/configs/typescript-config/tsconfig.react.json +8 -0
  142. package/package.json +16 -0
  143. package/packages/core/eslint.config.mjs +3 -0
  144. package/packages/core/node_modules/.bin/eslint +21 -0
  145. package/packages/core/node_modules/.bin/prettier +21 -0
  146. package/packages/core/node_modules/.bin/tsc +21 -0
  147. package/packages/core/node_modules/.bin/tsserver +21 -0
  148. package/packages/core/node_modules/.bin/tsup +21 -0
  149. package/packages/core/node_modules/.bin/tsup-node +21 -0
  150. package/packages/core/node_modules/.bin/vite +21 -0
  151. package/packages/core/node_modules/.bin/vitest +21 -0
  152. package/packages/core/node_modules/.bin/yaml +21 -0
  153. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  154. package/packages/core/package.json +35 -0
  155. package/packages/core/prettier.config.mjs +3 -0
  156. package/packages/core/src/are-objects-equal.ts +26 -0
  157. package/packages/core/src/have-same-items.ts +84 -0
  158. package/packages/core/src/index.ts +6 -0
  159. package/packages/core/src/snapshot.ts +11 -0
  160. package/packages/core/src/sort-keys.ts +7 -0
  161. package/packages/core/src/spec/are-objects-equal.spec.ts +30 -0
  162. package/packages/core/src/spec/have-same-items.spec.ts +29 -0
  163. package/packages/core/src/spec/sort-keys.spec.ts +57 -0
  164. package/packages/core/tsconfig.json +7 -0
  165. package/packages/core/tsup.config.ts +15 -0
  166. package/packages/core/vitest.config.mts +11 -0
  167. package/packages/react-css/eslint.config.mjs +10 -0
  168. package/packages/react-css/node_modules/.bin/esbuild +21 -0
  169. package/packages/react-css/node_modules/.bin/eslint +21 -0
  170. package/packages/react-css/node_modules/.bin/prettier +21 -0
  171. package/packages/react-css/node_modules/.bin/tsc +21 -0
  172. package/packages/react-css/node_modules/.bin/tsserver +21 -0
  173. package/packages/react-css/node_modules/.bin/tsup +21 -0
  174. package/packages/react-css/node_modules/.bin/tsup-node +21 -0
  175. package/packages/react-css/node_modules/.bin/vitest +21 -0
  176. package/packages/react-css/node_modules/.bin/yaml +21 -0
  177. package/packages/react-css/package.json +50 -0
  178. package/packages/react-css/prettier.config.mjs +3 -0
  179. package/packages/react-css/src/button.module.css +8 -0
  180. package/packages/react-css/src/button.spec.tsx +25 -0
  181. package/packages/react-css/src/button.tsx +11 -0
  182. package/packages/react-css/src/index.ts +1 -0
  183. package/packages/react-css/tsconfig.json +7 -0
  184. package/packages/react-css/tsup.config.ts +17 -0
  185. package/packages/react-css/vitest.config.ts +15 -0
  186. package/packages/react-styled-components/eslint.config.mjs +10 -0
  187. package/packages/react-styled-components/node_modules/.bin/eslint +21 -0
  188. package/packages/react-styled-components/node_modules/.bin/prettier +21 -0
  189. package/packages/react-styled-components/node_modules/.bin/tsc +21 -0
  190. package/packages/react-styled-components/node_modules/.bin/tsserver +21 -0
  191. package/packages/react-styled-components/node_modules/.bin/tsup +21 -0
  192. package/packages/react-styled-components/node_modules/.bin/tsup-node +21 -0
  193. package/packages/react-styled-components/node_modules/.bin/vitest +21 -0
  194. package/packages/react-styled-components/node_modules/.bin/yaml +21 -0
  195. package/packages/react-styled-components/package.json +51 -0
  196. package/packages/react-styled-components/prettier.config.mjs +3 -0
  197. package/packages/react-styled-components/src/button.spec.tsx +27 -0
  198. package/packages/react-styled-components/src/button.tsx +21 -0
  199. package/packages/react-styled-components/src/index.ts +1 -0
  200. package/packages/react-styled-components/tsconfig.json +7 -0
  201. package/packages/react-styled-components/tsup.config.ts +16 -0
  202. package/packages/react-styled-components/vitest.config.ts +15 -0
  203. package/pnpm-workspace.yaml +4 -0
  204. package/turbo.json +13 -0
@@ -0,0 +1,103 @@
1
+ import path from 'path';
2
+ import { PackageJsonGenerator } from '../../../file-generator';
3
+ import { Dependency, PackageJSON } from '../../../package-json';
4
+ import { PackageGenerator } from '../../../utils/package-generator';
5
+ import { getNamespace, getWorkspaceRoot } from '../../../utils/workspace';
6
+ import { BUTTON_CSS_MODULE_FILE_GENERATOR } from './files/button-css-module-file-generator';
7
+ import { BUTTON_FILE_GENERATOR } from './files/button-file-generator';
8
+ import { BUTTON_SPEC_FILE_GENERATOR } from './files/button-spec-file-generator';
9
+ import { ESLINT_CONFIG_FILE_GENERATOR } from './files/eslint-config-file-generator';
10
+ import { INDEX_FILE_GENERATOR } from './files/index-file-generator';
11
+ import { PRETTIER_CONFIG_FILE_GENERATOR } from './files/prettier-config-file-generator';
12
+ import { TSCONFIG_FILE_GENERATOR } from './files/tsconfig-file-generator';
13
+ import { TSUP_CONFIG_FILE_GENERATOR } from './files/tsup-config-file-generator';
14
+ import { VITEST_CONFIG_FILE_GENERATOR } from './files/vitest-config-file-generator';
15
+
16
+ export async function createCssReactPackage(name: string): Promise<void> {
17
+ const rootDir = await getWorkspaceRoot();
18
+ const directory = path.join(rootDir, 'packages', name);
19
+
20
+ const namespace = await getNamespace(rootDir);
21
+ const packageName = `${namespace}/${name}`;
22
+
23
+ console.log(`✨ Creating CSS Modules React library: ${packageName}`);
24
+
25
+ const generator = new PackageGenerator(
26
+ directory,
27
+ makePackageGenerator(packageName, namespace),
28
+ [
29
+ INDEX_FILE_GENERATOR,
30
+ BUTTON_FILE_GENERATOR,
31
+ BUTTON_CSS_MODULE_FILE_GENERATOR,
32
+ BUTTON_SPEC_FILE_GENERATOR,
33
+ TSUP_CONFIG_FILE_GENERATOR,
34
+ TSCONFIG_FILE_GENERATOR,
35
+ PRETTIER_CONFIG_FILE_GENERATOR,
36
+ ESLINT_CONFIG_FILE_GENERATOR,
37
+ VITEST_CONFIG_FILE_GENERATOR,
38
+ ],
39
+ );
40
+
41
+ await generator.generate();
42
+
43
+ console.log(`✅ Library created at: ${directory}`);
44
+ }
45
+
46
+ function makePackageGenerator(packageName: string, namespace: string) {
47
+ const packageJsonModel = new PackageJSON({
48
+ name: packageName,
49
+ peerDependencies: [
50
+ new Dependency('react', '>=18'),
51
+ new Dependency('react-dom', '>=18'),
52
+ ],
53
+ devDependencies: [
54
+ new Dependency(`${namespace}/eslint-config`, 'workspace:*'),
55
+ new Dependency(`${namespace}/prettier-config`, 'workspace:*'),
56
+ new Dependency(`${namespace}/typescript-config`, 'workspace:*'),
57
+ // Development React binaries
58
+ new Dependency('react', '^18.3.1'),
59
+ new Dependency('react-dom', '^18.3.1'),
60
+ new Dependency('@types/react', '^18.3.1'),
61
+ new Dependency('@types/react-dom', '^18.3.1'),
62
+ // Linting & Formatting
63
+ new Dependency('eslint', '^9.32.0'),
64
+ new Dependency('prettier', '^3.6.2'),
65
+ new Dependency('prettier-plugin-organize-imports', '^4.2.0'),
66
+ // Build
67
+ new Dependency('tsup', '^8.0.0'),
68
+ new Dependency('postcss', '^8.4.0'),
69
+ // Testing
70
+ new Dependency('vitest', '^3.2.4'),
71
+ new Dependency('@vitest/coverage-v8', '^3.2.4'),
72
+ new Dependency('@testing-library/react', '^16.0.0'),
73
+ new Dependency('@testing-library/jest-dom', '^6.0.0'),
74
+ new Dependency('jsdom', '^25.0.0'),
75
+ ],
76
+ additionalData: {
77
+ version: '0.1.0',
78
+ private: true,
79
+ main: 'dist/index.js',
80
+ module: 'dist/index.mjs',
81
+ types: 'dist/index.d.ts',
82
+ exports: {
83
+ '.': {
84
+ development: './src/index.ts',
85
+ import: './dist/index.mjs',
86
+ require: './dist/index.js',
87
+ types: './dist/index.d.ts',
88
+ },
89
+ './index.css': './dist/index.css',
90
+ },
91
+ scripts: {
92
+ build: 'tsup',
93
+ lint: 'eslint .',
94
+ format: 'prettier . --write',
95
+ test: 'vitest run',
96
+ 'test:watch': 'vitest',
97
+ },
98
+ sideEffects: ['**/*.css'],
99
+ },
100
+ });
101
+
102
+ return new PackageJsonGenerator(packageJsonModel, namespace);
103
+ }
@@ -0,0 +1,16 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const BUTTON_CSS_MODULE = `.styledButton {
4
+ background: blue;
5
+ color: white;
6
+ padding: 10px;
7
+ border: none;
8
+ border-radius: 4px;
9
+ cursor: pointer;
10
+ }
11
+ `;
12
+
13
+ export const BUTTON_CSS_MODULE_FILE_GENERATOR = new FileGeneratorImp(
14
+ 'src/button.module.css',
15
+ BUTTON_CSS_MODULE,
16
+ );
@@ -0,0 +1,14 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const BUTTON = `import React from 'react';
4
+ import * as styles from './button.module.css';
5
+
6
+ export function Button(props: HTMLAttributes<HTMLButtonElement>) {
7
+ return <button className={styles.styledButton} {...props} />;
8
+ }
9
+ `;
10
+
11
+ export const BUTTON_FILE_GENERATOR = new FileGeneratorImp(
12
+ 'src/button.tsx',
13
+ BUTTON,
14
+ );
@@ -0,0 +1,33 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const BUTTON_SPEC = `import { render, screen, fireEvent } from '@testing-library/react';
4
+ import { Button } from './button';
5
+
6
+ describe('Button', () => {
7
+ it('renders the label correctly', () => {
8
+ render(<Button>Click Me</Button>);
9
+ expect(screen.getByText('Click Me')).toBeDefined();
10
+ });
11
+
12
+ it('is a button element', () => {
13
+ render(<Button>Submit</Button>);
14
+ const buttonElement = screen.getByRole('button');
15
+ expect(buttonElement.tagName).toBe('BUTTON');
16
+ });
17
+
18
+ /* Note: Testing for specific CSS classes with CSS Modules is tricky
19
+ because class names are mangled (e.g., _styledButton_123).
20
+ Usually, we just test that the class attribute exists.
21
+ */
22
+ it('applies a class name', () => {
23
+ render(<Button>Styled</Button>);
24
+ const buttonElement = screen.getByRole('button');
25
+ expect(buttonElement.className).toBeTruthy();
26
+ });
27
+ });
28
+ `;
29
+
30
+ export const BUTTON_SPEC_FILE_GENERATOR = new FileGeneratorImp(
31
+ 'src/button.spec.tsx',
32
+ BUTTON_SPEC,
33
+ );
@@ -0,0 +1,18 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const ESLINT_CONFIG = `import base from '@stack-dev/eslint-config/base.mjs';
4
+ import react from '@stack-dev/eslint-config/react.mjs';
5
+
6
+ export default [
7
+ ...base,
8
+ ...react,
9
+ {
10
+ ignores: ['**/dist/**', '**/coverage/**']
11
+ }
12
+ ];
13
+ `;
14
+
15
+ export const ESLINT_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
16
+ 'eslint.config.mjs',
17
+ ESLINT_CONFIG,
18
+ );
@@ -0,0 +1,9 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const INDEX_TS = `export * from './button';
4
+ `;
5
+
6
+ export const INDEX_FILE_GENERATOR = new FileGeneratorImp(
7
+ 'src/index.ts',
8
+ INDEX_TS,
9
+ );
@@ -0,0 +1,11 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const PRETTIER_CONFIG = `import base from '@stack-dev/prettier-config/base.mjs';
4
+
5
+ export default base;
6
+ `;
7
+
8
+ export const PRETTIER_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
9
+ 'prettier.config.mjs',
10
+ PRETTIER_CONFIG,
11
+ );
@@ -0,0 +1,15 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const TSCONFIG = `{
4
+ "extends": "@stack-dev/typescript-config/tsconfig.react.json",
5
+ "compilerOptions": {
6
+ "outDir": "dist"
7
+ },
8
+ "include": ["src"]
9
+ }
10
+ `;
11
+
12
+ export const TSCONFIG_FILE_GENERATOR = new FileGeneratorImp(
13
+ 'tsconfig.json',
14
+ TSCONFIG,
15
+ );
@@ -0,0 +1,24 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const TSUP_CONFIG = `import { defineConfig } from 'tsup';
4
+
5
+ export default defineConfig({
6
+ entry: ['src/index.ts'],
7
+ format: ['cjs', 'esm'],
8
+ dts: true,
9
+ minify: true,
10
+ clean: true,
11
+ injectStyle: true,
12
+ external: ['react', 'react-dom'],
13
+ outExtension({ format }) {
14
+ return {
15
+ js: format === 'esm' ? '.mjs' : '.js',
16
+ };
17
+ },
18
+ });
19
+ `;
20
+
21
+ export const TSUP_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
22
+ 'tsup.config.ts',
23
+ TSUP_CONFIG,
24
+ );
@@ -0,0 +1,23 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const VITEST_CONFIG = `import { defineConfig } from 'vitest/config';
4
+ import react from '@vitejs/plugin-react';
5
+
6
+ export default defineConfig({
7
+ plugins: [react()],
8
+ test: {
9
+ globals: true,
10
+ environment: 'jsdom',
11
+ coverage: {
12
+ provider: 'v8',
13
+ reporter: ['text', 'json', 'html'],
14
+ },
15
+ css: true,
16
+ },
17
+ });
18
+ `;
19
+
20
+ export const VITEST_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
21
+ 'vitest.config.ts',
22
+ VITEST_CONFIG,
23
+ );
@@ -0,0 +1 @@
1
+ export * from './create-react-package';
@@ -0,0 +1,112 @@
1
+ import path from 'path';
2
+ import { PackageJsonGenerator } from '../../../file-generator';
3
+ import { Dependency, PackageJSON } from '../../../package-json';
4
+ import { PackageGenerator } from '../../../utils/package-generator';
5
+ import { getNamespace, getWorkspaceRoot } from '../../../utils/workspace';
6
+ import { BUTTON_FILE_GENERATOR } from './files/button-file-generator';
7
+ import { BUTTON_SPEC_FILE_GENERATOR } from './files/button-spec-file-generator';
8
+ import { ESLINT_CONFIG_FILE_GENERATOR } from './files/eslint-config-file-generator';
9
+ import { INDEX_FILE_GENERATOR } from './files/index-file-generator';
10
+ import { PRETTIER_CONFIG_FILE_GENERATOR } from './files/prettier-config-file-generator';
11
+ import { TSCONFIG_FILE_GENERATOR } from './files/tsconfig-file-generator';
12
+ import { TSUP_CONFIG_FILE_GENERATOR } from './files/tsup-config-file-generator';
13
+ import { VITEST_CONFIG_FILE_GENERATOR } from './files/vitest-config-file-generator';
14
+
15
+ export async function createStyledComponentsReactPackage(
16
+ name: string,
17
+ ): Promise<void> {
18
+ const rootDir = await getWorkspaceRoot();
19
+ const directory = path.join(rootDir, 'packages', name);
20
+
21
+ const namespace = await getNamespace(rootDir);
22
+ const packageName = `${namespace}/${name}`;
23
+
24
+ console.log(
25
+ `✨ Creating Styled Components Modules React library: ${packageName}`,
26
+ );
27
+
28
+ const generator = new PackageGenerator(
29
+ directory,
30
+ makePackageGenerator(packageName, namespace),
31
+ [
32
+ INDEX_FILE_GENERATOR,
33
+ BUTTON_FILE_GENERATOR,
34
+ BUTTON_SPEC_FILE_GENERATOR,
35
+ TSUP_CONFIG_FILE_GENERATOR,
36
+ TSCONFIG_FILE_GENERATOR,
37
+ PRETTIER_CONFIG_FILE_GENERATOR,
38
+ ESLINT_CONFIG_FILE_GENERATOR,
39
+ VITEST_CONFIG_FILE_GENERATOR,
40
+ ],
41
+ );
42
+
43
+ await generator.generate();
44
+
45
+ console.log(`✅ Library created at: ${directory}`);
46
+ }
47
+
48
+ function makePackageGenerator(packageName: string, namespace: string) {
49
+ const packageJsonModel = new PackageJSON({
50
+ name: packageName,
51
+ // Peer deps are crucial for Styled Components to prevent "Multiple instances" errors
52
+ peerDependencies: [
53
+ new Dependency('react', '>=18'),
54
+ new Dependency('react-dom', '>=18'),
55
+ new Dependency('styled-components', '>=6'),
56
+ ],
57
+ devDependencies: [
58
+ new Dependency(`${namespace}/eslint-config`, 'workspace:*'),
59
+ new Dependency(`${namespace}/prettier-config`, 'workspace:*'),
60
+ new Dependency(`${namespace}/typescript-config`, 'workspace:*'),
61
+ // Development React binaries
62
+ new Dependency('react', '^18.3.1'),
63
+ new Dependency('react-dom', '^18.3.1'),
64
+ new Dependency('@types/react', '^18.3.1'),
65
+ new Dependency('@types/react-dom', '^18.3.1'),
66
+ // Styled Components types and binary for build time
67
+ new Dependency('styled-components', '^6.1.13'),
68
+ new Dependency('@types/styled-components', '^5.1.34'),
69
+ // Linting & Formatting
70
+ new Dependency('eslint', '^9.32.0'),
71
+ new Dependency('prettier', '^3.6.2'),
72
+ new Dependency('prettier-plugin-organize-imports', '^4.2.0'),
73
+ // Build
74
+ new Dependency('tsup', '^8.0.0'),
75
+ // Testing
76
+ new Dependency('vitest', '^3.2.4'),
77
+ new Dependency('@vitest/coverage-v8', '^3.2.4'),
78
+ new Dependency('@testing-library/react', '^16.0.0'),
79
+ new Dependency('@testing-library/jest-dom', '^6.0.0'),
80
+ new Dependency('jsdom', '^25.0.0'),
81
+ ],
82
+ additionalData: {
83
+ version: '0.1.0',
84
+ private: true,
85
+ type: 'module', // Added this to ensure ESM consistency
86
+ main: 'dist/index.js',
87
+ module: 'dist/index.mjs',
88
+ types: 'dist/index.d.ts',
89
+ exports: {
90
+ '.': {
91
+ development: './src/index.ts',
92
+ import: './dist/index.mjs',
93
+ require: './dist/index.js',
94
+ types: './dist/index.d.ts',
95
+ },
96
+ // Removed './index.css' as it's no longer produced by Styled Components
97
+ },
98
+ scripts: {
99
+ build: 'tsup',
100
+ dev: 'tsup --watch', // Helpful for local lib dev
101
+ lint: 'eslint .',
102
+ format: 'prettier . --write',
103
+ test: 'vitest run',
104
+ 'test:watch': 'vitest',
105
+ },
106
+ // Set to false or removed because Styled Components are pure JS/TS
107
+ sideEffects: false,
108
+ },
109
+ });
110
+
111
+ return new PackageJsonGenerator(packageJsonModel, namespace);
112
+ }
@@ -0,0 +1,30 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const BUTTON = `import React, { HTMLAttributes } from 'react';
4
+ import styled from 'styled-components';
5
+
6
+ // This is your "Styled" version of the button
7
+ // No more imports, no more "empty objects"
8
+ const StyledButton = styled.button\`
9
+ background-color: #007bff;
10
+ color: white;
11
+ padding: 10px 20px;
12
+ border: none;
13
+ border-radius: 4px;
14
+ cursor: pointer;
15
+ font-size: 16px;
16
+
17
+ &:hover {
18
+ background-color: #0056b3;
19
+ }
20
+ \`;
21
+
22
+ export function Button(props: HTMLAttributes<HTMLButtonElement>) {
23
+ return <StyledButton {...props} />;
24
+ }
25
+ `;
26
+
27
+ export const BUTTON_FILE_GENERATOR = new FileGeneratorImp(
28
+ 'src/button.tsx',
29
+ BUTTON,
30
+ );
@@ -0,0 +1,33 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const BUTTON_SPEC = `import { render, screen, fireEvent } from '@testing-library/react';
4
+ import { Button } from './button';
5
+
6
+ describe('Button', () => {
7
+ it('renders the label correctly', () => {
8
+ render(<Button>Click Me</Button>);
9
+ expect(screen.getByText('Click Me')).toBeDefined();
10
+ });
11
+
12
+ it('is a button element', () => {
13
+ render(<Button>Submit</Button>);
14
+ const buttonElement = screen.getByRole('button');
15
+ expect(buttonElement.tagName).toBe('BUTTON');
16
+ });
17
+
18
+ /* Note: Testing for specific CSS classes with CSS Modules is tricky
19
+ because class names are mangled (e.g., _styledButton_123).
20
+ Usually, we just test that the class attribute exists.
21
+ */
22
+ it('applies a class name', () => {
23
+ render(<Button>Styled</Button>);
24
+ const buttonElement = screen.getByRole('button');
25
+ expect(buttonElement.className).toBeTruthy();
26
+ });
27
+ });
28
+ `;
29
+
30
+ export const BUTTON_SPEC_FILE_GENERATOR = new FileGeneratorImp(
31
+ 'src/button.spec.tsx',
32
+ BUTTON_SPEC,
33
+ );
@@ -0,0 +1,18 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const ESLINT_CONFIG = `import base from '@stack-dev/eslint-config/base.mjs';
4
+ import react from '@stack-dev/eslint-config/react.mjs';
5
+
6
+ export default [
7
+ ...base,
8
+ ...react,
9
+ {
10
+ ignores: ['**/dist/**', '**/coverage/**']
11
+ }
12
+ ];
13
+ `;
14
+
15
+ export const ESLINT_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
16
+ 'eslint.config.mjs',
17
+ ESLINT_CONFIG,
18
+ );
@@ -0,0 +1,9 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const INDEX_TS = `export * from './button';
4
+ `;
5
+
6
+ export const INDEX_FILE_GENERATOR = new FileGeneratorImp(
7
+ 'src/index.ts',
8
+ INDEX_TS,
9
+ );
@@ -0,0 +1,11 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const PRETTIER_CONFIG = `import base from '@stack-dev/prettier-config/base.mjs';
4
+
5
+ export default base;
6
+ `;
7
+
8
+ export const PRETTIER_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
9
+ 'prettier.config.mjs',
10
+ PRETTIER_CONFIG,
11
+ );
@@ -0,0 +1,15 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const TSCONFIG = `{
4
+ "extends": "@stack-dev/typescript-config/tsconfig.react.json",
5
+ "compilerOptions": {
6
+ "outDir": "dist"
7
+ },
8
+ "include": ["src"]
9
+ }
10
+ `;
11
+
12
+ export const TSCONFIG_FILE_GENERATOR = new FileGeneratorImp(
13
+ 'tsconfig.json',
14
+ TSCONFIG,
15
+ );
@@ -0,0 +1,21 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const TSUP_CONFIG = `import { defineConfig } from 'tsup';
4
+
5
+ export default defineConfig({
6
+ entry: ['src/index.ts'],
7
+ format: ['esm', 'cjs'],
8
+ dts: true,
9
+ clean: true,
10
+ external: ['react', 'react-dom', 'styled-components'],
11
+ outExtension({ format }) {
12
+ return {
13
+ js: format === 'esm' ? '.mjs' : '.js',
14
+ };
15
+ },
16
+ });`;
17
+
18
+ export const TSUP_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
19
+ 'tsup.config.ts',
20
+ TSUP_CONFIG,
21
+ );
@@ -0,0 +1,23 @@
1
+ import { FileGeneratorImp } from '../../../../file-generator/file-generator-imp';
2
+
3
+ const VITEST_CONFIG = `import { defineConfig } from 'vitest/config';
4
+ import react from '@vitejs/plugin-react';
5
+
6
+ export default defineConfig({
7
+ plugins: [react()],
8
+ test: {
9
+ globals: true,
10
+ environment: 'jsdom',
11
+ coverage: {
12
+ provider: 'v8',
13
+ reporter: ['text', 'json', 'html'],
14
+ },
15
+ css: true,
16
+ },
17
+ });
18
+ `;
19
+
20
+ export const VITEST_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
21
+ 'vitest.config.ts',
22
+ VITEST_CONFIG,
23
+ );
@@ -0,0 +1,79 @@
1
+ import path from 'path';
2
+ import { PackageJsonGenerator } from '../../file-generator';
3
+ import { Dependency, PackageJSON } from '../../package-json';
4
+ import { PackageGenerator } from '../../utils/package-generator';
5
+ import { getNamespace, getWorkspaceRoot } from '../../utils/workspace';
6
+
7
+ import { INDEX_HTML_FILE_GENERATOR } from './files/index-html-file-generator';
8
+ import { MAIN_FILE_GENERATOR } from './files/main-file-generator';
9
+ import { VITE_CONFIG_FILE_GENERATOR } from './files/vite-config-file-generator';
10
+
11
+ import { APP_FILE_GENERATOR } from './files/app-file-generator';
12
+ import { ESLINT_CONFIG_FILE_GENERATOR } from './files/eslint-config-file-generator';
13
+ import { PRETTIER_CONFIG_FILE_GENERATOR } from './files/prettier-config-file-generator';
14
+ import { TSCONFIG_FILE_GENERATOR } from './files/tsconfig-file-generator';
15
+ import { VITEST_CONFIG_FILE_GENERATOR } from './files/vitest-config-file-generator';
16
+
17
+ export async function createViteReactApp(name: string): Promise<void> {
18
+ const rootDir = await getWorkspaceRoot();
19
+ const directory = path.join(rootDir, 'apps', name);
20
+
21
+ const namespace = await getNamespace(rootDir);
22
+ const packageName = `${namespace}/${name}`;
23
+
24
+ console.log(`🚀 Creating Vite React App: ${packageName}`);
25
+
26
+ const generator = new PackageGenerator(
27
+ directory,
28
+ makeAppPackageGenerator(packageName, namespace),
29
+ [
30
+ VITE_CONFIG_FILE_GENERATOR,
31
+ INDEX_HTML_FILE_GENERATOR,
32
+ MAIN_FILE_GENERATOR,
33
+ APP_FILE_GENERATOR,
34
+ TSCONFIG_FILE_GENERATOR,
35
+ PRETTIER_CONFIG_FILE_GENERATOR,
36
+ ESLINT_CONFIG_FILE_GENERATOR,
37
+ VITEST_CONFIG_FILE_GENERATOR,
38
+ ],
39
+ );
40
+
41
+ await generator.generate();
42
+ }
43
+
44
+ function makeAppPackageGenerator(packageName: string, namespace: string) {
45
+ const packageJsonModel = new PackageJSON({
46
+ name: packageName,
47
+ dependencies: [
48
+ new Dependency('react', '^18.3.1'),
49
+ new Dependency('react-dom', '^18.3.1'),
50
+ ],
51
+ devDependencies: [
52
+ new Dependency(`${namespace}/eslint-config`, 'workspace:*'),
53
+ new Dependency(`${namespace}/prettier-config`, 'workspace:*'),
54
+ new Dependency(`${namespace}/typescript-config`, 'workspace:*'),
55
+ new Dependency('@types/react', '^18.3.1'),
56
+ new Dependency('@types/react-dom', '^18.3.1'),
57
+ new Dependency('@vitejs/plugin-react', '^4.3.1'),
58
+ new Dependency('vite', '^5.4.2'),
59
+ new Dependency('typescript', '^5.5.4'),
60
+ new Dependency('eslint', '^9.32.0'),
61
+ new Dependency('prettier', '^3.6.2'),
62
+ ],
63
+ additionalData: {
64
+ version: '0.1.0',
65
+ private: true,
66
+ type: 'module',
67
+ scripts: {
68
+ dev: 'vite',
69
+ build: 'tsc && vite build',
70
+ preview: 'vite preview',
71
+ start: 'pnpm run preview',
72
+ lint: 'eslint .',
73
+ format: 'prettier . --write',
74
+ },
75
+ },
76
+ });
77
+
78
+ return new PackageJsonGenerator(packageJsonModel, namespace);
79
+ }