@codedrifters/configulator 0.0.306 → 0.0.307

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.
package/lib/index.mjs CHANGED
@@ -32721,8 +32721,88 @@ var JsiiFaker = class _JsiiFaker extends Component13 {
32721
32721
  }
32722
32722
  };
32723
32723
 
32724
- // src/projects/astro-project.ts
32724
+ // src/projects/add-playwright.ts
32725
32725
  import { SampleFile as SampleFile2 } from "projen";
32726
+ function addPlaywright(project) {
32727
+ project.addDevDeps("@playwright/test");
32728
+ project.tasks.addTask("e2e:install", {
32729
+ description: "Install Playwright browsers",
32730
+ steps: [{ exec: "npx playwright install --with-deps" }]
32731
+ });
32732
+ project.tasks.addTask("e2e", {
32733
+ description: "Run Playwright E2E tests (headless)",
32734
+ steps: [{ exec: "npx playwright test" }]
32735
+ });
32736
+ project.tasks.addTask("e2e:ui", {
32737
+ description: "Run Playwright in UI mode",
32738
+ steps: [{ exec: "npx playwright test --ui" }]
32739
+ });
32740
+ project.tasks.addTask("e2e:report", {
32741
+ description: "Open last HTML report",
32742
+ steps: [{ exec: "npx playwright show-report" }]
32743
+ });
32744
+ project.setScript("e2e:install", "npx projen e2e:install");
32745
+ project.setScript("e2e", "npx projen e2e");
32746
+ project.setScript("e2e:ui", "npx projen e2e:ui");
32747
+ project.setScript("e2e:report", "npx projen e2e:report");
32748
+ new SampleFile2(project, "playwright.config.ts", {
32749
+ contents: `import { defineConfig, devices } from '@playwright/test';
32750
+
32751
+ export default defineConfig({
32752
+ testDir: './tests',
32753
+ reporter: [['html', { open: 'never' }]],
32754
+ use: {
32755
+ baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:5173',
32756
+ trace: 'on-first-retry',
32757
+ },
32758
+ projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
32759
+ });
32760
+ `
32761
+ });
32762
+ project.gitignore.addPatterns("test-results/", "playwright-report/");
32763
+ }
32764
+
32765
+ // src/projects/add-storybook.ts
32766
+ import { SampleFile as SampleFile3 } from "projen";
32767
+ function addStorybook(project, options = {}) {
32768
+ const withDocs = options.withDocs ?? true;
32769
+ project.addDevDeps(
32770
+ "storybook",
32771
+ "@storybook/react@^9",
32772
+ "@storybook/react-vite@^9",
32773
+ ...withDocs ? ["@storybook/addon-docs@^9"] : []
32774
+ );
32775
+ project.tasks.addTask("storybook", {
32776
+ description: "Run Storybook (Vite)",
32777
+ steps: [{ exec: "storybook dev -p 6006" }]
32778
+ });
32779
+ project.tasks.addTask("build-storybook", {
32780
+ description: "Build static Storybook",
32781
+ steps: [{ exec: "storybook build" }]
32782
+ });
32783
+ project.setScript("storybook", "npx projen storybook");
32784
+ project.setScript("build-storybook", "npx projen build-storybook");
32785
+ new SampleFile3(project, ".storybook/main.ts", {
32786
+ contents: `import type { StorybookConfig } from '@storybook/react-vite';
32787
+
32788
+ const config: StorybookConfig = {
32789
+ stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
32790
+ addons: [${withDocs ? `'@storybook/addon-docs'` : ""}],
32791
+ framework: { name: '@storybook/react-vite', options: {} },
32792
+ };
32793
+ export default config;
32794
+ `
32795
+ });
32796
+ new SampleFile3(project, ".storybook/preview.ts", {
32797
+ contents: `import '../src/index.css';
32798
+ const preview = { parameters: { controls: { expanded: true } } };
32799
+ export default preview;
32800
+ `
32801
+ });
32802
+ }
32803
+
32804
+ // src/projects/astro-project.ts
32805
+ import { SampleFile as SampleFile4 } from "projen";
32726
32806
  import { merge as merge3 } from "ts-deepmerge";
32727
32807
 
32728
32808
  // src/projects/monorepo-layout.ts
