@dbx-tools/projen 0.9.21 → 0.9.29

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 (111) hide show
  1. package/README.md +77 -207
  2. package/index.ts +10 -14
  3. package/package.json +4 -4
  4. package/src/barrels.ts +1 -74
  5. package/src/module-exports.ts +175 -1
  6. package/src/openapi.ts +5 -72
  7. package/src/packages.ts +45 -0
  8. package/src/project-js.ts +3 -6
  9. package/src/project-predicate.ts +1 -2
  10. package/src/project-py.ts +82 -103
  11. package/src/project.ts +2 -2
  12. package/src/python-node-bindings.ts +138 -0
  13. package/src/python-node-bundle.ts +92 -0
  14. package/src/release-catalog.ts +3 -5
  15. package/src/{release-dispatch.ts → release-context.ts} +0 -11
  16. package/src/release.ts +70 -152
  17. package/tasks/bump.ts +12 -21
  18. package/tasks/databricks-cli-assets.ts +129 -0
  19. package/tasks/local-publish.ts +23 -107
  20. package/tasks/publish-npm.ts +10 -1
  21. package/tasks/publish-python.ts +26 -11
  22. package/tasks/publish.ts +12 -48
  23. package/tasks/python-node-bindings-watch.ts +47 -0
  24. package/tasks/python-node-bindings.ts +1017 -0
  25. package/tasks/python-release.ts +74 -0
  26. package/tasks/release.ts +99 -0
  27. package/tasks/sync.ts +13 -18
  28. package/tasks/version-check.ts +1 -28
  29. package/._LICENSE +0 -0
  30. package/._README.md +0 -0
  31. package/._index.ts +0 -0
  32. package/._package.json +0 -0
  33. package/src/.__lazy-require.ts +0 -0
  34. package/src/.__release-platform.ts +0 -0
  35. package/src/.__rust-project.ts +0 -0
  36. package/src/.__rust-release-workflow.ts +0 -0
  37. package/src/.__task-command.ts +0 -0
  38. package/src/._barrels.ts +0 -0
  39. package/src/._bun-app.ts +0 -0
  40. package/src/._bun-workflow.ts +0 -0
  41. package/src/._clean.ts +0 -0
  42. package/src/._codegen.ts +0 -0
  43. package/src/._dbx-tools-config.ts +0 -0
  44. package/src/._engine-root.ts +0 -0
  45. package/src/._generated.ts +0 -0
  46. package/src/._mixin.ts +0 -0
  47. package/src/._module-exports.ts +0 -0
  48. package/src/._openapi.ts +0 -0
  49. package/src/._packages.ts +0 -0
  50. package/src/._pnpm-workspace.ts +0 -0
  51. package/src/._project-js.ts +0 -0
  52. package/src/._project-predicate.ts +0 -0
  53. package/src/._project-py.ts +0 -0
  54. package/src/._project-rs.ts +0 -0
  55. package/src/._project.ts +0 -0
  56. package/src/._projen-version.ts +0 -0
  57. package/src/._publish.ts +0 -0
  58. package/src/._release-catalog.ts +0 -0
  59. package/src/._release-dispatch.ts +0 -0
  60. package/src/._release-github.ts +0 -0
  61. package/src/._release.ts +0 -0
  62. package/src/._scaffold.ts +0 -0
  63. package/src/._tags.ts +0 -0
  64. package/src/._tsconfig.ts +0 -0
  65. package/src/._uniffi.ts +0 -0
  66. package/src/._vscode.ts +0 -0
  67. package/src/._watch.ts +0 -0
  68. package/src/._workspace-lock.ts +0 -0
  69. package/src/._workspace-version.ts +0 -0
  70. package/src/_release-platform.ts +0 -78
  71. package/src/_rust-project.ts +0 -429
  72. package/src/_rust-release-workflow.ts +0 -311
  73. package/src/project-rs.ts +0 -1054
  74. package/src/release-github.ts +0 -109
  75. package/src/uniffi.ts +0 -65
  76. package/tasks/._barrels.ts +0 -0
  77. package/tasks/._bump.ts +0 -0
  78. package/tasks/._clean.ts +0 -0
  79. package/tasks/._compile-workspace.ts +0 -0
  80. package/tasks/._local-publish.ts +0 -0
  81. package/tasks/._openapi.ts +0 -0
  82. package/tasks/._projenrc.ts +0 -0
  83. package/tasks/._publish-npm.ts +0 -0
  84. package/tasks/._publish-python.ts +0 -0
  85. package/tasks/._publish-uniffi-local.ts +0 -0
  86. package/tasks/._publish.ts +0 -0
  87. package/tasks/._python-registry.ts +0 -0
  88. package/tasks/._release-assets.ts +0 -0
  89. package/tasks/._release-candidate.ts +0 -0
  90. package/tasks/._release-manifest.ts +0 -0
  91. package/tasks/._release-pr.ts +0 -0
  92. package/tasks/._release-summary.ts +0 -0
  93. package/tasks/._release-version.ts +0 -0
  94. package/tasks/._rust.ts +0 -0
  95. package/tasks/._sync.ts +0 -0
  96. package/tasks/._uniffi-python.d.ts +0 -0
  97. package/tasks/._uniffi-python.js +0 -0
  98. package/tasks/._uniffi-release.mjs +0 -0
  99. package/tasks/._uniffi.ts +0 -0
  100. package/tasks/._version-check.ts +0 -0
  101. package/tasks/publish-uniffi-local.ts +0 -359
  102. package/tasks/release-assets.ts +0 -467
  103. package/tasks/release-candidate.ts +0 -416
  104. package/tasks/release-manifest.ts +0 -273
  105. package/tasks/release-pr.ts +0 -589
  106. package/tasks/release-summary.ts +0 -379
  107. package/tasks/rust.ts +0 -173
  108. package/tasks/uniffi-python.d.ts +0 -60
  109. package/tasks/uniffi-python.js +0 -178
  110. package/tasks/uniffi-release.mjs +0 -579
  111. package/tasks/uniffi.ts +0 -262
