@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
package/dist/index.js ADDED
@@ -0,0 +1,2097 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/utils/utils.ts
26
+ var import_promises = __toESM(require("fs/promises"));
27
+ var import_node_path = __toESM(require("path"));
28
+
29
+ // src/package-json/package-json.ts
30
+ var import_core = require("@stack-dev/core");
31
+ var import_json5 = __toESM(require("json5"));
32
+ var import_lodash = require("lodash");
33
+
34
+ // src/package-json/dependency.ts
35
+ var Dependency = class _Dependency {
36
+ _name;
37
+ _version;
38
+ constructor(name, version) {
39
+ this._name = name;
40
+ this._version = version;
41
+ }
42
+ get name() {
43
+ return this._name;
44
+ }
45
+ get version() {
46
+ return this._version;
47
+ }
48
+ equals(other) {
49
+ if (other instanceof _Dependency) {
50
+ return this._name === other._name && this._version === other._version;
51
+ } else {
52
+ return false;
53
+ }
54
+ }
55
+ };
56
+
57
+ // src/package-json/package-json.ts
58
+ var PackageJSON = class _PackageJSON {
59
+ _name;
60
+ _dependencies;
61
+ _devDependencies;
62
+ _peerDependencies;
63
+ _additionalData;
64
+ constructor(args) {
65
+ this._name = args.name;
66
+ this._dependencies = args.dependencies ?? [];
67
+ this._devDependencies = args.devDependencies ?? [];
68
+ this._peerDependencies = args.peerDependencies ?? [];
69
+ this._additionalData = args.additionalData ?? {};
70
+ }
71
+ get name() {
72
+ return this._name;
73
+ }
74
+ get dependencies() {
75
+ return this._dependencies;
76
+ }
77
+ get devDependencies() {
78
+ return this._devDependencies;
79
+ }
80
+ get peerDependencies() {
81
+ return this._peerDependencies;
82
+ }
83
+ addDependency(dependency) {
84
+ return new _PackageJSON({
85
+ name: this.name,
86
+ dependencies: [...this.dependencies, dependency],
87
+ devDependencies: this.devDependencies,
88
+ additionalData: this._additionalData
89
+ });
90
+ }
91
+ addDevDependency(dependency) {
92
+ return new _PackageJSON({
93
+ name: this.name,
94
+ dependencies: this.dependencies,
95
+ devDependencies: [...this.devDependencies, dependency],
96
+ additionalData: this._additionalData
97
+ });
98
+ }
99
+ addPeerDependency(dependency) {
100
+ return new _PackageJSON({
101
+ name: this.name,
102
+ dependencies: this.dependencies,
103
+ devDependencies: this.devDependencies,
104
+ peerDependencies: [...this.peerDependencies, dependency],
105
+ additionalData: this._additionalData
106
+ });
107
+ }
108
+ removeDependency(name) {
109
+ return new _PackageJSON({
110
+ name: this.name,
111
+ dependencies: this.dependencies.filter((d) => d.name !== name),
112
+ devDependencies: this.devDependencies,
113
+ additionalData: this._additionalData
114
+ });
115
+ }
116
+ removeDevDependency(name) {
117
+ return new _PackageJSON({
118
+ name: this.name,
119
+ dependencies: this.dependencies,
120
+ devDependencies: this.devDependencies.filter((d) => d.name !== name),
121
+ additionalData: this._additionalData
122
+ });
123
+ }
124
+ removePeerDependency(name) {
125
+ return new _PackageJSON({
126
+ name: this.name,
127
+ dependencies: this.dependencies,
128
+ devDependencies: this.devDependencies,
129
+ peerDependencies: this.peerDependencies.filter((d) => d.name !== name),
130
+ additionalData: this._additionalData
131
+ });
132
+ }
133
+ static parse(s) {
134
+ const json = import_json5.default.parse(s);
135
+ const name = json.name;
136
+ const dependencies = _PackageJSON.parseDependencies(json);
137
+ const devDependencies = _PackageJSON.parseDevDependencies(json);
138
+ const peerDependencies = _PackageJSON.parsePeerDependencies(json);
139
+ const additionalData = { ...json };
140
+ delete additionalData["name"];
141
+ delete additionalData["dependencies"];
142
+ delete additionalData["devDependencies"];
143
+ delete additionalData["peerDependencies"];
144
+ return new _PackageJSON({
145
+ name,
146
+ dependencies,
147
+ devDependencies,
148
+ peerDependencies,
149
+ additionalData
150
+ });
151
+ }
152
+ static parseDependencies(json) {
153
+ if ("dependencies" in json && typeof json.dependencies === "object") {
154
+ return Object.entries(json.dependencies).map(
155
+ ([name, version]) => new Dependency(name, version)
156
+ );
157
+ } else {
158
+ return [];
159
+ }
160
+ }
161
+ static parseDevDependencies(json) {
162
+ if ("devDependencies" in json && typeof json.devDependencies === "object") {
163
+ return Object.entries(json.devDependencies).map(
164
+ ([name, version]) => new Dependency(name, version)
165
+ );
166
+ } else {
167
+ return [];
168
+ }
169
+ }
170
+ static parsePeerDependencies(json) {
171
+ if ("peerDependencies" in json && typeof json.peerDependencies === "object") {
172
+ return Object.entries(json.peerDependencies).map(
173
+ ([name, version]) => new Dependency(name, version)
174
+ );
175
+ } else {
176
+ return [];
177
+ }
178
+ }
179
+ format(namespace) {
180
+ const json = {
181
+ name: this._name,
182
+ dependencies: makeDependencyObject(this._dependencies, namespace),
183
+ devDependencies: makeDependencyObject(this._devDependencies, namespace),
184
+ peerDependencies: makeDependencyObject(this._peerDependencies, namespace),
185
+ ...this._additionalData
186
+ };
187
+ const ordered = (0, import_core.sortKeys)(json, comparePackageJSONKeys);
188
+ return JSON.stringify(ordered, null, 2);
189
+ }
190
+ equals(other) {
191
+ if (other instanceof _PackageJSON) {
192
+ const sameDependencies = (0, import_core.haveSameItems)(
193
+ this._dependencies,
194
+ other._dependencies,
195
+ (d1, d2) => d1.equals(d2)
196
+ );
197
+ const sameDevDependencies = (0, import_core.haveSameItems)(
198
+ this._devDependencies,
199
+ other._devDependencies,
200
+ (d1, d2) => d1.equals(d2)
201
+ );
202
+ const samePeerDependencies = (0, import_core.haveSameItems)(
203
+ this._peerDependencies,
204
+ other._peerDependencies,
205
+ (d1, d2) => d1.equals(d2)
206
+ );
207
+ return this._name === other._name && sameDependencies && sameDevDependencies && samePeerDependencies && (0, import_lodash.isEqual)(this._additionalData, other._additionalData);
208
+ } else {
209
+ return false;
210
+ }
211
+ }
212
+ };
213
+ function makeDependencyObject(dependencies, namespace) {
214
+ if (dependencies.length === 0) {
215
+ return void 0;
216
+ }
217
+ const result = {};
218
+ dependencies.toSorted((a, b) => comparePackageNames(a.name, b.name, namespace)).forEach((d) => result[d.name] = d.version);
219
+ return result;
220
+ }
221
+ function comparePackageNames(a, b, namespace) {
222
+ if (a.startsWith(namespace) && b.startsWith(namespace)) {
223
+ return a.localeCompare(b);
224
+ } else if (a.startsWith(namespace)) {
225
+ return -1;
226
+ } else if (b.startsWith(namespace)) {
227
+ return 1;
228
+ } else {
229
+ return a.localeCompare(b);
230
+ }
231
+ }
232
+ function comparePackageJSONKeys(a, b) {
233
+ return getKeyIndex(a) - getKeyIndex(b);
234
+ }
235
+ function getKeyIndex(s) {
236
+ switch (s.toLowerCase()) {
237
+ case "name":
238
+ return 0;
239
+ case "version":
240
+ return 1;
241
+ case "private":
242
+ return 2;
243
+ case "bin":
244
+ return 3;
245
+ case "main":
246
+ return 4;
247
+ case "module":
248
+ return 5;
249
+ case "types":
250
+ return 6;
251
+ case "exports":
252
+ return 7;
253
+ case "scripts":
254
+ return 8;
255
+ case "dependencies":
256
+ return 9;
257
+ case "devDependencies":
258
+ return 10;
259
+ case "peerdependencies":
260
+ return 11;
261
+ default:
262
+ return Number.MAX_VALUE;
263
+ }
264
+ }
265
+
266
+ // src/utils/utils.ts
267
+ async function getDirectoryPackageJson(directory) {
268
+ const packageJsonPath = getPackageJSONPath(directory);
269
+ const packageJsonText = await import_promises.default.readFile(packageJsonPath, {
270
+ encoding: "utf-8"
271
+ });
272
+ return PackageJSON.parse(packageJsonText);
273
+ }
274
+ function getPackageJSONPath(directory) {
275
+ return import_node_path.default.join(directory, "package.json");
276
+ }
277
+ async function fileExists(filepath) {
278
+ try {
279
+ await import_promises.default.access(filepath, import_promises.default.constants.F_OK);
280
+ return true;
281
+ } catch {
282
+ return false;
283
+ }
284
+ }
285
+
286
+ // src/utils/workspace.ts
287
+ var import_promises2 = __toESM(require("fs/promises"));
288
+ var import_path = __toESM(require("path"));
289
+ var import_yaml = __toESM(require("yaml"));
290
+ async function getDirectoryWorkspaceFile(directory) {
291
+ const raw = await getRawDirectoryWorkspaceFile(directory);
292
+ if ("packages" in raw && raw.packages instanceof Array) {
293
+ return {
294
+ packages: raw.packages.filter((p) => typeof p === "string")
295
+ };
296
+ } else {
297
+ return { packages: [] };
298
+ }
299
+ }
300
+ async function getRawDirectoryWorkspaceFile(directory) {
301
+ const case1 = import_path.default.join(directory, "pnpm-workspace.yaml");
302
+ const case2 = import_path.default.join(directory, "pnpm-workspace.yml");
303
+ if (await fileExists(case1)) {
304
+ return import_yaml.default.parse(await import_promises2.default.readFile(case1, { encoding: "utf-8" }));
305
+ } else if (await fileExists(case2)) {
306
+ return import_yaml.default.parse(await import_promises2.default.readFile(case2, { encoding: "utf-8" }));
307
+ } else {
308
+ throw new Error(`Directory "${directory}" is not a workspace.`);
309
+ }
310
+ }
311
+ async function isWorkspaceRoot(directory) {
312
+ return await fileExists(import_path.default.join(directory, "pnpm-workspace.yaml")) || await fileExists(import_path.default.join(directory, "pnpm-workspace.yml"));
313
+ }
314
+ async function getWorkspaceRoot(directory = process.cwd()) {
315
+ const parent = import_path.default.dirname(directory);
316
+ if (parent === directory) {
317
+ throw new Error("Not a workspace.");
318
+ }
319
+ if (await isWorkspaceRoot(directory)) {
320
+ return directory;
321
+ }
322
+ return getWorkspaceRoot(parent);
323
+ }
324
+ async function getNamespace(directory = process.cwd()) {
325
+ const root = await getWorkspaceRoot(directory);
326
+ const packageJson = await getDirectoryPackageJson(root);
327
+ const result = packageJson.name;
328
+ if (!result) {
329
+ throw new Error("Missing name.");
330
+ }
331
+ return `@${result}`;
332
+ }
333
+
334
+ // src/packages/library-package/create-library-package.ts
335
+ var import_node_path3 = __toESM(require("path"));
336
+
337
+ // src/file-generator/package-json-generator.ts
338
+ var PackageJsonGenerator = class {
339
+ _packageJson;
340
+ _namespace;
341
+ constructor(packageJson, namespace = "") {
342
+ this._packageJson = packageJson;
343
+ this._namespace = namespace;
344
+ }
345
+ get filepath() {
346
+ return "package.json";
347
+ }
348
+ async generate() {
349
+ return this._packageJson.format(this._namespace);
350
+ }
351
+ };
352
+
353
+ // src/utils/package-generator.ts
354
+ var import_promises3 = __toESM(require("fs/promises"));
355
+ var import_node_path2 = __toESM(require("path"));
356
+ var PackageGenerator = class {
357
+ _root;
358
+ _packageJson;
359
+ _fileGenerators;
360
+ constructor(root, packageJson, fileGenerators = []) {
361
+ this._root = root;
362
+ this._packageJson = packageJson;
363
+ this._fileGenerators = fileGenerators;
364
+ }
365
+ async generate() {
366
+ const all = [this._packageJson, ...this._fileGenerators];
367
+ await import_promises3.default.mkdir(this._root, { recursive: true });
368
+ await Promise.all(all.map((gen) => this.write(gen)));
369
+ }
370
+ async write(fileGenerator) {
371
+ const contents = await fileGenerator.generate();
372
+ const filepath = import_node_path2.default.join(this._root, fileGenerator.filepath);
373
+ const directory = import_node_path2.default.dirname(filepath);
374
+ await import_promises3.default.mkdir(directory, { recursive: true });
375
+ await import_promises3.default.writeFile(filepath, contents);
376
+ }
377
+ };
378
+
379
+ // src/file-generator/file-generator-imp.ts
380
+ var FileGeneratorImp = class {
381
+ _filepath;
382
+ _contents;
383
+ constructor(filepath, contents) {
384
+ this._filepath = filepath;
385
+ this._contents = contents;
386
+ }
387
+ get filepath() {
388
+ return this._filepath;
389
+ }
390
+ async generate() {
391
+ return this._contents;
392
+ }
393
+ };
394
+
395
+ // src/packages/library-package/files/add-file-generator.ts
396
+ var ADD_TS = `export function add(n1: number, n2: number): number {
397
+ return n1 + n2;
398
+ }
399
+ `;
400
+ var ADD_FILE_GENERATOR = new FileGeneratorImp("src/add.ts", ADD_TS);
401
+
402
+ // src/packages/library-package/files/add-spec-file-generator.ts
403
+ var ADD_SPEC_TS = `import { describe, it, expect } from 'vitest';
404
+
405
+ import { add } from '../add';
406
+
407
+ describe('add', () => {
408
+ it('adds two numbers', () => {
409
+ expect(add(2, 3)).toBe(5);
410
+ });
411
+ });
412
+ `;
413
+ var ADD_SPEC_FILE_GENERATOR = new FileGeneratorImp(
414
+ "src/spec/add.spec.ts",
415
+ ADD_SPEC_TS
416
+ );
417
+
418
+ // src/packages/library-package/files/eslint-config-file-generator.ts
419
+ var ESLINT_CONFIG = `import base from '@stack-dev/eslint-config/base.mjs';
420
+
421
+ export default [...base, { ignores: ['**/dist/**'] }];
422
+ `;
423
+ var ESLINT_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
424
+ "eslint.config.mjs",
425
+ ESLINT_CONFIG
426
+ );
427
+
428
+ // src/packages/library-package/files/index-file-generator.ts
429
+ var INDEX_TS = `export * from './add';
430
+ `;
431
+ var INDEX_FILE_GENERATOR = new FileGeneratorImp(
432
+ "src/index.ts",
433
+ INDEX_TS
434
+ );
435
+
436
+ // src/packages/library-package/files/prettier-config-file-generator.ts
437
+ var PRETTIER_CONFIG = `import base from '@stack-dev/prettier-config/base.mjs';
438
+
439
+ export default base;
440
+ `;
441
+ var PRETTIER_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
442
+ "prettier.config.mjs",
443
+ PRETTIER_CONFIG
444
+ );
445
+
446
+ // src/packages/library-package/files/tsconfig-file-generator.ts
447
+ var TSCONFIG = `{
448
+ "extends": "@stack-dev/typescript-config/tsconfig.base.json",
449
+ "compilerOptions": {
450
+ "outDir": "dist"
451
+ },
452
+ "include": ["src"]
453
+ }
454
+ `;
455
+ var TSCONFIG_FILE_GENERATOR = new FileGeneratorImp(
456
+ "tsconfig.json",
457
+ TSCONFIG
458
+ );
459
+
460
+ // src/packages/library-package/files/tsup-config-file-generator.ts
461
+ var TSUP_CONFIG = `import { defineConfig } from 'tsup';
462
+
463
+ export default defineConfig({
464
+ entry: ['src/index.ts'],
465
+ format: ['esm', 'cjs'],
466
+ dts: true,
467
+ sourcemap: true,
468
+ clean: true,
469
+ target: 'esnext',
470
+ outExtension({ format }) {
471
+ return {
472
+ js: format === 'esm' ? '.mjs' : '.js',
473
+ };
474
+ },
475
+ });
476
+ `;
477
+ var TSUP_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
478
+ "tsup.config.ts",
479
+ TSUP_CONFIG
480
+ );
481
+
482
+ // src/packages/library-package/files/vitest-config-file-generator.ts
483
+ var VITEST_CONFIG = `import { defineConfig } from 'vitest/config';
484
+
485
+ export default defineConfig({
486
+ test: {
487
+ globals: true,
488
+ coverage: {
489
+ provider: 'v8',
490
+ },
491
+ environment: 'node',
492
+ },
493
+ });
494
+ `;
495
+ var VITEST_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
496
+ "vitest.config.ts",
497
+ VITEST_CONFIG
498
+ );
499
+
500
+ // src/packages/library-package/create-library-package.ts
501
+ async function createLibraryPackage(name) {
502
+ const rootDir = await getWorkspaceRoot();
503
+ const directory = import_node_path3.default.join(rootDir, "packages", name);
504
+ const namespace = await getNamespace(rootDir);
505
+ const packageName = `${namespace}/${name}`;
506
+ console.log(`\u2728 Creating config package: ${packageName}`);
507
+ const generator = new PackageGenerator(
508
+ directory,
509
+ makePackageGenerator(packageName, namespace),
510
+ [
511
+ INDEX_FILE_GENERATOR,
512
+ ADD_FILE_GENERATOR,
513
+ ADD_SPEC_FILE_GENERATOR,
514
+ TSUP_CONFIG_FILE_GENERATOR,
515
+ TSCONFIG_FILE_GENERATOR,
516
+ PRETTIER_CONFIG_FILE_GENERATOR,
517
+ ESLINT_CONFIG_FILE_GENERATOR,
518
+ VITEST_CONFIG_FILE_GENERATOR
519
+ ]
520
+ );
521
+ await generator.generate();
522
+ console.log(`\u2705 Config package created at: ${directory}`);
523
+ }
524
+ function makePackageGenerator(packageName, namespace) {
525
+ const packageJsonModel = new PackageJSON({
526
+ name: packageName,
527
+ devDependencies: [
528
+ new Dependency(`${namespace}/eslint-config`, "workspace:*"),
529
+ new Dependency(`${namespace}/prettier-config`, "workspace:*"),
530
+ new Dependency(`${namespace}/typescript-config`, "workspace:*"),
531
+ new Dependency("eslint", "^9.32.0"),
532
+ new Dependency("prettier", "^3.6.2"),
533
+ new Dependency("prettier-plugin-organize-imports", "^4.2.0"),
534
+ new Dependency("tsup", "^7.3.0"),
535
+ new Dependency("vitest", "^3.2.4"),
536
+ new Dependency("@vitest/coverage-v8", "^3.2.4")
537
+ ],
538
+ additionalData: {
539
+ version: "0.1.0",
540
+ private: true,
541
+ main: "dist/index.js",
542
+ module: "dist/index.mjs",
543
+ types: "dist/index.d.ts",
544
+ exports: {
545
+ ".": {
546
+ development: "./src/index.ts",
547
+ import: "./dist/index.mjs",
548
+ require: "./dist/index.js",
549
+ types: "./dist/index.d.ts"
550
+ }
551
+ },
552
+ scripts: {
553
+ build: "tsup",
554
+ lint: "eslint",
555
+ format: "prettier . --write",
556
+ test: "vitest run",
557
+ "test:watch": "vitest"
558
+ },
559
+ sideEffects: false
560
+ }
561
+ });
562
+ return new PackageJsonGenerator(packageJsonModel, namespace);
563
+ }
564
+
565
+ // src/packages/react-package/create-tailwind-react-package.ts
566
+ async function createTailwindReactPackage(name) {
567
+ throw new Error("Not implemented.");
568
+ }
569
+ var STYLED_BUTTON = `import React from 'react';
570
+
571
+ interface ButtonProps {
572
+ label: string;
573
+ onClick?: () => void;
574
+ }
575
+
576
+ export function TailwindButton(props: ButtonProps) {
577
+ const {label, onClick} = props;
578
+
579
+ return (
580
+ <button
581
+ onClick={onClick}
582
+ 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"
583
+ >
584
+ {label}
585
+ </button>
586
+ );
587
+ };`;
588
+ var STYLED_BUTTON_FILE_GENERATOR = new FileGeneratorImp(
589
+ "styled-button.ts",
590
+ STYLED_BUTTON
591
+ );
592
+
593
+ // src/packages/react-package/create-unstyled-react-package.ts
594
+ async function createUnstyledReactPackage(name) {
595
+ throw new Error("Not implemented.");
596
+ }
597
+
598
+ // src/packages/react-package/css-react-package/create-css-react-package.ts
599
+ var import_path2 = __toESM(require("path"));
600
+
601
+ // src/packages/react-package/css-react-package/files/button-css-module-file-generator.ts
602
+ var BUTTON_CSS_MODULE = `.styledButton {
603
+ background: blue;
604
+ color: white;
605
+ padding: 10px;
606
+ border: none;
607
+ border-radius: 4px;
608
+ cursor: pointer;
609
+ }
610
+ `;
611
+ var BUTTON_CSS_MODULE_FILE_GENERATOR = new FileGeneratorImp(
612
+ "src/button.module.css",
613
+ BUTTON_CSS_MODULE
614
+ );
615
+
616
+ // src/packages/react-package/css-react-package/files/button-file-generator.ts
617
+ var BUTTON = `import React from 'react';
618
+ import * as styles from './button.module.css';
619
+
620
+ export function Button(props: HTMLAttributes<HTMLButtonElement>) {
621
+ return <button className={styles.styledButton} {...props} />;
622
+ }
623
+ `;
624
+ var BUTTON_FILE_GENERATOR = new FileGeneratorImp(
625
+ "src/button.tsx",
626
+ BUTTON
627
+ );
628
+
629
+ // src/packages/react-package/css-react-package/files/button-spec-file-generator.ts
630
+ var BUTTON_SPEC = `import { render, screen, fireEvent } from '@testing-library/react';
631
+ import { Button } from './button';
632
+
633
+ describe('Button', () => {
634
+ it('renders the label correctly', () => {
635
+ render(<Button>Click Me</Button>);
636
+ expect(screen.getByText('Click Me')).toBeDefined();
637
+ });
638
+
639
+ it('is a button element', () => {
640
+ render(<Button>Submit</Button>);
641
+ const buttonElement = screen.getByRole('button');
642
+ expect(buttonElement.tagName).toBe('BUTTON');
643
+ });
644
+
645
+ /* Note: Testing for specific CSS classes with CSS Modules is tricky
646
+ because class names are mangled (e.g., _styledButton_123).
647
+ Usually, we just test that the class attribute exists.
648
+ */
649
+ it('applies a class name', () => {
650
+ render(<Button>Styled</Button>);
651
+ const buttonElement = screen.getByRole('button');
652
+ expect(buttonElement.className).toBeTruthy();
653
+ });
654
+ });
655
+ `;
656
+ var BUTTON_SPEC_FILE_GENERATOR = new FileGeneratorImp(
657
+ "src/button.spec.tsx",
658
+ BUTTON_SPEC
659
+ );
660
+
661
+ // src/packages/react-package/css-react-package/files/eslint-config-file-generator.ts
662
+ var ESLINT_CONFIG2 = `import base from '@stack-dev/eslint-config/base.mjs';
663
+ import react from '@stack-dev/eslint-config/react.mjs';
664
+
665
+ export default [
666
+ ...base,
667
+ ...react,
668
+ {
669
+ ignores: ['**/dist/**', '**/coverage/**']
670
+ }
671
+ ];
672
+ `;
673
+ var ESLINT_CONFIG_FILE_GENERATOR2 = new FileGeneratorImp(
674
+ "eslint.config.mjs",
675
+ ESLINT_CONFIG2
676
+ );
677
+
678
+ // src/packages/react-package/css-react-package/files/index-file-generator.ts
679
+ var INDEX_TS2 = `export * from './button';
680
+ `;
681
+ var INDEX_FILE_GENERATOR2 = new FileGeneratorImp(
682
+ "src/index.ts",
683
+ INDEX_TS2
684
+ );
685
+
686
+ // src/packages/react-package/css-react-package/files/prettier-config-file-generator.ts
687
+ var PRETTIER_CONFIG2 = `import base from '@stack-dev/prettier-config/base.mjs';
688
+
689
+ export default base;
690
+ `;
691
+ var PRETTIER_CONFIG_FILE_GENERATOR2 = new FileGeneratorImp(
692
+ "prettier.config.mjs",
693
+ PRETTIER_CONFIG2
694
+ );
695
+
696
+ // src/packages/react-package/css-react-package/files/tsconfig-file-generator.ts
697
+ var TSCONFIG2 = `{
698
+ "extends": "@stack-dev/typescript-config/tsconfig.react.json",
699
+ "compilerOptions": {
700
+ "outDir": "dist"
701
+ },
702
+ "include": ["src"]
703
+ }
704
+ `;
705
+ var TSCONFIG_FILE_GENERATOR2 = new FileGeneratorImp(
706
+ "tsconfig.json",
707
+ TSCONFIG2
708
+ );
709
+
710
+ // src/packages/react-package/css-react-package/files/tsup-config-file-generator.ts
711
+ var TSUP_CONFIG2 = `import { defineConfig } from 'tsup';
712
+
713
+ export default defineConfig({
714
+ entry: ['src/index.ts'],
715
+ format: ['cjs', 'esm'],
716
+ dts: true,
717
+ minify: true,
718
+ clean: true,
719
+ injectStyle: true,
720
+ external: ['react', 'react-dom'],
721
+ outExtension({ format }) {
722
+ return {
723
+ js: format === 'esm' ? '.mjs' : '.js',
724
+ };
725
+ },
726
+ });
727
+ `;
728
+ var TSUP_CONFIG_FILE_GENERATOR2 = new FileGeneratorImp(
729
+ "tsup.config.ts",
730
+ TSUP_CONFIG2
731
+ );
732
+
733
+ // src/packages/react-package/css-react-package/files/vitest-config-file-generator.ts
734
+ var VITEST_CONFIG2 = `import { defineConfig } from 'vitest/config';
735
+ import react from '@vitejs/plugin-react';
736
+
737
+ export default defineConfig({
738
+ plugins: [react()],
739
+ test: {
740
+ globals: true,
741
+ environment: 'jsdom',
742
+ coverage: {
743
+ provider: 'v8',
744
+ reporter: ['text', 'json', 'html'],
745
+ },
746
+ css: true,
747
+ },
748
+ });
749
+ `;
750
+ var VITEST_CONFIG_FILE_GENERATOR2 = new FileGeneratorImp(
751
+ "vitest.config.ts",
752
+ VITEST_CONFIG2
753
+ );
754
+
755
+ // src/packages/react-package/css-react-package/create-css-react-package.ts
756
+ async function createCssReactPackage(name) {
757
+ const rootDir = await getWorkspaceRoot();
758
+ const directory = import_path2.default.join(rootDir, "packages", name);
759
+ const namespace = await getNamespace(rootDir);
760
+ const packageName = `${namespace}/${name}`;
761
+ console.log(`\u2728 Creating CSS Modules React library: ${packageName}`);
762
+ const generator = new PackageGenerator(
763
+ directory,
764
+ makePackageGenerator2(packageName, namespace),
765
+ [
766
+ INDEX_FILE_GENERATOR2,
767
+ BUTTON_FILE_GENERATOR,
768
+ BUTTON_CSS_MODULE_FILE_GENERATOR,
769
+ BUTTON_SPEC_FILE_GENERATOR,
770
+ TSUP_CONFIG_FILE_GENERATOR2,
771
+ TSCONFIG_FILE_GENERATOR2,
772
+ PRETTIER_CONFIG_FILE_GENERATOR2,
773
+ ESLINT_CONFIG_FILE_GENERATOR2,
774
+ VITEST_CONFIG_FILE_GENERATOR2
775
+ ]
776
+ );
777
+ await generator.generate();
778
+ console.log(`\u2705 Library created at: ${directory}`);
779
+ }
780
+ function makePackageGenerator2(packageName, namespace) {
781
+ const packageJsonModel = new PackageJSON({
782
+ name: packageName,
783
+ peerDependencies: [
784
+ new Dependency("react", ">=18"),
785
+ new Dependency("react-dom", ">=18")
786
+ ],
787
+ devDependencies: [
788
+ new Dependency(`${namespace}/eslint-config`, "workspace:*"),
789
+ new Dependency(`${namespace}/prettier-config`, "workspace:*"),
790
+ new Dependency(`${namespace}/typescript-config`, "workspace:*"),
791
+ // Development React binaries
792
+ new Dependency("react", "^18.3.1"),
793
+ new Dependency("react-dom", "^18.3.1"),
794
+ new Dependency("@types/react", "^18.3.1"),
795
+ new Dependency("@types/react-dom", "^18.3.1"),
796
+ // Linting & Formatting
797
+ new Dependency("eslint", "^9.32.0"),
798
+ new Dependency("prettier", "^3.6.2"),
799
+ new Dependency("prettier-plugin-organize-imports", "^4.2.0"),
800
+ // Build
801
+ new Dependency("tsup", "^8.0.0"),
802
+ new Dependency("postcss", "^8.4.0"),
803
+ // Testing
804
+ new Dependency("vitest", "^3.2.4"),
805
+ new Dependency("@vitest/coverage-v8", "^3.2.4"),
806
+ new Dependency("@testing-library/react", "^16.0.0"),
807
+ new Dependency("@testing-library/jest-dom", "^6.0.0"),
808
+ new Dependency("jsdom", "^25.0.0")
809
+ ],
810
+ additionalData: {
811
+ version: "0.1.0",
812
+ private: true,
813
+ main: "dist/index.js",
814
+ module: "dist/index.mjs",
815
+ types: "dist/index.d.ts",
816
+ exports: {
817
+ ".": {
818
+ development: "./src/index.ts",
819
+ import: "./dist/index.mjs",
820
+ require: "./dist/index.js",
821
+ types: "./dist/index.d.ts"
822
+ },
823
+ "./index.css": "./dist/index.css"
824
+ },
825
+ scripts: {
826
+ build: "tsup",
827
+ lint: "eslint .",
828
+ format: "prettier . --write",
829
+ test: "vitest run",
830
+ "test:watch": "vitest"
831
+ },
832
+ sideEffects: ["**/*.css"]
833
+ }
834
+ });
835
+ return new PackageJsonGenerator(packageJsonModel, namespace);
836
+ }
837
+
838
+ // src/packages/react-package/styled-components-react-package/create-styled-components-react-package.ts
839
+ var import_path3 = __toESM(require("path"));
840
+
841
+ // src/packages/react-package/styled-components-react-package/files/button-file-generator.ts
842
+ var BUTTON2 = `import React, { HTMLAttributes } from 'react';
843
+ import styled from 'styled-components';
844
+
845
+ // This is your "Styled" version of the button
846
+ // No more imports, no more "empty objects"
847
+ const StyledButton = styled.button\`
848
+ background-color: #007bff;
849
+ color: white;
850
+ padding: 10px 20px;
851
+ border: none;
852
+ border-radius: 4px;
853
+ cursor: pointer;
854
+ font-size: 16px;
855
+
856
+ &:hover {
857
+ background-color: #0056b3;
858
+ }
859
+ \`;
860
+
861
+ export function Button(props: HTMLAttributes<HTMLButtonElement>) {
862
+ return <StyledButton {...props} />;
863
+ }
864
+ `;
865
+ var BUTTON_FILE_GENERATOR2 = new FileGeneratorImp(
866
+ "src/button.tsx",
867
+ BUTTON2
868
+ );
869
+
870
+ // src/packages/react-package/styled-components-react-package/files/button-spec-file-generator.ts
871
+ var BUTTON_SPEC2 = `import { render, screen, fireEvent } from '@testing-library/react';
872
+ import { Button } from './button';
873
+
874
+ describe('Button', () => {
875
+ it('renders the label correctly', () => {
876
+ render(<Button>Click Me</Button>);
877
+ expect(screen.getByText('Click Me')).toBeDefined();
878
+ });
879
+
880
+ it('is a button element', () => {
881
+ render(<Button>Submit</Button>);
882
+ const buttonElement = screen.getByRole('button');
883
+ expect(buttonElement.tagName).toBe('BUTTON');
884
+ });
885
+
886
+ /* Note: Testing for specific CSS classes with CSS Modules is tricky
887
+ because class names are mangled (e.g., _styledButton_123).
888
+ Usually, we just test that the class attribute exists.
889
+ */
890
+ it('applies a class name', () => {
891
+ render(<Button>Styled</Button>);
892
+ const buttonElement = screen.getByRole('button');
893
+ expect(buttonElement.className).toBeTruthy();
894
+ });
895
+ });
896
+ `;
897
+ var BUTTON_SPEC_FILE_GENERATOR2 = new FileGeneratorImp(
898
+ "src/button.spec.tsx",
899
+ BUTTON_SPEC2
900
+ );
901
+
902
+ // src/packages/react-package/styled-components-react-package/files/eslint-config-file-generator.ts
903
+ var ESLINT_CONFIG3 = `import base from '@stack-dev/eslint-config/base.mjs';
904
+ import react from '@stack-dev/eslint-config/react.mjs';
905
+
906
+ export default [
907
+ ...base,
908
+ ...react,
909
+ {
910
+ ignores: ['**/dist/**', '**/coverage/**']
911
+ }
912
+ ];
913
+ `;
914
+ var ESLINT_CONFIG_FILE_GENERATOR3 = new FileGeneratorImp(
915
+ "eslint.config.mjs",
916
+ ESLINT_CONFIG3
917
+ );
918
+
919
+ // src/packages/react-package/styled-components-react-package/files/index-file-generator.ts
920
+ var INDEX_TS3 = `export * from './button';
921
+ `;
922
+ var INDEX_FILE_GENERATOR3 = new FileGeneratorImp(
923
+ "src/index.ts",
924
+ INDEX_TS3
925
+ );
926
+
927
+ // src/packages/react-package/styled-components-react-package/files/prettier-config-file-generator.ts
928
+ var PRETTIER_CONFIG3 = `import base from '@stack-dev/prettier-config/base.mjs';
929
+
930
+ export default base;
931
+ `;
932
+ var PRETTIER_CONFIG_FILE_GENERATOR3 = new FileGeneratorImp(
933
+ "prettier.config.mjs",
934
+ PRETTIER_CONFIG3
935
+ );
936
+
937
+ // src/packages/react-package/styled-components-react-package/files/tsconfig-file-generator.ts
938
+ var TSCONFIG3 = `{
939
+ "extends": "@stack-dev/typescript-config/tsconfig.react.json",
940
+ "compilerOptions": {
941
+ "outDir": "dist"
942
+ },
943
+ "include": ["src"]
944
+ }
945
+ `;
946
+ var TSCONFIG_FILE_GENERATOR3 = new FileGeneratorImp(
947
+ "tsconfig.json",
948
+ TSCONFIG3
949
+ );
950
+
951
+ // src/packages/react-package/styled-components-react-package/files/tsup-config-file-generator.ts
952
+ var TSUP_CONFIG3 = `import { defineConfig } from 'tsup';
953
+
954
+ export default defineConfig({
955
+ entry: ['src/index.ts'],
956
+ format: ['esm', 'cjs'],
957
+ dts: true,
958
+ clean: true,
959
+ external: ['react', 'react-dom', 'styled-components'],
960
+ outExtension({ format }) {
961
+ return {
962
+ js: format === 'esm' ? '.mjs' : '.js',
963
+ };
964
+ },
965
+ });`;
966
+ var TSUP_CONFIG_FILE_GENERATOR3 = new FileGeneratorImp(
967
+ "tsup.config.ts",
968
+ TSUP_CONFIG3
969
+ );
970
+
971
+ // src/packages/react-package/styled-components-react-package/files/vitest-config-file-generator.ts
972
+ var VITEST_CONFIG3 = `import { defineConfig } from 'vitest/config';
973
+ import react from '@vitejs/plugin-react';
974
+
975
+ export default defineConfig({
976
+ plugins: [react()],
977
+ test: {
978
+ globals: true,
979
+ environment: 'jsdom',
980
+ coverage: {
981
+ provider: 'v8',
982
+ reporter: ['text', 'json', 'html'],
983
+ },
984
+ css: true,
985
+ },
986
+ });
987
+ `;
988
+ var VITEST_CONFIG_FILE_GENERATOR3 = new FileGeneratorImp(
989
+ "vitest.config.ts",
990
+ VITEST_CONFIG3
991
+ );
992
+
993
+ // src/packages/react-package/styled-components-react-package/create-styled-components-react-package.ts
994
+ async function createStyledComponentsReactPackage(name) {
995
+ const rootDir = await getWorkspaceRoot();
996
+ const directory = import_path3.default.join(rootDir, "packages", name);
997
+ const namespace = await getNamespace(rootDir);
998
+ const packageName = `${namespace}/${name}`;
999
+ console.log(
1000
+ `\u2728 Creating Styled Components Modules React library: ${packageName}`
1001
+ );
1002
+ const generator = new PackageGenerator(
1003
+ directory,
1004
+ makePackageGenerator3(packageName, namespace),
1005
+ [
1006
+ INDEX_FILE_GENERATOR3,
1007
+ BUTTON_FILE_GENERATOR2,
1008
+ BUTTON_SPEC_FILE_GENERATOR2,
1009
+ TSUP_CONFIG_FILE_GENERATOR3,
1010
+ TSCONFIG_FILE_GENERATOR3,
1011
+ PRETTIER_CONFIG_FILE_GENERATOR3,
1012
+ ESLINT_CONFIG_FILE_GENERATOR3,
1013
+ VITEST_CONFIG_FILE_GENERATOR3
1014
+ ]
1015
+ );
1016
+ await generator.generate();
1017
+ console.log(`\u2705 Library created at: ${directory}`);
1018
+ }
1019
+ function makePackageGenerator3(packageName, namespace) {
1020
+ const packageJsonModel = new PackageJSON({
1021
+ name: packageName,
1022
+ // Peer deps are crucial for Styled Components to prevent "Multiple instances" errors
1023
+ peerDependencies: [
1024
+ new Dependency("react", ">=18"),
1025
+ new Dependency("react-dom", ">=18"),
1026
+ new Dependency("styled-components", ">=6")
1027
+ ],
1028
+ devDependencies: [
1029
+ new Dependency(`${namespace}/eslint-config`, "workspace:*"),
1030
+ new Dependency(`${namespace}/prettier-config`, "workspace:*"),
1031
+ new Dependency(`${namespace}/typescript-config`, "workspace:*"),
1032
+ // Development React binaries
1033
+ new Dependency("react", "^18.3.1"),
1034
+ new Dependency("react-dom", "^18.3.1"),
1035
+ new Dependency("@types/react", "^18.3.1"),
1036
+ new Dependency("@types/react-dom", "^18.3.1"),
1037
+ // Styled Components types and binary for build time
1038
+ new Dependency("styled-components", "^6.1.13"),
1039
+ new Dependency("@types/styled-components", "^5.1.34"),
1040
+ // Linting & Formatting
1041
+ new Dependency("eslint", "^9.32.0"),
1042
+ new Dependency("prettier", "^3.6.2"),
1043
+ new Dependency("prettier-plugin-organize-imports", "^4.2.0"),
1044
+ // Build
1045
+ new Dependency("tsup", "^8.0.0"),
1046
+ // Testing
1047
+ new Dependency("vitest", "^3.2.4"),
1048
+ new Dependency("@vitest/coverage-v8", "^3.2.4"),
1049
+ new Dependency("@testing-library/react", "^16.0.0"),
1050
+ new Dependency("@testing-library/jest-dom", "^6.0.0"),
1051
+ new Dependency("jsdom", "^25.0.0")
1052
+ ],
1053
+ additionalData: {
1054
+ version: "0.1.0",
1055
+ private: true,
1056
+ type: "module",
1057
+ // Added this to ensure ESM consistency
1058
+ main: "dist/index.js",
1059
+ module: "dist/index.mjs",
1060
+ types: "dist/index.d.ts",
1061
+ exports: {
1062
+ ".": {
1063
+ development: "./src/index.ts",
1064
+ import: "./dist/index.mjs",
1065
+ require: "./dist/index.js",
1066
+ types: "./dist/index.d.ts"
1067
+ }
1068
+ // Removed './index.css' as it's no longer produced by Styled Components
1069
+ },
1070
+ scripts: {
1071
+ build: "tsup",
1072
+ dev: "tsup --watch",
1073
+ // Helpful for local lib dev
1074
+ lint: "eslint .",
1075
+ format: "prettier . --write",
1076
+ test: "vitest run",
1077
+ "test:watch": "vitest"
1078
+ },
1079
+ // Set to false or removed because Styled Components are pure JS/TS
1080
+ sideEffects: false
1081
+ }
1082
+ });
1083
+ return new PackageJsonGenerator(packageJsonModel, namespace);
1084
+ }
1085
+
1086
+ // src/packages/react-package/create-react-package.ts
1087
+ async function createReactPackage(name, style) {
1088
+ switch (style) {
1089
+ case "tailwind":
1090
+ await createTailwindReactPackage(name);
1091
+ break;
1092
+ case "css-modules":
1093
+ await createCssReactPackage(name);
1094
+ break;
1095
+ case "styled-components":
1096
+ await createStyledComponentsReactPackage(name);
1097
+ break;
1098
+ case "none":
1099
+ await createUnstyledReactPackage(name);
1100
+ break;
1101
+ }
1102
+ }
1103
+
1104
+ // src/packages/create-config-package.ts
1105
+ var import_node_path4 = __toESM(require("path"));
1106
+ async function createConfigPackage(name) {
1107
+ const rootDir = await getWorkspaceRoot();
1108
+ const directory = import_node_path4.default.join(rootDir, "configs", name);
1109
+ const namespace = await getNamespace(rootDir);
1110
+ const packageName = `${namespace}/${name}`;
1111
+ const packageJsonModel = new PackageJSON({
1112
+ name: packageName,
1113
+ additionalData: {
1114
+ version: "0.1.0",
1115
+ private: true
1116
+ }
1117
+ });
1118
+ const generator = new PackageGenerator(
1119
+ directory,
1120
+ new PackageJsonGenerator(packageJsonModel, namespace),
1121
+ []
1122
+ );
1123
+ await generator.generate();
1124
+ }
1125
+
1126
+ // src/utils/package.ts
1127
+ var import_fast_glob = require("fast-glob");
1128
+ var import_node_path5 = __toESM(require("path"));
1129
+ async function getCurrentPackage(directory = process.cwd()) {
1130
+ const packageRoot = await getPackageRoot(directory);
1131
+ const packageJson = await getDirectoryPackageJson(packageRoot);
1132
+ return getPackageByName(packageJson.name);
1133
+ }
1134
+ async function getPackageRoot(directory = process.cwd()) {
1135
+ const parent = import_node_path5.default.dirname(directory);
1136
+ if (parent === directory) {
1137
+ throw new Error("Not a package.");
1138
+ }
1139
+ if (await isPackageRoot(directory)) {
1140
+ return directory;
1141
+ }
1142
+ return getPackageRoot(parent);
1143
+ }
1144
+ async function getPackageByName(name) {
1145
+ const all = await getAllPackages();
1146
+ const match = all.find((p) => p.name === name);
1147
+ if (match === void 0) {
1148
+ throw new Error(`No package with name "${name}".`);
1149
+ }
1150
+ return match;
1151
+ }
1152
+ async function getAllPackages(directory = process.cwd()) {
1153
+ const workspaceRoot = await getWorkspaceRoot(directory);
1154
+ const workspaceFile = await getDirectoryWorkspaceFile(workspaceRoot);
1155
+ const results = [];
1156
+ for (const seg of workspaceFile.packages) {
1157
+ const packageType = getPackageType(seg);
1158
+ const packageJsonPaths = await (0, import_fast_glob.glob)(`${workspaceRoot}/${seg}/package.json`);
1159
+ const packageDirectories = packageJsonPaths.map((p) => import_node_path5.default.dirname(p));
1160
+ for (const directory2 of packageDirectories) {
1161
+ const name = (await getDirectoryPackageJson(directory2)).name;
1162
+ results.push({
1163
+ name,
1164
+ directory: directory2,
1165
+ type: packageType
1166
+ });
1167
+ }
1168
+ }
1169
+ return results;
1170
+ }
1171
+ function getPackageType(segment) {
1172
+ if (segment.startsWith("app")) {
1173
+ return "App";
1174
+ } else if (segment.startsWith("config")) {
1175
+ return "Config";
1176
+ } else if (segment.startsWith("package") || segment.startsWith("lib")) {
1177
+ return "Library";
1178
+ } else {
1179
+ return "Unknown";
1180
+ }
1181
+ }
1182
+ function comparePackages(a, b) {
1183
+ const packageTypeDifference = comparePackageTypes(a.type, b.type);
1184
+ if (packageTypeDifference !== 0) {
1185
+ return packageTypeDifference;
1186
+ } else {
1187
+ return a.name.localeCompare(b.name);
1188
+ }
1189
+ }
1190
+ function comparePackageTypes(a, b) {
1191
+ return getPackageTypeIndex(a) - getPackageTypeIndex(b);
1192
+ }
1193
+ function getPackageTypeIndex(packageType) {
1194
+ switch (packageType) {
1195
+ case "Library":
1196
+ return 0;
1197
+ case "Config":
1198
+ return 1;
1199
+ case "App":
1200
+ return 2;
1201
+ case "Unknown":
1202
+ return 3;
1203
+ }
1204
+ }
1205
+ async function isPackageRoot(directory) {
1206
+ return await fileExists(import_node_path5.default.join(directory, "package.json"));
1207
+ }
1208
+
1209
+ // src/utils/package-type.ts
1210
+ var import_enquirer = require("enquirer");
1211
+ var packageTypes = [
1212
+ "library",
1213
+ "config",
1214
+ "react",
1215
+ "vite",
1216
+ "fastify",
1217
+ "next",
1218
+ "cli"
1219
+ ];
1220
+ async function pickPackageType(options) {
1221
+ if (options?.type && isPackageType(options.type)) {
1222
+ return options.type;
1223
+ } else if (options?.type && !isPackageType(options.type)) {
1224
+ throw new Error(
1225
+ `--type setting "${options.type}" is invalid, must be one of ${packageTypes.join(", ")}.`
1226
+ );
1227
+ }
1228
+ const response = await (0, import_enquirer.prompt)({
1229
+ type: "select",
1230
+ name: "type",
1231
+ message: "What kind of package do you want?",
1232
+ choices: [...packageTypes]
1233
+ });
1234
+ if (!isPackageType(response.type)) {
1235
+ throw new Error(
1236
+ `Type "${response.type}" is invalid, must be one of ${packageTypes.join(", ")}.`
1237
+ );
1238
+ }
1239
+ return response.type;
1240
+ }
1241
+ function isPackageType(s) {
1242
+ return packageTypes.some((p) => p === s);
1243
+ }
1244
+
1245
+ // src/utils/style-type.ts
1246
+ var import_enquirer2 = require("enquirer");
1247
+ var styleTypes = [
1248
+ "tailwind",
1249
+ "css-modules",
1250
+ "styled-components",
1251
+ "none"
1252
+ ];
1253
+ async function pickStyleType(options) {
1254
+ if (options?.style && isStyleType(options?.style)) {
1255
+ return options?.style;
1256
+ } else if (options?.style && !isStyleType(options?.style)) {
1257
+ throw new Error(
1258
+ `--style setting "${options.style}" is invalid, must be one of ${styleTypes.join(", ")}.`
1259
+ );
1260
+ }
1261
+ const response = await (0, import_enquirer2.prompt)({
1262
+ type: "select",
1263
+ name: "type",
1264
+ message: "What kind of style do you want?",
1265
+ choices: [...styleTypes]
1266
+ });
1267
+ if (!isStyleType(response.type)) {
1268
+ throw new Error(
1269
+ `Type "${response.type}" is invalid, must be one of ${styleTypes.join(", ")}.`
1270
+ );
1271
+ }
1272
+ return response.type;
1273
+ }
1274
+ function isStyleType(s) {
1275
+ return styleTypes.some((p) => p === s);
1276
+ }
1277
+
1278
+ // src/index.ts
1279
+ var import_commander = require("commander");
1280
+ var import_enquirer3 = require("enquirer");
1281
+
1282
+ // src/link-packages.ts
1283
+ var import_promises4 = __toESM(require("fs/promises"));
1284
+ var import_node_path6 = __toESM(require("path"));
1285
+
1286
+ // src/tsconfig/tsconfig.ts
1287
+ var JSON52 = __toESM(require("json5"));
1288
+ var import_core3 = require("@stack-dev/core");
1289
+ var import_lodash3 = require("lodash");
1290
+
1291
+ // src/tsconfig/compiler-options.ts
1292
+ var import_core2 = require("@stack-dev/core");
1293
+ var import_lodash2 = require("lodash");
1294
+ var CompilerOptions = class _CompilerOptions {
1295
+ _additionalData;
1296
+ _paths;
1297
+ constructor(args) {
1298
+ this._paths = args?.paths ?? {};
1299
+ this._additionalData = args?.additionalData ?? {};
1300
+ }
1301
+ get paths() {
1302
+ return this._paths;
1303
+ }
1304
+ get additionalData() {
1305
+ return this._additionalData;
1306
+ }
1307
+ setPaths(paths) {
1308
+ return new _CompilerOptions({
1309
+ paths,
1310
+ additionalData: this._additionalData
1311
+ });
1312
+ }
1313
+ format() {
1314
+ const json = {
1315
+ paths: this._paths,
1316
+ ...this._additionalData
1317
+ };
1318
+ const ordered = (0, import_core2.sortKeys)(json, compareKeys);
1319
+ return JSON.stringify(ordered, null, 2);
1320
+ }
1321
+ equals(other) {
1322
+ if (other instanceof _CompilerOptions) {
1323
+ return (0, import_lodash2.isEqual)(this._paths, other._paths) && (0, import_lodash2.isEqual)(this._additionalData, other._additionalData);
1324
+ } else {
1325
+ return false;
1326
+ }
1327
+ }
1328
+ };
1329
+ function compareKeys(a, b) {
1330
+ return getKeyIndex2(a) - getKeyIndex2(b);
1331
+ }
1332
+ function getKeyIndex2(s) {
1333
+ const order = [
1334
+ "target",
1335
+ "module",
1336
+ "moduleResolution",
1337
+ "esModuleInterop",
1338
+ "lib",
1339
+ "types",
1340
+ "strict",
1341
+ "allowJs"
1342
+ ];
1343
+ if (order.every((key) => key !== s)) {
1344
+ return Number.MAX_VALUE;
1345
+ } else {
1346
+ return order.indexOf(s);
1347
+ }
1348
+ }
1349
+
1350
+ // src/tsconfig/reference.ts
1351
+ var Reference = class _Reference {
1352
+ _path;
1353
+ constructor(path14) {
1354
+ this._path = path14;
1355
+ }
1356
+ get path() {
1357
+ return this._path;
1358
+ }
1359
+ equals(other) {
1360
+ if (other instanceof _Reference) {
1361
+ return this._path === other._path;
1362
+ } else {
1363
+ return false;
1364
+ }
1365
+ }
1366
+ };
1367
+
1368
+ // src/tsconfig/tsconfig.ts
1369
+ var TSConfig = class _TSConfig {
1370
+ _compilerOptions;
1371
+ _references;
1372
+ _additionalData;
1373
+ constructor(args) {
1374
+ this._compilerOptions = args?.compilerOptions ?? new CompilerOptions();
1375
+ this._references = args?.references ?? [];
1376
+ this._additionalData = args?.additionalData ?? {};
1377
+ }
1378
+ get compilerOptions() {
1379
+ return this._compilerOptions;
1380
+ }
1381
+ addReference(reference) {
1382
+ return new _TSConfig({
1383
+ compilerOptions: this._compilerOptions,
1384
+ references: [...this._references, reference],
1385
+ additionalData: this._additionalData
1386
+ });
1387
+ }
1388
+ setCompilerOptions(compilerOptions) {
1389
+ return new _TSConfig({
1390
+ compilerOptions,
1391
+ references: this._references,
1392
+ additionalData: this._additionalData
1393
+ });
1394
+ }
1395
+ static parse(s) {
1396
+ const json = JSON52.parse(s);
1397
+ const references = _TSConfig.parseReferences(json);
1398
+ const compilerOptions = new CompilerOptions({
1399
+ paths: json.compilerOptions?.paths,
1400
+ ...json.compilerOptions
1401
+ });
1402
+ const additionalData = { ...json };
1403
+ delete additionalData["compilerOptions"];
1404
+ delete additionalData["references"];
1405
+ return new _TSConfig({
1406
+ compilerOptions,
1407
+ references,
1408
+ additionalData
1409
+ });
1410
+ }
1411
+ static parseReferences(json) {
1412
+ if (typeof json === "object" && json !== null && "references" in json && json.references instanceof Array) {
1413
+ return json.references.map(
1414
+ (r) => new Reference(r.path)
1415
+ );
1416
+ } else {
1417
+ return [];
1418
+ }
1419
+ }
1420
+ format() {
1421
+ const compilerOptions = JSON52.parse(this.compilerOptions.format());
1422
+ const json = {
1423
+ compilerOptions,
1424
+ references: this._references.map((r) => ({ path: r.path })),
1425
+ ...this._additionalData
1426
+ };
1427
+ const ordered = (0, import_core3.sortKeys)(json, compareKeys2);
1428
+ return JSON.stringify(ordered, null, 2);
1429
+ }
1430
+ equals(other) {
1431
+ if (other instanceof _TSConfig) {
1432
+ const sameReferences = (0, import_core3.haveSameItems)(
1433
+ this._references,
1434
+ other._references,
1435
+ (r1, r2) => r1.equals(r2)
1436
+ );
1437
+ return this._compilerOptions.equals(other._compilerOptions) && sameReferences && (0, import_lodash3.isEqual)(this._additionalData, other._additionalData);
1438
+ } else {
1439
+ return false;
1440
+ }
1441
+ }
1442
+ };
1443
+ function compareKeys2(a, b) {
1444
+ return getKeyIndex3(a) - getKeyIndex3(b);
1445
+ }
1446
+ function getKeyIndex3(s) {
1447
+ const order = [
1448
+ "extends",
1449
+ "compilerOptions",
1450
+ "include",
1451
+ "exclude",
1452
+ "references"
1453
+ ];
1454
+ if (order.every((key) => key !== s)) {
1455
+ return Number.MAX_VALUE;
1456
+ } else {
1457
+ return order.indexOf(s);
1458
+ }
1459
+ }
1460
+
1461
+ // src/link-packages.ts
1462
+ async function linkPackages(current, target, development) {
1463
+ await updatePackageJSON(current, target, development);
1464
+ await updateTSConfig(current, target);
1465
+ }
1466
+ async function updatePackageJSON(current, target, development) {
1467
+ const namespace = await getNamespace();
1468
+ const packageJSON = await getDirectoryPackageJson(current.directory);
1469
+ const updated = addDependency(packageJSON, target, development);
1470
+ const packageJSONPath = getPackageJSONPath(current.directory);
1471
+ await import_promises4.default.writeFile(packageJSONPath, updated.format(namespace));
1472
+ }
1473
+ function addDependency(packageJSON, target, development) {
1474
+ const dependency = new Dependency(target.name, "workspace:*");
1475
+ if (development) {
1476
+ return packageJSON.addDevDependency(dependency);
1477
+ } else {
1478
+ return packageJSON.addDependency(dependency);
1479
+ }
1480
+ }
1481
+ async function updateTSConfig(current, target) {
1482
+ const tsconfigPath = import_node_path6.default.join(current.directory, "tsconfig.json");
1483
+ const tsconfigContents = await import_promises4.default.readFile(tsconfigPath, "utf8");
1484
+ const tsconfig = TSConfig.parse(tsconfigContents);
1485
+ const targetDirectory = import_node_path6.default.join(target.directory, "src", "index.ts");
1486
+ const updatedPaths = {
1487
+ ...tsconfig.compilerOptions.paths,
1488
+ [target.name]: [import_node_path6.default.relative(current.directory, targetDirectory)]
1489
+ };
1490
+ const updatedCompilerOptions = tsconfig.compilerOptions.setPaths(updatedPaths);
1491
+ const updated = tsconfig.setCompilerOptions(updatedCompilerOptions);
1492
+ await import_promises4.default.writeFile(tsconfigPath, updated.format());
1493
+ }
1494
+
1495
+ // src/packages/vite-react-app/create-vite-react-app.ts
1496
+ var import_path4 = __toESM(require("path"));
1497
+
1498
+ // src/packages/vite-react-app/files/index-html-file-generator.ts
1499
+ var INDEX_HTML = `<!doctype html>
1500
+ <html lang="en">
1501
+ <head>
1502
+ <meta charset="UTF-8" />
1503
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1504
+ <title>Vite + React + Stack-Dev</title>
1505
+ </head>
1506
+ <body>
1507
+ <div id="root"></div>
1508
+ <script type="module" src="/src/main.tsx"></script>
1509
+ </body>
1510
+ </html>
1511
+ `;
1512
+ var INDEX_HTML_FILE_GENERATOR = new FileGeneratorImp(
1513
+ "index.html",
1514
+ INDEX_HTML
1515
+ );
1516
+
1517
+ // src/packages/vite-react-app/files/main-file-generator.ts
1518
+ var MAIN = `import React from 'react';
1519
+ import ReactDOM from 'react-dom/client';
1520
+ import { App } from './App';
1521
+
1522
+ ReactDOM.createRoot(document.getElementById('root')!).render(
1523
+ <React.StrictMode>
1524
+ <App />
1525
+ </React.StrictMode>,
1526
+ );
1527
+ `;
1528
+ var MAIN_FILE_GENERATOR = new FileGeneratorImp("src/main.tsx", MAIN);
1529
+
1530
+ // src/packages/vite-react-app/files/vite-config-file-generator.ts
1531
+ var VITE_CONFIG = `import { defineConfig } from 'vite';
1532
+ import react from '@vitejs/plugin-react';
1533
+
1534
+ export default defineConfig({
1535
+ plugins: [react()],
1536
+ server: {
1537
+ port: 3000,
1538
+ },
1539
+ });
1540
+ `;
1541
+ var VITE_CONFIG_FILE_GENERATOR = new FileGeneratorImp(
1542
+ "vite.config.ts",
1543
+ VITE_CONFIG
1544
+ );
1545
+
1546
+ // src/packages/vite-react-app/files/app-file-generator.ts
1547
+ var APP = `import React, { useState } from 'react';
1548
+
1549
+ export function App() {
1550
+ const [count, setCount] = useState(0);
1551
+
1552
+ return (
1553
+ <div style={{
1554
+ padding: '2rem',
1555
+ fontFamily: 'system-ui, sans-serif',
1556
+ textAlign: 'center'
1557
+ }}>
1558
+ <h1>Stack-Dev App</h1>
1559
+ <div className="card">
1560
+ <button onClick={function() { setCount(count + 1) }}>
1561
+ Count is {count}
1562
+ </button>
1563
+ </div>
1564
+ <p>
1565
+ Edit <code>src/App.tsx</code> and save to test HMR
1566
+ </p>
1567
+ </div>
1568
+ );
1569
+ }
1570
+ `;
1571
+ var APP_FILE_GENERATOR = new FileGeneratorImp("src/App.tsx", APP);
1572
+
1573
+ // src/packages/vite-react-app/files/eslint-config-file-generator.ts
1574
+ var ESLINT_CONFIG4 = `import base from '@stack-dev/eslint-config/base.mjs';
1575
+
1576
+ export default [...base, { ignores: ['**/dist/**'] }];
1577
+ `;
1578
+ var ESLINT_CONFIG_FILE_GENERATOR4 = new FileGeneratorImp(
1579
+ "eslint.config.mjs",
1580
+ ESLINT_CONFIG4
1581
+ );
1582
+
1583
+ // src/packages/vite-react-app/files/prettier-config-file-generator.ts
1584
+ var PRETTIER_CONFIG4 = `import base from '@stack-dev/prettier-config/base.mjs';
1585
+
1586
+ export default base;
1587
+ `;
1588
+ var PRETTIER_CONFIG_FILE_GENERATOR4 = new FileGeneratorImp(
1589
+ "prettier.config.mjs",
1590
+ PRETTIER_CONFIG4
1591
+ );
1592
+
1593
+ // src/packages/vite-react-app/files/tsconfig-file-generator.ts
1594
+ var TSCONFIG4 = `{
1595
+ "extends": "@stack-dev/typescript-config/tsconfig.react.json",
1596
+ "compilerOptions": {
1597
+ "outDir": "dist"
1598
+ },
1599
+ "include": ["src"]
1600
+ }
1601
+ `;
1602
+ var TSCONFIG_FILE_GENERATOR4 = new FileGeneratorImp(
1603
+ "tsconfig.json",
1604
+ TSCONFIG4
1605
+ );
1606
+
1607
+ // src/packages/vite-react-app/files/vitest-config-file-generator.ts
1608
+ var VITEST_CONFIG4 = `import { defineConfig } from 'vitest/config';
1609
+
1610
+ export default defineConfig({
1611
+ test: {
1612
+ globals: true,
1613
+ coverage: {
1614
+ provider: 'v8',
1615
+ },
1616
+ environment: 'node',
1617
+ },
1618
+ });
1619
+ `;
1620
+ var VITEST_CONFIG_FILE_GENERATOR4 = new FileGeneratorImp(
1621
+ "vitest.config.ts",
1622
+ VITEST_CONFIG4
1623
+ );
1624
+
1625
+ // src/packages/vite-react-app/create-vite-react-app.ts
1626
+ async function createViteReactApp(name) {
1627
+ const rootDir = await getWorkspaceRoot();
1628
+ const directory = import_path4.default.join(rootDir, "apps", name);
1629
+ const namespace = await getNamespace(rootDir);
1630
+ const packageName = `${namespace}/${name}`;
1631
+ console.log(`\u{1F680} Creating Vite React App: ${packageName}`);
1632
+ const generator = new PackageGenerator(
1633
+ directory,
1634
+ makeAppPackageGenerator(packageName, namespace),
1635
+ [
1636
+ VITE_CONFIG_FILE_GENERATOR,
1637
+ INDEX_HTML_FILE_GENERATOR,
1638
+ MAIN_FILE_GENERATOR,
1639
+ APP_FILE_GENERATOR,
1640
+ TSCONFIG_FILE_GENERATOR4,
1641
+ PRETTIER_CONFIG_FILE_GENERATOR4,
1642
+ ESLINT_CONFIG_FILE_GENERATOR4,
1643
+ VITEST_CONFIG_FILE_GENERATOR4
1644
+ ]
1645
+ );
1646
+ await generator.generate();
1647
+ }
1648
+ function makeAppPackageGenerator(packageName, namespace) {
1649
+ const packageJsonModel = new PackageJSON({
1650
+ name: packageName,
1651
+ dependencies: [
1652
+ new Dependency("react", "^18.3.1"),
1653
+ new Dependency("react-dom", "^18.3.1")
1654
+ ],
1655
+ devDependencies: [
1656
+ new Dependency(`${namespace}/eslint-config`, "workspace:*"),
1657
+ new Dependency(`${namespace}/prettier-config`, "workspace:*"),
1658
+ new Dependency(`${namespace}/typescript-config`, "workspace:*"),
1659
+ new Dependency("@types/react", "^18.3.1"),
1660
+ new Dependency("@types/react-dom", "^18.3.1"),
1661
+ new Dependency("@vitejs/plugin-react", "^4.3.1"),
1662
+ new Dependency("vite", "^5.4.2"),
1663
+ new Dependency("typescript", "^5.5.4"),
1664
+ new Dependency("eslint", "^9.32.0"),
1665
+ new Dependency("prettier", "^3.6.2")
1666
+ ],
1667
+ additionalData: {
1668
+ version: "0.1.0",
1669
+ private: true,
1670
+ type: "module",
1671
+ scripts: {
1672
+ dev: "vite",
1673
+ build: "tsc && vite build",
1674
+ preview: "vite preview",
1675
+ start: "pnpm run preview",
1676
+ lint: "eslint .",
1677
+ format: "prettier . --write"
1678
+ }
1679
+ }
1680
+ });
1681
+ return new PackageJsonGenerator(packageJsonModel, namespace);
1682
+ }
1683
+
1684
+ // src/unlink-packages.ts
1685
+ var import_promises5 = __toESM(require("fs/promises"));
1686
+ var import_node_path7 = __toESM(require("path"));
1687
+ async function unlinkPackages(current, target) {
1688
+ await updatePackageJSON2(current, target);
1689
+ await updateTSConfig2(current, target);
1690
+ }
1691
+ async function updatePackageJSON2(current, target) {
1692
+ const namespace = await getNamespace();
1693
+ const packageJSON = await getDirectoryPackageJson(current.directory);
1694
+ const updated = packageJSON.removeDependency(target.name).removeDevDependency(target.name);
1695
+ const packageJSONPath = getPackageJSONPath(current.directory);
1696
+ await import_promises5.default.writeFile(packageJSONPath, updated.format(namespace));
1697
+ }
1698
+ async function updateTSConfig2(current, target) {
1699
+ const tsconfigPath = import_node_path7.default.join(current.directory, "tsconfig.json");
1700
+ const tsconfigContents = await import_promises5.default.readFile(tsconfigPath, "utf8");
1701
+ const tsconfig = TSConfig.parse(tsconfigContents);
1702
+ const updatedPaths = Object.fromEntries(
1703
+ Object.entries(tsconfig.compilerOptions.paths).filter(
1704
+ ([key]) => key !== target.name
1705
+ )
1706
+ );
1707
+ const updatedCompilerOptions = tsconfig.compilerOptions.setPaths(updatedPaths);
1708
+ const updated = tsconfig.setCompilerOptions(updatedCompilerOptions);
1709
+ await import_promises5.default.writeFile(tsconfigPath, updated.format());
1710
+ }
1711
+
1712
+ // src/workspace/create-workspace.ts
1713
+ var import_promises6 = __toESM(require("fs/promises"));
1714
+ var import_path6 = __toESM(require("path"));
1715
+
1716
+ // src/workspace/root-package.ts
1717
+ async function makeRootPackage(directory, name) {
1718
+ const packageJsonModel = new PackageJSON({
1719
+ name,
1720
+ devDependencies: [new Dependency("turbo", "^2.5.4")],
1721
+ additionalData: {
1722
+ description: "",
1723
+ keywords: [],
1724
+ author: "",
1725
+ license: "ISC",
1726
+ packageManager: "pnpm@10.13.1"
1727
+ }
1728
+ });
1729
+ const PNPM_WORKSPACE = new FileGeneratorImp(
1730
+ "pnpm-workspace.yaml",
1731
+ ["packages:", " - apps/*", " - packages/*", " - configs/*"].join("\n")
1732
+ );
1733
+ const GITIGNORE = new FileGeneratorImp(".gitignore", GITIGNORE_CONTENT);
1734
+ const TURBO_JSON = new FileGeneratorImp(
1735
+ "turbo.json",
1736
+ JSON.stringify(
1737
+ {
1738
+ tasks: {
1739
+ build: {
1740
+ dependsOn: ["^build"],
1741
+ outputs: ["dist/**"]
1742
+ },
1743
+ lint: {},
1744
+ test: {}
1745
+ }
1746
+ },
1747
+ null,
1748
+ 2
1749
+ )
1750
+ );
1751
+ return new PackageGenerator(
1752
+ directory,
1753
+ new PackageJsonGenerator(packageJsonModel, ""),
1754
+ [PNPM_WORKSPACE, GITIGNORE, TURBO_JSON]
1755
+ );
1756
+ }
1757
+ var GITIGNORE_CONTENT = `# Logs
1758
+ logs
1759
+ *.log
1760
+ npm-debug.log*
1761
+ yarn-debug.log*
1762
+ yarn-error.log*
1763
+ lerna-debug.log*
1764
+
1765
+ # Diagnostic reports (https://nodejs.org/api/report.html)
1766
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
1767
+
1768
+ # Runtime data
1769
+ pids
1770
+ *.pid
1771
+ *.seed
1772
+ *.pid.lock
1773
+
1774
+ # Directory for instrumented libs generated by jscoverage/JSCover
1775
+ lib-cov
1776
+
1777
+ # Coverage directory used by tools like istanbul
1778
+ coverage
1779
+ *.lcov
1780
+
1781
+ # nyc test coverage
1782
+ .nyc_output
1783
+
1784
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
1785
+ .grunt
1786
+
1787
+ # Bower dependency directory (https://bower.io/)
1788
+ bower_components
1789
+
1790
+ # node-waf configuration
1791
+ .lock-wscript
1792
+
1793
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
1794
+ build/Release
1795
+
1796
+ # Dependency directories
1797
+ node_modules/
1798
+ jspm_packages/
1799
+
1800
+ # Snowpack dependency directory (https://snowpack.dev/)
1801
+ web_modules/
1802
+
1803
+ # TypeScript cache
1804
+ *.tsbuildinfo
1805
+
1806
+ # Optional npm cache directory
1807
+ .npm
1808
+
1809
+ # Optional eslint cache
1810
+ .eslintcache
1811
+
1812
+ # Optional stylelint cache
1813
+ .stylelintcache
1814
+
1815
+ # Optional REPL history
1816
+ .node_repl_history
1817
+
1818
+ # Output of 'npm pack'
1819
+ *.tgz
1820
+
1821
+ # Yarn Integrity file
1822
+ .yarn-integrity
1823
+
1824
+ # dotenv environment variable files
1825
+ .env
1826
+ .env.*
1827
+ !.env.example
1828
+
1829
+ # parcel-bundler cache (https://parceljs.org/)
1830
+ .cache
1831
+ .parcel-cache
1832
+
1833
+ # Next.js build output
1834
+ .next
1835
+ out
1836
+
1837
+ # Nuxt.js build / generate output
1838
+ .nuxt
1839
+ dist
1840
+
1841
+ # Gatsby files
1842
+ .cache/
1843
+ # Comment in the public line in if your project uses Gatsby and not Next.js
1844
+ # https://nextjs.org/blog/next-9-1#public-directory-support
1845
+ # public
1846
+
1847
+ # vuepress build output
1848
+ .vuepress/dist
1849
+
1850
+ # vuepress v2.x temp and cache directory
1851
+ .temp
1852
+ .cache
1853
+
1854
+ # Sveltekit cache directory
1855
+ .svelte-kit/
1856
+
1857
+ # vitepress build output
1858
+ **/.vitepress/dist
1859
+
1860
+ # vitepress cache directory
1861
+ **/.vitepress/cache
1862
+
1863
+ # Docusaurus cache and generated files
1864
+ .docusaurus
1865
+
1866
+ # Serverless directories
1867
+ .serverless/
1868
+
1869
+ # FuseBox cache
1870
+ .fusebox/
1871
+
1872
+ # DynamoDB Local files
1873
+ .dynamodb/
1874
+
1875
+ # Firebase cache directory
1876
+ .firebase/
1877
+
1878
+ # TernJS port file
1879
+ .tern-port
1880
+
1881
+ # Stores VSCode versions used for testing VSCode extensions
1882
+ .vscode-test
1883
+
1884
+ # yarn v3
1885
+ .pnp.*
1886
+ .yarn/*
1887
+ !.yarn/patches
1888
+ !.yarn/plugins
1889
+ !.yarn/releases
1890
+ !.yarn/sdks
1891
+ !.yarn/versions
1892
+
1893
+ # Vite logs files
1894
+ vite.config.js.timestamp-*
1895
+ vite.config.ts.timestamp-*
1896
+
1897
+ .turbo
1898
+ `;
1899
+
1900
+ // src/workspace/typescript-config.ts
1901
+ var import_path5 = __toESM(require("path"));
1902
+ async function makeTypescriptConfig(directory, namespace) {
1903
+ const packageJsonModel = new PackageJSON({
1904
+ name: `${namespace}/typescript-config`,
1905
+ devDependencies: [new Dependency("typescript", "^5.8.3")],
1906
+ additionalData: {
1907
+ version: "0.1.0",
1908
+ private: true,
1909
+ files: ["*.json"]
1910
+ }
1911
+ });
1912
+ const fullPath = import_path5.default.join(directory, "configs/typescript-config");
1913
+ return new PackageGenerator(
1914
+ fullPath,
1915
+ new PackageJsonGenerator(packageJsonModel, namespace),
1916
+ [BASE, REACT, NODE]
1917
+ );
1918
+ }
1919
+ var BASE = new FileGeneratorImp(
1920
+ "tsconfig.base.json",
1921
+ JSON.stringify(
1922
+ {
1923
+ compilerOptions: {
1924
+ target: "ES2022",
1925
+ module: "ESNext",
1926
+ moduleResolution: "bundler",
1927
+ resolveJsonModule: true,
1928
+ isolatedModules: true,
1929
+ strict: true,
1930
+ skipLibCheck: true,
1931
+ forceConsistentCasingInFileNames: true,
1932
+ esModuleInterop: true,
1933
+ allowSyntheticDefaultImports: true,
1934
+ noEmit: true,
1935
+ types: []
1936
+ }
1937
+ },
1938
+ null,
1939
+ 2
1940
+ )
1941
+ );
1942
+ var REACT = new FileGeneratorImp(
1943
+ "tsconfig.react.json",
1944
+ JSON.stringify(
1945
+ {
1946
+ extends: "./tsconfig.base.json",
1947
+ compilerOptions: {
1948
+ jsx: "react-jsx",
1949
+ lib: ["DOM", "DOM.Iterable", "ES2022"],
1950
+ types: []
1951
+ }
1952
+ },
1953
+ null,
1954
+ 2
1955
+ )
1956
+ );
1957
+ var NODE = new FileGeneratorImp(
1958
+ "tsconfig.node.json",
1959
+ JSON.stringify(
1960
+ {
1961
+ extends: "./tsconfig.base.json",
1962
+ compilerOptions: {
1963
+ lib: ["ES2022"],
1964
+ types: ["node"]
1965
+ }
1966
+ },
1967
+ null,
1968
+ 2
1969
+ )
1970
+ );
1971
+
1972
+ // src/workspace/create-workspace.ts
1973
+ async function createWorkspace(name, directory) {
1974
+ await validateNotInWorkspace(directory);
1975
+ console.log(`\u2728 Creating workspace: @${name}`);
1976
+ const fullPath = import_path6.default.join(directory, name);
1977
+ await import_promises6.default.mkdir(fullPath, { recursive: true });
1978
+ const namespace = `@${name}`;
1979
+ const PACKAGES = [
1980
+ await makeRootPackage(fullPath, name),
1981
+ await makeTypescriptConfig(fullPath, namespace)
1982
+ ];
1983
+ await Promise.all(PACKAGES.map((p) => p.generate()));
1984
+ await import_promises6.default.mkdir(import_path6.default.join(fullPath, "apps"));
1985
+ await import_promises6.default.mkdir(import_path6.default.join(fullPath, "configs"));
1986
+ await import_promises6.default.mkdir(import_path6.default.join(fullPath, "packages"));
1987
+ console.log(`\u2705 Workspace created at: ${fullPath}`);
1988
+ console.log("");
1989
+ console.log(`Run "cd ${fullPath}" followed by "pnpm install"`);
1990
+ }
1991
+ async function validateNotInWorkspace(directory) {
1992
+ const namespace = await getNamespace(directory);
1993
+ if (namespace !== void 0) {
1994
+ throw new Error(`Currently in workspace "${namespace}".`);
1995
+ }
1996
+ }
1997
+
1998
+ // src/index.ts
1999
+ var program = new import_commander.Command();
2000
+ program.name("stack").description("Opinionated TypeScript workspace manager").version("0.1.0");
2001
+ program.command("create <name>").description("Create a new workspace").option(
2002
+ "-o, --output <dir>",
2003
+ "Target directory to create the workspace in",
2004
+ "."
2005
+ ).action(async (name, options) => {
2006
+ const output = options.output ?? process.cwd();
2007
+ await createWorkspace(name, output);
2008
+ });
2009
+ program.command("g <name>").description("Generate a new package or app").option(
2010
+ "-t, --type <type>",
2011
+ `Type of package to generate (${packageTypes.join(", ")})`
2012
+ ).option("--style <style>", `Styling system to use (${styleTypes.join(", ")})`).action(async (name, options) => {
2013
+ const type = await pickPackageType(options);
2014
+ switch (type) {
2015
+ case "library":
2016
+ await createLibraryPackage(name);
2017
+ break;
2018
+ case "config":
2019
+ await createConfigPackage(name);
2020
+ break;
2021
+ case "react":
2022
+ await createReactPackage(name, await pickStyleType(options));
2023
+ break;
2024
+ case "vite":
2025
+ await createViteReactApp(name);
2026
+ break;
2027
+ case "cli":
2028
+ break;
2029
+ case "fastify":
2030
+ break;
2031
+ case "next":
2032
+ break;
2033
+ }
2034
+ console.log("");
2035
+ console.log("Run pnpm install to finish linking.");
2036
+ });
2037
+ program.command("link [name]").alias("l").option("-D, --dev", "Whether to link as a devDependency.", false).description("Link to the specified package").action(async (name, options) => {
2038
+ name = name ?? await promptForPackageToLinkTo();
2039
+ const development = options.dev ?? false;
2040
+ if (!isValidPackageName(name)) {
2041
+ throw new Error(`Package name "${name}" is not a valid option.`);
2042
+ }
2043
+ const current = await getCurrentPackage();
2044
+ const target = await getPackageByName(name);
2045
+ await linkPackages(current, target, development);
2046
+ console.log("");
2047
+ console.log("Run pnpm install to finish linking.");
2048
+ });
2049
+ program.command("unlink [name]").alias("u").description("Unlink the specified package").action(async (name) => {
2050
+ name = name ?? await promptForPackageToUnlinkFrom();
2051
+ if (!await isValidPackageName(name)) {
2052
+ throw new Error(`Package name "${name}" is not a valid option.`);
2053
+ }
2054
+ const current = await getCurrentPackage();
2055
+ const target = await getPackageByName(name);
2056
+ await unlinkPackages(current, target);
2057
+ });
2058
+ async function promptForPackageToLinkTo() {
2059
+ const options = await getAllPackages();
2060
+ const currentPackage = await getCurrentPackage();
2061
+ const linked = await getLinkedPackageNames();
2062
+ const validOptions = options.filter((o) => o.name !== currentPackage.name).filter((o) => !linked.has(o.name)).toSorted(comparePackages);
2063
+ const response = await (0, import_enquirer3.prompt)({
2064
+ type: "select",
2065
+ name: "packageName",
2066
+ message: "What package do you want to link to?",
2067
+ choices: [...validOptions]
2068
+ });
2069
+ return response.packageName;
2070
+ }
2071
+ async function promptForPackageToUnlinkFrom() {
2072
+ const validOptions = await getLinkedPackageNames();
2073
+ const response = await (0, import_enquirer3.prompt)({
2074
+ type: "select",
2075
+ name: "packageName",
2076
+ message: "What package do you want to unlink from?",
2077
+ choices: [...validOptions]
2078
+ });
2079
+ return response.packageName;
2080
+ }
2081
+ async function getLinkedPackageNames() {
2082
+ const currentPackage = await getCurrentPackage();
2083
+ const packageJSON = await getDirectoryPackageJson(currentPackage.directory);
2084
+ const namespace = await getNamespace();
2085
+ const names = [...packageJSON.dependencies, ...packageJSON.devDependencies].map((d) => d.name).filter((n) => n.startsWith(namespace));
2086
+ return new Set(names);
2087
+ }
2088
+ program.parse();
2089
+ async function isValidPackageName(packageName) {
2090
+ const options = await getValidPackageNames();
2091
+ return options.some((o) => o === packageName);
2092
+ }
2093
+ async function getValidPackageNames() {
2094
+ const options = await getAllPackages();
2095
+ const currentPackage = await getCurrentPackage();
2096
+ return options.filter((o) => o.name !== currentPackage.name).map((o) => o.name);
2097
+ }