@@ -32741,6 +32821,7 @@ var LAYOUT_ROOT_BY_PROJECT_TYPE = {
32741
32821
  TypeScriptProject: MONOREPO_LAYOUT.PACKAGES,
32742
32822
  AwsCdkProject: MONOREPO_LAYOUT.APPS,
32743
32823
  AstroProject: MONOREPO_LAYOUT.SITES,
32824
+ ReactViteSiteProject: MONOREPO_LAYOUT.SITES,
32744
32825
  StarlightProject: MONOREPO_LAYOUT.DOCS
32745
32826
  };
32746
32827
  function validateMonorepoLayout(root) {
@@ -32864,6 +32945,9 @@ function resolveAwsCdkProjectOutdir(packageName) {
32864
32945
  function resolveAstroProjectOutdir(packageName) {
32865
32946
  return resolveOutdirFromPackageName(packageName, MONOREPO_LAYOUT.SITES);
32866
32947
  }
32948
+ function resolveReactViteSiteProjectOutdir(packageName) {
32949
+ return resolveOutdirFromPackageName(packageName, MONOREPO_LAYOUT.SITES);
32950
+ }
32867
32951
 
32868
32952
  // src/projects/typescript-project.ts
32869
32953
  import { typescript } from "projen";
@@ -34175,10 +34259,10 @@ var AstroProject = class extends TypeScriptProject {
34175
34259
  adapter: options.adapter
34176
34260
  });
34177
34261
  if (options.sampleCode === true) {
34178
- new SampleFile2(this, "src/pages/index.astro", {
34262
+ new SampleFile4(this, "src/pages/index.astro", {
34179
34263
  contents: DEFAULT_INDEX_ASTRO
34180
34264
  });
34181
- new SampleFile2(this, "public/favicon.svg", {
34265
+ new SampleFile4(this, "public/favicon.svg", {
34182
34266
  contents: DEFAULT_FAVICON_SVG
34183
34267
  });
34184
34268
  }
@@ -34883,8 +34967,305 @@ var AwsCdkProject = class extends awscdk.AwsCdkTypeScriptApp {
34883
34967
  }
34884
34968
  };
34885
34969
 
34970
+ // src/projects/react-vite-site-project.ts
34971
+ import { SampleFile as SampleFile5, TextFile as TextFile7 } from "projen";
34972
+ import { merge as merge5 } from "ts-deepmerge";
34973
+ var ReactViteSiteProject = class extends TypeScriptProject {
34974
+ constructor(userOptions) {
34975
+ const resolvedOutdir = userOptions.outdir ?? resolveReactViteSiteProjectOutdir(
34976
+ userOptions.packageName ?? userOptions.name
34977
+ );
34978
+ const defaultOptions = {
34979
+ testRunner: TestRunner.VITEST,
34980
+ apiExtractor: false,
34981
+ // ESLint inherited from TypeScriptProject lints `src` by default;
34982
+ // skip projen's `.projenrc.ts` lint pass since downstream sites
34983
+ // configure projen through their own root project.
34984
+ eslintOptions: {
34985
+ dirs: ["src"],
34986
+ lintProjenRc: false
34987
+ },
34988
+ // VSCode workspace defaults (Prettier formatter, ESLint on save)
34989
+ // need a project-level `.vscode/` folder. The inherited
34990
+ // TypeScriptProject does not enable it on sub-projects by
34991
+ // default; flip it on so the React-site VSCode wiring below
34992
+ // actually renders.
34993
+ vscode: true,
34994
+ tsconfig: {
34995
+ compilerOptions: {
34996
+ declaration: false
34997
+ }
34998
+ }
34999
+ };
35000
+ const merged = merge5(
35001
+ defaultOptions,
35002
+ userOptions
35003
+ );
35004
+ const options = {
35005
+ ...merged,
35006
+ outdir: resolvedOutdir
35007
+ };
35008
+ super(options);
35009
+ this.package.addField("type", "module");
35010
+ new TextFile7(this, ".nvmrc", { lines: ["v24.11.0"] });
35011
+ this.tsconfig?.file.addOverride("compilerOptions.target", "ES2020");
35012
+ this.tsconfig?.file.addOverride("compilerOptions.lib", [
35013
+ "ES2020",
35014
+ "DOM",
35015
+ "DOM.Iterable"
35016
+ ]);
35017
+ this.tsconfig?.file.addOverride("compilerOptions.module", "ESNext");
35018
+ this.tsconfig?.file.addOverride(
35019
+ "compilerOptions.moduleResolution",
35020
+ "bundler"
35021
+ );
35022
+ this.tsconfig?.file.addOverride("compilerOptions.jsx", "react-jsxdev");
35023
+ this.tsconfig?.file.addOverride("compilerOptions.noEmit", true);
35024
+ this.tsconfig?.file.addOverride("compilerOptions.skipLibCheck", true);
35025
+ this.tsconfig?.file.addOverride("compilerOptions.strict", true);
35026
+ this.tsconfig?.file.addOverride("compilerOptions.resolveJsonModule", true);
35027
+ this.tsconfig?.file.addOverride("compilerOptions.declaration", false);
35028
+ this.tsconfig?.file.addOverride("compilerOptions.paths", {
35029
+ "@/*": ["./src/*"]
35030
+ });
35031
+ this.tsconfig?.file.addOverride("include", ["src"]);
35032
+ this.tsconfigDev?.file.addOverride("compilerOptions.types", [
35033
+ "vitest/globals",
35034
+ "vite/client"
35035
+ ]);
35036
+ this.tsconfigDev?.file.addOverride("include", [
35037
+ "src",
35038
+ "tests",
35039
+ "**/*.test.ts",
35040
+ "**/*.test.tsx",
35041
+ "**/*.spec.ts",
35042
+ "**/*.spec.tsx",
35043
+ "vitest.config.ts"
35044
+ ]);
35045
+ this.tsconfigDev?.file.addOverride("exclude", [
35046
+ "node_modules",
35047
+ "dist",
35048
+ "build",
35049
+ ".turbo"
35050
+ ]);
35051
+ new SampleFile5(this, "vite.config.ts", {
35052
+ contents: `import { defineConfig } from 'vite';
35053
+ import react from '@vitejs/plugin-react';
35054
+ import tailwindcss from '@tailwindcss/vite';
35055
+ import path from 'path';
35056
+
35057
+ export default defineConfig({
35058
+ plugins: [tailwindcss(), react()],
35059
+ resolve: { alias: { '@': path.resolve(__dirname, 'src') } },
35060
+ });
35061
+ `
35062
+ });
35063
+ if (options.testRunner !== TestRunner.JEST) {
35064
+ this.tryRemoveFile("vitest.config.ts");
35065
+ new SampleFile5(this, "vitest.config.ts", {
35066
+ contents: `import { defineConfig, mergeConfig } from 'vitest/config';
35067
+ import react from '@vitejs/plugin-react';
35068
+ import viteConfig from './vite.config';
35069
+
35070
+ export default mergeConfig(
35071
+ viteConfig,
35072
+ defineConfig({
35073
+ plugins: [react()],
35074
+ test: {
35075
+ environment: 'jsdom',
35076
+ globals: true,
35077
+ setupFiles: ['./src/setupTests.ts'],
35078
+ passWithNoTests: true,
35079
+ },
35080
+ })
35081
+ );
35082
+ `
35083
+ });
35084
+ }
35085
+ this.compileTask.reset();
35086
+ this.compileTask.exec("vite build");
35087
+ this.packageTask.reset();
35088
+ this.tasks.tryFind("watch")?.reset("vite");
35089
+ if (!this.tasks.tryFind("dev")) {
35090
+ this.addTask("dev", {
35091
+ description: "Start the Vite dev server",
35092
+ exec: "vite",
35093
+ receiveArgs: true
35094
+ });
35095
+ }
35096
+ if (!this.tasks.tryFind("preview")) {
35097
+ this.addTask("preview", {
35098
+ description: "Preview the built site locally",
35099
+ exec: "vite preview",
35100
+ receiveArgs: true
35101
+ });
35102
+ }
35103
+ this.addDeps("react", "react-dom", "react-router-dom");
35104
+ this.addDevDeps(
35105
+ "vite",
35106
+ "@vitejs/plugin-react",
35107
+ "@tailwindcss/vite",
35108
+ "tailwindcss",
35109
+ "jsdom",
35110
+ "@testing-library/react",
35111
+ "@testing-library/jest-dom",
35112
+ "@testing-library/user-event",
35113
+ "@types/react",
35114
+ "@types/react-dom",
35115
+ "eslint-plugin-react",
35116
+ "eslint-plugin-react-hooks"
35117
+ );
35118
+ this.eslint?.addExtends("plugin:react/recommended");
35119
+ this.eslint?.addExtends("plugin:react/jsx-runtime");
35120
+ this.eslint?.addExtends("plugin:react-hooks/recommended");
35121
+ this.eslint?.addOverride({
35122
+ files: ["**/*.{tsx,jsx}"],
35123
+ // Projen's ESLint override type does not include `settings`, but
35124
+ // `settings` is a valid ESLint override key. Cast to `any` so the
35125
+ // generated `.eslintrc.json` carries the React-version detection
35126
+ // settings on the JSX glob.
35127
+ settings: {
35128
+ react: {
35129
+ version: "detect"
35130
+ }
35131
+ }
35132
+ });
35133
+ this.eslint?.addRules({
35134
+ // We use TypeScript; prop-types are unnecessary.
35135
+ "react/prop-types": "off",
35136
+ // New JSX transform — React no longer needs to be in scope.
35137
+ "react/react-in-jsx-scope": "off"
35138
+ });
35139
+ this.eslint?.addOverride({
35140
+ files: [
35141
+ "**/*.{test,spec}.ts",
35142
+ "**/*.{test,spec}.tsx",
35143
+ "**/__tests__/**",
35144
+ "src/setupTests.ts"
35145
+ ],
35146
+ rules: {
35147
+ "import/no-extraneous-dependencies": [
35148
+ "error",
35149
+ { devDependencies: true }
35150
+ ]
35151
+ }
35152
+ });
35153
+ this.vscode?.settings.addSettings({
35154
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
35155
+ "editor.formatOnSave": true,
35156
+ // Prettier must format the whole file; "modifications" mode is
35157
+ // known to mis-merge ranges with Prettier and can corrupt saves.
35158
+ "editor.formatOnSaveMode": "file",
35159
+ "prettier.requireConfig": true,
35160
+ "eslint.useFlatConfig": false,
35161
+ "eslint.workingDirectories": [{ directory: ".", changeProcessCWD: true }],
35162
+ // Prettier is the default formatter; ESLint's fixAll must not
35163
+ // re-apply prettier/prettier (would double-format).
35164
+ "eslint.codeActionsOnSave.rules": ["!prettier/prettier", "*"],
35165
+ "eslint.format.enable": false,
35166
+ "[typescript]": {
35167
+ "editor.codeActionsOnSave": {
35168
+ "source.fixAll.eslint": "always",
35169
+ "source.organizeImports": "always"
35170
+ }
35171
+ },
35172
+ "[typescriptreact]": {
35173
+ "editor.codeActionsOnSave": {
35174
+ "source.fixAll.eslint": "always",
35175
+ "source.organizeImports": "always"
35176
+ }
35177
+ },
35178
+ "[javascript]": {
35179
+ "editor.codeActionsOnSave": {
35180
+ "source.fixAll.eslint": "always"
35181
+ }
35182
+ },
35183
+ "[javascriptreact]": {
35184
+ "editor.codeActionsOnSave": {
35185
+ "source.fixAll.eslint": "always"
35186
+ }
35187
+ },
35188
+ "eslint.validate": [
35189
+ "javascript",
35190
+ "javascriptreact",
35191
+ "typescript",
35192
+ "typescriptreact"
35193
+ ]
35194
+ });
35195
+ this.vscode?.extensions.addRecommendations("dbaeumer.vscode-eslint");
35196
+ this.vscode?.extensions.addRecommendations("esbenp.prettier-vscode");
35197
+ const turbo = TurboRepo.of(this);
35198
+ if (turbo?.compileTask) {
35199
+ turbo.compileTask.inputs.push(
35200
+ "public/**",
35201
+ "index.html",
35202
+ "vite.config.ts"
35203
+ );
35204
+ }
35205
+ if (userOptions.sampleCode === true) {
35206
+ const siteName = options.name;
35207
+ new SampleFile5(this, "index.html", {
35208
+ contents: `<!doctype html>
35209
+ <html>
35210
+ <head>
35211
+ <meta charset="utf-8"/>
35212
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
35213
+ <title>${siteName}</title>
35214
+ </head>
35215
+ <body>
35216
+ <div id="root"></div>
35217
+ <script type="module" src="/src/main.tsx"></script>
35218
+ </body>
35219
+ </html>
35220
+ `
35221
+ });
35222
+ new SampleFile5(this, "src/routes.tsx", {
35223
+ contents: `import { createBrowserRouter } from 'react-router-dom';
35224
+ import App from './App';
35225
+
35226
+ export const router = createBrowserRouter([
35227
+ { path: '/', element: <App /> },
35228
+ ]);
35229
+ `
35230
+ });
35231
+ new SampleFile5(this, "src/main.tsx", {
35232
+ contents: `import React from 'react';
35233
+ import ReactDOM from 'react-dom/client';
35234
+ import { RouterProvider } from 'react-router-dom';
35235
+ import { router } from './routes';
35236
+ import './index.css';
35237
+
35238
+ ReactDOM.createRoot(document.getElementById('root')!).render(
35239
+ <React.StrictMode>
35240
+ <RouterProvider router={router} />
35241
+ </React.StrictMode>
35242
+ );
35243
+ `
35244
+ });
35245
+ new SampleFile5(this, "src/App.tsx", {
35246
+ contents: `export default function App() {
35247
+ return (
35248
+ <main className="p-4">
35249
+ <h1 className="text-2xl font-bold">Hello from ${siteName}</h1>
35250
+ </main>
35251
+ );
35252
+ }
35253
+ `
35254
+ });
35255
+ new SampleFile5(this, "src/index.css", {
35256
+ contents: `@import "tailwindcss";
35257
+ `
35258
+ });
35259
+ new SampleFile5(this, "src/setupTests.ts", {
35260
+ contents: `import '@testing-library/jest-dom';
35261
+ `
35262
+ });
35263
+ }
35264
+ }
35265
+ };
35266
+
34886
35267
  // src/projects/starlight-project.ts
34887
- import { SampleFile as SampleFile3 } from "projen";
35268
+ import { SampleFile as SampleFile6 } from "projen";
34888
35269
  var STARLIGHT_ROLE = {
34889
35270
  DOCS: "docs",
34890
35271
  SITE: "site"
@@ -34926,10 +35307,10 @@ var StarlightProject = class extends AstroProject {
34926
35307
  turbo.compileTask.inputs.push("src/content/**");
34927
35308
  }
34928
35309
  if (userOptions.sampleContent === true) {
34929
- new SampleFile3(this, "src/content/docs/index.mdx", {
35310
+ new SampleFile6(this, "src/content/docs/index.mdx", {
34930
35311
  contents: DEFAULT_INDEX_MDX
34931
35312
  });
34932
- new SampleFile3(this, "src/content.config.ts", {
35313
+ new SampleFile6(this, "src/content.config.ts", {
34933
35314
  contents: DEFAULT_CONTENT_CONFIG_TS
34934
35315
  });
34935
35316
  }
@@ -35105,6 +35486,7 @@ export {
35105
35486
  REQUIREMENTS_WRITER_PATHS,
35106
35487
  ROOT_CI_TASK_NAME,
35107
35488
  ROOT_TURBO_TASK_NAME,
35489
+ ReactViteSiteProject,
35108
35490
  ResetTask,
35109
35491
  SCHEDULED_TASK_MODEL_VALUES,
35110
35492
  SCOPE_CLASS_VALUES,
@@ -35131,6 +35513,8 @@ export {
35131
35513
  Vitest,
35132
35514
  addApproveMergeUpgradeWorkflow,
35133
35515
  addBuildCompleteJob,
35516
+ addPlaywright,
35517
+ addStorybook,
35134
35518
  addSyncLabelsWorkflow,
35135
35519
  agendaBundle,
35136
35520
  analyzeTsDocCoverage,
@@ -35258,6 +35642,7 @@ export {
35258
35642
  resolveOutdirFromPackageName,
35259
35643
  resolveOverrideForLabels,
35260
35644
  resolveProgressFiles,
35645
+ resolveReactViteSiteProjectOutdir,
35261
35646
  resolveRunRatio,
35262
35647
  resolveScheduledTasks,
35263
35648
  resolveScopeGate,