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,65 @@
1
+ import { Dependency, PackageJSON } from './package-json';
2
+ import { getDirectoryPackageJson, getPackageJSONPath } from './utils/utils';
3
+
4
+ import fs from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { TSConfig } from './tsconfig';
7
+ import { Package } from './utils/package';
8
+ import { getNamespace } from './utils/workspace';
9
+
10
+ export async function linkPackages(
11
+ current: Package,
12
+ target: Package,
13
+ development: boolean,
14
+ ): Promise<void> {
15
+ await updatePackageJSON(current, target, development);
16
+ await updateTSConfig(current, target);
17
+ }
18
+
19
+ async function updatePackageJSON(
20
+ current: Package,
21
+ target: Package,
22
+ development: boolean,
23
+ ) {
24
+ const namespace = await getNamespace();
25
+
26
+ const packageJSON = await getDirectoryPackageJson(current.directory);
27
+ const updated = addDependency(packageJSON, target, development);
28
+
29
+ const packageJSONPath = getPackageJSONPath(current.directory);
30
+
31
+ await fs.writeFile(packageJSONPath, updated.format(namespace));
32
+ }
33
+
34
+ function addDependency(
35
+ packageJSON: PackageJSON,
36
+ target: Package,
37
+ development: boolean,
38
+ ): PackageJSON {
39
+ const dependency = new Dependency(target.name, 'workspace:*');
40
+
41
+ if (development) {
42
+ return packageJSON.addDevDependency(dependency);
43
+ } else {
44
+ return packageJSON.addDependency(dependency);
45
+ }
46
+ }
47
+
48
+ async function updateTSConfig(current: Package, target: Package) {
49
+ const tsconfigPath = path.join(current.directory, 'tsconfig.json');
50
+ const tsconfigContents = await fs.readFile(tsconfigPath, 'utf8');
51
+ const tsconfig = TSConfig.parse(tsconfigContents);
52
+
53
+ const targetDirectory = path.join(target.directory, 'src', 'index.ts');
54
+
55
+ const updatedPaths = {
56
+ ...tsconfig.compilerOptions.paths,
57
+ [target.name]: [path.relative(current.directory, targetDirectory)],
58
+ };
59
+ const updatedCompilerOptions =
60
+ tsconfig.compilerOptions.setPaths(updatedPaths);
61
+
62
+ const updated = tsconfig.setCompilerOptions(updatedCompilerOptions);
63
+
64
+ await fs.writeFile(tsconfigPath, updated.format());
65
+ }
@@ -0,0 +1,28 @@
1
+ import { Equalable } from '@stack-dev/core';
2
+
3
+ export class Dependency implements Equalable {
4
+ private readonly _name: string;
5
+
6
+ private readonly _version: string;
7
+
8
+ public constructor(name: string, version: string) {
9
+ this._name = name;
10
+ this._version = version;
11
+ }
12
+
13
+ public get name(): string {
14
+ return this._name;
15
+ }
16
+
17
+ public get version(): string {
18
+ return this._version;
19
+ }
20
+
21
+ public equals(other: unknown): boolean {
22
+ if (other instanceof Dependency) {
23
+ return this._name === other._name && this._version === other._version;
24
+ } else {
25
+ return false;
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,3 @@
1
+ export * from './package-json';
2
+
3
+ export * from './dependency';
@@ -0,0 +1,269 @@
1
+ import { Equalable, haveSameItems, sortKeys } from '@stack-dev/core';
2
+
3
+ import { Snapshot } from '@stack-dev/core';
4
+ import JSON5 from 'json5';
5
+ import { isEqual } from 'lodash';
6
+ import { Dependency } from './dependency';
7
+
8
+ export type ConstructorArgs = {
9
+ name: string;
10
+ dependencies?: ReadonlyArray<Dependency>;
11
+ devDependencies?: ReadonlyArray<Dependency>;
12
+ peerDependencies?: ReadonlyArray<Dependency>;
13
+ additionalData?: Snapshot;
14
+ };
15
+
16
+ export class PackageJSON implements Equalable {
17
+ private readonly _name: string;
18
+
19
+ private readonly _dependencies: ReadonlyArray<Dependency>;
20
+
21
+ private readonly _devDependencies: ReadonlyArray<Dependency>;
22
+
23
+ private readonly _peerDependencies: ReadonlyArray<Dependency>;
24
+
25
+ private readonly _additionalData: Snapshot;
26
+
27
+ public constructor(args: ConstructorArgs) {
28
+ this._name = args.name;
29
+ this._dependencies = args.dependencies ?? [];
30
+ this._devDependencies = args.devDependencies ?? [];
31
+ this._peerDependencies = args.peerDependencies ?? [];
32
+ this._additionalData = args.additionalData ?? {};
33
+ }
34
+
35
+ public get name(): string {
36
+ return this._name;
37
+ }
38
+
39
+ public get dependencies(): ReadonlyArray<Dependency> {
40
+ return this._dependencies;
41
+ }
42
+
43
+ public get devDependencies(): ReadonlyArray<Dependency> {
44
+ return this._devDependencies;
45
+ }
46
+
47
+ public get peerDependencies(): ReadonlyArray<Dependency> {
48
+ return this._peerDependencies;
49
+ }
50
+
51
+ public addDependency(dependency: Dependency): PackageJSON {
52
+ return new PackageJSON({
53
+ name: this.name,
54
+ dependencies: [...this.dependencies, dependency],
55
+ devDependencies: this.devDependencies,
56
+ additionalData: this._additionalData,
57
+ });
58
+ }
59
+
60
+ public addDevDependency(dependency: Dependency): PackageJSON {
61
+ return new PackageJSON({
62
+ name: this.name,
63
+ dependencies: this.dependencies,
64
+ devDependencies: [...this.devDependencies, dependency],
65
+ additionalData: this._additionalData,
66
+ });
67
+ }
68
+
69
+ public addPeerDependency(dependency: Dependency): PackageJSON {
70
+ return new PackageJSON({
71
+ name: this.name,
72
+ dependencies: this.dependencies,
73
+ devDependencies: this.devDependencies,
74
+ peerDependencies: [...this.peerDependencies, dependency],
75
+ additionalData: this._additionalData,
76
+ })
77
+ }
78
+
79
+ public removeDependency(name: string): PackageJSON {
80
+ return new PackageJSON({
81
+ name: this.name,
82
+ dependencies: this.dependencies.filter((d) => d.name !== name),
83
+ devDependencies: this.devDependencies,
84
+ additionalData: this._additionalData,
85
+ });
86
+ }
87
+
88
+ public removeDevDependency(name: string): PackageJSON {
89
+ return new PackageJSON({
90
+ name: this.name,
91
+ dependencies: this.dependencies,
92
+ devDependencies: this.devDependencies.filter((d) => d.name !== name),
93
+ additionalData: this._additionalData,
94
+ });
95
+ }
96
+
97
+ public removePeerDependency(name: string): PackageJSON {
98
+ return new PackageJSON({
99
+ name: this.name,
100
+ dependencies: this.dependencies,
101
+ devDependencies: this.devDependencies,
102
+ peerDependencies: this.peerDependencies.filter((d) => d.name !== name),
103
+ additionalData: this._additionalData,
104
+ });
105
+ }
106
+
107
+ public static parse(s: string): PackageJSON {
108
+ const json = JSON5.parse(s);
109
+
110
+ const name = json.name;
111
+ const dependencies = PackageJSON.parseDependencies(json);
112
+ const devDependencies = PackageJSON.parseDevDependencies(json);
113
+ const peerDependencies = PackageJSON.parsePeerDependencies(json);
114
+
115
+ const additionalData = { ...json };
116
+ delete additionalData['name'];
117
+ delete additionalData['dependencies'];
118
+ delete additionalData['devDependencies'];
119
+ delete additionalData['peerDependencies'];
120
+
121
+ return new PackageJSON({
122
+ name,
123
+ dependencies,
124
+ devDependencies,
125
+ peerDependencies,
126
+ additionalData,
127
+ });
128
+ }
129
+
130
+ private static parseDependencies(json: Snapshot) {
131
+ if ('dependencies' in json && typeof json.dependencies === 'object') {
132
+ return Object.entries(json.dependencies).map(
133
+ ([name, version]) => new Dependency(name, version as string),
134
+ );
135
+ } else {
136
+ return [];
137
+ }
138
+ }
139
+
140
+ private static parseDevDependencies(json: Snapshot) {
141
+ if ('devDependencies' in json && typeof json.devDependencies === 'object') {
142
+ return Object.entries(json.devDependencies).map(
143
+ ([name, version]) => new Dependency(name, version as string),
144
+ );
145
+ } else {
146
+ return [];
147
+ }
148
+ }
149
+
150
+ private static parsePeerDependencies(json: Snapshot) {
151
+ if ('peerDependencies' in json && typeof json.peerDependencies === 'object') {
152
+ return Object.entries(json.peerDependencies).map(
153
+ ([name, version]) => new Dependency(name, version as string),
154
+ );
155
+ } else {
156
+ return [];
157
+ }
158
+ }
159
+
160
+ public format(namespace: string): string {
161
+ const json = {
162
+ name: this._name,
163
+ dependencies: makeDependencyObject(this._dependencies, namespace),
164
+ devDependencies: makeDependencyObject(this._devDependencies, namespace),
165
+ peerDependencies: makeDependencyObject(this._peerDependencies, namespace),
166
+ ...this._additionalData,
167
+ };
168
+
169
+ const ordered = sortKeys(json, comparePackageJSONKeys);
170
+
171
+ return JSON.stringify(ordered, null, 2);
172
+ }
173
+
174
+ public equals(other: unknown): boolean {
175
+ if (other instanceof PackageJSON) {
176
+ const sameDependencies = haveSameItems(
177
+ this._dependencies,
178
+ other._dependencies,
179
+ (d1, d2) => d1.equals(d2),
180
+ );
181
+
182
+ const sameDevDependencies = haveSameItems(
183
+ this._devDependencies,
184
+ other._devDependencies,
185
+ (d1, d2) => d1.equals(d2),
186
+ );
187
+
188
+ const samePeerDependencies = haveSameItems(
189
+ this._peerDependencies,
190
+ other._peerDependencies,
191
+ (d1, d2) => d1.equals(d2),
192
+ )
193
+
194
+ return (
195
+ this._name === other._name &&
196
+ sameDependencies &&
197
+ sameDevDependencies &&
198
+ samePeerDependencies &&
199
+ isEqual(this._additionalData, other._additionalData)
200
+ );
201
+ } else {
202
+ return false;
203
+ }
204
+ }
205
+ }
206
+
207
+ function makeDependencyObject(
208
+ dependencies: ReadonlyArray<Dependency>,
209
+ namespace: string,
210
+ ): Record<string, string> | undefined {
211
+ if (dependencies.length === 0) {
212
+ return undefined;
213
+ }
214
+
215
+ const result: Record<string, string> = {};
216
+
217
+ dependencies
218
+ .toSorted((a, b) => comparePackageNames(a.name, b.name, namespace))
219
+ .forEach((d) => (result[d.name] = d.version));
220
+
221
+ return result;
222
+ }
223
+
224
+ function comparePackageNames(a: string, b: string, namespace: string): number {
225
+ if (a.startsWith(namespace) && b.startsWith(namespace)) {
226
+ return a.localeCompare(b);
227
+ } else if (a.startsWith(namespace)) {
228
+ return -1;
229
+ } else if (b.startsWith(namespace)) {
230
+ return 1;
231
+ } else {
232
+ return a.localeCompare(b);
233
+ }
234
+ }
235
+
236
+ function comparePackageJSONKeys(a: string, b: string): number {
237
+ return getKeyIndex(a) - getKeyIndex(b);
238
+ }
239
+
240
+ function getKeyIndex(s: string): number {
241
+ switch (s.toLowerCase()) {
242
+ case 'name':
243
+ return 0;
244
+ case 'version':
245
+ return 1;
246
+ case 'private':
247
+ return 2;
248
+ case 'bin':
249
+ return 3;
250
+ case 'main':
251
+ return 4;
252
+ case 'module':
253
+ return 5;
254
+ case 'types':
255
+ return 6;
256
+ case 'exports':
257
+ return 7;
258
+ case 'scripts':
259
+ return 8;
260
+ case 'dependencies':
261
+ return 9;
262
+ case 'devDependencies':
263
+ return 10;
264
+ case 'peerdependencies':
265
+ return 11;
266
+ default:
267
+ return Number.MAX_VALUE;
268
+ }
269
+ }
@@ -0,0 +1,29 @@
1
+ import path from 'node:path';
2
+ import { PackageJSON } from '../package-json';
3
+ import { PackageJsonGenerator } from '../file-generator';
4
+ import { PackageGenerator } from '../utils/package-generator';
5
+ import { getNamespace, getWorkspaceRoot } from '../utils/workspace';
6
+
7
+ export async function createConfigPackage(name: string): Promise<void> {
8
+ const rootDir = await getWorkspaceRoot();
9
+ const directory = path.join(rootDir, 'configs', name);
10
+
11
+ const namespace = await getNamespace(rootDir);
12
+ const packageName = `${namespace}/${name}`;
13
+
14
+ const packageJsonModel = new PackageJSON({
15
+ name: packageName,
16
+ additionalData: {
17
+ version: '0.1.0',
18
+ private: true,
19
+ },
20
+ });
21
+
22
+ const generator = new PackageGenerator(
23
+ directory,
24
+ new PackageJsonGenerator(packageJsonModel, namespace),
25
+ [],
26
+ );
27
+
28
+ await generator.generate();
29
+ }
@@ -0,0 +1,4 @@
1
+ export * from './library-package';
2
+ export * from './react-package';
3
+
4
+ export * from './create-config-package';
@@ -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
+ }