@dbx-tools/projen 0.6.229 → 0.7.0

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.
@@ -54,16 +54,27 @@ export const pythonProjectInfo = (source, toml) => {
54
54
  if (typeof project.name !== "string" || !project.name) {
55
55
  throw new Error("Missing Python project name");
56
56
  }
57
+ if (typeof project.version !== "string" || !project.version) {
58
+ throw new Error("Missing Python project version");
59
+ }
57
60
  const config = document?.tool?.["dbx-tools"];
58
61
  return {
59
62
  name: project.name,
63
+ version: project.version,
60
64
  private: Boolean(config && typeof config === "object" && config.private === true),
65
+ uniffi: Boolean(config && typeof config === "object" && config.uniffi === true),
61
66
  };
62
67
  };
63
68
 
69
+ const compatibleRequirement = (version) => {
70
+ const [major, minor] = version.split(".").map(Number);
71
+ const upper = major === 0 ? `0.${minor + 1}.0` : `${major + 1}.0.0`;
72
+ return `>=${version},<${upper}`;
73
+ };
74
+
64
75
  export const stampPythonProject = (
65
76
  source,
66
- { packages, rewriteDependencies = true, toml, version },
77
+ { packages, rewriteDependencies = true, usePackageVersions = false, toml, version },
67
78
  ) => {
68
79
  const marker = source.startsWith("# ") ? source.slice(0, source.indexOf("\n")) : undefined;
69
80
  const document = toml.parse(source);
@@ -83,7 +94,15 @@ export const stampPythonProject = (
83
94
  throw new Error("Python project dependencies must be strings");
84
95
  }
85
96
  const sibling = packages.find((candidate) => directSibling(dependency, candidate));
86
- return sibling ? `${sibling.name}==${version}` : dependency;
97
+ return sibling
98
+ ? `${sibling.name}${
99
+ usePackageVersions
100
+ ? sibling.uniffi
101
+ ? `==${sibling.version}`
102
+ : compatibleRequirement(sibling.version)
103
+ : `==${version}`
104
+ }`
105
+ : dependency;
87
106
  });
88
107
  }
89
108
  }