@@ -19,8 +19,9 @@
19
19
  * `export { ... }` is a hard error (TS1205). `export function` names are marked
20
20
  * `isFunction` so the barrel leaves them namespace-only.
21
21
  */
22
- import { readFileSync } from "node:fs";
22
+ import { existsSync, readFileSync } from "node:fs";
23
23
  import { createRequire } from "node:module";
24
+ import { dirname, extname, resolve } from "node:path";
24
25
  import type { parseSync as OxcParseSync } from "oxc-parser";
25
26
 
26
27
  const require = createRequire(import.meta.url);
@@ -63,6 +64,13 @@ export interface ModuleExport {
63
64
  readonly isFunction: boolean;
64
65
  }
65
66
 
67
+ /** Plain public function reachable through a module's re-export graph. */
68
+ export interface PublicFunctionExport {
69
+ readonly name: string;
70
+ readonly sourceFile: string;
71
+ readonly sourceName: string;
72
+ }
73
+
66
74
  /** Declaration node types that are inherently type-only. */
67
75
  const TYPE_DECLARATIONS = new Set(["TSInterfaceDeclaration", "TSTypeAliasDeclaration"]);
68
76
 
@@ -132,3 +140,169 @@ export function moduleExports(file: string): ModuleExport[] {
132
140
  }
133
141
  return [...byName.values()];
134
142
  }
