@dbx-tools/projen 0.9.32 → 0.9.37

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 (55) hide show
  1. package/README.md +71 -65
  2. package/index.ts +5 -8
  3. package/package.json +8 -7
  4. package/src/_task-command.ts +0 -75
  5. package/src/barrels.ts +15 -23
  6. package/src/bun-app.ts +5 -6
  7. package/src/clean.ts +41 -15
  8. package/src/codegen.ts +2 -3
  9. package/src/dbx-tools-config.ts +23 -64
  10. package/src/generated.ts +7 -1
  11. package/src/module-exports.ts +35 -3
  12. package/src/openapi.ts +34 -38
  13. package/src/packages.ts +3 -30
  14. package/src/pnpm-workspace.ts +21 -26
  15. package/src/project-js.ts +152 -365
  16. package/src/project-predicate.ts +4 -5
  17. package/src/project-py.ts +55 -144
  18. package/src/publish.ts +1 -1
  19. package/src/python-node-bindings.ts +140 -67
  20. package/src/python-node-bundle.ts +6 -42
  21. package/src/release-context.ts +4 -4
  22. package/src/release.ts +47 -85
  23. package/src/tags.ts +20 -18
  24. package/src/tsconfig.ts +9 -5
  25. package/src/vscode.ts +47 -58
  26. package/src/watch.ts +2 -8
  27. package/src/workspace-version.ts +1 -6
  28. package/tasks/barrels.ts +43 -38
  29. package/tasks/bump.ts +24 -20
  30. package/tasks/clean.ts +54 -50
  31. package/tasks/compile-workspace.ts +2 -117
  32. package/tasks/lib/compile-workspace.ts +119 -0
  33. package/tasks/lib/local-publish.ts +122 -0
  34. package/tasks/lib/publish-npm.ts +458 -0
  35. package/tasks/lib/publish-python.ts +195 -0
  36. package/tasks/lib/publish.ts +264 -0
  37. package/tasks/lib/python-node-bindings.ts +1262 -0
  38. package/tasks/{python-registry.ts → lib/python-registry.ts} +21 -30
  39. package/tasks/{python-release.ts → lib/python-release.ts} +1 -0
  40. package/tasks/lib/release-version.ts +66 -0
  41. package/tasks/lib/release.ts +212 -0
  42. package/tasks/local-publish.ts +4 -118
  43. package/tasks/openapi.ts +25 -21
  44. package/tasks/projenrc.ts +14 -12
  45. package/tasks/publish-npm.ts +3 -364
  46. package/tasks/publish-python.ts +3 -184
  47. package/tasks/publish.ts +3 -279
  48. package/tasks/python-node-bindings.ts +3 -1014
  49. package/tasks/release-version.ts +3 -62
  50. package/tasks/release.ts +3 -121
  51. package/tasks/sync.ts +71 -70
  52. package/tasks/version-check.ts +3 -10
  53. package/src/release-catalog.ts +0 -684
  54. package/tasks/databricks-cli-assets.ts +0 -129
  55. package/tasks/python-node-bindings-watch.ts +0 -47
package/src/project-js.ts CHANGED
@@ -12,24 +12,17 @@ import * as projectUtils from "@dbx-tools/core/project-utils";
12
12
  import { ignore, match } from "@dbx-tools/path";
13
13
  import { object, stringUtils, type OneOrMany } from "@dbx-tools/shared-core";
14
14
  import { type IConstruct } from "constructs";
15
- import { Component, IgnoreFile, Project, type TaskOptions, javascript, typescript } from "projen";
16
- import { BuildWorkflow } from "projen/lib/build";
17
- import { AutoMerge } from "projen/lib/github";
15
+ import { Component, IgnoreFile, Project, javascript, typescript } from "projen";
18
16
  import { JobPermission, type JobStep } from "projen/lib/github/workflows-model";
19
17
  import type { ReleaseProjectOptions } from "projen/lib/release";
20
- import { mixin } from "..";
21
18
  import { generateBarrels } from "./barrels.ts";
22
- import {
23
- BUN_APP_OVERRIDES,
24
- BunBuildFile,
25
- BunDevServerFile,
26
- BunfigFile,
27
- RootBunfigFile,
28
- } from "./bun-app.ts";
19
+
20
+ import { BUN_APP_OVERRIDES, RootBunfigFile } from "./bun-app.ts";
29
21
  import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
30
22
  import { codegenModulePaths, generateCodegen } from "./codegen.ts";
31
23
  import { DBXToolsConfig, type DBXToolsConfigOptions } from "./dbx-tools-config.ts";
32
24
  import { resolvePkgRoot } from "./engine-root.ts";
25
+ import * as mixin from "./mixin.ts";
33
26
  import {
34
27
  DEFAULT_PACKAGE_ROOTS,
35
28
  type DiscoveredPackage,
@@ -42,17 +35,12 @@ import { PnpmWorkspaceState, type DBXToolsPNPMWorkspaceOptions } from "./pnpm-wo
42
35
  import type { DBXToolsProject, DBXToolsProjectOptions as CommonProjectOptions } from "./project.ts";
43
36
  import { PROJEN_VERSION } from "./projen-version.ts";
44
37
  import { applyCompiledPublish } from "./publish.ts";
45
- import {
46
- DBXToolsReleaseCatalog,
47
- type ExternalReleaseProjectRegistration,
48
- type ReleaseDependencyInput,
49
- type ReleaseUnitRule,
50
- } from "./release-catalog.ts";
38
+ import { generatePythonNodeBindings } from "./python-node-bindings.ts";
51
39
  import { DBXToolsRelease, type ReleaseDocsOptions } from "./release.ts";
52
40
  import { AGNOSTIC_COMPILER_OPTIONS, PACKAGE_TAG_MIXINS, type PackageTag } from "./tags.ts";
53
41
  import { DBXToolsRootTsconfig } from "./tsconfig.ts";
54
- import { DBXToolsVsCode } from "./vscode.ts";
55
- import { syncWorkspaceManifestVersion } from "./workspace-version.ts";
42
+ import { configureVsCode } from "./vscode.ts";
43
+ import { readWorkspaceVersion, syncWorkspaceManifestVersion } from "./workspace-version.ts";
56
44
 
57
45
  /**
58
46
  * The dbx-tools project surface, backed by projen's Node toolchain. A single
@@ -73,12 +61,8 @@ export interface DBXToolsJavaScriptProject extends DBXToolsProject, javascript.N
73
61
  pnpmWorkspace?: PnpmWorkspaceState;
74
62
  /** Root projenrc tsconfigs - only a tree ROOT has one. */
75
63
  rootTsconfig?: DBXToolsRootTsconfig;
76
- /** Root `.vscode/*` - only a tree ROOT has one. */
77
- vsCode?: DBXToolsVsCode;
78
64
  /** Repository outputs excluded from generated workflow dependency-cache hashing. */
79
65
  readonly workflowCacheIgnorePaths: readonly string[];
80
- /** Cross-language release-unit ownership and version lookup. */
81
- readonly releaseCatalog: DBXToolsReleaseCatalog;
82
66
  }
