@codedrifters/configulator 0.0.155 → 0.0.157

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.js CHANGED
@@ -192,6 +192,7 @@ __export(index_exports, {
192
192
  MonorepoProject: () => MonorepoProject,
193
193
  PROD_DEPLOY_NAME: () => PROD_DEPLOY_NAME,
194
194
  PnpmWorkspace: () => PnpmWorkspace,
195
+ ProjectMetadata: () => ProjectMetadata,
195
196
  ROOT_CI_TASK_NAME: () => ROOT_CI_TASK_NAME,
196
197
  ROOT_TURBO_TASK_NAME: () => ROOT_TURBO_TASK_NAME,
197
198
  ResetTask: () => ResetTask,
@@ -213,6 +214,7 @@ __export(index_exports, {
213
214
  jestBundle: () => jestBundle,
214
215
  pnpmBundle: () => pnpmBundle,
215
216
  projenBundle: () => projenBundle,
217
+ resolveTemplateVariables: () => resolveTemplateVariables,
216
218
  turborepoBundle: () => turborepoBundle,
217
219
  typescriptBundle: () => typescriptBundle,
218
220
  vitestBundle: () => vitestBundle
@@ -220,7 +222,7 @@ __export(index_exports, {
220
222
  module.exports = __toCommonJS(index_exports);
221
223
 
222
224
  // src/agent/agent-config.ts
223
- var import_projen7 = require("projen");
225
+ var import_projen8 = require("projen");
224
226
 
225
227
  // src/agent/types.ts
226
228
  var AGENT_RULE_SCOPE = {
@@ -331,10 +333,109 @@ var awsCdkBundle = {
331
333
  };
332
334
 
333
335
  // src/agent/bundles/base.ts
336
+ var createRuleSkill = {
337
+ name: "create-rule",
338
+ description: "Guide for creating new agent rules in this project using configulator",
339
+ disableModelInvocation: true,
340
+ instructions: [
341
+ "# Create Agent Rule",
342
+ "",
343
+ "Create a new agent rule for the **{{repository.owner}}/{{repository.name}}** project.",
344
+ "",
345
+ "## Steps",
346
+ "",
347
+ "1. **Identify the rule purpose** \u2014 ask what behavior the rule should enforce or guide",
348
+ "2. **Choose a scope:**",
349
+ " - `AGENT_RULE_SCOPE.ALWAYS` \u2014 active in all contexts",
350
+ " - `AGENT_RULE_SCOPE.FILE_PATTERN` \u2014 active only when working on matching files (requires `filePatterns`)",
351
+ "3. **Pick a name** \u2014 lowercase kebab-case (e.g., `react-conventions`, `api-error-handling`)",
352
+ "4. **Write the content** \u2014 clear, actionable markdown instructions",
353
+ "5. **Add to the project config** \u2014 add the rule to `AgentConfigOptions.rules` in the Projen config file",
354
+ "",
355
+ "## Rule Template",
356
+ "",
357
+ "```typescript",
358
+ "import { AGENT_RULE_SCOPE } from '@codedrifters/configulator';",
359
+ "",
360
+ "// In your AgentConfig options:",
361
+ "{",
362
+ " rules: [",
363
+ " {",
364
+ " name: 'my-new-rule',",
365
+ " description: 'What this rule does \u2014 used by AI for rule selection',",
366
+ " scope: AGENT_RULE_SCOPE.ALWAYS, // or FILE_PATTERN",
367
+ " // filePatterns: ['src/**/*.ts'], // required for FILE_PATTERN scope",
368
+ " content: [",
369
+ " '# Rule Title',",
370
+ " '',",
371
+ " '## Guidelines',",
372
+ " '',",
373
+ " '- Guideline 1',",
374
+ " '- Guideline 2',",
375
+ " ].join('\\n'),",
376
+ " tags: ['coding'], // optional: for ordering",
377
+ " },",
378
+ " ],",
379
+ "}",
380
+ "```",
381
+ "",
382
+ "## Best Practices",
383
+ "",
384
+ "- Keep rules **focused** \u2014 one concern per rule",
385
+ '- Use **imperative tone** \u2014 "Use X" not "You should use X"',
386
+ "- Include **examples** for complex patterns",
387
+ "- Use `ruleExtensions` to add project-specific content to existing bundle rules instead of replacing them"
388
+ ].join("\n")
389
+ };
390
+ var reviewPrSkill = {
391
+ name: "review-pr",
392
+ description: "Review a pull request for code quality, conventions, and correctness",
393
+ instructions: [
394
+ "# Review Pull Request",
395
+ "",
396
+ "Review the current pull request in **{{repository.owner}}/{{repository.name}}**.",
397
+ "",
398
+ "## Review Checklist",
399
+ "",
400
+ "1. **Read the PR description** \u2014 understand the intent and linked issue",
401
+ "2. **Review the diff** \u2014 check all changed files for:",
402
+ " - Correctness and logic errors",
403
+ " - Adherence to project conventions",
404
+ " - Test coverage for new/changed behavior",
405
+ " - No unintended side effects",
406
+ "3. **Check PR conventions:**",
407
+ " - Title uses conventional commit prefix (`feat:`, `fix:`, `docs:`, etc.)",
408
+ " - Body includes a closing keyword (`Closes #<issue>`)",
409
+ " - Summary of changes is present",
410
+ "4. **Verify build and tests pass**",
411
+ "",
412
+ "## Commands",
413
+ "",
414
+ "```bash",
415
+ "# View the PR details",
416
+ "gh pr view",
417
+ "",
418
+ "# View the diff",
419
+ "gh pr diff",
420
+ "",
421
+ "# Check CI status",
422
+ "gh pr checks",
423
+ "```",
424
+ "",
425
+ "## Output Format",
426
+ "",
427
+ "Provide a structured review with:",
428
+ "- **Summary**: One-line verdict (approve, request changes, or comment)",
429
+ "- **Findings**: Bulleted list of issues or suggestions, grouped by severity",
430
+ "- **Positive notes**: What was done well"
431
+ ].join("\n"),
432
+ allowedTools: ["Read", "Glob", "Grep", "Bash(gh *)"]
433
+ };
334
434
  var baseBundle = {
335
435
  name: "base",
336
436
  description: "Core rules: project overview, interaction style, and general coding conventions",
337
437
  appliesWhen: () => true,
438
+ skills: [createRuleSkill, reviewPrSkill],
338
439
  rules: [
339
440
  {
340
441
  name: "project-overview",
@@ -343,6 +444,9 @@ var baseBundle = {
343
444
  content: [
344
445
  "# Project Overview",
345
446
  "",
447
+ "**Repository:** {{repository.owner}}/{{repository.name}}",
448
+ "**Default branch:** {{repository.defaultBranch}}",
449
+ "",
346
450
  "## Important Notes",
347
451
  "",
348
452
  "- **Never edit generated files** \u2014 they are marked with `// ~~ Generated by projen`",
@@ -1303,8 +1407,78 @@ var BUILT_IN_BUNDLES = [
1303
1407
  projenBundle
1304
1408
  ];
1305
1409
 
1306
- // src/agent/renderers/claude-renderer.ts
1410
+ // src/projects/project-metadata.ts
1307
1411
  var import_projen5 = require("projen");
1412
+ var import_javascript2 = require("projen/lib/javascript");
1413
+ var GITHUB_HTTPS_RE = /(?:https?:\/\/|git\+https:\/\/)github\.com\/([^/]+)\/([^/.]+)(?:\.git)?/;
1414
+ var GITHUB_SSH_RE = /git@github\.com:([^/]+)\/([^/.]+)(?:\.git)?/;
1415
+ function parseGitHubUrl(url) {
1416
+ const httpsMatch = url.match(GITHUB_HTTPS_RE);
1417
+ if (httpsMatch) {
1418
+ return { owner: httpsMatch[1], name: httpsMatch[2] };
1419
+ }
1420
+ const sshMatch = url.match(GITHUB_SSH_RE);
1421
+ if (sshMatch) {
1422
+ return { owner: sshMatch[1], name: sshMatch[2] };
1423
+ }
1424
+ return { owner: void 0, name: void 0 };
1425
+ }
1426
+ var ProjectMetadata = class _ProjectMetadata extends import_projen5.Component {
1427
+ /**
1428
+ * Returns the ProjectMetadata instance for a project, or undefined
1429
+ * if the component has not been added.
1430
+ */
1431
+ static of(project) {
1432
+ const isProjectMetadata = (c) => c instanceof _ProjectMetadata;
1433
+ return project.components.find(isProjectMetadata);
1434
+ }
1435
+ constructor(project, options = {}) {
1436
+ super(project);
1437
+ this.metadata = this.resolveMetadata(options);
1438
+ }
1439
+ /**
1440
+ * Merges explicit options with auto-detected values.
1441
+ * Auto-detection reads the repository URL from package.json
1442
+ * (via Projen's NodePackage manifest) and parses GitHub owner/name.
1443
+ * Explicit options always take precedence over auto-detected values.
1444
+ */
1445
+ resolveMetadata(options) {
1446
+ const autoDetected = this.autoDetectRepository();
1447
+ return {
1448
+ repository: {
1449
+ owner: options.repository?.owner ?? autoDetected.owner,
1450
+ name: options.repository?.name ?? autoDetected.name,
1451
+ defaultBranch: options.repository?.defaultBranch ?? "main"
1452
+ },
1453
+ githubProject: options.githubProject,
1454
+ organization: options.organization,
1455
+ slack: options.slack,
1456
+ labels: options.labels,
1457
+ milestones: options.milestones,
1458
+ docsPath: options.docsPath,
1459
+ deployment: options.deployment
1460
+ };
1461
+ }
1462
+ /**
1463
+ * Attempts to auto-detect repository owner and name from the Projen
1464
+ * project's package.json repository field.
1465
+ */
1466
+ autoDetectRepository() {
1467
+ if (!(this.project instanceof import_javascript2.NodeProject)) {
1468
+ return { owner: void 0, name: void 0 };
1469
+ }
1470
+ const manifest = this.project.package.manifest;
1471
+ const repoField = manifest.repository;
1472
+ if (!repoField) {
1473
+ return { owner: void 0, name: void 0 };
1474
+ }
1475
+ const url = typeof repoField === "string" ? repoField : repoField.url ?? "";
1476
+ return parseGitHubUrl(url);
1477
+ }
1478
+ };
1479
+
1480
+ // src/agent/renderers/claude-renderer.ts
1481
+ var import_projen6 = require("projen");
1308
1482
  var import_textfile2 = require("projen/lib/textfile");
1309
1483
  var GENERATED_MARKER = "<!-- ~~ Generated by @codedrifters/configulator. Edits welcome \u2014 please contribute improvements back. ~~ -->";
1310
1484
  var ClaudeRenderer = class _ClaudeRenderer {
@@ -1465,7 +1639,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
1465
1639
  hasContent = true;
1466
1640
  }
1467
1641
  if (!hasContent) return;
1468
- new import_projen5.JsonFile(component, ".claude/settings.json", { obj });
1642
+ new import_projen6.JsonFile(component, ".claude/settings.json", { obj });
1469
1643
  }
1470
1644
  static buildSandboxObj(sandbox) {
1471
1645
  const obj = {};
@@ -1532,6 +1706,15 @@ var ClaudeRenderer = class _ClaudeRenderer {
1532
1706
  lines.push(` - "${p}"`);
1533
1707
  }
1534
1708
  }
1709
+ if (skill.context) {
1710
+ lines.push(`context: "${skill.context}"`);
1711
+ }
1712
+ if (skill.agent) {
1713
+ lines.push(`agent: "${skill.agent}"`);
1714
+ }
1715
+ if (skill.shell) {
1716
+ lines.push(`shell: "${skill.shell}"`);
1717
+ }
1535
1718
  if (skill.allowedTools && skill.allowedTools.length > 0) {
1536
1719
  lines.push(`allowed-tools:`);
1537
1720
  for (const tool of skill.allowedTools) {
@@ -1603,7 +1786,7 @@ var CopilotRenderer = class {
1603
1786
  };
1604
1787
 
1605
1788
  // src/agent/renderers/cursor-renderer.ts
1606
- var import_projen6 = require("projen");
1789
+ var import_projen7 = require("projen");
1607
1790
  var import_textfile3 = require("projen/lib/textfile");
1608
1791
  var GENERATED_MARKER2 = "# ~~ Generated by @codedrifters/configulator. Edits welcome \u2014 please contribute improvements back. ~~";
1609
1792
  var CursorRenderer = class _CursorRenderer {
@@ -1648,6 +1831,15 @@ var CursorRenderer = class _CursorRenderer {
1648
1831
  if (skill.userInvocable === false) {
1649
1832
  lines.push(`user-invocable: false`);
1650
1833
  }
1834
+ if (skill.context) {
1835
+ lines.push(`context: "${skill.context}"`);
1836
+ }
1837
+ if (skill.agent) {
1838
+ lines.push(`agent: "${skill.agent}"`);
1839
+ }
1840
+ if (skill.shell) {
1841
+ lines.push(`shell: "${skill.shell}"`);
1842
+ }
1651
1843
  if (skill.allowedTools && skill.allowedTools.length > 0) {
1652
1844
  lines.push(`allowed-tools:`);
1653
1845
  for (const tool of skill.allowedTools) {
@@ -1698,7 +1890,7 @@ var CursorRenderer = class _CursorRenderer {
1698
1890
  if (config.env) server.env = { ...config.env };
1699
1891
  servers[name] = server;
1700
1892
  }
1701
- new import_projen6.JsonFile(component, ".cursor/mcp.json", { obj });
1893
+ new import_projen7.JsonFile(component, ".cursor/mcp.json", { obj });
1702
1894
  }
1703
1895
  static renderHooks(component, settings) {
1704
1896
  if (!settings?.hooks) return;
@@ -1736,7 +1928,7 @@ var CursorRenderer = class _CursorRenderer {
1736
1928
  }
1737
1929
  if (stop?.length) hooks.stop = stop.map((h) => ({ command: h.command }));
1738
1930
  if (Object.keys(hooks).length === 0) return;
1739
- new import_projen6.JsonFile(component, ".cursor/hooks.json", {
1931
+ new import_projen7.JsonFile(component, ".cursor/hooks.json", {
1740
1932
  obj: { version: 1, hooks }
1741
1933
  });
1742
1934
  }
@@ -1754,8 +1946,57 @@ var CursorRenderer = class _CursorRenderer {
1754
1946
  }
1755
1947
  };
1756
1948
 
1949
+ // src/agent/template-resolver.ts
1950
+ var FALLBACKS = {
1951
+ "repository.owner": "<owner>",
1952
+ "repository.name": "<repo>",
1953
+ "repository.defaultBranch": "main",
1954
+ "organization.name": "<organization>",
1955
+ "organization.githubOrg": "<org>",
1956
+ "githubProject.name": "<project-name>",
1957
+ "githubProject.number": "<project-number>",
1958
+ "githubProject.nodeId": "<project-node-id>",
1959
+ docsPath: "<docs-path>"
1960
+ };
1961
+ var TEMPLATE_RE = /\{\{(\w+(?:\.\w+)*)\}\}/g;
1962
+ function getNestedValue(obj, path) {
1963
+ const parts = path.split(".");
1964
+ let current = obj;
1965
+ for (const part of parts) {
1966
+ if (current == null || typeof current !== "object") {
1967
+ return void 0;
1968
+ }
1969
+ current = current[part];
1970
+ }
1971
+ if (current == null) {
1972
+ return void 0;
1973
+ }
1974
+ return String(current);
1975
+ }
1976
+ function resolveTemplateVariables(template, metadata) {
1977
+ if (!TEMPLATE_RE.test(template)) {
1978
+ return { resolved: template, unresolvedKeys: [] };
1979
+ }
1980
+ const unresolvedKeys = [];
1981
+ TEMPLATE_RE.lastIndex = 0;
1982
+ const resolved = template.replace(TEMPLATE_RE, (_match, key) => {
1983
+ if (metadata) {
1984
+ const value = getNestedValue(
1985
+ metadata,
1986
+ key
1987
+ );
1988
+ if (value !== void 0) {
1989
+ return value;
1990
+ }
1991
+ }
1992
+ unresolvedKeys.push(key);
1993
+ return FALLBACKS[key] ?? `<${key}>`;
1994
+ });
1995
+ return { resolved, unresolvedKeys };
1996
+ }
1997
+
1757
1998
  // src/agent/agent-config.ts
1758
- var AgentConfig = class _AgentConfig extends import_projen7.Component {
1999
+ var AgentConfig = class _AgentConfig extends import_projen8.Component {
1759
2000
  /**
1760
2001
  * Find the AgentConfig component on a project.
1761
2002
  */
@@ -1774,12 +2015,20 @@ var AgentConfig = class _AgentConfig extends import_projen7.Component {
1774
2015
  const skills = this.resolveSkills();
1775
2016
  const subAgents = this.resolveSubAgents();
1776
2017
  const mcpServers = this.options.mcpServers ?? {};
2018
+ const projectMetadata = ProjectMetadata.of(this.project);
2019
+ const metadata = projectMetadata?.metadata;
2020
+ const resolvedRules = this.resolveTemplates(rules, metadata);
2021
+ const resolvedSkills = this.resolveSkillTemplates(skills, metadata);
2022
+ const resolvedSubAgents = this.resolveSubAgentTemplates(
2023
+ subAgents,
2024
+ metadata
2025
+ );
1777
2026
  if (platforms.includes(AGENT_PLATFORM.CURSOR)) {
1778
2027
  CursorRenderer.render(
1779
2028
  this,
1780
- rules,
1781
- skills,
1782
- subAgents,
2029
+ resolvedRules,
2030
+ resolvedSkills,
2031
+ resolvedSubAgents,
1783
2032
  mcpServers,
1784
2033
  this.options.cursorSettings
1785
2034
  );
@@ -1787,18 +2036,28 @@ var AgentConfig = class _AgentConfig extends import_projen7.Component {
1787
2036
  if (platforms.includes(AGENT_PLATFORM.CLAUDE)) {
1788
2037
  ClaudeRenderer.render(
1789
2038
  this,
1790
- rules,
1791
- skills,
1792
- subAgents,
2039
+ resolvedRules,
2040
+ resolvedSkills,
2041
+ resolvedSubAgents,
1793
2042
  mcpServers,
1794
2043
  this.options.claudeSettings
1795
2044
  );
1796
2045
  }
1797
2046
  if (platforms.includes(AGENT_PLATFORM.CODEX)) {
1798
- CodexRenderer.render(this, rules, skills, subAgents);
2047
+ CodexRenderer.render(
2048
+ this,
2049
+ resolvedRules,
2050
+ resolvedSkills,
2051
+ resolvedSubAgents
2052
+ );
1799
2053
  }
1800
2054
  if (platforms.includes(AGENT_PLATFORM.COPILOT)) {
1801
- CopilotRenderer.render(this, rules, skills, subAgents);
2055
+ CopilotRenderer.render(
2056
+ this,
2057
+ resolvedRules,
2058
+ resolvedSkills,
2059
+ resolvedSubAgents
2060
+ );
1802
2061
  }
1803
2062
  }
1804
2063
  resolvePlatforms() {
@@ -1901,13 +2160,65 @@ ${extra}`
1901
2160
  }
1902
2161
  return [...agentMap.values()];
1903
2162
  }
2163
+ /**
2164
+ * Resolves template variables in rule content using project metadata.
2165
+ * Emits synthesis warnings for rules with unresolved variables.
2166
+ */
2167
+ resolveTemplates(rules, metadata) {
2168
+ return rules.map((rule) => {
2169
+ const { resolved, unresolvedKeys } = resolveTemplateVariables(
2170
+ rule.content,
2171
+ metadata
2172
+ );
2173
+ if (unresolvedKeys.length > 0) {
2174
+ this.project.logger.warn(
2175
+ `AgentConfig: ProjectMetadata not found; rule '${rule.name}' using default values`
2176
+ );
2177
+ }
2178
+ return resolved !== rule.content ? { ...rule, content: resolved } : rule;
2179
+ });
2180
+ }
2181
+ /**
2182
+ * Resolves template variables in skill instructions using project metadata.
2183
+ */
2184
+ resolveSkillTemplates(skills, metadata) {
2185
+ return skills.map((skill) => {
2186
+ const { resolved, unresolvedKeys } = resolveTemplateVariables(
2187
+ skill.instructions,
2188
+ metadata
2189
+ );
2190
+ if (unresolvedKeys.length > 0) {
2191
+ this.project.logger.warn(
2192
+ `AgentConfig: ProjectMetadata not found; skill '${skill.name}' using default values`
2193
+ );
2194
+ }
2195
+ return resolved !== skill.instructions ? { ...skill, instructions: resolved } : skill;
2196
+ });
2197
+ }
2198
+ /**
2199
+ * Resolves template variables in sub-agent prompts using project metadata.
2200
+ */
2201
+ resolveSubAgentTemplates(subAgents, metadata) {
2202
+ return subAgents.map((agent) => {
2203
+ const { resolved, unresolvedKeys } = resolveTemplateVariables(
2204
+ agent.prompt,
2205
+ metadata
2206
+ );
2207
+ if (unresolvedKeys.length > 0) {
2208
+ this.project.logger.warn(
2209
+ `AgentConfig: ProjectMetadata not found; sub-agent '${agent.name}' using default values`
2210
+ );
2211
+ }
2212
+ return resolved !== agent.prompt ? { ...agent, prompt: resolved } : agent;
2213
+ });
2214
+ }
1904
2215
  };
1905
2216
 
1906
2217
  // src/aws/aws-deployment-config.ts
1907
2218
  var import_node_path = require("path");
1908
2219
  var import_utils8 = __toESM(require_lib());
1909
- var import_projen8 = require("projen");
1910
- var AwsDeploymentConfig = class _AwsDeploymentConfig extends import_projen8.Component {
2220
+ var import_projen9 = require("projen");
2221
+ var AwsDeploymentConfig = class _AwsDeploymentConfig extends import_projen9.Component {
1911
2222
  constructor(project) {
1912
2223
  super(project);
1913
2224
  /**
@@ -2024,8 +2335,8 @@ var AwsDeploymentConfig = class _AwsDeploymentConfig extends import_projen8.Comp
2024
2335
 
2025
2336
  // src/aws/aws-deployment-target.ts
2026
2337
  var import_utils9 = __toESM(require_lib());
2027
- var import_projen9 = require("projen");
2028
- var AwsDeploymentTarget = class _AwsDeploymentTarget extends import_projen9.Component {
2338
+ var import_projen10 = require("projen");
2339
+ var AwsDeploymentTarget = class _AwsDeploymentTarget extends import_projen10.Component {
2029
2340
  constructor(project, options) {
2030
2341
  super(project);
2031
2342
  /**
@@ -2240,12 +2551,12 @@ var VERSION_KEYS_SKIP = [
2240
2551
 
2241
2552
  // src/jsii/jsii-faker.ts
2242
2553
  var spec = __toESM(require("@jsii/spec"));
2243
- var import_projen10 = require("projen");
2554
+ var import_projen11 = require("projen");
2244
2555
  var ProjenBaseFqn = {
2245
2556
  TYPESCRIPT_PROJECT: "projen.typescript.TypeScriptProject",
2246
2557
  TYPESCRIPT_PROJECT_OPTIONS: "projen.typescript.TypeScriptProjectOptions"
2247
2558
  };
2248
- var JsiiFaker = class _JsiiFaker extends import_projen10.Component {
2559
+ var JsiiFaker = class _JsiiFaker extends import_projen11.Component {
2249
2560
  constructor(project) {
2250
2561
  super(project);
2251
2562
  this.project = project;
@@ -2256,7 +2567,7 @@ var JsiiFaker = class _JsiiFaker extends import_projen10.Component {
2256
2567
  };
2257
2568
  };
2258
2569
  this._assemblyName = this.project.package.packageName;
2259
- new import_projen10.JsonFile(project, ".jsii", {
2570
+ new import_projen11.JsonFile(project, ".jsii", {
2260
2571
  obj: () => {
2261
2572
  return {
2262
2573
  name: this._assemblyName,
@@ -2294,23 +2605,23 @@ var JsiiFaker = class _JsiiFaker extends import_projen10.Component {
2294
2605
  };
2295
2606
 
2296
2607
  // src/projects/monorepo-project.ts
2297
- var import_javascript3 = require("projen/lib/javascript");
2608
+ var import_javascript4 = require("projen/lib/javascript");
2298
2609
  var import_typescript3 = require("projen/lib/typescript");
2299
2610
  var import_ts_deepmerge2 = require("ts-deepmerge");
2300
2611
 
2301
2612
  // src/tasks/reset-task.ts
2302
- var import_projen12 = require("projen");
2613
+ var import_projen13 = require("projen");
2303
2614
 
2304
2615
  // src/projects/typescript-project.ts
2305
- var import_projen11 = require("projen");
2306
- var import_javascript2 = require("projen/lib/javascript");
2616
+ var import_projen12 = require("projen");
2617
+ var import_javascript3 = require("projen/lib/javascript");
2307
2618
  var import_release = require("projen/lib/release");
2308
2619
  var import_ts_deepmerge = require("ts-deepmerge");
2309
2620
  var TestRunner = {
2310
2621
  JEST: "jest",
2311
2622
  VITEST: "vitest"
2312
2623
  };
2313
- var TypeScriptProject = class extends import_projen11.typescript.TypeScriptProject {
2624
+ var TypeScriptProject = class extends import_projen12.typescript.TypeScriptProject {
2314
2625
  constructor(userOptions) {
2315
2626
  const pnpmVersion = userOptions.parent && userOptions.parent instanceof MonorepoProject ? userOptions.parent.pnpmVersion : VERSION.PNPM_VERSION;
2316
2627
  const pnpmWorkspace = userOptions.parent && userOptions.parent instanceof MonorepoProject ? PnpmWorkspace.of(userOptions.parent) : void 0;
@@ -2328,7 +2639,7 @@ var TypeScriptProject = class extends import_projen11.typescript.TypeScriptProje
2328
2639
  /**
2329
2640
  * Packaging options
2330
2641
  */
2331
- packageManager: import_javascript2.NodePackageManager.PNPM,
2642
+ packageManager: import_javascript3.NodePackageManager.PNPM,
2332
2643
  pnpmVersion,
2333
2644
  licensed: userOptions.license !== void 0 || false,
2334
2645
  copyrightOwner: "CodeDrifters",
@@ -2346,7 +2657,7 @@ var TypeScriptProject = class extends import_projen11.typescript.TypeScriptProje
2346
2657
  jestConfig: {
2347
2658
  roots: [`<rootDir>/src`],
2348
2659
  transform: {
2349
- ["^.+\\.[t]sx?$"]: new import_javascript2.Transform("@swc/jest")
2660
+ ["^.+\\.[t]sx?$"]: new import_javascript3.Transform("@swc/jest")
2350
2661
  },
2351
2662
  moduleFileExtensions: ["js", "ts"]
2352
2663
  }
@@ -2381,7 +2692,7 @@ var TypeScriptProject = class extends import_projen11.typescript.TypeScriptProje
2381
2692
  exclude: Object.keys(pnpmWorkspace?.defaultCatalog || {}),
2382
2693
  ...userOptions.parent && userOptions.parent instanceof MonorepoProject ? {
2383
2694
  workflowOptions: {
2384
- schedule: import_javascript2.UpgradeDependenciesSchedule.WEEKLY
2695
+ schedule: import_javascript3.UpgradeDependenciesSchedule.WEEKLY
2385
2696
  },
2386
2697
  cooldown: 1
2387
2698
  } : {}
@@ -2470,7 +2781,7 @@ var TypeScriptProject = class extends import_projen11.typescript.TypeScriptProje
2470
2781
  };
2471
2782
 
2472
2783
  // src/tasks/reset-task.ts
2473
- var ResetTask = class _ResetTask extends import_projen12.Component {
2784
+ var ResetTask = class _ResetTask extends import_projen13.Component {
2474
2785
  constructor(project, options = {}) {
2475
2786
  super(project);
2476
2787
  this.project = project;
@@ -2543,12 +2854,12 @@ var ResetTask = class _ResetTask extends import_projen12.Component {
2543
2854
  };
2544
2855
 
2545
2856
  // src/vscode/vscode.ts
2546
- var import_projen13 = require("projen");
2547
- var VSCodeConfig = class extends import_projen13.Component {
2857
+ var import_projen14 = require("projen");
2858
+ var VSCodeConfig = class extends import_projen14.Component {
2548
2859
  constructor(project) {
2549
2860
  super(project);
2550
- const vsConfig = new import_projen13.vscode.VsCode(project);
2551
- const vsSettings = new import_projen13.vscode.VsCodeSettings(vsConfig);
2861
+ const vsConfig = new import_projen14.vscode.VsCode(project);
2862
+ const vsSettings = new import_projen14.vscode.VsCodeSettings(vsConfig);
2552
2863
  vsSettings.addSetting("editor.tabSize", 2);
2553
2864
  vsSettings.addSetting("editor.detectIndentation", false);
2554
2865
  vsSettings.addSetting("editor.bracketPairColorization.enabled", true);
@@ -2787,7 +3098,7 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
2787
3098
  depsUpgradeOptions: {
2788
3099
  exclude: ["@codedrifters/configulator"],
2789
3100
  workflowOptions: {
2790
- schedule: import_javascript3.UpgradeDependenciesSchedule.DAILY
3101
+ schedule: import_javascript4.UpgradeDependenciesSchedule.DAILY
2791
3102
  },
2792
3103
  cooldown: 1
2793
3104
  },
@@ -2843,7 +3154,7 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
2843
3154
  * Use PNPM instead of the default (Yarn). Much of the ecosystem depends
2844
3155
  * on PNPM and making monorepos PNPM only simplifies many configurations.
2845
3156
  */
2846
- packageManager: import_javascript3.NodePackageManager.PNPM,
3157
+ packageManager: import_javascript4.NodePackageManager.PNPM,
2847
3158
  /**
2848
3159
  * Some additional pre-build steps if we're using turbo's remote cache.
2849
3160
  * Set GIT_BRANCH_NAME so Turborepo remote cache hashes match between local and CI.
@@ -2920,6 +3231,12 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
2920
3231
  if (options.approveMergeUpgradeOptions) {
2921
3232
  addApproveMergeUpgradeWorkflow(this, options.approveMergeUpgradeOptions);
2922
3233
  }
3234
+ if (options.projectMetadata !== false) {
3235
+ new ProjectMetadata(
3236
+ this,
3237
+ typeof options.projectMetadata === "object" ? options.projectMetadata : {}
3238
+ );
3239
+ }
2923
3240
  if (options.agentConfig) {
2924
3241
  new AgentConfig(this, options.agentConfigOptions);
2925
3242
  }
@@ -2981,9 +3298,9 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
2981
3298
 
2982
3299
  // src/typescript/typescript-config.ts
2983
3300
  var import_node_path2 = require("path");
2984
- var import_projen14 = require("projen");
3301
+ var import_projen15 = require("projen");
2985
3302
  var import_path2 = require("projen/lib/util/path");
2986
- var TypeScriptConfig = class extends import_projen14.Component {
3303
+ var TypeScriptConfig = class extends import_projen15.Component {
2987
3304
  constructor(project) {
2988
3305
  super(project);
2989
3306
  let tsPaths = {};
@@ -3011,12 +3328,12 @@ var TypeScriptConfig = class extends import_projen14.Component {
3011
3328
 
3012
3329
  // src/workflows/aws-deploy-workflow.ts
3013
3330
  var import_utils10 = __toESM(require_lib());
3014
- var import_projen15 = require("projen");
3331
+ var import_projen16 = require("projen");
3015
3332
  var import_build = require("projen/lib/build");
3016
3333
  var import_github = require("projen/lib/github");
3017
3334
  var import_workflows_model4 = require("projen/lib/github/workflows-model");
3018
3335
  var PROD_DEPLOY_NAME = "prod-deploy";
3019
- var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen15.Component {
3336
+ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen16.Component {
3020
3337
  constructor(project, options = {}) {
3021
3338
  super(project);
3022
3339
  this.project = project;
@@ -3298,6 +3615,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen15.Compone
3298
3615
  MonorepoProject,
3299
3616
  PROD_DEPLOY_NAME,
3300
3617
  PnpmWorkspace,
3618
+ ProjectMetadata,
3301
3619
  ROOT_CI_TASK_NAME,
3302
3620
  ROOT_TURBO_TASK_NAME,
3303
3621
  ResetTask,
@@ -3319,6 +3637,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen15.Compone
3319
3637
  jestBundle,
3320
3638
  pnpmBundle,
3321
3639
  projenBundle,
3640
+ resolveTemplateVariables,
3322
3641
  turborepoBundle,
3323
3642
  typescriptBundle,
3324
3643
  vitestBundle