@dbx-tools/projen 0.6.77 → 0.6.78
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/index.ts +4 -4
- package/package.json +4 -4
- package/src/pnpm-workspace.ts +1 -0
- package/src/project-js.ts +23 -14
- package/src/project-predicate.ts +17 -6
- package/src/project-py.ts +179 -107
- package/src/project.ts +18 -5
- package/src/publish.ts +2 -2
package/index.ts
CHANGED
|
@@ -36,11 +36,11 @@ export { repoRoot, DEFAULT_PACKAGE_ROOTS, DiscoveredPackage } from "./src/packag
|
|
|
36
36
|
export type { RecordedPackage } from "./src/packages.ts";
|
|
37
37
|
export { PnpmWorkspaceState } from "./src/pnpm-workspace.ts";
|
|
38
38
|
export type { Catalog, AllowBuilds, DBXToolsPNPMWorkspaceOptions } from "./src/pnpm-workspace.ts";
|
|
39
|
-
export type { ApplyToProjectsOptions } from "./src/project.ts";
|
|
39
|
+
export type { DBXToolsProjectLanguage, DBXToolsProjectOptions, DBXToolsProject, ApplyToProjectsOptions } from "./src/project.ts";
|
|
40
40
|
export { PackageIdentifier, PROJEN_VERSION, DBXToolsNodeProject, ROOT_INSTALL_ONLY_MIXIN, DBXToolsTypeScriptProject } from "./src/project-js.ts";
|
|
41
|
-
export type {
|
|
42
|
-
export { DBXToolsPythonWorkspace } from "./src/project-py.ts";
|
|
43
|
-
export type { PythonRepositoryOptions, PythonPackageOptions, PythonReleaseOptions, DBXToolsPythonWorkspaceOptions } from "./src/project-py.ts";
|
|
41
|
+
export type { DBXToolsJavaScriptProject, DBXToolsJavaScriptProjectOptions, DBXToolsTypeScriptProjectOptions } from "./src/project-js.ts";
|
|
42
|
+
export { DBXToolsPythonProject, DBXToolsPythonWorkspace } from "./src/project-py.ts";
|
|
43
|
+
export type { PythonRepositoryOptions, PythonPackageOptions, DBXToolsPythonProjectOptions, PythonReleaseOptions, DBXToolsPythonWorkspaceOptions } from "./src/project-py.ts";
|
|
44
44
|
export { COMPILED_DIR, COMPILED_COMPILER_OPTIONS } from "./src/publish.ts";
|
|
45
45
|
export { DBXToolsRelease } from "./src/release.ts";
|
|
46
46
|
export type { StandaloneRelease, DBXToolsReleaseOptions } from "./src/release.ts";
|
package/package.json
CHANGED
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@clack/prompts": "^1.7.0",
|
|
29
|
-
"@dbx-tools/core": "0.6.
|
|
30
|
-
"@dbx-tools/path": "0.6.
|
|
31
|
-
"@dbx-tools/shared-core": "0.6.
|
|
29
|
+
"@dbx-tools/core": "0.6.78",
|
|
30
|
+
"@dbx-tools/path": "0.6.78",
|
|
31
|
+
"@dbx-tools/shared-core": "0.6.78",
|
|
32
32
|
"commander": "^15.0.0",
|
|
33
33
|
"concurrently": "^10.0.3",
|
|
34
34
|
"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.78",
|
|
51
51
|
"types": "index.ts",
|
|
52
52
|
"type": "module",
|
|
53
53
|
"exports": {
|
package/src/pnpm-workspace.ts
CHANGED
|
@@ -250,6 +250,7 @@ export class PnpmWorkspaceState {
|
|
|
250
250
|
*/
|
|
251
251
|
public resolveMembers(project: Project, extraMembers: readonly string[] = []): void {
|
|
252
252
|
const members = project.subprojects
|
|
253
|
+
.filter((sub): sub is javascript.NodeProject => sub instanceof javascript.NodeProject)
|
|
253
254
|
.map((sub) => toPosix(relative(project.outdir, sub.outdir)))
|
|
254
255
|
.filter(Boolean);
|
|
255
256
|
// `extraMembers` are workspace siblings NOT attached as subprojects (e.g. the
|
package/src/project-js.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The dbx-tools project surface plus package tooling: the single
|
|
3
|
-
* {@link
|
|
3
|
+
* {@link DBXToolsJavaScriptProject} interface, the projen Node/TypeScript project classes,
|
|
4
4
|
* naming, guards, manifest fields, and the shared root init.
|
|
5
5
|
*
|
|
6
6
|
* {@link DBXToolsNodeProject} (monorepo root) and {@link DBXToolsTypeScriptProject}
|
|
7
|
-
* (a package, or a standalone compiling root) both implement {@link
|
|
7
|
+
* (a package, or a standalone compiling root) both implement {@link DBXToolsJavaScriptProject}.
|
|
8
8
|
*/
|
|
9
9
|
import { existsSync, readdirSync } from "node:fs";
|
|
10
10
|
import { dirname, join, relative, resolve } from "node:path";
|
|
@@ -41,13 +41,14 @@ import { DBXToolsRelease, type StandaloneRelease } from "./release.ts";
|
|
|
41
41
|
import { AGNOSTIC_COMPILER_OPTIONS, PACKAGE_TAG_MIXINS, type PackageTag } from "./tags.ts";
|
|
42
42
|
import { DBXToolsRootTsconfig } from "./tsconfig.ts";
|
|
43
43
|
import { DBXToolsVsCode } from "./vscode.ts";
|
|
44
|
+
import type { DBXToolsProject, DBXToolsProjectOptions as CommonProjectOptions } from "./project.ts";
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* The dbx-tools project surface, backed by projen's Node toolchain. A single
|
|
47
48
|
* interface for both the monorepo root and each package: it carries the
|
|
48
49
|
* `dbxToolsConfig` component plus the npm-naming and root-only file components.
|
|
49
50
|
*/
|
|
50
|
-
export interface
|
|
51
|
+
export interface DBXToolsJavaScriptProject extends DBXToolsProject, javascript.NodeProject {
|
|
51
52
|
/** The package's `dbxToolsConfig` component (tags + `package.json` config). */
|
|
52
53
|
readonly dbxToolsConfig: DBXToolsConfig;
|
|
53
54
|
/** npm scope (the `@scope` in `@scope/pkg`), without the leading `@`. */
|
|
@@ -342,7 +343,9 @@ export const PROJEN_VERSION = "^0.101.16";
|
|
|
342
343
|
* inherits the root's config rather than emitting its own. `name`/`defaultReleaseBranch`
|
|
343
344
|
* are resolved/applied by the caller.
|
|
344
345
|
*/
|
|
345
|
-
function defaultProjectOptions(
|
|
346
|
+
function defaultProjectOptions(
|
|
347
|
+
options: DBXToolsJavaScriptProjectOptions,
|
|
348
|
+
): DBXToolsJavaScriptProjectOptions {
|
|
346
349
|
const isRoot = options.parent === undefined;
|
|
347
350
|
return {
|
|
348
351
|
// Bun owns install/run/build/test locally and in CI. projen renders
|
|
@@ -420,7 +423,7 @@ function defaultProjectOptions(options: DBXToolsProjectOptions): DBXToolsProject
|
|
|
420
423
|
* pristine array to seed a child's fresh one. Spread AFTER `...options`.
|
|
421
424
|
*/
|
|
422
425
|
function copiedGitIgnoreOptions(
|
|
423
|
-
options:
|
|
426
|
+
options: DBXToolsJavaScriptProjectOptions,
|
|
424
427
|
): Pick<javascript.NodeProjectOptions, "gitIgnoreOptions"> {
|
|
425
428
|
if (!options.gitIgnoreOptions?.ignorePatterns) return {};
|
|
426
429
|
return {
|
|
@@ -460,8 +463,9 @@ function defaultTypeScriptProjectOptions(
|
|
|
460
463
|
const DEV_DEPS_ROOT: string[] = ["typescript@^5.9.3", "@types/bun@^1.3.14"];
|
|
461
464
|
|
|
462
465
|
/** Options for {@link DBXToolsNodeProject} (the monorepo root). */
|
|
463
|
-
export interface
|
|
466
|
+
export interface DBXToolsJavaScriptProjectOptions
|
|
464
467
|
extends
|
|
468
|
+
CommonProjectOptions,
|
|
465
469
|
Partial<javascript.NodeProjectOptions>,
|
|
466
470
|
DBXToolsConfigOptions,
|
|
467
471
|
DBXToolsPNPMWorkspaceOptions {
|
|
@@ -529,7 +533,7 @@ export interface DBXToolsProjectOptions
|
|
|
529
533
|
|
|
530
534
|
/** Options for {@link DBXToolsTypeScriptProject} (a package, or a compiling root). */
|
|
531
535
|
export interface DBXToolsTypeScriptProjectOptions
|
|
532
|
-
extends Partial<typescript.TypeScriptProjectOptions>,
|
|
536
|
+
extends Partial<typescript.TypeScriptProjectOptions>, DBXToolsJavaScriptProjectOptions {
|
|
533
537
|
/** Emit the projen-owned bun app scaffolding (`bunfig.toml`/`dev.ts`/`build.ts`). */
|
|
534
538
|
readonly bunApp?: boolean;
|
|
535
539
|
}
|
|
@@ -539,7 +543,11 @@ export interface DBXToolsTypeScriptProjectOptions
|
|
|
539
543
|
* {@link DBXToolsTypeScriptProject} per `src`-bearing folder, then emits the
|
|
540
544
|
* shared config, tasks, `pnpm-workspace.yaml`, and barrels-on-synth.
|
|
541
545
|
*/
|
|
542
|
-
export class DBXToolsNodeProject
|
|
546
|
+
export class DBXToolsNodeProject
|
|
547
|
+
extends javascript.NodeProject
|
|
548
|
+
implements DBXToolsJavaScriptProject
|
|
549
|
+
{
|
|
550
|
+
readonly language = "javascript" as const;
|
|
543
551
|
readonly scope: string;
|
|
544
552
|
readonly dbxToolsConfig: DBXToolsConfig;
|
|
545
553
|
pnpmWorkspace?: PnpmWorkspaceState;
|
|
@@ -548,7 +556,7 @@ export class DBXToolsNodeProject extends javascript.NodeProject implements DBXTo
|
|
|
548
556
|
private readonly extraWorkspaceMembers: readonly string[];
|
|
549
557
|
private readonly rootInstallOnly: boolean;
|
|
550
558
|
|
|
551
|
-
constructor(options:
|
|
559
|
+
constructor(options: DBXToolsJavaScriptProjectOptions = {}) {
|
|
552
560
|
const { name, scope } = resolveIdentity(options);
|
|
553
561
|
const releaseDefaults =
|
|
554
562
|
options.release && options.releaseTrigger === undefined
|
|
@@ -622,8 +630,9 @@ export const ROOT_INSTALL_ONLY_MIXIN = mixin.create(
|
|
|
622
630
|
*/
|
|
623
631
|
export class DBXToolsTypeScriptProject
|
|
624
632
|
extends typescript.TypeScriptProject
|
|
625
|
-
implements
|
|
633
|
+
implements DBXToolsJavaScriptProject
|
|
626
634
|
{
|
|
635
|
+
readonly language = "javascript" as const;
|
|
627
636
|
readonly scope: string;
|
|
628
637
|
readonly dbxToolsConfig: DBXToolsConfig;
|
|
629
638
|
pnpmWorkspace?: PnpmWorkspaceState;
|
|
@@ -816,7 +825,7 @@ class PrettierIgnoreGenerated extends Component {
|
|
|
816
825
|
/** Default leading path segment stripped from a package's name (not its tag). */
|
|
817
826
|
const DEFAULT_OMIT_RELATIVE_PREFIX = ["node"];
|
|
818
827
|
|
|
819
|
-
/** Normalize the {@link
|
|
828
|
+
/** Normalize the {@link DBXToolsJavaScriptProjectOptions.omitRelativePrefix} option to a slug list. */
|
|
820
829
|
function resolveOmitRelativePrefix(option: OneOrMany<string> | undefined): string[] {
|
|
821
830
|
const raw = option === undefined ? DEFAULT_OMIT_RELATIVE_PREFIX : option;
|
|
822
831
|
const list = Array.isArray(raw) ? raw : [raw];
|
|
@@ -943,7 +952,7 @@ export function taskScript(_project: javascript.NodeProject, script: string, arg
|
|
|
943
952
|
*/
|
|
944
953
|
function initProject(
|
|
945
954
|
project: DBXToolsNodeProject | DBXToolsTypeScriptProject,
|
|
946
|
-
options:
|
|
955
|
+
options: DBXToolsJavaScriptProjectOptions,
|
|
947
956
|
): void {
|
|
948
957
|
// projen's GithubProject seeds a `# replace this` SampleReadme on every
|
|
949
958
|
// project. READMEs are hand-written and owned outside projen, so drop the
|
|
@@ -1101,7 +1110,7 @@ function initProject(
|
|
|
1101
1110
|
|
|
1102
1111
|
// Already-attached subprojects, keyed by repo-relative member path.
|
|
1103
1112
|
const rootAbs = resolve(project.outdir);
|
|
1104
|
-
const existing = new Map<string,
|
|
1113
|
+
const existing = new Map<string, DBXToolsJavaScriptProject>();
|
|
1105
1114
|
for (const sub of project.subprojects) {
|
|
1106
1115
|
if (sub instanceof DBXToolsNodeProject || sub instanceof DBXToolsTypeScriptProject) {
|
|
1107
1116
|
existing.set(toPosix(relative(rootAbs, sub.outdir)), sub);
|
|
@@ -1182,7 +1191,7 @@ class ChildGitignore extends IgnoreFile {
|
|
|
1182
1191
|
*/
|
|
1183
1192
|
function swapChildGitignore(
|
|
1184
1193
|
project: javascript.NodeProject,
|
|
1185
|
-
options:
|
|
1194
|
+
options: DBXToolsJavaScriptProjectOptions,
|
|
1186
1195
|
): void {
|
|
1187
1196
|
project.tryRemoveFile(".gitignore");
|
|
1188
1197
|
const fresh = new ChildGitignore(project, ".gitignore", {
|
package/src/project-predicate.ts
CHANGED
|
@@ -11,7 +11,8 @@ import { IConstruct } from "constructs";
|
|
|
11
11
|
import { Project } from "projen";
|
|
12
12
|
import { project } from "..";
|
|
13
13
|
import { toPosix } from "./packages.ts";
|
|
14
|
-
import { DBXToolsProject
|
|
14
|
+
import type { DBXToolsProject } from "./project.ts";
|
|
15
|
+
import type { DBXToolsJavaScriptProject } from "./project-js.ts";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Guard: the construct is a projen {@link Project} - the base every builder here
|
|
@@ -27,11 +28,19 @@ export function isProject(): Predicate<IConstruct, Project> {
|
|
|
27
28
|
return predicate.create((c: IConstruct): c is Project => Project.isProject(c));
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
/** Guard: the construct
|
|
31
|
+
/** Guard: the construct implements the language-agnostic {@link DBXToolsProject} contract. */
|
|
31
32
|
export function isDBXToolsProject(): Predicate<IConstruct, DBXToolsProject> {
|
|
32
33
|
return isProject().and(
|
|
33
34
|
(project): project is DBXToolsProject =>
|
|
34
|
-
project
|
|
35
|
+
(project as Partial<DBXToolsProject>).language === "javascript" ||
|
|
36
|
+
(project as Partial<DBXToolsProject>).language === "python",
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Guard: the construct is a dbx-tools JavaScript/TypeScript project. */
|
|
41
|
+
export function isDBXToolsJavaScriptProject(): Predicate<IConstruct, DBXToolsJavaScriptProject> {
|
|
42
|
+
return isDBXToolsProject().and(
|
|
43
|
+
(project): project is DBXToolsJavaScriptProject => project.language === "javascript",
|
|
35
44
|
);
|
|
36
45
|
}
|
|
37
46
|
|
|
@@ -97,14 +106,16 @@ export function hasIdentifierScope(
|
|
|
97
106
|
|
|
98
107
|
/**
|
|
99
108
|
* Matches DBXTools packages carrying every listed tag (`dbxToolsConfig.tags`), narrowing
|
|
100
|
-
* {@link Project} to {@link
|
|
109
|
+
* {@link Project} to {@link DBXToolsJavaScriptProject} (tags live only on JavaScript packages). Also the
|
|
101
110
|
* guard backing each built-in {@link PACKAGE_TAG_MIXINS} entry. Keep it in the SAME `.and(...)`
|
|
102
111
|
* as any name/path filter (or last when chaining) - a later non-tag `.and` re-widens to
|
|
103
112
|
* {@link Project} and drops the narrowing.
|
|
104
113
|
*/
|
|
105
|
-
export function hasTag(
|
|
114
|
+
export function hasTag(
|
|
115
|
+
...tags: OneOrMany<PathMatchInput>
|
|
116
|
+
): Predicate<IConstruct, DBXToolsJavaScriptProject> {
|
|
106
117
|
const matchers = projectMatchers(...tags);
|
|
107
|
-
return
|
|
118
|
+
return isDBXToolsJavaScriptProject().and((project) =>
|
|
108
119
|
matchers.every((matcher) => project.dbxToolsConfig.tags.some((tag) => matcher(tag))),
|
|
109
120
|
);
|
|
110
121
|
}
|
package/src/project-py.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/** Reusable uv workspace generation for Python packages hosted in a projen tree. */
|
|
2
2
|
import { string } from "@dbx-tools/shared-core";
|
|
3
|
-
import { Component,
|
|
3
|
+
import { Component, type Project, javascript, python, vscode } from "projen";
|
|
4
4
|
import { GithubWorkflow } from "projen/lib/github";
|
|
5
5
|
import { JobPermission } from "projen/lib/github/workflows-model";
|
|
6
|
+
import type { DBXToolsProject, DBXToolsProjectOptions } from "./project.ts";
|
|
6
7
|
|
|
7
8
|
/** Git location used by direct `#subdirectory=` package dependencies. */
|
|
8
9
|
export interface PythonRepositoryOptions {
|
|
@@ -12,7 +13,7 @@ export interface PythonRepositoryOptions {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/** One independently installable Python package in the uv workspace. */
|
|
15
|
-
export interface PythonPackageOptions {
|
|
16
|
+
export interface PythonPackageOptions extends DBXToolsProjectOptions {
|
|
16
17
|
readonly directory: string;
|
|
17
18
|
readonly name: string;
|
|
18
19
|
readonly module: string;
|
|
@@ -20,10 +21,19 @@ export interface PythonPackageOptions {
|
|
|
20
21
|
readonly dependencies?: readonly string[];
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/** Options for one projen-native Python workspace member. */
|
|
25
|
+
export interface DBXToolsPythonProjectOptions extends DBXToolsProjectOptions {
|
|
26
|
+
readonly parent: Project;
|
|
27
|
+
readonly package: PythonPackageOptions;
|
|
28
|
+
readonly repository: Required<PythonRepositoryOptions>;
|
|
29
|
+
readonly requiresPython: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
/** Python release workflow configuration. */
|
|
24
33
|
export interface PythonReleaseOptions {
|
|
25
34
|
readonly workflowName?: string;
|
|
26
|
-
|
|
35
|
+
/** GitHub environment by Python distribution name. Defaults to `pypi-<name>`. */
|
|
36
|
+
readonly environments?: Readonly<Record<string, string>>;
|
|
27
37
|
readonly environmentUrl?: string;
|
|
28
38
|
}
|
|
29
39
|
|
|
@@ -69,27 +79,112 @@ function projectVscode(project: Project): vscode.VsCode | undefined {
|
|
|
69
79
|
return (project as Project & { readonly vscode?: vscode.VsCode }).vscode;
|
|
70
80
|
}
|
|
71
81
|
|
|
82
|
+
/** A Python package implemented with projen's `PythonProject` and uv backend. */
|
|
83
|
+
export class DBXToolsPythonProject extends python.PythonProject implements DBXToolsProject {
|
|
84
|
+
readonly language = "python" as const;
|
|
85
|
+
readonly packageOptions: PythonPackageOptions;
|
|
86
|
+
readonly uv: python.Uv;
|
|
87
|
+
|
|
88
|
+
constructor(options: DBXToolsPythonProjectOptions) {
|
|
89
|
+
const pkg = options.package;
|
|
90
|
+
super({
|
|
91
|
+
parent: options.parent,
|
|
92
|
+
outdir: pythonPackagePath(options.repository, pkg.directory),
|
|
93
|
+
name: pkg.name,
|
|
94
|
+
moduleName: pkg.module,
|
|
95
|
+
authorName: "",
|
|
96
|
+
authorEmail: "",
|
|
97
|
+
version: "0.0.0",
|
|
98
|
+
description: pkg.description,
|
|
99
|
+
github: false,
|
|
100
|
+
sample: false,
|
|
101
|
+
pytest: false,
|
|
102
|
+
projenrcPython: false,
|
|
103
|
+
projenrcJs: false,
|
|
104
|
+
projenrcTs: false,
|
|
105
|
+
pip: false,
|
|
106
|
+
venv: false,
|
|
107
|
+
setuptools: false,
|
|
108
|
+
poetry: false,
|
|
109
|
+
uv: true,
|
|
110
|
+
projenCommand: options.parent.projenCommand,
|
|
111
|
+
uvOptions: {
|
|
112
|
+
project: {
|
|
113
|
+
name: pkg.name,
|
|
114
|
+
version: "0.0.0",
|
|
115
|
+
description: pkg.description,
|
|
116
|
+
readme: "README.md",
|
|
117
|
+
requiresPython: options.requiresPython,
|
|
118
|
+
dependencies: [...(pkg.dependencies ?? [])],
|
|
119
|
+
urls: {
|
|
120
|
+
Source: `${options.repository.url.replace(/\.git$/, "")}/tree/${options.repository.ref}/${pythonPackagePath(options.repository, pkg.directory)}`,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
buildSystem: {
|
|
124
|
+
requires: ["uv_build>=0.11.28,<0.12.0"],
|
|
125
|
+
buildBackend: "uv_build",
|
|
126
|
+
},
|
|
127
|
+
uv: {
|
|
128
|
+
buildBackend: {
|
|
129
|
+
moduleName: pkg.module,
|
|
130
|
+
moduleRoot: "src",
|
|
131
|
+
namespace: true,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
this.packageOptions = pkg;
|
|
137
|
+
if (!(this.packagingManager instanceof python.Uv)) {
|
|
138
|
+
throw new Error(`Expected uv packaging for ${pkg.name}`);
|
|
139
|
+
}
|
|
140
|
+
this.uv = this.packagingManager;
|
|
141
|
+
this.uv.file.addDeletionOverride("project.authors");
|
|
142
|
+
this.uv.file.addDeletionOverride("dependency-groups");
|
|
143
|
+
this.uv.file.readonly = true;
|
|
144
|
+
|
|
145
|
+
for (const path of [".gitattributes", ".gitignore"]) {
|
|
146
|
+
this.tryRemoveFile(path);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** The root workspace owns dependency installation for every member. */
|
|
151
|
+
public override postSynthesize(): void {}
|
|
152
|
+
}
|
|
153
|
+
|
|
72
154
|
/**
|
|
73
|
-
* Generates a root uv workspace, member
|
|
74
|
-
* interpreter selection, and an optional
|
|
155
|
+
* Generates a root uv workspace, projen-native Python member projects, Python
|
|
156
|
+
* tasks, editor interpreter selection, and an optional publishing workflow.
|
|
75
157
|
*/
|
|
76
158
|
export class DBXToolsPythonWorkspace extends Component {
|
|
77
|
-
readonly packages: readonly
|
|
159
|
+
readonly packages: readonly DBXToolsPythonProject[];
|
|
78
160
|
readonly repository: Required<PythonRepositoryOptions>;
|
|
79
161
|
readonly requiresPython: string;
|
|
162
|
+
readonly file: python.PyprojectTomlFile;
|
|
80
163
|
|
|
81
164
|
constructor(project: javascript.NodeProject, options: DBXToolsPythonWorkspaceOptions) {
|
|
82
165
|
super(project);
|
|
83
|
-
this.packages = options.packages;
|
|
84
166
|
this.repository = {
|
|
85
167
|
url: options.repository.url,
|
|
86
168
|
ref: options.repository.ref ?? "main",
|
|
87
169
|
root: options.repository.root ?? "packages/py",
|
|
88
170
|
};
|
|
89
171
|
this.requiresPython = options.requiresPython ?? ">=3.10";
|
|
90
|
-
|
|
91
|
-
this.
|
|
92
|
-
|
|
172
|
+
this.file = this.emitWorkspace(project, options);
|
|
173
|
+
this.packages = options.packages.map(
|
|
174
|
+
(pkg) =>
|
|
175
|
+
new DBXToolsPythonProject({
|
|
176
|
+
parent: project,
|
|
177
|
+
package: pkg,
|
|
178
|
+
repository: this.repository,
|
|
179
|
+
requiresPython: this.requiresPython,
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
182
|
+
for (const pkg of this.packages) {
|
|
183
|
+
const pyproject = `/${pythonPackagePath(this.repository, pkg.packageOptions.directory)}/pyproject.toml`;
|
|
184
|
+
project.gitignore.include(pyproject);
|
|
185
|
+
project.gitattributes.addAttributes(pyproject, "linguist-generated");
|
|
186
|
+
project.prettier?.addIgnorePattern(pyproject.slice(1));
|
|
187
|
+
}
|
|
93
188
|
this.addTasks(project, options);
|
|
94
189
|
|
|
95
190
|
const interpreterPath = options.interpreterPath ?? "${workspaceFolder}/.venv/bin/python";
|
|
@@ -115,81 +210,45 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
115
210
|
private emitWorkspace(
|
|
116
211
|
project: javascript.NodeProject,
|
|
117
212
|
options: DBXToolsPythonWorkspaceOptions,
|
|
118
|
-
):
|
|
119
|
-
const devDependencies = options.devDependencies ?? DEFAULT_DEV_DEPENDENCIES;
|
|
213
|
+
): python.PyprojectTomlFile {
|
|
120
214
|
const testPaths = options.testPaths ?? [this.repository.root];
|
|
121
|
-
const ruffTarget = options.ruffTarget ?? "py310";
|
|
122
215
|
const perFileIgnores = options.ruffPerFileIgnores ?? {};
|
|
123
|
-
new
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"line-length = 100",
|
|
153
|
-
"",
|
|
154
|
-
"[tool.ruff.lint.per-file-ignores]",
|
|
155
|
-
...Object.entries(perFileIgnores).map(
|
|
156
|
-
([path, rules]) => `${quote(path)} = [${rules.map(quote).join(", ")}]`,
|
|
157
|
-
),
|
|
158
|
-
"",
|
|
159
|
-
],
|
|
216
|
+
const file = new python.PyprojectTomlFile(project, {
|
|
217
|
+
project: {
|
|
218
|
+
name: options.workspaceName ?? `${string.toSlug(project.name)}-python-workspace`,
|
|
219
|
+
version: "0.0.0",
|
|
220
|
+
requiresPython: this.requiresPython,
|
|
221
|
+
dependencies: [],
|
|
222
|
+
},
|
|
223
|
+
dependencyGroups: {
|
|
224
|
+
dev: [...(options.devDependencies ?? DEFAULT_DEV_DEPENDENCIES)],
|
|
225
|
+
},
|
|
226
|
+
tool: {
|
|
227
|
+
uv: python.uvConfig.toJson_UvConfiguration({
|
|
228
|
+
package: false,
|
|
229
|
+
workspace: { members: [`${this.repository.root}/*`] },
|
|
230
|
+
}),
|
|
231
|
+
pytest: {
|
|
232
|
+
ini_options: {
|
|
233
|
+
asyncio_mode: "auto",
|
|
234
|
+
testpaths: testPaths,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
ruff: {
|
|
238
|
+
"target-version": options.ruffTarget ?? "py310",
|
|
239
|
+
"line-length": 100,
|
|
240
|
+
lint: {
|
|
241
|
+
"per-file-ignores": perFileIgnores,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
160
245
|
});
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
readonly: true,
|
|
168
|
-
lines: [
|
|
169
|
-
'# ~~ Generated by projen. To modify, edit .projenrc.ts and run "bunx projen".',
|
|
170
|
-
"[project]",
|
|
171
|
-
`name = ${quote(pkg.name)}`,
|
|
172
|
-
'version = "0.0.0"',
|
|
173
|
-
`description = ${quote(pkg.description)}`,
|
|
174
|
-
'readme = "README.md"',
|
|
175
|
-
`requires-python = ${quote(this.requiresPython)}`,
|
|
176
|
-
`dependencies = [${(pkg.dependencies ?? []).map(quote).join(", ")}]`,
|
|
177
|
-
"",
|
|
178
|
-
"[project.urls]",
|
|
179
|
-
`Source = ${quote(`${this.repository.url.replace(/\.git$/, "")}/tree/${this.repository.ref}/${this.packagePath(pkg.directory)}`)}`,
|
|
180
|
-
"",
|
|
181
|
-
"[build-system]",
|
|
182
|
-
'requires = ["uv_build>=0.11.28,<0.12.0"]',
|
|
183
|
-
'build-backend = "uv_build"',
|
|
184
|
-
"",
|
|
185
|
-
"[tool.uv.build-backend]",
|
|
186
|
-
`module-name = ${quote(pkg.module)}`,
|
|
187
|
-
'module-root = "src"',
|
|
188
|
-
"namespace = true",
|
|
189
|
-
"",
|
|
190
|
-
],
|
|
191
|
-
});
|
|
192
|
-
}
|
|
246
|
+
file.addOverride(
|
|
247
|
+
"tool.uv.sources",
|
|
248
|
+
Object.fromEntries(options.packages.map((pkg) => [pkg.name, { workspace: true }])),
|
|
249
|
+
);
|
|
250
|
+
file.readonly = true;
|
|
251
|
+
return file;
|
|
193
252
|
}
|
|
194
253
|
|
|
195
254
|
private addTasks(project: javascript.NodeProject, options: DBXToolsPythonWorkspaceOptions): void {
|
|
@@ -247,12 +306,20 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
247
306
|
env: { VERSION: "${{ inputs.version }}" },
|
|
248
307
|
run: this.renderVersionStampScript(),
|
|
249
308
|
},
|
|
250
|
-
{
|
|
309
|
+
{
|
|
310
|
+
name: "Build distributions",
|
|
311
|
+
run: this.packages
|
|
312
|
+
.map(
|
|
313
|
+
(pkg) =>
|
|
314
|
+
`uv build --package ${pkg.packageOptions.name} --out-dir dist/${pkg.packageOptions.directory}`,
|
|
315
|
+
)
|
|
316
|
+
.join("\n"),
|
|
317
|
+
},
|
|
251
318
|
{
|
|
252
319
|
name: "Validate distributions",
|
|
253
320
|
run: [
|
|
254
|
-
`test "$(find dist -
|
|
255
|
-
"uvx twine check dist
|
|
321
|
+
`test "$(find dist -type f \\( -name '*.whl' -o -name '*.tar.gz' \\) | wc -l | tr -d ' ')" -eq ${this.packages.length * 2}`,
|
|
322
|
+
"uvx twine check dist/*/*.whl dist/*/*.tar.gz",
|
|
256
323
|
].join("\n"),
|
|
257
324
|
},
|
|
258
325
|
{
|
|
@@ -262,29 +329,34 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
262
329
|
},
|
|
263
330
|
],
|
|
264
331
|
});
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
steps: [
|
|
276
|
-
{
|
|
277
|
-
name: "Download distributions",
|
|
278
|
-
uses: "actions/download-artifact@v8",
|
|
279
|
-
with: { name: "python-distributions", path: "dist" },
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
name: "Publish to PyPI",
|
|
283
|
-
uses: "pypa/gh-action-pypi-publish@release/v1",
|
|
284
|
-
with: { "packages-dir": "dist" },
|
|
332
|
+
for (const pkg of this.packages) {
|
|
333
|
+
workflow.addJob(`publish-${pkg.packageOptions.directory}`, {
|
|
334
|
+
if: "${{ inputs.publish }}",
|
|
335
|
+
needs: ["build"],
|
|
336
|
+
environment: {
|
|
337
|
+
name:
|
|
338
|
+
options.environments?.[pkg.packageOptions.name] ?? `pypi-${pkg.packageOptions.name}`,
|
|
339
|
+
url:
|
|
340
|
+
options.environmentUrl ??
|
|
341
|
+
`https://pypi.org/project/${pkg.packageOptions.name.replaceAll("_", "-")}/`,
|
|
285
342
|
},
|
|
286
|
-
|
|
287
|
-
|
|
343
|
+
runsOn: ["ubuntu-latest"],
|
|
344
|
+
permissions: { idToken: JobPermission.WRITE },
|
|
345
|
+
timeoutMinutes: 10,
|
|
346
|
+
steps: [
|
|
347
|
+
{
|
|
348
|
+
name: "Download distributions",
|
|
349
|
+
uses: "actions/download-artifact@v8",
|
|
350
|
+
with: { name: "python-distributions", path: "dist" },
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: `Publish ${pkg.packageOptions.name} to PyPI`,
|
|
354
|
+
uses: "pypa/gh-action-pypi-publish@release/v1",
|
|
355
|
+
with: { "packages-dir": `dist/${pkg.packageOptions.directory}` },
|
|
356
|
+
},
|
|
357
|
+
],
|
|
358
|
+
});
|
|
359
|
+
}
|
|
288
360
|
}
|
|
289
361
|
|
|
290
362
|
private renderVersionStampScript(): string {
|
package/src/project.ts
CHANGED
|
@@ -5,14 +5,27 @@
|
|
|
5
5
|
import { type PathMatchInput } from "@dbx-tools/path";
|
|
6
6
|
import { object, type OneOrMany } from "@dbx-tools/shared-core";
|
|
7
7
|
import { type IConstruct } from "constructs";
|
|
8
|
-
import { Project } from "projen";
|
|
8
|
+
import { Project, type ProjectOptions } from "projen";
|
|
9
9
|
import * as mixin from "./mixin.ts";
|
|
10
10
|
import * as projectPredicate from "./project-predicate.ts";
|
|
11
|
-
import type {
|
|
11
|
+
import type { DBXToolsJavaScriptProject } from "./project-js.ts";
|
|
12
12
|
|
|
13
13
|
export * from "./project-js.ts";
|
|
14
14
|
export * from "./project-py.ts";
|
|
15
15
|
|
|
16
|
+
/** Runtime family implemented by a dbx-tools project. */
|
|
17
|
+
export type DBXToolsProjectLanguage = "javascript" | "python";
|
|
18
|
+
|
|
19
|
+
/** Options shared by every dbx-tools project implementation. */
|
|
20
|
+
export interface DBXToolsProjectOptions extends Partial<
|
|
21
|
+
Pick<ProjectOptions, "name" | "parent" | "outdir">
|
|
22
|
+
> {}
|
|
23
|
+
|
|
24
|
+
/** Minimal language-agnostic project contract. */
|
|
25
|
+
export interface DBXToolsProject extends Project {
|
|
26
|
+
readonly language: DBXToolsProjectLanguage;
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
/** Filters selecting which projects an {@link applyToProjects} call runs against. */
|
|
17
30
|
export interface ApplyToProjectsOptions {
|
|
18
31
|
/** Include plain projen projects. Defaults to DBXTools projects only. */
|
|
@@ -45,8 +58,8 @@ type ApplyToAllProjectsOptions = Omit<ApplyToProjectsOptions, "includeNonDBXTool
|
|
|
45
58
|
export function applyToProjects(
|
|
46
59
|
construct: IConstruct,
|
|
47
60
|
...args:
|
|
48
|
-
| [ApplyToDBXToolsProjectsOptions, ...OneOrMany<(project:
|
|
49
|
-
| OneOrMany<(project:
|
|
61
|
+
| [ApplyToDBXToolsProjectsOptions, ...OneOrMany<(project: DBXToolsJavaScriptProject) => void>]
|
|
62
|
+
| OneOrMany<(project: DBXToolsJavaScriptProject) => void>
|
|
50
63
|
): void;
|
|
51
64
|
|
|
52
65
|
export function applyToProjects(
|
|
@@ -71,7 +84,7 @@ export function applyToProjects<P extends Project>(
|
|
|
71
84
|
const callbacks = (hasOptions ? rest : args) as OneOrMany<(project: Project) => void>;
|
|
72
85
|
let predicate = projectPredicate.isProject();
|
|
73
86
|
if (!options?.includeNonDBXToolsProjects) {
|
|
74
|
-
predicate = predicate.and(projectPredicate.
|
|
87
|
+
predicate = predicate.and(projectPredicate.isDBXToolsJavaScriptProject());
|
|
75
88
|
}
|
|
76
89
|
if (!options?.includeRoots) predicate = predicate.and((project) => project.parent != null);
|
|
77
90
|
if (options?.identifierPackageName) {
|
package/src/publish.ts
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import type { javascript } from "projen";
|
|
31
31
|
import { typescript } from "projen";
|
|
32
|
-
import {
|
|
32
|
+
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
33
33
|
import { addPackageFiles, applyCompilerOptions, applyIncludes } from "./project.ts";
|
|
34
34
|
|
|
35
35
|
/** Directory `tsc` emits into, and the root of every published entry point. */
|
|
@@ -63,7 +63,7 @@ export const COMPILED_COMPILER_OPTIONS: javascript.TypeScriptCompilerOptions = {
|
|
|
63
63
|
*/
|
|
64
64
|
export function publishesCompiled(pkg: javascript.NodeProject): boolean {
|
|
65
65
|
if (!(pkg instanceof typescript.TypeScriptProject) || !pkg.parent) return false;
|
|
66
|
-
return
|
|
66
|
+
return isDBXToolsJavaScriptProject()(pkg) && !pkg.dbxToolsConfig.tags.includes("ui");
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/** The `./lib/...` stem of a source path, or `undefined` if it is not TypeScript. */
|