@dbx-tools/projen 0.6.223 → 0.6.225
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/README.md +55 -8
- package/index.ts +7 -4
- package/package.json +5 -5
- package/src/barrels.ts +10 -4
- package/src/bun-workflow.ts +36 -17
- package/src/clean.ts +3 -3
- package/src/codegen.ts +16 -8
- package/src/packages.ts +14 -13
- package/src/project-js.ts +320 -148
- package/src/project-py.ts +8 -25
- package/src/project-rs.ts +100 -71
- package/src/release-dispatch.ts +10 -0
- package/src/release-github.ts +37 -0
- package/src/release.ts +57 -38
- package/src/tsconfig.ts +17 -17
- package/tasks/local-publish.ts +3 -3
- package/tasks/publish-npm.ts +75 -4
- package/tasks/publish-python.ts +13 -29
- package/tasks/publish-uniffi-local.ts +12 -9
- package/tasks/publish.ts +2 -2
- package/tasks/release-pr.ts +64 -10
- package/tasks/release-summary.ts +270 -0
- package/tasks/uniffi-python.d.ts +56 -0
- package/tasks/uniffi-python.js +160 -0
- package/tasks/uniffi-release.mjs +25 -49
- package/tasks/uniffi.ts +11 -45
package/README.md
CHANGED
|
@@ -37,6 +37,37 @@ project.synth();
|
|
|
37
37
|
Every `src`-bearing folder under the configured roots becomes a
|
|
38
38
|
`DBXToolsTypeScriptProject`. Folder path drives package name and runtime tags.
|
|
39
39
|
|
|
40
|
+
Use `DBXToolsTypeScriptProject` itself as the root when one package needs the
|
|
41
|
+
same Bun workspace, repository, task, and release defaults without a separate
|
|
42
|
+
non-compiling root. It preserves Projen's native compiling `tsconfig.json`
|
|
43
|
+
instead of creating a second owner. An explicit `outdir` is the workspace root
|
|
44
|
+
for naming, Git metadata, package discovery, codegen, and barrels even when the
|
|
45
|
+
calling process has a different current directory.
|
|
46
|
+
|
|
47
|
+
The unified dbx-tools release surface is enabled by default. Set
|
|
48
|
+
`releaseMode: "disabled"` to omit its workflow and bump/version/release tasks.
|
|
49
|
+
The inherited Projen `release` and `releaseTrigger` options are intentionally
|
|
50
|
+
not part of this engine's public options because they create a competing release
|
|
51
|
+
workflow.
|
|
52
|
+
|
|
53
|
+
Repository policy stays in the consuming `.projenrc.ts`:
|
|
54
|
+
|
|
55
|
+
- `releaseDocs` supplies repository-defined preparation and build steps plus
|
|
56
|
+
the Pages artifact path. The engine adds release checkout, Bun caching,
|
|
57
|
+
artifact upload, and deployment without naming a docs script or output tree.
|
|
58
|
+
- `releasePythonRoot` passes the actual Python package root to local release
|
|
59
|
+
preparation. Omit it when the workspace has no standard Python packages.
|
|
60
|
+
- `releaseSummary` controls optional AI release notes. It defaults to enabled
|
|
61
|
+
with Cursor, Codex, Claude fallback order; pass `false` to disable or provide
|
|
62
|
+
a `providers` array to choose the order/subset.
|
|
63
|
+
- `pullRequestTitlePolicy` configures semantic title types and scope policy.
|
|
64
|
+
Omit it or pass `false` to disable the title job.
|
|
65
|
+
- `workflowCacheIgnorePaths` excludes generated output trees that may contain
|
|
66
|
+
package manifests from the dependency-only Bun cache key.
|
|
67
|
+
- `extraWorkspaceMembers` declares self-synthesizing tooling packages outside
|
|
68
|
+
`packageRoots`. Their version, generated entrypoint, formatting, linting, and
|
|
69
|
+
workspace membership are derived from that declaration.
|
|
70
|
+
|
|
40
71
|
Dependency installation runs once from this root. The default-on
|
|
41
72
|
`ROOT_INSTALL_ONLY_MIXIN` clears child `install` / `install:ci` task steps during
|
|
42
73
|
root pre-synthesis, including packages attached after root construction. Set
|
|
@@ -53,9 +84,9 @@ new package membership.
|
|
|
53
84
|
without turning Python packages into JavaScript workspace projects. It generates
|
|
54
85
|
the root and member `pyproject.toml` files, standard `py:*` tasks, the VS Code
|
|
55
86
|
interpreter setting, and an optional manual PyPI trusted-publishing workflow.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
87
|
+
Projen's native `PyprojectTomlFile` owns generated TOML formatting. Temporary
|
|
88
|
+
publication stamping uses parsed TOML, changes versions and sibling
|
|
89
|
+
dependencies structurally, and restores the original files byte-for-byte.
|
|
59
90
|
|
|
60
91
|
```ts
|
|
61
92
|
import { project, projectPy } from "@dbx-tools/projen";
|
|
@@ -121,6 +152,10 @@ are library-local. Release wheels replace sibling Git requirements with matching
|
|
|
121
152
|
native-wheel versions, and dependent publishers wait for their dependencies.
|
|
122
153
|
Each crate builds its own `<crate>-uniffi-bindgen` executable so a workspace
|
|
123
154
|
build has no colliding binary outputs. Packaging runs that prebuilt executable.
|
|
155
|
+
Cargo manifests, target config, and UniFFI config are generated from structured
|
|
156
|
+
Projen `TomlFile` objects. Local and release Python generation share one
|
|
157
|
+
dependency-free helper for generator arguments, target-specific executable
|
|
158
|
+
names, generated headers, empty `__init__.py`, and native-library placement.
|
|
124
159
|
|
|
125
160
|
`sync --watch` runs a focused Rust watcher beside the OpenAPI watcher. Changes
|
|
126
161
|
inside an existing UniFFI crate regenerate that crate and its dependent bindings
|
|
@@ -409,7 +444,17 @@ it. `--message` sets the source commit message. The task never merges
|
|
|
409
444
|
the PR unless `--approve` is passed; that option merges the release branch
|
|
410
445
|
directly through GitHub's merge API so no PR checks are created. A repository
|
|
411
446
|
that blocks direct merges falls back to an immediate admin-merged PR. The task
|
|
412
|
-
then fast-forwards the still-active source branch to the release commit.
|
|
447
|
+
then fast-forwards the still-active source branch to the release commit.
|
|
448
|
+
|
|
449
|
+
After validation, release preparation optionally generates an immutable
|
|
450
|
+
`docs/releases/v<version>.md`. It tries the installed Cursor agent first, then
|
|
451
|
+
Codex, then Claude, all in non-interactive read-only modes against bounded Git
|
|
452
|
+
context. An unavailable, unauthenticated, failed, or empty provider falls
|
|
453
|
+
through to the next; if none works, release preparation continues without a
|
|
454
|
+
summary. The same file is included in the release PR and prepended to GitHub's
|
|
455
|
+
generated release notes, so repository and GitHub views share one source.
|
|
456
|
+
|
|
457
|
+
npm
|
|
413
458
|
uses `npm config get registry` and publishes to a local Verdaccio automatically.
|
|
414
459
|
Publishable JavaScript members compile once
|
|
415
460
|
from the root in parallel, then upload through a bounded pool without rerunning
|
|
@@ -425,10 +470,12 @@ Use `--local-registry false` or `--local-pypi false` to disable either local
|
|
|
425
470
|
publish. An explicit `--local-pypi http://localhost:3141/user/index/` overrides
|
|
426
471
|
auto-detection; `--python-root` defaults to `packages/py`.
|
|
427
472
|
|
|
428
|
-
The GitHub PR workflow runs
|
|
429
|
-
|
|
430
|
-
workspace
|
|
431
|
-
|
|
473
|
+
The GitHub PR workflow runs the explicit `pr:validate` task through Projen's
|
|
474
|
+
public `BuildWorkflow` `buildTask` option. That task runs synth plus the
|
|
475
|
+
workspace TypeScript compile rather than the complete root build. Release
|
|
476
|
+
preparation has already run Rust tests, workspace type-checking, and local
|
|
477
|
+
package preflight before opening the PR. JavaScript behavior tests remain an
|
|
478
|
+
explicit developer task.
|
|
432
479
|
|
|
433
480
|
The configured release branch publishes only when a reviewed PR changes
|
|
434
481
|
`VERSION`. Its workflow creates the annotated `v*` public release boundary.
|
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/projen";
|
|
6
|
-
export const PACKAGE_VERSION = "0.6.
|
|
6
|
+
export const PACKAGE_VERSION = "0.6.225";
|
|
7
7
|
export * as barrels from "./src/barrels.ts";
|
|
8
8
|
export * as bunApp from "./src/bun-app.ts";
|
|
9
9
|
export * as bunWorkflow from "./src/bun-workflow.ts";
|
|
@@ -25,6 +25,7 @@ export * as projectRs from "./src/project-rs.ts";
|
|
|
25
25
|
export * as publish from "./src/publish.ts";
|
|
26
26
|
export * as release from "./src/release.ts";
|
|
27
27
|
export * as releaseDispatch from "./src/release-dispatch.ts";
|
|
28
|
+
export * as releaseGithub from "./src/release-github.ts";
|
|
28
29
|
export * as scaffold from "./src/scaffold.ts";
|
|
29
30
|
export * as tags from "./src/tags.ts";
|
|
30
31
|
export * as tsconfig from "./src/tsconfig.ts";
|
|
@@ -47,15 +48,17 @@ export { PnpmWorkspaceState } from "./src/pnpm-workspace.ts";
|
|
|
47
48
|
export type { Catalog, AllowBuilds, DBXToolsPNPMWorkspaceOptions } from "./src/pnpm-workspace.ts";
|
|
48
49
|
export type { DBXToolsProjectLanguage, DBXToolsProjectOptions, DBXToolsProject, ApplyToProjectsOptions } from "./src/project.ts";
|
|
49
50
|
export { PackageIdentifier, PROJEN_VERSION, DBX_TOOLS_LICENSE, DBXToolsNodeProject, ROOT_INSTALL_ONLY_MIXIN, DBXToolsTypeScriptProject } from "./src/project-js.ts";
|
|
50
|
-
export type { DBXToolsJavaScriptProject, DBXToolsJavaScriptProjectOptions, DBXToolsTypeScriptProjectOptions } from "./src/project-js.ts";
|
|
51
|
+
export type { DBXToolsJavaScriptProject, DBXToolsReleaseMode, PullRequestTitlePolicyOptions, DBXToolsJavaScriptProjectOptions, DBXToolsTypeScriptProjectOptions } from "./src/project-js.ts";
|
|
51
52
|
export { DBXToolsPythonProject, DBXToolsPythonWorkspace } from "./src/project-py.ts";
|
|
52
53
|
export type { PythonRepositoryOptions, PythonPackageOptions, PythonTrustedPublisherOptions, DBXToolsPythonProjectOptions, PythonReleaseOptions, DBXToolsPythonWorkspaceOptions } from "./src/project-py.ts";
|
|
53
54
|
export { RustReleaseOs, RustReleaseCpu, UNIFFI_RELEASE_TARGETS, DBXToolsRustProject, DBXToolsRustWorkspace } from "./src/project-rs.ts";
|
|
54
55
|
export type { CargoDependencyOptions, CargoDependency, RustCliOptions, RustPackageOptions, DBXToolsRustWorkspaceOptions, RustReleasePlatform, UniFFIReleaseTarget, RustBindingMapping, RustWorkspaceMapping, RustReleaseBinaryAssetMapping, RustReleaseBinaryMapping } from "./src/project-rs.ts";
|
|
55
56
|
export { COMPILED_DIR, COMPILED_COMPILER_OPTIONS } from "./src/publish.ts";
|
|
56
57
|
export { DBXToolsRelease } from "./src/release.ts";
|
|
57
|
-
export type { ReleaseStage, ReleaseDocsOptions, DBXToolsReleaseOptions } from "./src/release.ts";
|
|
58
|
-
export { RELEASE_TAG, RELEASE_SHA, RELEASE_VERSION } from "./src/release-dispatch.ts";
|
|
58
|
+
export type { ReleaseStage, ReleaseDocsOptions, ReleaseSummaryOptions, DBXToolsReleaseOptions } from "./src/release.ts";
|
|
59
|
+
export { RELEASE_TAG, RELEASE_SHA, RELEASE_VERSION, RELEASE_SUMMARY_DIRECTORY, RELEASE_SUMMARY_PROVIDER_NAMES, RELEASE_SUMMARY_FILE } from "./src/release-dispatch.ts";
|
|
60
|
+
export type { ReleaseSummaryProviderName } from "./src/release-dispatch.ts";
|
|
61
|
+
export type { GithubRepositoryIdentity } from "./src/release-github.ts";
|
|
59
62
|
export { AGNOSTIC_COMPILER_OPTIONS, PACKAGE_TAG_MIXINS } from "./src/tags.ts";
|
|
60
63
|
export type { PackageTag } from "./src/tags.ts";
|
|
61
64
|
export { DBXToolsRootTsconfig } from "./src/tsconfig.ts";
|
package/package.json
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
"clobber": "projen clobber",
|
|
6
6
|
"compile": "projen compile",
|
|
7
7
|
"default": "projen default",
|
|
8
|
-
"demo": "projen demo",
|
|
9
8
|
"eject": "projen eject",
|
|
10
9
|
"package": "projen package",
|
|
11
10
|
"post-compile": "projen post-compile",
|
|
12
11
|
"post-upgrade": "projen post-upgrade",
|
|
13
12
|
"pre-compile": "projen pre-compile",
|
|
14
13
|
"test": "projen test",
|
|
14
|
+
"test:external-consumer": "projen test:external-consumer",
|
|
15
15
|
"upgrade": "projen upgrade",
|
|
16
16
|
"watch": "projen watch",
|
|
17
17
|
"projen": "projen"
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@clack/prompts": "^1.7.0",
|
|
28
|
-
"@dbx-tools/core": "0.6.
|
|
29
|
-
"@dbx-tools/path": "0.6.
|
|
30
|
-
"@dbx-tools/shared-core": "0.6.
|
|
28
|
+
"@dbx-tools/core": "0.6.225",
|
|
29
|
+
"@dbx-tools/path": "0.6.225",
|
|
30
|
+
"@dbx-tools/shared-core": "0.6.225",
|
|
31
31
|
"commander": "^15.0.0",
|
|
32
32
|
"concurrently": "^10.0.3",
|
|
33
33
|
"constructs": "^10.6.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"main": "index.ts",
|
|
49
49
|
"license": "Apache-2.0",
|
|
50
|
-
"version": "0.6.
|
|
50
|
+
"version": "0.6.225",
|
|
51
51
|
"types": "index.ts",
|
|
52
52
|
"type": "module",
|
|
53
53
|
"exports": {
|
package/src/barrels.ts
CHANGED
|
@@ -63,7 +63,7 @@ import { json, string } from "@dbx-tools/shared-core";
|
|
|
63
63
|
import isIdentifier from "is-identifier";
|
|
64
64
|
import { header, isGenerated, makeReadonly, makeWritable, type HeaderOpts } from "./generated.ts";
|
|
65
65
|
import { moduleExports, moduleStatements, type ModuleExport } from "./module-exports.ts";
|
|
66
|
-
import { isModuleFile, toPosix, recordedPackages,
|
|
66
|
+
import { isModuleFile, toPosix, recordedPackages, resolveRepoRoot } from "./packages.ts";
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* A `src`-relative posix path excluded from the root barrel:
|
|
@@ -555,8 +555,14 @@ function writeBarrel(file: string, content: string): void {
|
|
|
555
555
|
* order, so one unwritable barrel silently left the rest of the repo stale with
|
|
556
556
|
* nothing in the log to say which packages had been skipped.
|
|
557
557
|
*/
|
|
558
|
-
export function generateBarrels(
|
|
559
|
-
|
|
558
|
+
export function generateBarrels(
|
|
559
|
+
opts: { dirs?: string[]; includeRoot?: boolean; projectRoot?: string } = {},
|
|
560
|
+
): number {
|
|
561
|
+
const projectRoot = opts.projectRoot ?? resolveRepoRoot();
|
|
562
|
+
const dirs = opts.dirs ?? [
|
|
563
|
+
...(opts.includeRoot ? [projectRoot] : []),
|
|
564
|
+
...recordedPackages(projectRoot).map((p) => p.dir),
|
|
565
|
+
];
|
|
560
566
|
let total = 0;
|
|
561
567
|
const failures: { dir: string; err: unknown }[] = [];
|
|
562
568
|
for (const dir of dirs) {
|
|
@@ -567,7 +573,7 @@ export function generateBarrels(opts: { dirs?: string[] } = {}): number {
|
|
|
567
573
|
}
|
|
568
574
|
}
|
|
569
575
|
if (failures.length) {
|
|
570
|
-
const names = failures.map((f) => relative(
|
|
576
|
+
const names = failures.map((f) => relative(projectRoot, f.dir) || f.dir);
|
|
571
577
|
throw new AggregateError(
|
|
572
578
|
failures.map((f) => f.err),
|
|
573
579
|
`${string.pluralize(failures.length, "barrel")} failed: ${names.join(", ")}`,
|
package/src/bun-workflow.ts
CHANGED
|
@@ -3,15 +3,8 @@ import { TextFile, javascript } from "projen";
|
|
|
3
3
|
|
|
4
4
|
export const BUN_VERSION = "1.3.14";
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
import { createHash } from "node:crypto";
|
|
8
|
-
import { readdirSync, readFileSync } from "node:fs";
|
|
9
|
-
import { join } from "node:path";
|
|
10
|
-
|
|
11
|
-
const root = process.cwd();
|
|
12
|
-
const ignored = new Set([
|
|
6
|
+
const DEFAULT_CACHE_IGNORE_PATHS = [
|
|
13
7
|
".git",
|
|
14
|
-
".docs-build",
|
|
15
8
|
".venv",
|
|
16
9
|
".worktrees",
|
|
17
10
|
"coverage",
|
|
@@ -19,12 +12,24 @@ const ignored = new Set([
|
|
|
19
12
|
"lib",
|
|
20
13
|
"node_modules",
|
|
21
14
|
"target",
|
|
22
|
-
]
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
function cacheKeyScript(extraIgnorePaths: readonly string[]): string {
|
|
18
|
+
const ignorePaths = [...new Set(extraIgnorePaths)].sort();
|
|
19
|
+
return `#!/usr/bin/env node
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
22
|
+
import { join, sep } from "node:path";
|
|
23
|
+
|
|
24
|
+
const root = process.cwd();
|
|
25
|
+
const ignoredNames = new Set(${JSON.stringify(DEFAULT_CACHE_IGNORE_PATHS)});
|
|
26
|
+
const ignoredPaths = new Set(${JSON.stringify(ignorePaths)});
|
|
23
27
|
const manifests = [];
|
|
24
28
|
const walk = (directory) => {
|
|
25
29
|
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
26
|
-
if (ignored.has(entry.name)) continue;
|
|
27
30
|
const path = join(directory, entry.name);
|
|
31
|
+
const relativePath = path.slice(root.length + 1).split(sep).join("/");
|
|
32
|
+
if (ignoredNames.has(entry.name) || ignoredPaths.has(relativePath)) continue;
|
|
28
33
|
if (entry.isDirectory()) walk(path);
|
|
29
34
|
else if (entry.name === "package.json") manifests.push(path);
|
|
30
35
|
}
|
|
@@ -66,15 +71,27 @@ const dependencies = manifests
|
|
|
66
71
|
});
|
|
67
72
|
process.stdout.write(createHash("sha256").update(JSON.stringify(dependencies)).digest("hex"));
|
|
68
73
|
`;
|
|
74
|
+
}
|
|
69
75
|
|
|
70
|
-
const configured = new
|
|
76
|
+
const configured = new WeakMap<javascript.NodeProject, string>();
|
|
71
77
|
|
|
72
|
-
function ensureCacheKeyScript(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
function ensureCacheKeyScript(
|
|
79
|
+
project: javascript.NodeProject,
|
|
80
|
+
ignorePaths: readonly string[],
|
|
81
|
+
): void {
|
|
82
|
+
const root = project.root as javascript.NodeProject;
|
|
83
|
+
const key = JSON.stringify([...new Set(ignorePaths)].sort());
|
|
84
|
+
const existing = configured.get(root);
|
|
85
|
+
if (existing !== undefined) {
|
|
86
|
+
if (existing !== key) {
|
|
87
|
+
throw new Error("Bun workflow cache ignore paths must be consistent across one project");
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
new TextFile(root, ".projen/bun-cache-key.mjs", {
|
|
92
|
+
lines: cacheKeyScript(ignorePaths).trimEnd().split("\n"),
|
|
76
93
|
});
|
|
77
|
-
configured.
|
|
94
|
+
configured.set(root, key);
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
function stepCondition(condition: string | undefined, cacheMiss = false): string | undefined {
|
|
@@ -88,6 +105,8 @@ function stepCondition(condition: string | undefined, cacheMiss = false): string
|
|
|
88
105
|
export interface BunWorkflowCacheOptions {
|
|
89
106
|
readonly setupCondition?: string;
|
|
90
107
|
readonly condition?: string;
|
|
108
|
+
/** Repository-relative output paths excluded from dependency manifest hashing. */
|
|
109
|
+
readonly ignorePaths?: readonly string[];
|
|
91
110
|
}
|
|
92
111
|
|
|
93
112
|
/** Set up Bun and restore its global package cache. */
|
|
@@ -95,7 +114,7 @@ export function bunCacheRestoreSteps(
|
|
|
95
114
|
project: javascript.NodeProject,
|
|
96
115
|
options: BunWorkflowCacheOptions = {},
|
|
97
116
|
): readonly Record<string, unknown>[] {
|
|
98
|
-
ensureCacheKeyScript(project);
|
|
117
|
+
ensureCacheKeyScript(project, options.ignorePaths ?? []);
|
|
99
118
|
const condition = stepCondition(options.condition);
|
|
100
119
|
const setupCondition = stepCondition(options.setupCondition);
|
|
101
120
|
return [
|
package/src/clean.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { existsSync, rmSync, statSync } from "node:fs";
|
|
|
25
25
|
import { basename, join, relative } from "node:path";
|
|
26
26
|
import { find } from "@dbx-tools/path";
|
|
27
27
|
import { isReadonly, makeWritable } from "./generated.ts";
|
|
28
|
-
import {
|
|
28
|
+
import { resolveRepoRoot, toPosix } from "./packages.ts";
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Basenames `clean` never removes even when they are generated/read-only. `.gitignore`
|
|
@@ -40,7 +40,7 @@ const CLEAN_SKIP_FILES: ReadonlySet<string> = new Set([".gitignore"]);
|
|
|
40
40
|
* ignores AND every dot-prefixed folder (`.projen`, `.vscode`, `.github`, ...), and
|
|
41
41
|
* {@link CLEAN_SKIP_FILES} entry (`.gitignore`).
|
|
42
42
|
*/
|
|
43
|
-
export function listGeneratedFiles(root: string =
|
|
43
|
+
export function listGeneratedFiles(root: string = resolveRepoRoot()): string[] {
|
|
44
44
|
const rel = (f: string): string => toPosix(relative(root, f));
|
|
45
45
|
return [...find.findFiles("**/*", { cwd: root })]
|
|
46
46
|
.map((f) => join(root, f))
|
|
@@ -57,7 +57,7 @@ export function listGeneratedFiles(root: string = repoRoot): string[] {
|
|
|
57
57
|
* own - removing the top-level dir takes it along. Other vendor/build/VCS dirs are
|
|
58
58
|
* skipped for speed.
|
|
59
59
|
*/
|
|
60
|
-
export function listNodeModulesDirs(root: string =
|
|
60
|
+
export function listNodeModulesDirs(root: string = resolveRepoRoot()): string[] {
|
|
61
61
|
if (!existsSync(root)) return [];
|
|
62
62
|
const rel = (f: string): string => toPosix(relative(root, f));
|
|
63
63
|
return [...find.findFiles("**/node_modules", { cwd: root, ignoreOptions: { dot: false } })]
|
package/src/codegen.ts
CHANGED
|
@@ -50,7 +50,7 @@ import { log, object } from "@dbx-tools/shared-core";
|
|
|
50
50
|
import type * as ts from "typescript";
|
|
51
51
|
import { lazyRequire } from "./_lazy-require.ts";
|
|
52
52
|
import { header, isReadonly, makeReadonly, makeWritable } from "./generated.ts";
|
|
53
|
-
import { readPackageManifest,
|
|
53
|
+
import { readPackageManifest, recordedPackages, resolveRepoRoot } from "./packages.ts";
|
|
54
54
|
|
|
55
55
|
const logger = log.logger("projen:codegen");
|
|
56
56
|
|
|
@@ -115,7 +115,7 @@ export function codegenModulePaths(inputs: readonly string[]): string[] {
|
|
|
115
115
|
* package or hoisted to the workspace root. Any other source is treated as
|
|
116
116
|
* repo-root-relative.
|
|
117
117
|
*/
|
|
118
|
-
function resolveInputSource(source: string, fromDir: string): string {
|
|
118
|
+
function resolveInputSource(source: string, fromDir: string, projectRoot: string): string {
|
|
119
119
|
if (source.startsWith("node_modules/")) {
|
|
120
120
|
let dir = fromDir;
|
|
121
121
|
for (;;) {
|
|
@@ -126,7 +126,7 @@ function resolveInputSource(source: string, fromDir: string): string {
|
|
|
126
126
|
dir = parent;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
return resolve(
|
|
129
|
+
return resolve(projectRoot, source);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/**
|
|
@@ -276,6 +276,7 @@ function isGeneratedModule(srcDir: string, file: string): boolean {
|
|
|
276
276
|
function generatePackage(
|
|
277
277
|
tsRuntime: typeof ts,
|
|
278
278
|
generate: typeof import("ts-to-zod").generate,
|
|
279
|
+
projectRoot: string,
|
|
279
280
|
dir: string,
|
|
280
281
|
inputs: string[],
|
|
281
282
|
): string {
|
|
@@ -296,7 +297,7 @@ function generatePackage(
|
|
|
296
297
|
|
|
297
298
|
let warnings = 0;
|
|
298
299
|
for (const input of parsed) {
|
|
299
|
-
const sourcePath = resolveInputSource(input.source, dir);
|
|
300
|
+
const sourcePath = resolveInputSource(input.source, dir, projectRoot);
|
|
300
301
|
if (!existsSync(sourcePath)) {
|
|
301
302
|
throw new Error(`codegen input not found: ${input.source}`);
|
|
302
303
|
}
|
|
@@ -336,9 +337,16 @@ function generatePackage(
|
|
|
336
337
|
* `codegen` field. Returns the package dirs it wrote so the caller can rebuild
|
|
337
338
|
* their barrels. `ts-to-zod` + `typescript` are lazy-loaded.
|
|
338
339
|
*/
|
|
339
|
-
export function generateCodegen(
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
export function generateCodegen(
|
|
341
|
+
projectRoot: string = resolveRepoRoot(),
|
|
342
|
+
options: { includeRoot?: boolean } = {},
|
|
343
|
+
): string[] {
|
|
344
|
+
const packageDirs = [
|
|
345
|
+
...(options.includeRoot ? [projectRoot] : []),
|
|
346
|
+
...recordedPackages(projectRoot).map((pkg) => pkg.dir),
|
|
347
|
+
];
|
|
348
|
+
const targets = packageDirs
|
|
349
|
+
.map((dir) => ({ dir, inputs: codegenInputs(dir) }))
|
|
342
350
|
.filter((t): t is { dir: string; inputs: string[] } => t.inputs !== undefined);
|
|
343
351
|
|
|
344
352
|
// Nothing to generate is the NORMAL case for a workspace that declares no
|
|
@@ -356,7 +364,7 @@ export function generateCodegen(): string[] {
|
|
|
356
364
|
|
|
357
365
|
const written: string[] = [];
|
|
358
366
|
for (const target of targets) {
|
|
359
|
-
written.push(generatePackage(tsRuntime, generate, target.dir, target.inputs));
|
|
367
|
+
written.push(generatePackage(tsRuntime, generate, projectRoot, target.dir, target.inputs));
|
|
360
368
|
}
|
|
361
369
|
return written;
|
|
362
370
|
}
|
package/src/packages.ts
CHANGED
|
@@ -30,12 +30,13 @@ import { find } from "@dbx-tools/path";
|
|
|
30
30
|
import { json, object, string } from "@dbx-tools/shared-core";
|
|
31
31
|
import { parse } from "yaml";
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
/** Resolve the nearest package/projenrc root at call time. */
|
|
34
|
+
export function resolveRepoRoot(cwd: string = process.cwd()): string {
|
|
35
|
+
return coreProject.root(cwd) ?? cwd;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Current-process repository root for executable task entrypoints. */
|
|
39
|
+
export const repoRoot = resolveRepoRoot();
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Default package roots. Each is scanned for packages; override via the
|
|
@@ -49,8 +50,8 @@ export const DEFAULT_PACKAGE_ROOTS = ["packages"] as const;
|
|
|
49
50
|
* {@link coreProject.name}, which is also what a consuming repo's own tooling
|
|
50
51
|
* sees, so the engine and its host agree on the name.
|
|
51
52
|
*/
|
|
52
|
-
export function projectName(): string {
|
|
53
|
-
return coreProject.name(
|
|
53
|
+
export function projectName(projectRoot: string = resolveRepoRoot()): string {
|
|
54
|
+
return coreProject.name(projectRoot);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
const MODULE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
@@ -168,7 +169,7 @@ export class DiscoveredPackage {
|
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
/** Read the raw workspace member globs from `pnpm-workspace.yaml` (source of truth). */
|
|
171
|
-
function readRecordedMembers(projectRoot: string =
|
|
172
|
+
function readRecordedMembers(projectRoot: string = resolveRepoRoot()): string[] {
|
|
172
173
|
const file = resolve(projectRoot, "pnpm-workspace.yaml");
|
|
173
174
|
if (!existsSync(file)) return [];
|
|
174
175
|
const doc = parse(readFileSync(file, "utf8")) as {
|
|
@@ -218,7 +219,7 @@ function collectPackageDirs(rootAbs: string): string[] {
|
|
|
218
219
|
* recorded set. Sorted by member path.
|
|
219
220
|
*/
|
|
220
221
|
export function scanPackages(
|
|
221
|
-
projectRoot: string =
|
|
222
|
+
projectRoot: string = resolveRepoRoot(),
|
|
222
223
|
roots: readonly string[] = DEFAULT_PACKAGE_ROOTS,
|
|
223
224
|
): DiscoveredPackage[] {
|
|
224
225
|
const out: DiscoveredPackage[] = [];
|
|
@@ -285,7 +286,7 @@ function readManifestTags(dir: string): string[] | undefined {
|
|
|
285
286
|
* the root `package.json` `dbxToolsConfig.syncResynthPaths` (set via the
|
|
286
287
|
* {@link DBXToolsProjectOptions.syncResynthPaths} option at synth).
|
|
287
288
|
*/
|
|
288
|
-
export function syncResynthPaths(projectRoot: string =
|
|
289
|
+
export function syncResynthPaths(projectRoot: string = resolveRepoRoot()): string[] {
|
|
289
290
|
const paths = readDbxToolsConfig(projectRoot)?.syncResynthPaths;
|
|
290
291
|
return Array.isArray(paths) ? string.parseList(paths.map((p) => String(p))) : [];
|
|
291
292
|
}
|
|
@@ -297,7 +298,7 @@ export function syncResynthPaths(projectRoot: string = repoRoot): string[] {
|
|
|
297
298
|
* authoritative, so it reflects the resolved tag set.
|
|
298
299
|
* Sorted by path.
|
|
299
300
|
*/
|
|
300
|
-
export function recordedPackages(projectRoot: string =
|
|
301
|
+
export function recordedPackages(projectRoot: string = resolveRepoRoot()): RecordedPackage[] {
|
|
301
302
|
const out: RecordedPackage[] = [];
|
|
302
303
|
for (const member of readRecordedMembers(projectRoot)) {
|
|
303
304
|
const pkg = packageOfMember(projectRoot, member);
|
|
@@ -318,7 +319,7 @@ export function recordedPackages(projectRoot: string = repoRoot): RecordedPackag
|
|
|
318
319
|
* that field fall back to the distinct first segment of every recorded member,
|
|
319
320
|
* unioned with the defaults.
|
|
320
321
|
*/
|
|
321
|
-
export function recordedRoots(projectRoot: string =
|
|
322
|
+
export function recordedRoots(projectRoot: string = resolveRepoRoot()): string[] {
|
|
322
323
|
const configured = readDbxToolsConfig(projectRoot)?.packageRoots;
|
|
323
324
|
if (Array.isArray(configured)) {
|
|
324
325
|
const roots = string.parseList(configured.map((root) => String(root)));
|