@@ -222,9 +222,13 @@ const testNodeFacade = ({
222
222
  };
223
223
 
224
224
  /** Resolve workspace and generated catalog protocols for a publishable facade. */
225
- const facadeDependency = (name, dependency, version, catalog) => {
225
+ const facadeDependency = (name, dependency, catalog, workspaceVersions) => {
226
226
  if (typeof dependency !== "string") return dependency;
227
- if (dependency.startsWith("workspace:")) return version;
227
+ if (dependency.startsWith("workspace:")) {
228
+ const version = workspaceVersions.get(name);
229
+ if (!version) throw new Error(`Missing workspace version for ${name}`);
230
+ return dependency === "workspace:*" ? version : `${dependency.slice("workspace:".length)}${version}`;
231
+ }
228
232
  if (!dependency.startsWith("catalog:")) return dependency;
229
233
  const resolved = catalog[name];
230
234
  if (!resolved) throw new Error(`Missing root catalog entry for ${name}`);
@@ -344,6 +348,7 @@ const packageNodeFacade = ({ output, nodeDirectory, nodePackage, version, native
344
348
  const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
345
349
  const workspaceManifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
346
350
  const catalog = workspaceManifest.catalog ?? {};
351
+ const workspaceVersions = localWorkspacePackages();
347
352
  manifest.version = version;
348
353
  manifest.private = false;
349
354
  manifest.license = manifest.license === "UNLICENSED" ? "Apache-2.0" : manifest.license;
@@ -353,7 +358,7 @@ const packageNodeFacade = ({ output, nodeDirectory, nodePackage, version, native
353
358
  manifest.dependencies = Object.fromEntries(
354
359
  Object.entries(manifest.dependencies ?? {}).map(([name, dependency]) => [
355
360
  name,
356
- facadeDependency(name, dependency, version, catalog),
361
+ facadeDependency(name, dependency, catalog, workspaceVersions),
357
362
  ]),
358
363
  );
359
364
  writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env -S bun
2
- /** Verify that every committed package version matches the workspace VERSION. */
2
+ /** Verify that every committed package version matches its owning release unit. */
3
3
  import { existsSync, readFileSync } from "node:fs";
4
- import { join } from "node:path";
4
+ import { dirname, join, relative } from "node:path";
5
5
  import { exec, project } from "@dbx-tools/core";
6
6
  import { find } from "@dbx-tools/path";
7
7
  import { json, log, object } from "@dbx-tools/shared-core";
8
8
  import { parse } from "smol-toml";
9
9
  import { recordedPackages } from "../src/packages.ts";
10
+ import type { ReleaseUnitGraph } from "../src/release-catalog.ts";
10
11
  import { readWorkspaceVersion } from "../src/workspace-version.ts";
11
12
 
12
13
  const logger = log.logger("projen:version-check");
@@ -23,7 +24,7 @@ function pythonVersion(path: string): string | undefined {
23
24
  return typeof manifest.project?.version === "string" ? manifest.project.version : undefined;
24
25
  }
25
26
 
26
- function cargoVersions(root: string): Array<{ name: string; version: string }> {
27
+ function cargoVersions(root: string): Array<{ name: string; version: string; path: string }> {
27
28
  if (!existsSync(join(root, "Cargo.toml"))) return [];
28
29
  const locked = existsSync(join(root, "Cargo.lock"));
29
30
  const result = exec.spawnSync(
@@ -43,43 +44,70 @@ function cargoVersions(root: string): Array<{ name: string; version: string }> {
43
44
  if (
44
45
  !object.isRecord(candidate) ||
45
46
  typeof candidate.name !== "string" ||
46
- typeof candidate.version !== "string"
47
+ typeof candidate.version !== "string" ||
48
+ typeof candidate.manifest_path !== "string"
47
49
  ) {
48
50
  return [];
49
51
  }
50
- return [{ name: candidate.name, version: candidate.version }];
52
+ return [
53
+ {
54
+ name: candidate.name,
55
+ version: candidate.version,
56
+ path: relative(root, dirname(candidate.manifest_path)).replaceAll("\\", "/") || ".",
57
+ },
58
+ ];
51
59
  });
52
60
  }
53
61
 
54
62
  function main(): void {
55
63
  const root = project.root() ?? process.cwd();
56
- const version = readWorkspaceVersion(root);
64
+ const fixedVersion = readWorkspaceVersion(root);
65
+ const graphPath = join(root, ".projen/release-units.json");
66
+ const graph = existsSync(graphPath)
67
+ ? (JSON.parse(readFileSync(graphPath, "utf8")) as ReleaseUnitGraph)
68
+ : undefined;
69
+ const units = new Map(graph?.units.map((unit) => [unit.id, unit.version]) ?? []);
70
+ const projects = new Map(graph?.projects.map((entry) => [entry.path, entry]) ?? []);
57
71
  const mismatches: string[] = [];
58
- const check = (name: string, actual: string | undefined): void => {
59
- if (actual !== version) mismatches.push(`${name}: ${actual ?? "missing"} != ${version}`);
72
+ const expected = (path: string): string | undefined => {
73
+ const releaseProject = projects.get(path);
74
+ if (releaseProject?.unit) return units.get(releaseProject.unit);
75
+ return graph?.mode === "independent" ? undefined : fixedVersion;
76
+ };
77
+ const check = (name: string, path: string, actual: string | undefined): void => {
78
+ const version = expected(path);
79
+ if (version !== undefined && actual !== version) {
80
+ mismatches.push(`${name}: ${actual ?? "missing"} != ${version}`);
81
+ }
60
82
  };
61
83
 
62
- check("package.json", manifestVersion(join(root, "package.json")));
84
+ check("package.json", ".", manifestVersion(join(root, "package.json")));
63
85
  for (const pkg of recordedPackages(root)) {
64
- check(`${pkg.path}/package.json`, manifestVersion(join(pkg.dir, "package.json")));
86
+ check(`${pkg.path}/package.json`, pkg.path, manifestVersion(join(pkg.dir, "package.json")));
65
87
  const barrel = join(pkg.dir, "index.ts");
66
88
  if (existsSync(barrel)) {
67
89
  const actual = /export const PACKAGE_VERSION = "([^"]+)";/.exec(
68
90
  readFileSync(barrel, "utf8"),
69
91
  )?.[1];
70
- check(`${pkg.path}/index.ts`, actual);
92
+ check(`${pkg.path}/index.ts`, pkg.path, actual);
71
93
  }
72
94
  }
73
95
 
74
96
  for (const path of find.findFiles("**/pyproject.toml", { cwd: root })) {
75
- check(path, pythonVersion(join(root, path)));
97
+ check(path, dirname(path).replaceAll("\\", "/"), pythonVersion(join(root, path)));
98
+ }
99
+ for (const pkg of cargoVersions(root)) {
100
+ check(`Cargo package ${pkg.name}`, pkg.path, pkg.version);
76
101
  }
77
- for (const pkg of cargoVersions(root)) check(`Cargo package ${pkg.name}`, pkg.version);
78
102
 
79
103
  if (mismatches.length > 0) {
80
- throw new Error(`Workspace version mismatch:\n${mismatches.join("\n")}`);
104
+ throw new Error(`Release-unit version mismatch:\n${mismatches.join("\n")}`);
81
105
  }
82
- logger.success(`all workspace versions match ${version}`);
106
+ logger.success(
107
+ graph
108
+ ? `all package versions match ${graph.units.length} release units`
109
+ : `all workspace versions match ${fixedVersion}`,
110
+ );
83
111
  }
84
112
 
85
113
  main();