143
+
144
+ /**
145
+ * Resolve every plain named function exported by `file`, following relative
146
+ * named and star re-exports. Non-function values and types are ignored. A
147
+ * generator, declaration-only overload, or conflicting function definition is
148
+ * rejected because a generic runtime bridge cannot preserve those semantics.
149
+ */
150
+ export function publicFunctionExports(file: string): PublicFunctionExport[] {
151
+ return [...collectPublicFunctions(resolve(file), new Set()).values()]
152
+ .map(({ name, sourceFile, sourceName }) => ({ name, sourceFile, sourceName }))
153
+ .sort((left, right) => left.name.localeCompare(right.name));
154
+ }
155
+
156
+ interface ResolvedFunctionExport extends PublicFunctionExport {
157
+ readonly source: string;
158
+ }
159
+
160
+ function collectPublicFunctions(
161
+ file: string,
162
+ visiting: Set<string>,
163
+ ): Map<string, ResolvedFunctionExport> {
164
+ if (visiting.has(file)) return new Map();
165
+ visiting.add(file);
166
+ const source = readFileSync(file, "utf8");
167
+ const body = parseSync(file, source).program.body;
168
+ const functions = new Map<string, ResolvedFunctionExport>();
169
+ const localFunctions = new Map<string, FunctionNode>();
170
+
171
+ for (const statement of body) {
172
+ const node = statement as FunctionNode & { declaration?: FunctionNode | null };
173
+ const declaration =
174
+ node.type === "FunctionDeclaration" || node.type === "TSDeclareFunction"
175
+ ? node
176
+ : node.declaration;
177
+ if (declaration?.type === "FunctionDeclaration" || declaration?.type === "TSDeclareFunction") {
178
+ const name = declaration.id?.name;
179
+ if (name) localFunctions.set(name, declaration);
180
+ }
181
+ }
182
+
183
+ const add = (exported: ResolvedFunctionExport): void => {
184
+ const existing = functions.get(exported.name);
185
+ if (existing && existing.source !== exported.source) {
186
+ throw new Error(
187
+ `Conflicting function export ${exported.name} from ${existing.source} and ${exported.source}`,
188
+ );
189
+ }
190
+ functions.set(exported.name, exported);
191
+ };
192
+
193
+ for (const statement of body) {
194
+ if (statement.type === "ExportAllDeclaration") {
195
+ const node = statement as { exported?: unknown; source?: { value?: string } };
196
+ if (node.exported || !node.source?.value) continue;
197
+ for (const exported of collectPublicFunctions(
198
+ resolveModuleSpecifier(file, node.source.value),
199
+ visiting,
200
+ ).values()) {
201
+ add(exported);
202
+ }
203
+ continue;
204
+ }
205
+ if (statement.type !== "ExportNamedDeclaration") continue;
206
+ const node = statement as {
207
+ declaration?: FunctionNode | null;
208
+ source?: { value?: string } | null;
209
+ specifiers?: {
210
+ local?: { name?: string; value?: string };
211
+ exported?: { name?: string; value?: string };
212
+ exportKind?: "value" | "type";
213
+ }[];
214
+ exportKind?: "value" | "type";
215
+ };
216
+ if (
217
+ node.declaration?.type === "FunctionDeclaration" ||
218
+ node.declaration?.type === "TSDeclareFunction"
219
+ ) {
220
+ add(parseFunctionNode(file, node.declaration));
221
+ }
222
+ if (node.exportKind === "type") continue;
223
+ if (node.source?.value) {
224
+ const available = collectPublicFunctions(
225
+ resolveModuleSpecifier(file, node.source.value),
226
+ visiting,
227
+ );
228
+ for (const specifier of node.specifiers ?? []) {
229
+ if (specifier.exportKind === "type") continue;
230
+ const local = specifier.local?.name ?? specifier.local?.value;
231
+ const exportedName = specifier.exported?.name ?? specifier.exported?.value;
232
+ const target = local ? available.get(local) : undefined;
233
+ if (target && exportedName)
234
+ add({
235
+ name: exportedName,
236
+ source: target.source,
237
+ sourceFile: target.sourceFile,
238
+ sourceName: target.sourceName,
239
+ });
240
+ }
241
+ continue;
242
+ }
243
+ for (const specifier of node.specifiers ?? []) {
244
+ if (specifier.exportKind === "type") continue;
245
+ const local = specifier.local?.name ?? specifier.local?.value;
246
+ const exportedName = specifier.exported?.name ?? specifier.exported?.value;
247
+ const target = local ? localFunctions.get(local) : undefined;
248
+ if (target && exportedName) {
249
+ const parsed = parseFunctionNode(file, target);
250
+ add({
251
+ name: exportedName,
252
+ source: parsed.source,
253
+ sourceFile: parsed.sourceFile,
254
+ sourceName: parsed.sourceName,
255
+ });
256
+ }
257
+ }
258
+ }
259
+
260
+ visiting.delete(file);
261
+ return functions;
262
+ }
263
+
264
+ interface FunctionNode {
265
+ readonly type: string;
266
+ readonly id?: { readonly name?: string } | null;
267
+ readonly generator?: boolean;
268
+ readonly declare?: boolean;
269
+ readonly body?: unknown;
270
+ }
271
+
272
+ function parseFunctionNode(file: string, node: FunctionNode): ResolvedFunctionExport {
273
+ const name = node.id?.name;
274
+ if (!name) throw new Error(`Anonymous exported function is not supported in ${file}`);
275
+ if (node.generator) throw new Error(`Generator export ${name} is not supported in ${file}`);
276
+ if (node.type === "TSDeclareFunction" || node.declare || !node.body) {
277
+ throw new Error(`Declaration-only function export ${name} is not supported in ${file}`);
278
+ }
279
+ return { name, source: `${file}#${name}`, sourceFile: file, sourceName: name };
280
+ }
281
+
282
+ function resolveModuleSpecifier(importer: string, specifier: string): string {
283
+ if (!specifier.startsWith(".")) return createRequire(importer).resolve(specifier);
284
+ const base = resolve(dirname(importer), specifier);
285
+ const extension = extname(base);
286
+ const candidates = extension
287
+ ? [
288
+ base,
289
+ ...(extension === ".js" || extension === ".jsx"
290
+ ? [`${base.slice(0, -extension.length)}.ts`, `${base.slice(0, -extension.length)}.tsx`]
291
+ : []),
292
+ ]
293
+ : [
294
+ `${base}.ts`,
295
+ `${base}.tsx`,
296
+ `${base}.js`,
297
+ `${base}.jsx`,
298
+ `${base}.mjs`,
299
+ `${base}.cjs`,
300
+ resolve(base, "index.ts"),
301
+ resolve(base, "index.tsx"),
302
+ resolve(base, "index.js"),
303
+ ];
304
+ for (const candidate of candidates) {
305
+ if (existsSync(candidate)) return candidate;
306
+ }
307
+ throw new Error(`Could not resolve ${specifier} from ${importer}`);
308
+ }
package/src/openapi.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  /**
2
- * OpenAPI generator for tsoa controllers and code-first Rust producers.
2
+ * OpenAPI generator for tsoa controllers.
3
3
  *
4
- * TypeScript packages are discovered from tsoa imports. Rust producers are
5
- * recorded by `DBXToolsRustWorkspace`. Both feed the same optimized generated
6
- * package:
4
+ * TypeScript packages are discovered from tsoa imports and feed the optimized generated package:
7
5
  *
8
6
  * - `openapi.json` - the OpenAPI 3 spec (tsoa `generateSpec`, then Speakeasy
9
7
  * optimization to extract duplicate inline schemas into components).
@@ -48,7 +46,6 @@ import {
48
46
  toPosix,
49
47
  recordedPackages,
50
48
  } from "./packages.ts";
51
- import type { RustOpenApiMapping, RustWorkspaceMapping } from "./project-rs.ts";
52
49
  import type { ReleaseUnitGraph } from "./release-catalog.ts";
53
50
  import { readWorkspaceVersion } from "./workspace-version.ts";
54
51
 
@@ -100,15 +97,6 @@ function controllerPackages(): object.Sequence<RecordedPackage> {
100
97
  return object.sequence(recordedPackages()).filter(isTsoaCandidate).filter(hasTsoaControllers);
101
98
  }
102
99
 
103
- function rustOpenapiMappings(): RustOpenApiMapping[] {
104
- const manifest = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")) as unknown;
105
- if (!object.isRecord(manifest)) return [];
106
- const config = manifest.dbxToolsConfig;
107
- if (!object.isRecord(config) || !object.isRecord(config.rust)) return [];
108
- const mapping = config.rust as unknown as Partial<RustWorkspaceMapping>;
109
- return Array.isArray(mapping.openapi) ? [...mapping.openapi] : [];
110
- }
111
-
112
100
  function inside(path: string, directory: string): boolean {
113
101
  const child = relative(resolve(directory), resolve(path));
114
102
  return child === "" || (!child.startsWith("..") && !isAbsolute(child));
@@ -120,16 +108,11 @@ export function isOpenapiProducerSource(path: string, producers: readonly string
120
108
  return object.sequence(producers).some((producer) => inside(absolute, producer));
121
109
  }
122
110
 
123
- function rustOpenapiSources(mapping: RustOpenApiMapping): string[] {
124
- return [resolve(repoRoot, mapping.rust, "src"), resolve(repoRoot, mapping.rust, "Cargo.toml")];
125
- }
126
-
127
- /** Source roots consumed by TypeScript and Rust OpenAPI producers. */
111
+ /** Source roots consumed by TypeScript OpenAPI producers. */
128
112
  export function openapiWatchRoots(): string[] {
129
113
  return [
130
114
  ...controllerPackages()
131
115
  .map((pkg) => resolve(tsoaSource(pkg)))
132
- .join(object.sequence(rustOpenapiMappings()).flatMap(rustOpenapiSources))
133
116
  .distinct(),
134
117
  ];
135
118
  }