83
67
 
84
68
  /** Parsed npm package identifier: optional scope plus the unscoped package name. */
@@ -140,7 +124,8 @@ export class PackageIdentifier {
140
124
 
141
125
  /** Parsed `package.json` `name` for a projen `NodeProject`. */
142
126
  export function identifier(project: Project): PackageIdentifier {
143
- return PackageIdentifier.parse(project.name) ?? new PackageIdentifier(undefined, project.name);
127
+ const name = javascript.NodePackage.of(project)?.packageName ?? project.name;
128
+ return PackageIdentifier.parse(name) ?? new PackageIdentifier(undefined, name);
144
129
  }
145
130
 
146
131
  /** Root-only `package.json` fields. */
@@ -149,25 +134,19 @@ function configureRootPackage(project: javascript.NodeProject): void {
149
134
  project.package.addField("private", true);
150
135
  }
151
136
 
152
- /**
153
- * Stamp `repository` on a package's manifest so npm provenance can validate the
154
- * published source (without it, publish fails with E422). A child also carries the
155
- * monorepo `directory` subpath (its path relative to the root); the root omits it.
156
- * No-op when no git remote is detected and no `repository` override was supplied.
157
- * The URL is auto-detected + cached by {@link projectUtils.repositoryUrl} (gh, then
158
- * a normalized git remote), in npm's `git+https://.../repo.git` form.
159
- */
160
- function applyRepository(project: javascript.NodeProject, override?: string): void {
161
- const workspaceRoot = resolve(project.root.outdir);
162
- const url =
163
- override && override.length ? override : projectUtils.repositoryUrl(workspaceRoot, "npm");
164
- if (!url) return;
165
- const directory = toPosix(relative(workspaceRoot, resolve(project.outdir)));
166
- project.package.addField("repository", {
167
- type: "git",
168
- url,
169
- ...(directory ? { directory } : {}),
170
- });
137
+ function repositoryOptions(
138
+ options: DBXToolsJavaScriptProjectOptions,
139
+ ): Pick<javascript.NodeProjectOptions, "repository" | "repositoryDirectory"> {
140
+ const workspaceRoot = resolve(options.parent?.root.outdir ?? options.outdir ?? process.cwd());
141
+ const repository = options.repository ?? projectUtils.repositoryUrl(workspaceRoot, "npm");
142
+ const projectRoot = options.parent
143
+ ? resolve(options.parent.outdir, options.outdir ?? ".")
144
+ : resolve(options.outdir ?? process.cwd());
145
+ const directory = options.parent ? toPosix(relative(workspaceRoot, projectRoot)) : undefined;
146
+ return {
147
+ ...(repository ? { repository } : {}),
148
+ ...(directory ? { repositoryDirectory: directory } : {}),
149
+ };
171
150
  }
172
151
 
173
152
  /** Inherit a parent's package manager, else bun. */
@@ -202,16 +181,6 @@ export function applyIncludes(pkg: javascript.NodeProject, ...includes: string[]
202
181
  for (const include of includes) pkg.tsconfig?.addInclude(include);
203
182
  }
204
183
 
205
- /** Apply a tag's `tasks` through projen's task system. */
206
- export function applyTasks(pkg: javascript.NodeProject, tasks?: Record<string, TaskOptions>): void {
207
- if (!tasks) return;
208
- for (const [name, options] of Object.entries(tasks)) {
209
- const owned = name === "build" ? pkg.compileTask : pkg.tasks.tryFind(name);
210
- if (owned) owned.reset(options.exec, options);
211
- else pkg.addTask(name, options);
212
- }
213
- }
214
-
215
184
  /**
216
185
  * Set a package's `exports` subpath map (whole-field replace, so a later mixin
217
186
  * that supplies a fuller surface wins over a tag default). Lets the `cli` / `ui`
@@ -313,8 +282,9 @@ export function addPackageFiles(pkg: javascript.NodeProject, ...entries: string[
313
282
  }
314
283
 
315
284
  /**
316
- * The `./<name>` -> `./src/<name>.ts` subpath map for a package's top-level `src`
317
- * modules, skipping `_`-prefixed private modules and declaration files.
285
+ * The automatic subpath map for a package's public top-level TypeScript and CSS
286
+ * files plus directory entrypoints, skipping `_`-prefixed private modules and
287
+ * declaration files.
318
288
  *
319
289
  * This widens no API surface: the root `index.ts` barrel already re-exports every
320
290
  * non-`_` module, so those names are public through `.` either way - the subpaths
@@ -326,9 +296,23 @@ export function srcModuleExports(pkg: javascript.NodeProject): Record<string, st
326
296
  if (!existsSync(srcDir)) return {};
327
297
 
328
298
  const exports: Record<string, string> = {};
329
- for (const file of readdirSync(srcDir).sort()) {
330
- if (file.startsWith("_") || !file.endsWith(".ts") || file.endsWith(".d.ts")) continue;
331
- exports[`./${file.slice(0, -".ts".length)}`] = `./src/${file}`;
299
+ for (const entry of readdirSync(srcDir, { withFileTypes: true }).sort((left, right) =>
300
+ left.name.localeCompare(right.name),
301
+ )) {
302
+ if (entry.name.startsWith("_")) continue;
303
+ if (entry.isFile() && /\.(?:ts|tsx)$/.test(entry.name) && !entry.name.endsWith(".d.ts")) {
304
+ exports[`./${entry.name.replace(/\.tsx?$/, "")}`] = `./src/${entry.name}`;
305
+ continue;
306
+ }
307
+ if (entry.isFile() && entry.name.endsWith(".css")) {
308
+ exports[`./${entry.name}`] = `./src/${entry.name}`;
309
+ continue;
310
+ }
311
+ if (!entry.isDirectory()) continue;
312
+ const index = ["index.ts", "index.tsx"].find((file) =>
313
+ existsSync(join(srcDir, entry.name, file)),
314
+ );
315
+ if (index) exports[`./${entry.name}`] = `./src/${entry.name}/${index}`;
332
316
  }
333
317
  return exports;
334
318
  }
@@ -405,6 +389,7 @@ function defaultProjectOptions(options: DBXToolsJavaScriptProjectOptions) {
405
389
  // phase installs with pnpm - so a deployed app keeps its catalog + build
406
390
  // allowances even though the local/CI manager is bun.
407
391
  packageManager: javascript.NodePackageManager.BUN,
392
+ bunVersion: BUN_VERSION,
408
393
  // Pinned rather than left to projen's "latest": this is the co-tested release
409
394
  // whose `NodePackage` renders bun's `trustedDependencies` natively. Under bun,
410
395
  // projen does NOT create the `pnpm-workspace.yaml` component itself (that call
@@ -412,7 +397,6 @@ function defaultProjectOptions(options: DBXToolsJavaScriptProjectOptions) {
412
397
  // PnpmWorkspaceState}). Floating would let an install cross that boundary
413
398
  // silently, so the co-tested version is stated here and bumped deliberately.
414
399
  projenVersion: PROJEN_VERSION,
415
- defaultReleaseBranch: "main",
416
400
  projenrcJs: false,
417
401
  // Every CHILD is a publishable package, so it needs
418
402
  // `publishConfig.access: public` - projen renders that from `npmAccess`
@@ -437,8 +421,6 @@ function defaultProjectOptions(options: DBXToolsJavaScriptProjectOptions) {
437
421
  jest: false,
438
422
  github: false,
439
423
  npmignoreEnabled: false,
440
- license: DBX_TOOLS_LICENSE,
441
- licensed: true,
442
424
  entrypoint: "",
443
425
  depsUpgrade: false,
444
426
  // Bins are declared explicitly via `p.package.addBin(...)`. projen's default
@@ -448,7 +430,6 @@ function defaultProjectOptions(options: DBXToolsJavaScriptProjectOptions) {
448
430
  autoDetectBin: false,
449
431
  peerDependencyOptions: { pinnedDevDependency: false },
450
432
  addPackageManagerToDevEngines: false,
451
- devDeps: ["@types/node@^24.6.0"],
452
433
  ...(isRoot
453
434
  ? {
454
435
  prettier: true,
@@ -461,13 +442,14 @@ function defaultProjectOptions(options: DBXToolsJavaScriptProjectOptions) {
461
442
  },
462
443
  }
463
444
  : {}),
445
+ ...repositoryOptions(options),
464
446
  ...options,
465
- buildWorkflow: false,
466
- release: false,
467
- githubOptions: {
468
- ...options.githubOptions,
469
- pullRequestLint: false,
447
+ buildWorkflowOptions: {
448
+ mutableBuild: false,
449
+ permissions: { contents: JobPermission.READ },
450
+ ...options.buildWorkflowOptions,
470
451
  },
452
+ release: false,
471
453
  ...copiedGitIgnoreOptions(options),
472
454
  };
473
455
  }
@@ -502,11 +484,14 @@ function defaultTypeScriptProjectOptions(options: DBXToolsTypeScriptProjectOptio
502
484
  return {
503
485
  ...base,
504
486
  sampleCode: false,
505
- entrypoint: undefined,
487
+ entrypoint: "index.ts",
488
+ entrypointTypes: "index.ts",
489
+ typescriptVersion: options.typescriptVersion ?? "^5.9.3",
490
+ projenrcTs: false,
506
491
  // ESLint is configured once on the ROOT (see initProject) and lints the whole
507
492
  // tree, so packages don't emit their own config. A caller can still override.
508
493
  eslint: false,
509
- devDeps: [...(base.devDeps ?? []), "typescript@^5.9.3", `@types/bun@${BUN_VERSION}`],
494
+ devDeps: [...(base.devDeps ?? [])],
510
495
  ...options,
511
496
  ...copiedGitIgnoreOptions(options),
512
497
  };
@@ -514,37 +499,12 @@ function defaultTypeScriptProjectOptions(options: DBXToolsTypeScriptProjectOptio
514
499
 
515
500
  // Pinned to match the subproject defaults so bun resolves one TypeScript and
516
501
  // one runtime-compatible set of Bun globals across the workspace.
517
- const DEV_DEPS_ROOT: string[] = ["typescript@^5.9.3", `@types/bun@${BUN_VERSION}`];
518
- const NATIVE_RELEASE_OPTIONS = [
519
- "jsiiReleaseVersion",
520
- "majorVersion",
521
- "minMajorVersion",
522
- "npmDistTag",
523
- "prerelease",
524
- "publishDryRun",
525
- "publishTasks",
526
- "releasableCommits",
527
- "release",
528
- "releaseBranches",
529
- "releaseEnvironment",
530
- "releaseEveryCommit",
531
- "releaseFailureIssue",
532
- "releaseFailureIssueLabel",
533
- "releaseToNpm",
534
- "releaseTrigger",
535
- "releaseWorkflowName",
536
- "releaseWorkflowSetupSteps",
537
- "versionrcOptions",
538
- ] as const;
539
-
502
+ const DEV_DEPS_ROOT: string[] = [
503
+ "typescript@^5.9.3",
504
+ `@types/bun@${BUN_VERSION}`,
505
+ "@types/node@^24.6.0",
506
+ ];
540
507
  function validateReleaseOptions(options: DBXToolsJavaScriptProjectOptions): void {
541
- for (const key of NATIVE_RELEASE_OPTIONS) {
542
- if ((options as Record<string, unknown>)[key] !== undefined) {
543
- throw new Error(
544
- `${key} is a native Projen release option; use dbx-tools release options instead`,
545
- );
546
- }
547
- }
548
508
  if (
549
509
  options.releaseMode === "disabled" &&
550
510
  (options.releaseDocs !== undefined || options.nodeRelease !== undefined)
@@ -556,14 +516,6 @@ function validateReleaseOptions(options: DBXToolsJavaScriptProjectOptions): void
556
516
  /** Options for {@link DBXToolsNodeProject} (the monorepo root). */
557
517
  export type DBXToolsReleaseMode = "dbx-tools" | "disabled";
558
518
 
559
- /** Optional semantic pull request title policy for the generated build workflow. */
560
- export interface PullRequestTitlePolicyOptions {
561
- /** Allowed semantic title types. */
562
- readonly types: readonly string[];
563
- /** Require a semantic title scope. Defaults to `false`. */
564
- readonly requireScope?: boolean;
565
- }
566
-
567
519
  type SupportedWorkflowOptions = Pick<
568
520
  ReleaseProjectOptions,
569
521
  "postBuildSteps" | "workflowContainerImage" | "workflowRunsOn" | "workflowRunsOnGroup"
@@ -586,12 +538,6 @@ export type DBXToolsJavaScriptProjectOptions = CommonProjectOptions &
586
538
  * Only a ROOT scans. Defaults to {@link DEFAULT_PACKAGE_ROOTS}.
587
539
  */
588
540
  readonly packageRoots?: readonly string[];
589
- /**
590
- * Descriptions for published packages, keyed by repository-relative package
591
- * directory. When configured, synthesis rejects every public JavaScript
592
- * package whose final manifest has no non-empty description.
593
- */
594
- readonly packageDescriptions?: Readonly<Record<string, string>>;
595
541
  /**
596
542
  * Leading path segment(s) dropped from a discovered package's relative path
597
543
  * before its npm name is derived, so a tier folder doesn't become a name
@@ -602,6 +548,8 @@ export type DBXToolsJavaScriptProjectOptions = CommonProjectOptions &
602
548
  * disable. Defaults to `"node"`.
603
549
  */
604
550
  readonly omitRelativePrefix?: OneOrMany<string>;
551
+ /** Resolve a discovered package name before its project is constructed. */
552
+ readonly resolvePackageName?: (pkg: DiscoveredPackage, defaultPackageName: string) => string;
605
553
  /**
606
554
  * Maps a path token / relPath / glob to tag(s), unioned into a package's
607
555
  * path-derived tags. Defaults to an identity map over the known tag names; a
@@ -629,14 +577,8 @@ export type DBXToolsJavaScriptProjectOptions = CommonProjectOptions &
629
577
  readonly nodeRelease?: boolean;
630
578
  /** Unified dbx-tools release workflow, or no release surface. Defaults to `dbx-tools`. */
631
579
  readonly releaseMode?: DBXToolsReleaseMode;
632
- /** Explicit stable release-unit grouping rules. */
633
- readonly releaseUnits?: readonly ReleaseUnitRule[];
634
- /** Publishable workspace members synthesized outside the attached project tree. */
635
- readonly externalReleaseProjects?: readonly ExternalReleaseProjectRegistration[];
636
580
  /** Prefix for generated release tags. Defaults to `v`. */
637
581
  readonly releaseTagPrefix?: string;
638
- /** Semantic PR title validation policy. Omitted or `false` disables title validation. */
639
- readonly pullRequestTitlePolicy?: false | PullRequestTitlePolicyOptions;
640
582
  /** Repository output paths excluded from generated workflow dependency-cache hashing. */
641
583
  readonly workflowCacheIgnorePaths?: readonly string[];
642
584
  /**
@@ -663,10 +605,17 @@ export type DBXToolsTypeScriptProjectOptions = Partial<
663
605
  keyof ReleaseProjectOptions | "release" | "releaseToNpm"
664
606
  >
665
607
  > &
666
- DBXToolsJavaScriptProjectOptions & {
667
- /** Emit the projen-owned bun app scaffolding (`bunfig.toml`/`dev.ts`/`build.ts`). */
668
- readonly bunApp?: boolean;
669
- };
608
+ DBXToolsJavaScriptProjectOptions;
609
+
610
+ const initializingWorkflowCachePaths = new Map<string, readonly string[]>();
611
+
612
+ function configuredOutdir(
613
+ options: Pick<DBXToolsJavaScriptProjectOptions, "parent" | "outdir">,
614
+ ): string {
615
+ return options.parent
616
+ ? resolve(options.parent.outdir, options.outdir ?? ".")
617
+ : resolve(options.outdir ?? process.cwd());
618
+ }
670
619
 
671
620
  /**
672
621
  * A monorepo root. Scans `packageRoots` and appends a
@@ -682,11 +631,9 @@ export class DBXToolsNodeProject
682
631
  readonly dbxToolsConfig: DBXToolsConfig;
683
632
  pnpmWorkspace?: PnpmWorkspaceState;
684
633
  rootTsconfig?: DBXToolsRootTsconfig;
685
- vsCode?: DBXToolsVsCode;
686
634
  readonly extraWorkspaceMembers: readonly string[];
687
635
  readonly releaseBranch: string;
688
636
  readonly workflowCacheIgnorePaths: readonly string[];
689
- readonly releaseCatalog: DBXToolsReleaseCatalog;
690
637
  private readonly rootInstallOnly: boolean;
691
638
 
692
639
  constructor(options: DBXToolsJavaScriptProjectOptions = {}) {
@@ -699,6 +646,8 @@ export class DBXToolsNodeProject
699
646
  // into `package.json` (`workspaces`/`catalog`) for bun to read. The
700
647
  // `pnpm-workspace.yaml` is still emitted for the Databricks Apps pnpm install.
701
648
  const pnpmWorkspace = new PnpmWorkspaceState(options);
649
+ const outdir = configuredOutdir(options);
650
+ initializingWorkflowCachePaths.set(outdir, options.workflowCacheIgnorePaths ?? []);
702
651
  super({
703
652
  ...defaultProjectOptions(options),
704
653
  pnpmOptions: {
@@ -713,19 +662,14 @@ export class DBXToolsNodeProject
713
662
  // component, but the file is still required by the Databricks Apps platform
714
663
  // (its build phase installs with pnpm and reads catalog + `allowBuilds`).
715
664
  pnpmWorkspace.attachWorkspaceFile(this);
716
- this.releaseCatalog = new DBXToolsReleaseCatalog(this, {
717
- units: options.releaseUnits,
718
- externalProjects: options.externalReleaseProjects,
719
- });
720
- registerJavaScriptReleaseProject(this);
721
- this.package.addField("version", () => this.releaseCatalog.versionFor(this));
665
+ this.package.addVersion(readWorkspaceVersion(this.outdir));
722
666
  this.scope = scope;
723
667
  this.extraWorkspaceMembers = options.extraWorkspaceMembers ?? [];
724
668
  this.releaseBranch = options.defaultReleaseBranch ?? "main";
725
669
  this.workflowCacheIgnorePaths = options.workflowCacheIgnorePaths ?? [];
670
+ initializingWorkflowCachePaths.delete(outdir);
726
671
  this.rootInstallOnly = options.rootInstallOnly !== false;
727
672
  this.dbxToolsConfig = new DBXToolsConfig(this, options);
728
- configureBuildWorkflow(this, options);
729
673
  initProject(this, options);
730
674
  }
731
675
 
@@ -734,9 +678,16 @@ export class DBXToolsNodeProject
734
678
  if (this.parent) return steps;
735
679
  return steps.flatMap((step) => {
736
680
  if (step.uses?.startsWith("oven-sh/setup-bun@")) {
737
- return [...bunCacheRestoreSteps(this, { ignorePaths: this.workflowCacheIgnorePaths })];
681
+ return [
682
+ ...bunCacheRestoreSteps(this, {
683
+ ignorePaths:
684
+ this.workflowCacheIgnorePaths ??
685
+ initializingWorkflowCachePaths.get(resolve(this.outdir)) ??
686
+ [],
687
+ }),
688
+ ];
738
689
  }
739
- if (step.run === "bun install") {
690
+ if (step.run?.startsWith("bun install")) {
740
691
  return [
741
692
  step,
742
693
  bunCacheSaveStep({
@@ -799,11 +750,9 @@ export class DBXToolsTypeScriptProject
799
750
  readonly dbxToolsConfig: DBXToolsConfig;
800
751
  pnpmWorkspace?: PnpmWorkspaceState;
801
752
  rootTsconfig?: DBXToolsRootTsconfig;
802
- vsCode?: DBXToolsVsCode;
803
753
  readonly extraWorkspaceMembers: readonly string[];
804
754
  readonly releaseBranch: string;
805
755
  readonly workflowCacheIgnorePaths: readonly string[];
806
- readonly releaseCatalog: DBXToolsReleaseCatalog;
807
756
  private readonly rootInstallOnly: boolean;
808
757
 
809
758
  constructor(options: DBXToolsTypeScriptProjectOptions) {
@@ -846,14 +795,6 @@ export class DBXToolsTypeScriptProject
846
795
  this.releaseBranch = options.defaultReleaseBranch ?? "main";
847
796
  this.workflowCacheIgnorePaths = options.workflowCacheIgnorePaths ?? [];
848
797
  this.rootInstallOnly = options.rootInstallOnly !== false;
849
- this.releaseCatalog =
850
- parent &&
851
- (parent instanceof DBXToolsNodeProject || parent instanceof DBXToolsTypeScriptProject)
852
- ? parent.releaseCatalog
853
- : new DBXToolsReleaseCatalog(this, {
854
- units: options.releaseUnits,
855
- externalProjects: options.externalReleaseProjects,
856
- });
857
798
  // Pairs with `jsx` in SHARED_COMPILER_OPTIONS: projen's default `include` is
858
799
  // `src/**/*.ts` only, which silently omits a `.tsx` file from the program
859
800
  // instead of failing, so authoring a React component would otherwise need
@@ -863,25 +804,18 @@ export class DBXToolsTypeScriptProject
863
804
  // Source-first entry: point the package at its package-ROOT `index.ts` barrel
864
805
  // so packages resolve each other's `@scope/pkg` imports to source.
865
806
  this.package.addField("type", "module");
866
- this.package.addField("main", "index.ts");
867
- this.package.addField("types", "index.ts");
868
807
  this.package.addField("exports", {
869
808
  ".": "./index.ts",
809
+ ...srcModuleExports(this),
870
810
  "./package.json": "./package.json",
871
811
  });
872
- this.package.addField("version", () => this.releaseCatalog.versionFor(this));
873
- registerJavaScriptReleaseProject(this);
812
+ this.package.addVersion(readWorkspaceVersion(this.root.outdir));
874
813
  addPackageFiles(this, "index.ts", "src");
814
+ if (existsSync(join(this.outdir, "exports.ts"))) addPackageFiles(this, "exports.ts");
875
815
  // `bun test` intercepts `node:test` (the suites keep using node:test) and
876
816
  // runs it with bun's own fast runner. The native no-tests option is portable
877
817
  // across Windows and Unix and lets packages without tests remain a no-op.
878
818
  this.testTask.exec("bun test test --pass-with-no-tests");
879
- if (options.bunApp ?? false) {
880
- new BunfigFile(this);
881
- new BunDevServerFile(this);
882
- new BunBuildFile(this);
883
- }
884
- configureBuildWorkflow(this, options);
885
819
  initProject(this, options);
886
820
  }
887
821
 
@@ -893,88 +827,6 @@ export class DBXToolsTypeScriptProject
893
827
  }
894
828
  }
895
829
 
896
- function registerJavaScriptReleaseProject(project: DBXToolsJavaScriptProject): void {
897
- const projectPath = toPosix(relative(project.root.outdir, project.outdir));
898
- project.releaseCatalog.registerProject(project, {
899
- language: "javascript",
900
- identity: () => String(project.package.manifest.name ?? project.name),
901
- publish: () => project.package.manifest.private !== true,
902
- sourcePaths: ["src", "bin", "tasks"].map((path) =>
903
- projectPath ? `${projectPath}/${path}` : path,
904
- ),
905
- dependencies: () =>
906
- project.deps.all.map<ReleaseDependencyInput>((dependency) => ({
907
- target: dependency.name,
908
- kind:
909
- dependency.type === "devenv" || dependency.type === "override"
910
- ? "development"
911
- : dependency.type,
912
- ...(dependency.version ? { requirement: dependency.version } : {}),
913
- })),
914
- });
915
- }
916
-
917
- function configureBuildWorkflow(
918
- project: DBXToolsNodeProject | DBXToolsTypeScriptProject,
919
- options: DBXToolsJavaScriptProjectOptions,
920
- ): void {
921
- if (project.parent || !options.buildWorkflow || !project.github) return;
922
- const validation = project.addTask("pr:validate", {
923
- description: "Validate generated files and TypeScript packages",
924
- });
925
- validation.exec("bunx projen default");
926
- validation.exec("bun run compile");
927
- const configured = { ...options.buildWorkflowOptions };
928
- const compatibility = nodeWorkflowCompatibility(project);
929
- const configuredRunner = configured.runsOn !== undefined || configured.runsOnGroup !== undefined;
930
- const workflow = new BuildWorkflow(project, {
931
- buildTask: validation,
932
- artifactsDirectory: project.artifactsDirectory,
933
- containerImage: options.workflowContainerImage,
934
- gitIdentity: options.workflowGitIdentity,
935
- permissions: { idToken: compatibility.determineIdTokenPermissions(options) },
936
- ...configured,
937
- preBuildSteps: [
938
- ...project.renderWorkflowSetup({
939
- installStepConfiguration: {
940
- workingDirectory: compatibility.determineInstallWorkingDirectory(),
941
- },
942
- mutable: configured.mutableInstall ?? configured.mutableBuild ?? true,
943
- }),
944
- ...(configured.preBuildSteps ?? []),
945
- ],
946
- postBuildSteps: [...(options.postBuildSteps ?? [])],
947
- runsOn: configuredRunner ? configured.runsOn : options.workflowRunsOn,
948
- runsOnGroup: configuredRunner ? configured.runsOnGroup : options.workflowRunsOnGroup,
949
- });
950
- workflow.addPostBuildSteps(...compatibility.renderUploadCoverageJobStep(options));
951
- compatibility.buildWorkflow = workflow;
952
-
953
- if ((options.autoMerge ?? true) && project.github.mergify) {
954
- const autoMerge = new AutoMerge(project.github, options.autoMergeOptions);
955
- autoMerge.addConditionsLater({
956
- render: () => workflow.buildJobIds.map((id) => `status-success=${id}`),
957
- });
958
- compatibility.autoMerge = autoMerge;
959
- }
960
- }
961
-
962
- interface NodeWorkflowCompatibility {
963
- autoMerge?: AutoMerge;
964
- buildWorkflow?: BuildWorkflow;
965
- determineIdTokenPermissions(options: DBXToolsJavaScriptProjectOptions): JobPermission | undefined;
966
- determineInstallWorkingDirectory(): string | undefined;
967
- renderUploadCoverageJobStep(options: DBXToolsJavaScriptProjectOptions): JobStep[];
968
- }
969
-
970
- /**
971
- * Access the narrow NodeProject workflow hooks that have no public equivalent.
972
- * BuildWorkflow itself is created exclusively through its public constructor.
973
- */
974
- function nodeWorkflowCompatibility(project: javascript.NodeProject): NodeWorkflowCompatibility {
975
- return project as unknown as NodeWorkflowCompatibility;
976
- }
977
-
978
830
  function prepareRootSynthesis(
979
831
  project: DBXToolsNodeProject | DBXToolsTypeScriptProject,
980
832
  rootInstallOnly: boolean,
@@ -987,22 +839,17 @@ function resolveRootWorkspace(
987
839
  extraWorkspaceMembers: readonly string[],
988
840
  ): void {
989
841
  if (project.parent) return;
842
+ const version = readWorkspaceVersion(project.outdir);
990
843
  for (const member of extraWorkspaceMembers) {
991
- syncWorkspaceManifestVersion(
992
- join(project.outdir, member, "package.json"),
993
- project.releaseCatalog.versionForPath(member),
994
- );
844
+ syncWorkspaceManifestVersion(join(project.outdir, member, "package.json"), version);
995
845
  }
996
846
  project.pnpmWorkspace?.resolveMembers(project, extraWorkspaceMembers);
997
847
  }
998
848
 
999
849
  /**
1000
- * Regenerates the repo's generated source after synth: first the codegen
1001
- * modules (ts-to-zod schemas from each `codegen`-declaring package's upstream
1002
- * `.d.ts`), then every package's root `index.ts` barrel - so a freshly
1003
- * generated module is namespaced into its barrel in the same pass. This is the
1004
- * "generate on resynth" path for plain `projen`; codegen inputs (SDK `.d.ts`)
1005
- * change rarely, so a synth-time regen is enough and there's no separate watch.
850
+ * Regenerates the repo's generated source after synth: codegen modules, Python
851
+ * Node bindings, then package barrels. Python binding generation owns cleanup,
852
+ * so removing a configured package or module cannot leave stale files behind.
1006
853
  *
1007
854
  * projen only runs `postSynthesize` when `PROJEN_DISABLE_POST` is unset, so this
1008
855
  * is skipped during the watcher's fast `runSynth` (which sets it); there barrels
@@ -1010,10 +857,36 @@ function resolveRootWorkspace(
1010
857
  * install, so codegen's `node_modules/...` inputs resolve.
1011
858
  */
1012
859
  class GeneratedSource extends Component {
860
+ public override preSynthesize(): void {
861
+ const root = resolve(this.project.outdir);
862
+ for (const subproject of this.project.subprojects) {
863
+ if (!(subproject instanceof javascript.NodeProject)) continue;
864
+ const codegen = subproject.package.manifest.codegen as { inputs?: string[] } | undefined;
865
+ const packagePath = toPosix(relative(root, subproject.outdir));
866
+ const modules = codegenModulePaths(codegen?.inputs ?? []);
867
+ for (const module of modules) {
868
+ this.project.annotateGenerated(`/${packagePath}/${module}`);
869
+ }
870
+ if (modules.length === 0) continue;
871
+ const current = (subproject.package.manifest.exports ?? {}) as Record<string, unknown>;
872
+ const sourceExports = Object.fromEntries(
873
+ modules.map((module) => [`./${module.slice("src/".length, -".ts".length)}`, `./${module}`]),
874
+ );
875
+ subproject.package.addField("exports", {
876
+ ...Object.fromEntries(
877
+ Object.entries(current).filter(([subpath]) => subpath !== "./package.json"),
878
+ ),
879
+ ...sourceExports,
880
+ ...(current["./package.json"] ? { "./package.json": current["./package.json"] } : {}),
881
+ });
882
+ }
883
+ }
884
+
1013
885
  public override postSynthesize(): void {
1014
886
  const projectRoot = this.project.outdir;
1015
887
  const includeRoot = this.project instanceof DBXToolsTypeScriptProject;
1016
888
  generateCodegen(projectRoot, { includeRoot });
889
+ generatePythonNodeBindings(projectRoot);
1017
890
  generateBarrels({ projectRoot, includeRoot });
1018
891
  }
1019
892
  }
@@ -1042,7 +915,7 @@ class WorkspaceValidationTasks extends Component {
1042
915
  if (project.subprojects.length === 0 && project.extraWorkspaceMembers.length === 0) {
1043
916
  return;
1044
917
  }
1045
- project.compileTask.exec(taskScript(project, "compile-workspace.ts"));
918
+ project.compileTask.execArgs(taskCommand("compile-workspace.ts"));
1046
919
  project.testTask.exec("bun run --filter '*' test");
1047
920
  }
1048
921
  }
@@ -1055,35 +928,7 @@ class WorkspaceValidationTasks extends Component {
1055
928
  * off) do not gain new files.
1056
929
  */
1057
930
  class WorkflowDefaults extends Component {
1058
- constructor(
1059
- project: javascript.NodeProject,
1060
- private readonly pullRequestTitlePolicy: false | PullRequestTitlePolicyOptions | undefined,
1061
- ) {
1062
- super(project);
1063
- }
1064
-
1065
931
  public override preSynthesize(): void {
1066
- const project = this.project as javascript.NodeProject;
1067
- const workflow = project.buildWorkflow?.workflow;
1068
- if (workflow && this.pullRequestTitlePolicy) {
1069
- workflow.addJob("pr-title", {
1070
- name: "Validate PR title",
1071
- runsOn: ["ubuntu-latest"],
1072
- permissions: { pullRequests: JobPermission.READ },
1073
- if: "${{ github.event_name == 'pull_request' && github.event.action != 'closed' }}",
1074
- steps: [
1075
- {
1076
- name: "Validate semantic title",
1077
- uses: "amannn/action-semantic-pull-request@v6",
1078
- env: { GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" },
1079
- with: {
1080
- types: this.pullRequestTitlePolicy.types.join("\n"),
1081
- requireScope: this.pullRequestTitlePolicy.requireScope ?? false,
1082
- },
1083
- },
1084
- ],
1085
- });
1086
- }
1087
932
  const build = this.project.tryFindObjectFile(".github/workflows/build.yml");
1088
933
  build?.addOverride("on.pull_request.types", ["opened", "synchronize", "reopened", "closed"]);
1089
934
  build?.addOverride(
@@ -1261,70 +1106,19 @@ function resolveTags(p: DiscoveredPackage, tagPaths: Record<string, string[]>):
1261
1106
 
1262
1107
  /** Register the native projen tasks on the monorepo root. */
1263
1108
  function registerRootTasks(project: javascript.NodeProject): void {
1264
- applyTasks(project, {
1265
- barrels: { exec: taskScript(project, "barrels.ts") },
1266
- openapi: { exec: taskScript(project, "openapi.ts") },
1267
- clean: { exec: taskScript(project, "clean.ts"), receiveArgs: true },
1268
- // `receiveArgs` forwards `--watch`, so `bun run sync -- --watch` syncs once
1269
- // then starts the single node-path watcher loop.
1270
- sync: { exec: taskScript(project, "sync.ts"), receiveArgs: true },
1109
+ project.addTask("barrels", { execArgs: taskCommand("barrels.ts") });
1110
+ project.addTask("openapi", { execArgs: taskCommand("openapi.ts") });
1111
+ project.addTask("clean", { execArgs: taskCommand("clean.ts"), receiveArgs: true });
1112
+ project.addTask("sync", {
1113
+ execArgs: taskCommand("sync.ts"),
1114
+ receiveArgs: true,
1271
1115
  });
1272
1116
  }
1273
1117
 
1274
- function descendantJavaScriptProjects(
1275
- parent: Project,
1276
- ): Array<DBXToolsNodeProject | DBXToolsTypeScriptProject> {
1277
- return parent.subprojects.flatMap((subproject) => [
1278
- ...(subproject instanceof DBXToolsNodeProject || subproject instanceof DBXToolsTypeScriptProject
1279
- ? [subproject]
1280
- : []),
1281
- ...descendantJavaScriptProjects(subproject),
1282
- ]);
1283
- }
1284
-
1285
- class PublishedPackageDescriptionValidation extends Component {
1286
- constructor(
1287
- project: DBXToolsNodeProject | DBXToolsTypeScriptProject,
1288
- private readonly configuredDescriptions: Readonly<Record<string, string>>,
1289
- ) {
1290
- super(project);
1291
- }
1292
-
1293
- public override preSynthesize(): void {
1294
- const root = this.project as DBXToolsNodeProject | DBXToolsTypeScriptProject;
1295
- const packages = new Map(
1296
- descendantJavaScriptProjects(root).map((pkg) => [
1297
- toPosix(relative(root.outdir, pkg.outdir)),
1298
- pkg,
1299
- ]),
1300
- );
1301
- for (const packagePath of Object.keys(this.configuredDescriptions)) {
1302
- if (!packages.has(packagePath)) {
1303
- throw new Error(`Package description targets unknown package ${packagePath}`);
1304
- }
1305
- }
1306
- for (const [packagePath, pkg] of packages) {
1307
- if (pkg.package.manifest.private === true) continue;
1308
- const description = pkg.package.manifest.description;
1309
- if (typeof description !== "string" || !description.trim()) {
1310
- throw new Error(`Published package ${packagePath} requires a non-empty description`);
1311
- }
1312
- }
1313
- }
1314
- }
1315
-
1316
- /**
1317
- * `bun node_modules/@dbx-tools/projen/tasks/<script>` command for a projen task.
1318
- *
1319
- * Use the stable package symlink, never `require.resolve()`'s physical store
1320
- * path. A later install can change the peer-hash directory while leaving the
1321
- * package symlink valid; persisting the physical path made every generated task
1322
- * fail with ERR_MODULE_NOT_FOUND after such an update. bun runs the `.ts`
1323
- * directly (no tsx, no build step).
1324
- */
1325
- export function taskScript(_project: Project, script: string, args = ""): string {
1118
+ /** Stable argv for a TypeScript task shipped by `@dbx-tools/projen`. */
1119
+ export function taskCommand(script: string, ...args: string[]): string[] {
1326
1120
  const scriptPath = toPosix(join("node_modules", "@dbx-tools", "projen", "tasks", script));
1327
- return args ? `bun ${scriptPath} ${args}` : `bun ${scriptPath}`;
1121
+ return ["bun", scriptPath, ...args];
1328
1122
  }
1329
1123
 
1330
1124
  /**
@@ -1349,15 +1143,17 @@ function initProject(
1349
1143
  // `build` already compiles before its `package` phase. Keep the package's
1350
1144
  // `prepack` for standalone `bun publish`, but suppress lifecycle scripts in
1351
1145
  // this generated pack step so a direct child build does not compile twice.
1352
- const packageStep = project.packageTask.steps.find(
1146
+ const packageSteps = project.packageTask.steps;
1147
+ const packageStepIndex = packageSteps.findIndex(
1353
1148
  (step) => step.execArgs?.[0] === "npm" && step.execArgs[1] === "pack",
1354
1149
  );
1150
+ const packageStep = packageSteps[packageStepIndex];
1355
1151
  if (packageStep?.execArgs && !packageStep.execArgs.includes("--ignore-scripts")) {
1356
- packageStep.execArgs.push("--ignore-scripts");
1152
+ project.packageTask.updateStep(packageStepIndex, {
1153
+ ...packageStep,
1154
+ execArgs: [...packageStep.execArgs, "--ignore-scripts"],
1155
+ });
1357
1156
  }
1358
- // Stamp `repository` (with this package's `directory` subpath) so a published
1359
- // package passes npm provenance validation.
1360
- applyRepository(project, options.repository);
1361
1157
  // Only a ROOT configures the workspace; a child just swaps its default-laden
1362
1158
  // `.gitignore` for a fresh one that carries package-specific patterns only.
1363
1159
  swapChildGitignore(project, options);
@@ -1365,14 +1161,16 @@ function initProject(
1365
1161
  }
1366
1162
  project.package.file.readonly = false;
1367
1163
 
1368
- // NodeProject has no built-in TS projenrc support (unlike TypeScriptProject), so
1369
- // wire `.projenrc.ts` through a runner - this also populates the `default` task
1370
- // that `bunx projen` runs (and that the `sync` watcher invokes to re-synth).
1371
- // The runner choice is immaterial since the exec is reset to plain `bun` below;
1372
- // `nodejs()` avoids declaring a `ts-node`/`tsx` dependency.
1373
- new typescript.ProjenrcTs(project, {
1164
+ if (project instanceof DBXToolsNodeProject) {
1165
+ project.rootTsconfig = new DBXToolsRootTsconfig(project);
1166
+ }
1167
+ const projenrc = new typescript.ProjenrcTs(project, {
1374
1168
  runner: typescript.TypeScriptRunner.nodejs(),
1375
1169
  });
1170
+ const projenrcBase =
1171
+ project instanceof DBXToolsTypeScriptProject ? project.tsconfig : project.rootTsconfig?.config;
1172
+ if (projenrcBase) projenrc.tsconfig.addExtends(projenrcBase);
1173
+ projenrc.tsconfig.removeInclude("**/*.ts");
1376
1174
  // bun runs `.projenrc.ts` directly (native TS, no loader to register). Reset to
1377
1175
  // a plain `bun` exec rather than any wrapper: the default task is spawned by
1378
1176
  // nested installs/synths, and a wrapper that exported `npm_config_*` broke them.
@@ -1387,19 +1185,15 @@ function initProject(
1387
1185
  // always apply; the self-dep is added only when the engine is an installed pkg.
1388
1186
  const selfDep = engineSelfDependency(project);
1389
1187
  if (selfDep) project.addDevDeps(selfDep);
1390
- project.addDevDeps(...DEV_DEPS_ROOT, "concurrently@catalog:");
1188
+ project.addDevDeps(...DEV_DEPS_ROOT);
1391
1189
  configureRootPackage(project);
1392
- // Root carries the bare `repository` (no `directory`); children add their subpath.
1393
- applyRepository(project, options.repository);
1394
-
1395
1190
  const roots = options.packageRoots ?? DEFAULT_PACKAGE_ROOTS;
1396
1191
  project.dbxToolsConfig.packageRoots = [...roots];
1397
1192
  if (options.syncResynthPaths?.length) {
1398
1193
  project.dbxToolsConfig.syncResynthPaths = [...options.syncResynthPaths];
1399
1194
  }
1400
1195
 
1401
- project.rootTsconfig = new DBXToolsRootTsconfig(project);
1402
- project.vsCode = new DBXToolsVsCode(project);
1196
+ configureVsCode(project);
1403
1197
 
1404
1198
  registerRootTasks(project);
1405
1199
  if (options.prettier || project.prettier) {
@@ -1425,6 +1219,7 @@ function initProject(
1425
1219
  for (const root of roots) {
1426
1220
  project.annotateGenerated(`/${root}/**/index.ts`);
1427
1221
  project.annotateGenerated(`/${root}/openapi/**`);
1222
+ project.annotateGenerated(`/${root}/**/src/generated/**`);
1428
1223
  }
1429
1224
  for (const member of project.extraWorkspaceMembers) {
1430
1225
  project.annotateGenerated(`/${member}/index.ts`);
@@ -1536,23 +1331,15 @@ function initProject(
1536
1331
  found.dbxToolsConfig.tags.push(...tags);
1537
1332
  continue;
1538
1333
  }
1334
+ const defaultPackageName = packageNameFor(project.scope, p.relPath, omitPrefixes);
1539
1335
  new DBXToolsTypeScriptProject({
1540
1336
  parent: project,
1541
1337
  outdir: p.memberPath,
1542
- name: packageNameFor(project.scope, p.relPath, omitPrefixes),
1338
+ name: options.resolvePackageName?.(p, defaultPackageName) ?? defaultPackageName,
1543
1339
  tags,
1544
1340
  });
1545
1341
  }
1546
1342
 
1547
- if (options.packageDescriptions) {
1548
- for (const pkg of descendantJavaScriptProjects(project)) {
1549
- const packagePath = toPosix(relative(rootAbs, pkg.outdir));
1550
- const description = options.packageDescriptions[packagePath];
1551
- if (description !== undefined) pkg.package.addField("description", description.trim());
1552
- }
1553
- new PublishedPackageDescriptionValidation(project, options.packageDescriptions);
1554
- }
1555
-
1556
1343
  // The root project may itself carry tags (via a `""`/`"."` tag-path key).
1557
1344
  const rootTags = [...new Set([...(tagPaths[""] ?? []), ...(tagPaths["."] ?? [])])];
1558
1345
  if (rootTags.length) project.dbxToolsConfig.tags.push(...rootTags);
@@ -1565,10 +1352,10 @@ function initProject(
1565
1352
  }
1566
1353
 
1567
1354
  new WorkspaceValidationTasks(project);
1568
- new WorkflowDefaults(project, options.pullRequestTitlePolicy);
1355
+ new WorkflowDefaults(project);
1569
1356
  new PrettierIgnoreGenerated(project);
1570
-
1571
1357
  new GeneratedSource(project);
1358
+
1572
1359
  // Version mutation, reviewed release preparation, and public publication are
1573
1360
  // separate surfaces owned by one release component.
1574
1361
  if (options.releaseMode !== "disabled") {
@@ -1659,7 +1446,7 @@ function preSynthesizeProject(project: javascript.NodeProject): void {
1659
1446
  if (p.tryRemoveFile(path)) {
1660
1447
  const rootPath = resolve(p.outdir, path);
1661
1448
  if (existsSync(rootPath)) {
1662
- console.log(`Removed ${rootPath} from ${p.name}`);
1449
+ p.logger.info(`Removed ${rootPath} from ${p.name}`);
1663
1450
  }
1664
1451
  }
1665
1452
  }