@codedrifters/configulator 0.0.0 → 0.0.1

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 (38) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +761 -1
  3. package/lib/aws/aws-deployment-config.d.ts +45 -108
  4. package/lib/aws/aws-deployment-config.js +69 -100
  5. package/lib/aws/aws-deployment-target.d.ts +210 -0
  6. package/lib/aws/aws-deployment-target.js +202 -0
  7. package/lib/aws/index.d.ts +1 -1
  8. package/lib/aws/index.js +2 -2
  9. package/lib/index.d.ts +9 -0
  10. package/lib/index.js +26 -0
  11. package/lib/jsii/index.d.ts +1 -0
  12. package/lib/jsii/index.js +18 -0
  13. package/lib/jsii/jsii-faker.d.ts +47 -0
  14. package/lib/jsii/jsii-faker.js +103 -0
  15. package/lib/pnpm/pnpm-workspace.d.ts +240 -1
  16. package/lib/pnpm/pnpm-workspace.js +155 -15
  17. package/lib/projects/index.d.ts +2 -0
  18. package/lib/projects/index.js +19 -0
  19. package/lib/projects/monorepo-project.d.ts +50 -0
  20. package/lib/projects/monorepo-project.js +203 -0
  21. package/lib/projects/typescript-project.d.ts +4 -0
  22. package/lib/projects/typescript-project.js +150 -0
  23. package/lib/turbo/turbo-repo.d.ts +116 -9
  24. package/lib/turbo/turbo-repo.js +107 -20
  25. package/lib/versions.d.ts +19 -7
  26. package/lib/versions.js +20 -8
  27. package/lib/vscode/vscode.js +2 -1
  28. package/lib/workflows/aws-deploy-workflow.d.ts +84 -0
  29. package/lib/workflows/aws-deploy-workflow.js +312 -0
  30. package/lib/workflows/index.d.ts +1 -2
  31. package/lib/workflows/index.js +2 -3
  32. package/package.json +21 -20
  33. package/lib/workflows/build-workflow.d.ts +0 -13
  34. package/lib/workflows/build-workflow.js +0 -64
  35. package/lib/workflows/deploy-workflow.d.ts +0 -17
  36. package/lib/workflows/deploy-workflow.js +0 -113
  37. package/lib/workflows/steps/deploy.d.ts +0 -4
  38. package/lib/workflows/steps/deploy.js +0 -62
package/README.md CHANGED
@@ -1,4 +1,764 @@
1
1
  # Configulator
2
2
 
