@stack-dev/cli 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 (82) hide show
  1. package/.turbo/daemon/6fa76abe2aa470d0-turbo.log.2025-08-02 +5 -0
  2. package/.turbo/daemon/6fa76abe2aa470d0-turbo.log.2025-12-29 +1 -0
  3. package/.turbo/daemon/6fa76abe2aa470d0-turbo.log.2025-12-30 +0 -0
  4. package/.turbo/turbo-build.log +21 -0
  5. package/.turbo/turbo-check-types.log +5 -0
  6. package/dist/index.d.mts +2 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +2097 -0
  9. package/dist/index.mjs +2073 -0
  10. package/eslint.config.mjs +3 -0
  11. package/package.json +35 -0
  12. package/prettier.config.mjs +3 -0
  13. package/src/file-generator/file-generator-imp.ts +20 -0
  14. package/src/file-generator/file-generator.ts +5 -0
  15. package/src/file-generator/index.ts +3 -0
  16. package/src/file-generator/package-json-generator.ts +23 -0
  17. package/src/index.ts +185 -0
  18. package/src/link-packages.ts +65 -0
  19. package/src/package-json/dependency.ts +28 -0
  20. package/src/package-json/index.ts +3 -0
  21. package/src/package-json/package-json.ts +269 -0
  22. package/src/packages/create-config-package.ts +29 -0
  23. package/src/packages/index.ts +4 -0
  24. package/src/packages/library-package/create-library-package.ts +85 -0
  25. package/src/packages/library-package/files/add-file-generator.ts +8 -0
  26. package/src/packages/library-package/files/add-spec-file-generator.ts +17 -0
  27. package/src/packages/library-package/files/eslint-config-file-generator.ts +11 -0
  28. package/src/packages/library-package/files/index-file-generator.ts +9 -0
  29. package/src/packages/library-package/files/prettier-config-file-generator.ts +11 -0
  30. package/src/packages/library-package/files/tsconfig-file-generator.ts +15 -0
  31. package/src/packages/library-package/files/tsup-config-file-generator.ts +23 -0
  32. package/src/packages/library-package/files/vitest-config-file-generator.ts +19 -0
  33. package/src/packages/library-package/index.ts +1 -0
  34. package/src/packages/react-package/create-react-package.ts +25 -0
  35. package/src/packages/react-package/create-tailwind-react-package.ts +30 -0
  36. package/src/packages/react-package/create-unstyled-react-package.ts +3 -0
  37. package/src/packages/react-package/css-react-package/create-css-react-package.ts +103 -0
  38. package/src/packages/react-package/css-react-package/files/button-css-module-file-generator.ts +16 -0
  39. package/src/packages/react-package/css-react-package/files/button-file-generator.ts +14 -0
  40. package/src/packages/react-package/css-react-package/files/button-spec-file-generator.ts +33 -0
  41. package/src/packages/react-package/css-react-package/files/eslint-config-file-generator.ts +18 -0
  42. package/src/packages/react-package/css-react-package/files/index-file-generator.ts +9 -0
  43. package/src/packages/react-package/css-react-package/files/prettier-config-file-generator.ts +11 -0
  44. package/src/packages/react-package/css-react-package/files/tsconfig-file-generator.ts +15 -0
  45. package/src/packages/react-package/css-react-package/files/tsup-config-file-generator.ts +24 -0
  46. package/src/packages/react-package/css-react-package/files/vitest-config-file-generator.ts +23 -0
  47. package/src/packages/react-package/index.ts +1 -0
  48. package/src/packages/react-package/styled-components-react-package/create-styled-components-react-package.ts +112 -0
  49. package/src/packages/react-package/styled-components-react-package/files/button-file-generator.ts +30 -0
  50. package/src/packages/react-package/styled-components-react-package/files/button-spec-file-generator.ts +33 -0
  51. package/src/packages/react-package/styled-components-react-package/files/eslint-config-file-generator.ts +18 -0
  52. package/src/packages/react-package/styled-components-react-package/files/index-file-generator.ts +9 -0
  53. package/src/packages/react-package/styled-components-react-package/files/prettier-config-file-generator.ts +11 -0
  54. package/src/packages/react-package/styled-components-react-package/files/tsconfig-file-generator.ts +15 -0
  55. package/src/packages/react-package/styled-components-react-package/files/tsup-config-file-generator.ts +21 -0
  56. package/src/packages/react-package/styled-components-react-package/files/vitest-config-file-generator.ts +23 -0
  57. package/src/packages/vite-react-app/create-vite-react-app.ts +79 -0
  58. package/src/packages/vite-react-app/files/app-file-generator.ts +28 -0
  59. package/src/packages/vite-react-app/files/eslint-config-file-generator.ts +11 -0
  60. package/src/packages/vite-react-app/files/index-html-file-generator.ts +20 -0
  61. package/src/packages/vite-react-app/files/main-file-generator.ts +14 -0
  62. package/src/packages/vite-react-app/files/prettier-config-file-generator.ts +11 -0
  63. package/src/packages/vite-react-app/files/tsconfig-file-generator.ts +15 -0
  64. package/src/packages/vite-react-app/files/vite-config-file-generator.ts +17 -0
  65. package/src/packages/vite-react-app/files/vitest-config-file-generator.ts +19 -0
  66. package/src/tsconfig/compiler-options.ts +83 -0
  67. package/src/tsconfig/index.ts +4 -0
  68. package/src/tsconfig/reference.ts +21 -0
  69. package/src/tsconfig/tsconfig.ts +137 -0
  70. package/src/unlink-packages.ts +47 -0
  71. package/src/utils/package-generator.ts +41 -0
  72. package/src/utils/package-type.ts +44 -0
  73. package/src/utils/package.ts +126 -0
  74. package/src/utils/style-type.ts +41 -0
  75. package/src/utils/utils.ts +28 -0
  76. package/src/utils/workspace.ts +78 -0
  77. package/src/workspace/create-workspace.ts +39 -0
  78. package/src/workspace/index.ts +1 -0
  79. package/src/workspace/root-package.ts +195 -0
  80. package/src/workspace/typescript-config.ts +84 -0
  81. package/tsconfig.json +14 -0
  82. package/tsup.config.ts +16 -0