@@ -139,14 +122,6 @@ export function isOpenapiSource(path: string): boolean {
139
122
  const absolute = resolve(path);
140
123
  const segments = toPosix(relative(repoRoot, absolute)).split("/");
141
124
  if (segments.includes(OPENAPI_TAG)) return false;
142
- if (
143
- object
144
- .sequence(rustOpenapiMappings())
145
- .flatMap(rustOpenapiSources)
146
- .some((source) => inside(absolute, source))
147
- ) {
148
- return true;
149
- }
150
125
  return object
151
126
  .sequence(recordedPackages())
152
127
  .filter(isTsoaCandidate)
@@ -196,28 +171,6 @@ export async function optimizeOpenapiSpec(specPath: string, executable?: string)
196
171
  await execFileAsync(openapi, ["spec", "optimize", specPath, "--write", "--non-interactive"]);
197
172
  }
198
173
 
199
- /** Cargo arguments that export one Rust producer's aide document. */
200
- export function rustOpenapiArgs(
201
- mapping: RustOpenApiMapping,
202
- output: string,
203
- targetDir = join(repoRoot, "target/openapi"),
204
- ): string[] {
205
- return [
206
- "run",
207
- "--quiet",
208
- "--target-dir",
209
- targetDir,
210
- "--package",
211
- mapping.crate,
212
- ...(mapping.noDefaultFeatures ? ["--no-default-features"] : []),
213
- ...(mapping.features.length ? ["--features", mapping.features.join(",")] : []),
214
- ...(mapping.binary ? ["--bin", mapping.binary] : []),
215
- "--",
216
- "--generate-spec",
217
- output,
218
- ];
219
- }
220
-
221
174
  type OpenApiTypeTools = {
222
175
  openapiTS: typeof import("openapi-typescript").default;
223
176
  astToString: typeof import("openapi-typescript").astToString;
@@ -257,11 +210,10 @@ async function writeClientPackage(
257
210
  */
258
211
  export async function generateOpenapi(): Promise<string[]> {
259
212
  const pkgs = controllerPackages().toArray();
260
- const rustMappings = rustOpenapiMappings();
261
213
  // Same reasoning as codegen's empty case: a workspace with no tsoa controllers
262
214
  // is not a condition worth a line on every synth.
263
- if (pkgs.length === 0 && rustMappings.length === 0) {
264
- logger.debug("no TypeScript or Rust OpenAPI producers found");
215
+ if (pkgs.length === 0) {
216
+ logger.debug("no TypeScript OpenAPI producers found");
265
217
  return [];
266
218
  }
267
219
 
@@ -341,24 +293,5 @@ export async function generateOpenapi(): Promise<string[]> {
341
293
  written.push(outDir);
342
294
  logger.success(`openapi/${leaf} (from ${p.relPath})`);
343
295
  }
344
- for (const mapping of rustMappings) {
345
- const outDir = resolve(repoRoot, mapping.output);
346
- mkdirSync(outDir, { recursive: true });
347
- const specPath = join(outDir, "openapi.json");
348
- const tempDir = mkdtempSync(join(outDir, ".openapi-"));
349
- const tempSpecPath = join(tempDir, "openapi.json");
350
- try {
351
- await execFileAsync("cargo", rustOpenapiArgs(mapping, tempSpecPath), { cwd: repoRoot });
352
- await optimizeOpenapiSpec(tempSpecPath);
353
- makeWritable(specPath);
354
- renameSync(tempSpecPath, specPath);
355
- } finally {
356
- rmSync(tempDir, { recursive: true, force: true });
357
- }
358
- makeReadonly(specPath);
359
- await writeClientPackage(outDir, `the aide routes in ${mapping.rust}`, tools);
360
- written.push(outDir);
361
- logger.success(`${mapping.output} (from ${mapping.rust})`);
362
- }
363
296
  return written;
364
297
  }
package/src/packages.ts CHANGED
@@ -291,6 +291,19 @@ export function syncResynthPaths(projectRoot: string = resolveRepoRoot()): strin
291
291
  return Array.isArray(paths) ? stringUtils.parseList(paths.map((p) => String(p))) : [];
292
292
  }
293
293
 
294
+ /** Python projects with Node bindings registered for the root sync watcher. */
295
+ export function pythonNodeBindingProjects(projectRoot: string = resolveRepoRoot()): string[] {
296
+ const configured = readDbxToolsConfig(projectRoot)?.pythonNodeBindings;
297
+ if (!Array.isArray(configured)) return [];
298
+ return [
299
+ ...new Set(
300
+ configured.flatMap((value) =>
301
+ typeof value === "string" && value.trim() ? [value.trim()] : [],
302
+ ),
303
+ ),
304
+ ].sort();
305
+ }
306
+
294
307
  /**
295
308
  * The recorded workspace members from `pnpm-workspace.yaml` (the source of truth),
296
309
  * each augmented with the `tags` read back from its `package.json`. This is what
@@ -314,6 +327,38 @@ export function recordedPackages(projectRoot: string = resolveRepoRoot()): Recor
314
327
  return out.sort((a, b) => a.path.localeCompare(b.path));
315
328
  }
316
329
 
330
+ /**
331
+ * Absolute directories for a workspace package and its transitive runtime
332
+ * workspace dependencies. Dependency edges come from package manifests; external
333
+ * packages are ignored. Returns `[]` when `packageName` is not a workspace member.
334
+ */
335
+ export function workspaceDependencyDirectories(
336
+ packageName: string,
337
+ projectRoot: string = resolveRepoRoot(),
338
+ ): string[] {
339
+ const packages = new Map<string, { dir: string; manifest: Record<string, unknown> }>();
340
+ for (const pkg of recordedPackages(projectRoot)) {
341
+ const manifest = readPackageManifest(pkg.dir);
342
+ if (!manifest || typeof manifest.name !== "string") continue;
343
+ packages.set(manifest.name, { dir: pkg.dir, manifest });
344
+ }
345
+ if (!packages.has(packageName)) return [];
346
+
347
+ const directories = new Set<string>();
348
+ const visit = (name: string): void => {
349
+ const pkg = packages.get(name);
350
+ if (!pkg || directories.has(pkg.dir)) return;
351
+ directories.add(pkg.dir);
352
+ for (const field of ["dependencies", "optionalDependencies", "peerDependencies"] as const) {
353
+ const dependencies = pkg.manifest[field];
354
+ if (!object.isRecord(dependencies)) continue;
355
+ for (const dependency of Object.keys(dependencies)) visit(dependency);
356
+ }
357
+ };
358
+ visit(packageName);
359
+ return [...directories].sort();
360
+ }
361
+
317
362
  /**
318
363
  * The configured roots recorded in the root manifest. Older workspaces without
319
364
  * that field fall back to the distinct first segment of every recorded member,
package/src/project-js.ts CHANGED
@@ -48,7 +48,7 @@ import {
48
48
  type ReleaseDependencyInput,
49
49
  type ReleaseUnitRule,
50
50
  } from "./release-catalog.ts";
51
- import { DBXToolsRelease, type ReleaseDocsOptions, type ReleaseSummaryOptions } from "./release.ts";
51
+ import { DBXToolsRelease, type ReleaseDocsOptions } from "./release.ts";
52
52
  import { AGNOSTIC_COMPILER_OPTIONS, PACKAGE_TAG_MIXINS, type PackageTag } from "./tags.ts";
53
53
  import { DBXToolsRootTsconfig } from "./tsconfig.ts";
54
54
  import { DBXToolsVsCode } from "./vscode.ts";
@@ -384,7 +384,7 @@ const PRETTIER_SETTINGS: javascript.PrettierSettings = {
384
384
 
385
385
  export { PROJEN_VERSION } from "./projen-version.ts";
386
386
 
387
- /** SPDX license shared by generated JavaScript, Python, and Rust packages. */
387
+ /** SPDX license shared by generated JavaScript and Python packages. */
388
388
  export const DBX_TOOLS_LICENSE = "Apache-2.0";
389
389
 
390
390
  /**
@@ -625,8 +625,6 @@ export type DBXToolsJavaScriptProjectOptions = CommonProjectOptions &
625
625
  readonly releasePythonRoot?: string;
626
626
  /** Repository task names run during local release preparation before publication. */
627
627
  readonly releaseValidationTasks?: readonly string[];
628
- /** Optional AI-generated release summary. Defaults to enabled. */
629
- readonly releaseSummary?: boolean | ReleaseSummaryOptions;
630
628
  /** Set to `false` to omit normal npm workspace publication. */
631
629
  readonly nodeRelease?: boolean;
632
630
  /** Unified dbx-tools release workflow, or no release surface. Defaults to `dbx-tools`. */
@@ -1324,7 +1322,7 @@ class PublishedPackageDescriptionValidation extends Component {
1324
1322
  * fail with ERR_MODULE_NOT_FOUND after such an update. bun runs the `.ts`
1325
1323
  * directly (no tsx, no build step).
1326
1324
  */
1327
- export function taskScript(_project: javascript.NodeProject, script: string, args = ""): string {
1325
+ export function taskScript(_project: Project, script: string, args = ""): string {
1328
1326
  const scriptPath = toPosix(join("node_modules", "@dbx-tools", "projen", "tasks", script));
1329
1327
  return args ? `bun ${scriptPath} ${args}` : `bun ${scriptPath}`;
1330
1328
  }
@@ -1580,7 +1578,6 @@ function initProject(
1580
1578
  docs: options.releaseDocs,
1581
1579
  pythonRoot: options.releasePythonRoot,
1582
1580
  validationTasks: options.releaseValidationTasks,
1583
- summary: options.releaseSummary,
1584
1581
  });
1585
1582
  }
1586
1583
  }
@@ -33,8 +33,7 @@ export function isDBXToolsProject(): Predicate<IConstruct, DBXToolsProject> {
33
33
  return isProject().and(
34
34
  (project): project is DBXToolsProject =>
35
35
  (project as Partial<DBXToolsProject>).language === "javascript" ||
36
- (project as Partial<DBXToolsProject>).language === "python" ||
37
- (project as Partial<DBXToolsProject>).language === "rust",
36
+ (project as Partial<DBXToolsProject>).language === "python",
38
37
  );
39
38
  }
40
39