3
- A library of Projen components used by CodeDrifters to manage repository configuration across various projects.
3
+ A library of [Projen](https://projen.io/) components used by CodeDrifters to manage repository configuration across various projects. Configulator extends standard Projen configurations with our preferred defaults and provides company-specific components and workflows..
4
4
 
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [What is Projen?](#what-is-projen)
9
+ - [What is Configulator?](#what-is-configulator)
10
+ - [Project Types](#project-types)
11
+ - [MonorepoProject](#monorepoproject)
12
+ - [TypeScriptProject](#typescriptproject)
13
+ - [Usage Patterns](#usage-patterns)
14
+ - [Configuration Options](#configuration-options)
15
+ - [Turbo Repo](#turbo-repo)
16
+ - [PNPM Workspace](#pnpm-workspace)
17
+ - [File Management Rules](#file-management-rules)
18
+ - [Workflow Tips](#workflow-tips)
19
+ - [API Reference](#api-reference)
20
+ - [Troubleshooting](#troubleshooting)
21
+ - [Additional Resources](#additional-resources)
22
+
23
+ ## Overview
24
+
25
+ This guide explains the core infrastructure tools used in our projects: Projen and Configulator. These tools help us maintain consistency across multiple projects and reduce repetitive setup work.
26
+
27
+ ## What is Projen?
28
+
29
+ Projen is a project generator and configuration management tool that:
30
+
31
+ - Creates standardized project structures
32
+ - Manages configuration files programmatically
33
+ - Handles dependency updates automatically
34
+ - Provides consistent build workflows
35
+
36
+ ### Key Concepts
37
+
38
+ **Components:** Individual pieces of configuration (e.g., Jest, Prettier, TypeScript). Each component configures specific files and settings. When you add or remove a component, all its associated files and configurations are automatically managed.
39
+
40
+ **Project Types:** Base-level configurations for different kinds of projects (e.g., TypeScript app, monorepo, React project).
41
+
42
+ **Synthesis:** The process of generating actual files from your configuration. Run `npx projen` to synthesize your project.
43
+
44
+ ## What is Configulator?
45
+
46
+ Configulator is CodeDrifters' custom extension of Projen. It:
47
+
48
+ - Extends standard Projen configurations with our preferred defaults
49
+ - Provides company-specific components and workflows
50
+ - Available as an npm package: `@codedrifters/configulator`
51
+
52
+ ### Why We Built It
53
+
54
+ Instead of setting up each new project from scratch (90% identical setup repeated), Configulator lets us:
55
+
56
+ - Generate consistent project structures
57
+ - Pick and choose components we need
58
+ - Maintain standardized tooling across all projects
59
+ - Receive updates to common configurations automatically
60
+
61
+ ## Project Types
62
+
63
+ Configulator provides two main project types designed for monorepo workflows:
64
+
65
+ ### MonorepoProject
66
+
67
+ **MonorepoProject** extends Projen's `TypeScriptAppProject` and is designed specifically for monorepo root projects. It provides all the infrastructure needed to manage a monorepo with multiple sub-projects.
68
+
69
+ #### When to Use It
70
+
71
+ Use `MonorepoProject` for:
72
+ - Root-level monorepo configuration
73
+ - Managing workspace-wide settings (PNPM, Turborepo, VS Code)
74
+ - Defining shared dependency catalogs
75
+ - Configuring build workflows for the entire monorepo
76
+
77
+ #### Key Features
78
+
79
+ - **PNPM Workspace Management**: Automatically generates and manages `pnpm-workspace.yaml`
80
+ - **Turborepo Integration**: Built-in support for Turborepo with remote caching capabilities
81
+ - **VS Code Configuration**: Automatic VS Code settings for consistent development experience
82
+ - **Default Catalog**: Pre-configured catalog of common dependency versions (AWS CDK, Projen, Constructs, Turbo)
83
+ - **Build Workflow Configuration**: GitHub Actions workflows with Turborepo support
84
+ - **TypeScript Configuration**: Pre-configured TypeScript with sensible defaults
85
+
86
+ #### Basic Example
87
+
88
+ ```typescript
89
+ import { MonorepoProject } from '@codedrifters/configulator';
90
+
91
+ const project = new MonorepoProject({
92
+ name: 'my-monorepo'
93
+ });
94
+
95
+ project.synth();
96
+ ```
97
+
98
+ #### Advanced Example with Remote Cache
99
+
100
+ ```typescript
101
+ import { MonorepoProject } from '@codedrifters/configulator';
102
+
103
+ const project = new MonorepoProject({
104
+ name: 'my-monorepo',
105
+
106
+ turboOptions: {
107
+ remoteCacheOptions: {
108
+ profileName: 'profile-prod-000000000000-us-east-1',
109
+ oidcRole: 'arn:aws:iam::000000000000:role/TurborepoRemoteCachingRole',
110
+ endpointParamName: '/TURBOREPO/ENDPOINT/PARAMETER',
111
+ tokenParamName: '/TURBOREPO/TOKEN/PARAMETER',
112
+ teamName: 'prod',
113
+ },
114
+ },
115
+
116
+ pnpmOptions: {
117
+ pnpmWorkspaceOptions: {
118
+ onlyBuiltDependencies: ['@swc/core', 'esbuild', 'unrs-resolver'],
119
+ },
120
+ },
121
+ });
122
+
123
+ project.synth();
124
+ ```
125
+
126
+ #### Configuration Options
127
+
128
+ The `MonorepoProject` accepts all options from `TypeScriptProjectOptions` plus:
129
+
130
+ | Option | Type | Default | Description |
131
+ |--------|------|---------|-------------|
132
+ | `name` | `string` | **Required** | Project name |
133
+ | `turbo` | `boolean` | `true` | Enable Turborepo support |
134
+ | `turboOptions` | `TurboRepoOptions` | `undefined` | Turborepo configuration including remote cache options |
135
+ | `pnpmOptions.version` | `string` | `VERSION.PNPM_VERSION` | PNPM version to use |
136
+ | `pnpmOptions.pnpmWorkspaceOptions` | `PnpmWorkspaceOptions` | See below | PNPM workspace configuration |
137
+
138
+ **Default Behavior:**
139
+ - `projenrcTs: true` - Uses TypeScript for projen configuration
140
+ - `prettier: true` - Enables Prettier formatting
141
+ - `licensed: false` - No license by default
142
+ - `sampleCode: false` - No sample code generated
143
+ - `jest: false` - Jest disabled at root level
144
+ - `release: false` - Root project is not released
145
+ - `depsUpgrade: false` - No automatic dependency upgrades at root
146
+ - `disableTsconfigDev: true` - No tsconfig.dev.json at root
147
+ - `packageManager: NodePackageManager.PNPM` - PNPM is mandatory
148
+ - `defaultReleaseBranch: "main"` - Standard branch name
149
+
150
+ The root project automatically includes `@codedrifters/configulator` and `constructs` as dev dependencies.
151
+
152
+ ### TypeScriptProject
153
+
154
+ **TypeScriptProject** extends Projen's `TypeScriptProject` with CodeDrifters defaults. It's designed for sub-projects within a monorepo or standalone TypeScript projects.
155
+
156
+ #### When to Use It
157
+
158
+ Use `TypeScriptProject` for:
159
+ - Sub-projects within a monorepo (most common use case)
160
+ - Standalone TypeScript libraries or applications
161
+ - Packages that will be published to NPM
162
+ - Projects that need consistent testing, linting, and build configuration
163
+
164
+ #### Key Features
165
+
166
+ - **Automatic PNPM Version Inheritance**: Inherits PNPM version from parent `MonorepoProject` when used as a sub-project
167
+ - **SWC for Testing**: Uses `@swc/jest` instead of `ts-jest` for faster test execution
168
+ - **Prettier Integration**: Automatic Prettier configuration
169
+ - **Jest Configuration**: External Jest config file (not in package.json) with sensible defaults
170
+ - **Automatic Turborepo Integration**: Automatically configures Turborepo tasks when parent has TurboRepo enabled
171
+ - **Catalog Dependency Support**: Can use catalog dependencies defined in parent workspace
172
+ - **Release Support**: Built-in support for NPM releases with continuous deployment triggers
173
+
174
+ #### Basic Example
175
+
176
+ ```typescript
177
+ import { MonorepoProject, TypeScriptProject } from '@codedrifters/configulator';
178
+
179
+ // Root project
180
+ const root = new MonorepoProject({
181
+ name: 'my-monorepo'
182
+ });
183
+
184
+ // Sub-project
185
+ const myPackage = new TypeScriptProject({
186
+ name: 'my-package',
187
+ packageName: '@myorg/my-package',
188
+ outdir: 'packages/my-package',
189
+ parent: root,
190
+ description: 'My awesome package',
191
+ deps: ['some-dependency'],
192
+ devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
193
+ });
194
+
195
+ root.synth();
196
+ ```
197
+
198
+ #### Example with Release Configuration
199
+
200
+ ```typescript
201
+ import { MonorepoProject, TypeScriptProject } from '@codedrifters/configulator';
202
+
203
+ const root = new MonorepoProject({
204
+ name: 'my-monorepo'
205
+ });
206
+
207
+ const constructs = new TypeScriptProject({
208
+ name: '@codedrifters/constructs',
209
+ packageName: '@codedrifters/constructs',
210
+ outdir: 'packages/@codedrifters/constructs',
211
+ description: 'Constructs frequently used in CodeDrifter projects.',
212
+ repository: 'https://github.com/codedrifters/packages',
213
+ authorName: 'CodeDrifters',
214
+ authorOrganization: true,
215
+ licensed: false,
216
+ parent: root,
217
+
218
+ deps: [
219
+ '@aws-sdk/client-dynamodb',
220
+ '@types/aws-lambda',
221
+ 'change-case@^4.0',
222
+ 'type-fest@^4',
223
+ ],
224
+ devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
225
+ peerDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
226
+
227
+ release: true,
228
+ releaseToNpm: true,
229
+ });
230
+
231
+ root.synth();
232
+ ```
233
+
234
+ #### Parent-Child Relationship
235
+
236
+ When `TypeScriptProject` is created with a `parent` that is a `MonorepoProject`:
237
+
238
+ 1. **PNPM Version**: Automatically inherits the PNPM version from the parent
239
+ 2. **Workspace Integration**: Automatically added to the parent's PNPM workspace
240
+ 3. **Turborepo Integration**: If parent has Turborepo enabled, the sub-project automatically gets Turborepo task configuration
241
+ 4. **Catalog Dependencies**: Can reference catalog dependencies defined in the parent's workspace
242
+ 5. **Dependency Upgrade Exclusions**: Automatically excludes catalog-managed dependencies from upgrade workflows
243
+
244
+ #### Configuration Options
245
+
246
+ The `TypeScriptProject` accepts all options from Projen's `TypeScriptProjectOptions` with these defaults:
247
+
248
+ | Option | Type | Default | Description |
249
+ |--------|------|---------|-------------|
250
+ | `name` | `string` | **Required** | Project name |
251
+ | `packageName` | `string` | Same as `name` | NPM package name |
252
+ | `outdir` | `string` | `"."` | Output directory (required for sub-projects) |
253
+ | `parent` | `MonorepoProject` | `undefined` | Parent monorepo project (recommended) |
254
+ | `defaultReleaseBranch` | `string` | `"main"` | Default release branch |
255
+ | `packageManager` | `NodePackageManager` | `PNPM` | Package manager (always PNPM) |
256
+ | `prettier` | `boolean` | `true` | Enable Prettier |
257
+ | `sampleCode` | `boolean` | `false` | Generate sample code |
258
+ | `release` | `boolean` | `false` | Enable NPM releases |
259
+ | `licensed` | `boolean` | `false` | Include license (unless `license` option provided) |
260
+
261
+ **Jest Configuration:**
262
+ - Uses external `jest.config.json` file
263
+ - Configured to use `@swc/jest` for faster compilation
264
+ - Test files in `src/` directory
265
+ - ESLint rule `import/no-extraneous-dependencies` disabled for test files
266
+
267
+ **NPM Ignore:**
268
+ - Automatically ignores `*.spec.*`, `*.test.*`, and `__fixtures__` patterns
269
+
270
+ **Release Configuration:**
271
+ - Uses continuous release trigger
272
+ - Only releases when package directory content changes
273
+ - Release path based on `outdir`
274
+
275
+ ## Usage Patterns
276
+
277
+ ### Monorepo Setup Pattern
278
+
279
+ The most common pattern is to create a monorepo with a root project and multiple sub-projects:
280
+
281
+ 1. **Create the root project** using `MonorepoProject`:
282
+
283
+ ```typescript
284
+ // projenrc/root-project.ts
285
+ import { MonorepoProject } from '@codedrifters/configulator';
286
+
287
+ export const configureRootProject = () => {
288
+ const project = new MonorepoProject({
289
+ name: 'my-monorepo',
290
+ turboOptions: {
291
+ remoteCacheOptions: {
292
+ profileName: 'my-profile',
293
+ oidcRole: 'arn:aws:iam::123456789012:role/TurborepoRole',
294
+ endpointParamName: '/TURBOREPO/ENDPOINT',
295
+ tokenParamName: '/TURBOREPO/TOKEN',
296
+ teamName: 'my-team',
297
+ },
298
+ },
299
+ });
300
+
301
+ return project;
302
+ };
303
+ ```
304
+
305
+ 2. **Add sub-projects** using `TypeScriptProject`:
306
+
307
+ ```typescript
308
+ // projenrc/my-package.ts
309
+ import { MonorepoProject } from '@codedrifters/configulator';
310
+ import { TypeScriptProject } from '@codedrifters/configulator';
311
+
312
+ export const configureMyPackage = (parent: MonorepoProject) => {
313
+ const myPackage = new TypeScriptProject({
314
+ name: 'my-package',
315
+ packageName: '@myorg/my-package',
316
+ outdir: 'packages/my-package',
317
+ description: 'My package description',
318
+ parent,
319
+ deps: ['dependency-1', 'dependency-2'],
320
+ devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
321
+ });
322
+
323
+ return { myPackage };
324
+ };
325
+ ```
326
+
327
+ 3. **Wire everything together** in your main projenrc file:
328
+
329
+ ```typescript
330
+ // .projenrc.ts or projenrc/index.ts
331
+ import { configureRootProject } from './projenrc/root-project';
332
+ import { configureMyPackage } from './projenrc/my-package';
333
+
334
+ const root = configureRootProject();
335
+ const { myPackage } = configureMyPackage(root);
336
+
337
+ root.synth();
338
+ ```
339
+
340
+ ### Standalone Project Pattern
341
+
342
+ You can also use `TypeScriptProject` without a parent for standalone projects:
343
+
344
+ ```typescript
345
+ import { TypeScriptProject } from '@codedrifters/configulator';
346
+
347
+ const project = new TypeScriptProject({
348
+ name: 'standalone-project',
349
+ packageName: '@myorg/standalone-project',
350
+ description: 'A standalone TypeScript project',
351
+ deps: ['some-dependency'],
352
+ });
353
+
354
+ project.synth();
355
+ ```
356
+
357
+ Note: Without a parent, the project will use the default PNPM version from Configulator's version constants.
358
+
359
+ ### Dependency Management
360
+
361
+ #### Using Catalog Dependencies
362
+
363
+ The `MonorepoProject` automatically sets up a default catalog with common dependencies:
364
+
365
+ ```typescript
366
+ // Defined in MonorepoProject defaults
367
+ defaultCatalog: {
368
+ 'aws-cdk': VERSION.AWS_CDK_CLI_VERSION,
369
+ 'aws-cdk-lib': VERSION.AWS_CDK_LIB_VERSION,
370
+ 'projen': VERSION.PROJEN_VERSION,
371
+ 'constructs': VERSION.AWS_CONSTRUCTS_VERSION,
372
+ 'turbo': VERSION.TURBO_VERSION,
373
+ }
374
+ ```
375
+
376
+ Sub-projects can reference these using the `catalog:` protocol:
377
+
378
+ ```typescript
379
+ const myPackage = new TypeScriptProject({
380
+ // ... other options
381
+ devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
382
+ peerDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
383
+ });
384
+ ```
385
+
386
+ #### Workspace Dependencies
387
+
388
+ Sub-projects can depend on other packages in the same monorepo:
389
+
390
+ ```typescript
391
+ const packageB = new TypeScriptProject({
392
+ // ... other options
393
+ deps: ['@myorg/package-a@workspace:*'],
394
+ });
395
+ ```
396
+
397
+ #### Custom Catalog
398
+
399
+ You can also define custom catalogs in the `MonorepoProject`:
400
+
401
+ ```typescript
402
+ const root = new MonorepoProject({
403
+ name: 'my-monorepo',
404
+ pnpmOptions: {
405
+ pnpmWorkspaceOptions: {
406
+ defaultCatalog: {
407
+ 'react': '^18.0.0',
408
+ 'typescript': '^5.0.0',
409
+ },
410
+ namedCatalogs: {
411
+ frontend: {
412
+ 'react': '^18.0.0',
413
+ 'react-dom': '^18.0.0',
414
+ },
415
+ backend: {
416
+ 'express': '^4.18.0',
417
+ },
418
+ },
419
+ },
420
+ },
421
+ });
422
+ ```
423
+
424
+ Then reference them in sub-projects:
425
+
426
+ ```typescript
427
+ // Default catalog
428
+ deps: ['react@catalog:react']
429
+
430
+ // Named catalog
431
+ deps: ['react@catalog:frontend/react']
432
+ ```
433
+
434
+ ### Turborepo Integration
435
+
436
+ When you create a `MonorepoProject` with `turbo: true` (the default), Turborepo is automatically configured. Sub-projects created with `TypeScriptProject` automatically get Turborepo task configuration if their parent has Turborepo enabled.
437
+
438
+ The integration includes:
439
+ - Automatic task definitions (compile, test, package)
440
+ - Output directory configuration (`dist/**`, `lib/**`)
441
+ - Remote cache support (when configured)
442
+ - Build workflow integration
443
+
444
+ See the [Turbo Repo](#turbo-repo) section for more details.
445
+
446
+ ## Configuration Options
447
+
448
+ ### MonorepoProjectOptions
449
+
450
+ Extends `TypeScriptProjectOptions` with:
451
+
452
+ ```typescript
453
+ interface MonorepoProjectOptions {
454
+ name: string; // Required
455
+ turbo?: boolean; // Default: true
456
+ turboOptions?: TurboRepoOptions;
457
+ pnpmOptions?: {
458
+ version?: string;
459
+ pnpmWorkspaceOptions?: PnpmWorkspaceOptions;
460
+ };
461
+ // ... all TypeScriptProjectOptions
462
+ }
463
+ ```
464
+
465
+ ### TypeScriptProjectOptions
466
+
467
+ Extends Projen's `TypeScriptProjectOptions` with CodeDrifters defaults. See the [TypeScriptProject](#typescriptproject) section for details.
468
+
469
+ ### TurboRepoOptions
470
+
471
+ ```typescript
472
+ interface TurboRepoOptions {
473
+ turboVersion?: string;
474
+ remoteCacheOptions?: RemoteCacheOptions;
475
+ extends?: Array<string>;
476
+ globalDependencies?: Array<string>;
477
+ globalEnv?: Array<string>;
478
+ globalPassThroughEnv?: Array<string>;
479
+ ui?: 'tui' | 'stream';
480
+ envMode?: string;
481
+ // ... and more
482
+ }
483
+
484
+ interface RemoteCacheOptions {
485
+ profileName: string;
486
+ oidcRole: string;
487
+ endpointParamName: string;
488
+ tokenParamName: string;
489
+ teamName: string;
490
+ }
491
+ ```
492
+
493
+ ### PnpmWorkspaceOptions
494
+
495
+ ```typescript
496
+ interface PnpmWorkspaceOptions {
497
+ fileName?: string; // Default: 'pnpm-workspace.yaml'
498
+ minimumReleaseAge?: number; // Minutes, default: ONE_DAY (1440)
499
+ minimumReleaseAgeExclude?: Array<string>; // Default: ['@codedrifters/*']
500
+ onlyBuiltDependencies?: Array<string>;
501
+ ignoredBuiltDependencies?: Array<string>;
502
+ subprojects?: Array<string>;
503
+ defaultCatalog?: { [key: string]: string };
504
+ namedCatalogs?: { [catalogName: string]: { [dependencyName: string]: string } };
505
+ }
506
+ ```
507
+
508
+ ## Turbo Repo
509
+
510
+ ### What It Does
511
+
512
+ Turbo Repo is a build system for monorepos that:
513
+
514
+ - Caches build outputs intelligently
515
+ - Only rebuilds what changed
516
+ - Speeds up CI/CD significantly
517
+ - Works with remote caching
518
+
519
+ ### How It Works
520
+
521
+ **Hashing:** All input files (source code, configs) are hashed
522
+
523
+ **Cache Check:** If inputs haven't changed, cached outputs are reused
524
+
525
+ **Smart Rebuilds:** Only affected packages rebuild when dependencies change
526
+
527
+ **Remote Cache:** Build outputs stored in S3 (not Vercel) for team sharing
528
+
529
+ ### Configuration
530
+
531
+ Turborepo is automatically enabled in `MonorepoProject` (can be disabled with `turbo: false`). Configure it using the `turboOptions`:
532
+
533
+ ```typescript
534
+ const project = new MonorepoProject({
535
+ name: 'my-monorepo',
536
+ turboOptions: {
537
+ remoteCacheOptions: {
538
+ profileName: 'my-profile',
539
+ oidcRole: 'arn:aws:iam::123456789012:role/TurborepoRole',
540
+ endpointParamName: '/TURBOREPO/ENDPOINT',
541
+ tokenParamName: '/TURBOREPO/TOKEN',
542
+ teamName: 'my-team',
543
+ },
544
+ },
545
+ });
546
+ ```
547
+
548
+ ### Running Locally
549
+
550
+ Before using Turbo Repo locally, you need AWS credentials:
551
+
552
+ ```bash
553
+ # Run the login script (credentials last ~8 hours)
554
+ ./scripts/aws-profile-turbo-repo.sh
555
+ ```
556
+
557
+ **Common Error:** If you get a "gRPC error" when running Turbo first thing in the morning, the Lambda function is cold. Just run the command again - it will work the second time.
558
+
559
+ ### Benefits
560
+
561
+ - **Fast CI:** Builds can complete in under a minute when using cached outputs
562
+ - **Selective Rebuilds:** Only changed code rebuilds, not the entire monorepo
563
+ - **Local + CI Sharing:** Cache between your machine and GitHub Actions
564
+
565
+ ## PNPM Workspace
566
+
567
+ The `MonorepoProject` automatically generates and manages `pnpm-workspace.yaml`. This file:
568
+
569
+ - Lists all sub-projects in the `packages` array
570
+ - Configures PNPM settings like `minimumReleaseAge` and `onlyBuiltDependencies`
571
+ - Defines dependency catalogs for version management
572
+
573
+ ### Workspace Structure
574
+
575
+ The workspace file is auto-generated and lists all sub-projects:
576
+
577
+ ```yaml
578
+ packages:
579
+ - 'packages/package-a'
580
+ - 'packages/package-b'
581
+ - 'apps/frontend'
582
+ ```
583
+
584
+ Sub-projects are automatically discovered from `project.subprojects` and any additional paths specified in `pnpmWorkspaceOptions.subprojects`.
585
+
586
+ ### Configuration
587
+
588
+ Configure the workspace through `pnpmOptions.pnpmWorkspaceOptions`:
589
+
590
+ ```typescript
591
+ const project = new MonorepoProject({
592
+ name: 'my-monorepo',
593
+ pnpmOptions: {
594
+ pnpmWorkspaceOptions: {
595
+ minimumReleaseAge: MIMIMUM_RELEASE_AGE.ONE_DAY,
596
+ minimumReleaseAgeExclude: ['@codedrifters/*'],
597
+ onlyBuiltDependencies: ['@swc/core', 'esbuild'],
598
+ defaultCatalog: {
599
+ 'react': '^18.0.0',
600
+ },
601
+ },
602
+ },
603
+ });
604
+ ```
605
+
606
+ ## File Management Rules
607
+
608
+ ### DO NOT Edit These Files Directly
609
+
610
+ Projen manages many files automatically. Never edit these files by hand:
611
+
612
+ - Configuration files (`.prettierrc`, `tsconfig.json`, etc.)
613
+ - GitHub workflows (`.github/workflows/*`)
614
+ - Build scripts
615
+ - Most files listed in `.projen/files.json`
616
+
617
+ ### Exception: package.json
618
+
619
+ `package.json` is special - Projen reads, modifies, and writes it back, preserving some manual changes. However, you should still manage dependencies through Projen config, not by editing `package.json` directly.
620
+
621
+ ### Adding Dependencies
622
+
623
+ **WRONG:**
624
+ ```bash
625
+ npm install some-package
626
+ ```
627
+
628
+ **CORRECT:** Add dependencies in your `.projenrc.ts` configuration and run `npx projen`.
629
+
630
+ ```typescript
631
+ const project = new TypeScriptProject({
632
+ // ... other options
633
+ deps: ['some-package'],
634
+ });
635
+ ```
636
+
637
+ ## Workflow Tips
638
+
639
+ ### Before Committing
640
+
641
+ Run Turbo build locally (from monorepo root) to cache everything:
642
+
643
+ ```bash
644
+ # This caches outputs that GitHub Actions can reuse
645
+ pnpm build:all
646
+ ```
647
+
648
+ Then commit and push. Your GitHub build will be much faster.
649
+
650
+ ### Adding New Packages
651
+
652
+ 1. Create a new configuration file in `projenrc/` (e.g., `projenrc/new-package.ts`)
653
+ 2. Export a function that creates a `TypeScriptProject` with the parent as a parameter
654
+ 3. Import and call it in your main projenrc file
655
+ 4. Run `npx projen` to regenerate configs
656
+ 5. Commit the changes
657
+
658
+ Example:
659
+
660
+ ```typescript
661
+ // projenrc/new-package.ts
662
+ import { MonorepoProject, TypeScriptProject } from '@codedrifters/configulator';
663
+
664
+ export const configureNewPackage = (parent: MonorepoProject) => {
665
+ return new TypeScriptProject({
666
+ name: 'new-package',
667
+ packageName: '@myorg/new-package',
668
+ outdir: 'packages/new-package',
669
+ parent,
670
+ deps: ['dependency'],
671
+ });
672
+ };
673
+ ```
674
+
675
+ ### Updating Configulator
676
+
677
+ To receive updates from Configulator in your project:
678
+
679
+ 1. Update the version in your projenrc definition file
680
+ 2. Run `npx projen`
681
+ 3. Review and test changes
682
+ 4. Commit
683
+
684
+ ## API Reference
685
+
686
+ ### MonorepoProject
687
+
688
+ **Constructor:**
689
+ ```typescript
690
+ new MonorepoProject(options: MonorepoProjectOptions)
691
+ ```
692
+
693
+ **Key Properties:**
694
+ - `pnpmVersion: string` - The PNPM version used by the monorepo
695
+
696
+ **Key Methods:**
697
+ - Inherits all methods from `TypeScriptAppProject`
698
+
699
+ ### TypeScriptProject
700
+
701
+ **Constructor:**
702
+ ```typescript
703
+ new TypeScriptProject(options: TypeScriptProjectOptions)
704
+ ```
705
+
706
+ **Key Methods:**
707
+ - `addDeps(...deps: string[])` - Add runtime dependencies
708
+ - `addDevDeps(...deps: string[])` - Add dev dependencies
709
+ - `addPeerDeps(...deps: string[])` - Add peer dependencies
710
+ - Inherits all methods from Projen's `TypeScriptProject`
711
+
712
+ ### PnpmWorkspace
713
+
714
+ **Static Method:**
715
+ ```typescript
716
+ PnpmWorkspace.of(project: Project): PnpmWorkspace | undefined
717
+ ```
718
+
719
+ Returns the PnpmWorkspace component from a project if it exists.
720
+
721
+ ### TurboRepo
722
+
723
+ **Static Method:**
724
+ ```typescript
725
+ TurboRepo.of(project: Project): TurboRepo | undefined
726
+ ```
727
+
728
+ Returns the TurboRepo component from a project if it exists.
729
+
730
+ ## Troubleshooting
731
+
732
+ **"Cannot find module" errors**
733
+
734
+ Run `npx projen` to regenerate configuration files.
735
+
736
+ **Turbo Repo cache errors**
737
+
738
+ - Ensure you've run the AWS login script
739
+ - If it's your first run of the day, try running the command twice
740
+
741
+ **Build workflow failures**
742
+
743
+ Check that you haven't manually edited generated files. If you have, run `npx projen` to restore them.
744
+
745
+ **Dependency conflicts**
746
+
747
+ Don't mix `npm install` with Projen. Always add dependencies through configuration.
748
+
749
+ **Sub-project not appearing in workspace**
750
+
751
+ - Ensure the sub-project has `parent` set to the MonorepoProject
752
+ - Ensure `outdir` is set correctly
753
+ - Run `npx projen` to regenerate the workspace file
754
+
755
+ ## Additional Resources
756
+
757
+ - **Projen Documentation:** https://projen.io
758
+ - **Turbo Repo Docs:** https://turbo.build/repo/docs
759
+ - **PNPM Workspaces:** https://pnpm.io/workspaces
760
+ - **Code Drifters Configulator:** https://www.npmjs.com/package/@codedrifters/packages
761
+
762
+ ---
763
+
764
+ **Remember:** The goal is consistency and automation. Let the tools manage the boilerplate so you can focus on building features.