@@ -0,0 +1,85 @@
1
+ import { getNamespace, getWorkspaceRoot } from '../../utils/workspace';
2
+
3
+ import path from 'node:path';
4
+ import { PackageJsonGenerator } from '../../file-generator';
5
+ import { Dependency, PackageJSON } from '../../package-json';
6
+ import { PackageGenerator } from '../../utils/package-generator';
7
+ import { ADD_FILE_GENERATOR } from './files/add-file-generator';
8
+ import { ADD_SPEC_FILE_GENERATOR } from './files/add-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 createLibraryPackage(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 config package: ${packageName}`);
24
+
25
+ const generator = new PackageGenerator(
26
+ directory,
27
+ makePackageGenerator(packageName, namespace),
28
+ [
29
+ INDEX_FILE_GENERATOR,
30
+ ADD_FILE_GENERATOR,
31
+ ADD_SPEC_FILE_GENERATOR,
32
+ TSUP_CONFIG_FILE_GENERATOR,
33
+ TSCONFIG_FILE_GENERATOR,
34
+ PRETTIER_CONFIG_FILE_GENERATOR,
35
+ ESLINT_CONFIG_FILE_GENERATOR,
36
+ VITEST_CONFIG_FILE_GENERATOR,
37
+ ],
38
+ );
39
+
40
+ await generator.generate();
41
+
42
+ console.log(`✅ Config package created at: ${directory}`);
43
+ }
44
+
45
+ function makePackageGenerator(packageName: string, namespace: string) {
46
+ const packageJsonModel = new PackageJSON({
47
+ name: packageName,
48
+ devDependencies: [
49
+ new Dependency(`${namespace}/eslint-config`, 'workspace:*'),
50
+ new Dependency(`${namespace}/prettier-config`, 'workspace:*'),
51
+ new Dependency(`${namespace}/typescript-config`, 'workspace:*'),
52
+ new Dependency('eslint', '^9.32.0'),
53
+ new Dependency('prettier', '^3.6.2'),
54
+ new Dependency('prettier-plugin-organize-imports', '^4.2.0'),
55
+ new Dependency('tsup', '^7.3.0'),
56
+ new Dependency('vitest', '^3.2.4'),
57
+ new Dependency('@vitest/coverage-v8', '^3.2.4'),
58
+ ],
59
+ additionalData: {
60
+ version: '0.1.0',
61
+ private: true,
62
+ main: 'dist/index.js',
63
+ module: 'dist/index.mjs',
64
+ types: 'dist/index.d.ts',
65
+ exports: {
66
+ '.': {
67
+ development: './src/index.ts',
68
+ import: './dist/index.mjs',
69
+ require: './dist/index.js',
70
+ types: './dist/index.d.ts',
71
+ },
72
+ },
73
+ scripts: {
74
+ build: 'tsup',
75
+ lint: 'eslint',
76
+ format: 'prettier . --write',
77
+ test: 'vitest run',
78
+ 'test:watch': 'vitest',
79
+ },
80
+ sideEffects: false,
81
+ },
82
+ });
83
+
84
+ return new PackageJsonGenerator(packageJsonModel, namespace);
85
+ }
@@ -0,0 +1,8 @@
1
+ import { FileGeneratorImp } from '../../../file-generator/file-generator-imp';
2
+
3
+ const ADD_TS = `export function add(n1: number, n2: number): number {
4
+ return n1 + n2;
5
+ }
6
+ `;
7
+
8
+ export const ADD_FILE_GENERATOR = new FileGeneratorImp('src/add.ts', ADD_TS);
@@ -0,0 +1,17 @@
1
+ import { FileGeneratorImp } from '../../../file-generator/file-generator-imp';
2
+
3
+ const ADD_SPEC_TS = `import { describe, it, expect } from 'vitest';
4
+
5
+ import { add } from '../add';
6
+
7
+ describe('add', () => {
8
+ it('adds two numbers', () => {
9
+ expect(add(2, 3)).toBe(5);
10
+ });
11
+ });
12
+ `;
13
+
14
+ export const ADD_SPEC_FILE_GENERATOR = new FileGeneratorImp(
15
+ 'src/spec/add.spec.ts',
16
+ ADD_SPEC_TS,
17
+ );
@@ -0,0 +1,11 @@
1
+ import { FileGeneratorImp } from '../../../file-generator/file-generator-imp';
2
+
3
+ const ESLINT_CONFIG = `import base from '@stack-dev/eslint-config/base.mjs';
4
+
5
+ export default [...base, { ignores: ['**/dist/**'] }];
6
+ `;
7
+
8
+ export const ESLINT_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
9
+ 'eslint.config.mjs',
10
+ ESLINT_CONFIG,
11
+ );
@@ -0,0 +1,9 @@
1
+ import { FileGeneratorImp } from '../../../file-generator/file-generator-imp';
2
+
3
+ const INDEX_TS = `export * from './add';
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.base.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,23 @@
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
+ sourcemap: true,
10
+ clean: true,
11
+ target: 'esnext',
12
+ outExtension({ format }) {
13
+ return {
14
+ js: format === 'esm' ? '.mjs' : '.js',
15
+ };
16
+ },
17
+ });
18
+ `;
19
+
20
+ export const TSUP_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
21
+ 'tsup.config.ts',
22
+ TSUP_CONFIG,
23
+ );
@@ -0,0 +1,19 @@
1
+ import { FileGeneratorImp } from '../../../file-generator/file-generator-imp';
2
+
3
+ const VITEST_CONFIG = `import { defineConfig } from 'vitest/config';
4
+
5
+ export default defineConfig({
6
+ test: {
7
+ globals: true,
8
+ coverage: {
9
+ provider: 'v8',
10
+ },
11
+ environment: 'node',
12
+ },
13
+ });
14
+ `;
15
+
16
+ export const VITEST_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
17
+ 'vitest.config.ts',
18
+ VITEST_CONFIG,
19
+ );
@@ -0,0 +1 @@
1
+ export * from './create-library-package';
@@ -0,0 +1,25 @@
1
+ import { StyleType } from '../../utils/style-type';
2
+ import { createTailwindReactPackage } from './create-tailwind-react-package';
3
+ import { createUnstyledReactPackage } from './create-unstyled-react-package';
4
+ import { createCssReactPackage } from './css-react-package/create-css-react-package';
5
+ import { createStyledComponentsReactPackage } from './styled-components-react-package/create-styled-components-react-package';
6
+
7
+ export async function createReactPackage(
8
+ name: string,
9
+ style: StyleType,
10
+ ): Promise<void> {
11
+ switch (style) {
12
+ case 'tailwind':
13
+ await createTailwindReactPackage(name);
14
+ break;
15
+ case 'css-modules':
16
+ await createCssReactPackage(name);
17
+ break;
18
+ case 'styled-components':
19
+ await createStyledComponentsReactPackage(name);
20
+ break;
21
+ case 'none':
22
+ await createUnstyledReactPackage(name);
23
+ break;
24
+ }
25
+ }
@@ -0,0 +1,30 @@
1
+ import { FileGeneratorImp } from "../../file-generator/file-generator-imp";
2
+
3
+ export async function createTailwindReactPackage(name: string): Promise<void> {
4
+ throw new Error('Not implemented.');
5
+ }
6
+
7
+ const STYLED_BUTTON = `import React from 'react';
8
+
9
+ interface ButtonProps {
10
+ label: string;
11
+ onClick?: () => void;
12
+ }
13
+
14
+ export function TailwindButton(props: ButtonProps) {
15
+ const {label, onClick} = props;
16
+
17
+ return (
18
+ <button
19
+ onClick={onClick}
20
+ className="my-lib-bg-blue-600 my-lib-text-white my-lib-p-[10px] my-lib-border-none my-lib-rounded my-lib-cursor-pointer hover:my-lib-brightness-110"
21
+ >
22
+ {label}
23
+ </button>
24
+ );
25
+ };`;
26
+
27
+ export const STYLED_BUTTON_FILE_GENERATOR = new FileGeneratorImp(
28
+ 'styled-button.ts',
29
+ STYLED_BUTTON,
30
+ );
@@ -0,0 +1,3 @@
1
+ export async function createUnstyledReactPackage(name: string): Promise<void> {
2
+ throw new Error('Not implemented.');
3
+ }
@@ -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
+ }